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