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