]> granicus.if.org Git - clang/commitdiff
When computing in AnalysisContext the variables referenced
authorTed Kremenek <kremenek@apple.com>
Wed, 10 Mar 2010 00:18:11 +0000 (00:18 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 10 Mar 2010 00:18:11 +0000 (00:18 +0000)
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

lib/Analysis/AnalysisContext.cpp
test/Analysis/dead-stores.c

index d9933e85cb9103eebdf9cda50e06e208d0066eab..5640c4a461e0012fc368b34d4e591f5c3a339e33 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
-#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<FindBlockDeclRefExprsVals>{
   BumpVector<const VarDecl*> &BEVals;
   BumpVectorContext &BC;
   llvm::DenseMap<const VarDecl*, unsigned> Visited;
+  llvm::SmallSet<const DeclContext*, 4> IgnoredContexts;
 public:
   FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &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<VarDecl>(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
 
index a00217442053d16ef2ab24f547444d469c5a1d7f..9a266c9379392ca172f2dbe2c71162daa116350b 100644 (file)
@@ -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;
+}
+