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/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