clang 20.0.0git
AnalysisDeclContext.h
Go to the documentation of this file.
1//===- AnalysisDeclContext.h - Context for path sensitivity -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file
10/// This file defines AnalysisDeclContext, a class that manages the analysis
11/// context data for context sensitive and path sensitive analysis.
12/// It also defines the helper classes to model entering, leaving or inlining
13/// function calls.
14//
15//===----------------------------------------------------------------------===//
16
17#ifndef LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
18#define LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
19
20#include "clang/AST/DeclBase.h"
22#include "clang/Analysis/CFG.h"
24#include "clang/Basic/LLVM.h"
25#include "llvm/ADT/DenseMap.h"
26#include "llvm/ADT/FoldingSet.h"
27#include "llvm/ADT/StringRef.h"
28#include "llvm/ADT/iterator_range.h"
29#include "llvm/Support/Allocator.h"
30#include <functional>
31#include <memory>
32
33namespace clang {
34
35class AnalysisDeclContextManager;
36class ASTContext;
37class BlockDecl;
38class BlockInvocationContext;
39class CFGReverseBlockReachabilityAnalysis;
40class CFGStmtMap;
41class ImplicitParamDecl;
42class LocationContext;
43class LocationContextManager;
44class ParentMap;
45class StackFrameContext;
46class Stmt;
47class VarDecl;
48
49/// The base class of a hierarchy of objects representing analyses tied
50/// to AnalysisDeclContext.
52protected:
53 ManagedAnalysis() = default;
54
55public:
57
58 // Subclasses need to implement:
59 //
60 // static const void *getTag();
61 //
62 // Which returns a fixed pointer address to distinguish classes of
63 // analysis objects. They also need to implement:
64 //
65 // static [Derived*] create(AnalysisDeclContext &Ctx);
66 //
67 // which creates the analysis object given an AnalysisDeclContext.
68};
69
70/// AnalysisDeclContext contains the context data for the function, method
71/// or block under analysis.
73 // Backpoint to the AnalysisManager object that created this
74 // AnalysisDeclContext. This may be null.
76
77 const Decl *const D;
78
79 std::unique_ptr<CFG> cfg, completeCFG;
80 std::unique_ptr<CFGStmtMap> cfgStmtMap;
81
82 CFG::BuildOptions cfgBuildOptions;
83 CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs = nullptr;
84
85 bool builtCFG = false;
86 bool builtCompleteCFG = false;
87 std::unique_ptr<ParentMap> PM;
88 std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
89
90 llvm::BumpPtrAllocator A;
91
92 llvm::DenseMap<const BlockDecl *, void *> *ReferencedBlockVars = nullptr;
93
94 void *ManagedAnalyses = nullptr;
95
96public:
98
100 const CFG::BuildOptions &BuildOptions);
101
103
104 ASTContext &getASTContext() const { return D->getASTContext(); }
105
106 const Decl *getDecl() const { return D; }
107
108 AnalysisDeclContextManager *getManager() const { return ADCMgr; }
109
110 CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; }
111
113 return cfgBuildOptions;
114 }
115
116 /// \returns Whether we are adding exception handling edges from CallExprs.
117 /// If this is false, then try/catch statements and blocks reachable from them
118 /// can appear to be dead in the CFG, analysis passes must cope with that.
119 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
120 bool getUseUnoptimizedCFG() const {
121 return !cfgBuildOptions.PruneTriviallyFalseEdges;
122 }
123 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
124 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
125
128
129 /// \returns The body of the stored Decl \c D.
130 Stmt *getBody() const;
131
132 /// \copydoc AnalysisDeclContext::getBody()
133 /// \param[out] IsAutosynthesized Specifies if the body is auto-generated
134 /// by the BodyFarm.
135 Stmt *getBody(bool &IsAutosynthesized) const;
136
137 /// \returns Whether the body of the Decl \c D is generated by the BodyFarm.
138 ///
139 /// \note The lookup is not free. We are going to call getBody behind
140 /// the scenes.
141 /// \sa getBody
142 bool isBodyAutosynthesized() const;
143
144 /// \returns Whether the body of the Decl \c D is generated by the BodyFarm
145 /// from a model file.
146 ///
147 /// \note The lookup is not free. We are going to call getBody behind
148 /// the scenes.
149 /// \sa getBody
151
152 CFG *getCFG();
153
155
157
158 /// \returns A version of the CFG without any edges pruned.
160
161 void dumpCFG(bool ShowColors);
162
163 /// \returns Whether we have built a CFG for this analysis context.
164 ///
165 /// \note This doesn't correspond to whether or not a valid CFG exists, it
166 /// corresponds to whether we *attempted* to build one.
167 bool isCFGBuilt() const { return builtCFG; }
168
170
171 using referenced_decls_iterator = const VarDecl *const *;
172
173 llvm::iterator_range<referenced_decls_iterator>
175
176 /// \returns The ImplicitParamDecl associated with \c self if this
177 /// AnalysisDeclContext wraps an ObjCMethodDecl or nullptr otherwise.
178 const ImplicitParamDecl *getSelfDecl() const;
179
180 /// \copydoc LocationContextManager::getStackFrame()
181 const StackFrameContext *getStackFrame(LocationContext const *ParentLC,
182 const Stmt *S, const CFGBlock *Blk,
183 unsigned BlockCount, unsigned Index);
184
185 /// \copydoc LocationContextManager::getBlockInvocationContext()
188 const BlockDecl *BD, const void *Data);
189
190 /// \returns The specified analysis object, lazily running the analysis if
191 /// necessary or nullptr if the analysis could not run.
192 template <typename T> T *getAnalysis() {
193 const void *tag = T::getTag();
194 std::unique_ptr<ManagedAnalysis> &data = getAnalysisImpl(tag);
195 if (!data)
196 data = T::create(*this);
197 return static_cast<T *>(data.get());
198 }
199
200 /// \returns Whether the root namespace of \p D is the \c std C++ namespace.
201 static bool isInStdNamespace(const Decl *D);
202
203 static std::string getFunctionName(const Decl *D);
204
205private:
206 std::unique_ptr<ManagedAnalysis> &getAnalysisImpl(const void *tag);
207
208 LocationContextManager &getLocationContextManager();
209};
210
211/// It wraps the AnalysisDeclContext to represent both the call stack with
212/// the help of StackFrameContext and inside the function calls the
213/// BlockInvocationContext. It is needed for context sensitive analysis to
214/// model entering, leaving or inlining function calls.
215class LocationContext : public llvm::FoldingSetNode {
216public:
218
219private:
220 ContextKind Kind;
221
222 // AnalysisDeclContext can't be const since some methods may modify its
223 // member.
225
226 const LocationContext *Parent;
227 int64_t ID;
228
229protected:
231 const LocationContext *parent, int64_t ID)
232 : Kind(k), Ctx(ctx), Parent(parent), ID(ID) {
233 assert(ctx);
234 }
235
236public:
238
239 ContextKind getKind() const { return Kind; }
240
241 int64_t getID() const { return ID; }
242
243 LLVM_ATTRIBUTE_RETURNS_NONNULL
245
246 /// It might return null.
247 const LocationContext *getParent() const { return Parent; }
248
249 bool isParentOf(const LocationContext *LC) const;
250
251 const Decl *getDecl() const { return Ctx->getDecl(); }
252
253 CFG *getCFG() const { return Ctx->getCFG(); }
254
255 template <typename T> T *getAnalysis() const { return Ctx->getAnalysis<T>(); }
256
257 const ParentMap &getParentMap() const { return Ctx->getParentMap(); }
258
259 /// \copydoc AnalysisDeclContext::getSelfDecl()
260 const ImplicitParamDecl *getSelfDecl() const { return Ctx->getSelfDecl(); }
261
262 const StackFrameContext *getStackFrame() const;
263
264 /// \returns Whether the current LocationContext has no caller context.
265 virtual bool inTopFrame() const;
266
267 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
268
269 /// Prints out the call stack.
270 ///
271 /// \param Out The out stream.
272 LLVM_DUMP_METHOD void dumpStack(raw_ostream &Out) const;
273
274 /// Prints out the call stack in \c json format.
275 ///
276 /// \param Out The out stream.
277 /// \param NL The newline.
278 /// \param Space The space count for indentation.
279 /// \param IsDot Whether the output format is \c dot.
280 /// \param printMoreInfoPerContext
281 /// A callback to print more information for each context, for example:
282 /// \code
283 /// [&](const LocationContext *LC) { LC->dump(); }
284 /// \endcode
285 void printJson(
286 raw_ostream &Out, const char *NL = "\n", unsigned int Space = 0,
287 bool IsDot = false,
288 std::function<void(const LocationContext *)> printMoreInfoPerContext =
289 [](const LocationContext *) {}) const;
290
291 LLVM_DUMP_METHOD void dump() const;
292
293 static void