File indexing completed on 2026-05-10 08:37:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef LLVM_CLANG_SEMA_TEMPLATE_H
0013 #define LLVM_CLANG_SEMA_TEMPLATE_H
0014
0015 #include "clang/AST/DeclTemplate.h"
0016 #include "clang/AST/DeclVisitor.h"
0017 #include "clang/AST/TemplateBase.h"
0018 #include "clang/AST/Type.h"
0019 #include "clang/Basic/LLVM.h"
0020 #include "clang/Sema/Sema.h"
0021 #include "llvm/ADT/ArrayRef.h"
0022 #include "llvm/ADT/DenseMap.h"
0023 #include "llvm/ADT/PointerUnion.h"
0024 #include "llvm/ADT/SmallVector.h"
0025 #include <cassert>
0026 #include <optional>
0027 #include <utility>
0028
0029 namespace clang {
0030
0031 class ASTContext;
0032 class BindingDecl;
0033 class CXXMethodDecl;
0034 class Decl;
0035 class DeclaratorDecl;
0036 class DeclContext;
0037 class EnumDecl;
0038 class FunctionDecl;
0039 class NamedDecl;
0040 class ParmVarDecl;
0041 class TagDecl;
0042 class TypedefNameDecl;
0043 class TypeSourceInfo;
0044 class VarDecl;
0045
0046
0047 enum class TemplateSubstitutionKind : char {
0048
0049
0050 Specialization,
0051
0052
0053
0054 Rewrite,
0055 };
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 class MultiLevelTemplateArgumentList {
0077
0078
0079 using ArgList = ArrayRef<TemplateArgument>;
0080 struct ArgumentListLevel {
0081 llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
0082 ArgList Args;
0083 };
0084 using ContainerType = SmallVector<ArgumentListLevel, 4>;
0085
0086 using ArgListsIterator = ContainerType::iterator;
0087 using ConstArgListsIterator = ContainerType::const_iterator;
0088
0089
0090
0091 ContainerType TemplateArgumentLists;
0092
0093
0094
0095 unsigned NumRetainedOuterLevels = 0;
0096
0097
0098 TemplateSubstitutionKind Kind = TemplateSubstitutionKind::Specialization;
0099
0100 public:
0101
0102 MultiLevelTemplateArgumentList() = default;
0103
0104
0105 MultiLevelTemplateArgumentList(Decl *D, ArgList Args, bool Final) {
0106 addOuterTemplateArguments(D, Args, Final);
0107 }
0108
0109 void setKind(TemplateSubstitutionKind K) { Kind = K; }
0110
0111
0112 TemplateSubstitutionKind getKind() const { return Kind; }
0113
0114
0115
0116
0117 bool isRewrite() const {
0118 return Kind == TemplateSubstitutionKind::Rewrite;
0119 }
0120
0121
0122
0123 unsigned getNumLevels() const {
0124 return TemplateArgumentLists.size() + NumRetainedOuterLevels;
0125 }
0126
0127
0128
0129 unsigned getNumSubstitutedLevels() const {
0130 return TemplateArgumentLists.size();
0131 }
0132
0133
0134 unsigned getNumSubsitutedArgs(unsigned Depth) const {
0135 assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
0136 return TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size();
0137 }
0138
0139 unsigned getNumRetainedOuterLevels() const {
0140 return NumRetainedOuterLevels;
0141 }
0142
0143
0144
0145 unsigned getNewDepth(unsigned OldDepth) const {
0146 if (OldDepth < NumRetainedOuterLevels)
0147 return OldDepth;
0148 if (OldDepth < getNumLevels())
0149 return NumRetainedOuterLevels;
0150 return OldDepth - TemplateArgumentLists.size();
0151 }
0152
0153
0154 const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
0155 assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
0156 assert(Index <
0157 TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
0158 return TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index];
0159 }
0160
0161
0162
0163
0164 std::pair<Decl *, bool> getAssociatedDecl(unsigned Depth) const {
0165 assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
0166 auto AD = TemplateArgumentLists[getNumLevels() - Depth - 1]
0167 .AssociatedDeclAndFinal;
0168 return {AD.getPointer(), AD.getInt()};
0169 }
0170
0171
0172
0173
0174
0175 bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
0176 assert(Depth < getNumLevels());
0177
0178 if (Depth < NumRetainedOuterLevels)
0179 return false;
0180
0181 if (Index >=
0182 TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size())
0183 return false;
0184
0185 return !(*this)(Depth, Index).isNull();
0186 }
0187
0188 bool isAnyArgInstantiationDependent() const {
0189 for (ArgumentListLevel ListLevel : TemplateArgumentLists)
0190 for (const TemplateArgument &TA : ListLevel.Args)
0191 if (TA.isInstantiationDependent())
0192 return true;
0193 return false;
0194 }
0195
0196
0197 void setArgument(unsigned Depth, unsigned Index,
0198 TemplateArgument Arg) {
0199 assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
0200 assert(Index <
0201 TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
0202 const_cast<TemplateArgument &>(
0203 TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]) = Arg;
0204 }
0205
0206
0207
0208
0209
0210 void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args,
0211 bool Final) {
0212 assert(!NumRetainedOuterLevels &&
0213 "substituted args outside retained args?");
0214 assert(getKind() == TemplateSubstitutionKind::Specialization);
0215 TemplateArgumentLists.push_back(
0216 {{AssociatedDecl ? AssociatedDecl->getCanonicalDecl() : nullptr,
0217 Final},
0218 Args});
0219 }
0220
0221 void addOuterTemplateArguments(ArgList Args) {
0222 assert(!NumRetainedOuterLevels &&
0223 "substituted args outside retained args?");
0224 assert(getKind() == TemplateSubstitutionKind::Rewrite);
0225 TemplateArgumentLists.push_back({{}, Args});
0226 }
0227
0228 void addOuterTemplateArguments(std::nullopt_t) {
0229 assert(!NumRetainedOuterLevels &&
0230 "substituted args outside retained args?");
0231 TemplateArgumentLists.push_back({});
0232 }
0233
0234
0235
0236
0237 void replaceInnermostTemplateArguments(Decl *AssociatedDecl, ArgList Args) {
0238 assert((!TemplateArgumentLists.empty() || NumRetainedOuterLevels) &&
0239 "Replacing in an empty list?");
0240
0241 if (!TemplateArgumentLists.empty()) {
0242 assert((TemplateArgumentLists[0].AssociatedDeclAndFinal.getPointer() ||
0243 TemplateArgumentLists[0].AssociatedDeclAndFinal.getPointer() ==
0244 AssociatedDecl) &&
0245 "Trying to change incorrect declaration?");
0246 TemplateArgumentLists[0].Args = Args;
0247 } else {
0248 --NumRetainedOuterLevels;
0249 TemplateArgumentLists.push_back(
0250 {{AssociatedDecl, false}, Args});
0251 }
0252 }
0253
0254
0255
0256
0257 void addOuterRetainedLevel() {
0258 ++NumRetainedOuterLevels;
0259 }
0260 void addOuterRetainedLevels(unsigned Num) {
0261 NumRetainedOuterLevels += Num;
0262 }
0263
0264
0265 const ArgList &getInnermost() const {
0266 return TemplateArgumentLists.front().Args;
0267 }
0268
0269 const ArgList &getOutermost() const {
0270 return TemplateArgumentLists.back().Args;
0271 }
0272 ArgListsIterator begin() { return TemplateArgumentLists.begin(); }
0273 ConstArgListsIterator begin() const {
0274 return TemplateArgumentLists.begin();
0275 }
0276 ArgListsIterator end() { return TemplateArgumentLists.end(); }
0277 ConstArgListsIterator end() const { return TemplateArgumentLists.end(); }
0278
0279 LLVM_DUMP_METHOD void dump() const {
0280 LangOptions LO;
0281 LO.CPlusPlus = true;
0282 LO.Bool = true;
0283 PrintingPolicy PP(LO);
0284 llvm::errs() << "NumRetainedOuterLevels: " << NumRetainedOuterLevels
0285 << "\n";
0286 for (unsigned Depth = NumRetainedOuterLevels; Depth < getNumLevels();
0287 ++Depth) {
0288 llvm::errs() << Depth << ": ";
0289 printTemplateArgumentList(
0290 llvm::errs(),
0291 TemplateArgumentLists[getNumLevels() - Depth - 1].Args, PP);
0292 llvm::errs() << "\n";
0293 }
0294 }
0295 };
0296
0297
0298 enum TPOC {
0299
0300 TPOC_Call,
0301
0302
0303
0304 TPOC_Conversion,
0305
0306
0307
0308
0309 TPOC_Other
0310 };
0311
0312
0313
0314
0315
0316 class TemplatePartialOrderingContext {
0317 TPOC Value;
0318
0319 public:
0320 TemplatePartialOrderingContext(TPOC Value) : Value(Value) {}
0321
0322 operator TPOC() const { return Value; }
0323 };
0324
0325
0326
0327 class DeducedTemplateArgument : public TemplateArgument {
0328
0329
0330 bool DeducedFromArrayBound = false;
0331
0332 public:
0333 DeducedTemplateArgument() = default;
0334
0335 DeducedTemplateArgument(const TemplateArgument &Arg,
0336 bool DeducedFromArrayBound = false)
0337 : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) {}
0338
0339
0340
0341 DeducedTemplateArgument(ASTContext &Ctx,
0342 const llvm::APSInt &Value,
0343 QualType ValueType,
0344 bool DeducedFromArrayBound)
0345 : TemplateArgument(Ctx, Value, ValueType),
0346 DeducedFromArrayBound(DeducedFromArrayBound) {}
0347
0348
0349
0350 bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; }
0351
0352
0353
0354 void setDeducedFromArrayBound(bool Deduced) {
0355 DeducedFromArrayBound = Deduced;
0356 }
0357 };
0358
0359
0360
0361
0362
0363
0364
0365 class LocalInstantiationScope {
0366 public:
0367
0368 using DeclArgumentPack = SmallVector<VarDecl *, 4>;
0369
0370 private:
0371
0372
0373 Sema &SemaRef;
0374
0375 using LocalDeclsMap =
0376 llvm::SmallDenseMap<const Decl *,
0377 llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>;
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397 LocalDeclsMap LocalDecls;
0398
0399
0400 SmallVector<DeclArgumentPack *, 1> ArgumentPacks;
0401
0402
0403
0404
0405 LocalInstantiationScope *Outer;
0406
0407
0408 bool Exited = false;
0409
0410
0411
0412 bool CombineWithOuterScope;
0413
0414
0415
0416
0417 bool InstantiatingLambdaOrBlock = false;
0418
0419
0420
0421 NamedDecl *PartiallySubstitutedPack = nullptr;
0422
0423
0424
0425 const TemplateArgument *ArgsInPartiallySubstitutedPack;
0426
0427
0428
0429
0430 unsigned NumArgsInPartiallySubstitutedPack;
0431
0432 public:
0433 LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false,
0434 bool InstantiatingLambdaOrBlock = false)
0435 : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
0436 CombineWithOuterScope(CombineWithOuterScope),
0437 InstantiatingLambdaOrBlock(InstantiatingLambdaOrBlock) {
0438 SemaRef.CurrentInstantiationScope = this;
0439 }
0440
0441 LocalInstantiationScope(const LocalInstantiationScope &) = delete;
0442 LocalInstantiationScope &
0443 operator=(const LocalInstantiationScope &) = delete;
0444
0445 ~LocalInstantiationScope() {
0446 Exit();
0447 }
0448
0449 const Sema &getSema() const { return SemaRef; }
0450
0451
0452 void Exit() {
0453 if (Exited)
0454 return;
0455
0456 for (unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I)
0457 delete ArgumentPacks[I];
0458
0459 SemaRef.CurrentInstantiationScope = Outer;
0460 Exited = true;
0461 }
0462
0463
0464
0465 LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) {
0466 if (this == Outermost) return this;
0467
0468
0469
0470 LocalInstantiationScope *oldScope = SemaRef.CurrentInstantiationScope;
0471
0472 LocalInstantiationScope *newScope =
0473 new LocalInstantiationScope(SemaRef, CombineWithOuterScope);
0474
0475 newScope->Outer = nullptr;
0476 if (Outer)
0477 newScope->Outer = Outer->cloneScopes(Outermost);
0478
0479 newScope->PartiallySubstitutedPack = PartiallySubstitutedPack;
0480 newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack;
0481 newScope->NumArgsInPartiallySubstitutedPack =
0482 NumArgsInPartiallySubstitutedPack;
0483
0484 for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end();
0485 I != E; ++I) {
0486 const Decl *D = I->first;
0487 llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored =
0488 newScope->LocalDecls[D];
0489 if (auto *D2 = dyn_cast<Decl *>(I->second)) {
0490 Stored = D2;
0491 } else {
0492 DeclArgumentPack *OldPack = cast<DeclArgumentPack *>(I->second);
0493 DeclArgumentPack *NewPack = new DeclArgumentPack(*OldPack);
0494 Stored = NewPack;
0495 newScope->ArgumentPacks.push_back(NewPack);
0496 }
0497 }
0498
0499 SemaRef.CurrentInstantiationScope = oldScope;
0500 return newScope;
0501 }
0502
0503
0504
0505 static void deleteScopes(LocalInstantiationScope *Scope,
0506 LocalInstantiationScope *Outermost) {
0507 while (Scope && Scope != Outermost) {
0508 LocalInstantiationScope *Out = Scope->Outer;
0509 delete Scope;
0510 Scope = Out;
0511 }
0512 }
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522 llvm::PointerUnion<Decl *, DeclArgumentPack *> *
0523 findInstantiationOf(const Decl *D);
0524
0525 void InstantiatedLocal(const Decl *D, Decl *Inst);
0526 void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst);
0527 void MakeInstantiatedLocalArgPack(const Decl *D);
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541 void SetPartiallySubstitutedPack(NamedDecl *Pack,
0542 const TemplateArgument *ExplicitArgs,
0543 unsigned NumExplicitArgs);
0544
0545
0546
0547 void ResetPartiallySubstitutedPack() {
0548 assert(PartiallySubstitutedPack && "No partially-substituted pack");
0549 PartiallySubstitutedPack = nullptr;
0550 ArgsInPartiallySubstitutedPack = nullptr;
0551 NumArgsInPartiallySubstitutedPack = 0;
0552 }
0553
0554
0555
0556
0557 NamedDecl *
0558 getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr,
0559 unsigned *NumExplicitArgs = nullptr) const;
0560
0561
0562 bool isLocalPackExpansion(const Decl *D);
0563
0564
0565 bool isLambdaOrBlock() const { return InstantiatingLambdaOrBlock; }
0566 };
0567
0568 class TemplateDeclInstantiator
0569 : public DeclVisitor<TemplateDeclInstantiator, Decl *>
0570 {
0571 Sema &SemaRef;
0572 Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
0573 DeclContext *Owner;
0574 const MultiLevelTemplateArgumentList &TemplateArgs;
0575 Sema::LateInstantiatedAttrVec* LateAttrs = nullptr;
0576 LocalInstantiationScope *StartingScope = nullptr;
0577
0578 bool EvaluateConstraints = true;
0579
0580
0581
0582
0583 SmallVector<std::pair<ClassTemplateDecl *,
0584 ClassTemplatePartialSpecializationDecl *>, 4>
0585 OutOfLinePartialSpecs;
0586
0587
0588
0589
0590
0591 SmallVector<
0592 std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 4>
0593 OutOfLineVarPartialSpecs;
0594
0595 public:
0596 TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
0597 const MultiLevelTemplateArgumentList &TemplateArgs)
0598 : SemaRef(SemaRef),
0599 SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
0600 Owner(Owner), TemplateArgs(TemplateArgs) {}
0601
0602 void setEvaluateConstraints(bool B) {
0603 EvaluateConstraints = B;
0604 }
0605 bool getEvaluateConstraints() {
0606 return EvaluateConstraints;
0607 }
0608
0609
0610 #define DECL(DERIVED, BASE) \
0611 Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D);
0612 #define ABSTRACT_DECL(DECL)
0613
0614
0615 #define OBJCCONTAINER(DERIVED, BASE)
0616 #define FILESCOPEASM(DERIVED, BASE)
0617 #define TOPLEVELSTMT(DERIVED, BASE)
0618 #define IMPORT(DERIVED, BASE)
0619 #define EXPORT(DERIVED, BASE)
0620 #define LINKAGESPEC(DERIVED, BASE)
0621 #define OBJCCOMPATIBLEALIAS(DERIVED, BASE)
0622 #define OBJCMETHOD(DERIVED, BASE)
0623 #define OBJCTYPEPARAM(DERIVED, BASE)
0624 #define OBJCIVAR(DERIVED, BASE)
0625 #define OBJCPROPERTY(DERIVED, BASE)
0626 #define OBJCPROPERTYIMPL(DERIVED, BASE)
0627 #define EMPTY(DERIVED, BASE)
0628 #define LIFETIMEEXTENDEDTEMPORARY(DERIVED, BASE)
0629
0630
0631 #define OUTLINEDFUNCTION(DERIVED, BASE)
0632
0633
0634 #define BLOCK(DERIVED, BASE)
0635 #define CAPTURED(DERIVED, BASE)
0636 #define IMPLICITPARAM(DERIVED, BASE)
0637
0638 #include "clang/AST/DeclNodes.inc"
0639
0640 enum class RewriteKind { None, RewriteSpaceshipAsEqualEqual };
0641
0642 void adjustForRewrite(RewriteKind RK, FunctionDecl *Orig, QualType &T,
0643 TypeSourceInfo *&TInfo,
0644 DeclarationNameInfo &NameInfo);
0645
0646
0647 Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
0648 TemplateParameterList *TemplateParams,
0649 RewriteKind RK = RewriteKind::None);
0650 Decl *VisitFunctionDecl(FunctionDecl *D,
0651 TemplateParameterList *TemplateParams,
0652 RewriteKind RK = RewriteKind::None);
0653 Decl *VisitDecl(Decl *D);
0654 Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate,
0655 ArrayRef<BindingDecl *> *Bindings = nullptr);
0656 Decl *VisitBaseUsingDecls(BaseUsingDecl *D, BaseUsingDecl *Inst,
0657 LookupResult *Lookup);
0658
0659
0660
0661 void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA) {
0662 LateAttrs = LA;
0663 StartingScope = SemaRef.CurrentInstantiationScope;
0664 }
0665
0666
0667 void disableLateAttributeInstantiation() {
0668 LateAttrs = nullptr;
0669 StartingScope = nullptr;
0670 }
0671
0672 LocalInstantiationScope *getStartingScope() const { return StartingScope; }
0673
0674 using delayed_partial_spec_iterator = SmallVectorImpl<std::pair<
0675 ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>>::iterator;
0676
0677 using delayed_var_partial_spec_iterator = SmallVectorImpl<std::pair<
0678 VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>>::iterator;
0679
0680
0681
0682
0683
0684 delayed_partial_spec_iterator delayed_partial_spec_begin() {
0685 return OutOfLinePartialSpecs.begin();
0686 }
0687
0688 delayed_var_partial_spec_iterator delayed_var_partial_spec_begin() {
0689 return OutOfLineVarPartialSpecs.begin();
0690 }
0691
0692
0693
0694
0695
0696 delayed_partial_spec_iterator delayed_partial_spec_end() {
0697 return OutOfLinePartialSpecs.end();
0698 }
0699
0700 delayed_var_partial_spec_iterator delayed_var_partial_spec_end() {
0701 return OutOfLineVarPartialSpecs.end();
0702 }
0703
0704
0705 TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
0706 SmallVectorImpl<ParmVarDecl *> &Params);
0707 bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
0708 bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
0709
0710 bool SubstDefaultedFunction(FunctionDecl *New, FunctionDecl *Tmpl);
0711
0712 TemplateParameterList *
0713 SubstTemplateParams(TemplateParameterList *List);
0714
0715 bool SubstQualifier(const DeclaratorDecl *OldDecl,
0716 DeclaratorDecl *NewDecl);
0717 bool SubstQualifier(const TagDecl *OldDecl,
0718 TagDecl *NewDecl);
0719
0720 Decl *VisitVarTemplateSpecializationDecl(
0721 VarTemplateDecl *VarTemplate, VarDecl *FromVar,
0722 const TemplateArgumentListInfo &TemplateArgsInfo,
0723 ArrayRef<TemplateArgument> Converted,
0724 VarTemplateSpecializationDecl *PrevDecl = nullptr);
0725
0726 Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias);
0727 Decl *InstantiateTypeAliasTemplateDecl(TypeAliasTemplateDecl *D);
0728 ClassTemplatePartialSpecializationDecl *
0729 InstantiateClassTemplatePartialSpecialization(
0730 ClassTemplateDecl *ClassTemplate,
0731 ClassTemplatePartialSpecializationDecl *PartialSpec);
0732 VarTemplatePartialSpecializationDecl *
0733 InstantiateVarTemplatePartialSpecialization(
0734 VarTemplateDecl *VarTemplate,
0735 VarTemplatePartialSpecializationDecl *PartialSpec);
0736 void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern);
0737
0738 private:
0739 template<typename T>
0740 Decl *instantiateUnresolvedUsingDecl(T *D,
0741 bool InstantiatingPackElement = false);
0742 };
0743
0744 }
0745
0746 #endif