aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-02-25 19:01:53 +0000
committerDouglas Gregor <dgregor@apple.com>2010-02-25 19:01:53 +0000
commit102acd5369bbb17c0d6ab868af376671acff7a93 (patch)
tree50efe18ae6593f1cf6a5fb11535183a1b389747c /include/clang
parent9e23932aca7997315a78ea50e9415631a1880fa0 (diff)
Restore Zhongxing's commits r97122 r97127 r97129 r97131 which were reverted due to a Clang-on-Clang failure
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97162 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/Analysis/ProgramPoint.h33
-rw-r--r--include/clang/Checker/PathSensitive/Checker.h8
-rw-r--r--include/clang/Checker/PathSensitive/GRCoreEngine.h70
-rw-r--r--include/clang/Checker/PathSensitive/GRExprEngine.h8
-rw-r--r--include/clang/Checker/PathSensitive/GRSubEngine.h8
5 files changed, 126 insertions, 1 deletions
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 332f9d384f..fb8d4d5ff5 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -26,6 +26,7 @@
namespace clang {
class LocationContext;
+class FunctionDecl;
class ProgramPoint {
public:
@@ -41,6 +42,8 @@ public:
PostPurgeDeadSymbolsKind,
PostStmtCustomKind,
PostLValueKind,
+ CallEnterKind,
+ CallExitKind,
MinPostStmtKind = PostStmtKind,
MaxPostStmtKind = PostLValueKind };
@@ -308,6 +311,36 @@ public:
}
};
+class CallEnter : public StmtPoint {
+public:
+ // CallEnter uses the caller's location context.
+ CallEnter(const Stmt *S, const FunctionDecl *fd, const LocationContext *L)
+ : StmtPoint(S, fd, CallEnterKind, L, 0) {}
+
+ const Stmt *getCallExpr() const {
+ return static_cast<const Stmt *>(getData1());
+ }
+
+ const FunctionDecl *getCallee() const {
+ return static_cast<const FunctionDecl *>(getData2());
+ }
+
+ static bool classof(const ProgramPoint *Location) {
+ return Location->getKind() == CallEnterKind;
+ }
+};
+
+class CallExit : public StmtPoint {
+public:
+ // CallExit uses the callee's location context.
+ CallExit(const Stmt *S, const LocationContext *L)
+ : StmtPoint(S, 0, CallExitKind, L, 0) {}
+
+ static bool classof(const ProgramPoint *Location) {
+ return Location->getKind() == CallExitKind;
+ }
+};
+
} // end namespace clang
diff --git a/include/clang/Checker/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h
index 519c00ec59..2401a72741 100644
--- a/include/clang/Checker/PathSensitive/Checker.h
+++ b/include/clang/Checker/PathSensitive/Checker.h
@@ -155,6 +155,14 @@ public:
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 6da45815f9..dd789cb735 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&);
@@ -194,6 +202,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 +445,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 +454,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 90a2cd5597..763bbcc9e1 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/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h
index ce57c2c68b..f2cd0486e3 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.