diff options
author | Ted Kremenek <kremenek@apple.com> | 2011-03-23 21:33:21 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2011-03-23 21:33:21 +0000 |
commit | dcc4c389701737b4dd2ebb5644f48c3ae3777a1c (patch) | |
tree | 7e3010d87daf6ff97f604a2a48b0a7a88e0f65d3 | |
parent | ab234158b81dea3fb159ec9376096b68311d455f (diff) | |
download | bcm5719-llvm-dcc4c389701737b4dd2ebb5644f48c3ae3777a1c.tar.gz bcm5719-llvm-dcc4c389701737b4dd2ebb5644f48c3ae3777a1c.zip |
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>.
llvm-svn: 128170
-rw-r--r-- | clang/lib/Analysis/CFG.cpp | 32 | ||||
-rw-r--r-- | clang/test/Sema/exprs.c | 8 |
2 files changed, 31 insertions, 9 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index a1afd60fe7a..c193112131f 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/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/clang/test/Sema/exprs.c b/clang/test/Sema/exprs.c index 0d6c5488de5..86cd52ec636 100644 --- a/clang/test/Sema/exprs.c +++ b/clang/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'}} |