clang API Documentation
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