diff options
Diffstat (limited to 'include/clang')
-rw-r--r-- | include/clang/Analysis/PathSensitive/ExplodedGraph.h | 3 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/GREngine.h | 90 | ||||
-rw-r--r-- | include/clang/Analysis/ProgramPoint.h | 9 |
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; |