summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Analysis/CFRefCount.cpp66
-rw-r--r--clang/lib/Analysis/GRExprEngine.cpp54
-rw-r--r--clang/lib/Analysis/GRTransferFuncs.cpp19
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,
OpenPOWER on IntegriCloud