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/Decl.h"
19 #include "clang/Analysis/BodyFarm.h"
20 #include "clang/Analysis/CFG.h"
21 #include "clang/Analysis/CodeInjector.h"
22 #include "llvm/ADT/DenseMap.h"
23 #include "llvm/ADT/FoldingSet.h"
24 #include "llvm/Support/Allocator.h"
30 class CFGReverseBlockReachabilityAnalysis;
33 class ManagedAnalysis;
35 class PseudoConstantAnalysis;
36 class LocationContextManager;
37 class StackFrameContext;
38 class BlockInvocationContext;
39 class AnalysisDeclContextManager;
40 class LocationContext;
42 namespace idx { class TranslationUnit; }
44 /// The base class of a hierarchy of objects representing analyses tied
45 /// to AnalysisDeclContext.
46 class ManagedAnalysis {
50 virtual ~ManagedAnalysis();
52 // Subclasses need to implement:
54 // static const void *getTag();
56 // Which returns a fixed pointer address to distinguish classes of
57 // analysis objects. They also need to implement:
59 // static [Derived*] create(AnalysisDeclContext &Ctx);
61 // which creates the analysis object given an AnalysisDeclContext.
65 /// AnalysisDeclContext contains the context data for the function or method
67 class AnalysisDeclContext {
68 /// Backpoint to the AnalysisManager object that created this
69 /// AnalysisDeclContext. This may be null.
70 AnalysisDeclContextManager *Manager;
74 std::unique_ptr<CFG> cfg, completeCFG;
75 std::unique_ptr<CFGStmtMap> cfgStmtMap;
77 CFG::BuildOptions cfgBuildOptions;
78 CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
80 bool builtCFG, builtCompleteCFG;
81 std::unique_ptr<ParentMap> PM;
82 std::unique_ptr<PseudoConstantAnalysis> PCA;
83 std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
85 llvm::BumpPtrAllocator A;
87 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
89 void *ManagedAnalyses;
92 AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
95 AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
97 const CFG::BuildOptions &BuildOptions);
99 ~AnalysisDeclContext();
101 ASTContext &getASTContext() const { return D->getASTContext(); }
102 const Decl *getDecl() const { return D; }
104 /// Return the AnalysisDeclContextManager (if any) that created
105 /// this AnalysisDeclContext.
106 AnalysisDeclContextManager *getManager() const {
110 /// Return the build options used to construct the CFG.
111 CFG::BuildOptions &getCFGBuildOptions() {
112 return cfgBuildOptions;
115 const CFG::BuildOptions &getCFGBuildOptions() const {
116 return cfgBuildOptions;
119 /// getAddEHEdges - Return true iff we are adding exceptional edges from
120 /// callExprs. If this is false, then try/catch statements and blocks
121 /// reachable from them can appear to be dead in the CFG, analysis passes must
123 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
124 bool getUseUnoptimizedCFG() const {
125 return !cfgBuildOptions.PruneTriviallyFalseEdges;
127 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
128 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
130 void registerForcedBlockExpression(const Stmt *stmt);
131 const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
133 /// \brief Get the body of the Declaration.
134 Stmt *getBody() const;
136 /// \brief Get the body of the Declaration.
137 /// \param[out] IsAutosynthesized Specifies if the body is auto-generated
139 Stmt *getBody(bool &IsAutosynthesized) const;
141 /// \brief Checks if the body of the Decl is generated by the BodyFarm.
143 /// Note, the lookup is not free. We are going to call getBody behind
146 bool isBodyAutosynthesized() const;
148 /// \brief Checks if the body of the Decl is generated by the BodyFarm from a
151 /// Note, the lookup is not free. We are going to call getBody behind
154 bool isBodyAutosynthesizedFromModelFile() const;
158 CFGStmtMap *getCFGStmtMap();
160 CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
162 /// Return a version of the CFG without any edges pruned.
163 CFG *getUnoptimizedCFG();
165 void dumpCFG(bool ShowColors);
167 /// \brief Returns true if we have built a CFG for this analysis context.
168 /// Note that this doesn't correspond to whether or not a valid CFG exists, it
169 /// corresponds to whether we *attempted* to build one.
170 bool isCFGBuilt() const { return builtCFG; }
172 ParentMap &getParentMap();
173 PseudoConstantAnalysis *getPseudoConstantAnalysis();
175 typedef const VarDecl * const * referenced_decls_iterator;
177 llvm::iterator_range<referenced_decls_iterator>
178 getReferencedBlockVars(const BlockDecl *BD);
180 /// Return the ImplicitParamDecl* associated with 'self' if this
181 /// AnalysisDeclContext wraps an ObjCMethodDecl. Returns NULL otherwise.
182 const ImplicitParamDecl *getSelfDecl() const;
184 const StackFrameContext *getStackFrame(LocationContext const *Parent,
189 const BlockInvocationContext *
190 getBlockInvocationContext(const LocationContext *parent,
192 const void *ContextData);
194 /// Return the specified analysis object, lazily running the analysis if
195 /// necessary. Return NULL if the analysis could not run.
196 template <typename T>
198 const void *tag = T::getTag();
199 ManagedAnalysis *&data = getAnalysisImpl(tag);
201 data = T::create(*this);
203 return static_cast<T*>(data);
206 /// Returns true if the root namespace of the given declaration is the 'std'
208 static bool isInStdNamespace(const Decl *D);
210 ManagedAnalysis *&getAnalysisImpl(const void* tag);
212 LocationContextManager &getLocationContextManager();
215 class LocationContext : public llvm::FoldingSetNode {
217 enum ContextKind { StackFrame, Scope, Block };
222 // AnalysisDeclContext can't be const since some methods may modify its
224 AnalysisDeclContext *Ctx;
226 const LocationContext *Parent;
229 LocationContext(ContextKind k, AnalysisDeclContext *ctx,
230 const LocationContext *parent)
231 : Kind(k), Ctx(ctx), Parent(parent) {}
234 virtual ~LocationContext();
236 ContextKind getKind() const { return Kind; }
238 AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
240 const LocationContext *getParent() const { return Parent; }
242 bool isParentOf(const LocationContext *LC) const;
244 const Decl *getDecl() const { return getAnalysisDeclContext()->getDecl(); }
246 CFG *getCFG() const { return getAnalysisDeclContext()->getCFG(); }
248 template <typename T>
249 T *getAnalysis() const {
250 return getAnalysisDeclContext()->getAnalysis<T>();
253 ParentMap &getParentMap() const {
254 return getAnalysisDeclContext()->getParentMap();
257 const ImplicitParamDecl *getSelfDecl() const {
258 return Ctx->getSelfDecl();
261 const StackFrameContext *getCurrentStackFrame() const;
263 /// Return true if the current LocationContext has no caller context.
264 virtual bool inTopFrame() const;
266 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
268 void dumpStack(raw_ostream &OS, StringRef Indent = "") const;
269 void dumpStack() const;
272 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
274 AnalysisDeclContext *ctx,
275 const LocationContext *parent,
279 class StackFrameContext : public LocationContext {
280 // The callsite where this stack frame is established.
281 const Stmt *CallSite;
283 // The parent block of the callsite.
284 const CFGBlock *Block;
286 // The index of the callsite in the CFGBlock.
289 friend class LocationContextManager;
290 StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
291 const Stmt *s, const CFGBlock *blk,
293 : LocationContext(StackFrame, ctx, parent), CallSite(s),
294 Block(blk), Index(idx) {}
297 ~StackFrameContext() override {}
299 const Stmt *getCallSite() const { return CallSite; }
301 const CFGBlock *getCallSiteBlock() const { return Block; }
303 /// Return true if the current LocationContext has no caller context.
304 bool inTopFrame() const override { return getParent() == nullptr; }
306 unsigned getIndex() const { return Index; }
308 void Profile(llvm::FoldingSetNodeID &ID) override;
310 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
311 const LocationContext *parent, const Stmt *s,
312 const CFGBlock *blk, unsigned idx) {
313 ProfileCommon(ID, StackFrame, ctx, parent, s);
318 static bool classof(const LocationContext *Ctx) {
319 return Ctx->getKind() == StackFrame;
323 class ScopeContext : public LocationContext {
326 friend class LocationContextManager;
327 ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent,
329 : LocationContext(Scope, ctx, parent), Enter(s) {}
332 ~ScopeContext() override {}
334 void Profile(llvm::FoldingSetNodeID &ID) override;
336 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
337 const LocationContext *parent, const Stmt *s) {
338 ProfileCommon(ID, Scope, ctx, parent, s);
341 static bool classof(const LocationContext *Ctx) {
342 return Ctx->getKind() == Scope;
346 class BlockInvocationContext : public LocationContext {
349 // FIXME: Come up with a more type-safe way to model context-sensitivity.
350 const void *ContextData;
352 friend class LocationContextManager;
354 BlockInvocationContext(AnalysisDeclContext *ctx,
355 const LocationContext *parent,
356 const BlockDecl *bd, const void *contextData)
357 : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
360 ~BlockInvocationContext() override {}
362 const BlockDecl *getBlockDecl() const { return BD; }
364 const void *getContextData() const { return ContextData; }
366 void Profile(llvm::FoldingSetNodeID &ID) override;
368 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
369 const LocationContext *parent, const BlockDecl *bd,
370 const void *contextData) {
371 ProfileCommon(ID, Block, ctx, parent, bd);
372 ID.AddPointer(contextData);
375 static bool classof(const LocationContext *Ctx) {
376 return Ctx->getKind() == Block;
380 class LocationContextManager {
381 llvm::FoldingSet<LocationContext> Contexts;
383 ~LocationContextManager();
385 const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx,
386 const LocationContext *parent,
388 const CFGBlock *blk, unsigned idx);
390 const ScopeContext *getScope(AnalysisDeclContext *ctx,
391 const LocationContext *parent,
394 const BlockInvocationContext *
395 getBlockInvocationContext(AnalysisDeclContext *ctx,
396 const LocationContext *parent,
398 const void *ContextData);
400 /// Discard all previously created LocationContext objects.
403 template <typename LOC, typename DATA>
404 const LOC *getLocationContext(AnalysisDeclContext *ctx,
405 const LocationContext *parent,
409 class AnalysisDeclContextManager {
410 typedef llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>
414 LocationContextManager LocContexts;
415 CFG::BuildOptions cfgBuildOptions;
417 /// Pointer to an interface that can provide function bodies for
418 /// declarations from external source.
419 std::unique_ptr<CodeInjector> Injector;
421 /// A factory for creating and caching implementations for common
422 /// methods during the analysis.
423 BodyFarm FunctionBodyFarm;
425 /// Flag to indicate whether or not bodies should be synthesized
426 /// for well-known functions.
427 bool SynthesizeBodies;
430 AnalysisDeclContextManager(ASTContext &ASTCtx, bool useUnoptimizedCFG = false,
431 bool addImplicitDtors = false,
432 bool addInitializers = false,
433 bool addTemporaryDtors = false,
434 bool addLifetime = false, bool addLoopExit = false,
435 bool synthesizeBodies = false,
436 bool addStaticInitBranches = false,
437 bool addCXXNewAllocator = true,
438 CodeInjector *injector = nullptr);
440 AnalysisDeclContext *getContext(const Decl *D);
442 bool getUseUnoptimizedCFG() const {
443 return !cfgBuildOptions.PruneTriviallyFalseEdges;
446 CFG::BuildOptions &getCFGBuildOptions() {
447 return cfgBuildOptions;
450 /// Return true if faux bodies should be synthesized for well-known
452 bool synthesizeBodies() const { return SynthesizeBodies; }
454 const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx,
455 LocationContext const *Parent,
459 return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx);
462 // Get the top level stack frame.
463 const StackFrameContext *getStackFrame(const Decl *D) {
464 return LocContexts.getStackFrame(getContext(D), nullptr, nullptr, nullptr,
468 // Get a stack frame with parent.
469 StackFrameContext const *getStackFrame(const Decl *D,
470 LocationContext const *Parent,
474 return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
477 /// Get a reference to {@code BodyFarm} instance.
478 BodyFarm &getBodyFarm();
480 /// Discard all previously created AnalysisDeclContexts.
484 friend class AnalysisDeclContext;
486 LocationContextManager &getLocationContextManager() {
491 } // end clang namespace