aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-02-13 00:24:44 +0000
committerTed Kremenek <kremenek@apple.com>2008-02-13 00:24:44 +0000
commit754607e7cff2d902d9af8b771409449fb2f8d2bf (patch)
tree27781f2df71500bec9e06f5a10067e975babb71f /include/clang
parentf81086940024c8fd1c6497800386e88fd313a3d3 (diff)
Added support to GREngine/GRConstants for handling computed gotos.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47038 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/Analysis/PathSensitive/ExplodedGraph.h3
-rw-r--r--include/clang/Analysis/PathSensitive/GREngine.h90
-rw-r--r--include/clang/Analysis/ProgramPoint.h9
3 files changed, 101 insertions, 1 deletions
diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Analysis/PathSensitive/ExplodedGraph.h
index dcc833c0df..7b52003c6b 100644
--- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h
+++ b/include/clang/Analysis/PathSensitive/ExplodedGraph.h
@@ -30,6 +30,7 @@ class GREngineImpl;
class ExplodedNodeImpl;
class GRStmtNodeBuilderImpl;
class GRBranchNodeBuilderImpl;
+class GRIndirectGotoNodeBuilderImpl;
class CFG;
class ASTContext;
class FunctionDecl;
@@ -41,6 +42,7 @@ protected:
friend class GREngineImpl;
friend class GRStmtNodeBuilderImpl;
friend class GRBranchNodeBuilderImpl;
+ friend class GRIndirectGotoNodeBuilderImpl;
class NodeGroup {
enum { Size1 = 0x0, SizeOther = 0x1, AuxFlag = 0x2, Mask = 0x3 };
@@ -195,6 +197,7 @@ protected:
friend class GREngineImpl;
friend class GRStmtNodeBuilderImpl;
friend class GRBranchNodeBuilderImpl;
+ friend class GRIndirectGotoNodeBuilderImpl;
// Type definitions.
typedef llvm::DenseMap<ProgramPoint,void*> EdgeNodeSetMap;
diff --git a/include/clang/Analysis/PathSensitive/GREngine.h b/include/clang/Analysis/PathSensitive/GREngine.h
index 14ca1842da..4e1f2095cb 100644
--- a/include/clang/Analysis/PathSensitive/GREngine.h
+++ b/include/clang/Analysis/PathSensitive/GREngine.h
@@ -24,12 +24,15 @@ namespace clang {
class GRStmtNodeBuilderImpl;
class GRBranchNodeBuilderImpl;
+class GRIndirectGotoNodeBuilderImpl;
class GRWorkList;
+class LabelStmt;
class GREngineImpl {
protected:
friend class GRStmtNodeBuilderImpl;
friend class GRBranchNodeBuilderImpl;
+ friend class GRIndirectGotoNodeBuilderImpl;
typedef llvm::DenseMap<Stmt*,Stmt*> ParentMapTy;
@@ -78,6 +81,7 @@ protected:
virtual void ProcessBranch(Expr* Condition, Stmt* Terminator,
GRBranchNodeBuilderImpl& Builder) = 0;
+ virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& Builder) = 0;
private:
GREngineImpl(const GREngineImpl&); // Do not implement.
@@ -246,6 +250,87 @@ public:
}
};
+class GRIndirectGotoNodeBuilderImpl {
+ GREngineImpl& Eng;
+ CFGBlock* Src;
+ CFGBlock& DispatchBlock;
+ Expr* E;
+ ExplodedNodeImpl* Pred;
+public:
+ GRIndirectGotoNodeBuilderImpl(ExplodedNodeImpl* pred, CFGBlock* src,
+ Expr* e, CFGBlock* dispatch,
+ GREngineImpl* eng)
+ : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
+
+ class Iterator;
+
+ class Destination {
+ LabelStmt* L;
+ CFGBlock* B;
+
+ friend class Iterator;
+ Destination(LabelStmt* l, CFGBlock* b) : L(l), B(b) {}
+
+ public:
+ CFGBlock* getBlock() const { return B; }
+ LabelStmt* getLabel() const { return L; }
+ };
+
+ class Iterator {
+ CFGBlock::succ_iterator I;
+
+ friend class GRIndirectGotoNodeBuilderImpl;
+ Iterator(CFGBlock::succ_iterator i) : I(i) {}
+ public:
+
+ Iterator& operator++() { ++I; return *this; }
+ bool operator!=(const Iterator& X) const { return I != X.I; }
+
+ Destination operator*();
+ };
+
+ Iterator begin();
+ Iterator end();
+
+ ExplodedNodeImpl* generateNodeImpl(const Destination& D, void* State,
+ bool isSink);
+
+ inline Expr* getTarget() const { return E; }
+ inline void* getState() const { return Pred->State; }
+};
+
+template<typename CHECKER>
+class GRIndirectGotoNodeBuilder {
+ typedef CHECKER CheckerTy;
+ typedef typename CheckerTy::StateTy StateTy;
+ typedef ExplodedGraph<CheckerTy> GraphTy;
+ typedef typename GraphTy::NodeTy NodeTy;
+
+ GRIndirectGotoNodeBuilderImpl& NB;
+
+public:
+ GRIndirectGotoNodeBuilder(GRIndirectGotoNodeBuilderImpl& nb) : NB(nb) {}
+
+ typedef GRIndirectGotoNodeBuilderImpl::Iterator iterator;
+ typedef GRIndirectGotoNodeBuilderImpl::Destination Destination;
+
+ inline iterator begin() { return NB.begin(); }
+ inline iterator end() { return NB.end(); }
+
+ inline Expr* getTarget() const { return NB.getTarget(); }
+
+ inline NodeTy* generateNode(const Destination& D, StateTy St,
+ bool isSink = false) {
+
+ void *state = GRTrait<StateTy>::toPtr(St);
+ return static_cast<NodeTy*>(NB.generateNodeImpl(D, state, isSink));
+ }
+
+ inline StateTy getState() const {
+ return GRTrait<StateTy>::toState(NB.getState());
+ }
+};
+
template<typename CHECKER>
class GREngine : public GREngineImpl {
@@ -274,13 +359,16 @@ protected:
Checker->ProcessStmt(S, Builder);
}
-
virtual void ProcessBranch(Expr* Condition, Stmt* Terminator,
GRBranchNodeBuilderImpl& BuilderImpl) {
GRBranchNodeBuilder<CHECKER> Builder(BuilderImpl);
Checker->ProcessBranch(Condition, Terminator, Builder);
}
+ virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilderImpl& BuilderImpl) {
+ GRIndirectGotoNodeBuilder<CHECKER> Builder(BuilderImpl);
+ Checker->ProcessIndirectGoto(Builder);
+ }
public:
/// Construct a GREngine object to analyze the provided CFG using
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 39ce03fd96..45ec936e9a 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -104,6 +104,15 @@ class BlockEdge : public ProgramPoint {
typedef std::pair<CFGBlock*,CFGBlock*> BPair;
public:
BlockEdge(CFG& cfg, const CFGBlock* B1, const CFGBlock* B2);
+
+ /// This ctor forces the BlockEdge to be constructed using an explicitly
+ /// allocated pair object that is stored in the CFG. This is usually
+ /// used to construct edges representing jumps using computed gotos.
+ BlockEdge(CFG& cfg, const CFGBlock* B1, const CFGBlock* B2, bool) {
+ Data = reinterpret_cast<uintptr_t>(cfg.getBlockEdgeImpl(B1, B2))
+ | BlockEdgeAuxKind;
+ }
+
CFGBlock* getSrc() const;
CFGBlock* getDst() const;