aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2011-03-23 21:33:21 +0000
committerTed Kremenek <kremenek@apple.com>2011-03-23 21:33:21 +0000
commita8d459e8a68b1270b0c35fb73e8cc090b2b69e36 (patch)
treefe8dbcf5670755c0d49308ece7aa965dfcfa795c
parentbec7343433f6d4feee6af3a3a664f0301d41960e (diff)
Fix CFG-construction bug when run from AnalysisBasedWarnings::IssueWarnings() where block-level expressions that need
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
-rw-r--r--lib/Analysis/CFG.cpp32
-rw-r--r--test/Sema/exprs.c8
2 files changed, 31 insertions, 9 deletions
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index a1afd60fe7..c193112131 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -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;
}
diff --git a/test/Sema/exprs.c b/test/Sema/exprs.c
index 0d6c5488de..86cd52ec63 100644
--- a/test/Sema/exprs.c
+++ b/test/Sema/exprs.c
@@ -12,6 +12,14 @@
} 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'}}