1 //=== AnalysisContext.h - Analysis context for Path Sens analysis --*- C++ -*-//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines AnalysisDeclContext, a class that manages the analysis
11 // context data for path sensitive analysis.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
16 #define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
18 #include "clang/AST/Decl.h"
19 #include "clang/Analysis/CFG.h"
20 #include "clang/Analysis/CodeInjector.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/FoldingSet.h"
23 #include "llvm/Support/Allocator.h"
29 class CFGReverseBlockReachabilityAnalysis;
32 class ManagedAnalysis;
34 class PseudoConstantAnalysis;
35 class LocationContextManager;
36 class StackFrameContext;
37 class BlockInvocationContext;
38 class AnalysisDeclContextManager;
39 class LocationContext;
41 namespace idx { class TranslationUnit; }
43 /// The base class of a hierarchy of objects representing analyses tied
44 /// to AnalysisDeclContext.
45 class ManagedAnalysis {
49 virtual ~ManagedAnalysis();
51 // Subclasses need to implement:
53 // static const void *getTag();
55 // Which returns a fixed pointer address to distinguish classes of
56 // analysis objects. They also need to implement:
58 // static [Derived*] create(AnalysisDeclContext &Ctx);
60 // which creates the analysis object given an AnalysisDeclContext.
64 /// AnalysisDeclContext contains the context data for the function or method
66 class AnalysisDeclContext {
67 /// Backpoint to the AnalysisManager object that created this
68 /// AnalysisDeclContext. This may be null.
69 AnalysisDeclContextManager *Manager;
73 std::unique_ptr<CFG> cfg, completeCFG;
74 std::unique_ptr<CFGStmtMap> cfgStmtMap;
76 CFG::BuildOptions cfgBuildOptions;
77 CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
79 bool builtCFG, builtCompleteCFG;
80 std::unique_ptr<ParentMap> PM;
81 std::unique_ptr<PseudoConstantAnalysis> PCA;
82 std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
84 llvm::BumpPtrAllocator A;
86 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
88 void *ManagedAnalyses;
91 AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
94 AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
96 const CFG::BuildOptions &BuildOptions);
98 ~AnalysisDeclContext();
100 ASTContext &getASTContext() const { return D->getASTContext(); }
101 const Decl *getDecl() const { return D; }
103 /// Return the AnalysisDeclContextManager (if any) that created
104 /// this AnalysisDeclContext.
105 AnalysisDeclContextManager *getManager() const {
109 /// Return the build options used to construct the CFG.
110 CFG::BuildOptions &getCFGBuildOptions() {
111 return cfgBuildOptions;
114 const CFG::BuildOptions &getCFGBuildOptions() const {
115 return cfgBuildOptions;
118 /// getAddEHEdges - Return true iff we are adding exceptional edges from
119 /// callExprs. If this is false, then try/catch statements and blocks
120 /// reachable from them can appear to be dead in the CFG, analysis passes must
122 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
123 bool getUseUnoptimizedCFG() const {
124 return !cfgBuildOptions.PruneTriviallyFalseEdges;
126 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
127 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
129 void registerForcedBlockExpression(const Stmt *stmt);
130 const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
132 /// \brief Get the body of the Declaration.
133 Stmt *getBody() const;
135 /// \brief Get the body of the Declaration.
136 /// \param[out] IsAutosynthesized Specifies if the body is auto-generated
138 Stmt *getBody(bool &IsAutosynthesized) const;
140 /// \brief Checks if the body of the Decl is generated by the BodyFarm.
142 /// Note, the lookup is not free. We are going to call getBody behind
145 bool isBodyAutosynthesized() const;
147 /// \brief Checks if the body of the Decl is generated by the BodyFarm from a
150 /// Note, the lookup is not free. We are going to call getBody behind
153 bool isBodyAutosynthesizedFromModelFile() const;
157 CFGStmtMap *getCFGStmtMap();
159 CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
161 /// Return a version of the CFG without any edges pruned.
162 CFG *getUnoptimizedCFG();
164 void dumpCFG(bool ShowColors);
166 /// \brief Returns true if we have built a CFG for this analysis context.
167 /// Note that this doesn't correspond to whether or not a valid CFG exists, it
168 /// corresponds to whether we *attempted* to build one.
169 bool isCFGBuilt() const { return builtCFG; }
171 ParentMap &getParentMap();
172 PseudoConstantAnalysis *getPseudoConstantAnalysis();
174 typedef const VarDecl * const * referenced_decls_iterator;
176 llvm::iterator_range<referenced_decls_iterator>
177 getReferencedBlockVars(const BlockDecl *BD);
179 /// Return the ImplicitParamDecl* associated with 'self' if this
180 /// AnalysisDeclContext wraps an ObjCMethodDecl. Returns NULL otherwise.
181 const ImplicitParamDecl *getSelfDecl() const;
183 const StackFrameContext *getStackFrame(LocationContext const *Parent,
188 const BlockInvocationContext *
189 getBlockInvocationContext(const LocationContext *parent,
191 const void *ContextData);
193 /// Return the specified analysis object, lazily running the analysis if
194 /// necessary. Return NULL if the analysis could not run.
195 template <typename T>
197 const void *tag = T::getTag();
198 ManagedAnalysis *&data = getAnalysisImpl(tag);
200 data = T::create(*this);
202 return static_cast<T*>(data);
205 /// Returns true if the root namespace of the given declaration is the 'std'
207 static bool isInStdNamespace(const Decl *D);
209 ManagedAnalysis *&getAnalysisImpl(const void* tag);
211 LocationContextManager &getLocationContextManager();
214 class LocationContext : public llvm::FoldingSetNode {
216 enum ContextKind { StackFrame, Scope, Block };
221 // AnalysisDeclContext can't be const since some methods may modify its
223 AnalysisDeclContext *Ctx;
225 const LocationContext *Parent;
228 LocationContext(ContextKind k, AnalysisDeclContext *ctx,
229 const LocationContext *parent)
230 : Kind(k), Ctx(ctx), Parent(parent) {}
233 virtual ~LocationContext();
235 ContextKind getKind() const { return Kind; }
237 AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
239 const LocationContext *getParent() const { return Parent; }
241 bool isParentOf(const LocationContext *LC) const;
243 const Decl *getDecl() const { return getAnalysisDeclContext()->getDecl(); }
245 CFG *getCFG() const { return getAnalysisDeclContext()->getCFG(); }
247 template <typename T>
248 T *getAnalysis() const {
249 return getAnalysisDeclContext()->getAnalysis<T>();
252 ParentMap &getParentMap() const {
253 return getAnalysisDeclContext()->getParentMap();
256 const ImplicitParamDecl *getSelfDecl() const {
257 return Ctx->getSelfDecl();
260 const StackFrameContext *getCurrentStackFrame() const;
262 /// Return true if the current LocationContext has no caller context.
263 virtual bool inTopFrame() const;
265 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
267 void dumpStack(raw_ostream &OS, StringRef Indent = "") const;
268 void dumpStack() const;
271 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
273 AnalysisDeclContext *ctx,
274 const LocationContext *parent,
278 class StackFrameContext : public LocationContext {
279 // The callsite where this stack frame is established.
280 const Stmt *CallSite;
282 // The parent block of the callsite.
283 const CFGBlock *Block;
285 // The index of the callsite in the CFGBlock.
288 friend class LocationContextManager;
289 StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
290 const Stmt *s, const CFGBlock *blk,
292 : LocationContext(StackFrame, ctx, parent), CallSite(s),
293 Block(blk), Index(idx) {}
296 ~StackFrameContext() override {}
298 const Stmt *getCallSite() const { return CallSite; }
300 const CFGBlock *getCallSiteBlock() const { return Block; }
302 /// Return true if the current LocationContext has no caller context.
303 bool inTopFrame() const override { return getParent() == nullptr; }
305 unsigned getIndex() const { return Index; }
307 void Profile(llvm::FoldingSetNodeID &ID) override;
309 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
310 const LocationContext *parent, const Stmt *s,
311 const CFGBlock *blk, unsigned idx) {
312 ProfileCommon(ID, StackFrame, ctx, parent, s);
317 static bool classof(const LocationContext *Ctx) {
318 return Ctx->getKind() == StackFrame;
322 class ScopeContext : public LocationContext {
325 friend class LocationContextManager;
326 ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent,
328 : LocationContext(Scope, ctx, parent), Enter(s) {}
331 ~ScopeContext() override {}
333 void Profile(llvm::FoldingSetNodeID &ID) override;
335 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
336 const LocationContext *parent, const Stmt *s) {
337 ProfileCommon(ID, Scope, ctx, parent, s);
340 static bool classof(const LocationContext *Ctx) {
341 return Ctx->getKind() == Scope;
345 class BlockInvocationContext : public LocationContext {
348 // FIXME: Come up with a more type-safe way to model context-sensitivity.
349 const void *ContextData;
351 friend class LocationContextManager;
353 BlockInvocationContext(AnalysisDeclContext *ctx,
354 const LocationContext *parent,
355 const BlockDecl *bd, const void *contextData)
356 : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
359 ~BlockInvocationContext() override {}
361 const BlockDecl *getBlockDecl() const { return BD; }
363 const void *getContextData() const { return ContextData; }
365 void Profile(llvm::FoldingSetNodeID &ID) override;
367 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
368 const LocationContext *parent, const BlockDecl *bd,
369 const void *contextData) {
370 ProfileCommon(ID, Block, ctx, parent, bd);
371 ID.AddPointer(contextData);
374 static bool classof(const LocationContext *Ctx) {
375 return Ctx->getKind() == Block;
379 class LocationContextManager {
380 llvm::FoldingSet<LocationContext> Contexts;
382 ~LocationContextManager();
384 const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx,
385 const LocationContext *parent,
387 const CFGBlock *blk, unsigned idx);
389 const ScopeContext *getScope(AnalysisDeclContext *ctx,
390 const LocationContext *parent,
393 const BlockInvocationContext *
394 getBlockInvocationContext(AnalysisDeclContext *ctx,
395 const LocationContext *parent,
397 const void *ContextData);
399 /// Discard all previously created LocationContext objects.
402 template <typename LOC, typename DATA>
403 const LOC *getLocationContext(AnalysisDeclContext *ctx,
404 const LocationContext *parent,
408 class AnalysisDeclContextManager {
409 typedef llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>
413 LocationContextManager LocContexts;
414 CFG::BuildOptions cfgBuildOptions;
416 /// Pointer to an interface that can provide function bodies for
417 /// declarations from external source.
418 std::unique_ptr<CodeInjector> Injector;
420 /// Flag to indicate whether or not bodies should be synthesized
421 /// for well-known functions.
422 bool SynthesizeBodies;
425 AnalysisDeclContextManager(bool useUnoptimizedCFG = false,
426 bool addImplicitDtors = false,
427 bool addInitializers = false,
428 bool addTemporaryDtors = false,
429 bool synthesizeBodies = false,
430 bool addStaticInitBranches = false,
431 bool addCXXNewAllocator = true,
432 CodeInjector* injector = nullptr);
434 ~AnalysisDeclContextManager();
436 AnalysisDeclContext *getContext(const Decl *D);
438 bool getUseUnoptimizedCFG() const {
439 return !cfgBuildOptions.PruneTriviallyFalseEdges;
442 CFG::BuildOptions &getCFGBuildOptions() {
443 return cfgBuildOptions;
446 /// Return true if faux bodies should be synthesized for well-known
448 bool synthesizeBodies() const { return SynthesizeBodies; }
450 const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx,
451 LocationContext const *Parent,
455 return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx);
458 // Get the top level stack frame.
459 const StackFrameContext *getStackFrame(const Decl *D) {
460 return LocContexts.getStackFrame(getContext(D), nullptr, nullptr, nullptr,
464 // Get a stack frame with parent.
465 StackFrameContext const *getStackFrame(const Decl *D,
466 LocationContext const *Parent,
470 return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
473 /// Discard all previously created AnalysisDeclContexts.
477 friend class AnalysisDeclContext;
479 LocationContextManager &getLocationContextManager() {
484 } // end clang namespace