File indexing completed on 2026-05-10 08:36:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
0018 #define LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
0019
0020 #include "clang/AST/DeclBase.h"
0021 #include "clang/Analysis/BodyFarm.h"
0022 #include "clang/Analysis/CFG.h"
0023 #include "clang/Analysis/CodeInjector.h"
0024 #include "clang/Basic/LLVM.h"
0025 #include "llvm/ADT/DenseMap.h"
0026 #include "llvm/ADT/FoldingSet.h"
0027 #include "llvm/ADT/StringRef.h"
0028 #include "llvm/ADT/iterator_range.h"
0029 #include "llvm/Support/Allocator.h"
0030 #include <functional>
0031 #include <memory>
0032
0033 namespace clang {
0034
0035 class AnalysisDeclContextManager;
0036 class ASTContext;
0037 class BlockDecl;
0038 class BlockInvocationContext;
0039 class CFGReverseBlockReachabilityAnalysis;
0040 class CFGStmtMap;
0041 class ImplicitParamDecl;
0042 class LocationContext;
0043 class LocationContextManager;
0044 class ParentMap;
0045 class StackFrameContext;
0046 class Stmt;
0047 class VarDecl;
0048
0049
0050
0051 class ManagedAnalysis {
0052 protected:
0053 ManagedAnalysis() = default;
0054
0055 public:
0056 virtual ~ManagedAnalysis();
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068 };
0069
0070
0071
0072 class AnalysisDeclContext {
0073
0074
0075 AnalysisDeclContextManager *ADCMgr;
0076
0077 const Decl *const D;
0078
0079 std::unique_ptr<CFG> cfg, completeCFG;
0080 std::unique_ptr<CFGStmtMap> cfgStmtMap;
0081
0082 CFG::BuildOptions cfgBuildOptions;
0083 CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs = nullptr;
0084
0085 bool builtCFG = false;
0086 bool builtCompleteCFG = false;
0087 std::unique_ptr<ParentMap> PM;
0088 std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
0089
0090 llvm::BumpPtrAllocator A;
0091
0092 llvm::DenseMap<const BlockDecl *, void *> *ReferencedBlockVars = nullptr;
0093
0094 void *ManagedAnalyses = nullptr;
0095
0096 public:
0097 AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D);
0098
0099 AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D,
0100 const CFG::BuildOptions &BuildOptions);
0101
0102 ~AnalysisDeclContext();
0103
0104 ASTContext &getASTContext() const { return D->getASTContext(); }
0105
0106 const Decl *getDecl() const { return D; }
0107
0108 AnalysisDeclContextManager *getManager() const { return ADCMgr; }
0109
0110 CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; }
0111
0112 const CFG::BuildOptions &getCFGBuildOptions() const {
0113 return cfgBuildOptions;
0114 }
0115
0116
0117
0118
0119 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
0120 bool getUseUnoptimizedCFG() const {
0121 return !cfgBuildOptions.PruneTriviallyFalseEdges;
0122 }
0123 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
0124 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
0125
0126 void registerForcedBlockExpression(const Stmt *stmt);
0127 const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
0128
0129
0130 Stmt *getBody() const;
0131
0132
0133
0134
0135 Stmt *getBody(bool &IsAutosynthesized) const;
0136
0137
0138
0139
0140
0141
0142 bool isBodyAutosynthesized() const;
0143
0144
0145
0146
0147
0148
0149
0150 bool isBodyAutosynthesizedFromModelFile() const;
0151
0152 CFG *getCFG();
0153
0154 CFGStmtMap *getCFGStmtMap();
0155
0156 CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
0157
0158
0159 CFG *getUnoptimizedCFG();
0160
0161 void dumpCFG(bool ShowColors);
0162
0163
0164
0165
0166
0167 bool isCFGBuilt() const { return builtCFG; }
0168
0169 ParentMap &getParentMap();
0170
0171 using referenced_decls_iterator = const VarDecl *const *;
0172
0173 llvm::iterator_range<referenced_decls_iterator>
0174 getReferencedBlockVars(const BlockDecl *BD);
0175
0176
0177
0178 const ImplicitParamDecl *getSelfDecl() const;
0179
0180
0181 const StackFrameContext *getStackFrame(LocationContext const *ParentLC,
0182 const Stmt *S, const CFGBlock *Blk,
0183 unsigned BlockCount, unsigned Index);
0184
0185
0186 const BlockInvocationContext *
0187 getBlockInvocationContext(const LocationContext *ParentLC,
0188 const BlockDecl *BD, const void *Data);
0189
0190
0191
0192 template <typename T> T *getAnalysis() {
0193 const void *tag = T::getTag();
0194 std::unique_ptr<ManagedAnalysis> &data = getAnalysisImpl(tag);
0195 if (!data)
0196 data = T::create(*this);
0197 return static_cast<T *>(data.get());
0198 }
0199
0200
0201 static bool isInStdNamespace(const Decl *D);
0202
0203 static std::string getFunctionName(const Decl *D);
0204
0205 private:
0206 std::unique_ptr<ManagedAnalysis> &getAnalysisImpl(const void *tag);
0207
0208 LocationContextManager &getLocationContextManager();
0209 };
0210
0211
0212
0213
0214
0215 class LocationContext : public llvm::FoldingSetNode {
0216 public:
0217 enum ContextKind { StackFrame, Block };
0218
0219 private:
0220 ContextKind Kind;
0221
0222
0223
0224 AnalysisDeclContext *Ctx;
0225
0226 const LocationContext *Parent;
0227 int64_t ID;
0228
0229 protected:
0230 LocationContext(ContextKind k, AnalysisDeclContext *ctx,
0231 const LocationContext *parent, int64_t ID)
0232 : Kind(k), Ctx(ctx), Parent(parent), ID(ID) {
0233 assert(ctx);
0234 }
0235
0236 public:
0237 virtual ~LocationContext();
0238
0239 ContextKind getKind() const { return Kind; }
0240
0241 int64_t getID() const { return ID; }
0242
0243 LLVM_ATTRIBUTE_RETURNS_NONNULL
0244 AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
0245
0246
0247 const LocationContext *getParent() const { return Parent; }
0248
0249 bool isParentOf(const LocationContext *LC) const;
0250
0251 const Decl *getDecl() const { return Ctx->getDecl(); }
0252
0253 CFG *getCFG() const { return Ctx->getCFG(); }
0254
0255 template <typename T> T *getAnalysis() const { return Ctx->getAnalysis<T>(); }
0256
0257 const ParentMap &getParentMap() const { return Ctx->getParentMap(); }
0258
0259
0260 const ImplicitParamDecl *getSelfDecl() const { return Ctx->getSelfDecl(); }
0261
0262 const StackFrameContext *getStackFrame() const;
0263
0264
0265 virtual bool inTopFrame() const;
0266
0267 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
0268
0269
0270
0271
0272 LLVM_DUMP_METHOD void dumpStack(raw_ostream &Out) const;
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285 void printJson(
0286 raw_ostream &Out, const char *NL = "\n", unsigned int Space = 0,
0287 bool IsDot = false,
0288 std::function<void(const LocationContext *)> printMoreInfoPerContext =
0289 [](const LocationContext *) {}) const;
0290
0291 LLVM_DUMP_METHOD void dump() const;
0292
0293 static void ProfileCommon(llvm::FoldingSetNodeID &ID, ContextKind ck,
0294 AnalysisDeclContext *ctx,
0295 const LocationContext *parent, const void *data);
0296 };
0297
0298
0299 class StackFrameContext : public LocationContext {
0300 friend class LocationContextManager;
0301
0302
0303 const Stmt *CallSite;
0304
0305
0306 const CFGBlock *Block;
0307
0308
0309
0310
0311 const unsigned BlockCount;
0312
0313
0314 const unsigned Index;
0315
0316 StackFrameContext(AnalysisDeclContext *ADC, const LocationContext *ParentLC,
0317 const Stmt *S, const CFGBlock *Block, unsigned BlockCount,
0318 unsigned Index, int64_t ID)
0319 : LocationContext(StackFrame, ADC, ParentLC, ID), CallSite(S),
0320 Block(Block), BlockCount(BlockCount), Index(Index) {}
0321
0322 public:
0323 ~StackFrameContext() override = default;
0324
0325 const Stmt *getCallSite() const { return CallSite; }
0326
0327 const CFGBlock *getCallSiteBlock() const { return Block; }
0328
0329 bool inTopFrame() const override { return getParent() == nullptr; }
0330
0331 unsigned getIndex() const { return Index; }
0332
0333 CFGElement getCallSiteCFGElement() const { return (*Block)[Index]; }
0334
0335 void Profile(llvm::FoldingSetNodeID &ID) override;
0336
0337 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC,
0338 const LocationContext *ParentLC, const Stmt *S,
0339 const CFGBlock *Block, unsigned BlockCount,
0340 unsigned Index) {
0341 ProfileCommon(ID, StackFrame, ADC, ParentLC, S);
0342 ID.AddPointer(Block);
0343 ID.AddInteger(BlockCount);
0344 ID.AddInteger(Index);
0345 }
0346
0347 static bool classof(const LocationContext *LC) {
0348 return LC->getKind() == StackFrame;
0349 }
0350 };
0351
0352
0353 class BlockInvocationContext : public LocationContext {
0354 friend class LocationContextManager;
0355
0356 const BlockDecl *BD;
0357
0358
0359 const void *Data;
0360
0361 BlockInvocationContext(AnalysisDeclContext *ADC,
0362 const LocationContext *ParentLC, const BlockDecl *BD,
0363 const void *Data, int64_t ID)
0364 : LocationContext(Block, ADC, ParentLC, ID), BD(BD), Data(Data) {}
0365
0366 public:
0367 ~BlockInvocationContext() override = default;
0368
0369 const BlockDecl *getBlockDecl() const { return BD; }
0370
0371 const void *getData() const { return Data; }
0372
0373 void Profile(llvm::FoldingSetNodeID &ID) override;
0374
0375 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC,
0376 const LocationContext *ParentLC, const BlockDecl *BD,
0377 const void *Data) {
0378 ProfileCommon(ID, Block, ADC, ParentLC, BD);
0379 ID.AddPointer(Data);
0380 }
0381
0382 static bool classof(const LocationContext *LC) {
0383 return LC->getKind() == Block;
0384 }
0385 };
0386
0387 class LocationContextManager {
0388 llvm::FoldingSet<LocationContext> Contexts;
0389
0390
0391 int64_t NewID = 0;
0392
0393 public:
0394 ~LocationContextManager();
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405 const StackFrameContext *getStackFrame(AnalysisDeclContext *ADC,
0406 const LocationContext *ParentLC,
0407 const Stmt *S, const CFGBlock *Block,
0408 unsigned BlockCount, unsigned Index);
0409
0410
0411
0412
0413
0414
0415
0416 const BlockInvocationContext *
0417 getBlockInvocationContext(AnalysisDeclContext *ADC,
0418 const LocationContext *ParentLC,
0419 const BlockDecl *BD, const void *Data);
0420
0421
0422 void clear();
0423 };
0424
0425 class AnalysisDeclContextManager {
0426 using ContextMap =
0427 llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>;
0428
0429 ContextMap Contexts;
0430 LocationContextManager LocCtxMgr;
0431 CFG::BuildOptions cfgBuildOptions;
0432
0433
0434
0435 std::unique_ptr<CodeInjector> Injector;
0436
0437
0438
0439 BodyFarm FunctionBodyFarm;
0440
0441
0442
0443 bool SynthesizeBodies;
0444
0445 public:
0446 AnalysisDeclContextManager(
0447 ASTContext &ASTCtx, bool useUnoptimizedCFG = false,
0448 bool addImplicitDtors = false, bool addInitializers = false,
0449 bool addTemporaryDtors = false, bool addLifetime = false,
0450 bool addLoopExit = false, bool addScopes = false,
0451 bool synthesizeBodies = false, bool addStaticInitBranches = false,
0452 bool addCXXNewAllocator = true, bool addRichCXXConstructors = true,
0453 bool markElidedCXXConstructors = true, bool addVirtualBaseBranches = true,
0454 CodeInjector *injector = nullptr);
0455
0456 AnalysisDeclContext *getContext(const Decl *D);
0457
0458 bool getUseUnoptimizedCFG() const {
0459 return !cfgBuildOptions.PruneTriviallyFalseEdges;
0460 }
0461
0462 CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; }
0463
0464
0465 bool synthesizeBodies() const { return SynthesizeBodies; }
0466
0467
0468
0469
0470 const StackFrameContext *getStackFrame(const Decl *D) {
0471 return LocCtxMgr.getStackFrame(getContext(D), nullptr, nullptr, nullptr, 0,
0472 0);
0473 }
0474
0475
0476 const StackFrameContext *getStackFrame(AnalysisDeclContext *ADC,
0477 const LocationContext *Parent,
0478 const Stmt *S, const CFGBlock *Block,
0479 unsigned BlockCount, unsigned Index) {
0480 return LocCtxMgr.getStackFrame(ADC, Parent, S, Block, BlockCount, Index);
0481 }
0482
0483 BodyFarm &getBodyFarm();
0484
0485
0486 void clear();
0487
0488 private:
0489 friend class AnalysisDeclContext;
0490
0491 LocationContextManager &getLocationContextManager() { return LocCtxMgr; }
0492 };
0493
0494 }
0495
0496 #endif