1//===- DeclTemplate.cpp - Template Declaration AST Node Implementation ----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the C++ related Decl classes for templates.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/AST/DeclTemplate.h"
14#include "clang/AST/ASTContext.h"
15#include "clang/AST/ASTMutationListener.h"
16#include "clang/AST/DeclCXX.h"
17#include "clang/AST/DeclarationName.h"
18#include "clang/AST/Expr.h"
19#include "clang/AST/ExprCXX.h"
20#include "clang/AST/ExternalASTSource.h"
21#include "clang/AST/ODRHash.h"
22#include "clang/AST/TemplateBase.h"
23#include "clang/AST/TemplateName.h"
24#include "clang/AST/Type.h"
25#include "clang/AST/TypeLoc.h"
26#include "clang/Basic/Builtins.h"
27#include "clang/Basic/LLVM.h"
28#include "clang/Basic/SourceLocation.h"
29#include "llvm/ADT/ArrayRef.h"
30#include "llvm/ADT/FoldingSet.h"
31#include "llvm/ADT/PointerUnion.h"
32#include "llvm/ADT/STLExtras.h"
33#include "llvm/ADT/SmallVector.h"
34#include "llvm/Support/ErrorHandling.h"
35#include <cassert>
36#include <optional>
37#include <utility>
38
39using namespace clang;
40
41//===----------------------------------------------------------------------===//
42// TemplateParameterList Implementation
43//===----------------------------------------------------------------------===//
44
45template <class TemplateParam>
46static bool
47DefaultTemplateArgumentContainsUnexpandedPack(const TemplateParam &P) {
48 return P.hasDefaultArgument() &&
49 P.getDefaultArgument().getArgument().containsUnexpandedParameterPack();
50}
51
52TemplateParameterList::TemplateParameterList(const ASTContext &C,
53 SourceLocation TemplateLoc,
54 SourceLocation LAngleLoc,
55 ArrayRef<NamedDecl *> Params,
56 SourceLocation RAngleLoc,
57 Expr *RequiresClause)
58 : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
59 NumParams(Params.size()), ContainsUnexpandedParameterPack(false),
60 HasRequiresClause(RequiresClause != nullptr),
61 HasConstrainedParameters(false) {
62 for (unsigned Idx = 0; Idx < NumParams; ++Idx) {
63 NamedDecl *P = Params[Idx];
64 begin()[Idx] = P;
65
66 bool IsPack = P->isTemplateParameterPack();
67 if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: P)) {
68 if (!IsPack && (NTTP->getType()->containsUnexpandedParameterPack() ||
69 DefaultTemplateArgumentContainsUnexpandedPack(P: *NTTP)))
70 ContainsUnexpandedParameterPack = true;
71 if (NTTP->hasPlaceholderTypeConstraint())
72 HasConstrainedParameters = true;
73 } else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Val: P)) {
74 if (!IsPack &&
75 (TTP->getTemplateParameters()->containsUnexpandedParameterPack() ||
76 DefaultTemplateArgumentContainsUnexpandedPack(P: *TTP))) {
77 ContainsUnexpandedParameterPack = true;
78 }
79 } else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Val: P)) {
80 if (!IsPack && DefaultTemplateArgumentContainsUnexpandedPack(P: *TTP)) {
81 ContainsUnexpandedParameterPack = true;
82 } else if (const TypeConstraint *TC = TTP->getTypeConstraint();
83 TC && TC->getImmediatelyDeclaredConstraint()
84 ->containsUnexpandedParameterPack()) {
85 ContainsUnexpandedParameterPack = true;
86 }
87 if (TTP->hasTypeConstraint())
88 HasConstrainedParameters = true;
89 } else {
90 llvm_unreachable("unexpected template parameter type");
91 }
92 }
93
94 if (HasRequiresClause) {
95 if (RequiresClause->containsUnexpandedParameterPack())
96 ContainsUnexpandedParameterPack = true;
97 *getTrailingObjects<Expr *>() = RequiresClause;
98 }
99}
100
101bool TemplateParameterList::containsUnexpandedParameterPack() const {
102 if (ContainsUnexpandedParameterPack)
103 return true;
104 if (!HasConstrainedParameters)
105 return false;
106
107 // An implicit constrained parameter might have had a use of an unexpanded
108 // pack added to it after the template parameter list was created. All
109 // implicit parameters are at the end of the parameter list.
110 for (const NamedDecl *Param : llvm::reverse(C: asArray())) {
111 if (!Param->isImplicit())
112 break;
113
114 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Val: Param)) {
115 const auto *TC = TTP->getTypeConstraint();
116 if (TC && TC->getImmediatelyDeclaredConstraint()
117 ->containsUnexpandedParameterPack())
118 return true;
119 }
120 }
121
122 return false;
123}
124
125TemplateParameterList *
126TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc,
127 SourceLocation LAngleLoc,
128 ArrayRef<NamedDecl *> Params,
129 SourceLocation RAngleLoc, Expr *RequiresClause) {
130 void *Mem = C.Allocate(Size: totalSizeToAlloc<NamedDecl *, Expr *>(
131 Counts: Params.size(), Counts: RequiresClause ? 1u : 0u),
132 Align: alignof(TemplateParameterList));
133 return new (Mem) TemplateParameterList(C, TemplateLoc, LAngleLoc, Params,
134 RAngleLoc, RequiresClause);
135}
136
137void TemplateParameterList::Profile(llvm::FoldingSetNodeID &ID,
138 const ASTContext &C) const {
139 const Expr *RC = getRequiresClause();
140 ID.AddBoolean(B: RC != nullptr);
141 if (RC)
142 RC->Profile(ID, Context: C, /*Canonical=*/true);
143 ID.AddInteger(I: size());
144 for (NamedDecl *D : *this) {
145 if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: D)) {
146 ID.AddInteger(I: 0);
147 ID.AddBoolean(B: NTTP->isParameterPack());
148 NTTP->getType().getCanonicalType().Profile(ID);
149 ID.AddBoolean(B: NTTP->hasPlaceholderTypeConstraint());
150 if (const Expr *E = NTTP->getPlaceholderTypeConstraint())
151 E->Profile(ID, Context: C, /*Canonical=*/true);
152 continue;
153 }
154 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Val: D)) {
155 ID.AddInteger(I: 1);
156 ID.AddBoolean(B: TTP->isParameterPack());
157 ID.AddBoolean(B: TTP->hasTypeConstraint());
158 if (const TypeConstraint *TC = TTP->getTypeConstraint())
159 TC->getImmediatelyDeclaredConstraint()->Profile(ID, Context: C,
160 /*Canonical=*/true);
161 continue;
162 }
163 const auto *TTP = cast<TemplateTemplateParmDecl>(Val: D);
164 ID.AddInteger(I: 2);
165 ID.AddInteger(I: TTP->templateParameterKind());
166 ID.AddBoolean(B: TTP->isParameterPack());
167 TTP->getTemplateParameters()->Profile(ID, C);
168 }
169}
170
171unsigned TemplateParameterList::getMinRequiredArguments() const {
172 unsigned NumRequiredArgs = 0;
173 for (const NamedDecl *P : asArray()) {
174 if (P->isTemplateParameterPack()) {
175 if (UnsignedOrNone Expansions = getExpandedPackSize(Param: P)) {
176 NumRequiredArgs += *Expansions;
177 continue;
178 }
179 break;
180 }
181
182 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Val: P)) {
183 if (TTP->hasDefaultArgument())
184 break;
185 } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: P)) {
186 if (NTTP->hasDefaultArgument())
187 break;
188 } else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Val: P);
189 TTP && TTP->hasDefaultArgument())
190 break;
191
192 ++NumRequiredArgs;
193 }
194
195 return NumRequiredArgs;
196}
197
198unsigned TemplateParameterList::getDepth() const {
199 if (size() == 0)
200 return 0;
201
202 const NamedDecl *FirstParm = getParam(Idx: 0);
203 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Val: FirstParm))
204 return TTP->getDepth();
205 else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: FirstParm))
206 return NTTP->getDepth();
207 else
208 return cast<TemplateTemplateParmDecl>(Val: FirstParm)->getDepth();
209}
210
211static bool AdoptTemplateParameterList(TemplateParameterList *Params,
212 DeclContext *Owner) {
213 bool Invalid = false;
214 for (NamedDecl *P : *Params) {
215 P->setDeclContext(Owner);
216
217 if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Val: P))
218 if (AdoptTemplateParameterList(Params: TTP->getTemplateParameters(), Owner))
219 Invalid = true;
220
221 if (P->isInvalidDecl())
222 Invalid = true;
223 }
224 return Invalid;
225}
226
227void TemplateParameterList::getAssociatedConstraints(
228 llvm::SmallVectorImpl<AssociatedConstraint> &ACs) const {
229 if (HasConstrainedParameters)
230 for (const NamedDecl *Param : *this) {
231 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Val: Param)) {
232 if (const auto *TC = TTP->getTypeConstraint())
233 ACs.emplace_back(Args: TC->getImmediatelyDeclaredConstraint(),
234 Args: TC->getArgPackSubstIndex());
235 } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: Param)) {
236 if (const Expr *E = NTTP->getPlaceholderTypeConstraint())
237 ACs.emplace_back(Args&: E);
238 }
239 }
240 if (HasRequiresClause)
241 ACs.emplace_back(Args: getRequiresClause());
242}
243
244bool TemplateParameterList::hasAssociatedConstraints() const {
245 return HasRequiresClause || HasConstrainedParameters;
246}
247
248ArrayRef<TemplateArgument>
249TemplateParameterList::getInjectedTemplateArgs(const ASTContext &Context) {
250 if (!InjectedArgs) {
251 InjectedArgs = new (Context) TemplateArgument[size()];
252 llvm::transform(Range&: *this, d_first: InjectedArgs, F: [&](NamedDecl *ND) {
253 return Context.getInjectedTemplateArg(ParamDecl: ND);
254 });
255 }
256 return {InjectedArgs, NumParams};
257}
258
259bool TemplateParameterList::shouldIncludeTypeForArgument(
260 const PrintingPolicy &Policy, const TemplateParameterList *TPL,
261 unsigned Idx) {
262 if (!TPL || Idx >= TPL->size() || Policy.AlwaysIncludeTypeForTemplateArgument)
263 return true;
264 const NamedDecl *TemplParam = TPL->getParam(Idx);
265 if (const auto *ParamValueDecl =
266 dyn_cast<NonTypeTemplateParmDecl>(Val: TemplParam))
267 if (ParamValueDecl->getType()->getContainedDeducedType())
268 return true;
269 return false;
270}
271
272namespace clang {
273
274void *allocateDefaultArgStorageChain(const ASTContext &C) {
275 return new (C) char[sizeof(void*) * 2];
276}
277
278} // namespace clang
279
280//===----------------------------------------------------------------------===//
281// TemplateDecl Implementation
282//===----------------------------------------------------------------------===//
283
284TemplateDecl::TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
285 DeclarationName Name, TemplateParameterList *Params,
286 NamedDecl *Decl)
287 : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), TemplateParams(Params) {}
288
289void TemplateDecl::anchor() {}
290
291void TemplateDecl::getAssociatedConstraints(
292 llvm::SmallVectorImpl<AssociatedConstraint> &ACs) const {
293 TemplateParams->getAssociatedConstraints(ACs);
294 if (auto *FD = dyn_cast_or_null<FunctionDecl>(Val: getTemplatedDecl()))
295 if (const AssociatedConstraint &TRC = FD->getTrailingRequiresClause())
296 ACs.emplace_back(Args: TRC);
297}
298
299bool TemplateDecl::hasAssociatedConstraints() const {
300 if (TemplateParams->hasAssociatedConstraints())
301 return true;
302 if (auto *FD = dyn_cast_or_null<FunctionDecl>(Val: getTemplatedDecl()))
303 return static_cast<bool>(FD->getTrailingRequiresClause());
304 return false;
305}
306
307bool TemplateDecl::isTypeAlias() const {
308 switch (getKind()) {
309 case TemplateDecl::TypeAliasTemplate:
310 return true;
311 case TemplateDecl::BuiltinTemplate:
312 return !cast<BuiltinTemplateDecl>(Val: this)->isPackProducingBuiltinTemplate();
313 default:
314 return false;
315 };
316}
317
318//===----------------------------------------------------------------------===//
319// RedeclarableTemplateDecl Implementation
320//===----------------------------------------------------------------------===//
321
322void RedeclarableTemplateDecl::anchor() {}
323
324RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() const {
325 if (Common)
326 return Common;
327
328 // Walk the previous-declaration chain until we either find a declaration
329 // with a common pointer or we run out of previous declarations.
330 SmallVector<const RedeclarableTemplateDecl *, 2> PrevDecls;
331 for (const RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev;
332 Prev = Prev->getPreviousDecl()) {
333 if (Prev->Common) {
334 Common = Prev->Common;
335 break;
336 }
337
338 PrevDecls.push_back(Elt: Prev);
339 }
340
341 // If we never found a common pointer, allocate one now.
342 if (!Common) {
343 // FIXME: If any of the declarations is from an AST file, we probably
344 // need an update record to add the common data.
345
346 Common = newCommon(C&: getASTContext());
347 }
348
349 // Update any previous declarations we saw with the common pointer.
350 for (const RedeclarableTemplateDecl *Prev : PrevDecls)
351 Prev->Common = Common;
352
353 return Common;
354}
355
356void RedeclarableTemplateDecl::loadLazySpecializationsImpl(
357 bool OnlyPartial /*=false*/) const {
358 auto *ExternalSource = getASTContext().getExternalSource();
359 if (!ExternalSource)
360 return;
361
362 ExternalSource->LoadExternalSpecializations(D: this->getCanonicalDecl(),
363 OnlyPartial);
364}
365
366bool RedeclarableTemplateDecl::loadLazySpecializationsImpl(
367 ArrayRef<TemplateArgument> Args, TemplateParameterList *TPL) const {
368 auto *ExternalSource = getASTContext().getExternalSource();
369 if (!ExternalSource)
370 return false;
371
372 return ExternalSource->LoadExternalSpecializations(D: this->getCanonicalDecl(),
373 TemplateArgs: Args);
374}
375
376template <class EntryType, typename... ProfileArguments>
377typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
378RedeclarableTemplateDecl::findSpecializationLocally(
379 llvm::FoldingSetVector<EntryType> &Specs,
380 llvm::FoldingSetInsertToken &InsertToken, ProfileArguments... ProfileArgs) {
381 using SETraits = RedeclarableTemplateDecl::SpecEntryTraits<EntryType>;
382
383 llvm::FoldingSetNodeID ID;
384 EntryType::Profile(ID, ProfileArgs..., getASTContext());
385 EntryType *Entry = Specs.lookup(ID, InsertToken);
386 return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr;
387}
388
389template <class EntryType, typename... ProfileArguments>
390typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
391RedeclarableTemplateDecl::findSpecializationImpl(
392 llvm::FoldingSetVector<EntryType> &Specs,
393 llvm::FoldingSetInsertToken &InsertToken, ProfileArguments... ProfileArgs) {
394
395 if (auto *Found =
396 findSpecializationLocally(Specs, InsertToken, ProfileArgs...))
397 return Found;
398
399 if (!loadLazySpecializationsImpl(ProfileArgs...))
400 return nullptr;
401
402 return findSpecializationLocally(Specs, InsertToken, ProfileArgs...);
403}
404
405template <class Derived, class EntryType>
406void RedeclarableTemplateDecl::addSpecializationImpl(
407 llvm::FoldingSetVector<EntryType> &Specializations, EntryType *Entry,
408 llvm::FoldingSetInsertToken InsertToken) {
409 using SETraits = SpecEntryTraits<EntryType>;
410
411 if (InsertToken) {
412#ifndef NDEBUG
413 auto Args = SETraits::getTemplateArgs(Entry);
414 // Due to hash collisions, it can happen that we load another template
415 // specialization with the same hash. This is fine, as long as the next
416 // call to findSpecializationImpl does not find a matching Decl for the
417 // template arguments.
418 loadLazySpecializationsImpl(Args);
419 llvm::FoldingSetInsertToken CorrectToken;
420 assert(!findSpecializationImpl(Specializations, CorrectToken, Args) &&
421 InsertToken == CorrectToken &&
422 "given incorrect InsertToken for specialization");
423#endif
424 Specializations.insert(Entry, InsertToken);
425 } else {
426 EntryType *Existing = Specializations.getOrInsert(Entry);
427 (void)Existing;
428 assert(SETraits::getDecl(Existing)->isCanonicalDecl() &&
429 "non-canonical specialization?");
430 }
431
432 if (ASTMutationListener *L = getASTMutationListener())
433 L->AddedCXXTemplateSpecialization(cast<Derived>(this),
434 SETraits::getDecl(Entry));
435}
436
437//===----------------------------------------------------------------------===//
438// FunctionTemplateDecl Implementation
439//===----------------------------------------------------------------------===//
440
441FunctionTemplateDecl *
442FunctionTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
443 DeclarationName Name,
444 TemplateParameterList *Params, NamedDecl *Decl) {
445 assert(!Params->empty() && "template with no template parameters");
446 bool Invalid = AdoptTemplateParameterList(Params, Owner: cast<DeclContext>(Val: Decl));
447 auto *TD = new (C, DC) FunctionTemplateDecl(C, DC, L, Name, Params, Decl);
448 if (Invalid)
449 TD->setInvalidDecl();
450 return TD;
451}
452
453FunctionTemplateDecl *
454FunctionTemplateDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
455 return new (C, ID) FunctionTemplateDecl(C, nullptr, SourceLocation(),
456 DeclarationName(), nullptr, nullptr);
457}
458
459RedeclarableTemplateDecl::CommonBase *
460FunctionTemplateDecl::newCommon(ASTContext &C) const {
461 auto *CommonPtr = new (C) Common;
462 C.addDestruction(Ptr: CommonPtr);
463 return CommonPtr;
464}
465
466void FunctionTemplateDecl::LoadLazySpecializations() const {
467 loadLazySpecializationsImpl();
468}
469
470llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
471FunctionTemplateDecl::getSpecializations() const {
472 LoadLazySpecializations();
473 return getCommonPtr()->Specializations;
474}
475
476FunctionDecl *FunctionTemplateDecl::findSpecialization(
477 ArrayRef<TemplateArgument> Args, llvm::FoldingSetInsertToken &InsertToken) {
478 auto *Common = getCommonPtr();
479 return findSpecializationImpl(Specs&: Common->Specializations, InsertToken, ProfileArgs: Args);
480}
481
482void FunctionTemplateDecl::addSpecialization(
483 FunctionTemplateSpecializationInfo *Info,
484 llvm::FoldingSetInsertToken InsertToken) {
485 auto *Common = getCommonPtr();
486 addSpecializationImpl<FunctionTemplateDecl>(Specializations&: Common->Specializations, Entry: Info,
487 InsertToken);
488}
489
490void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
491 using Base = RedeclarableTemplateDecl;
492
493 // If we haven't created a common pointer yet, then it can just be created
494 // with the usual method.
495 if (!Base::Common)
496 return;
497
498 Common *ThisCommon = static_cast<Common *>(Base::Common);
499 Common *PrevCommon = nullptr;
500 SmallVector<FunctionTemplateDecl *, 8> PreviousDecls;
501 for (; Prev; Prev = Prev->getPreviousDecl()) {
502 if (Prev->Base::Common) {
503 PrevCommon = static_cast<Common *>(Prev->Base::Common);
504 break;
505 }
506 PreviousDecls.push_back(Elt: Prev);
507 }
508
509 // If the previous redecl chain hasn't created a common pointer yet, then just
510 // use this common pointer.
511 if (!PrevCommon) {
512 for (auto *D : PreviousDecls)
513 D->Base::Common = ThisCommon;
514 return;
515 }
516
517 // Ensure we don't leak any important state.
518 assert(ThisCommon->Specializations.size() == 0 &&
519 "Can't merge incompatible declarations!");
520
521 Base::Common = PrevCommon;
522}
523
524//===----------------------------------------------------------------------===//
525// ClassTemplateDecl Implementation
526//===----------------------------------------------------------------------===//
527
528ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, DeclContext *DC,
529 SourceLocation L,
530 DeclarationName Name,
531 TemplateParameterList *Params,
532 NamedDecl *Decl) {
533 assert(!Params->empty() && "template with no template parameters");
534 bool Invalid = AdoptTemplateParameterList(Params, Owner: cast<DeclContext>(Val: Decl));
535 auto *TD = new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
536 if (Invalid)
537 TD->setInvalidDecl();
538 return TD;
539}
540
541ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
542 GlobalDeclID ID) {
543 return new (C, ID) ClassTemplateDecl(C, nullptr, SourceLocation(),
544 DeclarationName(), nullptr, nullptr);
545}
546
547void ClassTemplateDecl::LoadLazySpecializations(
548 bool OnlyPartial /*=false*/) const {
549 loadLazySpecializationsImpl(OnlyPartial);
550}
551
552llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
553ClassTemplateDecl::getSpecializations() const {
554 LoadLazySpecializations();
555 return getCommonPtr()->Specializations;
556}
557
558llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
559ClassTemplateDecl::getPartialSpecializations() const {
560 LoadLazySpecializations(/*PartialOnly = */ OnlyPartial: true);
561 return getCommonPtr()->PartialSpecializations;
562}
563
564RedeclarableTemplateDecl::CommonBase *
565ClassTemplateDecl::newCommon(ASTContext &C) const {
566 auto *CommonPtr = new (C) Common;
567 C.addDestruction(Ptr: CommonPtr);
568 return CommonPtr;
569}
570
571ClassTemplateSpecializationDecl *ClassTemplateDecl::findSpecialization(
572 ArrayRef<TemplateArgument> Args, llvm::FoldingSetInsertToken &InsertToken) {
573 auto *Common = getCommonPtr();
574 return findSpecializationImpl(Specs&: Common->Specializations, InsertToken, ProfileArgs: Args);
575}
576
577void ClassTemplateDecl::AddSpecialization(
578 ClassTemplateSpecializationDecl *D,
579 llvm::FoldingSetInsertToken InsertToken) {
580 auto *Common = getCommonPtr();
581 addSpecializationImpl<ClassTemplateDecl>(Specializations&: Common->Specializations, Entry: D,
582 InsertToken);
583}
584
585ClassTemplatePartialSpecializationDecl *
586ClassTemplateDecl::findPartialSpecialization(
587 ArrayRef<TemplateArgument> Args, TemplateParameterList *TPL,
588 llvm::FoldingSetInsertToken &InsertToken) {
589 return findSpecializationImpl(Specs&: getPartialSpecializations(), InsertToken, ProfileArgs: Args,
590 ProfileArgs: TPL);
591}
592
593void ClassTemplatePartialSpecializationDecl::Profile(
594 llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
595 TemplateParameterList *TPL, const ASTContext &Context) {
596 ID.AddInteger(I: TemplateArgs.size());
597 for (const TemplateArgument &TemplateArg : TemplateArgs)
598 TemplateArg.Profile(ID, Context);
599 TPL->Profile(ID, C: Context);
600}
601
602void ClassTemplateDecl::AddPartialSpecialization(
603 ClassTemplatePartialSpecializationDecl *D,
604 llvm::FoldingSetInsertToken InsertToken) {
605 if (InsertToken)
606 getPartialSpecializations().insert(N: D, Token: InsertToken);
607 else {
608 ClassTemplatePartialSpecializationDecl *Existing =
609 getPartialSpecializations().getOrInsert(N: D);
610 (void)Existing;
611 assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
612 }
613
614 if (ASTMutationListener *L = getASTMutationListener())
615 L->AddedCXXTemplateSpecialization(TD: this, D);
616}
617
618void ClassTemplateDecl::getPartialSpecializations(
619 SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) const {
620 llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &PartialSpecs
621 = getPartialSpecializations();
622 PS.clear();
623 PS.reserve(N: PartialSpecs.size());
624 for (ClassTemplatePartialSpecializationDecl &P : PartialSpecs)
625 PS.push_back(Elt: P.getMostRecentDecl());
626}
627
628ClassTemplatePartialSpecializationDecl *
629ClassTemplateDecl::findPartialSpecialization(QualType T) {
630 ASTContext &Context = getASTContext();
631 for (ClassTemplatePartialSpecializationDecl &P :
632 getPartialSpecializations()) {
633 if (Context.hasSameType(T1: P.getCanonicalInjectedSpecializationType(Ctx: Context),
634 T2: T))
635 return P.getMostRecentDecl();
636 }
637
638 return nullptr;
639}
640
641ClassTemplatePartialSpecializationDecl *
642ClassTemplateDecl::findPartialSpecInstantiatedFromMember(
643 ClassTemplatePartialSpecializationDecl *D) {
644 Decl *DCanon = D->getCanonicalDecl();
645 for (ClassTemplatePartialSpecializationDecl &P : getPartialSpecializations()) {
646 if (P.getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
647 return P.getMostRecentDecl();
648 }
649
650 return nullptr;
651}
652
653CanQualType ClassTemplateDecl::getCanonicalInjectedSpecializationType(
654 const ASTContext &Ctx) const {
655 Common *CommonPtr = getCommonPtr();
656
657 if (CommonPtr->CanonInjectedTST.isNull()) {
658 SmallVector<TemplateArgument> CanonicalArgs(
659 getTemplateParameters()->getInjectedTemplateArgs(Context: Ctx));
660 Ctx.canonicalizeTemplateArguments(Args: CanonicalArgs);
661 CommonPtr->CanonInjectedTST =
662 CanQualType::CreateUnsafe(Other: Ctx.getCanonicalTemplateSpecializationType(
663 Keyword: ElaboratedTypeKeyword::None,
664 T: TemplateName(const_cast<ClassTemplateDecl *>(getCanonicalDecl())),
665 CanonicalArgs));
666 }
667 return CommonPtr->CanonInjectedTST;
668}
669
670//===----------------------------------------------------------------------===//
671// TemplateTypeParm Allocation/Deallocation Method Implementations
672//===----------------------------------------------------------------------===//
673
674TemplateTypeParmDecl *TemplateTypeParmDecl::Create(
675 const ASTContext &C, DeclContext *DC, SourceLocation KeyLoc,
676 SourceLocation NameLoc, int D, int P, IdentifierInfo *Id, bool Typename,
677 bool ParameterPack, bool HasTypeConstraint, UnsignedOrNone NumExpanded) {
678 auto *TTPDecl =
679 new (C, DC,
680 additionalSizeToAlloc<TypeConstraint>(Counts: HasTypeConstraint ? 1 : 0))
681 TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename,
682 HasTypeConstraint, NumExpanded);
683 QualType TTPType = C.getTemplateTypeParmType(Depth: D, Index: P, ParameterPack, ParmDecl: TTPDecl);
684 TTPDecl->setTypeForDecl(TTPType.getTypePtr());
685 return TTPDecl;
686}
687
688TemplateTypeParmDecl *
689TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, GlobalDeclID ID) {
690 return new (C, ID)
691 TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), nullptr,
692 false, false, std::nullopt);
693}
694
695TemplateTypeParmDecl *
696TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, GlobalDeclID ID,
697 bool HasTypeConstraint) {
698 return new (C, ID,
699 additionalSizeToAlloc<TypeConstraint>(Counts: HasTypeConstraint ? 1 : 0))
700 TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), nullptr,
701 false, HasTypeConstraint, std::nullopt);
702}
703
704SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
705 return hasDefaultArgument() ? getDefaultArgument().getLocation()
706 : SourceLocation();
707}
708
709SourceRange TemplateTypeParmDecl::getSourceRange() const {
710 if (hasDefaultArgument() && !defaultArgumentWasInherited())
711 return SourceRange(getBeginLoc(),
712 getDefaultArgument().getSourceRange().getEnd());
713 // TypeDecl::getSourceRange returns a range containing name location, which is
714 // wrong for unnamed template parameters. e.g:
715 // it will return <[[typename>]] instead of <[[typename]]>
716 if (getDeclName().isEmpty())
717 return SourceRange(getBeginLoc());
718 return TypeDecl::getSourceRange();
719}
720
721void TemplateTypeParmDecl::setDefaultArgument(
722 const ASTContext &C, const TemplateArgumentLoc &DefArg) {
723 if (DefArg.getArgument().isNull())
724 DefaultArgument.set(nullptr);
725 else
726 DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg));
727}
728
729unsigned TemplateTypeParmDecl::getDepth() const {
730 return dyn_cast<TemplateTypeParmType>(Val: getTypeForDecl())->getDepth();
731}
732
733unsigned TemplateTypeParmDecl::getIndex() const {
734 return dyn_cast<TemplateTypeParmType>(Val: getTypeForDecl())->getIndex();
735}
736
737bool TemplateTypeParmDecl::isParameterPack() const {
738 return dyn_cast<TemplateTypeParmType>(Val: getTypeForDecl())->isParameterPack();
739}
740
741void TemplateTypeParmDecl::setTypeConstraint(
742 ConceptReference *Loc, Expr *ImmediatelyDeclaredConstraint,
743 UnsignedOrNone ArgPackSubstIndex) {
744 assert(HasTypeConstraint &&
745 "HasTypeConstraint=true must be passed at construction in order to "
746 "call setTypeConstraint");
747 assert(!TypeConstraintInitialized &&
748 "TypeConstraint was already initialized!");
749 new (getTrailingObjects())
750 TypeConstraint(Loc, ImmediatelyDeclaredConstraint, ArgPackSubstIndex);
751 TypeConstraintInitialized = true;
752}
753
754//===----------------------------------------------------------------------===//
755// NonTypeTemplateParmDecl Method Implementations
756//===----------------------------------------------------------------------===//
757
758NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(
759 DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, int D,
760 int P, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
761 ArrayRef<QualType> ExpandedTypes, ArrayRef<TypeSourceInfo *> ExpandedTInfos)
762 : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
763 TemplateParmPosition(D, P), ParameterPack(true),
764 ExpandedParameterPack(true), NumExpandedTypes(ExpandedTypes.size()) {
765 if (!ExpandedTypes.empty() && !ExpandedTInfos.empty()) {
766 auto TypesAndInfos =
767 getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
768 for (unsigned I = 0; I != NumExpandedTypes; ++I) {
769 new (&TypesAndInfos[I].first) QualType(ExpandedTypes[I]);
770 TypesAndInfos[I].second = ExpandedTInfos[I];
771 }
772 }
773}
774
775NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create(
776 const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
777 SourceLocation IdLoc, int D, int P, const IdentifierInfo *Id, QualType T,
778 bool ParameterPack, TypeSourceInfo *TInfo) {
779 AutoType *AT =
780 C.getLangOpts().CPlusPlus20 ? T->getContainedAutoType() : nullptr;
781 const bool HasConstraint = AT && AT->isConstrained();
782 auto *NTTP =
783 new (C, DC,
784 additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, Expr *>(
785 Counts: 0, Counts: HasConstraint ? 1 : 0))
786 NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T,
787 ParameterPack, TInfo);
788 if (HasConstraint)
789 NTTP->setPlaceholderTypeConstraint(nullptr);
790 return NTTP;
791}
792
793NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create(
794 const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
795 SourceLocation IdLoc, int D, int P, const IdentifierInfo *Id, QualType T,
796 TypeSourceInfo *TInfo, ArrayRef<QualType> ExpandedTypes,
797 ArrayRef<TypeSourceInfo *> ExpandedTInfos) {
798 AutoType *AT = TInfo->getType()->getContainedAutoType();
799 const bool HasConstraint = AT && AT->isConstrained();
800 auto *NTTP =
801 new (C, DC,
802 additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, Expr *>(
803 Counts: ExpandedTypes.size(), Counts: HasConstraint ? 1 : 0))
804 NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T, TInfo,
805 ExpandedTypes, ExpandedTInfos);
806 if (HasConstraint)
807 NTTP->setPlaceholderTypeConstraint(nullptr);
808 return NTTP;
809}
810
811NonTypeTemplateParmDecl *
812NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
813 bool HasTypeConstraint) {
814 auto *NTTP =
815 new (C, ID,
816 additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, Expr *>(
817 Counts: 0, Counts: HasTypeConstraint ? 1 : 0))
818 NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(),
819 0, 0, nullptr, QualType(), false, nullptr);
820 if (HasTypeConstraint)
821 NTTP->setPlaceholderTypeConstraint(nullptr);
822 return NTTP;
823}
824
825NonTypeTemplateParmDecl *
826NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
827 unsigned NumExpandedTypes,
828 bool HasTypeConstraint) {
829 auto *NTTP =
830 new (C, ID,
831 additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, Expr *>(
832 Counts: NumExpandedTypes, Counts: HasTypeConstraint ? 1 : 0))
833 NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(),
834 0, 0, nullptr, QualType(), nullptr, {}, {});
835 NTTP->NumExpandedTypes = NumExpandedTypes;
836 if (HasTypeConstraint)
837 NTTP->setPlaceholderTypeConstraint(nullptr);
838 return NTTP;
839}
840
841SourceRange NonTypeTemplateParmDecl::getSourceRange() const {
842 if (hasDefaultArgument() && !defaultArgumentWasInherited())
843 return SourceRange(getOuterLocStart(),
844 getDefaultArgument().getSourceRange().getEnd());
845 return DeclaratorDecl::getSourceRange();
846}
847
848SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
849 return hasDefaultArgument() ? getDefaultArgument().getSourceRange().getBegin()
850 : SourceLocation();
851}
852
853void NonTypeTemplateParmDecl::setDefaultArgument(
854 const ASTContext &C, const TemplateArgumentLoc &DefArg) {
855 if (DefArg.getArgument().isNull())
856 DefaultArgument.set(nullptr);
857 else
858 DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg));
859}
860
861//===----------------------------------------------------------------------===//
862// TemplateTemplateParmDecl Method Implementations
863//===----------------------------------------------------------------------===//
864
865void TemplateTemplateParmDecl::anchor() {}
866
867TemplateTemplateParmDecl::TemplateTemplateParmDecl(
868 DeclContext *DC, SourceLocation L, int D, int P, IdentifierInfo *Id,
869 TemplateNameKind Kind, bool Typename, TemplateParameterList *Params,
870 ArrayRef<TemplateParameterList *> Expansions)
871 : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
872 TemplateParmPosition(D, P), ParameterKind(Kind), Typename(Typename),
873 ParameterPack(true), ExpandedParameterPack(true),
874 NumExpandedParams(Expansions.size()) {
875 llvm::uninitialized_copy(Src&: Expansions, Dst: getTrailingObjects());
876}
877
878TemplateTemplateParmDecl *TemplateTemplateParmDecl::Create(
879 const ASTContext &C, DeclContext *DC, SourceLocation L, int D, int P,
880 bool ParameterPack, IdentifierInfo *Id, TemplateNameKind Kind,
881 bool Typename, TemplateParameterList *Params) {
882 assert(!Params->empty() && "template with no template parameters");
883 return new (C, DC) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id,
884 Kind, Typename, Params);
885}
886
887TemplateTemplateParmDecl *
888TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
889 SourceLocation L, int D, int P,
890 IdentifierInfo *Id, TemplateNameKind Kind,
891 bool Typename, TemplateParameterList *Params,
892 ArrayRef<TemplateParameterList *> Expansions) {
893 assert(!Params->empty() && "template with no template parameters");
894 return new (C, DC,
895 additionalSizeToAlloc<TemplateParameterList *>(Counts: Expansions.size()))
896 TemplateTemplateParmDecl(DC, L, D, P, Id, Kind, Typename, Params,
897 Expansions);
898}
899
900TemplateTemplateParmDecl *
901TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
902 return new (C, ID) TemplateTemplateParmDecl(
903 nullptr, SourceLocation(), 0, 0, false, nullptr,
904 TemplateNameKind::TNK_Type_template, false, nullptr);
905}
906
907TemplateTemplateParmDecl *
908TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
909 unsigned NumExpansions) {
910 auto *TTP =
911 new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(Counts: NumExpansions))
912 TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr,
913 TemplateNameKind::TNK_Type_template, false,
914 nullptr, {});
915 TTP->NumExpandedParams = NumExpansions;
916 return TTP;
917}
918
919SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
920 return hasDefaultArgument() ? getDefaultArgument().getLocation()
921 : SourceLocation();
922}
923
924void TemplateTemplateParmDecl::setDefaultArgument(
925 const ASTContext &C, const TemplateArgumentLoc &DefArg) {
926 if (DefArg.getArgument().isNull())
927 DefaultArgument.set(nullptr);
928 else
929 DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg));
930}
931
932//===----------------------------------------------------------------------===//
933// TemplateArgumentList Implementation
934//===----------------------------------------------------------------------===//
935TemplateArgumentList::TemplateArgumentList(ArrayRef<TemplateArgument> Args)
936 : NumArguments(Args.size()) {
937 llvm::uninitialized_copy(Src&: Args, Dst: getTrailingObjects());
938}
939
940TemplateArgumentList *
941TemplateArgumentList::CreateCopy(ASTContext &Context,
942 ArrayRef<TemplateArgument> Args) {
943 void *Mem = Context.Allocate(Size: totalSizeToAlloc<TemplateArgument>(Counts: Args.size()));
944 return new (Mem) TemplateArgumentList(Args);
945}
946
947FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create(
948 ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
949 TemplateSpecializationKind TSK, TemplateArgumentList *TemplateArgs,
950 const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI,
951 MemberSpecializationInfo *MSInfo) {
952 const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
953 if (TemplateArgsAsWritten)
954 ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C,
955 List: *TemplateArgsAsWritten);
956
957 void *Mem =
958 C.Allocate(Size: totalSizeToAlloc<MemberSpecializationInfo *>(Counts: MSInfo ? 1 : 0));
959 return new (Mem) FunctionTemplateSpecializationInfo(
960 FD, Template, TSK, TemplateArgs, ArgsAsWritten, POI, MSInfo);
961}
962
963//===----------------------------------------------------------------------===//
964// ClassTemplateSpecializationDecl Implementation
965//===----------------------------------------------------------------------===//
966
967ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(
968 ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC,
969 SourceLocation StartLoc, SourceLocation IdLoc,
970 ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
971 bool StrictPackMatch, ClassTemplateSpecializationDecl *PrevDecl)
972 : CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc,
973 SpecializedTemplate->getIdentifier(), PrevDecl),
974 SpecializedTemplate(SpecializedTemplate),
975 TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
976 SpecializationKind(TSK_Undeclared), StrictPackMatch(StrictPackMatch) {
977 assert(DK == Kind::ClassTemplateSpecialization || StrictPackMatch == false);
978}
979
980ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
981 Kind DK)
982 : CXXRecordDecl(DK, TagTypeKind::Struct, C, nullptr, SourceLocation(),
983 SourceLocation(), nullptr, nullptr),
984 SpecializationKind(TSK_Undeclared) {}
985
986ClassTemplateSpecializationDecl *ClassTemplateSpecializationDecl::Create(
987 ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
988 SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate,
989 ArrayRef<TemplateArgument> Args, bool StrictPackMatch,
990 ClassTemplateSpecializationDecl *PrevDecl) {
991 auto *Result = new (Context, DC) ClassTemplateSpecializationDecl(
992 Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
993 SpecializedTemplate, Args, StrictPackMatch, PrevDecl);
994
995 return Result;
996}
997
998ClassTemplateSpecializationDecl *
999ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
1000 GlobalDeclID ID) {
1001 return new (C, ID)
1002 ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
1003}
1004
1005void ClassTemplateSpecializationDecl::getNameForDiagnostic(
1006 raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
1007 NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
1008
1009 const auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(Val: this);
1010 if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
1011 PS ? PS->getTemplateArgsAsWritten() : nullptr) {
1012 printTemplateArgumentList(
1013 OS, Args: ArgsAsWritten->arguments(), Policy,
1014 TPL: getSpecializedTemplate()->getTemplateParameters());
1015 } else {
1016 const TemplateArgumentList &TemplateArgs = getTemplateArgs();
1017 printTemplateArgumentList(
1018 OS, Args: TemplateArgs.asArray(), Policy,
1019 TPL: getSpecializedTemplate()->getTemplateParameters());
1020 }
1021}
1022
1023ClassTemplateDecl *
1024ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
1025 if (const auto *PartialSpec =
1026 SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
1027 return PartialSpec->PartialSpecialization->getSpecializedTemplate();
1028 return cast<ClassTemplateDecl *>(Val: SpecializedTemplate);
1029}
1030
1031SourceRange
1032ClassTemplateSpecializationDecl::getSourceRange() const {
1033 switch (getSpecializationKind()) {
1034 case TSK_Undeclared:
1035 case TSK_ImplicitInstantiation: {
1036 llvm::PointerUnion<ClassTemplateDecl *,
1037 ClassTemplatePartialSpecializationDecl *>
1038 Pattern = getSpecializedTemplateOrPartial();
1039 assert(!Pattern.isNull() &&
1040 "Class template specialization without pattern?");
1041 if (const auto *CTPSD =
1042 dyn_cast<ClassTemplatePartialSpecializationDecl *>(Val&: Pattern))
1043 return CTPSD->getSourceRange();
1044 return cast<ClassTemplateDecl *>(Val&: Pattern)->getSourceRange();
1045 }
1046 case TSK_ExplicitSpecialization: {
1047 SourceRange Range = CXXRecordDecl::getSourceRange();
1048 if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten();
1049 !isThisDeclarationADefinition() && Args)
1050 Range.setEnd(Args->getRAngleLoc());
1051 return Range;
1052 }
1053 case TSK_ExplicitInstantiationDeclaration:
1054 case TSK_ExplicitInstantiationDefinition: {
1055 SourceRange Range = CXXRecordDecl::getSourceRange();
1056 if (SourceLocation ExternKW = getExternKeywordLoc(); ExternKW.isValid())
1057 Range.setBegin(ExternKW);
1058 else if (SourceLocation TemplateKW = getTemplateKeywordLoc();
1059 TemplateKW.isValid())
1060 Range.setBegin(TemplateKW);
1061 if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten())
1062 Range.setEnd(Args->getRAngleLoc());
1063 return Range;
1064 }
1065 }
1066 llvm_unreachable("unhandled template specialization kind");
1067}
1068
1069void ClassTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) {
1070 auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(Val&: ExplicitInfo);
1071 if (!Info) {
1072 // Don't allocate if the location is invalid.
1073 if (Loc.isInvalid())
1074 return;
1075 Info = new (getASTContext()) ExplicitInstantiationInfo;
1076 Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
1077 ExplicitInfo = Info;
1078 }
1079 Info->ExternKeywordLoc = Loc;
1080}
1081
1082void ClassTemplateSpecializationDecl::setTemplateKeywordLoc(
1083 SourceLocation Loc) {
1084 auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(Val&: ExplicitInfo);
1085 if (!Info) {
1086 // Don't allocate if the location is invalid.
1087 if (Loc.isInvalid())
1088 return;
1089 Info = new (getASTContext()) ExplicitInstantiationInfo;
1090 Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
1091 ExplicitInfo = Info;
1092 }
1093 Info->TemplateKeywordLoc = Loc;
1094}
1095
1096//===----------------------------------------------------------------------===//
1097// ConceptDecl Implementation
1098//===----------------------------------------------------------------------===//
1099ConceptDecl *ConceptDecl::Create(ASTContext &C, DeclContext *DC,
1100 SourceLocation L, DeclarationName Name,
1101 TemplateParameterList *Params,
1102 Expr *ConstraintExpr) {
1103 assert(!Params->empty() && "template with no template parameters");
1104 bool Invalid = AdoptTemplateParameterList(Params, Owner: DC);
1105 auto *TD = new (C, DC) ConceptDecl(DC, L, Name, Params, ConstraintExpr);
1106 if (Invalid)
1107 TD->setInvalidDecl();
1108 return TD;
1109}
1110
1111ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
1112 ConceptDecl *Result = new (C, ID) ConceptDecl(nullptr, SourceLocation(),
1113 DeclarationName(),
1114 nullptr, nullptr);
1115
1116 return Result;
1117}
1118
1119//===----------------------------------------------------------------------===//
1120// ImplicitConceptSpecializationDecl Implementation
1121//===----------------------------------------------------------------------===//
1122ImplicitConceptSpecializationDecl::ImplicitConceptSpecializationDecl(
1123 DeclContext *DC, SourceLocation SL,
1124 ArrayRef<TemplateArgument> ConvertedArgs)
1125 : Decl(ImplicitConceptSpecialization, DC, SL),
1126 NumTemplateArgs(ConvertedArgs.size()) {
1127 setTemplateArguments(ConvertedArgs);
1128}
1129
1130ImplicitConceptSpecializationDecl::ImplicitConceptSpecializationDecl(
1131 EmptyShell Empty, unsigned NumTemplateArgs)
1132 : Decl(ImplicitConceptSpecialization, Empty),
1133 NumTemplateArgs(NumTemplateArgs) {}
1134
1135ImplicitConceptSpecializationDecl *ImplicitConceptSpecializationDecl::Create(
1136 const ASTContext &C, DeclContext *DC, SourceLocation SL,
1137 ArrayRef<TemplateArgument> ConvertedArgs) {
1138 return new (C, DC,
1139 additionalSizeToAlloc<TemplateArgument>(Counts: ConvertedArgs.size()))
1140 ImplicitConceptSpecializationDecl(DC, SL, ConvertedArgs);
1141}
1142
1143ImplicitConceptSpecializationDecl *
1144ImplicitConceptSpecializationDecl::CreateDeserialized(
1145 const ASTContext &C, GlobalDeclID ID, unsigned NumTemplateArgs) {
1146 return new (C, ID, additionalSizeToAlloc<TemplateArgument>(Counts: NumTemplateArgs))
1147 ImplicitConceptSpecializationDecl(EmptyShell{}, NumTemplateArgs);
1148}
1149
1150void ImplicitConceptSpecializationDecl::setTemplateArguments(
1151 ArrayRef<TemplateArgument> Converted) {
1152 assert(Converted.size() == NumTemplateArgs);
1153 llvm::uninitialized_copy(Src&: Converted, Dst: getTrailingObjects());
1154}
1155
1156//===----------------------------------------------------------------------===//
1157// ClassTemplatePartialSpecializationDecl Implementation
1158//===----------------------------------------------------------------------===//
1159void ClassTemplatePartialSpecializationDecl::anchor() {}
1160
1161ClassTemplatePartialSpecializationDecl::ClassTemplatePartialSpecializationDecl(
1162 ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
1163 SourceLocation IdLoc, TemplateParameterList *Params,
1164 ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
1165 CanQualType CanonInjectedTST,
1166 ClassTemplatePartialSpecializationDecl *PrevDecl)
1167 : ClassTemplateSpecializationDecl(
1168 Context, ClassTemplatePartialSpecialization, TK, DC, StartLoc, IdLoc,
1169 // Tracking StrictPackMatch for Partial
1170 // Specializations is not needed.
1171 SpecializedTemplate, Args, /*StrictPackMatch=*/false, PrevDecl),
1172 TemplateParams(Params), InstantiatedFromMember(nullptr, false),
1173 CanonInjectedTST(CanonInjectedTST) {
1174 if (AdoptTemplateParameterList(Params, Owner: this))
1175 setInvalidDecl();
1176}
1177
1178ClassTemplatePartialSpecializationDecl *
1179ClassTemplatePartialSpecializationDecl::Create(
1180 ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
1181 SourceLocation IdLoc, TemplateParameterList *Params,
1182 ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
1183 CanQualType CanonInjectedTST,
1184 ClassTemplatePartialSpecializationDecl *PrevDecl) {
1185 assert(!Params->empty() && "template with no template parameters");
1186 auto *Result = new (Context, DC) ClassTemplatePartialSpecializationDecl(
1187 Context, TK, DC, StartLoc, IdLoc, Params, SpecializedTemplate, Args,
1188 CanonInjectedTST, PrevDecl);
1189 Result->setSpecializationKind(TSK_ExplicitSpecialization);
1190 return Result;
1191}
1192
1193ClassTemplatePartialSpecializationDecl *
1194ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
1195 GlobalDeclID ID) {
1196 return new (C, ID) ClassTemplatePartialSpecializationDecl(C);
1197}
1198
1199CanQualType
1200ClassTemplatePartialSpecializationDecl::getCanonicalInjectedSpecializationType(
1201 const ASTContext &Ctx) const {
1202 if (CanonInjectedTST.isNull()) {
1203 CanonInjectedTST =
1204 CanQualType::CreateUnsafe(Other: Ctx.getCanonicalTemplateSpecializationType(
1205 Keyword: ElaboratedTypeKeyword::None,
1206 T: TemplateName(getSpecializedTemplate()->getCanonicalDecl()),
1207 CanonicalArgs: getTemplateArgs().asArray()));
1208 }
1209 return CanonInjectedTST;
1210}
1211
1212SourceRange ClassTemplatePartialSpecializationDecl::getSourceRange() const {
1213 if (const ClassTemplatePartialSpecializationDecl *MT =
1214 getInstantiatedFromMember();
1215 MT && !isMemberSpecialization())
1216 return MT->getSourceRange();
1217 SourceRange Range = ClassTemplateSpecializationDecl::getSourceRange();
1218 if (const TemplateParameterList *TPL = getTemplateParameters();
1219 TPL && getTemplateParameterLists().empty())
1220 Range.setBegin(TPL->getTemplateLoc());
1221 return Range;
1222}
1223
1224//===----------------------------------------------------------------------===//
1225// FriendTemplateDecl Implementation
1226//===----------------------------------------------------------------------===//
1227
1228void FriendTemplateDecl::anchor() {}
1229
1230FriendTemplateDecl *
1231FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC,
1232 SourceLocation Loc, FriendUnion Friend,
1233 SourceLocation FriendLoc,
1234 ArrayRef<TemplateParameterList *> FriendTPLists,
1235 SourceLocation EllipsisLoc, TemplateName Template) {
1236 std::size_t Extra =
1237 FriendTemplateDecl::additionalSizeToAlloc<TemplateParameterList *>(
1238 Counts: FriendTPLists.size());
1239 auto *FTD = new (Context, DC, Extra) FriendTemplateDecl(
1240 DC, Loc, Friend, FriendLoc, EllipsisLoc, FriendTPLists, Template);
1241 cast<CXXRecordDecl>(Val: DC)->pushFriendDecl(FD: FTD);
1242 return FTD;
1243}
1244
1245FriendTemplateDecl *
1246FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC,
1247 SourceLocation Loc, TemplateName Template,
1248 SourceLocation FriendLoc,
1249 ArrayRef<TemplateParameterList *> FriendTPLists,
1250 SourceLocation EllipsisLoc) {
1251 auto *Friend = Template.getAsTemplateDecl();
1252 assert(Friend && "friend template name must be resolved");
1253 std::size_t Extra =
1254 FriendTemplateDecl::additionalSizeToAlloc<TemplateParameterList *>(
1255 Counts: FriendTPLists.size());
1256 auto *FTD = new (Context, DC, Extra) FriendTemplateDecl(
1257 DC, Loc, Friend, FriendLoc, EllipsisLoc, FriendTPLists, Template);
1258 cast<CXXRecordDecl>(Val: DC)->pushFriendDecl(FD: FTD);
1259 return FTD;
1260}
1261
1262FriendTemplateDecl *
1263FriendTemplateDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
1264 unsigned NumFriendTPLists) {
1265 std::size_t Extra =
1266 FriendTemplateDecl::additionalSizeToAlloc<TemplateParameterList *>(
1267 Counts: NumFriendTPLists);
1268 return new (C, ID, Extra) FriendTemplateDecl(EmptyShell(), NumFriendTPLists);
1269}
1270
1271SourceRange FriendTemplateDecl::getSourceRange() const {
1272 SourceLocation Begin = getTemplateParameterLists().front()->getTemplateLoc();
1273 SourceLocation End =
1274 !Template.isNull() && !getFriendType()
1275 ? (isPackExpansion() ? getEllipsisLoc() : getLocation())
1276 : FriendDecl::getSourceRange().getEnd();
1277 return SourceRange(Begin, End);
1278}
1279
1280//===----------------------------------------------------------------------===//
1281// TypeAliasTemplateDecl Implementation
1282//===----------------------------------------------------------------------===//
1283
1284TypeAliasTemplateDecl *
1285TypeAliasTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
1286 DeclarationName Name,
1287 TemplateParameterList *Params, NamedDecl *Decl) {
1288 assert(!Params->empty() && "template with no template parameters");
1289 bool Invalid = AdoptTemplateParameterList(Params, Owner: DC);
1290 auto *TD = new (C, DC) TypeAliasTemplateDecl(C, DC, L, Name, Params, Decl);
1291 if (Invalid)
1292 TD->setInvalidDecl();
1293 return TD;
1294}
1295
1296TypeAliasTemplateDecl *
1297TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
1298 return new (C, ID) TypeAliasTemplateDecl(C, nullptr, SourceLocation(),
1299 DeclarationName(), nullptr, nullptr);
1300}
1301
1302RedeclarableTemplateDecl::CommonBase *
1303TypeAliasTemplateDecl::newCommon(ASTContext &C) const {
1304 auto *CommonPtr = new (C) Common;
1305 C.addDestruction(Ptr: CommonPtr);
1306 return CommonPtr;
1307}
1308
1309//===----------------------------------------------------------------------===//
1310// VarTemplateDecl Implementation
1311//===----------------------------------------------------------------------===//
1312
1313VarTemplateDecl *VarTemplateDecl::getDefinition() {
1314 VarTemplateDecl *CurD = this;
1315 while (CurD) {
1316 if (CurD->isThisDeclarationADefinition())
1317 return CurD;
1318 CurD = CurD->getPreviousDecl();
1319 }
1320 return nullptr;
1321}
1322
1323VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC,
1324 SourceLocation L, DeclarationName Name,
1325 TemplateParameterList *Params,
1326 VarDecl *Decl) {
1327 assert(!Params->empty() && "template with no template parameters");
1328 bool Invalid = AdoptTemplateParameterList(Params, Owner: DC);
1329 auto *TD = new (C, DC) VarTemplateDecl(C, DC, L, Name, Params, Decl);
1330 if (Invalid)
1331 TD->setInvalidDecl();
1332 return TD;
1333}
1334
1335VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
1336 GlobalDeclID ID) {
1337 return new (C, ID) VarTemplateDecl(C, nullptr, SourceLocation(),
1338 DeclarationName(), nullptr, nullptr);
1339}
1340
1341void VarTemplateDecl::LoadLazySpecializations(
1342 bool OnlyPartial /*=false*/) const {
1343 loadLazySpecializationsImpl(OnlyPartial);
1344}
1345
1346llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
1347VarTemplateDecl::getSpecializations() const {
1348 LoadLazySpecializations();
1349 return getCommonPtr()->Specializations;
1350}
1351
1352llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
1353VarTemplateDecl::getPartialSpecializations() const {
1354 LoadLazySpecializations(/*PartialOnly = */ OnlyPartial: true);
1355 return getCommonPtr()->PartialSpecializations;
1356}
1357
1358RedeclarableTemplateDecl::CommonBase *
1359VarTemplateDecl::newCommon(ASTContext &C) const {
1360 auto *CommonPtr = new (C) Common;
1361 C.addDestruction(Ptr: CommonPtr);
1362 return CommonPtr;
1363}
1364
1365VarTemplateSpecializationDecl *
1366VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
1367 llvm::FoldingSetInsertToken &InsertToken) {
1368 auto *Common = getCommonPtr();
1369 return findSpecializationImpl(Specs&: Common->Specializations, InsertToken, ProfileArgs: Args);
1370}
1371
1372void VarTemplateDecl::AddSpecialization(
1373 VarTemplateSpecializationDecl *D, llvm::FoldingSetInsertToken InsertToken) {
1374 auto *Common = getCommonPtr();
1375 addSpecializationImpl<VarTemplateDecl>(Specializations&: Common->Specializations, Entry: D,
1376 InsertToken);
1377}
1378
1379VarTemplatePartialSpecializationDecl *
1380VarTemplateDecl::findPartialSpecialization(
1381 ArrayRef<TemplateArgument> Args, TemplateParameterList *TPL,
1382 llvm::FoldingSetInsertToken &InsertToken) {
1383 return findSpecializationImpl(Specs&: getPartialSpecializations(), InsertToken, ProfileArgs: Args,
1384 ProfileArgs: TPL);
1385}
1386
1387void VarTemplatePartialSpecializationDecl::Profile(
1388 llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
1389 TemplateParameterList *TPL, const ASTContext &Context) {
1390 ID.AddInteger(I: TemplateArgs.size());
1391 for (const TemplateArgument &TemplateArg : TemplateArgs)
1392 TemplateArg.Profile(ID, Context);
1393 TPL->Profile(ID, C: Context);
1394}
1395
1396void VarTemplateDecl::AddPartialSpecialization(
1397 VarTemplatePartialSpecializationDecl *D,
1398 llvm::FoldingSetInsertToken InsertToken) {
1399 if (InsertToken)
1400 getPartialSpecializations().insert(N: D, Token: InsertToken);
1401 else {
1402 VarTemplatePartialSpecializationDecl *Existing =
1403 getPartialSpecializations().getOrInsert(N: D);
1404 (void)Existing;
1405 assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
1406 }
1407
1408 if (ASTMutationListener *L = getASTMutationListener())
1409 L->AddedCXXTemplateSpecialization(TD: this, D);
1410}
1411
1412void VarTemplateDecl::getPartialSpecializations(
1413 SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS) const {
1414 llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &PartialSpecs =
1415 getPartialSpecializations();
1416 PS.clear();
1417 PS.reserve(N: PartialSpecs.size());
1418 for (VarTemplatePartialSpecializationDecl &P : PartialSpecs)
1419 PS.push_back(Elt: P.getMostRecentDecl());
1420}
1421
1422VarTemplatePartialSpecializationDecl *
1423VarTemplateDecl::findPartialSpecInstantiatedFromMember(
1424 VarTemplatePartialSpecializationDecl *D) {
1425 Decl *DCanon = D->getCanonicalDecl();
1426 for (VarTemplatePartialSpecializationDecl &P : getPartialSpecializations()) {
1427 if (P.getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
1428 return P.getMostRecentDecl();
1429 }
1430
1431 return nullptr;
1432}
1433
1434//===----------------------------------------------------------------------===//
1435// VarTemplateSpecializationDecl Implementation
1436//===----------------------------------------------------------------------===//
1437
1438VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(
1439 Kind DK, ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1440 SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
1441 TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args)
1442 : VarDecl(DK, Context, DC, StartLoc, IdLoc,
1443 SpecializedTemplate->getIdentifier(), T, TInfo, S),
1444 SpecializedTemplate(SpecializedTemplate),
1445 TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
1446 SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {}
1447
1448VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK,
1449 ASTContext &C)
1450 : VarDecl(DK, C, nullptr, SourceLocation(), SourceLocation(), nullptr,
1451 QualType(), nullptr, SC_None),
1452 SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {}
1453
1454VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create(
1455 ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1456 SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
1457 TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args) {
1458 return new (Context, DC) VarTemplateSpecializationDecl(
1459 VarTemplateSpecialization, Context, DC, StartLoc, IdLoc,
1460 SpecializedTemplate, T, TInfo, S, Args);
1461}
1462
1463VarTemplateSpecializationDecl *
1464VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
1465 GlobalDeclID ID) {
1466 return new (C, ID)
1467 VarTemplateSpecializationDecl(VarTemplateSpecialization, C);
1468}
1469
1470void VarTemplateSpecializationDecl::getNameForDiagnostic(
1471 raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
1472 NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
1473
1474 const auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(Val: this);
1475 if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
1476 PS ? PS->getTemplateArgsAsWritten() : nullptr) {
1477 printTemplateArgumentList(
1478 OS, Args: ArgsAsWritten->arguments(), Policy,
1479 TPL: getSpecializedTemplate()->getTemplateParameters());
1480 } else {
1481 const TemplateArgumentList &TemplateArgs = getTemplateArgs();
1482 printTemplateArgumentList(
1483 OS, Args: TemplateArgs.asArray(), Policy,
1484 TPL: getSpecializedTemplate()->getTemplateParameters());
1485 }
1486}
1487
1488VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
1489 if (const auto *PartialSpec =
1490 SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
1491 return PartialSpec->PartialSpecialization->getSpecializedTemplate();
1492 return cast<VarTemplateDecl *>(Val: SpecializedTemplate);
1493}
1494
1495SourceRange VarTemplateSpecializationDecl::getSourceRange() const {
1496 switch (getSpecializationKind()) {
1497 case TSK_Undeclared:
1498 case TSK_ImplicitInstantiation: {
1499 llvm::PointerUnion<VarTemplateDecl *,
1500 VarTemplatePartialSpecializationDecl *>
1501 Pattern = getSpecializedTemplateOrPartial();
1502 assert(!Pattern.isNull() &&
1503 "Variable template specialization without pattern?");
1504 if (const auto *VTPSD =
1505 dyn_cast<VarTemplatePartialSpecializationDecl *>(Val&: Pattern))
1506 return VTPSD->getSourceRange();
1507 VarTemplateDecl *VTD = cast<VarTemplateDecl *>(Val&: Pattern);
1508 if (hasInit()) {
1509 if (VarTemplateDecl *Definition = VTD->getDefinition())
1510 return Definition->getSourceRange();
1511 }
1512 return VTD->getCanonicalDecl()->getSourceRange();
1513 }
1514 case TSK_ExplicitSpecialization: {
1515 SourceRange Range = VarDecl::getSourceRange();
1516 if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten();
1517 !hasInit() && Args)
1518 Range.setEnd(Args->getRAngleLoc());
1519 return Range;
1520 }
1521 case TSK_ExplicitInstantiationDeclaration:
1522 case TSK_ExplicitInstantiationDefinition: {
1523 SourceRange Range = VarDecl::getSourceRange();
1524 if (SourceLocation ExternKW = getExternKeywordLoc(); ExternKW.isValid())
1525 Range.setBegin(ExternKW);
1526 else if (SourceLocation TemplateKW = getTemplateKeywordLoc();
1527 TemplateKW.isValid())
1528 Range.setBegin(TemplateKW);
1529 if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten())
1530 Range.setEnd(Args->getRAngleLoc());
1531 return Range;
1532 }
1533 }
1534 llvm_unreachable("unhandled template specialization kind");
1535}
1536
1537void VarTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) {
1538 auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(Val&: ExplicitInfo);
1539 if (!Info) {
1540 // Don't allocate if the location is invalid.
1541 if (Loc.isInvalid())
1542 return;
1543 Info = new (getASTContext()) ExplicitInstantiationInfo;
1544 Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
1545 ExplicitInfo = Info;
1546 }
1547 Info->ExternKeywordLoc = Loc;
1548}
1549
1550void VarTemplateSpecializationDecl::setTemplateKeywordLoc(SourceLocation Loc) {
1551 auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(Val&: ExplicitInfo);
1552 if (!Info) {
1553 // Don't allocate if the location is invalid.
1554 if (Loc.isInvalid())
1555 return;
1556 Info = new (getASTContext()) ExplicitInstantiationInfo;
1557 Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
1558 ExplicitInfo = Info;
1559 }
1560 Info->TemplateKeywordLoc = Loc;
1561}
1562
1563//===----------------------------------------------------------------------===//
1564// VarTemplatePartialSpecializationDecl Implementation
1565//===----------------------------------------------------------------------===//
1566
1567void VarTemplatePartialSpecializationDecl::anchor() {}
1568
1569VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl(
1570 ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1571 SourceLocation IdLoc, TemplateParameterList *Params,
1572 VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
1573 StorageClass S, ArrayRef<TemplateArgument> Args)
1574 : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context,
1575 DC, StartLoc, IdLoc, SpecializedTemplate, T,
1576 TInfo, S, Args),
1577 TemplateParams(Params), InstantiatedFromMember(nullptr, false) {
1578 if (AdoptTemplateParameterList(Params, Owner: DC))
1579 setInvalidDecl();
1580}
1581
1582VarTemplatePartialSpecializationDecl *
1583VarTemplatePartialSpecializationDecl::Create(
1584 ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1585 SourceLocation IdLoc, TemplateParameterList *Params,
1586 VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
1587 StorageClass S, ArrayRef<TemplateArgument> Args) {
1588 assert(!Params->empty() && "template with no template parameters");
1589 auto *Result = new (Context, DC) VarTemplatePartialSpecializationDecl(
1590 Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo, S,
1591 Args);
1592 Result->setSpecializationKind(TSK_ExplicitSpecialization);
1593 return Result;
1594}
1595
1596VarTemplatePartialSpecializationDecl *
1597VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
1598 GlobalDeclID ID) {
1599 return new (C, ID) VarTemplatePartialSpecializationDecl(C);
1600}
1601
1602SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const {
1603 if (const VarTemplatePartialSpecializationDecl *MT =
1604 getInstantiatedFromMember();
1605 MT && !isMemberSpecialization())
1606 return MT->getSourceRange();
1607 SourceRange Range = VarTemplateSpecializationDecl::getSourceRange();
1608 if (const TemplateParameterList *TPL = getTemplateParameters();
1609 TPL && getTemplateParameterLists().empty())
1610 Range.setBegin(TPL->getTemplateLoc());
1611 return Range;
1612}
1613
1614static TemplateParameterList *createBuiltinTemplateParameterList(
1615 const ASTContext &C, DeclContext *DC, BuiltinTemplateKind BTK) {
1616 switch (BTK) {
1617#define CREATE_BUILTIN_TEMPLATE_PARAMETER_LIST
1618#include "clang/Basic/BuiltinTemplates.inc"
1619 }
1620
1621 llvm_unreachable("unhandled BuiltinTemplateKind!");
1622}
1623
1624void BuiltinTemplateDecl::anchor() {}
1625
1626BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
1627 DeclarationName Name,
1628 BuiltinTemplateKind BTK)
1629 : TemplateDecl(BuiltinTemplate, DC, SourceLocation(), Name,
1630 createBuiltinTemplateParameterList(C, DC, BTK)),
1631 BTK(BTK) {}
1632
1633bool BuiltinTemplateDecl::isPackProducingBuiltinTemplate() const {
1634 return getBuiltinTemplateKind() == clang::BTK__builtin_dedup_pack;
1635}
1636
1637bool clang::isPackProducingBuiltinTemplateName(TemplateName N) {
1638 auto *T = dyn_cast_or_null<BuiltinTemplateDecl>(
1639 Val: N.getAsTemplateDecl(/*IgnoreDeduced=*/true));
1640 return T && T->isPackProducingBuiltinTemplate();
1641}
1642
1643TemplateParamObjectDecl *TemplateParamObjectDecl::Create(const ASTContext &C,
1644 QualType T,
1645 const APValue &V) {
1646 DeclContext *DC = C.getTranslationUnitDecl();
1647 auto *TPOD = new (C, DC) TemplateParamObjectDecl(DC, T, V);
1648 C.addDestruction(Ptr: &TPOD->Value);
1649 return TPOD;
1650}
1651
1652TemplateParamObjectDecl *
1653TemplateParamObjectDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
1654 auto *TPOD = new (C, ID) TemplateParamObjectDecl(nullptr, QualType(), APValue());
1655 C.addDestruction(Ptr: &TPOD->Value);
1656 return TPOD;
1657}
1658
1659void TemplateParamObjectDecl::printName(llvm::raw_ostream &OS,
1660 const PrintingPolicy &Policy) const {
1661 OS << "<template param ";
1662 printAsExpr(OS, Policy);
1663 OS << ">";
1664}
1665
1666void TemplateParamObjectDecl::printAsExpr(llvm::raw_ostream &OS) const {
1667 printAsExpr(OS, Policy: getASTContext().getPrintingPolicy());
1668}
1669
1670void TemplateParamObjectDecl::printAsExpr(llvm::raw_ostream &OS,
1671 const PrintingPolicy &Policy) const {
1672 getType().getUnqualifiedType().print(OS, Policy);
1673 printAsInit(OS, Policy);
1674}
1675
1676void TemplateParamObjectDecl::printAsInit(llvm::raw_ostream &OS) const {
1677 printAsInit(OS, Policy: getASTContext().getPrintingPolicy());
1678}
1679
1680void TemplateParamObjectDecl::printAsInit(llvm::raw_ostream &OS,
1681 const PrintingPolicy &Policy) const {
1682 getValue().printPretty(OS, Policy, Ty: getType(), Ctx: &getASTContext());
1683}
1684
1685std::tuple<NamedDecl *, TemplateArgument>
1686clang::getReplacedTemplateParameter(Decl *D, unsigned Index) {
1687 switch (D->getKind()) {
1688 case Decl::Kind::BuiltinTemplate:
1689 case Decl::Kind::ClassTemplate:
1690 case Decl::Kind::Concept:
1691 case Decl::Kind::FunctionTemplate:
1692 case Decl::Kind::TemplateTemplateParm:
1693 case Decl::Kind::TypeAliasTemplate:
1694 case Decl::Kind::VarTemplate:
1695 return {cast<TemplateDecl>(Val: D)->getTemplateParameters()->getParam(Idx: Index),
1696 {}};
1697 case Decl::Kind::ClassTemplateSpecialization: {
1698 const auto *CTSD = cast<ClassTemplateSpecializationDecl>(Val: D);
1699 auto P = CTSD->getSpecializedTemplateOrPartial();
1700 if (const auto *CTPSD =
1701 dyn_cast<ClassTemplatePartialSpecializationDecl *>(Val&: P)) {
1702 TemplateParameterList *TPL = CTPSD->getTemplateParameters();
1703 return {TPL->getParam(Idx: Index),
1704 CTSD->getTemplateInstantiationArgs()[Index]};
1705 }
1706 TemplateParameterList *TPL =
1707 cast<ClassTemplateDecl *>(Val&: P)->getTemplateParameters();
1708 return {TPL->getParam(Idx: Index), CTSD->getTemplateArgs()[Index]};
1709 }
1710 case Decl::Kind::VarTemplateSpecialization: {
1711 const auto *VTSD = cast<VarTemplateSpecializationDecl>(Val: D);
1712 auto P = VTSD->getSpecializedTemplateOrPartial();
1713 if (const auto *VTPSD =
1714 dyn_cast<VarTemplatePartialSpecializationDecl *>(Val&: P)) {
1715 TemplateParameterList *TPL = VTPSD->getTemplateParameters();
1716 return {TPL->getParam(Idx: Index),
1717 VTSD->getTemplateInstantiationArgs()[Index]};
1718 }
1719 TemplateParameterList *TPL =
1720 cast<VarTemplateDecl *>(Val&: P)->getTemplateParameters();
1721 return {TPL->getParam(Idx: Index), VTSD->getTemplateArgs()[Index]};
1722 }
1723 case Decl::Kind::ClassTemplatePartialSpecialization:
1724 return {cast<ClassTemplatePartialSpecializationDecl>(Val: D)
1725 ->getTemplateParameters()
1726 ->getParam(Idx: Index),
1727 {}};
1728 case Decl::Kind::VarTemplatePartialSpecialization:
1729 return {cast<VarTemplatePartialSpecializationDecl>(Val: D)
1730 ->getTemplateParameters()
1731 ->getParam(Idx: Index),
1732 {}};
1733 // This is used as the AssociatedDecl for placeholder type deduction.
1734 case Decl::TemplateTypeParm:
1735 return {cast<NamedDecl>(Val: D), {}};
1736 // FIXME: Always use the template decl as the AssociatedDecl.
1737 case Decl::Kind::CXXRecord:
1738 return getReplacedTemplateParameter(
1739 D: cast<CXXRecordDecl>(Val: D)->getDescribedClassTemplate(), Index);
1740 case Decl::Kind::CXXDeductionGuide:
1741 case Decl::Kind::CXXConversion:
1742 case Decl::Kind::CXXConstructor:
1743 case Decl::Kind::CXXDestructor:
1744 case Decl::Kind::CXXMethod:
1745 case Decl::Kind::Function: {
1746 const FunctionTemplateSpecializationInfo *Info =
1747 cast<FunctionDecl>(Val: D)->getTemplateSpecializationInfo();
1748 return {Info->getTemplate()->getTemplateParameters()->getParam(Idx: Index),
1749 Info->TemplateArguments->asArray()[Index]};
1750 }
1751 case Decl::Kind::CXXExpansionStmt:
1752 assert(Index == 0 && "expansion stmts only have a single template param");
1753 return {cast<CXXExpansionStmtDecl>(Val: D)->getIndexTemplateParm(), {}};
1754 default:
1755 llvm_unreachable("Unhandled templated declaration kind");
1756 }
1757}
1758
1759const Decl &clang::adjustDeclToTemplate(const Decl &D) {
1760 if (const auto *FD = dyn_cast<FunctionDecl>(Val: &D)) {
1761 // Is this function declaration part of a function template?
1762 if (const FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate())
1763 return *FTD;
1764
1765 // Nothing to do if function is not an implicit instantiation.
1766 if (FD->getTemplateSpecializationKind() != TSK_ImplicitInstantiation)
1767 return D;
1768
1769 // Function is an implicit instantiation of a function template?
1770 if (const FunctionTemplateDecl *FTD = FD->getPrimaryTemplate())
1771 return *FTD;
1772
1773 // Function is instantiated from a member definition of a class template?
1774 if (const FunctionDecl *MemberDecl =
1775 FD->getInstantiatedFromMemberFunction())
1776 return *MemberDecl;
1777
1778 return D;
1779 }
1780 if (const auto *VD = dyn_cast<VarDecl>(Val: &D)) {
1781 // Static data member is instantiated from a member definition of a class
1782 // template?
1783 if (VD->isStaticDataMember())
1784 if (const VarDecl *MemberDecl = VD->getInstantiatedFromStaticDataMember())
1785 return *MemberDecl;
1786
1787 return D;
1788 }
1789 if (const auto *CRD = dyn_cast<CXXRecordDecl>(Val: &D)) {
1790 // Is this class declaration part of a class template?
1791 if (const ClassTemplateDecl *CTD = CRD->getDescribedClassTemplate())
1792 return *CTD;
1793
1794 // Class is an implicit instantiation of a class template or partial
1795 // specialization?
1796 if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Val: CRD)) {
1797 if (CTSD->getSpecializationKind() != TSK_ImplicitInstantiation)
1798 return D;
1799 llvm::PointerUnion<ClassTemplateDecl *,
1800 ClassTemplatePartialSpecializationDecl *>
1801 PU = CTSD->getSpecializedTemplateOrPartial();
1802 return isa<ClassTemplateDecl *>(Val: PU)
1803 ? *static_cast<const Decl *>(cast<ClassTemplateDecl *>(Val&: PU))
1804 : *static_cast<const Decl *>(
1805 cast<ClassTemplatePartialSpecializationDecl *>(Val&: PU));
1806 }
1807
1808 // Class is instantiated from a member definition of a class template?
1809 if (const MemberSpecializationInfo *Info =
1810 CRD->getMemberSpecializationInfo())
1811 return *Info->getInstantiatedFrom();
1812
1813 return D;
1814 }
1815 if (const auto *ED = dyn_cast<EnumDecl>(Val: &D)) {
1816 // Enum is instantiated from a member definition of a class template?
1817 if (const EnumDecl *MemberDecl = ED->getInstantiatedFromMemberEnum())
1818 return *MemberDecl;
1819
1820 return D;
1821 }
1822 // FIXME: Adjust alias templates?
1823 return D;
1824}
1825
1826ExplicitInstantiationDecl::ExplicitInstantiationDecl(
1827 DeclContext *DC, NamedDecl *Specialization, SourceLocation ExternLoc,
1828 SourceLocation TemplateLoc, NestedNameSpecifierLoc QualifierLoc,
1829 const ASTTemplateArgumentListInfo *ArgsAsWritten, SourceLocation NameLoc,
1830 TypeSourceInfo *TypeAsWritten, TemplateSpecializationKind TSK)
1831 : Decl(ExplicitInstantiation, DC, TemplateLoc),
1832 SpecAndTSK(Specialization, TSK), ExternLoc(ExternLoc), NameLoc(NameLoc) {
1833 unsigned Flags = 0;
1834 if (QualifierLoc)
1835 Flags |= HasQualifierFlag;
1836 if (ArgsAsWritten)
1837 Flags |= HasArgsAsWrittenFlag;
1838 // Set flags BEFORE writing trailing objects, because
1839 // numTrailingObjects reads TypeAndFlags.getInt() to compute offsets.
1840 TypeAndFlags.setPointerAndInt(PtrVal: TypeAsWritten, IntVal: Flags);
1841 if (QualifierLoc)
1842 *getTrailingObjects<NestedNameSpecifierLoc>() = QualifierLoc;
1843 if (ArgsAsWritten)
1844 *getTrailingObjects<const ASTTemplateArgumentListInfo *>() = ArgsAsWritten;
1845}
1846
1847ExplicitInstantiationDecl *ExplicitInstantiationDecl::Create(
1848 ASTContext &C, DeclContext *DC, NamedDecl *Specialization,
1849 SourceLocation ExternLoc, SourceLocation TemplateLoc,
1850 NestedNameSpecifierLoc QualifierLoc,
1851 const ASTTemplateArgumentListInfo *ArgsAsWritten, SourceLocation NameLoc,
1852 TypeSourceInfo *TypeAsWritten, TemplateSpecializationKind TSK) {
1853 unsigned Extra = additionalSizeToAlloc<NestedNameSpecifierLoc,
1854 const ASTTemplateArgumentListInfo *>(
1855 Counts: QualifierLoc ? 1 : 0, Counts: ArgsAsWritten ? 1 : 0);
1856 return new (C, DC, Extra) ExplicitInstantiationDecl(
1857 DC, Specialization, ExternLoc, TemplateLoc, QualifierLoc, ArgsAsWritten,
1858 NameLoc, TypeAsWritten, TSK);
1859}
1860
1861ExplicitInstantiationDecl *
1862ExplicitInstantiationDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
1863 unsigned TrailingFlags) {
1864 unsigned Extra = additionalSizeToAlloc<NestedNameSpecifierLoc,
1865 const ASTTemplateArgumentListInfo *>(
1866 Counts: (TrailingFlags & HasQualifierFlag) ? 1 : 0,
1867 Counts: (TrailingFlags & HasArgsAsWrittenFlag) ? 1 : 0);
1868 auto *D = new (C, ID, Extra) ExplicitInstantiationDecl(EmptyShell());
1869 // Set the flags so the reader knows which trailing objects are present.
1870 D->TypeAndFlags.setInt(TrailingFlags);
1871 return D;
1872}
1873
1874SourceLocation ExplicitInstantiationDecl::getTagKWLoc() const {
1875 if (auto TL = getClassTypeLoc()) {
1876 if (auto TST = TL->getAs<TemplateSpecializationTypeLoc>())
1877 return TST.getElaboratedKeywordLoc();
1878 if (auto Tag = TL->getAs<TagTypeLoc>())
1879 return Tag.getElaboratedKeywordLoc();
1880 }
1881 return SourceLocation();
1882}
1883
1884NestedNameSpecifierLoc ExplicitInstantiationDecl::getQualifierLoc() const {
1885 if (hasTrailingQualifier())
1886 return *getTrailingObjects<NestedNameSpecifierLoc>();
1887 if (auto TL = getClassTypeLoc())
1888 return TL->getPrefix();
1889 return NestedNameSpecifierLoc();
1890}
1891
1892TypeSourceInfo *ExplicitInstantiationDecl::getTypeAsWritten() const {
1893 // For class-like entities, TSI encodes the class itself, not a declared type.
1894 if (getClassTypeLoc())
1895 return nullptr;
1896 return getRawTypeSourceInfo();
1897}
1898
1899std::optional<unsigned> ExplicitInstantiationDecl::getNumTemplateArgs() const {
1900 if (const auto *Args = getTrailingArgsInfo())
1901 return Args->NumTemplateArgs;
1902 if (auto TL = getClassTypeLoc())
1903 if (auto TST = TL->getAs<TemplateSpecializationTypeLoc>())
1904 return TST.getNumArgs();
1905 return std::nullopt;
1906}
1907
1908TemplateArgumentLoc
1909ExplicitInstantiationDecl::getTemplateArg(unsigned I) const {
1910 if (const auto *Args = getTrailingArgsInfo())
1911 return (*Args)[I];
1912 if (auto TL = getClassTypeLoc())
1913 if (auto TST = TL->getAs<TemplateSpecializationTypeLoc>())
1914 return TST.getArgLoc(i: I);
1915 llvm_unreachable("template arguments not found in trailing args or TypeLoc");
1916}
1917
1918SourceLocation ExplicitInstantiationDecl::getTemplateArgsLAngleLoc() const {
1919 if (const auto *Args = getTrailingArgsInfo())
1920 return Args->getLAngleLoc();
1921 if (auto TL = getClassTypeLoc())
1922 if (auto TST = TL->getAs<TemplateSpecializationTypeLoc>())
1923 return TST.getLAngleLoc();
1924 llvm_unreachable("template arguments not found in trailing args or TypeLoc");
1925}
1926
1927SourceLocation ExplicitInstantiationDecl::getTemplateArgsRAngleLoc() const {
1928 if (const auto *Args = getTrailingArgsInfo())
1929 return Args->getRAngleLoc();
1930 if (auto TL = getClassTypeLoc())
1931 if (auto TST = TL->getAs<TemplateSpecializationTypeLoc>())
1932 return TST.getRAngleLoc();
1933 llvm_unreachable("template arguments not found in trailing args or TypeLoc");
1934}
1935
1936SourceLocation ExplicitInstantiationDecl::getEndLoc() const {
1937 // For func/var templates with postfix type syntax (arrays, functions),
1938 // the type extends past the name, so use the type's end location.
1939 if (auto *TSI = getTypeAsWritten())
1940 if (TSI->getType().hasPostfixDeclaratorSyntax())
1941 return TSI->getTypeLoc().getEndLoc();
1942 // Otherwise, template args RAngleLoc or NameLoc.
1943 if (getNumTemplateArgs()) {
1944 SourceLocation RAngle = getTemplateArgsRAngleLoc();
1945 if (RAngle.isValid())
1946 return RAngle;
1947 }
1948 return NameLoc;
1949}
1950
1951SourceRange ExplicitInstantiationDecl::getSourceRange() const {
1952 SourceLocation Begin = ExternLoc.isValid() ? ExternLoc : getLocation();
1953 return SourceRange(Begin, getEndLoc());
1954}
1955
1956CXXExpansionStmtDecl::CXXExpansionStmtDecl(DeclContext *DC, SourceLocation Loc,
1957 NonTypeTemplateParmDecl *NTTP)
1958 : Decl(CXXExpansionStmt, DC, Loc), DeclContext(CXXExpansionStmt),
1959 IndexNTTP(NTTP) {}
1960
1961CXXExpansionStmtDecl *
1962CXXExpansionStmtDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation Loc,
1963 NonTypeTemplateParmDecl *NTTP) {
1964 return new (C, DC) CXXExpansionStmtDecl(DC, Loc, NTTP);
1965}
1966CXXExpansionStmtDecl *
1967CXXExpansionStmtDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
1968 return new (C, ID)
1969 CXXExpansionStmtDecl(/*DC=*/nullptr, SourceLocation(), /*NTTP=*/nullptr);
1970}
1971
1972SourceRange CXXExpansionStmtDecl::getSourceRange() const {
1973 return Pattern ? Pattern->getSourceRange() : SourceRange();
1974}
1975