| //=== AnalysisContext.h - Analysis context for Path Sens analysis --*- C++ -*-// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines AnalysisContext, a class that manages the analysis context |
| // data for path sensitive analysis. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H |
| #define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H |
| |
| #include "clang/AST/Decl.h" |
| #include "llvm/ADT/OwningPtr.h" |
| #include "llvm/ADT/FoldingSet.h" |
| #include "llvm/ADT/PointerUnion.h" |
| #include "llvm/ADT/DenseMap.h" |
| #include "llvm/Support/Allocator.h" |
| |
| namespace clang { |
| |
| class Decl; |
| class Stmt; |
| class CFG; |
| class CFGBlock; |
| class LiveVariables; |
| class ParentMap; |
| class ImplicitParamDecl; |
| class LocationContextManager; |
| class StackFrameContext; |
| |
| /// AnalysisContext contains the context data for the function or method under |
| /// analysis. |
| class AnalysisContext { |
| const Decl *D; |
| |
| // AnalysisContext owns the following data. |
| CFG *cfg; |
| LiveVariables *liveness; |
| ParentMap *PM; |
| llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; |
| llvm::BumpPtrAllocator A; |
| bool AddEHEdges; |
| public: |
| AnalysisContext(const Decl *d, bool addehedges = false) |
| : D(d), cfg(0), liveness(0), PM(0), ReferencedBlockVars(0), |
| AddEHEdges(addehedges) {} |
| |
| ~AnalysisContext(); |
| |
| ASTContext &getASTContext() { return D->getASTContext(); } |
| const Decl *getDecl() { return D; } |
| /// getAddEHEdges - Return true iff we are adding exceptional edges from |
| /// callExprs. If this is false, then try/catch statements and blocks |
| /// reachable from them can appear to be dead in the CFG, analysis passes must |
| /// cope with that. |
| bool getAddEHEdges() const { return AddEHEdges; } |
| Stmt *getBody(); |
| CFG *getCFG(); |
| ParentMap &getParentMap(); |
| LiveVariables *getLiveVariables(); |
| |
| typedef const VarDecl * const * referenced_decls_iterator; |
| |
| std::pair<referenced_decls_iterator, referenced_decls_iterator> |
| getReferencedBlockVars(const BlockDecl *BD); |
| |
| /// Return the ImplicitParamDecl* associated with 'self' if this |
| /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise. |
| const ImplicitParamDecl *getSelfDecl() const; |
| }; |
| |
| class AnalysisContextManager { |
| typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap; |
| ContextMap Contexts; |
| public: |
| ~AnalysisContextManager(); |
| |
| AnalysisContext *getContext(const Decl *D); |
| |
| // Discard all previously created AnalysisContexts. |
| void clear(); |
| }; |
| |
| class LocationContext : public llvm::FoldingSetNode { |
| public: |
| enum ContextKind { StackFrame, Scope, Block }; |
| |
| private: |
| ContextKind Kind; |
| AnalysisContext *Ctx; |
| const LocationContext *Parent; |
| |
| protected: |
| LocationContext(ContextKind k, AnalysisContext *ctx, |
| const LocationContext *parent) |
| : Kind(k), Ctx(ctx), Parent(parent) {} |
| |
| public: |
| virtual ~LocationContext(); |
| |
| ContextKind getKind() const { return Kind; } |
| |
| AnalysisContext *getAnalysisContext() const { return Ctx; } |
| |
| const LocationContext *getParent() const { return Parent; } |
| |
| bool isParentOf(const LocationContext *LC) const; |
| |
| const Decl *getDecl() const { return getAnalysisContext()->getDecl(); } |
| |
| CFG *getCFG() const { return getAnalysisContext()->getCFG(); } |
| |
| LiveVariables *getLiveVariables() const { |
| return getAnalysisContext()->getLiveVariables(); |
| } |
| |
| ParentMap &getParentMap() const { |
| return getAnalysisContext()->getParentMap(); |
| } |
| |
| const ImplicitParamDecl *getSelfDecl() const { |
| return Ctx->getSelfDecl(); |
| } |
| |
| const StackFrameContext *getCurrentStackFrame() const; |
| const StackFrameContext * |
| getStackFrameForDeclContext(const DeclContext *DC) const; |
| |
| virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; |
| |
| static bool classof(const LocationContext*) { return true; } |
| |
| public: |
| static void ProfileCommon(llvm::FoldingSetNodeID &ID, |
| ContextKind ck, |
| AnalysisContext *ctx, |
| const LocationContext *parent, |
| const void* data); |
| }; |
| |
| class StackFrameContext : public LocationContext { |
| // The callsite where this stack frame is established. |
| const Stmt *CallSite; |
| |
| // The parent block of the callsite. |
| const CFGBlock *Block; |
| |
| // The index of the callsite in the CFGBlock. |
| unsigned Index; |
| |
| friend class LocationContextManager; |
| StackFrameContext(AnalysisContext *ctx, const LocationContext *parent, |
| const Stmt *s, const CFGBlock *blk, unsigned idx) |
| : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk), |
| Index(idx) {} |
| |
| public: |
| ~StackFrameContext() {} |
| |
| const Stmt *getCallSite() const { return CallSite; } |
| |
| const CFGBlock *getCallSiteBlock() const { return Block; } |
| |
| unsigned getIndex() const { return Index; } |
| |
| void Profile(llvm::FoldingSetNodeID &ID); |
| |
| static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, |
| const LocationContext *parent, const Stmt *s, |
| const CFGBlock *blk, unsigned idx) { |
| ProfileCommon(ID, StackFrame, ctx, parent, s); |
| ID.AddPointer(blk); |
| ID.AddInteger(idx); |
| } |
| |
| static bool classof(const LocationContext* Ctx) { |
| return Ctx->getKind() == StackFrame; |
| } |
| }; |
| |
| class ScopeContext : public LocationContext { |
| const Stmt *Enter; |
| |
| friend class LocationContextManager; |
| ScopeContext(AnalysisContext *ctx, const LocationContext *parent, |
| const Stmt *s) |
| : LocationContext(Scope, ctx, parent), Enter(s) {} |
| |
| public: |
| ~ScopeContext() {} |
| |
| void Profile(llvm::FoldingSetNodeID &ID); |
| |
| static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, |
| const LocationContext *parent, const Stmt *s) { |
| ProfileCommon(ID, Scope, ctx, parent, s); |
| } |
| |
| static bool classof(const LocationContext* Ctx) { |
| return Ctx->getKind() == Scope; |
| } |
| }; |
| |
| class BlockInvocationContext : public LocationContext { |
| // FIXME: Add back context-sensivity (we don't want libAnalysis to know |
| // about MemRegion). |
| const BlockDecl *BD; |
| |
| friend class LocationContextManager; |
| |
| BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent, |
| const BlockDecl *bd) |
| : LocationContext(Block, ctx, parent), BD(bd) {} |
| |
| public: |
| ~BlockInvocationContext() {} |
| |
| const BlockDecl *getBlockDecl() const { return BD; } |
| |
| void Profile(llvm::FoldingSetNodeID &ID); |
| |
| static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, |
| const LocationContext *parent, const BlockDecl *bd) { |
| ProfileCommon(ID, Block, ctx, parent, bd); |
| } |
| |
| static bool classof(const LocationContext* Ctx) { |
| return Ctx->getKind() == Block; |
| } |
| }; |
| |
| class LocationContextManager { |
| llvm::FoldingSet<LocationContext> Contexts; |
| public: |
| ~LocationContextManager(); |
| |
| const StackFrameContext *getStackFrame(AnalysisContext *ctx, |
| const LocationContext *parent, |
| const Stmt *s, const CFGBlock *blk, |
| unsigned idx); |
| |
| const ScopeContext *getScope(AnalysisContext *ctx, |
| const LocationContext *parent, |
| const Stmt *s); |
| |
| /// Discard all previously created LocationContext objects. |
| void clear(); |
| private: |
| template <typename LOC, typename DATA> |
| const LOC *getLocationContext(AnalysisContext *ctx, |
| const LocationContext *parent, |
| const DATA *d); |
| }; |
| |
| } // end clang namespace |
| #endif |