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