File indexing completed on 2026-05-10 08:36:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
0017 #define LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H
0018
0019 #include "clang/Analysis/Support/BumpVector.h"
0020 #include "clang/AST/ExprCXX.h"
0021 #include "clang/AST/ExprObjC.h"
0022
0023 namespace clang {
0024
0025
0026
0027
0028 class ConstructionContextItem {
0029 public:
0030 enum ItemKind {
0031 VariableKind,
0032 NewAllocatorKind,
0033 ReturnKind,
0034 MaterializationKind,
0035 TemporaryDestructorKind,
0036 ElidedDestructorKind,
0037 ElidableConstructorKind,
0038 ArgumentKind,
0039 LambdaCaptureKind,
0040 STATEMENT_WITH_INDEX_KIND_BEGIN = ArgumentKind,
0041 STATEMENT_WITH_INDEX_KIND_END = LambdaCaptureKind,
0042 STATEMENT_KIND_BEGIN = VariableKind,
0043 STATEMENT_KIND_END = LambdaCaptureKind,
0044 InitializerKind,
0045 INITIALIZER_KIND_BEGIN = InitializerKind,
0046 INITIALIZER_KIND_END = InitializerKind
0047 };
0048
0049 LLVM_DUMP_METHOD static StringRef getKindAsString(ItemKind K) {
0050 switch (K) {
0051 case VariableKind: return "construct into local variable";
0052 case NewAllocatorKind: return "construct into new-allocator";
0053 case ReturnKind: return "construct into return address";
0054 case MaterializationKind: return "materialize temporary";
0055 case TemporaryDestructorKind: return "destroy temporary";
0056 case ElidedDestructorKind: return "elide destructor";
0057 case ElidableConstructorKind: return "elide constructor";
0058 case ArgumentKind: return "construct into argument";
0059 case LambdaCaptureKind:
0060 return "construct into lambda captured variable";
0061 case InitializerKind: return "construct into member variable";
0062 };
0063 llvm_unreachable("Unknown ItemKind");
0064 }
0065
0066 private:
0067 const void *const Data;
0068 const ItemKind Kind;
0069 const unsigned Index = 0;
0070
0071 bool hasStatement() const {
0072 return Kind >= STATEMENT_KIND_BEGIN &&
0073 Kind <= STATEMENT_KIND_END;
0074 }
0075
0076 bool hasIndex() const {
0077 return Kind >= STATEMENT_WITH_INDEX_KIND_BEGIN &&
0078 Kind <= STATEMENT_WITH_INDEX_KIND_END;
0079 }
0080
0081 bool hasInitializer() const {
0082 return Kind >= INITIALIZER_KIND_BEGIN &&
0083 Kind <= INITIALIZER_KIND_END;
0084 }
0085
0086 public:
0087
0088
0089
0090 ConstructionContextItem(const DeclStmt *DS)
0091 : Data(DS), Kind(VariableKind) {}
0092
0093 ConstructionContextItem(const CXXNewExpr *NE)
0094 : Data(NE), Kind(NewAllocatorKind) {}
0095
0096 ConstructionContextItem(const ReturnStmt *RS)
0097 : Data(RS), Kind(ReturnKind) {}
0098
0099 ConstructionContextItem(const MaterializeTemporaryExpr *MTE)
0100 : Data(MTE), Kind(MaterializationKind) {}
0101
0102 ConstructionContextItem(const CXXBindTemporaryExpr *BTE,
0103 bool IsElided = false)
0104 : Data(BTE),
0105 Kind(IsElided ? ElidedDestructorKind : TemporaryDestructorKind) {}
0106
0107 ConstructionContextItem(const CXXConstructExpr *CE)
0108 : Data(CE), Kind(ElidableConstructorKind) {}
0109
0110 ConstructionContextItem(const CallExpr *CE, unsigned Index)
0111 : Data(CE), Kind(ArgumentKind), Index(Index) {}
0112
0113 ConstructionContextItem(const CXXConstructExpr *CE, unsigned Index)
0114 : Data(CE), Kind(ArgumentKind), Index(Index) {}
0115
0116 ConstructionContextItem(const CXXInheritedCtorInitExpr *CE, unsigned Index)
0117 : Data(CE), Kind(ArgumentKind), Index(Index) {}
0118
0119 ConstructionContextItem(const ObjCMessageExpr *ME, unsigned Index)
0120 : Data(ME), Kind(ArgumentKind), Index(Index) {}
0121
0122
0123 ConstructionContextItem(const Expr *E, unsigned Index)
0124 : Data(E), Kind(ArgumentKind), Index(Index) {
0125 assert(isa<CallExpr>(E) || isa<CXXConstructExpr>(E) ||
0126 isa<CXXDeleteExpr>(E) || isa<CXXInheritedCtorInitExpr>(E) ||
0127 isa<ObjCMessageExpr>(E));
0128 }
0129
0130 ConstructionContextItem(const CXXCtorInitializer *Init)
0131 : Data(Init), Kind(InitializerKind), Index(0) {}
0132
0133 ConstructionContextItem(const LambdaExpr *LE, unsigned Index)
0134 : Data(LE), Kind(LambdaCaptureKind), Index(Index) {}
0135
0136 ItemKind getKind() const { return Kind; }
0137
0138 LLVM_DUMP_METHOD StringRef getKindAsString() const {
0139 return getKindAsString(getKind());
0140 }
0141
0142
0143
0144
0145
0146 const Stmt *getStmt() const {
0147 assert(hasStatement());
0148 return static_cast<const Stmt *>(Data);
0149 }
0150
0151 const Stmt *getStmtOrNull() const {
0152 return hasStatement() ? getStmt() : nullptr;
0153 }
0154
0155
0156
0157
0158 const CXXCtorInitializer *getCXXCtorInitializer() const {
0159 assert(hasInitializer());
0160 return static_cast<const CXXCtorInitializer *>(Data);
0161 }
0162
0163
0164
0165
0166
0167 unsigned getIndex() const {
0168
0169
0170 assert(hasIndex());
0171 return Index;
0172 }
0173
0174 void Profile(llvm::FoldingSetNodeID &ID) const {
0175 ID.AddPointer(Data);
0176 ID.AddInteger(Kind);
0177 ID.AddInteger(Index);
0178 }
0179
0180 bool operator==(const ConstructionContextItem &Other) const {
0181
0182
0183
0184 return std::make_tuple(Data, Kind, Index) ==
0185 std::make_tuple(Other.Data, Other.Kind, Other.Index);
0186 }
0187
0188 bool operator<(const ConstructionContextItem &Other) const {
0189 return std::make_tuple(Data, Kind, Index) <
0190 std::make_tuple(Other.Data, Other.Kind, Other.Index);
0191 }
0192 };
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213 class ConstructionContextLayer {
0214 const ConstructionContextLayer *Parent = nullptr;
0215 ConstructionContextItem Item;
0216
0217 ConstructionContextLayer(ConstructionContextItem Item,
0218 const ConstructionContextLayer *Parent)
0219 : Parent(Parent), Item(Item) {}
0220
0221 public:
0222 static const ConstructionContextLayer *
0223 create(BumpVectorContext &C, const ConstructionContextItem &Item,
0224 const ConstructionContextLayer *Parent = nullptr);
0225
0226 const ConstructionContextItem &getItem() const { return Item; }
0227 const ConstructionContextLayer *getParent() const { return Parent; }
0228 bool isLast() const { return !Parent; }
0229
0230
0231
0232
0233
0234
0235 bool isStrictlyMoreSpecificThan(const ConstructionContextLayer *Other) const;
0236 };
0237
0238
0239
0240
0241
0242
0243 class ConstructionContext {
0244 public:
0245 enum Kind {
0246 SimpleVariableKind,
0247 CXX17ElidedCopyVariableKind,
0248 VARIABLE_BEGIN = SimpleVariableKind,
0249 VARIABLE_END = CXX17ElidedCopyVariableKind,
0250 SimpleConstructorInitializerKind,
0251 CXX17ElidedCopyConstructorInitializerKind,
0252 INITIALIZER_BEGIN = SimpleConstructorInitializerKind,
0253 INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind,
0254 NewAllocatedObjectKind,
0255 SimpleTemporaryObjectKind,
0256 ElidedTemporaryObjectKind,
0257 TEMPORARY_BEGIN = SimpleTemporaryObjectKind,
0258 TEMPORARY_END = ElidedTemporaryObjectKind,
0259 SimpleReturnedValueKind,
0260 CXX17ElidedCopyReturnedValueKind,
0261 RETURNED_VALUE_BEGIN = SimpleReturnedValueKind,
0262 RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind,
0263 ArgumentKind,
0264 LambdaCaptureKind
0265 };
0266
0267 protected:
0268 Kind K;
0269
0270
0271
0272 explicit ConstructionContext(Kind K) : K(K) {}
0273
0274 private:
0275
0276 template <typename T, typename... ArgTypes>
0277 static T *create(BumpVectorContext &C, ArgTypes... Args) {
0278 auto *CC = C.getAllocator().Allocate<T>();
0279 return new (CC) T(Args...);
0280 }
0281
0282
0283
0284
0285 static const ConstructionContext *createMaterializedTemporaryFromLayers(
0286 BumpVectorContext &C, const MaterializeTemporaryExpr *MTE,
0287 const CXXBindTemporaryExpr *BTE,
0288 const ConstructionContextLayer *ParentLayer);
0289
0290
0291
0292
0293
0294 static const ConstructionContext *
0295 createBoundTemporaryFromLayers(
0296 BumpVectorContext &C, const CXXBindTemporaryExpr *BTE,
0297 const ConstructionContextLayer *ParentLayer);
0298
0299 public:
0300
0301
0302
0303 static const ConstructionContext *
0304 createFromLayers(BumpVectorContext &C,
0305 const ConstructionContextLayer *TopLayer);
0306
0307 Kind getKind() const { return K; }
0308
0309 virtual const ArrayInitLoopExpr *getArrayInitLoop() const { return nullptr; }
0310
0311
0312 virtual ~ConstructionContext() = default;
0313 };
0314
0315
0316 class VariableConstructionContext : public ConstructionContext {
0317 const DeclStmt *DS;
0318
0319 protected:
0320 VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS)
0321 : ConstructionContext(K), DS(DS) {
0322 assert(classof(this));
0323 assert(DS);
0324 }
0325
0326 public:
0327 const DeclStmt *getDeclStmt() const { return DS; }
0328
0329 const ArrayInitLoopExpr *getArrayInitLoop() const override {
0330 const auto *Var = cast<VarDecl>(DS->getSingleDecl());
0331
0332 return dyn_cast<ArrayInitLoopExpr>(Var->getInit());
0333 }
0334
0335 static bool classof(const ConstructionContext *CC) {
0336 return CC->getKind() >= VARIABLE_BEGIN &&
0337 CC->getKind() <= VARIABLE_END;
0338 }
0339 };
0340
0341
0342
0343
0344
0345 class SimpleVariableConstructionContext : public VariableConstructionContext {
0346 friend class ConstructionContext;
0347
0348 explicit SimpleVariableConstructionContext(const DeclStmt *DS)
0349 : VariableConstructionContext(ConstructionContext::SimpleVariableKind,
0350 DS) {}
0351
0352 public:
0353 static bool classof(const ConstructionContext *CC) {
0354 return CC->getKind() == SimpleVariableKind;
0355 }
0356 };
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367 class CXX17ElidedCopyVariableConstructionContext
0368 : public VariableConstructionContext {
0369 const CXXBindTemporaryExpr *BTE;
0370
0371 friend class ConstructionContext;
0372
0373 explicit CXX17ElidedCopyVariableConstructionContext(
0374 const DeclStmt *DS, const CXXBindTemporaryExpr *BTE)
0375 : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) {
0376 assert(BTE);
0377 }
0378
0379 public:
0380 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
0381
0382 static bool classof(const ConstructionContext *CC) {
0383 return CC->getKind() == CXX17ElidedCopyVariableKind;
0384 }
0385 };
0386
0387
0388 class ConstructorInitializerConstructionContext : public ConstructionContext {
0389 const CXXCtorInitializer *I;
0390
0391 protected:
0392 explicit ConstructorInitializerConstructionContext(
0393 ConstructionContext::Kind K, const CXXCtorInitializer *I)
0394 : ConstructionContext(K), I(I) {
0395 assert(classof(this));
0396 assert(I);
0397 }
0398
0399 public:
0400 const CXXCtorInitializer *getCXXCtorInitializer() const { return I; }
0401
0402 const ArrayInitLoopExpr *getArrayInitLoop() const override {
0403 return dyn_cast<ArrayInitLoopExpr>(I->getInit());
0404 }
0405
0406 static bool classof(const ConstructionContext *CC) {
0407 return CC->getKind() >= INITIALIZER_BEGIN &&
0408 CC->getKind() <= INITIALIZER_END;
0409 }
0410 };
0411
0412
0413
0414 class SimpleConstructorInitializerConstructionContext
0415 : public ConstructorInitializerConstructionContext {
0416 friend class ConstructionContext;
0417
0418 explicit SimpleConstructorInitializerConstructionContext(
0419 const CXXCtorInitializer *I)
0420 : ConstructorInitializerConstructionContext(
0421 ConstructionContext::SimpleConstructorInitializerKind, I) {}
0422
0423 public:
0424 static bool classof(const ConstructionContext *CC) {
0425 return CC->getKind() == SimpleConstructorInitializerKind;
0426 }
0427 };
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439 class CXX17ElidedCopyConstructorInitializerConstructionContext
0440 : public ConstructorInitializerConstructionContext {
0441 const CXXBindTemporaryExpr *BTE;
0442
0443 friend class ConstructionContext;
0444
0445 explicit CXX17ElidedCopyConstructorInitializerConstructionContext(
0446 const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE)
0447 : ConstructorInitializerConstructionContext(
0448 CXX17ElidedCopyConstructorInitializerKind, I),
0449 BTE(BTE) {
0450 assert(BTE);
0451 }
0452
0453 public:
0454 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
0455
0456 static bool classof(const ConstructionContext *CC) {
0457 return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind;
0458 }
0459 };
0460
0461
0462
0463 class NewAllocatedObjectConstructionContext : public ConstructionContext {
0464 const CXXNewExpr *NE;
0465
0466 friend class ConstructionContext;
0467
0468 explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE)
0469 : ConstructionContext(ConstructionContext::NewAllocatedObjectKind),
0470 NE(NE) {
0471 assert(NE);
0472 }
0473
0474 public:
0475 const CXXNewExpr *getCXXNewExpr() const { return NE; }
0476
0477 static bool classof(const ConstructionContext *CC) {
0478 return CC->getKind() == NewAllocatedObjectKind;
0479 }
0480 };
0481
0482
0483
0484
0485
0486 class TemporaryObjectConstructionContext : public ConstructionContext {
0487 const CXXBindTemporaryExpr *BTE;
0488 const MaterializeTemporaryExpr *MTE;
0489
0490 protected:
0491 explicit TemporaryObjectConstructionContext(
0492 ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE,
0493 const MaterializeTemporaryExpr *MTE)
0494 : ConstructionContext(K), BTE(BTE), MTE(MTE) {
0495
0496
0497
0498
0499 }
0500
0501 public:
0502
0503
0504 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const {
0505 return BTE;
0506 }
0507
0508
0509
0510
0511
0512
0513 const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const {
0514 return MTE;
0515 }
0516
0517 static bool classof(const ConstructionContext *CC) {
0518 return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END;
0519 }
0520 };
0521
0522
0523
0524
0525
0526 class SimpleTemporaryObjectConstructionContext
0527 : public TemporaryObjectConstructionContext {
0528 friend class ConstructionContext;
0529
0530 explicit SimpleTemporaryObjectConstructionContext(
0531 const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE)
0532 : TemporaryObjectConstructionContext(
0533 ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {}
0534
0535 public:
0536 static bool classof(const ConstructionContext *CC) {
0537 return CC->getKind() == SimpleTemporaryObjectKind;
0538 }
0539 };
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549 class ElidedTemporaryObjectConstructionContext
0550 : public TemporaryObjectConstructionContext {
0551 const CXXConstructExpr *ElidedCE;
0552 const ConstructionContext *ElidedCC;
0553
0554 friend class ConstructionContext;
0555
0556 explicit ElidedTemporaryObjectConstructionContext(
0557 const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE,
0558 const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC)
0559 : TemporaryObjectConstructionContext(
0560 ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE),
0561 ElidedCE(ElidedCE), ElidedCC(ElidedCC) {
0562
0563
0564
0565 assert(ElidedCE && ElidedCE->isElidable() && ElidedCC);
0566 }
0567
0568 public:
0569 const CXXConstructExpr *getConstructorAfterElision() const {
0570 return ElidedCE;
0571 }
0572
0573 const ConstructionContext *getConstructionContextAfterElision() const {
0574 return ElidedCC;
0575 }
0576
0577 static bool classof(const ConstructionContext *CC) {
0578 return CC->getKind() == ElidedTemporaryObjectKind;
0579 }
0580 };
0581
0582 class ReturnedValueConstructionContext : public ConstructionContext {
0583 const ReturnStmt *RS;
0584
0585 protected:
0586 explicit ReturnedValueConstructionContext(ConstructionContext::Kind K,
0587 const ReturnStmt *RS)
0588 : ConstructionContext(K), RS(RS) {
0589 assert(classof(this));
0590 assert(RS);
0591 }
0592
0593 public:
0594 const ReturnStmt *getReturnStmt() const { return RS; }
0595
0596 static bool classof(const ConstructionContext *CC) {
0597 return CC->getKind() >= RETURNED_VALUE_BEGIN &&
0598 CC->getKind() <= RETURNED_VALUE_END;
0599 }
0600 };
0601
0602
0603
0604
0605
0606
0607 class SimpleReturnedValueConstructionContext
0608 : public ReturnedValueConstructionContext {
0609 friend class ConstructionContext;
0610
0611 explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS)
0612 : ReturnedValueConstructionContext(
0613 ConstructionContext::SimpleReturnedValueKind, RS) {}
0614
0615 public:
0616 static bool classof(const ConstructionContext *CC) {
0617 return CC->getKind() == SimpleReturnedValueKind;
0618 }
0619 };
0620
0621
0622
0623
0624
0625
0626
0627
0628
0629 class CXX17ElidedCopyReturnedValueConstructionContext
0630 : public ReturnedValueConstructionContext {
0631 const CXXBindTemporaryExpr *BTE;
0632
0633 friend class ConstructionContext;
0634
0635 explicit CXX17ElidedCopyReturnedValueConstructionContext(
0636 const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE)
0637 : ReturnedValueConstructionContext(
0638 ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS),
0639 BTE(BTE) {
0640 assert(BTE);
0641 }
0642
0643 public:
0644 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
0645
0646 static bool classof(const ConstructionContext *CC) {
0647 return CC->getKind() == CXX17ElidedCopyReturnedValueKind;
0648 }
0649 };
0650
0651 class ArgumentConstructionContext : public ConstructionContext {
0652
0653 const Expr *CE;
0654
0655
0656
0657
0658 unsigned Index;
0659
0660
0661 const CXXBindTemporaryExpr *BTE;
0662
0663 friend class ConstructionContext;
0664
0665 explicit ArgumentConstructionContext(const Expr *CE, unsigned Index,
0666 const CXXBindTemporaryExpr *BTE)
0667 : ConstructionContext(ArgumentKind), CE(CE),
0668 Index(Index), BTE(BTE) {
0669 assert(isa<CallExpr>(CE) || isa<CXXConstructExpr>(CE) ||
0670 isa<ObjCMessageExpr>(CE));
0671
0672 }
0673
0674 public:
0675 const Expr *getCallLikeExpr() const { return CE; }
0676 unsigned getIndex() const { return Index; }
0677 const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; }
0678
0679 static bool classof(const ConstructionContext *CC) {
0680 return CC->getKind() == ArgumentKind;
0681 }
0682 };
0683
0684 class LambdaCaptureConstructionContext : public ConstructionContext {
0685
0686 const LambdaExpr *LE;
0687
0688
0689 unsigned Index;
0690
0691 friend class ConstructionContext;
0692
0693 explicit LambdaCaptureConstructionContext(const LambdaExpr *LE,
0694 unsigned Index)
0695 : ConstructionContext(LambdaCaptureKind), LE(LE), Index(Index) {}
0696
0697 public:
0698 const LambdaExpr *getLambdaExpr() const { return LE; }
0699 unsigned getIndex() const { return Index; }
0700
0701 const Expr *getInitializer() const {
0702 return *(LE->capture_init_begin() + Index);
0703 }
0704
0705 const FieldDecl *getFieldDecl() const {
0706 auto It = LE->getLambdaClass()->field_begin();
0707 std::advance(It, Index);
0708 return *It;
0709 }
0710
0711 const ArrayInitLoopExpr *getArrayInitLoop() const override {
0712 return dyn_cast_or_null<ArrayInitLoopExpr>(getInitializer());
0713 }
0714
0715 static bool classof(const ConstructionContext *CC) {
0716 return CC->getKind() == LambdaCaptureKind;
0717 }
0718 };
0719
0720 }
0721
0722 #endif