diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-02-14 01:43:44 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-02-14 01:43:44 +0000 |
commit | 41573ebf8fb971f40fa8a3e20648362c359b4916 (patch) | |
tree | 819d4b68e8463bfab03d015c4c894a72d4fc4d8f /lib/Analysis/GRExprEngine.cpp | |
parent | 13f5f6e4796607e7bebfed1c09d9e5d4248fce9e (diff) |
Static analyzer:
- Added a new 'node builder' class called GRStmtNodeBuilderRef (name may
change). This is essentially a smart reference to a GRStmtNodeBuilder object
that keeps track of the current context (predecessor node, GRExprEngine
object, etc.) The idea is to gradually simplify the interface between
GRExprEngine and GRTransferFuncs using this new builder (i.e., passing 1
argument instead of 5). It also handles some of the "auto-transition" for node
creation, simplifying some of the logic in GRExprEngine itself.
- Used GRStmtBuilderRef to replace GRTransferFuncs::EvalStore with
GRTransferFuncs::EvalBind. The new EvalBind method will be used at any
arbitrary places where a binding between a location and value takes place.
Moreover, GRTransferFuncs no longer has the responsibility to request
StoreManager to do the binding; this is now in GRExprEngine::EvalBind. All
GRTransferFuncs::EvalBind does is checker-specific logic (which can be a
no-op).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64525 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/GRExprEngine.cpp')
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 54 |
1 files changed, 22 insertions, 32 deletions
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index a52437c343..f0e93de219 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/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. |