aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/CFRefCount.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-04-18 19:23:43 +0000
committerTed Kremenek <kremenek@apple.com>2008-04-18 19:23:43 +0000
commitcb61292aeafc1dc1bc4064fb3d2733717d1d50e5 (patch)
treea211da1ffa3b4c26fe8bc6d99c2f00fa27f49ee5 /lib/Analysis/CFRefCount.cpp
parent550a0f94938817e3550d79adcc6f1f27410f7593 (diff)
Added "GetErrorNodes()" to BugType so that -trim-egraph can recognize errors
from registered BugTypes. This helps with debugging. Add detection of NULL values in ref count checker; this suppresses false positives. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49912 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/CFRefCount.cpp')
-rw-r--r--lib/Analysis/CFRefCount.cpp58
1 files changed, 53 insertions, 5 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 1618f04359..3eb037978a 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -693,7 +693,12 @@ public:
GRStmtNodeBuilder<ValueState>& Builder,
ReturnStmt* S,
ExplodedNode<ValueState>* Pred);
-
+
+ // Assumptions.
+
+ virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
+ RVal Cond, bool Assumption, bool& isFeasible);
+
// Error iterators.
typedef UseAfterReleasesTy::iterator use_after_iterator;
@@ -1029,8 +1034,6 @@ ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St,
// End-of-path.
-
-
ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr,
ValueState* St, SymbolID sid,
RefVal V, bool& hasLeak) {
@@ -1066,9 +1069,9 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng,
ExplodedNode<ValueState>* N = Builder.MakeNode(St);
- if (!N)
+ if (!N || Leaked.empty())
return;
-
+
std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
assert (!LeaksAtNode);
LeaksAtNode = new std::vector<SymbolID>();
@@ -1138,6 +1141,44 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& Dst,
Builder.MakeNode(Dst, S, Pred, StateMgr.getPersistentState(StImpl));
}
+// Assumptions.
+
+ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St,
+ RVal Cond, bool Assumption,
+ bool& isFeasible) {
+
+ // FIXME: We may add to the interface of EvalAssume the list of symbols
+ // whose assumptions have changed. For now we just iterate through the
+ // bindings and check if any of the tracked symbols are NULL. This isn't
+ // too bad since the number of symbols we will track in practice are
+ // probably small and EvalAssume is only called at branches and a few
+ // other places.
+
+ RefBindings B = GetRefBindings(*St);
+
+ if (B.isEmpty())
+ return St;
+
+ bool changed = false;
+
+ for (RefBindings::iterator I=B.begin(), E=B.end(); I!=E; ++I) {
+
+ // Check if the symbol is null (or equal to any constant).
+ // If this is the case, stop tracking the symbol.
+
+ if (St->getSymVal(I.getKey())) {
+ changed = true;
+ B = RefBFactory.Remove(B, I.getKey());
+ }
+ }
+
+ if (!changed)
+ return St;
+
+ ValueState StImpl = *St;
+ StImpl.CheckerState = B.getRoot();
+ return Eng.getStateManager().getPersistentState(StImpl);
+}
CFRefCount::RefBindings CFRefCount::Update(RefBindings B, SymbolID sym,
RefVal V, ArgEffect E,
@@ -1280,6 +1321,7 @@ namespace {
}
virtual void EmitWarnings(BugReporter& BR);
+ virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes);
};
//===---------===//
@@ -1465,6 +1507,12 @@ void Leak::EmitWarnings(BugReporter& BR) {
}
}
+void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
+ for (CFRefCount::leaks_iterator I=TF.leaks_begin(), E=TF.leaks_end();
+ I!=E; ++I)
+ Nodes.push_back(I->first);
+}
+
//===----------------------------------------------------------------------===//
// Transfer function creation for external clients.
//===----------------------------------------------------------------------===//