Home | History | Annotate | Download | only in Analysis
      1 //=== AnalysisContext.h - Analysis context for Path Sens analysis --*- C++ -*-//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file defines AnalysisContext, a class that manages the analysis context
     11 // data for path sensitive analysis.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
     16 #define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
     17 
     18 #include "clang/AST/Decl.h"
     19 #include "clang/AST/Expr.h"
     20 #include "clang/Analysis/CFG.h"
     21 #include "llvm/ADT/OwningPtr.h"
     22 #include "llvm/ADT/FoldingSet.h"
     23 #include "llvm/ADT/PointerUnion.h"
     24 #include "llvm/ADT/DenseMap.h"
     25 #include "llvm/Support/Allocator.h"
     26 
     27 namespace clang {
     28 
     29 class Decl;
     30 class Stmt;
     31 class CFGReverseBlockReachabilityAnalysis;
     32 class CFGStmtMap;
     33 class LiveVariables;
     34 class ParentMap;
     35 class PseudoConstantAnalysis;
     36 class ImplicitParamDecl;
     37 class LocationContextManager;
     38 class StackFrameContext;
     39 
     40 namespace idx { class TranslationUnit; }
     41 
     42 /// AnalysisContext contains the context data for the function or method under
     43 /// analysis.
     44 class AnalysisContext {
     45   const Decl *D;
     46 
     47   // TranslationUnit is NULL if we don't have multiple translation units.
     48   idx::TranslationUnit *TU;
     49 
     50   llvm::OwningPtr<CFG> cfg, completeCFG;
     51   llvm::OwningPtr<CFGStmtMap> cfgStmtMap;
     52 
     53   CFG::BuildOptions cfgBuildOptions;
     54   CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
     55 
     56   bool builtCFG, builtCompleteCFG;
     57   const bool useUnoptimizedCFG;
     58 
     59   llvm::OwningPtr<LiveVariables> liveness;
     60   llvm::OwningPtr<LiveVariables> relaxedLiveness;
     61   llvm::OwningPtr<ParentMap> PM;
     62   llvm::OwningPtr<PseudoConstantAnalysis> PCA;
     63   llvm::OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA;
     64 
     65   llvm::BumpPtrAllocator A;
     66 
     67   // FIXME: remove.
     68   llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
     69 
     70 public:
     71   AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
     72                   bool useUnoptimizedCFG = false,
     73                   bool addehedges = false,
     74                   bool addImplicitDtors = false,
     75                   bool addInitializers = false);
     76 
     77   ~AnalysisContext();
     78 
     79   ASTContext &getASTContext() { return D->getASTContext(); }
     80   const Decl *getDecl() const { return D; }
     81 
     82   idx::TranslationUnit *getTranslationUnit() const { return TU; }
     83 
     84   /// Return the build options used to construct the CFG.
     85   CFG::BuildOptions &getCFGBuildOptions() {
     86     return cfgBuildOptions;
     87   }
     88 
     89   const CFG::BuildOptions &getCFGBuildOptions() const {
     90     return cfgBuildOptions;
     91   }
     92 
     93   /// getAddEHEdges - Return true iff we are adding exceptional edges from
     94   /// callExprs.  If this is false, then try/catch statements and blocks
     95   /// reachable from them can appear to be dead in the CFG, analysis passes must
     96   /// cope with that.
     97   bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
     98   bool getUseUnoptimizedCFG() const {
     99       return cfgBuildOptions.PruneTriviallyFalseEdges;
    100   }
    101   bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
    102   bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
    103 
    104   void registerForcedBlockExpression(const Stmt *stmt);
    105   const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
    106 
    107   Stmt *getBody();
    108   CFG *getCFG();
    109 
    110   CFGStmtMap *getCFGStmtMap();
    111 
    112   CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
    113 
    114   /// Return a version of the CFG without any edges pruned.
    115   CFG *getUnoptimizedCFG();
    116 
    117   void dumpCFG();
    118 
    119   /// \brief Returns true if we have built a CFG for this analysis context.
    120   /// Note that this doesn't correspond to whether or not a valid CFG exists, it
    121   /// corresponds to whether we *attempted* to build one.
    122   bool isCFGBuilt() const { return builtCFG; }
    123 
    124   ParentMap &getParentMap();
    125   PseudoConstantAnalysis *getPseudoConstantAnalysis();
    126   LiveVariables *getLiveVariables();
    127   LiveVariables *getRelaxedLiveVariables();
    128 
    129   typedef const VarDecl * const * referenced_decls_iterator;
    130 
    131   std::pair<referenced_decls_iterator, referenced_decls_iterator>
    132     getReferencedBlockVars(const BlockDecl *BD);
    133 
    134   /// Return the ImplicitParamDecl* associated with 'self' if this
    135   /// AnalysisContext wraps an ObjCMethodDecl.  Returns NULL otherwise.
    136   const ImplicitParamDecl *getSelfDecl() const;
    137 };
    138 
    139 class AnalysisContextManager {
    140   typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
    141   ContextMap Contexts;
    142   bool UseUnoptimizedCFG;
    143   bool AddImplicitDtors;
    144   bool AddInitializers;
    145 public:
    146   AnalysisContextManager(bool useUnoptimizedCFG = false,
    147       bool addImplicitDtors = false, bool addInitializers = false)
    148     : UseUnoptimizedCFG(useUnoptimizedCFG), AddImplicitDtors(addImplicitDtors),
    149       AddInitializers(addInitializers) {}
    150 
    151   ~AnalysisContextManager();
    152 
    153   AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
    154 
    155   bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
    156   bool getAddImplicitDtors() const { return AddImplicitDtors; }
    157   bool getAddInitializers() const { return AddInitializers; }
    158 
    159   // Discard all previously created AnalysisContexts.
    160   void clear();
    161 };
    162 
    163 class LocationContext : public llvm::FoldingSetNode {
    164 public:
    165   enum ContextKind { StackFrame, Scope, Block };
    166 
    167 private:
    168   ContextKind Kind;
    169 
    170   // AnalysisContext can't be const since some methods may modify its member.
    171   AnalysisContext *Ctx;
    172 
    173   const LocationContext *Parent;
    174 
    175 protected:
    176   LocationContext(ContextKind k, AnalysisContext *ctx,
    177                   const LocationContext *parent)
    178     : Kind(k), Ctx(ctx), Parent(parent) {}
    179 
    180 public:
    181   virtual ~LocationContext();
    182 
    183   ContextKind getKind() const { return Kind; }
    184 
    185   AnalysisContext *getAnalysisContext() const { return Ctx; }
    186 
    187   idx::TranslationUnit *getTranslationUnit() const {
    188     return Ctx->getTranslationUnit();
    189   }
    190 
    191   const LocationContext *getParent() const { return Parent; }
    192 
    193   bool isParentOf(const LocationContext *LC) const;
    194 
    195   const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
    196 
    197   CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
    198 
    199   LiveVariables *getLiveVariables() const {
    200     return getAnalysisContext()->getLiveVariables();
    201   }
    202 
    203   ParentMap &getParentMap() const {
    204     return getAnalysisContext()->getParentMap();
    205   }
    206 
    207   const ImplicitParamDecl *getSelfDecl() const {
    208     return Ctx->getSelfDecl();
    209   }
    210 
    211   const StackFrameContext *getCurrentStackFrame() const;
    212   const StackFrameContext *
    213     getStackFrameForDeclContext(const DeclContext *DC) const;
    214 
    215   virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
    216 
    217   static bool classof(const LocationContext*) { return true; }
    218 
    219 public:
    220   static void ProfileCommon(llvm::FoldingSetNodeID &ID,
    221                             ContextKind ck,
    222                             AnalysisContext *ctx,
    223                             const LocationContext *parent,
    224                             const void* data);
    225 };
    226 
    227 class StackFrameContext : public LocationContext {
    228   // The callsite where this stack frame is established.
    229   const Stmt *CallSite;
    230 
    231   // The parent block of the callsite.
    232   const CFGBlock *Block;
    233 
    234   // The index of the callsite in the CFGBlock.
    235   unsigned Index;
    236 
    237   friend class LocationContextManager;
    238   StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
    239                     const Stmt *s, const CFGBlock *blk,
    240                     unsigned idx)
    241     : LocationContext(StackFrame, ctx, parent), CallSite(s),
    242       Block(blk), Index(idx) {}
    243 
    244 public:
    245   ~StackFrameContext() {}
    246 
    247   const Stmt *getCallSite() const { return CallSite; }
    248 
    249   const CFGBlock *getCallSiteBlock() const { return Block; }
    250 
    251   unsigned getIndex() const { return Index; }
    252 
    253   void Profile(llvm::FoldingSetNodeID &ID);
    254 
    255   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
    256                       const LocationContext *parent, const Stmt *s,
    257                       const CFGBlock *blk, unsigned idx) {
    258     ProfileCommon(ID, StackFrame, ctx, parent, s);
    259     ID.AddPointer(blk);
    260     ID.AddInteger(idx);
    261   }
    262 
    263   static bool classof(const LocationContext* Ctx) {
    264     return Ctx->getKind() == StackFrame;
    265   }
    266 };
    267 
    268 class ScopeContext : public LocationContext {
    269   const Stmt *Enter;
    270 
    271   friend class LocationContextManager;
    272   ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
    273                const Stmt *s)
    274     : LocationContext(Scope, ctx, parent), Enter(s) {}
    275 
    276 public:
    277   ~ScopeContext() {}
    278 
    279   void Profile(llvm::FoldingSetNodeID &ID);
    280 
    281   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
    282                       const LocationContext *parent, const Stmt *s) {
    283     ProfileCommon(ID, Scope, ctx, parent, s);
    284   }
    285 
    286   static bool classof(const LocationContext* Ctx) {
    287     return Ctx->getKind() == Scope;
    288   }
    289 };
    290 
    291 class BlockInvocationContext : public LocationContext {
    292   // FIXME: Add back context-sensivity (we don't want libAnalysis to know
    293   //  about MemRegion).
    294   const BlockDecl *BD;
    295 
    296   friend class LocationContextManager;
    297 
    298   BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
    299                          const BlockDecl *bd)
    300     : LocationContext(Block, ctx, parent), BD(bd) {}
    301 
    302 public:
    303   ~BlockInvocationContext() {}
    304 
    305   const BlockDecl *getBlockDecl() const { return BD; }
    306 
    307   void Profile(llvm::FoldingSetNodeID &ID);
    308 
    309   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
    310                       const LocationContext *parent, const BlockDecl *bd) {
    311     ProfileCommon(ID, Block, ctx, parent, bd);
    312   }
    313 
    314   static bool classof(const LocationContext* Ctx) {
    315     return Ctx->getKind() == Block;
    316   }
    317 };
    318 
    319 class LocationContextManager {
    320   llvm::FoldingSet<LocationContext> Contexts;
    321 public:
    322   ~LocationContextManager();
    323 
    324   const StackFrameContext *getStackFrame(AnalysisContext *ctx,
    325                                          const LocationContext *parent,
    326                                          const Stmt *s,
    327                                          const CFGBlock *blk, unsigned idx);
    328 
    329   const ScopeContext *getScope(AnalysisContext *ctx,
    330                                const LocationContext *parent,
    331                                const Stmt *s);
    332 
    333   /// Discard all previously created LocationContext objects.
    334   void clear();
    335 private:
    336   template <typename LOC, typename DATA>
    337   const LOC *getLocationContext(AnalysisContext *ctx,
    338                                 const LocationContext *parent,
    339                                 const DATA *d);
    340 };
    341 
    342 } // end clang namespace
    343 #endif
    344