File indexing completed on 2026-05-10 08:37:01
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_CLANG_SEMA_SCOPE_H
0014 #define LLVM_CLANG_SEMA_SCOPE_H
0015
0016 #include "clang/AST/Decl.h"
0017 #include "clang/Basic/Diagnostic.h"
0018 #include "llvm/ADT/PointerIntPair.h"
0019 #include "llvm/ADT/SmallPtrSet.h"
0020 #include "llvm/ADT/SmallVector.h"
0021 #include "llvm/ADT/iterator_range.h"
0022 #include <cassert>
0023 #include <optional>
0024
0025 namespace llvm {
0026
0027 class raw_ostream;
0028
0029 }
0030
0031 namespace clang {
0032
0033 class Decl;
0034 class DeclContext;
0035 class UsingDirectiveDecl;
0036 class VarDecl;
0037
0038
0039
0040
0041 class Scope {
0042 public:
0043
0044
0045 enum ScopeFlags {
0046
0047 NoScope = 0,
0048
0049
0050
0051 FnScope = 0x01,
0052
0053
0054
0055 BreakScope = 0x02,
0056
0057
0058
0059 ContinueScope = 0x04,
0060
0061
0062
0063 DeclScope = 0x08,
0064
0065
0066 ControlScope = 0x10,
0067
0068
0069 ClassScope = 0x20,
0070
0071
0072
0073
0074
0075 BlockScope = 0x40,
0076
0077
0078
0079
0080
0081 TemplateParamScope = 0x80,
0082
0083
0084
0085 FunctionPrototypeScope = 0x100,
0086
0087
0088
0089
0090
0091 FunctionDeclarationScope = 0x200,
0092
0093
0094
0095 AtCatchScope = 0x400,
0096
0097
0098
0099 ObjCMethodScope = 0x800,
0100
0101
0102 SwitchScope = 0x1000,
0103
0104
0105 TryScope = 0x2000,
0106
0107
0108 FnTryCatchScope = 0x4000,
0109
0110
0111 OpenMPDirectiveScope = 0x8000,
0112
0113
0114 OpenMPLoopDirectiveScope = 0x10000,
0115
0116
0117
0118
0119 OpenMPSimdDirectiveScope = 0x20000,
0120
0121
0122 EnumScope = 0x40000,
0123
0124
0125 SEHTryScope = 0x80000,
0126
0127
0128 SEHExceptScope = 0x100000,
0129
0130
0131 SEHFilterScope = 0x200000,
0132
0133
0134 CompoundStmtScope = 0x400000,
0135
0136
0137
0138 ClassInheritanceScope = 0x800000,
0139
0140
0141 CatchScope = 0x1000000,
0142
0143
0144
0145
0146 ConditionVarScope = 0x2000000,
0147
0148
0149
0150 OpenMPOrderClauseScope = 0x4000000,
0151
0152
0153
0154
0155 LambdaScope = 0x8000000,
0156
0157
0158
0159 OpenACCComputeConstructScope = 0x10000000,
0160
0161
0162 TypeAliasScope = 0x20000000,
0163
0164
0165 FriendScope = 0x40000000,
0166 };
0167
0168 private:
0169
0170
0171 Scope *AnyParent;
0172
0173
0174
0175 unsigned Flags;
0176
0177
0178
0179 unsigned short Depth;
0180
0181
0182
0183 unsigned short MSLastManglingNumber;
0184
0185 unsigned short MSCurManglingNumber;
0186
0187
0188
0189 unsigned short PrototypeDepth;
0190
0191
0192
0193 unsigned short PrototypeIndex;
0194
0195
0196
0197 Scope *FnParent;
0198 Scope *MSLastManglingParent;
0199
0200
0201
0202
0203
0204 Scope *BreakParent, *ContinueParent;
0205
0206
0207
0208 Scope *BlockParent;
0209
0210
0211
0212
0213
0214 Scope *TemplateParamParent;
0215
0216
0217
0218 Scope *DeclParent;
0219
0220
0221
0222
0223
0224
0225
0226 using DeclSetTy = llvm::SmallPtrSet<Decl *, 32>;
0227 DeclSetTy DeclsInScope;
0228
0229
0230
0231
0232 DeclContext *Entity;
0233
0234 using UsingDirectivesTy = SmallVector<UsingDirectiveDecl *, 2>;
0235 UsingDirectivesTy UsingDirectives;
0236
0237
0238 DiagnosticErrorTrap ErrorTrap;
0239
0240
0241
0242
0243
0244
0245
0246
0247 std::optional<VarDecl *> NRVO;
0248
0249
0250
0251
0252 llvm::SmallPtrSet<VarDecl *, 8> ReturnSlots;
0253
0254 void setFlags(Scope *Parent, unsigned F);
0255
0256 public:
0257 Scope(Scope *Parent, unsigned ScopeFlags, DiagnosticsEngine &Diag)
0258 : ErrorTrap(Diag) {
0259 Init(Parent, ScopeFlags);
0260 }
0261
0262
0263 unsigned getFlags() const { return Flags; }
0264
0265 void setFlags(unsigned F) { setFlags(getParent(), F); }
0266
0267
0268 bool isBlockScope() const { return Flags & BlockScope; }
0269
0270
0271 const Scope *getParent() const { return AnyParent; }
0272 Scope *getParent() { return AnyParent; }
0273
0274
0275 const Scope *getFnParent() const { return FnParent; }
0276 Scope *getFnParent() { return FnParent; }
0277
0278 const Scope *getMSLastManglingParent() const {
0279 return MSLastManglingParent;
0280 }
0281 Scope *getMSLastManglingParent() { return MSLastManglingParent; }
0282
0283
0284
0285 Scope *getContinueParent() {
0286 return ContinueParent;
0287 }
0288
0289 const Scope *getContinueParent() const {
0290 return const_cast<Scope*>(this)->getContinueParent();
0291 }
0292
0293
0294
0295 void setIsConditionVarScope(bool InConditionVarScope) {
0296 Flags = (Flags & ~ConditionVarScope) |
0297 (InConditionVarScope ? ConditionVarScope : 0);
0298 }
0299
0300 bool isConditionVarScope() const {
0301 return Flags & ConditionVarScope;
0302 }
0303
0304
0305
0306 Scope *getBreakParent() {
0307 return BreakParent;
0308 }
0309 const Scope *getBreakParent() const {
0310 return const_cast<Scope*>(this)->getBreakParent();
0311 }
0312
0313 Scope *getBlockParent() { return BlockParent; }
0314 const Scope *getBlockParent() const { return BlockParent; }
0315
0316 Scope *getTemplateParamParent() { return TemplateParamParent; }
0317 const Scope *getTemplateParamParent() const { return TemplateParamParent; }
0318
0319 Scope *getDeclParent() { return DeclParent; }
0320 const Scope *getDeclParent() const { return DeclParent; }
0321
0322
0323 unsigned getDepth() const { return Depth; }
0324
0325
0326
0327 unsigned getFunctionPrototypeDepth() const {
0328 return PrototypeDepth;
0329 }
0330
0331
0332
0333 unsigned getNextFunctionPrototypeIndex() {
0334 assert(isFunctionPrototypeScope());
0335 return PrototypeIndex++;
0336 }
0337
0338 using decl_range = llvm::iterator_range<DeclSetTy::iterator>;
0339
0340 decl_range decls() const {
0341 return decl_range(DeclsInScope.begin(), DeclsInScope.end());
0342 }
0343
0344 bool decl_empty() const { return DeclsInScope.empty(); }
0345
0346 void AddDecl(Decl *D) {
0347 if (auto *VD = dyn_cast<VarDecl>(D))
0348 if (!isa<ParmVarDecl>(VD))
0349 ReturnSlots.insert(VD);
0350
0351 DeclsInScope.insert(D);
0352 }
0353
0354 void RemoveDecl(Decl *D) { DeclsInScope.erase(D); }
0355
0356 void incrementMSManglingNumber() {
0357 if (Scope *MSLMP = getMSLastManglingParent()) {
0358 MSLMP->MSLastManglingNumber += 1;
0359 MSCurManglingNumber += 1;
0360 }
0361 }
0362
0363 void decrementMSManglingNumber() {
0364 if (Scope *MSLMP = getMSLastManglingParent()) {
0365 MSLMP->MSLastManglingNumber -= 1;
0366 MSCurManglingNumber -= 1;
0367 }
0368 }
0369
0370 unsigned getMSLastManglingNumber() const {
0371 if (const Scope *MSLMP = getMSLastManglingParent())
0372 return MSLMP->MSLastManglingNumber;
0373 return 1;
0374 }
0375
0376 unsigned getMSCurManglingNumber() const {
0377 return MSCurManglingNumber;
0378 }
0379
0380
0381
0382 bool isDeclScope(const Decl *D) const { return DeclsInScope.contains(D); }
0383
0384
0385 DeclContext *getEntity() const {
0386 return isTemplateParamScope() ? nullptr : Entity;
0387 }
0388
0389
0390
0391 DeclContext *getLookupEntity() const { return Entity; }
0392
0393 void setEntity(DeclContext *E) {
0394 assert(!isTemplateParamScope() &&
0395 "entity associated with template param scope");
0396 Entity = E;
0397 }
0398 void setLookupEntity(DeclContext *E) { Entity = E; }
0399
0400
0401
0402
0403
0404 bool hasUnrecoverableErrorOccurred() const {
0405 return ErrorTrap.hasUnrecoverableErrorOccurred();
0406 }
0407
0408
0409 bool isFunctionScope() const { return getFlags() & Scope::FnScope; }
0410
0411
0412 bool isClassScope() const { return getFlags() & Scope::ClassScope; }
0413
0414
0415
0416 bool isClassInheritanceScope() const {
0417 return getFlags() & Scope::ClassInheritanceScope;
0418 }
0419
0420
0421
0422 bool isInCXXInlineMethodScope() const {
0423 if (const Scope *FnS = getFnParent()) {
0424 assert(FnS->getParent() && "TUScope not created?");
0425 return FnS->getParent()->isClassScope();
0426 }
0427 return false;
0428 }
0429
0430
0431
0432 bool isInObjcMethodScope() const {
0433 for (const Scope *S = this; S; S = S->getParent()) {
0434
0435 if (S->getFlags() & ObjCMethodScope)
0436 return true;
0437 }
0438 return false;
0439 }
0440
0441
0442
0443 bool isInObjcMethodOuterScope() const {
0444 if (const Scope *S = this) {
0445
0446 if (S->getFlags() & ObjCMethodScope)
0447 return true;
0448 }
0449 return false;
0450 }
0451
0452
0453
0454 bool isTemplateParamScope() const {
0455 return getFlags() & Scope::TemplateParamScope;
0456 }
0457
0458
0459
0460 bool isFunctionPrototypeScope() const {
0461 return getFlags() & Scope::FunctionPrototypeScope;
0462 }
0463
0464
0465
0466 bool isFunctionDeclarationScope() const {
0467 return getFlags() & Scope::FunctionDeclarationScope;
0468 }
0469
0470
0471 bool isAtCatchScope() const {
0472 return getFlags() & Scope::AtCatchScope;
0473 }
0474
0475
0476 bool isCatchScope() const { return getFlags() & Scope::CatchScope; }
0477
0478
0479 bool isSwitchScope() const {
0480 for (const Scope *S = this; S; S = S->getParent()) {
0481 if (S->getFlags() & Scope::SwitchScope)
0482 return true;
0483 else if (S->getFlags() & (Scope::FnScope | Scope::ClassScope |
0484 Scope::BlockScope | Scope::TemplateParamScope |
0485 Scope::FunctionPrototypeScope |
0486 Scope::AtCatchScope | Scope::ObjCMethodScope))
0487 return false;
0488 }
0489 return false;
0490 }
0491
0492
0493 bool isLoopScope() const {
0494
0495
0496 return (getFlags() & Scope::BreakScope) &&
0497 !(getFlags() & Scope::SwitchScope);
0498 }
0499
0500
0501 bool isOpenMPDirectiveScope() const {
0502 return (getFlags() & Scope::OpenMPDirectiveScope);
0503 }
0504
0505
0506
0507 bool isOpenMPLoopDirectiveScope() const {
0508 if (getFlags() & Scope::OpenMPLoopDirectiveScope) {
0509 assert(isOpenMPDirectiveScope() &&
0510 "OpenMP loop directive scope is not a directive scope");
0511 return true;
0512 }
0513 return false;
0514 }
0515
0516
0517
0518 bool isOpenMPSimdDirectiveScope() const {
0519 return getFlags() & Scope::OpenMPSimdDirectiveScope;
0520 }
0521
0522
0523
0524 bool isOpenMPLoopScope() const {
0525 const Scope *P = getParent();
0526 return P && P->isOpenMPLoopDirectiveScope();
0527 }
0528
0529
0530
0531 bool isOpenMPOrderClauseScope() const {
0532 return getFlags() & Scope::OpenMPOrderClauseScope;
0533 }
0534
0535
0536
0537 bool isOpenACCComputeConstructScope() const {
0538 return getFlags() & Scope::OpenACCComputeConstructScope;
0539 }
0540
0541
0542
0543
0544 bool isInOpenACCComputeConstructScope(ScopeFlags Flags = NoScope) const {
0545 for (const Scope *S = this; S; S = S->getParent()) {
0546 if (S->isOpenACCComputeConstructScope())
0547 return true;
0548
0549 if (S->getFlags() & Flags)
0550 return false;
0551
0552 else if (S->getFlags() &
0553 (Scope::FnScope | Scope::ClassScope | Scope::BlockScope |
0554 Scope::TemplateParamScope | Scope::FunctionPrototypeScope |
0555 Scope::AtCatchScope | Scope::ObjCMethodScope))
0556 return false;
0557 }
0558 return false;
0559 }
0560
0561
0562
0563 bool isContinueScope() const {
0564 return getFlags() & ScopeFlags::ContinueScope;
0565 }
0566
0567
0568 bool isTryScope() const { return getFlags() & Scope::TryScope; }
0569
0570
0571 bool isFnTryCatchScope() const {
0572 return getFlags() & ScopeFlags::FnTryCatchScope;
0573 }
0574
0575
0576 bool isSEHTryScope() const { return getFlags() & Scope::SEHTryScope; }
0577
0578
0579 bool isSEHExceptScope() const { return getFlags() & Scope::SEHExceptScope; }
0580
0581
0582 bool isCompoundStmtScope() const {
0583 return getFlags() & Scope::CompoundStmtScope;
0584 }
0585
0586
0587
0588 bool isControlScope() const { return getFlags() & Scope::ControlScope; }
0589
0590
0591 bool isTypeAliasScope() const { return getFlags() & Scope::TypeAliasScope; }
0592
0593
0594 bool isFriendScope() const { return getFlags() & Scope::FriendScope; }
0595
0596
0597
0598
0599
0600 bool Contains(const Scope& rhs) const { return Depth < rhs.Depth; }
0601
0602
0603
0604 bool containedInPrototypeScope() const;
0605
0606 void PushUsingDirective(UsingDirectiveDecl *UDir) {
0607 UsingDirectives.push_back(UDir);
0608 }
0609
0610 using using_directives_range =
0611 llvm::iterator_range<UsingDirectivesTy::iterator>;
0612
0613 using_directives_range using_directives() {
0614 return using_directives_range(UsingDirectives.begin(),
0615 UsingDirectives.end());
0616 }
0617
0618 void updateNRVOCandidate(VarDecl *VD);
0619
0620 void applyNRVO();
0621
0622
0623 void Init(Scope *parent, unsigned flags);
0624
0625
0626
0627 void AddFlags(unsigned Flags);
0628
0629 void dumpImpl(raw_ostream &OS) const;
0630 void dump() const;
0631 };
0632
0633 }
0634
0635 #endif