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