File indexing completed on 2026-05-10 08:37:01
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_SEMA_SCOPEINFO_H
0015 #define LLVM_CLANG_SEMA_SCOPEINFO_H
0016
0017 #include "clang/AST/Expr.h"
0018 #include "clang/AST/ExprCXX.h"
0019 #include "clang/AST/Type.h"
0020 #include "clang/Basic/CapturedStmt.h"
0021 #include "clang/Basic/LLVM.h"
0022 #include "clang/Basic/PartialDiagnostic.h"
0023 #include "clang/Basic/SourceLocation.h"
0024 #include "clang/Sema/CleanupInfo.h"
0025 #include "clang/Sema/DeclSpec.h"
0026 #include "llvm/ADT/DenseMap.h"
0027 #include "llvm/ADT/DenseMapInfo.h"
0028 #include "llvm/ADT/MapVector.h"
0029 #include "llvm/ADT/PointerIntPair.h"
0030 #include "llvm/ADT/SmallPtrSet.h"
0031 #include "llvm/ADT/SmallSet.h"
0032 #include "llvm/ADT/SmallVector.h"
0033 #include "llvm/ADT/StringRef.h"
0034 #include "llvm/ADT/StringSwitch.h"
0035 #include "llvm/ADT/TinyPtrVector.h"
0036 #include "llvm/Support/Casting.h"
0037 #include "llvm/Support/ErrorHandling.h"
0038 #include <algorithm>
0039 #include <cassert>
0040 #include <utility>
0041
0042 namespace clang {
0043
0044 class BlockDecl;
0045 class CapturedDecl;
0046 class CXXMethodDecl;
0047 class CXXRecordDecl;
0048 class ImplicitParamDecl;
0049 class NamedDecl;
0050 class ObjCIvarRefExpr;
0051 class ObjCMessageExpr;
0052 class ObjCPropertyDecl;
0053 class ObjCPropertyRefExpr;
0054 class ParmVarDecl;
0055 class RecordDecl;
0056 class ReturnStmt;
0057 class Scope;
0058 class Stmt;
0059 class SwitchStmt;
0060 class TemplateParameterList;
0061 class VarDecl;
0062
0063 namespace sema {
0064
0065
0066
0067 class CompoundScopeInfo {
0068 public:
0069
0070
0071 bool HasEmptyLoopBodies = false;
0072
0073
0074
0075 bool IsStmtExpr;
0076
0077
0078
0079 FPOptions InitialFPFeatures;
0080
0081 CompoundScopeInfo(bool IsStmtExpr, FPOptions FPO)
0082 : IsStmtExpr(IsStmtExpr), InitialFPFeatures(FPO) {}
0083
0084 void setHasEmptyLoopBodies() {
0085 HasEmptyLoopBodies = true;
0086 }
0087 };
0088
0089 class PossiblyUnreachableDiag {
0090 public:
0091 PartialDiagnostic PD;
0092 SourceLocation Loc;
0093 llvm::TinyPtrVector<const Stmt*> Stmts;
0094
0095 PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc,
0096 ArrayRef<const Stmt *> Stmts)
0097 : PD(PD), Loc(Loc), Stmts(Stmts) {}
0098 };
0099
0100 enum class FirstCoroutineStmtKind { CoReturn, CoAwait, CoYield };
0101
0102
0103
0104 class FunctionScopeInfo {
0105 protected:
0106 enum ScopeKind {
0107 SK_Function,
0108 SK_Block,
0109 SK_Lambda,
0110 SK_CapturedRegion
0111 };
0112
0113 public:
0114
0115 ScopeKind Kind : 3;
0116
0117
0118
0119 bool HasBranchProtectedScope : 1;
0120
0121
0122 bool HasBranchIntoScope : 1;
0123
0124
0125 bool HasIndirectGoto : 1;
0126
0127
0128
0129 bool HasMustTail : 1;
0130
0131
0132 bool HasDroppedStmt : 1;
0133
0134
0135 bool HasOMPDeclareReductionCombiner : 1;
0136
0137
0138 bool HasFallthroughStmt : 1;
0139
0140
0141 bool UsesFPIntrin : 1;
0142
0143
0144
0145 bool HasPotentialAvailabilityViolations : 1;
0146
0147
0148
0149
0150 bool ObjCShouldCallSuper : 1;
0151
0152
0153 bool ObjCIsDesignatedInit : 1;
0154
0155
0156
0157
0158 bool ObjCWarnForNoDesignatedInitChain : 1;
0159
0160
0161
0162
0163 bool ObjCIsSecondaryInit : 1;
0164
0165
0166
0167 bool ObjCWarnForNoInitDelegation : 1;
0168
0169
0170
0171 bool NeedsCoroutineSuspends : 1;
0172
0173
0174
0175 LLVM_PREFERRED_TYPE(FirstCoroutineStmtKind)
0176 unsigned char FirstCoroutineStmtKind : 2;
0177
0178
0179 bool FoundImmediateEscalatingExpression : 1;
0180
0181
0182
0183 SourceLocation FirstCoroutineStmtLoc;
0184
0185
0186 SourceLocation FirstReturnLoc;
0187
0188
0189 SourceLocation FirstCXXOrObjCTryLoc;
0190 enum { TryLocIsCXX, TryLocIsObjC, Unknown } FirstTryType = Unknown;
0191
0192
0193 SourceLocation FirstSEHTryLoc;
0194
0195
0196 SourceLocation FirstVLALoc;
0197
0198 private:
0199
0200 DiagnosticErrorTrap ErrorTrap;
0201
0202 public:
0203
0204
0205 using SwitchInfo = llvm::PointerIntPair<SwitchStmt*, 1, bool>;
0206
0207
0208
0209 SmallVector<SwitchInfo, 8> SwitchStack;
0210
0211
0212
0213
0214 SmallVector<ReturnStmt*, 4> Returns;
0215
0216
0217 VarDecl *CoroutinePromise = nullptr;
0218
0219
0220
0221 llvm::SmallMapVector<ParmVarDecl *, Stmt *, 4> CoroutineParameterMoves;
0222
0223
0224 std::pair<Stmt *, Stmt *> CoroutineSuspends;
0225
0226
0227
0228 SmallVector<CompoundScopeInfo, 4> CompoundScopes;
0229
0230
0231 llvm::SmallPtrSet<const BlockDecl *, 1> Blocks;
0232
0233
0234 llvm::TinyPtrVector<VarDecl *> ByrefBlockVars;
0235
0236
0237
0238
0239 SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags;
0240
0241
0242
0243 llvm::SmallPtrSet<const ParmVarDecl *, 8> ModifiedNonNullParams;
0244
0245
0246 llvm::SmallVector<AddrLabelExpr *, 4> AddrLabels;
0247
0248 public:
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271 class WeakObjectProfileTy {
0272
0273
0274
0275
0276
0277
0278 using BaseInfoTy = llvm::PointerIntPair<const NamedDecl *, 1, bool>;
0279 BaseInfoTy Base;
0280
0281
0282
0283
0284
0285 const NamedDecl *Property = nullptr;
0286
0287
0288 static BaseInfoTy getBaseInfo(const Expr *BaseE);
0289
0290 inline WeakObjectProfileTy();
0291 static inline WeakObjectProfileTy getSentinel();
0292
0293 public:
0294 WeakObjectProfileTy(const ObjCPropertyRefExpr *RE);
0295 WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property);
0296 WeakObjectProfileTy(const DeclRefExpr *RE);
0297 WeakObjectProfileTy(const ObjCIvarRefExpr *RE);
0298
0299 const NamedDecl *getBase() const { return Base.getPointer(); }
0300 const NamedDecl *getProperty() const { return Property; }
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313 bool isExactProfile() const {
0314 return Base.getInt();
0315 }
0316
0317 bool operator==(const WeakObjectProfileTy &Other) const {
0318 return Base == Other.Base && Property == Other.Property;
0319 }
0320
0321
0322
0323
0324
0325 class DenseMapInfo {
0326 public:
0327 static inline WeakObjectProfileTy getEmptyKey() {
0328 return WeakObjectProfileTy();
0329 }
0330
0331 static inline WeakObjectProfileTy getTombstoneKey() {
0332 return WeakObjectProfileTy::getSentinel();
0333 }
0334
0335 static unsigned getHashValue(const WeakObjectProfileTy &Val) {
0336 using Pair = std::pair<BaseInfoTy, const NamedDecl *>;
0337
0338 return llvm::DenseMapInfo<Pair>::getHashValue(Pair(Val.Base,
0339 Val.Property));
0340 }
0341
0342 static bool isEqual(const WeakObjectProfileTy &LHS,
0343 const WeakObjectProfileTy &RHS) {
0344 return LHS == RHS;
0345 }
0346 };
0347 };
0348
0349
0350
0351
0352
0353
0354
0355 class WeakUseTy {
0356 llvm::PointerIntPair<const Expr *, 1, bool> Rep;
0357
0358 public:
0359 WeakUseTy(const Expr *Use, bool IsRead) : Rep(Use, IsRead) {}
0360
0361 const Expr *getUseExpr() const { return Rep.getPointer(); }
0362 bool isUnsafe() const { return Rep.getInt(); }
0363 void markSafe() { Rep.setInt(false); }
0364
0365 bool operator==(const WeakUseTy &Other) const {
0366 return Rep == Other.Rep;
0367 }
0368 };
0369
0370
0371
0372
0373 using WeakUseVector = SmallVector<WeakUseTy, 4>;
0374
0375
0376
0377
0378 using WeakObjectUseMap =
0379 llvm::SmallDenseMap<WeakObjectProfileTy, WeakUseVector, 8,
0380 WeakObjectProfileTy::DenseMapInfo>;
0381
0382 private:
0383
0384
0385
0386 WeakObjectUseMap WeakObjectUses;
0387
0388 protected:
0389 FunctionScopeInfo(const FunctionScopeInfo&) = default;
0390
0391 public:
0392 FunctionScopeInfo(DiagnosticsEngine &Diag)
0393 : Kind(SK_Function), HasBranchProtectedScope(false),
0394 HasBranchIntoScope(false), HasIndirectGoto(false), HasMustTail(false),
0395 HasDroppedStmt(false), HasOMPDeclareReductionCombiner(false),
0396 HasFallthroughStmt(false), UsesFPIntrin(false),
0397 HasPotentialAvailabilityViolations(false), ObjCShouldCallSuper(false),
0398 ObjCIsDesignatedInit(false), ObjCWarnForNoDesignatedInitChain(false),
0399 ObjCIsSecondaryInit(false), ObjCWarnForNoInitDelegation(false),
0400 NeedsCoroutineSuspends(true), FoundImmediateEscalatingExpression(false),
0401 ErrorTrap(Diag) {}
0402
0403 virtual ~FunctionScopeInfo();
0404
0405
0406
0407
0408
0409
0410
0411
0412 bool hasUnrecoverableErrorOccurred() const {
0413 return ErrorTrap.hasUnrecoverableErrorOccurred();
0414 }
0415
0416
0417
0418
0419 template <typename ExprT>
0420 inline void recordUseOfWeak(const ExprT *E, bool IsRead = true);
0421
0422 void recordUseOfWeak(const ObjCMessageExpr *Msg,
0423 const ObjCPropertyDecl *Prop);
0424
0425
0426
0427
0428
0429 void markSafeWeakUse(const Expr *E);
0430
0431 const WeakObjectUseMap &getWeakObjectUses() const {
0432 return WeakObjectUses;
0433 }
0434
0435 void setHasBranchIntoScope() {
0436 HasBranchIntoScope = true;
0437 }
0438
0439 void setHasBranchProtectedScope() {
0440 HasBranchProtectedScope = true;
0441 }
0442
0443 void setHasIndirectGoto() {
0444 HasIndirectGoto = true;
0445 }
0446
0447 void setHasMustTail() { HasMustTail = true; }
0448
0449 void setHasDroppedStmt() {
0450 HasDroppedStmt = true;
0451 }
0452
0453 void setHasOMPDeclareReductionCombiner() {
0454 HasOMPDeclareReductionCombiner = true;
0455 }
0456
0457 void setHasFallthroughStmt() {
0458 HasFallthroughStmt = true;
0459 }
0460
0461 void setUsesFPIntrin() {
0462 UsesFPIntrin = true;
0463 }
0464
0465 void setHasCXXTry(SourceLocation TryLoc) {
0466 setHasBranchProtectedScope();
0467 FirstCXXOrObjCTryLoc = TryLoc;
0468 FirstTryType = TryLocIsCXX;
0469 }
0470
0471 void setHasObjCTry(SourceLocation TryLoc) {
0472 setHasBranchProtectedScope();
0473 FirstCXXOrObjCTryLoc = TryLoc;
0474 FirstTryType = TryLocIsObjC;
0475 }
0476
0477 void setHasSEHTry(SourceLocation TryLoc) {
0478 setHasBranchProtectedScope();
0479 FirstSEHTryLoc = TryLoc;
0480 }
0481
0482 void setHasVLA(SourceLocation VLALoc) {
0483 if (FirstVLALoc.isInvalid())
0484 FirstVLALoc = VLALoc;
0485 }
0486
0487 bool NeedsScopeChecking() const {
0488 return !HasDroppedStmt && (HasIndirectGoto || HasMustTail ||
0489 (HasBranchProtectedScope && HasBranchIntoScope));
0490 }
0491
0492
0493 void addBlock(const BlockDecl *BD) {
0494 Blocks.insert(BD);
0495 }
0496
0497
0498 void addByrefBlockVar(VarDecl *VD) {
0499 ByrefBlockVars.push_back(VD);
0500 }
0501
0502 bool isCoroutine() const { return !FirstCoroutineStmtLoc.isInvalid(); }
0503
0504 void setFirstCoroutineStmt(SourceLocation Loc, StringRef Keyword) {
0505 assert(FirstCoroutineStmtLoc.isInvalid() &&
0506 "first coroutine statement location already set");
0507 FirstCoroutineStmtLoc = Loc;
0508 FirstCoroutineStmtKind =
0509 llvm::StringSwitch<unsigned char>(Keyword)
0510 .Case("co_return",
0511 llvm::to_underlying(FirstCoroutineStmtKind::CoReturn))
0512 .Case("co_await",
0513 llvm::to_underlying(FirstCoroutineStmtKind::CoAwait))
0514 .Case("co_yield",
0515 llvm::to_underlying(FirstCoroutineStmtKind::CoYield));
0516 }
0517
0518 StringRef getFirstCoroutineStmtKeyword() const {
0519 assert(FirstCoroutineStmtLoc.isValid()
0520 && "no coroutine statement available");
0521 auto Value =
0522 static_cast<enum FirstCoroutineStmtKind>(FirstCoroutineStmtKind);
0523 switch (Value) {
0524 case FirstCoroutineStmtKind::CoReturn:
0525 return "co_return";
0526 case FirstCoroutineStmtKind::CoAwait:
0527 return "co_await";
0528 case FirstCoroutineStmtKind::CoYield:
0529 return "co_yield";
0530 };
0531 llvm_unreachable("FirstCoroutineStmtKind has an invalid value");
0532 }
0533
0534 void setNeedsCoroutineSuspends(bool value = true) {
0535 assert((!value || CoroutineSuspends.first == nullptr) &&
0536 "we already have valid suspend points");
0537 NeedsCoroutineSuspends = value;
0538 }
0539
0540 bool hasInvalidCoroutineSuspends() const {
0541 return !NeedsCoroutineSuspends && CoroutineSuspends.first == nullptr;
0542 }
0543
0544 void setCoroutineSuspends(Stmt *Initial, Stmt *Final) {
0545 assert(Initial && Final && "suspend points cannot be null");
0546 assert(CoroutineSuspends.first == nullptr && "suspend points already set");
0547 NeedsCoroutineSuspends = false;
0548 CoroutineSuspends.first = Initial;
0549 CoroutineSuspends.second = Final;
0550 }
0551
0552
0553
0554 void Clear();
0555
0556 bool isPlainFunction() const { return Kind == SK_Function; }
0557 };
0558
0559 class Capture {
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573 enum CaptureKind {
0574 Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA
0575 };
0576
0577 union {
0578
0579 const VariableArrayType *CapturedVLA;
0580
0581
0582 ValueDecl *CapturedVar;
0583 };
0584
0585
0586 SourceLocation Loc;
0587
0588
0589 SourceLocation EllipsisLoc;
0590
0591
0592
0593 QualType CaptureType;
0594
0595
0596 LLVM_PREFERRED_TYPE(CaptureKind)
0597 unsigned Kind : 2;
0598
0599
0600
0601 LLVM_PREFERRED_TYPE(bool)
0602 unsigned Nested : 1;
0603
0604
0605 LLVM_PREFERRED_TYPE(bool)
0606 unsigned CapturesThis : 1;
0607
0608
0609
0610 LLVM_PREFERRED_TYPE(bool)
0611 unsigned ODRUsed : 1;
0612
0613
0614
0615 LLVM_PREFERRED_TYPE(bool)
0616 unsigned NonODRUsed : 1;
0617
0618
0619
0620 LLVM_PREFERRED_TYPE(bool)
0621 unsigned Invalid : 1;
0622
0623 public:
0624 Capture(ValueDecl *Var, bool Block, bool ByRef, bool IsNested,
0625 SourceLocation Loc, SourceLocation EllipsisLoc, QualType CaptureType,
0626 bool Invalid)
0627 : CapturedVar(Var), Loc(Loc), EllipsisLoc(EllipsisLoc),
0628 CaptureType(CaptureType), Kind(Block ? Cap_Block
0629 : ByRef ? Cap_ByRef
0630 : Cap_ByCopy),
0631 Nested(IsNested), CapturesThis(false), ODRUsed(false),
0632 NonODRUsed(false), Invalid(Invalid) {}
0633
0634 enum IsThisCapture { ThisCapture };
0635 Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
0636 QualType CaptureType, const bool ByCopy, bool Invalid)
0637 : Loc(Loc), CaptureType(CaptureType),
0638 Kind(ByCopy ? Cap_ByCopy : Cap_ByRef), Nested(IsNested),
0639 CapturesThis(true), ODRUsed(false), NonODRUsed(false),
0640 Invalid(Invalid) {}
0641
0642 enum IsVLACapture { VLACapture };
0643 Capture(IsVLACapture, const VariableArrayType *VLA, bool IsNested,
0644 SourceLocation Loc, QualType CaptureType)
0645 : CapturedVLA(VLA), Loc(Loc), CaptureType(CaptureType), Kind(Cap_VLA),
0646 Nested(IsNested), CapturesThis(false), ODRUsed(false),
0647 NonODRUsed(false), Invalid(false) {}
0648
0649 bool isThisCapture() const { return CapturesThis; }
0650 bool isVariableCapture() const {
0651 return !isThisCapture() && !isVLATypeCapture();
0652 }
0653
0654 bool isCopyCapture() const { return Kind == Cap_ByCopy; }
0655 bool isReferenceCapture() const { return Kind == Cap_ByRef; }
0656 bool isBlockCapture() const { return Kind == Cap_Block; }
0657 bool isVLATypeCapture() const { return Kind == Cap_VLA; }
0658
0659 bool isNested() const { return Nested; }
0660
0661 bool isInvalid() const { return Invalid; }
0662
0663
0664 bool isInitCapture() const;
0665
0666 bool isODRUsed() const { return ODRUsed; }
0667 bool isNonODRUsed() const { return NonODRUsed; }
0668 void markUsed(bool IsODRUse) {
0669 if (IsODRUse)
0670 ODRUsed = true;
0671 else
0672 NonODRUsed = true;
0673 }
0674
0675 ValueDecl *getVariable() const {
0676 assert(isVariableCapture());
0677 return CapturedVar;
0678 }
0679
0680 const VariableArrayType *getCapturedVLAType() const {
0681 assert(isVLATypeCapture());
0682 return CapturedVLA;
0683 }
0684
0685
0686 SourceLocation getLocation() const { return Loc; }
0687
0688
0689
0690 SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
0691
0692
0693
0694
0695 QualType getCaptureType() const { return CaptureType; }
0696 };
0697
0698 class CapturingScopeInfo : public FunctionScopeInfo {
0699 protected:
0700 CapturingScopeInfo(const CapturingScopeInfo&) = default;
0701
0702 public:
0703 enum ImplicitCaptureStyle {
0704 ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block,
0705 ImpCap_CapturedRegion
0706 };
0707
0708 ImplicitCaptureStyle ImpCaptureStyle;
0709
0710 CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style)
0711 : FunctionScopeInfo(Diag), ImpCaptureStyle(Style) {}
0712
0713
0714 llvm::DenseMap<ValueDecl *, unsigned> CaptureMap;
0715
0716
0717
0718 unsigned CXXThisCaptureIndex = 0;
0719
0720
0721 SmallVector<Capture, 4> Captures;
0722
0723
0724
0725 bool HasImplicitReturnType = false;
0726
0727
0728 bool ContainsUnexpandedParameterPack = false;
0729
0730
0731
0732 QualType ReturnType;
0733
0734
0735 SmallVector<NamedDecl *, 4> LocalPacks;
0736
0737 void addCapture(ValueDecl *Var, bool isBlock, bool isByref, bool isNested,
0738 SourceLocation Loc, SourceLocation EllipsisLoc,
0739 QualType CaptureType, bool Invalid) {
0740 Captures.push_back(Capture(Var, isBlock, isByref, isNested, Loc,
0741 EllipsisLoc, CaptureType, Invalid));
0742 CaptureMap[Var] = Captures.size();
0743 }
0744
0745 void addVLATypeCapture(SourceLocation Loc, const VariableArrayType *VLAType,
0746 QualType CaptureType) {
0747 Captures.push_back(Capture(Capture::VLACapture, VLAType,
0748 false, Loc, CaptureType));
0749 }
0750
0751 void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType,
0752 bool ByCopy);
0753
0754
0755 bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; }
0756
0757
0758 Capture &getCXXThisCapture() {
0759 assert(isCXXThisCaptured() && "this has not been captured");
0760 return Captures[CXXThisCaptureIndex - 1];
0761 }
0762
0763
0764 bool isCaptured(ValueDecl *Var) const { return CaptureMap.count(Var); }
0765
0766
0767 bool isVLATypeCaptured(const VariableArrayType *VAT) const;
0768
0769
0770
0771 Capture &getCapture(ValueDecl *Var) {
0772 assert(isCaptured(Var) && "Variable has not been captured");
0773 return Captures[CaptureMap[Var] - 1];
0774 }
0775
0776 const Capture &getCapture(ValueDecl *Var) const {
0777 llvm::DenseMap<ValueDecl *, unsigned>::const_iterator Known =
0778 CaptureMap.find(Var);
0779 assert(Known != CaptureMap.end() && "Variable has not been captured");
0780 return Captures[Known->second - 1];
0781 }
0782
0783 static bool classof(const FunctionScopeInfo *FSI) {
0784 return FSI->Kind == SK_Block || FSI->Kind == SK_Lambda
0785 || FSI->Kind == SK_CapturedRegion;
0786 }
0787 };
0788
0789
0790 class BlockScopeInfo final : public CapturingScopeInfo {
0791 public:
0792 BlockDecl *TheDecl;
0793
0794
0795
0796 Scope *TheScope;
0797
0798
0799
0800 QualType FunctionType;
0801
0802 BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block)
0803 : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block),
0804 TheScope(BlockScope) {
0805 Kind = SK_Block;
0806 }
0807
0808 ~BlockScopeInfo() override;
0809
0810 static bool classof(const FunctionScopeInfo *FSI) {
0811 return FSI->Kind == SK_Block;
0812 }
0813 };
0814
0815
0816 class CapturedRegionScopeInfo final : public CapturingScopeInfo {
0817 public:
0818
0819 CapturedDecl *TheCapturedDecl;
0820
0821
0822 RecordDecl *TheRecordDecl;
0823
0824
0825 Scope *TheScope;
0826
0827
0828 ImplicitParamDecl *ContextParam;
0829
0830
0831 unsigned short CapRegionKind;
0832
0833 unsigned short OpenMPLevel;
0834 unsigned short OpenMPCaptureLevel;
0835
0836 CapturedRegionScopeInfo(DiagnosticsEngine &Diag, Scope *S, CapturedDecl *CD,
0837 RecordDecl *RD, ImplicitParamDecl *Context,
0838 CapturedRegionKind K, unsigned OpenMPLevel,
0839 unsigned OpenMPCaptureLevel)
0840 : CapturingScopeInfo(Diag, ImpCap_CapturedRegion),
0841 TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S),
0842 ContextParam(Context), CapRegionKind(K), OpenMPLevel(OpenMPLevel),
0843 OpenMPCaptureLevel(OpenMPCaptureLevel) {
0844 Kind = SK_CapturedRegion;
0845 }
0846
0847 ~CapturedRegionScopeInfo() override;
0848
0849
0850 StringRef getRegionName() const {
0851 switch (CapRegionKind) {
0852 case CR_Default:
0853 return "default captured statement";
0854 case CR_ObjCAtFinally:
0855 return "Objective-C @finally statement";
0856 case CR_OpenMP:
0857 return "OpenMP region";
0858 }
0859 llvm_unreachable("Invalid captured region kind!");
0860 }
0861
0862 static bool classof(const FunctionScopeInfo *FSI) {
0863 return FSI->Kind == SK_CapturedRegion;
0864 }
0865 };
0866
0867 class LambdaScopeInfo final :
0868 public CapturingScopeInfo, public InventedTemplateParameterInfo {
0869 public:
0870
0871 CXXRecordDecl *Lambda = nullptr;
0872
0873
0874 CXXMethodDecl *CallOperator = nullptr;
0875
0876
0877
0878
0879 bool AfterParameterList = true;
0880
0881 ParmVarDecl *ExplicitObjectParameter = nullptr;
0882
0883
0884 SourceRange IntroducerRange;
0885
0886
0887
0888 SourceLocation CaptureDefaultLoc;
0889
0890
0891
0892 unsigned NumExplicitCaptures = 0;
0893
0894
0895
0896 bool Mutable = true;
0897
0898
0899 bool ExplicitParams = false;
0900
0901
0902 CleanupInfo Cleanup;
0903
0904
0905 SourceRange ExplicitTemplateParamsRange;
0906
0907
0908
0909
0910 ExprResult RequiresClause;
0911
0912
0913
0914
0915 TemplateParameterList *GLTemplateParameterList = nullptr;
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930 llvm::SmallVector<Expr*, 4> PotentiallyCapturingExprs;
0931
0932
0933
0934
0935
0936 llvm::SmallSet<Expr *, 8> NonODRUsedCapturingExprs;
0937
0938
0939 llvm::DenseMap<unsigned, SourceRange> ExplicitCaptureRanges;
0940
0941
0942
0943
0944 struct ShadowedOuterDecl {
0945 const NamedDecl *VD;
0946 const NamedDecl *ShadowedDecl;
0947 };
0948 llvm::SmallVector<ShadowedOuterDecl, 4> ShadowingDecls;
0949
0950 SourceLocation PotentialThisCaptureLocation;
0951
0952 LambdaScopeInfo(DiagnosticsEngine &Diag)
0953 : CapturingScopeInfo(Diag, ImpCap_None) {
0954 Kind = SK_Lambda;
0955 }
0956
0957
0958 void finishedExplicitCaptures() {
0959 NumExplicitCaptures = Captures.size();
0960 }
0961
0962 static bool classof(const FunctionScopeInfo *FSI) {
0963 return FSI->Kind == SK_Lambda;
0964 }
0965
0966
0967
0968 bool isGenericLambda() const {
0969 return !TemplateParams.empty() || GLTemplateParameterList;
0970 }
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989 void addPotentialCapture(Expr *VarExpr) {
0990 assert(isa<DeclRefExpr>(VarExpr) || isa<MemberExpr>(VarExpr) ||
0991 isa<FunctionParmPackExpr>(VarExpr));
0992 PotentiallyCapturingExprs.push_back(VarExpr);
0993 }
0994
0995 void addPotentialThisCapture(SourceLocation Loc) {
0996 PotentialThisCaptureLocation = Loc;
0997 }
0998
0999 bool hasPotentialThisCapture() const {
1000 return PotentialThisCaptureLocation.isValid();
1001 }
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042 void markVariableExprAsNonODRUsed(Expr *CapturingVarExpr) {
1043 assert(isa<DeclRefExpr>(CapturingVarExpr) ||
1044 isa<MemberExpr>(CapturingVarExpr) ||
1045 isa<FunctionParmPackExpr>(CapturingVarExpr));
1046 NonODRUsedCapturingExprs.insert(CapturingVarExpr);
1047 }
1048 bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) const {
1049 assert(isa<DeclRefExpr>(CapturingVarExpr) ||
1050 isa<MemberExpr>(CapturingVarExpr) ||
1051 isa<FunctionParmPackExpr>(CapturingVarExpr));
1052 return NonODRUsedCapturingExprs.count(CapturingVarExpr);
1053 }
1054 void removePotentialCapture(Expr *E) {
1055 llvm::erase(PotentiallyCapturingExprs, E);
1056 }
1057 void clearPotentialCaptures() {
1058 PotentiallyCapturingExprs.clear();
1059 PotentialThisCaptureLocation = SourceLocation();
1060 }
1061 unsigned getNumPotentialVariableCaptures() const {
1062 return PotentiallyCapturingExprs.size();
1063 }
1064
1065 bool hasPotentialCaptures() const {
1066 return getNumPotentialVariableCaptures() ||
1067 PotentialThisCaptureLocation.isValid();
1068 }
1069
1070 void visitPotentialCaptures(
1071 llvm::function_ref<void(ValueDecl *, Expr *)> Callback) const;
1072
1073 bool lambdaCaptureShouldBeConst() const;
1074 };
1075
1076 FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy()
1077 : Base(nullptr, false) {}
1078
1079 FunctionScopeInfo::WeakObjectProfileTy
1080 FunctionScopeInfo::WeakObjectProfileTy::getSentinel() {
1081 FunctionScopeInfo::WeakObjectProfileTy Result;
1082 Result.Base.setInt(true);
1083 return Result;
1084 }
1085
1086 template <typename ExprT>
1087 void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) {
1088 assert(E);
1089 WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)];
1090 Uses.push_back(WeakUseTy(E, IsRead));
1091 }
1092
1093 inline void CapturingScopeInfo::addThisCapture(bool isNested,
1094 SourceLocation Loc,
1095 QualType CaptureType,
1096 bool ByCopy) {
1097 Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType,
1098 ByCopy, false));
1099 CXXThisCaptureIndex = Captures.size();
1100 }
1101
1102 }
1103
1104 }
1105
1106 #endif