1 // AnalysisDeclContext.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_ANALYSISDECLCONTEXT_H
16 #define LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
18 #include "clang/AST/DeclBase.h"
19 #include "clang/Analysis/BodyFarm.h"
20 #include "clang/Analysis/CFG.h"
21 #include "clang/Analysis/CodeInjector.h"
22 #include "clang/Basic/LLVM.h"
23 #include "llvm/ADT/DenseMap.h"
24 #include "llvm/ADT/FoldingSet.h"
25 #include "llvm/ADT/StringRef.h"
26 #include "llvm/ADT/iterator_range.h"
27 #include "llvm/Support/Allocator.h"
33 class AnalysisDeclContextManager;
36 class BlockInvocationContext;
37 class CFGReverseBlockReachabilityAnalysis;
39 class ImplicitParamDecl;
40 class LocationContext;
41 class LocationContextManager;
43 class PseudoConstantAnalysis;
44 class StackFrameContext;
48 /// The base class of a hierarchy of objects representing analyses tied
49 /// to AnalysisDeclContext.
50 class ManagedAnalysis {
52 ManagedAnalysis() = default;
55 virtual ~ManagedAnalysis();
57 // Subclasses need to implement:
59 // static const void *getTag();
61 // Which returns a fixed pointer address to distinguish classes of
62 // analysis objects. They also need to implement:
64 // static [Derived*] create(AnalysisDeclContext &Ctx);
66 // which creates the analysis object given an AnalysisDeclContext.
69 /// AnalysisDeclContext contains the context data for the function or method
71 class AnalysisDeclContext {
72 /// Backpoint to the AnalysisManager object that created this
73 /// AnalysisDeclContext. This may be null.
74 AnalysisDeclContextManager *Manager;
78 std::unique_ptr<CFG> cfg, completeCFG;
79 std::unique_ptr<CFGStmtMap> cfgStmtMap;
81 CFG::BuildOptions cfgBuildOptions;
82 CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs = nullptr;
84 bool builtCFG = false;
85 bool builtCompleteCFG = false;
86 std::unique_ptr<ParentMap> PM;
87 std::unique_ptr<PseudoConstantAnalysis> PCA;
88 std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
90 llvm::BumpPtrAllocator A;
92 llvm::DenseMap<const BlockDecl *,void *> *ReferencedBlockVars = nullptr;
94 void *ManagedAnalyses = nullptr;
97 AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
100 AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
102 const CFG::BuildOptions &BuildOptions);
104 ~AnalysisDeclContext();
106 ASTContext &getASTContext() const { return D->getASTContext(); }
107 const Decl *getDecl() const { return D; }
109 /// Return the AnalysisDeclContextManager (if any) that created
110 /// this AnalysisDeclContext.
111 AnalysisDeclContextManager *getManager() const {
115 /// Return the build options used to construct the CFG.
116 CFG::BuildOptions &getCFGBuildOptions() {
117 return cfgBuildOptions;
120 const CFG::BuildOptions &getCFGBuildOptions() const {
121 return cfgBuildOptions;
124 /// getAddEHEdges - Return true iff we are adding exceptional edges from
125 /// callExprs. If this is false, then try/catch statements and blocks
126 /// reachable from them can appear to be dead in the CFG, analysis passes must
128 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
129 bool getUseUnoptimizedCFG() const {
130 return !cfgBuildOptions.PruneTriviallyFalseEdges;
132 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
133 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
135 void registerForcedBlockExpression(const Stmt *stmt);
136 const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
138 /// Get the body of the Declaration.
139 Stmt *getBody() const;
141 /// Get the body of the Declaration.
142 /// \param[out] IsAutosynthesized Specifies if the body is auto-generated
144 Stmt *getBody(bool &IsAutosynthesized) const;
146 /// Checks if the body of the Decl is generated by the BodyFarm.
148 /// Note, the lookup is not free. We are going to call getBody behind
151 bool isBodyAutosynthesized() const;
153 /// Checks if the body of the Decl is generated by the BodyFarm from a
156 /// Note, the lookup is not free. We are going to call getBody behind
159 bool isBodyAutosynthesizedFromModelFile() const;
163 CFGStmtMap *getCFGStmtMap();
165 CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
167 /// Return a version of the CFG without any edges pruned.
168 CFG *getUnoptimizedCFG();
170 void dumpCFG(bool ShowColors);
172 /// Returns true if we have built a CFG for this analysis context.
173 /// Note that this doesn't correspond to whether or not a valid CFG exists, it
174 /// corresponds to whether we *attempted* to build one.
175 bool isCFGBuilt() const { return builtCFG; }
177 ParentMap &getParentMap();
178 PseudoConstantAnalysis *getPseudoConstantAnalysis();
180 using referenced_decls_iterator = const VarDecl * const *;
182 llvm::iterator_range<referenced_decls_iterator>
183 getReferencedBlockVars(const BlockDecl *BD);
185 /// Return the ImplicitParamDecl* associated with 'self' if this
186 /// AnalysisDeclContext wraps an ObjCMethodDecl. Returns NULL otherwise.
187 const ImplicitParamDecl *getSelfDecl() const;
189 const StackFrameContext *getStackFrame(LocationContext const *Parent,
194 const BlockInvocationContext *
195 getBlockInvocationContext(const LocationContext *parent,
197 const void *ContextData);
199 /// Return the specified analysis object, lazily running the analysis if
200 /// necessary. Return NULL if the analysis could not run.
201 template <typename T>
203 const void *tag = T::getTag();
204 ManagedAnalysis *&data = getAnalysisImpl(tag);
206 data = T::create(*this);
208 return static_cast<T *>(data);
211 /// Returns true if the root namespace of the given declaration is the 'std'
213 static bool isInStdNamespace(const Decl *D);
216 ManagedAnalysis *&getAnalysisImpl(const void* tag);
218 LocationContextManager &getLocationContextManager();
221 class LocationContext : public llvm::FoldingSetNode {
223 enum ContextKind { StackFrame, Scope, Block };
228 // AnalysisDeclContext can't be const since some methods may modify its
230 AnalysisDeclContext *Ctx;
232 const LocationContext *Parent;
235 LocationContext(ContextKind k, AnalysisDeclContext *ctx,
236 const LocationContext *parent)
237 : Kind(k), Ctx(ctx), Parent(parent) {}
240 virtual ~LocationContext();
242 ContextKind getKind() const { return Kind; }
244 AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
246 const LocationContext *getParent() const { return Parent; }
248 bool isParentOf(const LocationContext *LC) const;
250 const Decl *getDecl() const { return getAnalysisDeclContext()->getDecl(); }
252 CFG *getCFG() const { return getAnalysisDeclContext()->getCFG(); }
254 template <typename T>
255 T *getAnalysis() const {
256 return getAnalysisDeclContext()->getAnalysis<T>();
259 ParentMap &getParentMap() const {
260 return getAnalysisDeclContext()->getParentMap();
263 const ImplicitParamDecl *getSelfDecl() const {
264 return Ctx->getSelfDecl();
267 const StackFrameContext *getStackFrame() const;
269 /// Return true if the current LocationContext has no caller context.
270 virtual bool inTopFrame() const;
272 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
275 raw_ostream &OS, StringRef Indent = {}, const char *NL = "\n",
276 const char *Sep = "",
277 std::function<void(const LocationContext *)> printMoreInfoPerContext =
278 [](const LocationContext *) {}) const;
279 void dumpStack() const;
282 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
284 AnalysisDeclContext *ctx,
285 const LocationContext *parent,
289 class StackFrameContext : public LocationContext {
290 friend class LocationContextManager;
292 // The callsite where this stack frame is established.
293 const Stmt *CallSite;
295 // The parent block of the callsite.
296 const CFGBlock *Block;
298 // The index of the callsite in the CFGBlock.
301 StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
302 const Stmt *s, const CFGBlock *blk,
304 : LocationContext(StackFrame, ctx, parent), CallSite(s),
305 Block(blk), Index(idx) {}
308 ~StackFrameContext() override = default;
310 const Stmt *getCallSite() const { return CallSite; }
312 const CFGBlock *getCallSiteBlock() const { return Block; }
314 /// Return true if the current LocationContext has no caller context.
315 bool inTopFrame() const override { return getParent() == nullptr; }
317 unsigned getIndex() const { return Index; }
319 void Profile(llvm::FoldingSetNodeID &ID) override;
321 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
322 const LocationContext *parent, const Stmt *s,
323 const CFGBlock *blk, unsigned idx) {
324 ProfileCommon(ID, StackFrame, ctx, parent, s);
329 static bool classof(const LocationContext *Ctx) {
330 return Ctx->getKind() == StackFrame;
334 class ScopeContext : public LocationContext {
335 friend class LocationContextManager;
339 ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent,
341 : LocationContext(Scope, ctx, parent), Enter(s) {}
344 ~ScopeContext() override = default;
346 void Profile(llvm::FoldingSetNodeID &ID) override;
348 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
349 const LocationContext *parent, const Stmt *s) {
350 ProfileCommon(ID, Scope, ctx, parent, s);
353 static bool classof(const LocationContext *Ctx) {
354 return Ctx->getKind() == Scope;
358 class BlockInvocationContext : public LocationContext {
359 friend class LocationContextManager;
363 // FIXME: Come up with a more type-safe way to model context-sensitivity.
364 const void *ContextData;
366 BlockInvocationContext(AnalysisDeclContext *ctx,
367 const LocationContext *parent,
368 const BlockDecl *bd, const void *contextData)
369 : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
372 ~BlockInvocationContext() override = default;
374 const BlockDecl *getBlockDecl() const { return BD; }
376 const void *getContextData() const { return ContextData; }
378 void Profile(llvm::FoldingSetNodeID &ID) override;
380 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
381 const LocationContext *parent, const BlockDecl *bd,
382 const void *contextData) {
383 ProfileCommon(ID, Block, ctx, parent, bd);
384 ID.AddPointer(contextData);
387 static bool classof(const LocationContext *Ctx) {
388 return Ctx->getKind() == Block;
392 class LocationContextManager {
393 llvm::FoldingSet<LocationContext> Contexts;
396 ~LocationContextManager();
398 const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx,
399 const LocationContext *parent,
401 const CFGBlock *blk, unsigned idx);
403 const ScopeContext *getScope(AnalysisDeclContext *ctx,
404 const LocationContext *parent,
407 const BlockInvocationContext *
408 getBlockInvocationContext(AnalysisDeclContext *ctx,
409 const LocationContext *parent,
411 const void *ContextData);
413 /// Discard all previously created LocationContext objects.
416 template <typename LOC, typename DATA>
417 const LOC *getLocationContext(AnalysisDeclContext *ctx,
418 const LocationContext *parent,
422 class AnalysisDeclContextManager {
424 llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>;
427 LocationContextManager LocContexts;
428 CFG::BuildOptions cfgBuildOptions;
430 /// Pointer to an interface that can provide function bodies for
431 /// declarations from external source.
432 std::unique_ptr<CodeInjector> Injector;
434 /// A factory for creating and caching implementations for common
435 /// methods during the analysis.
436 BodyFarm FunctionBodyFarm;
438 /// Flag to indicate whether or not bodies should be synthesized
439 /// for well-known functions.
440 bool SynthesizeBodies;
443 AnalysisDeclContextManager(ASTContext &ASTCtx, bool useUnoptimizedCFG = false,
444 bool addImplicitDtors = false,
445 bool addInitializers = false,
446 bool addTemporaryDtors = false,
447 bool addLifetime = false,
448 bool addLoopExit = false,
449 bool addScopes = false,
450 bool synthesizeBodies = false,
451 bool addStaticInitBranches = false,
452 bool addCXXNewAllocator = true,
453 bool addRichCXXConstructors = true,
454 bool markElidedCXXConstructors = true,
455 CodeInjector *injector = nullptr);
457 AnalysisDeclContext *getContext(const Decl *D);
459 bool getUseUnoptimizedCFG() const {
460 return !cfgBuildOptions.PruneTriviallyFalseEdges;
463 CFG::BuildOptions &getCFGBuildOptions() {
464 return cfgBuildOptions;
467 /// Return true if faux bodies should be synthesized for well-known
469 bool synthesizeBodies() const { return SynthesizeBodies; }
471 const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx,
472 LocationContext const *Parent,
476 return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx);
479 // Get the top level stack frame.
480 const StackFrameContext *getStackFrame(const Decl *D) {
481 return LocContexts.getStackFrame(getContext(D), nullptr, nullptr, nullptr,
485 // Get a stack frame with parent.
486 StackFrameContext const *getStackFrame(const Decl *D,
487 LocationContext const *Parent,
491 return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
494 /// Get a reference to {@code BodyFarm} instance.
495 BodyFarm &getBodyFarm();
497 /// Discard all previously created AnalysisDeclContexts.
501 friend class AnalysisDeclContext;
503 LocationContextManager &getLocationContextManager() {
510 #endif // LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H