From: Ted Kremenek Date: Fri, 18 Apr 2008 19:23:43 +0000 (+0000) Subject: Added "GetErrorNodes()" to BugType so that -trim-egraph can recognize errors X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cb61292aeafc1dc1bc4064fb3d2733717d1d50e5;p=clang 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 --- diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h index b209a3296b..f2f2e03166 100644 --- a/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/include/clang/Analysis/PathSensitive/BugReporter.h @@ -19,6 +19,7 @@ #include "clang/Analysis/PathSensitive/ValueState.h" #include "clang/Analysis/PathSensitive/ExplodedGraph.h" #include "llvm/ADT/SmallPtrSet.h" +#include namespace clang { @@ -41,6 +42,7 @@ public: virtual const char* getDescription() const { return getName(); } virtual void EmitWarnings(BugReporter& BR) {} + virtual void GetErrorNodes(std::vector*>& Nodes) {} }; class BugReport { diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index 60492b5eea..33199a574c 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -99,11 +99,8 @@ public: // Assumptions. - virtual ValueState* EvalAssume(ValueState* St, NonLVal Cond, bool Assumption){ - return St; - } - - virtual ValueState* EvalAssume(ValueState* St, LVal Cond, bool Assumption) { + virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St, + RVal Cond, bool Assumption, bool& isFeasible) { return St; } }; 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& Builder, ReturnStmt* S, ExplodedNode* 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* N = Builder.MakeNode(St); - if (!N) + if (!N || Leaked.empty()) return; - + std::vector*& LeaksAtNode = Leaks[N]; assert (!LeaksAtNode); LeaksAtNode = new std::vector(); @@ -1138,6 +1141,44 @@ void CFRefCount::EvalReturn(ExplodedNodeSet& 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*>& Nodes); }; //===---------===// @@ -1465,6 +1507,12 @@ void Leak::EmitWarnings(BugReporter& BR) { } } +void Leak::GetErrorNodes(std::vector*>& 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. //===----------------------------------------------------------------------===// diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index e3fe239553..63986fb38a 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1843,7 +1843,9 @@ ValueState* GRExprEngine::Assume(ValueState* St, LVal Cond, bool Assumption, bool& isFeasible) { St = AssumeAux(St, Cond, Assumption, isFeasible); - return isFeasible ? St : TF->EvalAssume(St, Cond, Assumption); + + return isFeasible ? TF->EvalAssume(*this, St, Cond, Assumption, isFeasible) + : St; } ValueState* GRExprEngine::AssumeAux(ValueState* St, LVal Cond, @@ -1881,7 +1883,9 @@ ValueState* GRExprEngine::Assume(ValueState* St, NonLVal Cond, bool Assumption, bool& isFeasible) { St = AssumeAux(St, Cond, Assumption, isFeasible); - return isFeasible ? St : TF->EvalAssume(St, Cond, Assumption); + + return isFeasible ? TF->EvalAssume(*this, St, Cond, Assumption, isFeasible) + : St; } ValueState* GRExprEngine::AssumeAux(ValueState* St, NonLVal Cond, @@ -2258,7 +2262,7 @@ GetGraphNode::iterator> } template -static void AddSources(llvm::SmallVector& Sources, +static void AddSources(std::vector& Sources, ITERATOR I, ITERATOR E) { llvm::SmallPtrSet CachedSources; @@ -2280,7 +2284,9 @@ static void AddSources(llvm::SmallVector& Sources, void GRExprEngine::ViewGraph(bool trim) { #ifndef NDEBUG if (trim) { - llvm::SmallVector Src; + std::vector Src; + + // Fixme: Migrate over to the new way of adding nodes. AddSources(Src, null_derefs_begin(), null_derefs_end()); AddSources(Src, undef_derefs_begin(), undef_derefs_end()); AddSources(Src, explicit_bad_divides_begin(), explicit_bad_divides_end()); @@ -2289,6 +2295,11 @@ void GRExprEngine::ViewGraph(bool trim) { AddSources(Src, undef_arg_begin(), undef_arg_end()); AddSources(Src, undef_branches_begin(), undef_branches_end()); + // The new way. + for (BugTypeSet::iterator I=BugTypes.begin(), E=BugTypes.end(); I!=E; ++I) + (*I)->GetErrorNodes(Src); + + ViewGraph(&Src[0], &Src[0]+Src.size()); } else {