summaryrefslogtreecommitdiffstats
path: root/include/clang/Checker
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/Checker')
-rw-r--r--include/clang/Checker/PathSensitive/Checker.h10
-rw-r--r--include/clang/Checker/PathSensitive/GRCoreEngine.h75
-rw-r--r--include/clang/Checker/PathSensitive/GRExprEngine.h8
-rw-r--r--include/clang/Checker/PathSensitive/GRState.h24
-rw-r--r--include/clang/Checker/PathSensitive/GRSubEngine.h8
-rw-r--r--include/clang/Checker/PathSensitive/MemRegion.h15
-rw-r--r--include/clang/Checker/PathSensitive/SymbolManager.h25
-rw-r--r--include/clang/Checker/PathSensitive/ValueManager.h3
8 files changed, 123 insertions, 45 deletions
diff --git a/include/clang/Checker/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h
index d498044..2401a72 100644
--- a/include/clang/Checker/PathSensitive/Checker.h
+++ b/include/clang/Checker/PathSensitive/Checker.h
@@ -147,12 +147,22 @@ public:
void addTransition(const GRState *state) {
assert(state);
+ // If the 'state' is not new, we need to check if the cached state 'ST'
+ // is new.
if (state != getState() || (ST && ST != B.GetState(Pred)))
GenerateNode(state, true);
else
Dst.Add(Pred);
}
+ // Generate a node with a new program point different from the one that will
+ // be created by the GRStmtNodeBuilder.
+ void addTransition(const GRState *state, ProgramPoint Loc) {
+ ExplodedNode *N = B.generateNode(Loc, state, Pred);
+ if (N)
+ addTransition(N);
+ }
+
void EmitReport(BugReport *R) {
Eng.getBugReporter().EmitReport(R);
}
diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h
index 6da4581..c5bf513 100644
--- a/include/clang/Checker/PathSensitive/GRCoreEngine.h
+++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h
@@ -40,6 +40,8 @@ class GRCoreEngine {
friend class GRIndirectGotoNodeBuilder;
friend class GRSwitchNodeBuilder;
friend class GREndPathNodeBuilder;
+ friend class GRCallEnterNodeBuilder;
+ friend class GRCallExitNodeBuilder;
GRSubEngine& SubEngine;
@@ -67,6 +69,9 @@ class GRCoreEngine {
void HandleBranch(Stmt* Cond, Stmt* Term, CFGBlock* B,
ExplodedNode* Pred);
+ void HandleCallEnter(const CallEnter &L, const CFGBlock *Block,
+ unsigned Index, ExplodedNode *Pred);
+ void HandleCallExit(const CallExit &L, ExplodedNode *Pred);
/// Get the initial state from the subengine.
const GRState* getInitialState(const LocationContext *InitLoc) {
@@ -90,6 +95,9 @@ class GRCoreEngine {
void ProcessSwitch(GRSwitchNodeBuilder& Builder);
+ void ProcessCallEnter(GRCallEnterNodeBuilder &Builder);
+ void ProcessCallExit(GRCallExitNodeBuilder &Builder);
+
private:
GRCoreEngine(const GRCoreEngine&); // Do not implement.
GRCoreEngine& operator=(const GRCoreEngine&);
@@ -130,7 +138,6 @@ class GRStmtNodeBuilder {
CFGBlock& B;
const unsigned Idx;
ExplodedNode* Pred;
- ExplodedNode* LastNode;
GRStateManager& Mgr;
GRAuditor* Auditor;
@@ -157,10 +164,6 @@ public:
ExplodedNode* getBasePredecessor() const { return Pred; }
- ExplodedNode* getLastNode() const {
- return LastNode ? (LastNode->isSink() ? NULL : LastNode) : NULL;
- }
-
// FIXME: This should not be exposed.
GRWorkList *getWorkList() { return Eng.WList; }
@@ -194,6 +197,12 @@ public:
return generateNode(S, St, Pred, PointKind);
}
+ ExplodedNode *generateNode(const ProgramPoint &PP, const GRState* State,
+ ExplodedNode* Pred) {
+ HasGeneratedNode = true;
+ return generateNodeInternal(PP, State, Pred);
+ }
+
ExplodedNode*
generateNodeInternal(const ProgramPoint &PP, const GRState* State,
ExplodedNode* Pred);
@@ -431,6 +440,8 @@ public:
ExplodedNode* generateNode(const GRState* State, const void *tag = 0,
ExplodedNode *P = 0);
+ void GenerateCallExitNode(const GRState *state);
+
CFGBlock* getBlock() const { return &B; }
const GRState* getState() const {
@@ -438,6 +449,60 @@ public:
}
};
+class GRCallEnterNodeBuilder {
+ GRCoreEngine &Eng;
+
+ const ExplodedNode *Pred;
+
+ // The call site.
+ const Stmt *CE;
+
+ // The definition of callee.
+ const FunctionDecl *FD;
+
+ // The parent block of the CallExpr.
+ const CFGBlock *Block;
+
+ // The CFGBlock index of the CallExpr.
+ unsigned Index;
+
+public:
+ GRCallEnterNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred,
+ const Stmt *s, const FunctionDecl *fd,
+ const CFGBlock *blk, unsigned idx)
+ : Eng(eng), Pred(pred), CE(s), FD(fd), Block(blk), Index(idx) {}
+
+ const GRState *getState() const { return Pred->getState(); }
+
+ const LocationContext *getLocationContext() const {
+ return Pred->getLocationContext();
+ }
+
+ const Stmt *getCallExpr() const { return CE; }
+
+ const FunctionDecl *getCallee() const { return FD; }
+
+ const CFGBlock *getBlock() const { return Block; }
+
+ unsigned getIndex() const { return Index; }
+
+ void GenerateNode(const GRState *state, const LocationContext *LocCtx);
+};
+
+class GRCallExitNodeBuilder {
+ GRCoreEngine &Eng;
+ const ExplodedNode *Pred;
+
+public:
+ GRCallExitNodeBuilder(GRCoreEngine &eng, const ExplodedNode *pred)
+ : Eng(eng), Pred(pred) {}
+
+ const ExplodedNode *getPredecessor() const { return Pred; }
+
+ const GRState *getState() const { return Pred->getState(); }
+
+ void GenerateNode(const GRState *state);
+};
} // end clang namespace
#endif
diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h
index 90a2cd5..763bbcc 100644
--- a/include/clang/Checker/PathSensitive/GRExprEngine.h
+++ b/include/clang/Checker/PathSensitive/GRExprEngine.h
@@ -171,7 +171,13 @@ public:
/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
void ProcessEndPath(GREndPathNodeBuilder& builder);
-
+
+ // Generate the entry node of the callee.
+ void ProcessCallEnter(GRCallEnterNodeBuilder &builder);
+
+ // Generate the first post callsite node.
+ void ProcessCallExit(GRCallExitNodeBuilder &builder);
+
/// EvalAssume - Callback function invoked by the ConstraintManager when
/// making assumptions about state values.
const GRState *ProcessAssume(const GRState *state, SVal cond, bool assumption);
diff --git a/include/clang/Checker/PathSensitive/GRState.h b/include/clang/Checker/PathSensitive/GRState.h
index 4e44697..9194ee8 100644
--- a/include/clang/Checker/PathSensitive/GRState.h
+++ b/include/clang/Checker/PathSensitive/GRState.h
@@ -16,25 +16,24 @@
// FIXME: Reduce the number of includes.
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Checker/PathSensitive/ConstraintManager.h"
#include "clang/Checker/PathSensitive/Environment.h"
+#include "clang/Checker/PathSensitive/GRCoreEngine.h"
#include "clang/Checker/PathSensitive/Store.h"
-#include "clang/Checker/PathSensitive/ConstraintManager.h"
#include "clang/Checker/PathSensitive/ValueManager.h"
-#include "clang/Checker/PathSensitive/GRCoreEngine.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/Analysis/Analyses/LiveVariables.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/System/DataTypes.h"
#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
-
+#include "llvm/System/DataTypes.h"
#include <functional>
namespace clang {
@@ -77,16 +76,13 @@ public:
typedef llvm::ImmutableMap<void*, void*> GenericDataMap;
private:
- void operator=(const GRState& R) const;
+ void operator=(const GRState& R) const; // Do not implement.
friend class GRStateManager;
GRStateManager *StateMgr;
Environment Env;
Store St;
-
- // FIXME: Make these private.
-public:
GenericDataMap GDM;
public:
diff --git a/include/clang/Checker/PathSensitive/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h
index ce57c2c..f2cd048 100644
--- a/include/clang/Checker/PathSensitive/GRSubEngine.h
+++ b/include/clang/Checker/PathSensitive/GRSubEngine.h
@@ -28,6 +28,8 @@ class GRBranchNodeBuilder;
class GRIndirectGotoNodeBuilder;
class GRSwitchNodeBuilder;
class GREndPathNodeBuilder;
+class GRCallEnterNodeBuilder;
+class GRCallExitNodeBuilder;
class LocationContext;
class GRSubEngine {
@@ -64,6 +66,12 @@ public:
/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
/// nodes when the control reaches the end of a function.
virtual void ProcessEndPath(GREndPathNodeBuilder& builder) = 0;
+
+ // Generate the entry node of the callee.
+ virtual void ProcessCallEnter(GRCallEnterNodeBuilder &builder) = 0;
+
+ // Generate the first post callsite node.
+ virtual void ProcessCallExit(GRCallExitNodeBuilder &builder) = 0;
/// EvalAssume - Called by ConstraintManager. Used to call checker-specific
/// logic for handling assumptions on symbolic values.
diff --git a/include/clang/Checker/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h
index 12bc0b7..be89d2a 100644
--- a/include/clang/Checker/PathSensitive/MemRegion.h
+++ b/include/clang/Checker/PathSensitive/MemRegion.h
@@ -428,7 +428,6 @@ public:
/// which correspond to "code+data". The distinction is important, because
/// like a closure a block captures the values of externally referenced
/// variables.
-/// BlockDataRegion - A region that represents code texts of blocks (closures).
class BlockDataRegion : public SubRegion {
friend class MemRegionManager;
const BlockTextRegion *BC;
@@ -798,11 +797,10 @@ class MemRegionManager {
GlobalsSpaceRegion *globals;
- const StackFrameContext *cachedStackLocalsFrame;
- StackLocalsSpaceRegion *cachedStackLocalsRegion;
-
- const StackFrameContext *cachedStackArgumentsFrame;
- StackArgumentsSpaceRegion *cachedStackArgumentsRegion;
+ llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *>
+ StackLocalsSpaceRegions;
+ llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *>
+ StackArgumentsSpaceRegions;
HeapSpaceRegion *heap;
UnknownSpaceRegion *unknown;
@@ -810,10 +808,7 @@ class MemRegionManager {
public:
MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a)
- : C(c), A(a), globals(0),
- cachedStackLocalsFrame(0), cachedStackLocalsRegion(0),
- cachedStackArgumentsFrame(0), cachedStackArgumentsRegion(0),
- heap(0), unknown(0), code(0) {}
+ : C(c), A(a), globals(0), heap(0), unknown(0), code(0) {}
~MemRegionManager();
diff --git a/include/clang/Checker/PathSensitive/SymbolManager.h b/include/clang/Checker/PathSensitive/SymbolManager.h
index 8eb3196..d49f5e8 100644
--- a/include/clang/Checker/PathSensitive/SymbolManager.h
+++ b/include/clang/Checker/PathSensitive/SymbolManager.h
@@ -89,27 +89,23 @@ public:
typedef const SymbolData* SymbolRef;
+// A symbol representing the value of a MemRegion.
class SymbolRegionValue : public SymbolData {
- const MemRegion *R;
- // We may cast the region to another type, so the expected type of the symbol
- // may be different from the region's original type.
- QualType T;
+ const TypedRegion *R;
public:
- SymbolRegionValue(SymbolID sym, const MemRegion *r, QualType t = QualType())
- : SymbolData(RegionValueKind, sym), R(r), T(t) {}
+ SymbolRegionValue(SymbolID sym, const TypedRegion *r)
+ : SymbolData(RegionValueKind, sym), R(r) {}
- const MemRegion* getRegion() const { return R; }
+ const TypedRegion* getRegion() const { return R; }
- static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion* R,
- QualType T) {
+ static void Profile(llvm::FoldingSetNodeID& profile, const TypedRegion* R) {
profile.AddInteger((unsigned) RegionValueKind);
profile.AddPointer(R);
- T.Profile(profile);
}
virtual void Profile(llvm::FoldingSetNodeID& profile) {
- Profile(profile, R, T);
+ Profile(profile, R);
}
void dumpToStream(llvm::raw_ostream &os) const;
@@ -122,6 +118,7 @@ public:
}
};
+// A symbol representing the result of an expression.
class SymbolConjured : public SymbolData {
const Stmt* S;
QualType T;
@@ -161,6 +158,8 @@ public:
}
};
+// A symbol representing the value of a MemRegion whose parent region has
+// symbolic value.
class SymbolDerived : public SymbolData {
SymbolRef parentSymbol;
const TypedRegion *R;
@@ -294,8 +293,8 @@ public:
static bool canSymbolicate(QualType T);
/// Make a unique symbol for MemRegion R according to its kind.
- const SymbolRegionValue* getRegionValueSymbol(const MemRegion* R,
- QualType T = QualType());
+ const SymbolRegionValue* getRegionValueSymbol(const TypedRegion* R);
+
const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T,
unsigned VisitCount,
const void* SymbolTag = 0);
diff --git a/include/clang/Checker/PathSensitive/ValueManager.h b/include/clang/Checker/PathSensitive/ValueManager.h
index ea3af57..f80ad42 100644
--- a/include/clang/Checker/PathSensitive/ValueManager.h
+++ b/include/clang/Checker/PathSensitive/ValueManager.h
@@ -94,8 +94,7 @@ public:
DefinedOrUnknownSVal makeZeroVal(QualType T);
/// getRegionValueSymbolVal - make a unique symbol for value of R.
- DefinedOrUnknownSVal getRegionValueSymbolVal(const MemRegion *R,
- QualType T = QualType());
+ DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedRegion *R);
DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag,
const Expr *E, unsigned Count);
OpenPOWER on IntegriCloud