AnalysisContext.h revision b1b5daf30d2597e066936772bd206500232d7d65
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 28namespace clang { 29 30class Decl; 31class Stmt; 32class CFGReverseBlockReachabilityAnalysis; 33class CFGStmtMap; 34class LiveVariables; 35class ManagedAnalysis; 36class ParentMap; 37class PseudoConstantAnalysis; 38class ImplicitParamDecl; 39class LocationContextManager; 40class StackFrameContext; 41class AnalysisContextManager; 42class LocationContext; 43 44namespace idx { class TranslationUnit; } 45 46/// The base class of a hierarchy of objects representing analyses tied 47/// to AnalysisContext. 48class ManagedAnalysis { 49protected: 50 ManagedAnalysis() {} 51public: 52 virtual ~ManagedAnalysis(); 53 54 // Subclasses need to implement: 55 // 56 // static const void *getTag(); 57 // 58 // Which returns a fixed pointer address to distinguish classes of 59 // analysis objects. They also need to implement: 60 // 61 // static [Derived*] create(AnalysisContext &Ctx); 62 // 63 // which creates the analysis object given an AnalysisContext. 64}; 65 66 67/// AnalysisContext contains the context data for the function or method under 68/// analysis. 69class AnalysisContext { 70 /// Backpoint to the AnalysisManager object that created this AnalysisContext. 71 /// This may be null. 72 AnalysisContextManager *Manager; 73 74 const Decl *D; 75 76 // TranslationUnit is NULL if we don't have multiple translation units. 77 idx::TranslationUnit *TU; 78 79 llvm::OwningPtr<CFG> cfg, completeCFG; 80 llvm::OwningPtr<CFGStmtMap> cfgStmtMap; 81 82 CFG::BuildOptions cfgBuildOptions; 83 CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs; 84 85 bool builtCFG, builtCompleteCFG; 86 87 llvm::OwningPtr<LiveVariables> liveness; 88 llvm::OwningPtr<LiveVariables> relaxedLiveness; 89 llvm::OwningPtr<ParentMap> PM; 90 llvm::OwningPtr<PseudoConstantAnalysis> PCA; 91 llvm::OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA; 92 93 llvm::BumpPtrAllocator A; 94 95 // FIXME: remove. 96 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; 97 98 void *ManagedAnalyses; 99 100public: 101 AnalysisContext(AnalysisContextManager *Mgr, 102 const Decl *D, 103 idx::TranslationUnit *TU); 104 105 AnalysisContext(AnalysisContextManager *Mgr, 106 const Decl *D, 107 idx::TranslationUnit *TU, 108 const CFG::BuildOptions &BuildOptions); 109 110 ~AnalysisContext(); 111 112 ASTContext &getASTContext() { return D->getASTContext(); } 113 const Decl *getDecl() const { return D; } 114 115 idx::TranslationUnit *getTranslationUnit() const { return TU; } 116 117 /// Return the build options used to construct the CFG. 118 CFG::BuildOptions &getCFGBuildOptions() { 119 return cfgBuildOptions; 120 } 121 122 const CFG::BuildOptions &getCFGBuildOptions() const { 123 return cfgBuildOptions; 124 } 125 126 /// getAddEHEdges - Return true iff we are adding exceptional edges from 127 /// callExprs. If this is false, then try/catch statements and blocks 128 /// reachable from them can appear to be dead in the CFG, analysis passes must 129 /// cope with that. 130 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; } 131 bool getUseUnoptimizedCFG() const { 132 return !cfgBuildOptions.PruneTriviallyFalseEdges; 133 } 134 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; } 135 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; } 136 137 void registerForcedBlockExpression(const Stmt *stmt); 138 const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt); 139 140 Stmt *getBody() const; 141 CFG *getCFG(); 142 143 CFGStmtMap *getCFGStmtMap(); 144 145 CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis(); 146 147 /// Return a version of the CFG without any edges pruned. 148 CFG *getUnoptimizedCFG(); 149 150 void dumpCFG(); 151 152 /// \brief Returns true if we have built a CFG for this analysis context. 153 /// Note that this doesn't correspond to whether or not a valid CFG exists, it 154 /// corresponds to whether we *attempted* to build one. 155 bool isCFGBuilt() const { return builtCFG; } 156 157 ParentMap &getParentMap(); 158 PseudoConstantAnalysis *getPseudoConstantAnalysis(); 159 160 typedef const VarDecl * const * referenced_decls_iterator; 161 162 std::pair<referenced_decls_iterator, referenced_decls_iterator> 163 getReferencedBlockVars(const BlockDecl *BD); 164 165 /// Return the ImplicitParamDecl* associated with 'self' if this 166 /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise. 167 const ImplicitParamDecl *getSelfDecl() const; 168 169 const StackFrameContext *getStackFrame(LocationContext const *Parent, 170 const Stmt *S, 171 const CFGBlock *Blk, 172 unsigned Idx); 173 174 /// Return the specified analysis object, lazily running the analysis if 175 /// necessary. Return NULL if the analysis could not run. 176 template <typename T> 177 T *getAnalysis() { 178 const void *tag = T::getTag(); 179 ManagedAnalysis *&data = getAnalysisImpl(tag); 180 if (!data) { 181 data = T::create(*this); 182 } 183 return static_cast<T*>(data); 184 } 185private: 186 ManagedAnalysis *&getAnalysisImpl(const void* tag); 187 188 LocationContextManager &getLocationContextManager(); 189}; 190 191class LocationContext : public llvm::FoldingSetNode { 192public: 193 enum ContextKind { StackFrame, Scope, Block }; 194 195private: 196 ContextKind Kind; 197 198 // AnalysisContext can't be const since some methods may modify its member. 199 AnalysisContext *Ctx; 200 201 const LocationContext *Parent; 202 203protected: 204 LocationContext(ContextKind k, AnalysisContext *ctx, 205 const LocationContext *parent) 206 : Kind(k), Ctx(ctx), Parent(parent) {} 207 208public: 209 virtual ~LocationContext(); 210 211 ContextKind getKind() const { return Kind; } 212 213 AnalysisContext *getAnalysisContext() const { return Ctx; } 214 215 idx::TranslationUnit *getTranslationUnit() const { 216 return Ctx->getTranslationUnit(); 217 } 218 219 const LocationContext *getParent() const { return Parent; } 220 221 bool isParentOf(const LocationContext *LC) const; 222 223 const Decl *getDecl() const { return getAnalysisContext()->getDecl(); } 224 225 CFG *getCFG() const { return getAnalysisContext()->getCFG(); } 226 227 template <typename T> 228 T *getAnalysis() const { 229 return getAnalysisContext()->getAnalysis<T>(); 230 } 231 232 ParentMap &getParentMap() const { 233 return getAnalysisContext()->getParentMap(); 234 } 235 236 const ImplicitParamDecl *getSelfDecl() const { 237 return Ctx->getSelfDecl(); 238 } 239 240 const StackFrameContext *getCurrentStackFrame() const; 241 const StackFrameContext * 242 getStackFrameForDeclContext(const DeclContext *DC) const; 243 244 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; 245 246 static bool classof(const LocationContext*) { return true; } 247 248public: 249 static void ProfileCommon(llvm::FoldingSetNodeID &ID, 250 ContextKind ck, 251 AnalysisContext *ctx, 252 const LocationContext *parent, 253 const void *data); 254}; 255 256class StackFrameContext : public LocationContext { 257 // The callsite where this stack frame is established. 258 const Stmt *CallSite; 259 260 // The parent block of the callsite. 261 const CFGBlock *Block; 262 263 // The index of the callsite in the CFGBlock. 264 unsigned Index; 265 266 friend class LocationContextManager; 267 StackFrameContext(AnalysisContext *ctx, const LocationContext *parent, 268 const Stmt *s, const CFGBlock *blk, 269 unsigned idx) 270 : LocationContext(StackFrame, ctx, parent), CallSite(s), 271 Block(blk), Index(idx) {} 272 273public: 274 ~StackFrameContext() {} 275 276 const Stmt *getCallSite() const { return CallSite; } 277 278 const CFGBlock *getCallSiteBlock() const { return Block; } 279 280 unsigned getIndex() const { return Index; } 281 282 void Profile(llvm::FoldingSetNodeID &ID); 283 284 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, 285 const LocationContext *parent, const Stmt *s, 286 const CFGBlock *blk, unsigned idx) { 287 ProfileCommon(ID, StackFrame, ctx, parent, s); 288 ID.AddPointer(blk); 289 ID.AddInteger(idx); 290 } 291 292 static bool classof(const LocationContext *Ctx) { 293 return Ctx->getKind() == StackFrame; 294 } 295}; 296 297class ScopeContext : public LocationContext { 298 const Stmt *Enter; 299 300 friend class LocationContextManager; 301 ScopeContext(AnalysisContext *ctx, const LocationContext *parent, 302 const Stmt *s) 303 : LocationContext(Scope, ctx, parent), Enter(s) {} 304 305public: 306 ~ScopeContext() {} 307 308 void Profile(llvm::FoldingSetNodeID &ID); 309 310 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, 311 const LocationContext *parent, const Stmt *s) { 312 ProfileCommon(ID, Scope, ctx, parent, s); 313 } 314 315 static bool classof(const LocationContext *Ctx) { 316 return Ctx->getKind() == Scope; 317 } 318}; 319 320class BlockInvocationContext : public LocationContext { 321 // FIXME: Add back context-sensivity (we don't want libAnalysis to know 322 // about MemRegion). 323 const BlockDecl *BD; 324 325 friend class LocationContextManager; 326 327 BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent, 328 const BlockDecl *bd) 329 : LocationContext(Block, ctx, parent), BD(bd) {} 330 331public: 332 ~BlockInvocationContext() {} 333 334 const BlockDecl *getBlockDecl() const { return BD; } 335 336 void Profile(llvm::FoldingSetNodeID &ID); 337 338 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, 339 const LocationContext *parent, const BlockDecl *bd) { 340 ProfileCommon(ID, Block, ctx, parent, bd); 341 } 342 343 static bool classof(const LocationContext *Ctx) { 344 return Ctx->getKind() == Block; 345 } 346}; 347 348class LocationContextManager { 349 llvm::FoldingSet<LocationContext> Contexts; 350public: 351 ~LocationContextManager(); 352 353 const StackFrameContext *getStackFrame(AnalysisContext *ctx, 354 const LocationContext *parent, 355 const Stmt *s, 356 const CFGBlock *blk, unsigned idx); 357 358 const ScopeContext *getScope(AnalysisContext *ctx, 359 const LocationContext *parent, 360 const Stmt *s); 361 362 /// Discard all previously created LocationContext objects. 363 void clear(); 364private: 365 template <typename LOC, typename DATA> 366 const LOC *getLocationContext(AnalysisContext *ctx, 367 const LocationContext *parent, 368 const DATA *d); 369}; 370 371class AnalysisContextManager { 372 typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap; 373 374 ContextMap Contexts; 375 LocationContextManager LocContexts; 376 CFG::BuildOptions cfgBuildOptions; 377 378public: 379 AnalysisContextManager(bool useUnoptimizedCFG = false, 380 bool addImplicitDtors = false, 381 bool addInitializers = false); 382 383 ~AnalysisContextManager(); 384 385 AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0); 386 387 bool getUseUnoptimizedCFG() const { 388 return !cfgBuildOptions.PruneTriviallyFalseEdges; 389 } 390 391 CFG::BuildOptions &getCFGBuildOptions() { 392 return cfgBuildOptions; 393 } 394 395 const StackFrameContext *getStackFrame(AnalysisContext *Ctx, 396 LocationContext const *Parent, 397 const Stmt *S, 398 const CFGBlock *Blk, 399 unsigned Idx) { 400 return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx); 401 } 402 403 // Get the top level stack frame. 404 const StackFrameContext *getStackFrame(Decl const *D, 405 idx::TranslationUnit *TU) { 406 return LocContexts.getStackFrame(getContext(D, TU), 0, 0, 0, 0); 407 } 408 409 // Get a stack frame with parent. 410 StackFrameContext const *getStackFrame(const Decl *D, 411 LocationContext const *Parent, 412 const Stmt *S, 413 const CFGBlock *Blk, 414 unsigned Idx) { 415 return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx); 416 } 417 418 419 /// Discard all previously created AnalysisContexts. 420 void clear(); 421 422private: 423 friend class AnalysisContext; 424 425 LocationContextManager &getLocationContextManager() { 426 return LocContexts; 427 } 428}; 429 430} // end clang namespace 431#endif 432