aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-09-25 19:03:06 +0000
committerJordan Rose <jordan_rose@apple.com>2012-09-25 19:03:06 +0000
commit0073a5c7ce38e98365c00921316030627b3d129f (patch)
treeb5d729236bb901d9a6003035dd66004b324e45e1
parent6e3bf21f20d4d744fdf5acd719e9f442f4a144fc (diff)
Reapply "[analyzer] Remove constraints on dead symbols as part of removeDeadBindings."
Previously, we'd just keep constraints around forever, which means we'd never be able to merge paths that differed only in constraints on dead symbols. Because we now allow constraints on symbolic expressions, not just single symbols, this requires changing SymExpr::symbol_iterator to include intermediate symbol nodes in its traversal, not just the SymbolData leaf nodes. This depends on the previous commit to be correct. Originally applied in r163444, reverted in r164275, now being re-applied. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164622 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/StaticAnalyzer/Core/ProgramState.cpp9
-rw-r--r--lib/StaticAnalyzer/Core/SymbolManager.cpp8
-rw-r--r--test/Analysis/traversal-path-unification.c21
3 files changed, 29 insertions, 9 deletions
diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp
index ed128ef00d..56c6c04df0 100644
--- a/lib/StaticAnalyzer/Core/ProgramState.cpp
+++ b/lib/StaticAnalyzer/Core/ProgramState.cpp
@@ -106,8 +106,9 @@ ProgramStateManager::removeDeadBindings(ProgramStateRef state,
SymReaper);
NewState.setStore(newStore);
SymReaper.setReapedStore(newStore);
-
- return getPersistentState(NewState);
+
+ ProgramStateRef Result = getPersistentState(NewState);
+ return ConstraintMgr->removeDeadBindings(Result, SymReaper);
}
ProgramStateRef ProgramState::bindCompoundLiteral(const CompoundLiteralExpr *CL,
@@ -686,7 +687,9 @@ bool ProgramState::isTainted(SymbolRef Sym, TaintTagType Kind) const {
bool Tainted = false;
for (SymExpr::symbol_iterator SI = Sym->symbol_begin(), SE =Sym->symbol_end();
SI != SE; ++SI) {
- assert(isa<SymbolData>(*SI));
+ if (!isa<SymbolData>(*SI))
+ continue;
+
const TaintTagType *Tag = get<TaintMap>(*SI);
Tainted = (Tag && *Tag == Kind);
diff --git a/lib/StaticAnalyzer/Core/SymbolManager.cpp b/lib/StaticAnalyzer/Core/SymbolManager.cpp
index 87b4ba315e..5334b03b3f 100644
--- a/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ b/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -117,21 +117,17 @@ bool SymExpr::symbol_iterator::operator!=(const symbol_iterator &X) const {
SymExpr::symbol_iterator::symbol_iterator(const SymExpr *SE) {
itr.push_back(SE);
- while (!isa<SymbolData>(itr.back())) expand();
}
SymExpr::symbol_iterator &SymExpr::symbol_iterator::operator++() {
assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
- assert(isa<SymbolData>(itr.back()));
- itr.pop_back();
- if (!itr.empty())
- while (!isa<SymbolData>(itr.back())) expand();
+ expand();
return *this;
}
SymbolRef SymExpr::symbol_iterator::operator*() {
assert(!itr.empty() && "attempting to dereference an 'end' iterator");
- return cast<SymbolData>(itr.back());
+ return itr.back();
}
void SymExpr::symbol_iterator::expand() {
diff --git a/test/Analysis/traversal-path-unification.c b/test/Analysis/traversal-path-unification.c
new file mode 100644
index 0000000000..0a45f48a01
--- /dev/null
+++ b/test/Analysis/traversal-path-unification.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.DumpTraversal %s | FileCheck %s
+
+int a();
+int b();
+int c();
+
+void testRemoveDeadBindings() {
+ int i = a();
+ if (i)
+ a();
+ else
+ b();
+
+ // At this point the symbol bound to 'i' is dead.
+ // The effects of a() and b() are identical (they both invalidate globals).
+ // We should unify the two paths here and only get one end-of-path node.
+ c();
+}
+
+// CHECK: --END PATH--
+// CHECK-NOT: --END PATH-- \ No newline at end of file