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/Analysis/CFG.h"
00020 #include "clang/Analysis/CodeInjector.h"
00021 #include "llvm/ADT/DenseMap.h"
00022 #include "llvm/ADT/FoldingSet.h"
00023 #include "llvm/Support/Allocator.h"
00024 #include <memory>
00025 
00026 namespace clang {
00027 
00028 class Stmt;
00029 class CFGReverseBlockReachabilityAnalysis;
00030 class CFGStmtMap;
00031 class LiveVariables;
00032 class ManagedAnalysis;
00033 class ParentMap;
00034 class PseudoConstantAnalysis;
00035 class LocationContextManager;
00036 class StackFrameContext;
00037 class BlockInvocationContext;
00038 class AnalysisDeclContextManager;
00039 class LocationContext;
00040 
00041 namespace idx { class TranslationUnit; }
00042 
00043 /// The base class of a hierarchy of objects representing analyses tied
00044 /// to AnalysisDeclContext.
00045 class ManagedAnalysis {
00046 protected:
00047   ManagedAnalysis() {}
00048 public:
00049   virtual ~ManagedAnalysis();
00050 
00051   // Subclasses need to implement:
00052   //
00053   //  static const void *getTag();
00054   //
00055   // Which returns a fixed pointer address to distinguish classes of
00056   // analysis objects.  They also need to implement:
00057   //
00058   //  static [Derived*] create(AnalysisDeclContext &Ctx);
00059   //
00060   // which creates the analysis object given an AnalysisDeclContext.
00061 };
00062 
00063 
00064 /// AnalysisDeclContext contains the context data for the function or method
00065 /// under analysis.
00066 class AnalysisDeclContext {
00067   /// Backpoint to the AnalysisManager object that created this
00068   /// AnalysisDeclContext. This may be null.
00069   AnalysisDeclContextManager *Manager;
00070 
00071   const Decl * const D;
00072 
00073   std::unique_ptr<CFG> cfg, completeCFG;
00074   std::unique_ptr<CFGStmtMap> cfgStmtMap;
00075 
00076   CFG::BuildOptions cfgBuildOptions;
00077   CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
00078 
00079   bool builtCFG, builtCompleteCFG;
00080   std::unique_ptr<ParentMap> PM;
00081   std::unique_ptr<PseudoConstantAnalysis> PCA;
00082   std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
00083 
00084   llvm::BumpPtrAllocator A;
00085 
00086   llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
00087 
00088   void *ManagedAnalyses;
00089 
00090 public:
00091   AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
00092                   const Decl *D);
00093 
00094   AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
00095                   const Decl *D,
00096                   const CFG::BuildOptions &BuildOptions);
00097 
00098   ~AnalysisDeclContext();
00099 
00100   ASTContext &getASTContext() const { return D->getASTContext(); }
00101   const Decl *getDecl() const { return D; }
00102 
00103   /// Return the AnalysisDeclContextManager (if any) that created
00104   /// this AnalysisDeclContext.
00105   AnalysisDeclContextManager *getManager() const {
00106     return Manager;
00107   }
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   /// \brief Get the body of the Declaration.
00133   Stmt *getBody() const;
00134 
00135   /// \brief Get the body of the Declaration.
00136   /// \param[out] IsAutosynthesized Specifies if the body is auto-generated
00137   ///             by the BodyFarm.
00138   Stmt *getBody(bool &IsAutosynthesized) const;
00139 
00140   /// \brief Checks if the body of the Decl is generated by the BodyFarm.
00141   ///
00142   /// Note, the lookup is not free. We are going to call getBody behind
00143   /// the scenes.
00144   /// \sa getBody
00145   bool isBodyAutosynthesized() const;
00146 
00147   /// \brief Checks if the body of the Decl is generated by the BodyFarm from a
00148   /// model file.
00149   ///
00150   /// Note, the lookup is not free. We are going to call getBody behind
00151   /// the scenes.
00152   /// \sa getBody
00153   bool isBodyAutosynthesizedFromModelFile() const;
00154 
00155   CFG *getCFG();
00156 
00157   CFGStmtMap *getCFGStmtMap();
00158 
00159   CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
00160 
00161   /// Return a version of the CFG without any edges pruned.
00162   CFG *getUnoptimizedCFG();
00163 
00164   void dumpCFG(bool ShowColors);
00165 
00166   /// \brief Returns true if we have built a CFG for this analysis context.
00167   /// Note that this doesn't correspond to whether or not a valid CFG exists, it
00168   /// corresponds to whether we *attempted* to build one.
00169   bool isCFGBuilt() const { return builtCFG; }
00170 
00171   ParentMap &getParentMap();
00172   PseudoConstantAnalysis *getPseudoConstantAnalysis();
00173 
00174   typedef const VarDecl * const * referenced_decls_iterator;
00175 
00176   std::pair<referenced_decls_iterator, referenced_decls_iterator>
00177     getReferencedBlockVars(const BlockDecl *BD);
00178 
00179   /// Return the ImplicitParamDecl* associated with 'self' if this
00180   /// AnalysisDeclContext wraps an ObjCMethodDecl.  Returns NULL otherwise.
00181   const ImplicitParamDecl *getSelfDecl() const;
00182 
00183   const StackFrameContext *getStackFrame(LocationContext const *Parent,
00184                                          const Stmt *S,
00185                                          const CFGBlock *Blk,
00186                                          unsigned Idx);
00187   
00188   const BlockInvocationContext *
00189   getBlockInvocationContext(const LocationContext *parent,
00190                             const BlockDecl *BD,
00191                             const void *ContextData);
00192 
00193   /// Return the specified analysis object, lazily running the analysis if
00194   /// necessary.  Return NULL if the analysis could not run.
00195   template <typename T>
00196   T *getAnalysis() {
00197     const void *tag = T::getTag();
00198     ManagedAnalysis *&data = getAnalysisImpl(tag);
00199     if (!data) {
00200       data = T::create(*this);
00201     }
00202     return static_cast<T*>(data);
00203   }
00204 private:
00205   ManagedAnalysis *&getAnalysisImpl(const void* tag);
00206 
00207   LocationContextManager &getLocationContextManager();
00208 };
00209 
00210 class LocationContext : public llvm::FoldingSetNode {
00211 public:
00212   enum ContextKind { StackFrame, Scope, Block };
00213 
00214 private:
00215   ContextKind Kind;
00216 
00217   // AnalysisDeclContext can't be const since some methods may modify its
00218   // member.
00219   AnalysisDeclContext *Ctx;
00220 
00221   const LocationContext *Parent;
00222 
00223 protected:
00224   LocationContext(ContextKind k, AnalysisDeclContext *ctx,
00225                   const LocationContext *parent)
00226     : Kind(k), Ctx(ctx), Parent(parent) {}
00227 
00228 public:
00229   virtual ~LocationContext();
00230 
00231   ContextKind getKind() const { return Kind; }
00232 
00233   AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
00234 
00235   const LocationContext *getParent() const { return Parent; }
00236 
00237   bool isParentOf(const LocationContext *LC) const;
00238 
00239   const Decl *getDecl() const { return getAnalysisDeclContext()->getDecl(); }
00240 
00241   CFG *getCFG() const { return getAnalysisDeclContext()->getCFG(); }
00242 
00243   template <typename T>
00244   T *getAnalysis() const {
00245     return getAnalysisDeclContext()->getAnalysis<T>();
00246   }
00247 
00248   ParentMap &getParentMap() const {
00249     return getAnalysisDeclContext()->getParentMap();
00250   }
00251 
00252   const ImplicitParamDecl *getSelfDecl() const {
00253     return Ctx->getSelfDecl();
00254   }
00255 
00256   const StackFrameContext *getCurrentStackFrame() const;
00257 
00258   /// Return true if the current LocationContext has no caller context.
00259   virtual bool inTopFrame() const;
00260 
00261   virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
00262 
00263   void dumpStack(raw_ostream &OS, StringRef Indent = "") const;
00264   void dumpStack() const;
00265 
00266 public:
00267   static void ProfileCommon(llvm::FoldingSetNodeID &ID,
00268                             ContextKind ck,
00269                             AnalysisDeclContext *ctx,
00270                             const LocationContext *parent,
00271                             const void *data);
00272 };
00273 
00274 class StackFrameContext : public LocationContext {
00275   // The callsite where this stack frame is established.
00276   const Stmt *CallSite;
00277 
00278   // The parent block of the callsite.
00279   const CFGBlock *Block;
00280 
00281   // The index of the callsite in the CFGBlock.
00282   unsigned Index;
00283 
00284   friend class LocationContextManager;
00285   StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
00286                     const Stmt *s, const CFGBlock *blk,
00287                     unsigned idx)
00288     : LocationContext(StackFrame, ctx, parent), CallSite(s),
00289       Block(blk), Index(idx) {}
00290 
00291 public:
00292   ~StackFrameContext() {}
00293 
00294   const Stmt *getCallSite() const { return CallSite; }
00295 
00296   const CFGBlock *getCallSiteBlock() const { return Block; }
00297 
00298   /// Return true if the current LocationContext has no caller context.
00299   bool inTopFrame() const override { return getParent() == nullptr;  }
00300 
00301   unsigned getIndex() const { return Index; }
00302 
00303   void Profile(llvm::FoldingSetNodeID &ID) override;
00304 
00305   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
00306                       const LocationContext *parent, const Stmt *s,
00307                       const CFGBlock *blk, unsigned idx) {
00308     ProfileCommon(ID, StackFrame, ctx, parent, s);
00309     ID.AddPointer(blk);
00310     ID.AddInteger(idx);
00311   }
00312 
00313   static bool classof(const LocationContext *Ctx) {
00314     return Ctx->getKind() == StackFrame;
00315   }
00316 };
00317 
00318 class ScopeContext : public LocationContext {
00319   const Stmt *Enter;
00320 
00321   friend class LocationContextManager;
00322   ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent,
00323                const Stmt *s)
00324     : LocationContext(Scope, ctx, parent), Enter(s) {}
00325 
00326 public:
00327   ~ScopeContext() {}
00328 
00329   void Profile(llvm::FoldingSetNodeID &ID) override;
00330 
00331   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
00332                       const LocationContext *parent, const Stmt *s) {
00333     ProfileCommon(ID, Scope, ctx, parent, s);
00334   }
00335 
00336   static bool classof(const LocationContext *Ctx) {
00337     return Ctx->getKind() == Scope;
00338   }
00339 };
00340 
00341 class BlockInvocationContext : public LocationContext {
00342   const BlockDecl *BD;
00343   
00344   // FIXME: Come up with a more type-safe way to model context-sensitivity.
00345   const void *ContextData;
00346 
00347   friend class LocationContextManager;
00348 
00349   BlockInvocationContext(AnalysisDeclContext *ctx,
00350                          const LocationContext *parent,
00351                          const BlockDecl *bd, const void *contextData)
00352     : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
00353 
00354 public:
00355   ~BlockInvocationContext() {}
00356 
00357   const BlockDecl *getBlockDecl() const { return BD; }
00358   
00359   const void *getContextData() const { return ContextData; }
00360 
00361   void Profile(llvm::FoldingSetNodeID &ID) override;
00362 
00363   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
00364                       const LocationContext *parent, const BlockDecl *bd,
00365                       const void *contextData) {
00366     ProfileCommon(ID, Block, ctx, parent, bd);
00367     ID.AddPointer(contextData);
00368   }
00369 
00370   static bool classof(const LocationContext *Ctx) {
00371     return Ctx->getKind() == Block;
00372   }
00373 };
00374 
00375 class LocationContextManager {
00376   llvm::FoldingSet<LocationContext> Contexts;
00377 public:
00378   ~LocationContextManager();
00379 
00380   const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx,
00381                                          const LocationContext *parent,
00382                                          const Stmt *s,
00383                                          const CFGBlock *blk, unsigned idx);
00384 
00385   const ScopeContext *getScope(AnalysisDeclContext *ctx,
00386                                const LocationContext *parent,
00387                                const Stmt *s);
00388   
00389   const BlockInvocationContext *
00390   getBlockInvocationContext(AnalysisDeclContext *ctx,
00391                             const LocationContext *parent,
00392                             const BlockDecl *BD,
00393                             const void *ContextData);
00394 
00395   /// Discard all previously created LocationContext objects.
00396   void clear();
00397 private:
00398   template <typename LOC, typename DATA>
00399   const LOC *getLocationContext(AnalysisDeclContext *ctx,
00400                                 const LocationContext *parent,
00401                                 const DATA *d);
00402 };
00403 
00404 class AnalysisDeclContextManager {
00405   typedef llvm::DenseMap<const Decl*, AnalysisDeclContext*> ContextMap;
00406 
00407   ContextMap Contexts;
00408   LocationContextManager LocContexts;
00409   CFG::BuildOptions cfgBuildOptions;
00410 
00411   /// Pointer to an interface that can provide function bodies for
00412   /// declarations from external source.
00413   std::unique_ptr<CodeInjector> Injector;
00414   
00415   /// Flag to indicate whether or not bodies should be synthesized
00416   /// for well-known functions.
00417   bool SynthesizeBodies;
00418 
00419 public:
00420   AnalysisDeclContextManager(bool useUnoptimizedCFG = false,
00421                              bool addImplicitDtors = false,
00422                              bool addInitializers = false,
00423                              bool addTemporaryDtors = false,
00424                              bool synthesizeBodies = false,
00425                              bool addStaticInitBranches = false,
00426                              bool addCXXNewAllocator = true,
00427                              CodeInjector* injector = nullptr);
00428 
00429   ~AnalysisDeclContextManager();
00430 
00431   AnalysisDeclContext *getContext(const Decl *D);
00432 
00433   bool getUseUnoptimizedCFG() const {
00434     return !cfgBuildOptions.PruneTriviallyFalseEdges;
00435   }
00436 
00437   CFG::BuildOptions &getCFGBuildOptions() {
00438     return cfgBuildOptions;
00439   }
00440   
00441   /// Return true if faux bodies should be synthesized for well-known
00442   /// functions.
00443   bool synthesizeBodies() const { return SynthesizeBodies; }
00444 
00445   const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx,
00446                                          LocationContext const *Parent,
00447                                          const Stmt *S,
00448                                          const CFGBlock *Blk,
00449                                          unsigned Idx) {
00450     return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx);
00451   }
00452 
00453   // Get the top level stack frame.
00454   const StackFrameContext *getStackFrame(const Decl *D) {
00455     return LocContexts.getStackFrame(getContext(D), nullptr, nullptr, nullptr,
00456                                      0);
00457   }
00458 
00459   // Get a stack frame with parent.
00460   StackFrameContext const *getStackFrame(const Decl *D,
00461                                          LocationContext const *Parent,
00462                                          const Stmt *S,
00463                                          const CFGBlock *Blk,
00464                                          unsigned Idx) {
00465     return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
00466   }
00467 
00468   /// Discard all previously created AnalysisDeclContexts.
00469   void clear();
00470 
00471 private:
00472   friend class AnalysisDeclContext;
00473 
00474   LocationContextManager &getLocationContextManager() {
00475     return LocContexts;
00476   }
00477 };
00478 
00479 } // end clang namespace
00480 #endif