File indexing completed on 2026-05-10 08:37:00
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_SEMA_LOOKUP_H
0015 #define LLVM_CLANG_SEMA_LOOKUP_H
0016
0017 #include "clang/AST/Decl.h"
0018 #include "clang/AST/DeclBase.h"
0019 #include "clang/AST/DeclCXX.h"
0020 #include "clang/AST/DeclarationName.h"
0021 #include "clang/AST/Type.h"
0022 #include "clang/AST/UnresolvedSet.h"
0023 #include "clang/Basic/LLVM.h"
0024 #include "clang/Basic/LangOptions.h"
0025 #include "clang/Basic/SourceLocation.h"
0026 #include "clang/Basic/Specifiers.h"
0027 #include "clang/Sema/Sema.h"
0028 #include "llvm/ADT/MapVector.h"
0029 #include "llvm/ADT/STLExtras.h"
0030 #include "llvm/Support/Casting.h"
0031 #include <cassert>
0032 #include <optional>
0033 #include <utility>
0034
0035 namespace clang {
0036
0037 class CXXBasePaths;
0038
0039
0040
0041
0042
0043
0044
0045
0046 class LookupResult {
0047 public:
0048 enum LookupResultKind {
0049
0050 NotFound = 0,
0051
0052
0053
0054
0055 NotFoundInCurrentInstantiation,
0056
0057
0058
0059 Found,
0060
0061
0062
0063 FoundOverloaded,
0064
0065
0066
0067
0068 FoundUnresolvedValue,
0069
0070
0071
0072
0073 Ambiguous
0074 };
0075
0076 enum AmbiguityKind {
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 AmbiguousBaseSubobjectTypes,
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103 AmbiguousBaseSubobjects,
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 AmbiguousReference,
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129 AmbiguousReferenceToPlaceholderVariable,
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146 AmbiguousTagHiding
0147 };
0148
0149
0150 enum TemporaryToken {
0151 Temporary
0152 };
0153
0154 using iterator = UnresolvedSetImpl::iterator;
0155
0156 LookupResult(
0157 Sema &SemaRef, const DeclarationNameInfo &NameInfo,
0158 Sema::LookupNameKind LookupKind,
0159 RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration)
0160 : SemaPtr(&SemaRef), NameInfo(NameInfo), LookupKind(LookupKind),
0161 Redecl(Redecl != RedeclarationKind::NotForRedeclaration),
0162 ExternalRedecl(Redecl == RedeclarationKind::ForExternalRedeclaration),
0163 DiagnoseAccess(Redecl == RedeclarationKind::NotForRedeclaration),
0164 DiagnoseAmbiguous(Redecl == RedeclarationKind::NotForRedeclaration) {
0165 configure();
0166 }
0167
0168
0169
0170
0171 LookupResult(
0172 Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc,
0173 Sema::LookupNameKind LookupKind,
0174 RedeclarationKind Redecl = RedeclarationKind::NotForRedeclaration)
0175 : SemaPtr(&SemaRef), NameInfo(Name, NameLoc), LookupKind(LookupKind),
0176 Redecl(Redecl != RedeclarationKind::NotForRedeclaration),
0177 ExternalRedecl(Redecl == RedeclarationKind::ForExternalRedeclaration),
0178 DiagnoseAccess(Redecl == RedeclarationKind::NotForRedeclaration),
0179 DiagnoseAmbiguous(Redecl == RedeclarationKind::NotForRedeclaration) {
0180 configure();
0181 }
0182
0183
0184
0185
0186 LookupResult(TemporaryToken _, const LookupResult &Other)
0187 : SemaPtr(Other.SemaPtr), NameInfo(Other.NameInfo),
0188 LookupKind(Other.LookupKind), IDNS(Other.IDNS), Redecl(Other.Redecl),
0189 ExternalRedecl(Other.ExternalRedecl), HideTags(Other.HideTags),
0190 AllowHidden(Other.AllowHidden),
0191 TemplateNameLookup(Other.TemplateNameLookup) {}
0192
0193
0194
0195 LookupResult(const LookupResult &) = delete;
0196 LookupResult &operator=(const LookupResult &) = delete;
0197
0198 LookupResult(LookupResult &&Other)
0199 : ResultKind(std::move(Other.ResultKind)),
0200 Ambiguity(std::move(Other.Ambiguity)), Decls(std::move(Other.Decls)),
0201 Paths(std::move(Other.Paths)),
0202 NamingClass(std::move(Other.NamingClass)),
0203 BaseObjectType(std::move(Other.BaseObjectType)),
0204 SemaPtr(std::move(Other.SemaPtr)), NameInfo(std::move(Other.NameInfo)),
0205 NameContextRange(std::move(Other.NameContextRange)),
0206 LookupKind(std::move(Other.LookupKind)), IDNS(std::move(Other.IDNS)),
0207 Redecl(std::move(Other.Redecl)),
0208 ExternalRedecl(std::move(Other.ExternalRedecl)),
0209 HideTags(std::move(Other.HideTags)),
0210 DiagnoseAccess(std::move(Other.DiagnoseAccess)),
0211 DiagnoseAmbiguous(std::move(Other.DiagnoseAmbiguous)),
0212 AllowHidden(std::move(Other.AllowHidden)),
0213 Shadowed(std::move(Other.Shadowed)),
0214 TemplateNameLookup(std::move(Other.TemplateNameLookup)) {
0215 Other.Paths = nullptr;
0216 Other.DiagnoseAccess = false;
0217 Other.DiagnoseAmbiguous = false;
0218 }
0219
0220 LookupResult &operator=(LookupResult &&Other) {
0221 ResultKind = std::move(Other.ResultKind);
0222 Ambiguity = std::move(Other.Ambiguity);
0223 Decls = std::move(Other.Decls);
0224 Paths = std::move(Other.Paths);
0225 NamingClass = std::move(Other.NamingClass);
0226 BaseObjectType = std::move(Other.BaseObjectType);
0227 SemaPtr = std::move(Other.SemaPtr);
0228 NameInfo = std::move(Other.NameInfo);
0229 NameContextRange = std::move(Other.NameContextRange);
0230 LookupKind = std::move(Other.LookupKind);
0231 IDNS = std::move(Other.IDNS);
0232 Redecl = std::move(Other.Redecl);
0233 ExternalRedecl = std::move(Other.ExternalRedecl);
0234 HideTags = std::move(Other.HideTags);
0235 DiagnoseAccess = std::move(Other.DiagnoseAccess);
0236 DiagnoseAmbiguous = std::move(Other.DiagnoseAmbiguous);
0237 AllowHidden = std::move(Other.AllowHidden);
0238 Shadowed = std::move(Other.Shadowed);
0239 TemplateNameLookup = std::move(Other.TemplateNameLookup);
0240 Other.Paths = nullptr;
0241 Other.DiagnoseAccess = false;
0242 Other.DiagnoseAmbiguous = false;
0243 return *this;
0244 }
0245
0246 ~LookupResult() {
0247 if (DiagnoseAccess)
0248 diagnoseAccess();
0249 if (DiagnoseAmbiguous)
0250 diagnoseAmbiguous();
0251 if (Paths) deletePaths(Paths);
0252 }
0253
0254
0255 const DeclarationNameInfo &getLookupNameInfo() const {
0256 return NameInfo;
0257 }
0258
0259
0260 void setLookupNameInfo(const DeclarationNameInfo &NameInfo) {
0261 this->NameInfo = NameInfo;
0262 }
0263
0264
0265 DeclarationName getLookupName() const {
0266 return NameInfo.getName();
0267 }
0268
0269
0270 void setLookupName(DeclarationName Name) {
0271 NameInfo.setName(Name);
0272 }
0273
0274
0275 Sema::LookupNameKind getLookupKind() const {
0276 return LookupKind;
0277 }
0278
0279
0280 bool isForRedeclaration() const {
0281 return Redecl;
0282 }
0283
0284
0285
0286 bool isForExternalRedeclaration() const {
0287 return ExternalRedecl;
0288 }
0289
0290 RedeclarationKind redeclarationKind() const {
0291 return ExternalRedecl ? RedeclarationKind::ForExternalRedeclaration
0292 : Redecl ? RedeclarationKind::ForVisibleRedeclaration
0293 : RedeclarationKind::NotForRedeclaration;
0294 }
0295
0296
0297
0298 void setAllowHidden(bool AH) {
0299 AllowHidden = AH;
0300 }
0301
0302
0303
0304 bool isHiddenDeclarationVisible(NamedDecl *ND) const {
0305 return AllowHidden ||
0306 (isForExternalRedeclaration() && ND->isExternallyDeclarable());
0307 }
0308
0309
0310
0311 void setHideTags(bool Hide) {
0312 HideTags = Hide;
0313 }
0314
0315
0316
0317
0318 void setTemplateNameLookup(bool TemplateName) {
0319 TemplateNameLookup = TemplateName;
0320 }
0321
0322 bool isTemplateNameLookup() const { return TemplateNameLookup; }
0323
0324 bool isAmbiguous() const {
0325 return getResultKind() == Ambiguous;
0326 }
0327
0328
0329
0330
0331 bool isSingleResult() const {
0332 return getResultKind() == Found;
0333 }
0334
0335
0336 bool isOverloadedResult() const {
0337 return getResultKind() == FoundOverloaded;
0338 }
0339
0340 bool isUnresolvableResult() const {
0341 return getResultKind() == FoundUnresolvedValue;
0342 }
0343
0344 LookupResultKind getResultKind() const {
0345 assert(checkDebugAssumptions());
0346 return ResultKind;
0347 }
0348
0349 AmbiguityKind getAmbiguityKind() const {
0350 assert(isAmbiguous());
0351 return Ambiguity;
0352 }
0353
0354 const UnresolvedSetImpl &asUnresolvedSet() const {
0355 return Decls;
0356 }
0357
0358 iterator begin() const { return iterator(Decls.begin()); }
0359 iterator end() const { return iterator(Decls.end()); }
0360
0361
0362 bool empty() const { return Decls.empty(); }
0363
0364
0365
0366 CXXBasePaths *getBasePaths() const {
0367 return Paths;
0368 }
0369
0370
0371
0372 static bool isVisible(Sema &SemaRef, NamedDecl *D);
0373
0374 static bool isReachable(Sema &SemaRef, NamedDecl *D);
0375
0376 static bool isAcceptable(Sema &SemaRef, NamedDecl *D,
0377 Sema::AcceptableKind Kind) {
0378 return Kind == Sema::AcceptableKind::Visible ? isVisible(SemaRef, D)
0379 : isReachable(SemaRef, D);
0380 }
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404 static bool isAvailableForLookup(Sema &SemaRef, NamedDecl *ND);
0405
0406
0407
0408 NamedDecl *getAcceptableDecl(NamedDecl *D) const {
0409 if (!D->isInIdentifierNamespace(IDNS))
0410 return nullptr;
0411
0412 if (isAvailableForLookup(getSema(), D) || isHiddenDeclarationVisible(D))
0413 return D;
0414
0415 return getAcceptableDeclSlow(D);
0416 }
0417
0418 private:
0419 static bool isAcceptableSlow(Sema &SemaRef, NamedDecl *D,
0420 Sema::AcceptableKind Kind);
0421 static bool isReachableSlow(Sema &SemaRef, NamedDecl *D);
0422 NamedDecl *getAcceptableDeclSlow(NamedDecl *D) const;
0423
0424 public:
0425
0426 unsigned getIdentifierNamespace() const {
0427 return IDNS;
0428 }
0429
0430
0431
0432 bool isClassLookup() const {
0433 return NamingClass != nullptr;
0434 }
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452 CXXRecordDecl *getNamingClass() const {
0453 return NamingClass;
0454 }
0455
0456
0457 void setNamingClass(CXXRecordDecl *Record) {
0458 NamingClass = Record;
0459 }
0460
0461
0462
0463
0464 QualType getBaseObjectType() const {
0465 return BaseObjectType;
0466 }
0467
0468
0469 void setBaseObjectType(QualType T) {
0470 BaseObjectType = T;
0471 }
0472
0473
0474
0475 void addDecl(NamedDecl *D) {
0476 addDecl(D, D->getAccess());
0477 }
0478
0479
0480
0481 void addDecl(NamedDecl *D, AccessSpecifier AS) {
0482 Decls.addDecl(D, AS);
0483 ResultKind = Found;
0484 }
0485
0486
0487
0488 void addAllDecls(const LookupResult &Other) {
0489 Decls.append(Other.Decls.begin(), Other.Decls.end());
0490 ResultKind = Found;
0491 }
0492
0493
0494
0495 bool wasNotFoundInCurrentInstantiation() const {
0496 return ResultKind == NotFoundInCurrentInstantiation;
0497 }
0498
0499
0500
0501 void setNotFoundInCurrentInstantiation() {
0502 assert((ResultKind == NotFound ||
0503 ResultKind == NotFoundInCurrentInstantiation) &&
0504 Decls.empty());
0505 ResultKind = NotFoundInCurrentInstantiation;
0506 }
0507
0508
0509
0510 bool isShadowed() const { return Shadowed; }
0511
0512
0513
0514 void setShadowed() { Shadowed = true; }
0515
0516
0517
0518
0519
0520
0521 void resolveKind();
0522
0523
0524
0525 void resolveKindAfterFilter() {
0526 if (Decls.empty()) {
0527 if (ResultKind != NotFoundInCurrentInstantiation)
0528 ResultKind = NotFound;
0529
0530 if (Paths) {
0531 deletePaths(Paths);
0532 Paths = nullptr;
0533 }
0534 } else {
0535 std::optional<AmbiguityKind> SavedAK;
0536 bool WasAmbiguous = false;
0537 if (ResultKind == Ambiguous) {
0538 SavedAK = Ambiguity;
0539 WasAmbiguous = true;
0540 }
0541 ResultKind = Found;
0542 resolveKind();
0543
0544
0545
0546 if (ResultKind == Ambiguous) {
0547 (void)WasAmbiguous;
0548 assert(WasAmbiguous);
0549 Ambiguity = *SavedAK;
0550 } else if (Paths) {
0551 deletePaths(Paths);
0552 Paths = nullptr;
0553 }
0554 }
0555 }
0556
0557 template <class DeclClass>
0558 DeclClass *getAsSingle() const {
0559 if (getResultKind() != Found) return nullptr;
0560 return dyn_cast<DeclClass>(getFoundDecl());
0561 }
0562
0563
0564
0565
0566
0567
0568 NamedDecl *getFoundDecl() const {
0569 assert(getResultKind() == Found
0570 && "getFoundDecl called on non-unique result");
0571 return (*begin())->getUnderlyingDecl();
0572 }
0573
0574
0575 NamedDecl *getRepresentativeDecl() const {
0576 assert(!Decls.empty() && "cannot get representative of empty set");
0577 return *begin();
0578 }
0579
0580
0581 bool isSingleTagDecl() const {
0582 return getResultKind() == Found && isa<TagDecl>(getFoundDecl());
0583 }
0584
0585
0586
0587
0588
0589 void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P);
0590
0591
0592
0593
0594
0595 void setAmbiguousBaseSubobjects(CXXBasePaths &P);
0596
0597
0598
0599
0600 void setAmbiguousQualifiedTagHiding() {
0601 setAmbiguous(AmbiguousTagHiding);
0602 }
0603
0604
0605 LLVM_ATTRIBUTE_REINITIALIZES void clear() {
0606 ResultKind = NotFound;
0607 Decls.clear();
0608 if (Paths) deletePaths(Paths);
0609 Paths = nullptr;
0610 NamingClass = nullptr;
0611 Shadowed = false;
0612 }
0613
0614
0615
0616 void clear(Sema::LookupNameKind Kind) {
0617 clear();
0618 LookupKind = Kind;
0619 configure();
0620 }
0621
0622
0623 void setRedeclarationKind(RedeclarationKind RK) {
0624 Redecl = (RK != RedeclarationKind::NotForRedeclaration);
0625 ExternalRedecl = (RK == RedeclarationKind::ForExternalRedeclaration);
0626 configure();
0627 }
0628
0629 void dump();
0630 void print(raw_ostream &);
0631
0632
0633
0634 void suppressDiagnostics() {
0635 DiagnoseAccess = false;
0636 DiagnoseAmbiguous = false;
0637 }
0638
0639
0640
0641 void suppressAccessDiagnostics() { DiagnoseAccess = false; }
0642
0643
0644 bool isSuppressingAccessDiagnostics() const { return !DiagnoseAccess; }
0645
0646
0647
0648 bool isSuppressingAmbiguousDiagnostics() const { return !DiagnoseAmbiguous; }
0649
0650
0651 void setContextRange(SourceRange SR) {
0652 NameContextRange = SR;
0653 }
0654
0655
0656
0657
0658 SourceRange getContextRange() const {
0659 return NameContextRange;
0660 }
0661
0662
0663
0664 SourceLocation getNameLoc() const {
0665 return NameInfo.getLoc();
0666 }
0667
0668
0669
0670 Sema &getSema() const { return *SemaPtr; }
0671
0672
0673
0674
0675 class Filter {
0676 friend class LookupResult;
0677
0678 LookupResult &Results;
0679 LookupResult::iterator I;
0680 bool Changed = false;
0681 bool CalledDone = false;
0682
0683 Filter(LookupResult &Results) : Results(Results), I(Results.begin()) {}
0684
0685 public:
0686 Filter(Filter &&F)
0687 : Results(F.Results), I(F.I), Changed(F.Changed),
0688 CalledDone(F.CalledDone) {
0689 F.CalledDone = true;
0690 }
0691
0692
0693
0694 Filter &operator=(Filter &&) = delete;
0695
0696
0697
0698 Filter(const Filter &) = delete;
0699 Filter &operator=(const Filter &) = delete;
0700
0701 ~Filter() {
0702 assert(CalledDone &&
0703 "LookupResult::Filter destroyed without done() call");
0704 }
0705
0706 bool hasNext() const {
0707 return I != Results.end();
0708 }
0709
0710 NamedDecl *next() {
0711 assert(I != Results.end() && "next() called on empty filter");
0712 return *I++;
0713 }
0714
0715
0716 void restart() {
0717 I = Results.begin();
0718 }
0719
0720
0721 void erase() {
0722 Results.Decls.erase(--I);
0723 Changed = true;
0724 }
0725
0726
0727
0728 void replace(NamedDecl *D) {
0729 Results.Decls.replace(I-1, D);
0730 Changed = true;
0731 }
0732
0733
0734 void replace(NamedDecl *D, AccessSpecifier AS) {
0735 Results.Decls.replace(I-1, D, AS);
0736 Changed = true;
0737 }
0738
0739 void done() {
0740 assert(!CalledDone && "done() called twice");
0741 CalledDone = true;
0742
0743 if (Changed)
0744 Results.resolveKindAfterFilter();
0745 }
0746 };
0747
0748
0749 Filter makeFilter() {
0750 return Filter(*this);
0751 }
0752
0753 void setFindLocalExtern(bool FindLocalExtern) {
0754 if (FindLocalExtern)
0755 IDNS |= Decl::IDNS_LocalExtern;
0756 else
0757 IDNS &= ~Decl::IDNS_LocalExtern;
0758 }
0759
0760 private:
0761 void diagnoseAccess() {
0762 if (!isAmbiguous() && isClassLookup() &&
0763 getSema().getLangOpts().AccessControl)
0764 getSema().CheckLookupAccess(*this);
0765 }
0766
0767 void diagnoseAmbiguous() {
0768 if (isAmbiguous())
0769 getSema().DiagnoseAmbiguousLookup(*this);
0770 }
0771
0772 void setAmbiguous(AmbiguityKind AK) {
0773 ResultKind = Ambiguous;
0774 Ambiguity = AK;
0775 }
0776
0777 void addDeclsFromBasePaths(const CXXBasePaths &P);
0778 void configure();
0779
0780 bool checkDebugAssumptions() const;
0781
0782 bool checkUnresolved() const {
0783 for (iterator I = begin(), E = end(); I != E; ++I)
0784 if (isa<UnresolvedUsingValueDecl>((*I)->getUnderlyingDecl()))
0785 return true;
0786 return false;
0787 }
0788
0789 static void deletePaths(CXXBasePaths *);
0790
0791
0792 LookupResultKind ResultKind = NotFound;
0793
0794
0795 AmbiguityKind Ambiguity = {};
0796 UnresolvedSet<8> Decls;
0797 CXXBasePaths *Paths = nullptr;
0798 CXXRecordDecl *NamingClass = nullptr;
0799 QualType BaseObjectType;
0800
0801
0802 Sema *SemaPtr;
0803 DeclarationNameInfo NameInfo;
0804 SourceRange NameContextRange;
0805 Sema::LookupNameKind LookupKind;
0806 unsigned IDNS = 0;
0807
0808 bool Redecl;
0809 bool ExternalRedecl;
0810
0811
0812
0813 bool HideTags = true;
0814
0815 bool DiagnoseAccess = false;
0816 bool DiagnoseAmbiguous = false;
0817
0818
0819 bool AllowHidden = false;
0820
0821
0822
0823
0824 bool Shadowed = false;
0825
0826
0827 bool TemplateNameLookup = false;
0828 };
0829
0830
0831
0832
0833
0834
0835
0836 class VisibleDeclConsumer {
0837 public:
0838
0839 virtual ~VisibleDeclConsumer();
0840
0841
0842
0843
0844 virtual bool includeHiddenDecls() const;
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855
0856
0857
0858 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
0859 bool InBaseClass) = 0;
0860
0861
0862
0863
0864
0865 virtual void EnteredContext(DeclContext *Ctx) {}
0866 };
0867
0868
0869 class ADLResult {
0870 private:
0871
0872 llvm::MapVector<NamedDecl*, NamedDecl*> Decls;
0873
0874 struct select_second {
0875 NamedDecl *operator()(std::pair<NamedDecl*, NamedDecl*> P) const {
0876 return P.second;
0877 }
0878 };
0879
0880 public:
0881
0882 void insert(NamedDecl *D);
0883
0884
0885 void erase(NamedDecl *D) {
0886 Decls.erase(cast<NamedDecl>(D->getCanonicalDecl()));
0887 }
0888
0889 using iterator =
0890 llvm::mapped_iterator<decltype(Decls)::iterator, select_second>;
0891
0892 iterator begin() { return iterator(Decls.begin(), select_second()); }
0893 iterator end() { return iterator(Decls.end(), select_second()); }
0894 };
0895
0896 }
0897
0898 #endif