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