File indexing completed on 2026-05-10 08:36:43
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_AST_TEMPLATEBASE_H
0015 #define LLVM_CLANG_AST_TEMPLATEBASE_H
0016
0017 #include "clang/AST/DependenceFlags.h"
0018 #include "clang/AST/NestedNameSpecifier.h"
0019 #include "clang/AST/TemplateName.h"
0020 #include "clang/AST/Type.h"
0021 #include "clang/Basic/LLVM.h"
0022 #include "clang/Basic/SourceLocation.h"
0023 #include "llvm/ADT/APInt.h"
0024 #include "llvm/ADT/APSInt.h"
0025 #include "llvm/ADT/ArrayRef.h"
0026 #include "llvm/ADT/SmallVector.h"
0027 #include "llvm/Support/Compiler.h"
0028 #include "llvm/Support/TrailingObjects.h"
0029 #include <cassert>
0030 #include <cstddef>
0031 #include <cstdint>
0032 #include <optional>
0033
0034 namespace llvm {
0035
0036 class FoldingSetNodeID;
0037
0038
0039
0040
0041 template <> struct PointerLikeTypeTraits<clang::Expr *> {
0042 static inline void *getAsVoidPointer(clang::Expr *P) { return P; }
0043 static inline clang::Expr *getFromVoidPointer(void *P) {
0044 return static_cast<clang::Expr *>(P);
0045 }
0046 static constexpr int NumLowBitsAvailable = 2;
0047 };
0048
0049 }
0050
0051 namespace clang {
0052
0053 class APValue;
0054 class ASTContext;
0055 class Expr;
0056 struct PrintingPolicy;
0057 class TypeSourceInfo;
0058 class ValueDecl;
0059
0060
0061 class TemplateArgument {
0062 public:
0063
0064 enum ArgKind {
0065
0066
0067 Null = 0,
0068
0069
0070 Type,
0071
0072
0073
0074 Declaration,
0075
0076
0077
0078 NullPtr,
0079
0080
0081
0082 Integral,
0083
0084
0085
0086
0087
0088
0089 StructuralValue,
0090
0091
0092
0093 Template,
0094
0095
0096
0097 TemplateExpansion,
0098
0099
0100
0101
0102
0103 Expression,
0104
0105
0106
0107 Pack
0108 };
0109
0110 private:
0111
0112
0113 struct DA {
0114 LLVM_PREFERRED_TYPE(ArgKind)
0115 unsigned Kind : 31;
0116 LLVM_PREFERRED_TYPE(bool)
0117 unsigned IsDefaulted : 1;
0118 void *QT;
0119 ValueDecl *D;
0120 };
0121 struct I {
0122 LLVM_PREFERRED_TYPE(ArgKind)
0123 unsigned Kind : 31;
0124 LLVM_PREFERRED_TYPE(bool)
0125 unsigned IsDefaulted : 1;
0126
0127
0128
0129 unsigned BitWidth : 31;
0130 LLVM_PREFERRED_TYPE(bool)
0131 unsigned IsUnsigned : 1;
0132 union {
0133
0134 uint64_t VAL;
0135
0136
0137 const uint64_t *pVal;
0138 };
0139 void *Type;
0140 };
0141 struct V {
0142 LLVM_PREFERRED_TYPE(ArgKind)
0143 unsigned Kind : 31;
0144 LLVM_PREFERRED_TYPE(bool)
0145 unsigned IsDefaulted : 1;
0146 APValue *Value;
0147 void *Type;
0148 };
0149 struct A {
0150 LLVM_PREFERRED_TYPE(ArgKind)
0151 unsigned Kind : 31;
0152 LLVM_PREFERRED_TYPE(bool)
0153 unsigned IsDefaulted : 1;
0154 unsigned NumArgs;
0155 const TemplateArgument *Args;
0156 };
0157 struct TA {
0158 LLVM_PREFERRED_TYPE(ArgKind)
0159 unsigned Kind : 31;
0160 LLVM_PREFERRED_TYPE(bool)
0161 unsigned IsDefaulted : 1;
0162 unsigned NumExpansions;
0163 void *Name;
0164 };
0165 struct TV {
0166 LLVM_PREFERRED_TYPE(ArgKind)
0167 unsigned Kind : 31;
0168 LLVM_PREFERRED_TYPE(bool)
0169 unsigned IsDefaulted : 1;
0170 uintptr_t V;
0171 };
0172 union {
0173 struct DA DeclArg;
0174 struct I Integer;
0175 struct V Value;
0176 struct A Args;
0177 struct TA TemplateArg;
0178 struct TV TypeOrValue;
0179 };
0180
0181 void initFromType(QualType T, bool IsNullPtr, bool IsDefaulted);
0182 void initFromDeclaration(ValueDecl *D, QualType QT, bool IsDefaulted);
0183 void initFromIntegral(const ASTContext &Ctx, const llvm::APSInt &Value,
0184 QualType Type, bool IsDefaulted);
0185 void initFromStructural(const ASTContext &Ctx, QualType Type,
0186 const APValue &V, bool IsDefaulted);
0187
0188 public:
0189
0190 constexpr TemplateArgument() : TypeOrValue({Null, 0, 0}) {}
0191
0192
0193 TemplateArgument(QualType T, bool isNullPtr = false,
0194 bool IsDefaulted = false) {
0195 initFromType(T, isNullPtr, IsDefaulted);
0196 }
0197
0198
0199
0200 TemplateArgument(ValueDecl *D, QualType QT, bool IsDefaulted = false) {
0201 initFromDeclaration(D, QT, IsDefaulted);
0202 }
0203
0204
0205
0206 TemplateArgument(const ASTContext &Ctx, const llvm::APSInt &Value,
0207 QualType Type, bool IsDefaulted = false);
0208
0209
0210 TemplateArgument(const ASTContext &Ctx, QualType Type, const APValue &Value,
0211 bool IsDefaulted = false);
0212
0213
0214
0215 TemplateArgument(const TemplateArgument &Other, QualType Type) {
0216 Integer = Other.Integer;
0217 Integer.Type = Type.getAsOpaquePtr();
0218 }
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231 TemplateArgument(TemplateName Name, bool IsDefaulted = false) {
0232 TemplateArg.Kind = Template;
0233 TemplateArg.IsDefaulted = IsDefaulted;
0234 TemplateArg.Name = Name.getAsVoidPointer();
0235 TemplateArg.NumExpansions = 0;
0236 }
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252 TemplateArgument(TemplateName Name, std::optional<unsigned> NumExpansions,
0253 bool IsDefaulted = false) {
0254 TemplateArg.Kind = TemplateExpansion;
0255 TemplateArg.IsDefaulted = IsDefaulted;
0256 TemplateArg.Name = Name.getAsVoidPointer();
0257 if (NumExpansions)
0258 TemplateArg.NumExpansions = *NumExpansions + 1;
0259 else
0260 TemplateArg.NumExpansions = 0;
0261 }
0262
0263
0264
0265
0266
0267
0268 TemplateArgument(Expr *E, bool IsDefaulted = false) {
0269 TypeOrValue.Kind = Expression;
0270 TypeOrValue.IsDefaulted = IsDefaulted;
0271 TypeOrValue.V = reinterpret_cast<uintptr_t>(E);
0272 }
0273
0274
0275
0276
0277
0278 explicit TemplateArgument(ArrayRef<TemplateArgument> Args) {
0279 this->Args.Kind = Pack;
0280 this->Args.IsDefaulted = false;
0281 this->Args.Args = Args.data();
0282 this->Args.NumArgs = Args.size();
0283 }
0284
0285 static TemplateArgument getEmptyPack() {
0286 return TemplateArgument(ArrayRef<TemplateArgument>());
0287 }
0288
0289
0290
0291 static TemplateArgument CreatePackCopy(ASTContext &Context,
0292 ArrayRef<TemplateArgument> Args);
0293
0294
0295 ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; }
0296
0297
0298 bool isNull() const { return getKind() == Null; }
0299
0300 TemplateArgumentDependence getDependence() const;
0301
0302
0303
0304
0305 bool isDependent() const;
0306
0307
0308
0309 bool isInstantiationDependent() const;
0310
0311
0312
0313 bool containsUnexpandedParameterPack() const;
0314
0315
0316 bool isPackExpansion() const;
0317
0318
0319 QualType getAsType() const {
0320 assert(getKind() == Type && "Unexpected kind");
0321 return QualType::getFromOpaquePtr(reinterpret_cast<void *>(TypeOrValue.V));
0322 }
0323
0324
0325
0326 ValueDecl *getAsDecl() const {
0327 assert(getKind() == Declaration && "Unexpected kind");
0328 return DeclArg.D;
0329 }
0330
0331 QualType getParamTypeForDecl() const {
0332 assert(getKind() == Declaration && "Unexpected kind");
0333 return QualType::getFromOpaquePtr(DeclArg.QT);
0334 }
0335
0336
0337 QualType getNullPtrType() const {
0338 assert(getKind() == NullPtr && "Unexpected kind");
0339 return QualType::getFromOpaquePtr(reinterpret_cast<void *>(TypeOrValue.V));
0340 }
0341
0342
0343 TemplateName getAsTemplate() const {
0344 assert(getKind() == Template && "Unexpected kind");
0345 return TemplateName::getFromVoidPointer(TemplateArg.Name);
0346 }
0347
0348
0349
0350 TemplateName getAsTemplateOrTemplatePattern() const {
0351 assert((getKind() == Template || getKind() == TemplateExpansion) &&
0352 "Unexpected kind");
0353
0354 return TemplateName::getFromVoidPointer(TemplateArg.Name);
0355 }
0356
0357
0358
0359 std::optional<unsigned> getNumTemplateExpansions() const;
0360
0361
0362
0363 llvm::APSInt getAsIntegral() const {
0364 assert(getKind() == Integral && "Unexpected kind");
0365
0366 using namespace llvm;
0367
0368 if (Integer.BitWidth <= 64)
0369 return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned);
0370
0371 unsigned NumWords = APInt::getNumWords(Integer.BitWidth);
0372 return APSInt(APInt(Integer.BitWidth, ArrayRef(Integer.pVal, NumWords)),
0373 Integer.IsUnsigned);
0374 }
0375
0376
0377 QualType getIntegralType() const {
0378 assert(getKind() == Integral && "Unexpected kind");
0379 return QualType::getFromOpaquePtr(Integer.Type);
0380 }
0381
0382 void setIntegralType(QualType T) {
0383 assert(getKind() == Integral && "Unexpected kind");
0384 Integer.Type = T.getAsOpaquePtr();
0385 }
0386
0387
0388
0389 void setIsDefaulted(bool v) { TypeOrValue.IsDefaulted = v; }
0390
0391
0392
0393 bool getIsDefaulted() const { return (bool)TypeOrValue.IsDefaulted; }
0394
0395
0396 const APValue &getAsStructuralValue() const { return *Value.Value; }
0397
0398
0399 QualType getStructuralValueType() const {
0400 return QualType::getFromOpaquePtr(Value.Type);
0401 }
0402
0403
0404
0405 QualType getNonTypeTemplateArgumentType() const;
0406
0407
0408 Expr *getAsExpr() const {
0409 assert(getKind() == Expression && "Unexpected kind");
0410 return reinterpret_cast<Expr *>(TypeOrValue.V);
0411 }
0412
0413
0414 using pack_iterator = const TemplateArgument *;
0415
0416
0417
0418 pack_iterator pack_begin() const {
0419 assert(getKind() == Pack);
0420 return Args.Args;
0421 }
0422
0423
0424
0425 pack_iterator pack_end() const {
0426 assert(getKind() == Pack);
0427 return Args.Args + Args.NumArgs;
0428 }
0429
0430
0431
0432 ArrayRef<TemplateArgument> pack_elements() const {
0433 return llvm::ArrayRef(pack_begin(), pack_end());
0434 }
0435
0436
0437
0438 unsigned pack_size() const {
0439 assert(getKind() == Pack);
0440 return Args.NumArgs;
0441 }
0442
0443
0444 ArrayRef<TemplateArgument> getPackAsArray() const {
0445 assert(getKind() == Pack);
0446 return llvm::ArrayRef(Args.Args, Args.NumArgs);
0447 }
0448
0449
0450
0451 bool structurallyEquals(const TemplateArgument &Other) const;
0452
0453
0454
0455 TemplateArgument getPackExpansionPattern() const;
0456
0457
0458 void print(const PrintingPolicy &Policy, raw_ostream &Out,
0459 bool IncludeType) const;
0460
0461
0462 void dump(raw_ostream &Out, const ASTContext &Context) const;
0463
0464
0465 void dump() const;
0466
0467
0468 void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const;
0469 };
0470
0471
0472 struct TemplateArgumentLocInfo {
0473 private:
0474 struct TemplateTemplateArgLocInfo {
0475
0476
0477 NestedNameSpecifier *Qualifier;
0478 void *QualifierLocData;
0479 SourceLocation TemplateNameLoc;
0480 SourceLocation EllipsisLoc;
0481 };
0482
0483 llvm::PointerUnion<TemplateTemplateArgLocInfo *, Expr *, TypeSourceInfo *>
0484 Pointer;
0485
0486 TemplateTemplateArgLocInfo *getTemplate() const {
0487 return cast<TemplateTemplateArgLocInfo *>(Pointer);
0488 }
0489
0490 public:
0491 TemplateArgumentLocInfo() {}
0492 TemplateArgumentLocInfo(TypeSourceInfo *Declarator) { Pointer = Declarator; }
0493
0494 TemplateArgumentLocInfo(Expr *E) { Pointer = E; }
0495
0496
0497 TemplateArgumentLocInfo(ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc,
0498 SourceLocation TemplateNameLoc,
0499 SourceLocation EllipsisLoc);
0500
0501 TypeSourceInfo *getAsTypeSourceInfo() const {
0502 return cast<TypeSourceInfo *>(Pointer);
0503 }
0504
0505 Expr *getAsExpr() const { return cast<Expr *>(Pointer); }
0506
0507 NestedNameSpecifierLoc getTemplateQualifierLoc() const {
0508 const auto *Template = getTemplate();
0509 return NestedNameSpecifierLoc(Template->Qualifier,
0510 Template->QualifierLocData);
0511 }
0512
0513 SourceLocation getTemplateNameLoc() const {
0514 return getTemplate()->TemplateNameLoc;
0515 }
0516
0517 SourceLocation getTemplateEllipsisLoc() const {
0518 return getTemplate()->EllipsisLoc;
0519 }
0520 };
0521
0522
0523
0524 class TemplateArgumentLoc {
0525 TemplateArgument Argument;
0526 TemplateArgumentLocInfo LocInfo;
0527
0528 public:
0529 TemplateArgumentLoc() {}
0530
0531 TemplateArgumentLoc(const TemplateArgument &Argument,
0532 TemplateArgumentLocInfo Opaque)
0533 : Argument(Argument), LocInfo(Opaque) {}
0534
0535 TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo)
0536 : Argument(Argument), LocInfo(TInfo) {
0537 assert(Argument.getKind() == TemplateArgument::Type);
0538 }
0539
0540 TemplateArgumentLoc(const TemplateArgument &Argument, Expr *E)
0541 : Argument(Argument), LocInfo(E) {
0542
0543
0544
0545 assert(Argument.getKind() == TemplateArgument::NullPtr ||
0546 Argument.getKind() == TemplateArgument::Integral ||
0547 Argument.getKind() == TemplateArgument::Declaration ||
0548 Argument.getKind() == TemplateArgument::StructuralValue ||
0549 Argument.getKind() == TemplateArgument::Expression);
0550 }
0551
0552 TemplateArgumentLoc(ASTContext &Ctx, const TemplateArgument &Argument,
0553 NestedNameSpecifierLoc QualifierLoc,
0554 SourceLocation TemplateNameLoc,
0555 SourceLocation EllipsisLoc = SourceLocation())
0556 : Argument(Argument),
0557 LocInfo(Ctx, QualifierLoc, TemplateNameLoc, EllipsisLoc) {
0558 assert(Argument.getKind() == TemplateArgument::Template ||
0559 Argument.getKind() == TemplateArgument::TemplateExpansion);
0560 }
0561
0562
0563 SourceLocation getLocation() const {
0564 if (Argument.getKind() == TemplateArgument::Template ||
0565 Argument.getKind() == TemplateArgument::TemplateExpansion)
0566 return getTemplateNameLoc();
0567
0568 return getSourceRange().getBegin();
0569 }
0570
0571
0572 SourceRange getSourceRange() const LLVM_READONLY;
0573
0574 const TemplateArgument &getArgument() const { return Argument; }
0575
0576 TemplateArgumentLocInfo getLocInfo() const { return LocInfo; }
0577
0578 TypeSourceInfo *getTypeSourceInfo() const {
0579 if (Argument.getKind() != TemplateArgument::Type)
0580 return nullptr;
0581 return LocInfo.getAsTypeSourceInfo();
0582 }
0583
0584 Expr *getSourceExpression() const {
0585 assert(Argument.getKind() == TemplateArgument::Expression);
0586 return LocInfo.getAsExpr();
0587 }
0588
0589 Expr *getSourceDeclExpression() const {
0590 assert(Argument.getKind() == TemplateArgument::Declaration);
0591 return LocInfo.getAsExpr();
0592 }
0593
0594 Expr *getSourceNullPtrExpression() const {
0595 assert(Argument.getKind() == TemplateArgument::NullPtr);
0596 return LocInfo.getAsExpr();
0597 }
0598
0599 Expr *getSourceIntegralExpression() const {
0600 assert(Argument.getKind() == TemplateArgument::Integral);
0601 return LocInfo.getAsExpr();
0602 }
0603
0604 Expr *getSourceStructuralValueExpression() const {
0605 assert(Argument.getKind() == TemplateArgument::StructuralValue);
0606 return LocInfo.getAsExpr();
0607 }
0608
0609 NestedNameSpecifierLoc getTemplateQualifierLoc() const {
0610 if (Argument.getKind() != TemplateArgument::Template &&
0611 Argument.getKind() != TemplateArgument::TemplateExpansion)
0612 return NestedNameSpecifierLoc();
0613 return LocInfo.getTemplateQualifierLoc();
0614 }
0615
0616 SourceLocation getTemplateNameLoc() const {
0617 if (Argument.getKind() != TemplateArgument::Template &&
0618 Argument.getKind() != TemplateArgument::TemplateExpansion)
0619 return SourceLocation();
0620 return LocInfo.getTemplateNameLoc();
0621 }
0622
0623 SourceLocation getTemplateEllipsisLoc() const {
0624 if (Argument.getKind() != TemplateArgument::TemplateExpansion)
0625 return SourceLocation();
0626 return LocInfo.getTemplateEllipsisLoc();
0627 }
0628 };
0629
0630
0631
0632 class TemplateArgumentListInfo {
0633 SmallVector<TemplateArgumentLoc, 8> Arguments;
0634 SourceLocation LAngleLoc;
0635 SourceLocation RAngleLoc;
0636
0637 public:
0638 TemplateArgumentListInfo() = default;
0639
0640 TemplateArgumentListInfo(SourceLocation LAngleLoc, SourceLocation RAngleLoc)
0641 : LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc) {}
0642
0643
0644
0645 void *operator new(size_t bytes, ASTContext &C) = delete;
0646
0647 SourceLocation getLAngleLoc() const { return LAngleLoc; }
0648 SourceLocation getRAngleLoc() const { return RAngleLoc; }
0649
0650 void setLAngleLoc(SourceLocation Loc) { LAngleLoc = Loc; }
0651 void setRAngleLoc(SourceLocation Loc) { RAngleLoc = Loc; }
0652
0653 unsigned size() const { return Arguments.size(); }
0654
0655 const TemplateArgumentLoc *getArgumentArray() const {
0656 return Arguments.data();
0657 }
0658
0659 llvm::ArrayRef<TemplateArgumentLoc> arguments() const { return Arguments; }
0660
0661 const TemplateArgumentLoc &operator[](unsigned I) const {
0662 return Arguments[I];
0663 }
0664
0665 TemplateArgumentLoc &operator[](unsigned I) { return Arguments[I]; }
0666
0667 void addArgument(const TemplateArgumentLoc &Loc) { Arguments.push_back(Loc); }
0668 };
0669
0670
0671
0672
0673
0674 struct ASTTemplateArgumentListInfo final
0675 : private llvm::TrailingObjects<ASTTemplateArgumentListInfo,
0676 TemplateArgumentLoc> {
0677 private:
0678 friend class ASTNodeImporter;
0679 friend TrailingObjects;
0680
0681 ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List);
0682
0683
0684 ASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo *List);
0685
0686 public:
0687
0688 SourceLocation LAngleLoc;
0689
0690
0691 SourceLocation RAngleLoc;
0692
0693
0694 unsigned NumTemplateArgs;
0695
0696 SourceLocation getLAngleLoc() const { return LAngleLoc; }
0697 SourceLocation getRAngleLoc() const { return RAngleLoc; }
0698
0699
0700 const TemplateArgumentLoc *getTemplateArgs() const {
0701 return getTrailingObjects<TemplateArgumentLoc>();
0702 }
0703 unsigned getNumTemplateArgs() const { return NumTemplateArgs; }
0704
0705 llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
0706 return llvm::ArrayRef(getTemplateArgs(), getNumTemplateArgs());
0707 }
0708
0709 const TemplateArgumentLoc &operator[](unsigned I) const {
0710 return getTemplateArgs()[I];
0711 }
0712
0713 static const ASTTemplateArgumentListInfo *
0714 Create(const ASTContext &C, const TemplateArgumentListInfo &List);
0715
0716
0717 static const ASTTemplateArgumentListInfo *
0718 Create(const ASTContext &C, const ASTTemplateArgumentListInfo *List);
0719 };
0720
0721
0722
0723
0724
0725
0726
0727
0728 struct alignas(void *) ASTTemplateKWAndArgsInfo {
0729
0730 SourceLocation LAngleLoc;
0731
0732
0733 SourceLocation RAngleLoc;
0734
0735
0736
0737
0738
0739 SourceLocation TemplateKWLoc;
0740
0741
0742 unsigned NumTemplateArgs;
0743
0744 void initializeFrom(SourceLocation TemplateKWLoc,
0745 const TemplateArgumentListInfo &List,
0746 TemplateArgumentLoc *OutArgArray);
0747
0748
0749
0750 void initializeFrom(SourceLocation TemplateKWLoc,
0751 const TemplateArgumentListInfo &List,
0752 TemplateArgumentLoc *OutArgArray,
0753 TemplateArgumentDependence &Deps);
0754 void initializeFrom(SourceLocation TemplateKWLoc);
0755
0756 void copyInto(const TemplateArgumentLoc *ArgArray,
0757 TemplateArgumentListInfo &List) const;
0758 };
0759
0760 const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
0761 const TemplateArgument &Arg);
0762
0763 }
0764
0765 #endif