File indexing completed on 2026-05-10 08:36:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_CLANG_AST_TEMPLATENAME_H
0014 #define LLVM_CLANG_AST_TEMPLATENAME_H
0015
0016 #include "clang/AST/DependenceFlags.h"
0017 #include "clang/AST/NestedNameSpecifier.h"
0018 #include "clang/Basic/LLVM.h"
0019 #include "llvm/ADT/FoldingSet.h"
0020 #include "llvm/ADT/PointerIntPair.h"
0021 #include "llvm/ADT/PointerUnion.h"
0022 #include "llvm/Support/PointerLikeTypeTraits.h"
0023 #include <cassert>
0024 #include <optional>
0025
0026 namespace clang {
0027
0028 class ASTContext;
0029 class Decl;
0030 class DependentTemplateName;
0031 class IdentifierInfo;
0032 class NamedDecl;
0033 class NestedNameSpecifier;
0034 enum OverloadedOperatorKind : int;
0035 class OverloadedTemplateStorage;
0036 class AssumedTemplateStorage;
0037 class DeducedTemplateStorage;
0038 struct PrintingPolicy;
0039 class QualifiedTemplateName;
0040 class SubstTemplateTemplateParmPackStorage;
0041 class SubstTemplateTemplateParmStorage;
0042 class TemplateArgument;
0043 class TemplateDecl;
0044 class TemplateTemplateParmDecl;
0045 class UsingShadowDecl;
0046
0047
0048
0049 class UncommonTemplateNameStorage {
0050 protected:
0051 enum Kind {
0052 Overloaded,
0053 Assumed,
0054 Deduced,
0055 SubstTemplateTemplateParm,
0056 SubstTemplateTemplateParmPack
0057 };
0058
0059 struct BitsTag {
0060 LLVM_PREFERRED_TYPE(Kind)
0061 unsigned Kind : 3;
0062
0063
0064 unsigned Index : 14;
0065
0066
0067
0068 unsigned Data : 15;
0069 };
0070
0071 union {
0072 struct BitsTag Bits;
0073 void *PointerAlignment;
0074 };
0075
0076 UncommonTemplateNameStorage(Kind Kind, unsigned Index, unsigned Data) {
0077 Bits.Kind = Kind;
0078 Bits.Index = Index;
0079 Bits.Data = Data;
0080 }
0081
0082 public:
0083 OverloadedTemplateStorage *getAsOverloadedStorage() {
0084 return Bits.Kind == Overloaded
0085 ? reinterpret_cast<OverloadedTemplateStorage *>(this)
0086 : nullptr;
0087 }
0088
0089 AssumedTemplateStorage *getAsAssumedTemplateName() {
0090 return Bits.Kind == Assumed
0091 ? reinterpret_cast<AssumedTemplateStorage *>(this)
0092 : nullptr;
0093 }
0094
0095 DeducedTemplateStorage *getAsDeducedTemplateName() {
0096 return Bits.Kind == Deduced
0097 ? reinterpret_cast<DeducedTemplateStorage *>(this)
0098 : nullptr;
0099 }
0100
0101 SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() {
0102 return Bits.Kind == SubstTemplateTemplateParm
0103 ? reinterpret_cast<SubstTemplateTemplateParmStorage *>(this)
0104 : nullptr;
0105 }
0106
0107 SubstTemplateTemplateParmPackStorage *getAsSubstTemplateTemplateParmPack() {
0108 return Bits.Kind == SubstTemplateTemplateParmPack
0109 ? reinterpret_cast<SubstTemplateTemplateParmPackStorage *>(this)
0110 : nullptr;
0111 }
0112 };
0113
0114
0115
0116 class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
0117 friend class ASTContext;
0118
0119 OverloadedTemplateStorage(unsigned size)
0120 : UncommonTemplateNameStorage(Overloaded, 0, size) {}
0121
0122 NamedDecl **getStorage() {
0123 return reinterpret_cast<NamedDecl **>(this + 1);
0124 }
0125 NamedDecl * const *getStorage() const {
0126 return reinterpret_cast<NamedDecl *const *>(this + 1);
0127 }
0128
0129 public:
0130 unsigned size() const { return Bits.Data; }
0131
0132 using iterator = NamedDecl *const *;
0133
0134 iterator begin() const { return getStorage(); }
0135 iterator end() const { return getStorage() + Bits.Data; }
0136
0137 llvm::ArrayRef<NamedDecl*> decls() const {
0138 return llvm::ArrayRef(begin(), end());
0139 }
0140 };
0141
0142
0143
0144
0145
0146
0147
0148 class SubstTemplateTemplateParmPackStorage : public UncommonTemplateNameStorage,
0149 public llvm::FoldingSetNode {
0150 const TemplateArgument *Arguments;
0151 llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
0152
0153 public:
0154 SubstTemplateTemplateParmPackStorage(ArrayRef<TemplateArgument> ArgPack,
0155 Decl *AssociatedDecl, unsigned Index,
0156 bool Final);
0157
0158
0159
0160 Decl *getAssociatedDecl() const;
0161
0162
0163
0164 unsigned getIndex() const { return Bits.Index; }
0165
0166
0167 bool getFinal() const;
0168
0169
0170 TemplateTemplateParmDecl *getParameterPack() const;
0171
0172
0173
0174 TemplateArgument getArgumentPack() const;
0175
0176 void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context);
0177
0178 static void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context,
0179 const TemplateArgument &ArgPack, Decl *AssociatedDecl,
0180 unsigned Index, bool Final);
0181 };
0182
0183 struct DefaultArguments {
0184
0185
0186 unsigned StartPos;
0187 ArrayRef<TemplateArgument> Args;
0188
0189 operator bool() const { return !Args.empty(); }
0190 };
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220 class TemplateName {
0221
0222
0223
0224
0225 using StorageType =
0226 llvm::PointerUnion<Decl *, UncommonTemplateNameStorage *,
0227 QualifiedTemplateName *, DependentTemplateName *>;
0228
0229 StorageType Storage;
0230
0231 explicit TemplateName(void *Ptr);
0232
0233 public:
0234
0235 enum NameKind {
0236
0237 Template,
0238
0239
0240 OverloadedTemplate,
0241
0242
0243
0244 AssumedTemplate,
0245
0246
0247
0248 QualifiedTemplate,
0249
0250
0251
0252 DependentTemplate,
0253
0254
0255
0256 SubstTemplateTemplateParm,
0257
0258
0259
0260
0261 SubstTemplateTemplateParmPack,
0262
0263
0264
0265 UsingTemplate,
0266
0267
0268
0269 DeducedTemplate,
0270 };
0271
0272 TemplateName() = default;
0273 explicit TemplateName(TemplateDecl *Template);
0274 explicit TemplateName(OverloadedTemplateStorage *Storage);
0275 explicit TemplateName(AssumedTemplateStorage *Storage);
0276 explicit TemplateName(SubstTemplateTemplateParmStorage *Storage);
0277 explicit TemplateName(SubstTemplateTemplateParmPackStorage *Storage);
0278 explicit TemplateName(QualifiedTemplateName *Qual);
0279 explicit TemplateName(DependentTemplateName *Dep);
0280 explicit TemplateName(UsingShadowDecl *Using);
0281 explicit TemplateName(DeducedTemplateStorage *Deduced);
0282
0283
0284 bool isNull() const;
0285
0286
0287 NameKind getKind() const;
0288
0289
0290
0291
0292
0293
0294
0295
0296 TemplateDecl *getAsTemplateDecl(bool IgnoreDeduced = false) const;
0297
0298
0299
0300
0301 std::pair<TemplateDecl *, DefaultArguments>
0302 getTemplateDeclAndDefaultArgs() const;
0303
0304
0305
0306
0307
0308
0309
0310
0311 OverloadedTemplateStorage *getAsOverloadedTemplate() const;
0312
0313
0314
0315 AssumedTemplateStorage *getAsAssumedTemplateName() const;
0316
0317
0318
0319
0320
0321
0322 SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const;
0323
0324
0325
0326
0327
0328
0329 SubstTemplateTemplateParmPackStorage *
0330 getAsSubstTemplateTemplateParmPack() const;
0331
0332
0333
0334 QualifiedTemplateName *getAsQualifiedTemplateName() const;
0335
0336
0337
0338 DependentTemplateName *getAsDependentTemplateName() const;
0339
0340
0341
0342 UsingShadowDecl *getAsUsingShadowDecl() const;
0343
0344
0345 DeducedTemplateStorage *getAsDeducedTemplateName() const;
0346
0347 std::optional<TemplateName> desugar(bool IgnoreDeduced) const;
0348
0349 TemplateName getUnderlying() const;
0350
0351 TemplateNameDependence getDependence() const;
0352
0353
0354 bool isDependent() const;
0355
0356
0357
0358 bool isInstantiationDependent() const;
0359
0360
0361
0362 bool containsUnexpandedParameterPack() const;
0363
0364 enum class Qualified { None, AsWritten };
0365
0366
0367
0368
0369
0370
0371
0372
0373 void print(raw_ostream &OS, const PrintingPolicy &Policy,
0374 Qualified Qual = Qualified::AsWritten) const;
0375
0376
0377 void dump(raw_ostream &OS, const ASTContext &Context) const;
0378
0379
0380
0381 void dump() const;
0382
0383 void Profile(llvm::FoldingSetNodeID &ID) {
0384 ID.AddPointer(Storage.getOpaqueValue());
0385 }
0386
0387
0388 void *getAsVoidPointer() const { return Storage.getOpaqueValue(); }
0389
0390
0391 static TemplateName getFromVoidPointer(void *Ptr) {
0392 return TemplateName(Ptr);
0393 }
0394
0395
0396 bool operator==(TemplateName Other) const { return Storage == Other.Storage; }
0397 bool operator!=(TemplateName Other) const { return !operator==(Other); }
0398 };
0399
0400
0401
0402 const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
0403 TemplateName N);
0404
0405
0406
0407 class SubstTemplateTemplateParmStorage
0408 : public UncommonTemplateNameStorage, public llvm::FoldingSetNode {
0409 friend class ASTContext;
0410
0411 TemplateName Replacement;
0412 Decl *AssociatedDecl;
0413
0414 SubstTemplateTemplateParmStorage(TemplateName Replacement,
0415 Decl *AssociatedDecl, unsigned Index,
0416 std::optional<unsigned> PackIndex)
0417 : UncommonTemplateNameStorage(SubstTemplateTemplateParm, Index,
0418 PackIndex ? *PackIndex + 1 : 0),
0419 Replacement(Replacement), AssociatedDecl(AssociatedDecl) {
0420 assert(AssociatedDecl != nullptr);
0421 }
0422
0423 public:
0424
0425
0426 Decl *getAssociatedDecl() const { return AssociatedDecl; }
0427
0428
0429
0430 unsigned getIndex() const { return Bits.Index; }
0431
0432 std::optional<unsigned> getPackIndex() const {
0433 if (Bits.Data == 0)
0434 return std::nullopt;
0435 return Bits.Data - 1;
0436 }
0437
0438 TemplateTemplateParmDecl *getParameter() const;
0439 TemplateName getReplacement() const { return Replacement; }
0440
0441 void Profile(llvm::FoldingSetNodeID &ID);
0442
0443 static void Profile(llvm::FoldingSetNodeID &ID, TemplateName Replacement,
0444 Decl *AssociatedDecl, unsigned Index,
0445 std::optional<unsigned> PackIndex);
0446 };
0447
0448 class DeducedTemplateStorage : public UncommonTemplateNameStorage,
0449 public llvm::FoldingSetNode {
0450 friend class ASTContext;
0451
0452 TemplateName Underlying;
0453
0454 DeducedTemplateStorage(TemplateName Underlying,
0455 const DefaultArguments &DefArgs);
0456
0457 public:
0458 TemplateName getUnderlying() const { return Underlying; }
0459
0460 DefaultArguments getDefaultArguments() const {
0461 return {Bits.Index,
0462 {reinterpret_cast<const TemplateArgument *>(this + 1),
0463 Bits.Data}};
0464 }
0465
0466 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
0467
0468 static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
0469 TemplateName Underlying, const DefaultArguments &DefArgs);
0470 };
0471
0472 inline TemplateName TemplateName::getUnderlying() const {
0473 if (SubstTemplateTemplateParmStorage *subst
0474 = getAsSubstTemplateTemplateParm())
0475 return subst->getReplacement().getUnderlying();
0476 return *this;
0477 }
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491 class QualifiedTemplateName : public llvm::FoldingSetNode {
0492 friend class ASTContext;
0493
0494
0495
0496
0497
0498
0499
0500
0501 llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier;
0502
0503
0504
0505
0506
0507
0508 TemplateName UnderlyingTemplate;
0509
0510 QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword,
0511 TemplateName Template)
0512 : Qualifier(NNS, TemplateKeyword ? 1 : 0), UnderlyingTemplate(Template) {
0513 assert(UnderlyingTemplate.getKind() == TemplateName::Template ||
0514 UnderlyingTemplate.getKind() == TemplateName::UsingTemplate);
0515 }
0516
0517 public:
0518
0519 NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
0520
0521
0522
0523 bool hasTemplateKeyword() const { return Qualifier.getInt(); }
0524
0525
0526 TemplateName getUnderlyingTemplate() const { return UnderlyingTemplate; }
0527
0528 void Profile(llvm::FoldingSetNodeID &ID) {
0529 Profile(ID, getQualifier(), hasTemplateKeyword(), UnderlyingTemplate);
0530 }
0531
0532 static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
0533 bool TemplateKeyword, TemplateName TN) {
0534 ID.AddPointer(NNS);
0535 ID.AddBoolean(TemplateKeyword);
0536 ID.AddPointer(TN.getAsVoidPointer());
0537 }
0538 };
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548 class DependentTemplateName : public llvm::FoldingSetNode {
0549 friend class ASTContext;
0550
0551
0552
0553
0554
0555
0556
0557 llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier;
0558
0559
0560 union {
0561
0562
0563
0564 const IdentifierInfo *Identifier;
0565
0566
0567
0568
0569 OverloadedOperatorKind Operator;
0570 };
0571
0572
0573
0574
0575
0576
0577
0578 TemplateName CanonicalTemplateName;
0579
0580 DependentTemplateName(NestedNameSpecifier *Qualifier,
0581 const IdentifierInfo *Identifier)
0582 : Qualifier(Qualifier, false), Identifier(Identifier),
0583 CanonicalTemplateName(this) {}
0584
0585 DependentTemplateName(NestedNameSpecifier *Qualifier,
0586 const IdentifierInfo *Identifier,
0587 TemplateName Canon)
0588 : Qualifier(Qualifier, false), Identifier(Identifier),
0589 CanonicalTemplateName(Canon) {}
0590
0591 DependentTemplateName(NestedNameSpecifier *Qualifier,
0592 OverloadedOperatorKind Operator)
0593 : Qualifier(Qualifier, true), Operator(Operator),
0594 CanonicalTemplateName(this) {}
0595
0596 DependentTemplateName(NestedNameSpecifier *Qualifier,
0597 OverloadedOperatorKind Operator,
0598 TemplateName Canon)
0599 : Qualifier(Qualifier, true), Operator(Operator),
0600 CanonicalTemplateName(Canon) {}
0601
0602 public:
0603
0604 NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); }
0605
0606
0607 bool isIdentifier() const { return !Qualifier.getInt(); }
0608
0609
0610 const IdentifierInfo *getIdentifier() const {
0611 assert(isIdentifier() && "Template name isn't an identifier?");
0612 return Identifier;
0613 }
0614
0615
0616
0617 bool isOverloadedOperator() const { return Qualifier.getInt(); }
0618
0619
0620 OverloadedOperatorKind getOperator() const {
0621 assert(isOverloadedOperator() &&
0622 "Template name isn't an overloaded operator?");
0623 return Operator;
0624 }
0625
0626 void Profile(llvm::FoldingSetNodeID &ID) {
0627 if (isIdentifier())
0628 Profile(ID, getQualifier(), getIdentifier());
0629 else
0630 Profile(ID, getQualifier(), getOperator());
0631 }
0632
0633 static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
0634 const IdentifierInfo *Identifier) {
0635 ID.AddPointer(NNS);
0636 ID.AddBoolean(false);
0637 ID.AddPointer(Identifier);
0638 }
0639
0640 static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS,
0641 OverloadedOperatorKind Operator) {
0642 ID.AddPointer(NNS);
0643 ID.AddBoolean(true);
0644 ID.AddInteger(Operator);
0645 }
0646 };
0647
0648 }
0649
0650 namespace llvm {
0651
0652
0653 template<>
0654 struct PointerLikeTypeTraits<clang::TemplateName> {
0655 static inline void *getAsVoidPointer(clang::TemplateName TN) {
0656 return TN.getAsVoidPointer();
0657 }
0658
0659 static inline clang::TemplateName getFromVoidPointer(void *Ptr) {
0660 return clang::TemplateName::getFromVoidPointer(Ptr);
0661 }
0662
0663
0664 static constexpr int NumLowBitsAvailable = 0;
0665 };
0666
0667 }
0668
0669 #endif