aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Analysis/PathSensitive/BasicStore.h27
-rw-r--r--include/clang/Analysis/PathSensitive/ExplodedGraph.h27
-rw-r--r--include/clang/Analysis/PathSensitive/GRCoreEngine.h71
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngine.h73
-rw-r--r--include/clang/Analysis/PathSensitive/GRTransferFuncs.h10
-rw-r--r--include/clang/Analysis/PathSensitive/Store.h34
-rw-r--r--include/clang/Analysis/PathSensitive/ValueState.h113
-rw-r--r--lib/Analysis/BasicObjCFoundationChecks.cpp6
-rw-r--r--lib/Analysis/BasicStore.cpp141
-rw-r--r--lib/Analysis/BugReporter.cpp6
-rw-r--r--lib/Analysis/CFRefCount.cpp62
-rw-r--r--lib/Analysis/GRCoreEngine.cpp18
-rw-r--r--lib/Analysis/GRExprEngine.cpp133
-rw-r--r--lib/Analysis/GRSimpleVals.cpp10
-rw-r--r--lib/Analysis/GRTransferFuncs.cpp2
-rw-r--r--lib/Analysis/ValueState.cpp151
16 files changed, 519 insertions, 365 deletions
diff --git a/include/clang/Analysis/PathSensitive/BasicStore.h b/include/clang/Analysis/PathSensitive/BasicStore.h
new file mode 100644
index 0000000000..88ac9ce381
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/BasicStore.h
@@ -0,0 +1,27 @@
+//== BasicStore.h - Basic map from Locations to Values ----------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the BasicStore and BasicStoreManager classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_BASICSTORE_H
+#define LLVM_CLANG_ANALYSIS_BASICSTORE_H
+
+#include "clang/Analysis/PathSensitive/Store.h"
+
+namespace llvm {
+ class llvm::BumpPtrAllocator;
+}
+
+namespace clang {
+ StoreManager* CreateBasicStoreManager(llvm::BumpPtrAllocator& Alloc);
+}
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Analysis/PathSensitive/ExplodedGraph.h
index 39a064d4c6..71043f0ef6 100644
--- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h
+++ b/include/clang/Analysis/PathSensitive/ExplodedGraph.h
@@ -95,10 +95,8 @@ protected:
/// with this node.
const ProgramPoint Location;
- /// State - The state associated with this node. Normally this value
- /// is immutable, but we anticipate there will be times when algorithms
- /// that directly manipulate the analysis graph will need to change it.
- void* State;
+ /// State - The state associated with this node.
+ const void* State;
/// Preds - The predecessors of this node.
NodeGroup Preds;
@@ -107,7 +105,7 @@ protected:
NodeGroup Succs;
/// Construct a ExplodedNodeImpl with the provided location and state.
- explicit ExplodedNodeImpl(const ProgramPoint& loc, void* state)
+ explicit ExplodedNodeImpl(const ProgramPoint& loc, const void* state)
: Location(loc), State(state) {}
/// addPredeccessor - Adds a predecessor to the current node, and
@@ -146,19 +144,19 @@ class ExplodedNode : public ExplodedNodeImpl {
public:
/// Construct a ExplodedNodeImpl with the given node ID, program edge,
/// and state.
- explicit ExplodedNode(const ProgramPoint& loc, StateTy* St)
+ explicit ExplodedNode(const ProgramPoint& loc, const StateTy* St)
: ExplodedNodeImpl(loc, St) {}
/// getState - Returns the state associated with the node.
- inline StateTy* getState() const {
- return static_cast<StateTy*>(State);
+ inline const StateTy* getState() const {
+ return static_cast<const StateTy*>(State);
}
// Profiling (for FoldingSet).
static inline void Profile(llvm::FoldingSetNodeID& ID,
const ProgramPoint& Loc,
- StateTy* state) {
+ const StateTy* state) {
ID.Add(Loc);
GRTrait<StateTy>::Profile(ID, state);
}
@@ -241,7 +239,8 @@ protected:
/// getNodeImpl - Retrieve the node associated with a (Location,State)
/// pair, where 'State' is represented as an opaque void*. This method
/// is intended to be used only by GRCoreEngineImpl.
- virtual ExplodedNodeImpl* getNodeImpl(const ProgramPoint& L, void* State,
+ virtual ExplodedNodeImpl* getNodeImpl(const ProgramPoint& L,
+ const void* State,
bool* IsNew) = 0;
virtual ExplodedGraphImpl* MakeEmptyGraph() const = 0;
@@ -300,9 +299,10 @@ protected:
protected:
virtual ExplodedNodeImpl* getNodeImpl(const ProgramPoint& L,
- void* State, bool* IsNew) {
+ const void* State,
+ bool* IsNew) {
- return getNode(L, static_cast<StateTy*>(State), IsNew);
+ return getNode(L, static_cast<const StateTy*>(State), IsNew);
}
virtual ExplodedGraphImpl* MakeEmptyGraph() const {
@@ -317,7 +317,8 @@ public:
/// where the 'Location' is a ProgramPoint in the CFG. If no node for
/// this pair exists, it is created. IsNew is set to true if
/// the node was freshly created.
- NodeTy* getNode(const ProgramPoint& L, StateTy* State, bool* IsNew = NULL) {
+ NodeTy* getNode(const ProgramPoint& L, const StateTy* State,
+ bool* IsNew = NULL) {
// Profile 'State' to determine if we already have an existing node.
llvm::FoldingSetNodeID profile;
diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Analysis/PathSensitive/GRCoreEngine.h
index 19028ee875..32fe9d3342 100644
--- a/include/clang/Analysis/PathSensitive/GRCoreEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRCoreEngine.h
@@ -61,14 +61,14 @@ protected:
/// number of times different CFGBlocks have been visited along a path.
GRBlockCounter::Factory BCounterFactory;
- void GenerateNode(const ProgramPoint& Loc, void* State,
+ void GenerateNode(const ProgramPoint& Loc, const void* State,
ExplodedNodeImpl* Pred = NULL);
/// getInitialState - Gets the void* representing the initial 'state'
/// of the analysis. This is simply a wrapper (implemented
/// in GRCoreEngine) that performs type erasure on the initial
/// state returned by the checker object.
- virtual void* getInitialState() = 0;
+ virtual const void* getInitialState() = 0;
void HandleBlockEdge(const BlockEdge& E, ExplodedNodeImpl* Pred);
void HandleBlockEntrance(const BlockEntrance& E, ExplodedNodeImpl* Pred);
@@ -81,7 +81,7 @@ protected:
virtual void ProcessEndPath(GREndPathNodeBuilderImpl& Builder) = 0;
- virtual bool ProcessBlockEntrance(CFGBlock* Blk, void* State,
+ virtual bool ProcessBlockEntrance(CFGBlock* Blk, const void* State,
GRBlockCounter BC) = 0;
virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& Builder) = 0;
@@ -142,11 +142,11 @@ public:
}
ExplodedNodeImpl*
- generateNodeImpl(Stmt* S, void* State, ExplodedNodeImpl* Pred,
+ generateNodeImpl(Stmt* S, const void* State, ExplodedNodeImpl* Pred,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind);
ExplodedNodeImpl*
- generateNodeImpl(Stmt* S, void* State,
+ generateNodeImpl(Stmt* S, const void* State,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind) {
ExplodedNodeImpl* N = getLastNode();
assert (N && "Predecessor of new node is infeasible.");
@@ -169,7 +169,7 @@ class GRStmtNodeBuilder {
typedef ExplodedNode<StateTy> NodeTy;
GRStmtNodeBuilderImpl& NB;
- StateTy* CleanedState;
+ const StateTy* CleanedState;
GRAuditor<StateTy> **CallExprAuditBeg, **CallExprAuditEnd;
GRAuditor<StateTy> **ObjCMsgExprAuditBeg, **ObjCMsgExprAuditEnd;
@@ -201,7 +201,7 @@ public:
}
NodeTy*
- generateNode(Stmt* S, StateTy* St, NodeTy* Pred,
+ generateNode(Stmt* S, const StateTy* St, NodeTy* Pred,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind) {
HasGeneratedNode = true;
@@ -210,7 +210,7 @@ public:
}
NodeTy*
- generateNode(Stmt* S, StateTy* St,
+ generateNode(Stmt* S, const StateTy* St,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind) {
HasGeneratedNode = true;
@@ -226,21 +226,21 @@ public:
return NB.getCurrentBlockCount();
}
- StateTy* GetState(NodeTy* Pred) const {
+ const StateTy* GetState(NodeTy* Pred) const {
if ((ExplodedNodeImpl*) Pred == NB.getBasePredecessor())
return CleanedState;
else
return Pred->getState();
}
- void SetCleanedState(StateTy* St) {
+ void SetCleanedState(const StateTy* St) {
CleanedState = St;
}
NodeTy* MakeNode(ExplodedNodeSet<StateTy>& Dst, Stmt* S,
- NodeTy* Pred, StateTy* St) {
+ NodeTy* Pred, const StateTy* St) {
- StateTy* PredState = GetState(Pred);
+ const StateTy* PredState = GetState(Pred);
GRAuditor<StateTy> **AB = NULL, **AE = NULL;
@@ -309,7 +309,7 @@ public:
const ExplodedGraphImpl& getGraph() const { return *Eng.G; }
GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}
- ExplodedNodeImpl* generateNodeImpl(void* State, bool branch);
+ ExplodedNodeImpl* generateNodeImpl(const void* State, bool branch);
CFGBlock* getTargetBlock(bool branch) const {
return branch ? DstT : DstF;
@@ -340,11 +340,11 @@ public:
return static_cast<NodeTy*>(NB.getPredecessor());
}
- StateTy* getState() const {
+ const StateTy* getState() const {
return getPredecessor()->getState();
}
- NodeTy* generateNode(StateTy* St, bool branch) {
+ NodeTy* generateNode(const StateTy* St, bool branch) {
return static_cast<NodeTy*>(NB.generateNodeImpl(St, branch));
}
@@ -396,11 +396,11 @@ public:
Iterator begin() { return Iterator(DispatchBlock.succ_begin()); }
Iterator end() { return Iterator(DispatchBlock.succ_end()); }
- ExplodedNodeImpl* generateNodeImpl(const Iterator& I, void* State,
+ ExplodedNodeImpl* generateNodeImpl(const Iterator& I, const void* State,
bool isSink);
Expr* getTarget() const { return E; }
- void* getState() const { return Pred->State; }
+ const void* getState() const { return Pred->State; }
};
template<typename STATE>
@@ -421,12 +421,12 @@ public:
Expr* getTarget() const { return NB.getTarget(); }
- NodeTy* generateNode(const iterator& I, StateTy* St, bool isSink=false){
+ NodeTy* generateNode(const iterator& I, const StateTy* St, bool isSink=false){
return static_cast<NodeTy*>(NB.generateNodeImpl(I, St, isSink));
}
- StateTy* getState() const {
- return static_cast<StateTy*>(NB.getState());
+ const StateTy* getState() const {
+ return static_cast<const StateTy*>(NB.getState());
}
};
@@ -462,11 +462,14 @@ public:
Iterator begin() { return Iterator(Src->succ_rbegin()+1); }
Iterator end() { return Iterator(Src->succ_rend()); }
- ExplodedNodeImpl* generateCaseStmtNodeImpl(const Iterator& I, void* State);
- ExplodedNodeImpl* generateDefaultCaseNodeImpl(void* State, bool isSink);
+ ExplodedNodeImpl* generateCaseStmtNodeImpl(const Iterator& I,
+ const void* State);
+
+ ExplodedNodeImpl* generateDefaultCaseNodeImpl(const void* State,
+ bool isSink);
Expr* getCondition() const { return Condition; }
- void* getState() const { return Pred->State; }
+ const void* getState() const { return Pred->State; }
};
template<typename STATE>
@@ -487,16 +490,16 @@ public:
Expr* getCondition() const { return NB.getCondition(); }
- NodeTy* generateCaseStmtNode(const iterator& I, StateTy* St) {
+ NodeTy* generateCaseStmtNode(const iterator& I, const StateTy* St) {
return static_cast<NodeTy*>(NB.generateCaseStmtNodeImpl(I, St));
}
- NodeTy* generateDefaultCaseNode(StateTy* St, bool isSink = false) {
+ NodeTy* generateDefaultCaseNode(const StateTy* St, bool isSink = false) {
return static_cast<NodeTy*>(NB.generateDefaultCaseNodeImpl(St, isSink));
}
- StateTy* getState() const {
- return static_cast<StateTy*>(NB.getState());
+ const StateTy* getState() const {
+ return static_cast<const StateTy*>(NB.getState());
}
};
@@ -522,7 +525,7 @@ public:
return getBlockCounter().getNumVisited(B.getBlockID());
}
- ExplodedNodeImpl* generateNodeImpl(void* State);
+ ExplodedNodeImpl* generateNodeImpl(const void* State);
CFGBlock* getBlock() const { return &B; }
};
@@ -550,11 +553,11 @@ public:
return NB.getCurrentBlockCount();
}
- StateTy* getState() const {
+ const StateTy* getState() const {
return getPredecessor()->getState();
}
- NodeTy* MakeNode(StateTy* St) {
+ NodeTy* MakeNode(const StateTy* St) {
return static_cast<NodeTy*>(NB.generateNodeImpl(St));
}
};
@@ -571,7 +574,7 @@ public:
protected:
SubEngineTy& SubEngine;
- virtual void* getInitialState() {
+ virtual const void* getInitialState() {
return SubEngine.getInitialState();
}
@@ -585,9 +588,11 @@ protected:
SubEngine.ProcessStmt(S, Builder);
}
- virtual bool ProcessBlockEntrance(CFGBlock* Blk, void* State,
+ virtual bool ProcessBlockEntrance(CFGBlock* Blk, const void* State,
GRBlockCounter BC) {
- return SubEngine.ProcessBlockEntrance(Blk, static_cast<StateTy*>(State),BC);
+ return SubEngine.ProcessBlockEntrance(Blk,
+ static_cast<const StateTy*>(State),
+ BC);
}
virtual void ProcessBranch(Expr* Condition, Stmt* Terminator,
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
index 6dfd428bf4..97699ca902 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -86,7 +86,7 @@ protected:
/// CleanedState - The state for EntryNode "cleaned" of all dead
/// variables and symbols (as determined by a liveness analysis).
- ValueState* CleanedState;
+ const ValueState* CleanedState;
/// CurrentStmt - The current block-level statement.
Stmt* CurrentStmt;
@@ -210,7 +210,7 @@ public:
/// getInitialState - Return the initial state used for the root vertex
/// in the ExplodedGraph.
- ValueState* getInitialState();
+ const ValueState* getInitialState();
GraphTy& getGraph() { return G; }
const GraphTy& getGraph() const { return G; }
@@ -370,7 +370,8 @@ public:
/// ProcessBlockEntrance - Called by GRCoreEngine when start processing
/// a CFGBlock. This method returns true if the analysis should continue
/// exploring the given path, and false otherwise.
- bool ProcessBlockEntrance(CFGBlock* B, ValueState* St, GRBlockCounter BC);
+ bool ProcessBlockEntrance(CFGBlock* B, const ValueState* St,
+ GRBlockCounter BC);
/// ProcessBranch - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a branch condition.
@@ -401,7 +402,7 @@ public:
protected:
- ValueState* GetState(NodeTy* N) {
+ const ValueState* GetState(NodeTy* N) {
return N == EntryNode ? CleanedState : N->getState();
}
@@ -409,35 +410,35 @@ public:
// FIXME: Maybe make these accesible only within the StmtBuilder?
- ValueState* SetRVal(ValueState* St, Expr* Ex, RVal V);
+ const ValueState* SetRVal(const ValueState* St, Expr* Ex, RVal V);
- ValueState* SetRVal(ValueState* St, const Expr* Ex, RVal V) {
+ const ValueState* SetRVal(const ValueState* St, const Expr* Ex, RVal V) {
return SetRVal(St, const_cast<Expr*>(Ex), V);
}
protected:
- ValueState* SetBlkExprRVal(ValueState* St, Expr* Ex, RVal V) {
+ const ValueState* SetBlkExprRVal(const ValueState* St, Expr* Ex, RVal V) {
return StateMgr.SetRVal(St, Ex, V, true, false);
}
- ValueState* SetRVal(ValueState* St, LVal LV, RVal V) {
+ const ValueState* SetRVal(const ValueState* St, LVal LV, RVal V) {
return StateMgr.SetRVal(St, LV, V);
}
- RVal GetRVal(ValueState* St, Expr* Ex) {
+ RVal GetRVal(const ValueState* St, Expr* Ex) {
return StateMgr.GetRVal(St, Ex);
}
- RVal GetRVal(ValueState* St, const Expr* Ex) {
+ RVal GetRVal(const ValueState* St, const Expr* Ex) {
return GetRVal(St, const_cast<Expr*>(Ex));
}
- RVal GetBlkExprRVal(ValueState* St, Expr* Ex) {
+ RVal GetBlkExprRVal(const ValueState* St, Expr* Ex) {
return StateMgr.GetBlkExprRVal(St, Ex);
}
- RVal GetRVal(ValueState* St, LVal LV, QualType T = QualType()) {
+ RVal GetRVal(const ValueState* St, LVal LV, QualType T = QualType()) {
return StateMgr.GetRVal(St, LV, T);
}
@@ -447,8 +448,8 @@ protected:
/// Assume - Create new state by assuming that a given expression
/// is true or false.
- ValueState* Assume(ValueState* St, RVal Cond, bool Assumption,
- bool& isFeasible) {
+ const ValueState* Assume(const ValueState* St, RVal Cond, bool Assumption,
+ bool& isFeasible) {
if (Cond.isUnknown()) {
isFeasible = true;
@@ -461,28 +462,28 @@ protected:
return Assume(St, cast<NonLVal>(Cond), Assumption, isFeasible);
}
- ValueState* Assume(ValueState* St, LVal Cond, bool Assumption,
- bool& isFeasible);
+ const ValueState* Assume(const ValueState* St, LVal Cond, bool Assumption,
+ bool& isFeasible);
- ValueState* AssumeAux(ValueState* St, LVal Cond, bool Assumption,
- bool& isFeasible);
+ const ValueState* AssumeAux(const ValueState* St, LVal Cond, bool Assumption,
+ bool& isFeasible);
- ValueState* Assume(ValueState* St, NonLVal Cond, bool Assumption,
- bool& isFeasible);
+ const ValueState* Assume(const ValueState* St, NonLVal Cond, bool Assumption,
+ bool& isFeasible);
- ValueState* AssumeAux(ValueState* St, NonLVal Cond, bool Assumption,
- bool& isFeasible);
+ const ValueState* AssumeAux(const ValueState* St, NonLVal Cond,
+ bool Assumption, bool& isFeasible);
- ValueState* AssumeSymNE(ValueState* St, SymbolID sym, const llvm::APSInt& V,
- bool& isFeasible);
+ const ValueState* AssumeSymNE(const ValueState* St, SymbolID sym,
+ const llvm::APSInt& V, bool& isFeasible);
- ValueState* AssumeSymEQ(ValueState* St, SymbolID sym, const llvm::APSInt& V,
- bool& isFeasible);
+ const ValueState* AssumeSymEQ(const ValueState* St, SymbolID sym,
+ const llvm::APSInt& V, bool& isFeasible);
- ValueState* AssumeSymInt(ValueState* St, bool Assumption,
- const SymIntConstraint& C, bool& isFeasible);
+ const ValueState* AssumeSymInt(const ValueState* St, bool Assumption,
+ const SymIntConstraint& C, bool& isFeasible);
- NodeTy* MakeNode(NodeSet& Dst, Stmt* S, NodeTy* Pred, ValueState* St) {
+ NodeTy* MakeNode(NodeSet& Dst, Stmt* S, NodeTy* Pred, const ValueState* St) {
assert (Builder && "GRStmtNodeBuilder not present.");
return Builder->MakeNode(Dst, S, Pred, St);
}
@@ -568,7 +569,8 @@ protected:
void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst,
bool asLVal);
- bool CheckDivideZero(Expr* Ex, ValueState* St, NodeTy* Pred, RVal Denom);
+ bool CheckDivideZero(Expr* Ex, const ValueState* St, NodeTy* Pred,
+ RVal Denom);
RVal EvalCast(RVal X, QualType CastT) {
if (X.isUnknownOrUndef())
@@ -634,21 +636,22 @@ protected:
TF->EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred);
}
- void EvalStore(NodeSet& Dst, Expr* E, NodeTy* Pred, ValueState* St,
+ void EvalStore(NodeSet& Dst, Expr* E, NodeTy* Pred, const ValueState* St,
RVal TargetLV, RVal Val);
// FIXME: The "CheckOnly" option exists only because Array and Field
// loads aren't fully implemented. Eventually this option will go away.
void EvalLoad(NodeSet& Dst, Expr* Ex, NodeTy* Pred,
- ValueState* St, RVal location, bool CheckOnly = false);
+ const ValueState* St, RVal location, bool CheckOnly = false);
- ValueState* EvalLocation(Expr* Ex, NodeTy* Pred,
- ValueState* St, RVal location, bool isLoad = false);
+ const ValueState* EvalLocation(Expr* Ex, NodeTy* Pred,
+ const ValueState* St, RVal location,
+ bool isLoad = false);
void EvalReturn(NodeSet& Dst, ReturnStmt* s, NodeTy* Pred);
- ValueState* MarkBranch(ValueState* St, Stmt* Terminator, bool branchTaken);
+ const ValueState* MarkBranch(const ValueState* St, Stmt* Terminator, bool branchTaken);
};
} // end clang namespace
diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
index 323358e0c3..4e267f8859 100644
--- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
+++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
@@ -82,7 +82,7 @@ public:
GRExprEngine& Engine,
GRStmtNodeBuilder<ValueState>& Builder,
Expr* E, ExplodedNode<ValueState>* Pred,
- ValueState* St, RVal TargetLV, RVal Val);
+ const ValueState* St, RVal TargetLV, RVal Val);
// End-of-path and dead symbol notification.
@@ -96,7 +96,7 @@ public:
GRStmtNodeBuilder<ValueState>& Builder,
ExplodedNode<ValueState>* Pred,
Stmt* S,
- ValueState* St,
+ const ValueState* St,
const ValueStateManager::DeadSymbolsTy& Dead) {}
// Return statements.
@@ -109,8 +109,10 @@ public:
// Assumptions.
- virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St,
- RVal Cond, bool Assumption, bool& isFeasible) {
+ virtual const ValueState* EvalAssume(GRExprEngine& Engine,
+ const ValueState* St,
+ RVal Cond, bool Assumption,
+ bool& isFeasible) {
return St;
}
};
diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h
new file mode 100644
index 0000000000..adf9cf8eae
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/Store.h
@@ -0,0 +1,34 @@
+//== Store.h - Interface for maps from Locations to Values ------*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defined the types Store and StoreManager.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_STORE_H
+#define LLVM_CLANG_ANALYSIS_STORE_H
+
+#include "clang/Analysis/PathSensitive/RValues.h"
+
+namespace clang {
+
+typedef const void* Store;
+
+class StoreManager {
+public:
+ virtual ~StoreManager() {}
+ virtual RVal GetRVal(Store St, LVal LV, QualType T) = 0;
+ virtual Store SetRVal(Store St, LVal LV, RVal V) = 0;
+ virtual Store Remove(Store St, LVal LV) = 0;
+ virtual Store getInitialStore() = 0;
+};
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/ValueState.h b/include/clang/Analysis/PathSensitive/ValueState.h
index ab9b4a8b32..36bfdff5b9 100644
--- a/include/clang/Analysis/PathSensitive/ValueState.h
+++ b/include/clang/Analysis/PathSensitive/ValueState.h
@@ -17,6 +17,7 @@
// FIXME: Reduce the number of includes.
#include "clang/Analysis/PathSensitive/Environment.h"
+#include "clang/Analysis/PathSensitive/Store.h"
#include "clang/Analysis/PathSensitive/RValues.h"
#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
#include "clang/AST/Expr.h"
@@ -54,7 +55,6 @@ class ValueState : public llvm::FoldingSetNode {
public:
// Typedefs.
typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
- typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;
typedef llvm::ImmutableMap<SymbolID,IntSetTy> ConstNotEqTy;
typedef llvm::ImmutableMap<SymbolID,const llvm::APSInt*> ConstEqTy;
@@ -64,10 +64,10 @@ private:
friend class ValueStateManager;
Environment Env;
+ Store St;
// FIXME: Make these private.
public:
- VarBindingsTy VarBindings;
ConstNotEqTy ConstNotEq;
ConstEqTy ConstEq;
void* CheckerState;
@@ -75,10 +75,10 @@ public:
public:
/// This ctor is used when creating the first ValueState object.
- ValueState(const Environment& env, VarBindingsTy VB,
+ ValueState(const Environment& env, Store st,
ConstNotEqTy CNE, ConstEqTy CE)
: Env(env),
- VarBindings(VB),
+ St(st),
ConstNotEq(CNE),
ConstEq(CE),
CheckerState(NULL) {}
@@ -88,7 +88,7 @@ public:
ValueState(const ValueState& RHS)
: llvm::FoldingSetNode(),
Env(RHS.Env),
- VarBindings(RHS.VarBindings),
+ St(RHS.St),
ConstNotEq(RHS.ConstNotEq),
ConstEq(RHS.ConstEq),
CheckerState(RHS.CheckerState) {}
@@ -97,11 +97,15 @@ public:
/// The environment is the mapping from expressions to values.
const Environment& getEnvironment() const { return Env; }
+ /// getStore - Return the store associated with this state. The store
+ /// is a mapping from locations to values.
+ Store getStore() const { return St; }
+
/// Profile - Profile the contents of a ValueState object for use
/// in a FoldingSet.
static void Profile(llvm::FoldingSetNodeID& ID, const ValueState* V) {
V->Env.Profile(ID);
- V->VarBindings.Profile(ID);
+ ID.AddPointer(V->St);
V->ConstNotEq.Profile(ID);
V->ConstEq.Profile(ID);
ID.AddPointer(V->CheckerState);
@@ -124,9 +128,18 @@ public:
// Iterators.
+ // FIXME: We'll be removing the VarBindings iterator very soon. Right now
+ // it assumes that Store is a VarBindingsTy.
+ typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;
typedef VarBindingsTy::iterator vb_iterator;
- vb_iterator vb_begin() const { return VarBindings.begin(); }
- vb_iterator vb_end() const { return VarBindings.end(); }
+ vb_iterator vb_begin() const {
+ VarBindingsTy B(static_cast<const VarBindingsTy::TreeTy*>(St));
+ return B.begin();
+ }
+ vb_iterator vb_end() const {
+ VarBindingsTy B(static_cast<const VarBindingsTy::TreeTy*>(St));
+ return B.end();
+ }
typedef Environment::seb_iterator seb_iterator;
seb_iterator seb_begin() const { return Env.seb_begin(); }
@@ -173,8 +186,8 @@ template<> struct GRTrait<ValueState*> {
class ValueStateManager {
private:
EnvironmentManager EnvMgr;
+ llvm::OwningPtr<StoreManager> StMgr;
ValueState::IntSetTy::Factory ISetFactory;
- ValueState::VarBindingsTy::Factory VBFactory;
ValueState::ConstNotEqTy::Factory CNEFactory;
ValueState::ConstEqTy::Factory CEFactory;
@@ -196,58 +209,53 @@ private:
Environment RemoveBlkExpr(const Environment& Env, Expr* E) {
return EnvMgr.RemoveBlkExpr(Env, E);
}
-
- ValueState::VarBindingsTy Remove(ValueState::VarBindingsTy B, VarDecl* V) {
- return VBFactory.Remove(B, V);
- }
-
- ValueState::VarBindingsTy Remove(const ValueState& V, VarDecl* D) {
- return Remove(V.VarBindings, D);
+
+ // FIXME: Remove when we do lazy initializaton of variable bindings.
+ const ValueState* BindVar(const ValueState* St, VarDecl* D, RVal V) {
+ return SetRVal(St, lval::DeclVal(D), V);
}
-
- ValueState* BindVar(ValueState* St, VarDecl* D, RVal V);
- ValueState* UnbindVar(ValueState* St, VarDecl* D);
-
+
public:
- ValueStateManager(ASTContext& Ctx, llvm::BumpPtrAllocator& alloc)
- : EnvMgr(alloc),
- ISetFactory(alloc),
- VBFactory(alloc),
- CNEFactory(alloc),
- CEFactory(alloc),
- BasicVals(Ctx, alloc),
- SymMgr(alloc),
- Alloc(alloc) {}
-
- ValueState* getInitialState();
+ ValueStateManager(ASTContext& Ctx, StoreManager* stmgr,
+ llvm::BumpPtrAllocator& alloc)
+ : EnvMgr(alloc),
+ StMgr(stmgr),
+ ISetFactory(alloc),
+ CNEFactory(alloc),
+ CEFactory(alloc),
+ BasicVals(Ctx, alloc),
+ SymMgr(alloc),
+ Alloc(alloc) {}
+
+ const ValueState* getInitialState();
BasicValueFactory& getBasicValueFactory() { return BasicVals; }
SymbolManager& getSymbolManager() { return SymMgr; }
typedef llvm::DenseSet<SymbolID> DeadSymbolsTy;
- ValueState* RemoveDeadBindings(ValueState* St, Stmt* Loc,
- const LiveVariables& Liveness,
- DeadSymbolsTy& DeadSymbols);
+ const ValueState* RemoveDeadBindings(const ValueState* St, Stmt* Loc,
+ const LiveVariables& Liveness,
+ DeadSymbolsTy& DeadSymbols);
- ValueState* RemoveSubExprBindings(ValueState* St) {
+ const ValueState* RemoveSubExprBindings(const ValueState* St) {
ValueState NewSt = *St;
NewSt.Env = EnvMgr.RemoveSubExprBindings(NewSt.Env);
- return getPersistentState(NewSt);
+ return getPersistentState(NewSt);
}
// Methods that query & manipulate the Environment.
- RVal GetRVal(ValueState* St, Expr* Ex) {
+ RVal GetRVal(const ValueState* St, Expr* Ex) {
return St->getEnvironment().GetRVal(Ex, BasicVals);
}
- RVal GetBlkExprRVal(ValueState* St, Expr* Ex) {
+ RVal GetBlkExprRVal(const ValueState* St, Expr* Ex) {
return St->getEnvironment().GetBlkExprRVal(Ex, BasicVals);
}
- ValueState* SetRVal(ValueState* St, Expr* Ex, RVal V, bool isBlkExpr,
- bool Invalidate) {
+ const ValueState* SetRVal(const ValueState* St, Expr* Ex, RVal V,
+ bool isBlkExpr, bool Invalidate) {
const Environment& OldEnv = St->getEnvironment();
Environment NewEnv = EnvMgr.SetRVal(OldEnv, Ex, V, isBlkExpr, Invalidate);
@@ -262,18 +270,29 @@ public:
// Methods that query & manipulate the Store.
- RVal GetRVal(ValueState* St, LVal LV, QualType T = QualType());
+ RVal GetRVal(const ValueState* St, LVal LV, QualType T = QualType()) {
+ return StMgr->GetRVal(St->getStore(), LV, T);
+ }
- ValueState* SetRVal(ValueState* St, LVal LV, RVal V);
+ void SetRVal(ValueState& St, LVal LV, RVal V) {
+ St.St = StMgr->SetRVal(St.St, LV, V);
+ }
+
+ const ValueState* SetRVal(const ValueState* St, LVal LV, RVal V);
- void BindVar(ValueState& StImpl, VarDecl* D, RVal V);
+ void Unbind(ValueState& St, LVal LV) {
+ St.St = StMgr->Remove(St.St, LV);
+ }
- void Unbind(ValueState& StImpl, LVal LV);
+ const ValueState* Unbind(const ValueState* St, LVal LV);
- ValueState* getPersistentState(ValueState& Impl);
+ const ValueState* getPersistentState(ValueState& Impl);
- ValueState* AddEQ(ValueState* St, SymbolID sym, const llvm::APSInt& V);
- ValueState* AddNE(ValueState* St, SymbolID sym, const llvm::APSInt& V);
+ const ValueState* AddEQ(const ValueState* St, SymbolID sym,
+ const llvm::APSInt& V);
+
+ const ValueState* AddNE(const ValueState* St, SymbolID sym,
+ const llvm::APSInt& V);
};
} // end clang namespace
diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp
index 1667a21494..4475ed2bc5 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.cpp
+++ b/lib/Analysis/BasicObjCFoundationChecks.cpp
@@ -107,7 +107,7 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
typedef std::vector<BugReport*> ErrorsTy;
ErrorsTy Errors;
- RVal GetRVal(ValueState* St, Expr* E) { return VMgr->GetRVal(St, E); }
+ RVal GetRVal(const ValueState* St, Expr* E) { return VMgr->GetRVal(St, E); }
bool isNSString(ObjCInterfaceType* T, const char* suffix);
bool AuditNSString(NodeTy* N, ObjCMessageExpr* ME);
@@ -338,8 +338,8 @@ class VISIBILITY_HIDDEN AuditCFNumberCreate : public GRSimpleAPICheck {
IdentifierInfo* II;
ValueStateManager* VMgr;
- RVal GetRVal(ValueState* St, Expr* E) { return VMgr->GetRVal(St, E); }
- RVal GetRVal(ValueState* St, LVal LV) { return VMgr->GetRVal(St, LV); }
+ RVal GetRVal(const ValueState* St, Expr* E) { retu