diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Analysis/CFRefCount.cpp | 66 | ||||
-rw-r--r-- | clang/lib/Analysis/GRExprEngine.cpp | 54 | ||||
-rw-r--r-- | clang/lib/Analysis/GRTransferFuncs.cpp | 19 |
3 files changed, 44 insertions, 95 deletions
diff --git a/clang/lib/Analysis/CFRefCount.cpp b/clang/lib/Analysis/CFRefCount.cpp index 5d8e4f2badf..875c4e39b88 100644 --- a/clang/lib/Analysis/CFRefCount.cpp +++ b/clang/lib/Analysis/CFRefCount.cpp @@ -15,7 +15,7 @@ #include "GRSimpleVals.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceManager.h" -#include "clang/Analysis/PathSensitive/GRState.h" +#include "clang/Analysis/PathSensitive/GRExprEngineBuilders.h" #include "clang/Analysis/PathSensitive/GRStateTrait.h" #include "clang/Analysis/PathDiagnostic.h" #include "clang/Analysis/LocalCheckers.h" @@ -1360,13 +1360,9 @@ public: ObjCMessageExpr* ME, ExplodedNode<GRState>* Pred); - // Stores. - - virtual void EvalStore(ExplodedNodeSet<GRState>& Dst, - GRExprEngine& Engine, - GRStmtNodeBuilder<GRState>& Builder, - Expr* E, ExplodedNode<GRState>* Pred, - const GRState* St, SVal TargetLV, SVal Val); + // Stores. + virtual void EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val); + // End-of-path. virtual void EvalEndPath(GRExprEngine& Engine, @@ -1741,22 +1737,13 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst, ME->arg_begin(), ME->arg_end(), Pred); } -// Stores. - -void CFRefCount::EvalStore(ExplodedNodeSet<GRState>& Dst, - GRExprEngine& Eng, - GRStmtNodeBuilder<GRState>& Builder, - Expr* E, ExplodedNode<GRState>* Pred, - const GRState* St, SVal TargetLV, SVal Val) { - +void CFRefCount::EvalBind(GRStmtNodeBuilderRef& B, SVal location, SVal val) { // Check if we have a binding for "Val" and if we are storing it to something - // we don't understand or otherwise the value "escapes" the function. - - if (!isa<loc::SymbolVal>(Val)) + // we don't understand or otherwise the value "escapes" the function. + if (!isa<loc::SymbolVal>(val)) return; - // Are we storing to something that causes the value to "escape"? - + // Are we storing to something that causes the value to "escape"? bool escapes = false; // A value escapes in three possible cases (this may change): @@ -1764,44 +1751,35 @@ void CFRefCount::EvalStore(ExplodedNodeSet<GRState>& Dst, // (1) we are binding to something that is not a memory region. // (2) we are binding to a memregion that does not have stack storage // (3) we are binding to a memregion with stack storage that the store - // does not understand. - - SymbolRef Sym = cast<loc::SymbolVal>(Val).getSymbol(); - GRStateRef state(St, Eng.getStateManager()); + // does not understand. + SymbolRef Sym = cast<loc::SymbolVal>(val).getSymbol(); + GRStateRef state = B.getState(); - if (!isa<loc::MemRegionVal>(TargetLV)) + if (!isa<loc::MemRegionVal>(location)) escapes = true; else { - const MemRegion* R = cast<loc::MemRegionVal>(TargetLV).getRegion(); - escapes = !Eng.getStateManager().hasStackStorage(R); + const MemRegion* R = cast<loc::MemRegionVal>(location).getRegion(); + escapes = !B.getStateManager().hasStackStorage(R); if (!escapes) { // To test (3), generate a new state with the binding removed. If it is // the same state, then it escapes (since the store cannot represent // the binding). - GRStateRef stateNew = state.BindLoc(cast<Loc>(TargetLV), Val); - escapes = (stateNew == state); + escapes = (state == (state.BindLoc(cast<Loc>(location), UnknownVal()))); } } - - if (!escapes) - return; - // Do we have a reference count binding? - // FIXME: Is this step even needed? We do blow away the binding anyway. - if (!state.get<RefBindings>(Sym)) + // Our store can represent the binding and we aren't storing to something + // that doesn't have local storage. Just return and have the simulation + // state continue as is. We should also just return if the tracked symbol + // is not associated with a reference count. + if (!escapes || !state.get<RefBindings>(Sym)) return; - - // Nuke the binding. - state = state.remove<RefBindings>(Sym); - // Hand of the remaining logic to the parent implementation. - GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, state, TargetLV, Val); + // The tracked object excapes. Stop tracking the object. + B.MakeNode(state.remove<RefBindings>(Sym)); } -// End-of-path. - - std::pair<GRStateRef,bool> CFRefCount::HandleSymbolDeath(GRStateManager& VMgr, const GRState* St, const Decl* CD, diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index a52437c343e..f0e93de2193 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -14,6 +14,8 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/PathSensitive/GRExprEngine.h" +#include "clang/Analysis/PathSensitive/GRExprEngineBuilders.h" + #include "clang/Analysis/PathSensitive/BugReporter.h" #include "clang/Basic/SourceManager.h" #include "llvm/Support/Streams.h" @@ -125,28 +127,6 @@ GRExprEngine::~GRExprEngine() { // Utility methods. //===----------------------------------------------------------------------===// -// SaveAndRestore - A utility class that uses RIIA to save and restore -// the value of a variable. -template<typename T> -struct VISIBILITY_HIDDEN SaveAndRestore { - SaveAndRestore(T& x) : X(x), old_value(x) {} - ~SaveAndRestore() { X = old_value; } - T get() { return old_value; } - - T& X; - T old_value; -}; - -// SaveOr - Similar to SaveAndRestore. Operates only on bools; the old -// value of a variable is saved, and during the dstor the old value is -// or'ed with the new value. -struct VISIBILITY_HIDDEN SaveOr { - SaveOr(bool& x) : X(x), old_value(x) { x = false; } - ~SaveOr() { X |= old_value; } - - bool& X; - bool old_value; -}; void GRExprEngine::setTransferFunctions(GRTransferFuncs* tf) { StateMgr.TF = tf; @@ -920,17 +900,27 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred, void GRExprEngine::EvalBind(NodeSet& Dst, Expr* Ex, NodeTy* Pred, const GRState* state, SVal location, SVal Val) { - unsigned size = Dst.size(); - SaveAndRestore<bool> OldSink(Builder->BuildSinks); - SaveOr OldHasGen(Builder->HasGeneratedNode); - - getTF().EvalStore(Dst, *this, *Builder, Ex, Pred, state, location, Val); + const GRState* newState = 0; + + if (location.isUnknown()) { + // We know that the new state will be the same as the old state since + // the location of the binding is "unknown". Consequently, there + // is no reason to just create a new node. + newState = state; + } + else { + // We are binding to a value other than 'unknown'. Perform the binding + // using the StoreManager. + newState = StateMgr.BindLoc(state, cast<Loc>(location), Val); + } - // Handle the case where no nodes where generated. Auto-generate that - // contains the updated state if we aren't generating sinks. - if (!Builder->BuildSinks && Dst.size() == size && !Builder->HasGeneratedNode) - getTF().GRTransferFuncs::EvalStore(Dst, *this, *Builder, Ex, Pred, state, - location, Val); + // The next thing to do is check if the GRTransferFuncs object wants to + // update the state based on the new binding. If the GRTransferFunc object + // doesn't do anything, just auto-propagate the current state. + GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, Pred, newState, Ex, + newState != state); + + getTF().EvalBind(BuilderRef, location, Val); } /// EvalStore - Handle the semantics of a store via an assignment. diff --git a/clang/lib/Analysis/GRTransferFuncs.cpp b/clang/lib/Analysis/GRTransferFuncs.cpp index d621edddc6d..c08bd8f0b19 100644 --- a/clang/lib/Analysis/GRTransferFuncs.cpp +++ b/clang/lib/Analysis/GRTransferFuncs.cpp @@ -17,25 +17,6 @@ using namespace clang; -void GRTransferFuncs::EvalStore(ExplodedNodeSet<GRState>& Dst, - GRExprEngine& Eng, - GRStmtNodeBuilder<GRState>& Builder, - Expr* E, ExplodedNode<GRState>* Pred, - const GRState* St, SVal TargetLV, SVal Val) { - - // This code basically matches the "safety-net" logic of GRExprEngine: - // bind Val to TargetLV, and create a new node. We replicate it here - // because subclasses of GRTransferFuncs may wish to call it. - - assert (!TargetLV.isUndef()); - - if (TargetLV.isUnknown()) - Builder.MakeNode(Dst, E, Pred, St); - else - Builder.MakeNode(Dst, E, Pred, - Eng.getStateManager().BindLoc(St, cast<Loc>(TargetLV), Val)); -} - void GRTransferFuncs::EvalBinOpNN(GRStateSet& OStates, GRExprEngine& Eng, const GRState *St, Expr* Ex, |