diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Analysis/PathSensitive/BugReporter.h | 2 | ||||
-rw-r--r-- | clang/include/clang/Analysis/PathSensitive/GRTransferFuncs.h | 7 | ||||
-rw-r--r-- | clang/lib/Analysis/CFRefCount.cpp | 58 | ||||
-rw-r--r-- | clang/lib/Analysis/GRExprEngine.cpp | 19 |
4 files changed, 72 insertions, 14 deletions
diff --git a/clang/include/clang/Analysis/PathSensitive/BugReporter.h b/clang/include/clang/Analysis/PathSensitive/BugReporter.h index b209a3296bd..f2f2e031661 100644 --- a/clang/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/clang/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 <vector> namespace clang { @@ -41,6 +42,7 @@ public: virtual const char* getDescription() const { return getName(); } virtual void EmitWarnings(BugReporter& BR) {} + virtual void GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {} }; class BugReport { diff --git a/clang/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/clang/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index 60492b5eeab..33199a574c4 100644 --- a/clang/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/clang/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/clang/lib/Analysis/CFRefCount.cpp b/clang/lib/Analysis/CFRefCount.cpp index 1618f04359d..3eb037978a1 100644 --- a/clang/lib/Analysis/CFRefCount.cpp +++ b/clang/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. //===----------------------------------------------------------------------===// diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index e3fe2395535..63986fb38a5 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/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<llvm::DenseMap<GRExprEngine::NodeTy*, Expr*>::iterator> } template <typename ITERATOR> -static void AddSources(llvm::SmallVector<GRExprEngine::NodeTy*, 10>& Sources, +static void AddSources(std::vector<GRExprEngine::NodeTy*>& Sources, ITERATOR I, ITERATOR E) { llvm::SmallPtrSet<void*,10> CachedSources; @@ -2280,7 +2284,9 @@ static void AddSources(llvm::SmallVector<GRExprEngine::NodeTy*, 10>& Sources, void GRExprEngine::ViewGraph(bool trim) { #ifndef NDEBUG if (trim) { - llvm::SmallVector<NodeTy*, 10> Src; + std::vector<NodeTy*> 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 { |