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/FoldingSet.h" 23 #include "llvm/ADT/PointerUnion.h" 24 #include "llvm/ADT/DenseMap.h" 25 #include "llvm/Support/Allocator.h" 26 27 namespace clang { 28 29 class Decl; 30 class Stmt; 31 class CFGReverseBlockReachabilityAnalysis; 32 class CFGStmtMap; 33 class LiveVariables; 34 class ParentMap; 35 class PseudoConstantAnalysis; 36 class ImplicitParamDecl; 37 class LocationContextManager; 38 class StackFrameContext; 39 40 namespace idx { class TranslationUnit; } 41 42 /// AnalysisContext contains the context data for the function or method under 43 /// analysis. 44 class AnalysisContext { 45 const Decl *D; 46 47 // TranslationUnit is NULL if we don't have multiple translation units. 48 idx::TranslationUnit *TU; 49 50 llvm::OwningPtr<CFG> cfg, completeCFG; 51 llvm::OwningPtr<CFGStmtMap> cfgStmtMap; 52 53 CFG::BuildOptions cfgBuildOptions; 54 CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs; 55 56 bool builtCFG, builtCompleteCFG; 57 const bool useUnoptimizedCFG; 58 59 llvm::OwningPtr<LiveVariables> liveness; 60 llvm::OwningPtr<LiveVariables> relaxedLiveness; 61 llvm::OwningPtr<ParentMap> PM; 62 llvm::OwningPtr<PseudoConstantAnalysis> PCA; 63 llvm::OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA; 64 65 llvm::BumpPtrAllocator A; 66 67 // FIXME: remove. 68 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; 69 70 public: 71 AnalysisContext(const Decl *d, idx::TranslationUnit *tu, 72 bool useUnoptimizedCFG = false, 73 bool addehedges = false, 74 bool addImplicitDtors = false, 75 bool addInitializers = false); 76 77 ~AnalysisContext(); 78 79 ASTContext &getASTContext() { return D->getASTContext(); } 80 const Decl *getDecl() const { return D; } 81 82 idx::TranslationUnit *getTranslationUnit() const { return TU; } 83 84 /// Return the build options used to construct the CFG. 85 CFG::BuildOptions &getCFGBuildOptions() { 86 return cfgBuildOptions; 87 } 88 89 const CFG::BuildOptions &getCFGBuildOptions() const { 90 return cfgBuildOptions; 91 } 92 93 /// getAddEHEdges - Return true iff we are adding exceptional edges from 94 /// callExprs. If this is false, then try/catch statements and blocks 95 /// reachable from them can appear to be dead in the CFG, analysis passes must 96 /// cope with that. 97 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; } 98 bool getUseUnoptimizedCFG() const { 99 return cfgBuildOptions.PruneTriviallyFalseEdges; 100 } 101 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; } 102 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; } 103 104 void registerForcedBlockExpression(const Stmt *stmt); 105 const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt); 106 107 Stmt *getBody(); 108 CFG *getCFG(); 109 110 CFGStmtMap *getCFGStmtMap(); 111 112 CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis(); 113 114 /// Return a version of the CFG without any edges pruned. 115 CFG *getUnoptimizedCFG(); 116 117 void dumpCFG(); 118 119 /// \brief Returns true if we have built a CFG for this analysis context. 120 /// Note that this doesn't correspond to whether or not a valid CFG exists, it 121 /// corresponds to whether we *attempted* to build one. 122 bool isCFGBuilt() const { return builtCFG; } 123 124 ParentMap &getParentMap(); 125 PseudoConstantAnalysis *getPseudoConstantAnalysis(); 126 LiveVariables *getLiveVariables(); 127 LiveVariables *getRelaxedLiveVariables(); 128 129 typedef const VarDecl * const * referenced_decls_iterator; 130 131 std::pair<referenced_decls_iterator, referenced_decls_iterator> 132 getReferencedBlockVars(const BlockDecl *BD); 133 134 /// Return the ImplicitParamDecl* associated with 'self' if this 135 /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise. 136 const ImplicitParamDecl *getSelfDecl() const; 137 }; 138 139 class AnalysisContextManager { 140 typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap; 141 ContextMap Contexts; 142 bool UseUnoptimizedCFG; 143 bool AddImplicitDtors; 144 bool AddInitializers; 145 public: 146 AnalysisContextManager(bool useUnoptimizedCFG = false, 147 bool addImplicitDtors = false, bool addInitializers = false) 148 : UseUnoptimizedCFG(useUnoptimizedCFG), AddImplicitDtors(addImplicitDtors), 149 AddInitializers(addInitializers) {} 150 151 ~AnalysisContextManager(); 152 153 AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0); 154 155 bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; } 156 bool getAddImplicitDtors() const { return AddImplicitDtors; } 157 bool getAddInitializers() const { return AddInitializers; } 158 159 // Discard all previously created AnalysisContexts. 160 void clear(); 161 }; 162 163 class LocationContext : public llvm::FoldingSetNode { 164 public: 165 enum ContextKind { StackFrame, Scope, Block }; 166 167 private: 168 ContextKind Kind; 169 170 // AnalysisContext can't be const since some methods may modify its member. 171 AnalysisContext *Ctx; 172 173 const LocationContext *Parent; 174 175 protected: 176 LocationContext(ContextKind k, AnalysisContext *ctx, 177 const LocationContext *parent) 178 : Kind(k), Ctx(ctx), Parent(parent) {} 179 180 public: 181 virtual ~LocationContext(); 182 183 ContextKind getKind() const { return Kind; } 184 185 AnalysisContext *getAnalysisContext() const { return Ctx; } 186 187 idx::TranslationUnit *getTranslationUnit() const { 188 return Ctx->getTranslationUnit(); 189 } 190 191 const LocationContext *getParent() const { return Parent; } 192 193 bool isParentOf(const LocationContext *LC) const; 194 195 const Decl *getDecl() const { return getAnalysisContext()->getDecl(); } 196 197 CFG *getCFG() const { return getAnalysisContext()->getCFG(); } 198 199 LiveVariables *getLiveVariables() const { 200 return getAnalysisContext()->getLiveVariables(); 201 } 202 203 ParentMap &getParentMap() const { 204 return getAnalysisContext()->getParentMap(); 205 } 206 207 const ImplicitParamDecl *getSelfDecl() const { 208 return Ctx->getSelfDecl(); 209 } 210 211 const StackFrameContext *getCurrentStackFrame() const; 212 const StackFrameContext * 213 getStackFrameForDeclContext(const DeclContext *DC) const; 214 215 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; 216 217 static bool classof(const LocationContext*) { return true; } 218 219 public: 220 static void ProfileCommon(llvm::FoldingSetNodeID &ID, 221 ContextKind ck, 222 AnalysisContext *ctx, 223 const LocationContext *parent, 224 const void* data); 225 }; 226 227 class StackFrameContext : public LocationContext { 228 // The callsite where this stack frame is established. 229 const Stmt *CallSite; 230 231 // The parent block of the callsite. 232 const CFGBlock *Block; 233 234 // The index of the callsite in the CFGBlock. 235 unsigned Index; 236 237 friend class LocationContextManager; 238 StackFrameContext(AnalysisContext *ctx, const LocationContext *parent, 239 const Stmt *s, const CFGBlock *blk, 240 unsigned idx) 241 : LocationContext(StackFrame, ctx, parent), CallSite(s), 242 Block(blk), Index(idx) {} 243 244 public: 245 ~StackFrameContext() {} 246 247 const Stmt *getCallSite() const { return CallSite; } 248 249 const CFGBlock *getCallSiteBlock() const { return Block; } 250 251 unsigned getIndex() const { return Index; } 252 253 void Profile(llvm::FoldingSetNodeID &ID); 254 255 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, 256 const LocationContext *parent, const Stmt *s, 257 const CFGBlock *blk, unsigned idx) { 258 ProfileCommon(ID, StackFrame, ctx, parent, s); 259 ID.AddPointer(blk); 260 ID.AddInteger(idx); 261 } 262 263 static bool classof(const LocationContext* Ctx) { 264 return Ctx->getKind() == StackFrame; 265 } 266 }; 267 268 class ScopeContext : public LocationContext { 269 const Stmt *Enter; 270 271 friend class LocationContextManager; 272 ScopeContext(AnalysisContext *ctx, const LocationContext *parent, 273 const Stmt *s) 274 : LocationContext(Scope, ctx, parent), Enter(s) {} 275 276 public: 277 ~ScopeContext() {} 278 279 void Profile(llvm::FoldingSetNodeID &ID); 280 281 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, 282 const LocationContext *parent, const Stmt *s) { 283 ProfileCommon(ID, Scope, ctx, parent, s); 284 } 285 286 static bool classof(const LocationContext* Ctx) { 287 return Ctx->getKind() == Scope; 288 } 289 }; 290 291 class BlockInvocationContext : public LocationContext { 292 // FIXME: Add back context-sensivity (we don't want libAnalysis to know 293 // about MemRegion). 294 const BlockDecl *BD; 295 296 friend class LocationContextManager; 297 298 BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent, 299 const BlockDecl *bd) 300 : LocationContext(Block, ctx, parent), BD(bd) {} 301 302 public: 303 ~BlockInvocationContext() {} 304 305 const BlockDecl *getBlockDecl() const { return BD; } 306 307 void Profile(llvm::FoldingSetNodeID &ID); 308 309 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, 310 const LocationContext *parent, const BlockDecl *bd) { 311 ProfileCommon(ID, Block, ctx, parent, bd); 312 } 313 314 static bool classof(const LocationContext* Ctx) { 315 return Ctx->getKind() == Block; 316 } 317 }; 318 319 class LocationContextManager { 320 llvm::FoldingSet<LocationContext> Contexts; 321 public: 322 ~LocationContextManager(); 323 324 const StackFrameContext *getStackFrame(AnalysisContext *ctx, 325 const LocationContext *parent, 326 const Stmt *s, 327 const CFGBlock *blk, unsigned idx); 328 329 const ScopeContext *getScope(AnalysisContext *ctx, 330 const LocationContext *parent, 331 const Stmt *s); 332 333 /// Discard all previously created LocationContext objects. 334 void clear(); 335 private: 336 template <typename LOC, typename DATA> 337 const LOC *getLocationContext(AnalysisContext *ctx, 338 const LocationContext *parent, 339 const DATA *d); 340 }; 341 342 } // end clang namespace 343 #endif 344