]> granicus.if.org Git - clang/commitdiff
Fix CFG-construction bug when run from AnalysisBasedWarnings::IssueWarnings() where...
authorTed Kremenek <kremenek@apple.com>
Wed, 23 Mar 2011 21:33:21 +0000 (21:33 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 23 Mar 2011 21:33:21 +0000 (21:33 +0000)
to be recorded in the Stmt*->CFGBlock* map were not always done so.  Fixes <rdar://problem/9171946>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128170 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/CFG.cpp
test/Sema/exprs.c

index a1afd60fe7ad5914dc86a6db1b881dd1bf18994a..c193112131ff1fd4ffb30301ca39859e43a08434 100644 (file)
@@ -284,6 +284,7 @@ class CFGBuilder {
   Expr::EvalResult *switchCond;
   
   CFG::BuildOptions::ForcedBlkExprs::value_type *cachedEntry;
+  const Stmt *lastLookup;
 
 public:
   explicit CFGBuilder(ASTContext *astContext,
@@ -293,7 +294,7 @@ public:
       SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL),
       TryTerminatedBlock(NULL), badCFG(false), BuildOpts(buildOpts), 
       switchExclusivelyCovered(false), switchCond(0),
-      cachedEntry(0) {}
+      cachedEntry(0), lastLookup(0) {}
 
   // buildCFG - Used by external clients to construct the CFG.
   CFG* buildCFG(const Decl *D, Stmt *Statement);
@@ -393,11 +394,8 @@ private:
 
   // Interface to CFGBlock - adding CFGElements.
   void appendStmt(CFGBlock *B, Stmt *S) {
-    if (cachedEntry) {
-      assert(cachedEntry->first == S);
+    if (alwaysAdd(S))
       cachedEntry->second = B;
-      cachedEntry = 0;
-    }    
 
     B->appendStmt(S, cfg->getBumpVectorContext());
   }
@@ -459,20 +457,36 @@ inline bool AddStmtChoice::alwaysAdd(CFGBuilder &builder,
                                      const Stmt *stmt) const {
   return builder.alwaysAdd(stmt) || kind == AlwaysAdd;
 }
-  
+
 bool CFGBuilder::alwaysAdd(const Stmt *stmt) {
   if (!BuildOpts.forcedBlkExprs)
     return false;
+
+  if (lastLookup == stmt) {  
+    if (cachedEntry) {
+      assert(cachedEntry->first == stmt);
+      return true;
+    }
+    return false;
+  }
   
+  lastLookup = stmt;
+
+  // Perform the lookup!
   CFG::BuildOptions::ForcedBlkExprs *fb = *BuildOpts.forcedBlkExprs;
 
-  if (!fb)
+  if (!fb) {
+    // No need to update 'cachedEntry', since it will always be null.
+    assert(cachedEntry == 0);
     return false;
+  }
 
   CFG::BuildOptions::ForcedBlkExprs::iterator itr = fb->find(stmt);
-  if (itr == fb->end())
+  if (itr == fb->end()) {
+    cachedEntry = 0;
     return false;
-  
+  }
+
   cachedEntry = &*itr;
   return true;
 }
index 0d6c5488de5f25695e22728c0232b68d46187b73..86cd52ec636244159103837eb1142d2ce721d7dc 100644 (file)
   } while (0)
 
 
+// Test that we don't report divide-by-zero errors in unreachable code.
+// This test should be left as is, as it also tests CFG functionality.
+void radar9171946() {
+  if (0) {
+    0 / (0 ? 1 : 0); // expected-warning {{expression result unused}}
+  }
+}
+
 int test_pr8876() {
   PR8876(0); // no-warning
   PR8876_pos(0); // expected-warning{{indirection of non-volatile null pointer will be deleted, not trap}} expected-note{{consider using __builtin_trap() or qualifying pointer with 'volatile'}}