From: Ted Kremenek Date: Wed, 10 Mar 2010 00:18:11 +0000 (+0000) Subject: When computing in AnalysisContext the variables referenced X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2cfe28b6a061e72c6c8726d7ecb879093a1ab7a3;p=clang When computing in AnalysisContext the variables referenced by a block, also look at the contained blocks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98111 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp index d9933e85cb..5640c4a461 100644 --- a/lib/Analysis/AnalysisContext.cpp +++ b/lib/Analysis/AnalysisContext.cpp @@ -12,15 +12,16 @@ // //===----------------------------------------------------------------------===// -#include "clang/Analysis/CFG.h" -#include "clang/Analysis/AnalysisContext.h" -#include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ParentMap.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Analysis/Analyses/LiveVariables.h" +#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/CFG.h" #include "clang/Analysis/Support/BumpVector.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -207,11 +208,17 @@ class FindBlockDeclRefExprsVals : public StmtVisitor{ BumpVector &BEVals; BumpVectorContext &BC; llvm::DenseMap Visited; + llvm::SmallSet IgnoredContexts; public: FindBlockDeclRefExprsVals(BumpVector &bevals, BumpVectorContext &bc) : BEVals(bevals), BC(bc) {} - + + bool IsTrackedDecl(const VarDecl *VD) { + const DeclContext *DC = VD->getDeclContext(); + return IgnoredContexts.count(DC) == 0; + } + void VisitStmt(Stmt *S) { for (Stmt::child_iterator I = S->child_begin(), E = S->child_end();I!=E;++I) if (Stmt *child = *I) @@ -229,16 +236,23 @@ public: } } } - + void VisitBlockDeclRefExpr(BlockDeclRefExpr *DR) { if (const VarDecl *VD = dyn_cast(DR->getDecl())) { unsigned &flag = Visited[VD]; if (!flag) { flag = 1; - BEVals.push_back(VD, BC); + if (IsTrackedDecl(VD)) + BEVals.push_back(VD, BC); } } } + + void VisitBlockExpr(BlockExpr *BR) { + // Blocks containing blocks can transitively capture more variables. + IgnoredContexts.insert(BR->getBlockDecl()); + Visit(BR->getBlockDecl()->getBody()); + } }; } // end anonymous namespace diff --git a/test/Analysis/dead-stores.c b/test/Analysis/dead-stores.c index a002174420..9a266c9379 100644 --- a/test/Analysis/dead-stores.c +++ b/test/Analysis/dead-stores.c @@ -1,8 +1,8 @@ -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code %s -// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code %s +// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=basic -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=basic -analyzer-constraints=range -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=basic -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s +// RUN: %clang_cc1 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -analyzer-constraints=range -analyzer-check-dead-stores -fblocks -verify -Wno-unreachable-code -analyzer-opt-analyze-nested-blocks %s void f1() { int k, y; @@ -377,7 +377,7 @@ void f24_A(int y) { // FIXME: One day this should be reported as dead since 'z = x + y' is dead. int x = (y > 2); // no-warning ^ { - int z = x + y; // FIXME: Eventually this should be reported as a dead store. + int z = x + y; // expected-warning{{Value stored to 'z' during its initialization is never read}} }(); } @@ -429,3 +429,17 @@ int f25_b(int y) { return z; } +int f26_nestedblocks() { + int z; + z = 1; + __block int y = 0; + ^{ + int k; + k = 1; // expected-warning{{Value stored to 'k' is never read}} + ^{ + y = z + 1; + }(); + }(); + return y; +} +