clang API Documentation

AnalysisContext.h
Go to the documentation of this file.
00001 //=== AnalysisContext.h - Analysis context for Path Sens analysis --*- C++ -*-//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines AnalysisDeclContext, a class that manages the analysis
00011 // context data for path sensitive analysis.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
00016 #define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
00017 
00018 #include "clang/AST/Decl.h"
00019 #include "clang/AST/Expr.h"
00020 #include "clang/Analysis/CFG.h"
00021 #include "llvm/ADT/OwningPtr.h"
00022 #include "llvm/ADT/IntrusiveRefCntPtr.h"
00023 #include "llvm/ADT/FoldingSet.h"
00024 #include "llvm/ADT/PointerUnion.h"
00025 #include "llvm/ADT/DenseMap.h"
00026 #include "llvm/Support/Allocator.h"
00027 
00028 namespace clang {
00029 
00030 class Decl;
00031 class Stmt;
00032 class CFGReverseBlockReachabilityAnalysis;
00033 class CFGStmtMap;
00034 class LiveVariables;
00035 class ManagedAnalysis;
00036 class ParentMap;
00037 class PseudoConstantAnalysis;
00038 class ImplicitParamDecl;
00039 class LocationContextManager;
00040 class StackFrameContext;
00041 class AnalysisDeclContextManager;
00042 class LocationContext;
00043 
00044 namespace idx { class TranslationUnit; }
00045 
00046 /// The base class of a hierarchy of objects representing analyses tied
00047 /// to AnalysisDeclContext.
00048 class ManagedAnalysis {
00049 protected:
00050   ManagedAnalysis() {}
00051 public:
00052   virtual ~ManagedAnalysis();
00053 
00054   // Subclasses need to implement:
00055   //
00056   //  static const void *getTag();
00057   //
00058   // Which returns a fixed pointer address to distinguish classes of
00059   // analysis objects.  They also need to implement:
00060   //
00061   //  static [Derived*] create(AnalysisDeclContext &Ctx);
00062   //
00063   // which creates the analysis object given an AnalysisDeclContext.
00064 };
00065 
00066 
00067 /// AnalysisDeclContext contains the context data for the function or method
00068 /// under analysis.
00069 class AnalysisDeclContext {
00070   /// Backpoint to the AnalysisManager object that created this
00071   /// AnalysisDeclContext. This may be null.
00072   AnalysisDeclContextManager *Manager;
00073 
00074   const Decl *D;
00075 
00076   OwningPtr<CFG> cfg, completeCFG;
00077   OwningPtr<CFGStmtMap> cfgStmtMap;
00078 
00079   CFG::BuildOptions cfgBuildOptions;
00080   CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
00081 
00082   bool builtCFG, builtCompleteCFG;
00083 
00084   OwningPtr<LiveVariables> liveness;
00085   OwningPtr<LiveVariables> relaxedLiveness;
00086   OwningPtr<ParentMap> PM;
00087   OwningPtr<PseudoConstantAnalysis> PCA;
00088   OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA;
00089 
00090   llvm::BumpPtrAllocator A;
00091 
00092   llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
00093 
00094   void *ManagedAnalyses;
00095 
00096 public:
00097   AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
00098                   const Decl *D);
00099 
00100   AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
00101                   const Decl *D,
00102                   const CFG::BuildOptions &BuildOptions);
00103 
00104   ~AnalysisDeclContext();
00105 
00106   ASTContext &getASTContext() { return D->getASTContext(); }
00107   const Decl *getDecl() const { return D; }
00108 
00109   /// Return the build options used to construct the CFG.
00110   CFG::BuildOptions &getCFGBuildOptions() {
00111     return cfgBuildOptions;
00112   }
00113 
00114   const CFG::BuildOptions &getCFGBuildOptions() const {
00115     return cfgBuildOptions;
00116   }
00117 
00118   /// getAddEHEdges - Return true iff we are adding exceptional edges from
00119   /// callExprs.  If this is false, then try/catch statements and blocks
00120   /// reachable from them can appear to be dead in the CFG, analysis passes must
00121   /// cope with that.
00122   bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
00123   bool getUseUnoptimizedCFG() const {
00124       return !cfgBuildOptions.PruneTriviallyFalseEdges;
00125   }
00126   bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
00127   bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
00128 
00129   void registerForcedBlockExpression(const Stmt *stmt);
00130   const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
00131 
00132   Stmt *getBody() const;
00133   CFG *getCFG();
00134 
00135   CFGStmtMap *getCFGStmtMap();
00136 
00137   CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
00138 
00139   /// Return a version of the CFG without any edges pruned.
00140   CFG *getUnoptimizedCFG();
00141 
00142   void dumpCFG(bool ShowColors);
00143 
00144   /// \brief Returns true if we have built a CFG for this analysis context.
00145   /// Note that this doesn't correspond to whether or not a valid CFG exists, it
00146   /// corresponds to whether we *attempted* to build one.
00147   bool isCFGBuilt() const { return builtCFG; }
00148 
00149   ParentMap &getParentMap();
00150   PseudoConstantAnalysis *getPseudoConstantAnalysis();
00151 
00152   typedef const VarDecl * const * referenced_decls_iterator;
00153 
00154   std::pair<referenced_decls_iterator, referenced_decls_iterator>
00155     getReferencedBlockVars(const BlockDecl *BD);
00156 
00157   /// Return the ImplicitParamDecl* associated with 'self' if this
00158   /// AnalysisDeclContext wraps an ObjCMethodDecl.  Returns NULL otherwise.
00159   const ImplicitParamDecl *getSelfDecl() const;
00160 
00161   const StackFrameContext *getStackFrame(LocationContext const *Parent,
00162                                          const Stmt *S,
00163                                          const CFGBlock *Blk,
00164                                          unsigned Idx);
00165 
00166   /// Return the specified analysis object, lazily running the analysis if
00167   /// necessary.  Return NULL if the analysis could not run.
00168   template <typename T>
00169   T *getAnalysis() {
00170     const void *tag = T::getTag();
00171     ManagedAnalysis *&data = getAnalysisImpl(tag);
00172     if (!data) {
00173       data = T::create(*this);
00174     }
00175     return static_cast<T*>(data);
00176   }
00177 private:
00178   ManagedAnalysis *&getAnalysisImpl(const void* tag);
00179 
00180   LocationContextManager &getLocationContextManager();
00181 };
00182 
00183 class LocationContext : public llvm::FoldingSetNode {
00184 public:
00185   enum ContextKind { StackFrame, Scope, Block };
00186 
00187 private:
00188   ContextKind Kind;
00189 
00190   // AnalysisDeclContext can't be const since some methods may modify its
00191   // member.
00192   AnalysisDeclContext *Ctx;
00193 
00194   const LocationContext *Parent;
00195 
00196 protected:
00197   LocationContext(ContextKind k, AnalysisDeclContext *ctx,
00198                   const LocationContext *parent)
00199     : Kind(k), Ctx(ctx), Parent(parent) {}
00200 
00201 public:
00202   virtual ~LocationContext();
00203 
00204   ContextKind getKind() const { return Kind; }
00205 
00206   AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
00207 
00208   const LocationContext *getParent() const { return Parent; }
00209 
00210   bool isParentOf(const LocationContext *LC) const;
00211 
00212   const Decl *getDecl() const { return getAnalysisDeclContext()->getDecl(); }
00213 
00214   CFG *getCFG() const { return getAnalysisDeclContext()->getCFG(); }
00215 
00216   template <typename T>
00217   T *getAnalysis() const {
00218     return getAnalysisDeclContext()->getAnalysis<T>();
00219   }
00220 
00221   ParentMap &getParentMap() const {
00222     return getAnalysisDeclContext()->getParentMap();
00223   }
00224 
00225   const ImplicitParamDecl *getSelfDecl() const {
00226     return Ctx->getSelfDecl();
00227   }
00228 
00229   const StackFrameContext *getCurrentStackFrame() const;
00230   const StackFrameContext *
00231     getStackFrameForDeclContext(const DeclContext *DC) const;
00232 
00233   virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
00234 
00235   static bool classof(const LocationContext*) { return true; }
00236 
00237 public:
00238   static void ProfileCommon(llvm::FoldingSetNodeID &ID,
00239                             ContextKind ck,
00240                             AnalysisDeclContext *ctx,
00241                             const LocationContext *parent,
00242                             const void *data);
00243 };
00244 
00245 class StackFrameContext : public LocationContext {
00246   // The callsite where this stack frame is established.
00247   const Stmt *CallSite;
00248 
00249   // The parent block of the callsite.
00250   const CFGBlock *Block;
00251 
00252   // The index of the callsite in the CFGBlock.
00253   unsigned Index;
00254 
00255   friend class LocationContextManager;
00256   StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
00257                     const Stmt *s, const CFGBlock *blk,
00258                     unsigned idx)
00259     : LocationContext(StackFrame, ctx, parent), CallSite(s),
00260       Block(blk), Index(idx) {}
00261 
00262 public:
00263   ~StackFrameContext() {}
00264 
00265   const Stmt *getCallSite() const { return CallSite; }
00266 
00267   const CFGBlock *getCallSiteBlock() const { return Block; }
00268 
00269   unsigned getIndex() const { return Index; }
00270 
00271   void Profile(llvm::FoldingSetNodeID &ID);
00272 
00273   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
00274                       const LocationContext *parent, const Stmt *s,
00275                       const CFGBlock *blk, unsigned idx) {
00276     ProfileCommon(ID, StackFrame, ctx, parent, s);
00277     ID.AddPointer(blk);
00278     ID.AddInteger(idx);
00279   }
00280 
00281   static bool classof(const LocationContext *Ctx) {
00282     return Ctx->getKind() == StackFrame;
00283   }
00284 };
00285 
00286 class ScopeContext : public LocationContext {
00287   const Stmt *Enter;
00288 
00289   friend class LocationContextManager;
00290   ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent,
00291                const Stmt *s)
00292     : LocationContext(Scope, ctx, parent), Enter(s) {}
00293 
00294 public:
00295   ~ScopeContext() {}
00296 
00297   void Profile(llvm::FoldingSetNodeID &ID);
00298 
00299   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
00300                       const LocationContext *parent, const Stmt *s) {
00301     ProfileCommon(ID, Scope, ctx, parent, s);
00302   }
00303 
00304   static bool classof(const LocationContext *Ctx) {
00305     return Ctx->getKind() == Scope;
00306   }
00307 };
00308 
00309 class BlockInvocationContext : public LocationContext {
00310   // FIXME: Add back context-sensivity (we don't want libAnalysis to know
00311   //  about MemRegion).
00312   const BlockDecl *BD;
00313 
00314   friend class LocationContextManager;
00315 
00316   BlockInvocationContext(AnalysisDeclContext *ctx,
00317                          const LocationContext *parent,
00318                          const BlockDecl *bd)
00319     : LocationContext(Block, ctx, parent), BD(bd) {}
00320 
00321 public:
00322   ~BlockInvocationContext() {}
00323 
00324   const BlockDecl *getBlockDecl() const { return BD; }
00325 
00326   void Profile(llvm::FoldingSetNodeID &ID);
00327 
00328   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
00329                       const LocationContext *parent, const BlockDecl *bd) {
00330     ProfileCommon(ID, Block, ctx, parent, bd);
00331   }
00332 
00333   static bool classof(const LocationContext *Ctx) {
00334     return Ctx->getKind() == Block;
00335   }
00336 };
00337 
00338 class LocationContextManager {
00339   llvm::FoldingSet<LocationContext> Contexts;
00340 public:
00341   ~LocationContextManager();
00342 
00343   const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx,
00344                                          const LocationContext *parent,
00345                                          const Stmt *s,
00346                                          const CFGBlock *blk, unsigned idx);
00347 
00348   const ScopeContext *getScope(AnalysisDeclContext *ctx,
00349                                const LocationContext *parent,
00350                                const Stmt *s);
00351 
00352   /// Discard all previously created LocationContext objects.
00353   void clear();
00354 private:
00355   template <typename LOC, typename DATA>
00356   const LOC *getLocationContext(AnalysisDeclContext *ctx,
00357                                 const LocationContext *parent,
00358                                 const DATA *d);
00359 };
00360 
00361 class AnalysisDeclContextManager {
00362   typedef llvm::DenseMap<const Decl*, AnalysisDeclContext*> ContextMap;
00363 
00364   ContextMap Contexts;
00365   LocationContextManager LocContexts;
00366   CFG::BuildOptions cfgBuildOptions;
00367 
00368 public:
00369   AnalysisDeclContextManager(bool useUnoptimizedCFG = false,
00370                          bool addImplicitDtors = false,
00371                          bool addInitializers = false);
00372 
00373   ~AnalysisDeclContextManager();
00374 
00375   AnalysisDeclContext *getContext(const Decl *D);
00376 
00377   bool getUseUnoptimizedCFG() const {
00378     return !cfgBuildOptions.PruneTriviallyFalseEdges;
00379   }
00380 
00381   CFG::BuildOptions &getCFGBuildOptions() {
00382     return cfgBuildOptions;
00383   }
00384 
00385   const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx,
00386                                          LocationContext const *Parent,
00387                                          const Stmt *S,
00388                                          const CFGBlock *Blk,
00389                                          unsigned Idx) {
00390     return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx);
00391   }
00392 
00393   // Get the top level stack frame.
00394   const StackFrameContext *getStackFrame(const Decl *D) {
00395     return LocContexts.getStackFrame(getContext(D), 0, 0, 0, 0);
00396   }
00397 
00398   // Get a stack frame with parent.
00399   StackFrameContext const *getStackFrame(const Decl *D,
00400                                          LocationContext const *Parent,
00401                                          const Stmt *S,
00402                                          const CFGBlock *Blk,
00403                                          unsigned Idx) {
00404     return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
00405   }
00406 
00407 
00408   /// Discard all previously created AnalysisDeclContexts.
00409   void clear();
00410 
00411 private:
00412   friend class AnalysisDeclContext;
00413 
00414   LocationContextManager &getLocationContextManager() {
00415     return LocContexts;
00416   }
00417 };
00418 
00419 } // end clang namespace
00420 #endif