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, void *&InsertPos,
380 ProfileArguments... ProfileArgs) {
381 using SETraits = RedeclarableTemplateDecl::SpecEntryTraits<EntryType>;
382
383 llvm::FoldingSetNodeID ID;
384 EntryType::Profile(ID, ProfileArgs..., getASTContext());
385 EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
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, void *&InsertPos,
393 ProfileArguments... ProfileArgs) {
394
395 if (auto *Found = findSpecializationLocally(Specs, InsertPos, ProfileArgs...))
396 return Found;
397
398 if (!loadLazySpecializationsImpl(ProfileArgs...))
399 return nullptr;
400
401 return findSpecializationLocally(Specs, InsertPos, ProfileArgs...);
402}
403
404template<class Derived, class EntryType>
405void RedeclarableTemplateDecl::addSpecializationImpl(
406 llvm::FoldingSetVector<EntryType> &Specializations, EntryType *Entry,
407 void *InsertPos) {
408 using SETraits = SpecEntryTraits<EntryType>;
409
410 if (InsertPos) {
411#ifndef NDEBUG
412 auto Args = SETraits::getTemplateArgs(Entry);
413 // Due to hash collisions, it can happen that we load another template
414 // specialization with the same hash. This is fine, as long as the next
415 // call to findSpecializationImpl does not find a matching Decl for the
416 // template arguments.
417 loadLazySpecializationsImpl(Args);
418 void *CorrectInsertPos;
419 assert(!findSpecializationImpl(Specializations, CorrectInsertPos, Args) &&
420 InsertPos == CorrectInsertPos &&
421 "given incorrect InsertPos for specialization");
422#endif
423 Specializations.InsertNode(Entry, InsertPos);
424 } else {
425 EntryType *Existing = Specializations.GetOrInsertNode(Entry);
426 (void)Existing;
427 assert(SETraits::getDecl(Existing)->isCanonicalDecl() &&
428 "non-canonical specialization?");
429 }
430
431 if (ASTMutationListener *L = getASTMutationListener())
432 L->AddedCXXTemplateSpecialization(cast<Derived>(this),
433 SETraits::getDecl(Entry));
434}
435
436//===----------------------------------------------------------------------===//
437// FunctionTemplateDecl Implementation
438//===----------------------------------------------------------------------===//
439
440FunctionTemplateDecl *
441FunctionTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
442 DeclarationName Name,
443 TemplateParameterList *Params, NamedDecl *Decl) {
444 bool Invalid = AdoptTemplateParameterList(Params, Owner: cast<DeclContext>(Val: Decl));
445 auto *TD = new (C, DC) FunctionTemplateDecl(C, DC, L, Name, Params, Decl);
446 if (Invalid)
447 TD->setInvalidDecl();
448 return TD;
449}
450
451FunctionTemplateDecl *
452FunctionTemplateDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
453 return new (C, ID) FunctionTemplateDecl(C, nullptr, SourceLocation(),
454 DeclarationName(), nullptr, nullptr);
455}
456
457RedeclarableTemplateDecl::CommonBase *
458FunctionTemplateDecl::newCommon(ASTContext &C) const {
459 auto *CommonPtr = new (C) Common;
460 C.addDestruction(Ptr: CommonPtr);
461 return CommonPtr;
462}
463
464void FunctionTemplateDecl::LoadLazySpecializations() const {
465 loadLazySpecializationsImpl();
466}
467
468llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
469FunctionTemplateDecl::getSpecializations() const {
470 LoadLazySpecializations();
471 return getCommonPtr()->Specializations;
472}
473
474FunctionDecl *
475FunctionTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
476 void *&InsertPos) {
477 auto *Common = getCommonPtr();
478 return findSpecializationImpl(Specs&: Common->Specializations, InsertPos, ProfileArgs: Args);
479}
480
481void FunctionTemplateDecl::addSpecialization(
482 FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
483 auto *Common = getCommonPtr();
484 addSpecializationImpl<FunctionTemplateDecl>(Specializations&: Common->Specializations, Entry: Info,
485 InsertPos);
486}
487
488void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
489 using Base = RedeclarableTemplateDecl;
490
491 // If we haven't created a common pointer yet, then it can just be created
492 // with the usual method.
493 if (!Base::Common)
494 return;
495
496 Common *ThisCommon = static_cast<Common *>(Base::Common);
497 Common *PrevCommon = nullptr;
498 SmallVector<FunctionTemplateDecl *, 8> PreviousDecls;
499 for (; Prev; Prev = Prev->getPreviousDecl()) {
500 if (Prev->Base::Common) {
501 PrevCommon = static_cast<Common *>(Prev->Base::Common);
502 break;
503 }
504 PreviousDecls.push_back(Elt: Prev);
505 }
506
507 // If the previous redecl chain hasn't created a common pointer yet, then just
508 // use this common pointer.
509 if (!PrevCommon) {
510 for (auto *D : PreviousDecls)
511 D->Base::Common = ThisCommon;
512 return;
513 }
514
515 // Ensure we don't leak any important state.
516 assert(ThisCommon->Specializations.size() == 0 &&
517 "Can't merge incompatible declarations!");
518
519 Base::Common = PrevCommon;
520}
521
522//===----------------------------------------------------------------------===//
523// ClassTemplateDecl Implementation
524//===----------------------------------------------------------------------===//
525
526ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, DeclContext *DC,
527 SourceLocation L,
528 DeclarationName Name,
529 TemplateParameterList *Params,
530 NamedDecl *Decl) {
531 bool Invalid = AdoptTemplateParameterList(Params, Owner: cast<DeclContext>(Val: Decl));
532 auto *TD = new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
533 if (Invalid)
534 TD->setInvalidDecl();
535 return TD;
536}
537
538ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
539 GlobalDeclID ID) {
540 return new (C, ID) ClassTemplateDecl(C, nullptr, SourceLocation(),
541 DeclarationName(), nullptr, nullptr);
542}
543
544void ClassTemplateDecl::LoadLazySpecializations(
545 bool OnlyPartial /*=false*/) const {
546 loadLazySpecializationsImpl(OnlyPartial);
547}
548
549llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
550ClassTemplateDecl::getSpecializations() const {
551 LoadLazySpecializations();
552 return getCommonPtr()->Specializations;
553}
554
555llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
556ClassTemplateDecl::getPartialSpecializations() const {
557 LoadLazySpecializations(/*PartialOnly = */ OnlyPartial: true);
558 return getCommonPtr()->PartialSpecializations;
559}
560
561RedeclarableTemplateDecl::CommonBase *
562ClassTemplateDecl::newCommon(ASTContext &C) const {
563 auto *CommonPtr = new (C) Common;
564 C.addDestruction(Ptr: CommonPtr);
565 return CommonPtr;
566}
567
568ClassTemplateSpecializationDecl *
569ClassTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
570 void *&InsertPos) {
571 auto *Common = getCommonPtr();
572 return findSpecializationImpl(Specs&: Common->Specializations, InsertPos, ProfileArgs: Args);
573}
574
575void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D,
576 void *InsertPos) {
577 auto *Common = getCommonPtr();
578 addSpecializationImpl<ClassTemplateDecl>(Specializations&: Common->Specializations, Entry: D,
579 InsertPos);
580}
581
582ClassTemplatePartialSpecializationDecl *
583ClassTemplateDecl::findPartialSpecialization(
584 ArrayRef<TemplateArgument> Args,
585 TemplateParameterList *TPL, void *&InsertPos) {
586 return findSpecializationImpl(Specs&: getPartialSpecializations(), InsertPos, ProfileArgs: Args,
587 ProfileArgs: TPL);
588}
589
590void ClassTemplatePartialSpecializationDecl::Profile(
591 llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
592 TemplateParameterList *TPL, const ASTContext &Context) {
593 ID.AddInteger(I: TemplateArgs.size());
594 for (const TemplateArgument &TemplateArg : TemplateArgs)
595 TemplateArg.Profile(ID, Context);
596 TPL->Profile(ID, C: Context);
597}
598
599void ClassTemplateDecl::AddPartialSpecialization(
600 ClassTemplatePartialSpecializationDecl *D,
601 void *InsertPos) {
602 if (InsertPos)
603 getPartialSpecializations().InsertNode(N: D, InsertPos);
604 else {
605 ClassTemplatePartialSpecializationDecl *Existing
606 = getPartialSpecializations().GetOrInsertNode(N: D);
607 (void)Existing;
608 assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
609 }
610
611 if (ASTMutationListener *L = getASTMutationListener())
612 L->AddedCXXTemplateSpecialization(TD: this, D);
613}
614
615void ClassTemplateDecl::getPartialSpecializations(
616 SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) const {
617 llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &PartialSpecs
618 = getPartialSpecializations();
619 PS.clear();
620 PS.reserve(N: PartialSpecs.size());
621 for (ClassTemplatePartialSpecializationDecl &P : PartialSpecs)
622 PS.push_back(Elt: P.getMostRecentDecl());
623}
624
625ClassTemplatePartialSpecializationDecl *
626ClassTemplateDecl::findPartialSpecialization(QualType T) {
627 ASTContext &Context = getASTContext();
628 for (ClassTemplatePartialSpecializationDecl &P :
629 getPartialSpecializations()) {
630 if (Context.hasSameType(T1: P.getCanonicalInjectedSpecializationType(Ctx: Context),
631 T2: T))
632 return P.getMostRecentDecl();
633 }
634
635 return nullptr;
636}
637
638ClassTemplatePartialSpecializationDecl *
639ClassTemplateDecl::findPartialSpecInstantiatedFromMember(
640 ClassTemplatePartialSpecializationDecl *D) {
641 Decl *DCanon = D->getCanonicalDecl();
642 for (ClassTemplatePartialSpecializationDecl &P : getPartialSpecializations()) {
643 if (P.getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
644 return P.getMostRecentDecl();
645 }
646
647 return nullptr;
648}
649
650CanQualType ClassTemplateDecl::getCanonicalInjectedSpecializationType(
651 const ASTContext &Ctx) const {
652 Common *CommonPtr = getCommonPtr();
653
654 if (CommonPtr->CanonInjectedTST.isNull()) {
655 SmallVector<TemplateArgument> CanonicalArgs(
656 getTemplateParameters()->getInjectedTemplateArgs(Context: Ctx));
657 Ctx.canonicalizeTemplateArguments(Args: CanonicalArgs);
658 CommonPtr->CanonInjectedTST =
659 CanQualType::CreateUnsafe(Other: Ctx.getCanonicalTemplateSpecializationType(
660 Keyword: ElaboratedTypeKeyword::None,
661 T: TemplateName(const_cast<ClassTemplateDecl *>(getCanonicalDecl())),
662 CanonicalArgs));
663 }
664 return CommonPtr->CanonInjectedTST;
665}
666
667//===----------------------------------------------------------------------===//
668// TemplateTypeParm Allocation/Deallocation Method Implementations
669//===----------------------------------------------------------------------===//
670
671TemplateTypeParmDecl *TemplateTypeParmDecl::Create(
672 const ASTContext &C, DeclContext *DC, SourceLocation KeyLoc,
673 SourceLocation NameLoc, unsigned D, unsigned P, IdentifierInfo *Id,
674 bool Typename, bool ParameterPack, bool HasTypeConstraint,
675 UnsignedOrNone NumExpanded) {
676 auto *TTPDecl =
677 new (C, DC,
678 additionalSizeToAlloc<TypeConstraint>(Counts: HasTypeConstraint ? 1 : 0))
679 TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename,
680 HasTypeConstraint, NumExpanded);
681 QualType TTPType = C.getTemplateTypeParmType(Depth: D, Index: P, ParameterPack, ParmDecl: TTPDecl);
682 TTPDecl->setTypeForDecl(TTPType.getTypePtr());
683 return TTPDecl;
684}
685
686TemplateTypeParmDecl *
687TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, GlobalDeclID ID) {
688 return new (C, ID)
689 TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), nullptr,
690 false, false, std::nullopt);
691}
692
693TemplateTypeParmDecl *
694TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, GlobalDeclID ID,
695 bool HasTypeConstraint) {
696 return new (C, ID,
697 additionalSizeToAlloc<TypeConstraint>(Counts: HasTypeConstraint ? 1 : 0))
698 TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), nullptr,
699 false, HasTypeConstraint, std::nullopt);
700}
701
702SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
703 return hasDefaultArgument() ? getDefaultArgument().getLocation()
704 : SourceLocation();
705}
706
707SourceRange TemplateTypeParmDecl::getSourceRange() const {
708 if (hasDefaultArgument() && !defaultArgumentWasInherited())
709 return SourceRange(getBeginLoc(),
710 getDefaultArgument().getSourceRange().getEnd());
711 // TypeDecl::getSourceRange returns a range containing name location, which is
712 // wrong for unnamed template parameters. e.g:
713 // it will return <[[typename>]] instead of <[[typename]]>
714 if (getDeclName().isEmpty())
715 return SourceRange(getBeginLoc());
716 return TypeDecl::getSourceRange();
717}
718
719void TemplateTypeParmDecl::setDefaultArgument(
720 const ASTContext &C, const TemplateArgumentLoc &DefArg) {
721 if (DefArg.getArgument().isNull())
722 DefaultArgument.set(nullptr);
723 else
724 DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg));
725}
726
727unsigned TemplateTypeParmDecl::getDepth() const {
728 return dyn_cast<TemplateTypeParmType>(Val: getTypeForDecl())->getDepth();
729}
730
731unsigned TemplateTypeParmDecl::getIndex() const {
732 return dyn_cast<TemplateTypeParmType>(Val: getTypeForDecl())->getIndex();
733}
734
735bool TemplateTypeParmDecl::isParameterPack() const {
736 return dyn_cast<TemplateTypeParmType>(Val: getTypeForDecl())->isParameterPack();
737}
738
739void TemplateTypeParmDecl::setTypeConstraint(
740 ConceptReference *Loc, Expr *ImmediatelyDeclaredConstraint,
741 UnsignedOrNone ArgPackSubstIndex) {
742 assert(HasTypeConstraint &&
743 "HasTypeConstraint=true must be passed at construction in order to "
744 "call setTypeConstraint");
745 assert(!TypeConstraintInitialized &&
746 "TypeConstraint was already initialized!");
747 new (getTrailingObjects())
748 TypeConstraint(Loc, ImmediatelyDeclaredConstraint, ArgPackSubstIndex);
749 TypeConstraintInitialized = true;
750}
751
752//===----------------------------------------------------------------------===//
753// NonTypeTemplateParmDecl Method Implementations
754//===----------------------------------------------------------------------===//
755
756NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(
757 DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D,
758 unsigned P, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
759 ArrayRef<QualType> ExpandedTypes, ArrayRef<TypeSourceInfo *> ExpandedTInfos)
760 : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
761 TemplateParmPosition(D, P), ParameterPack(true),
762 ExpandedParameterPack(true), NumExpandedTypes(ExpandedTypes.size()) {
763 if (!ExpandedTypes.empty() && !ExpandedTInfos.empty()) {
764 auto TypesAndInfos =
765 getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
766 for (unsigned I = 0; I != NumExpandedTypes; ++I) {
767 new (&TypesAndInfos[I].first) QualType(ExpandedTypes[I]);
768 TypesAndInfos[I].second = ExpandedTInfos[I];
769 }
770 }
771}
772
773NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create(
774 const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
775 SourceLocation IdLoc, unsigned D, unsigned P, const IdentifierInfo *Id,
776 QualType T, bool ParameterPack, TypeSourceInfo *TInfo) {
777 AutoType *AT =
778 C.getLangOpts().CPlusPlus20 ? T->getContainedAutoType() : nullptr;
779 const bool HasConstraint = AT && AT->isConstrained();
780 auto *NTTP =
781 new (C, DC,
782 additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, Expr *>(
783 Counts: 0, Counts: HasConstraint ? 1 : 0))
784 NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T,
785 ParameterPack, TInfo);
786 if (HasConstraint)
787 NTTP->setPlaceholderTypeConstraint(nullptr);
788 return NTTP;
789}
790
791NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create(
792 const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
793 SourceLocation IdLoc, unsigned D, unsigned P, const IdentifierInfo *Id,
794 QualType T, TypeSourceInfo *TInfo, ArrayRef<QualType> ExpandedTypes,
795 ArrayRef<TypeSourceInfo *> ExpandedTInfos) {
796 AutoType *AT = TInfo->getType()->getContainedAutoType();
797 const bool HasConstraint = AT && AT->isConstrained();
798 auto *NTTP =
799 new (C, DC,
800 additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, Expr *>(
801 Counts: ExpandedTypes.size(), Counts: HasConstraint ? 1 : 0))
802 NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T, TInfo,
803 ExpandedTypes, ExpandedTInfos);
804 if (HasConstraint)
805 NTTP->setPlaceholderTypeConstraint(nullptr);
806 return NTTP;
807}
808
809NonTypeTemplateParmDecl *
810NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
811 bool HasTypeConstraint) {
812 auto *NTTP =
813 new (C, ID,
814 additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, Expr *>(
815 Counts: 0, Counts: HasTypeConstraint ? 1 : 0))
816 NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(),
817 0, 0, nullptr, QualType(), false, nullptr);
818 if (HasTypeConstraint)
819 NTTP->setPlaceholderTypeConstraint(nullptr);
820 return NTTP;
821}
822
823NonTypeTemplateParmDecl *
824NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
825 unsigned NumExpandedTypes,
826 bool HasTypeConstraint) {
827 auto *NTTP =
828 new (C, ID,
829 additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, Expr *>(
830 Counts: NumExpandedTypes, Counts: HasTypeConstraint ? 1 : 0))
831 NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(),
832 0, 0, nullptr, QualType(), nullptr, {}, {});
833 NTTP->NumExpandedTypes = NumExpandedTypes;
834 if (HasTypeConstraint)
835 NTTP->setPlaceholderTypeConstraint(nullptr);
836 return NTTP;
837}
838
839SourceRange NonTypeTemplateParmDecl::getSourceRange() const {
840 if (hasDefaultArgument() && !defaultArgumentWasInherited())
841 return SourceRange(getOuterLocStart(),
842 getDefaultArgument().getSourceRange().getEnd());
843 return DeclaratorDecl::getSourceRange();
844}
845
846SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
847 return hasDefaultArgument() ? getDefaultArgument().getSourceRange().getBegin()
848 : SourceLocation();
849}
850
851void NonTypeTemplateParmDecl::setDefaultArgument(
852 const ASTContext &C, const TemplateArgumentLoc &DefArg) {
853 if (DefArg.getArgument().isNull())
854 DefaultArgument.set(nullptr);
855 else
856 DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg));
857}
858
859//===----------------------------------------------------------------------===//
860// TemplateTemplateParmDecl Method Implementations
861//===----------------------------------------------------------------------===//
862
863void TemplateTemplateParmDecl::anchor() {}
864
865TemplateTemplateParmDecl::TemplateTemplateParmDecl(
866 DeclContext *DC, SourceLocation L, unsigned D, unsigned P,
867 IdentifierInfo *Id, TemplateNameKind Kind, bool Typename,
868 TemplateParameterList *Params, ArrayRef<TemplateParameterList *> Expansions)
869 : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
870 TemplateParmPosition(D, P), ParameterKind(Kind), Typename(Typename),
871 ParameterPack(true), ExpandedParameterPack(true),
872 NumExpandedParams(Expansions.size()) {
873 llvm::uninitialized_copy(Src&: Expansions, Dst: getTrailingObjects());
874}
875
876TemplateTemplateParmDecl *TemplateTemplateParmDecl::Create(
877 const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
878 unsigned P, bool ParameterPack, IdentifierInfo *Id, TemplateNameKind Kind,
879 bool Typename, TemplateParameterList *Params) {
880 return new (C, DC) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id,
881 Kind, Typename, Params);
882}
883
884TemplateTemplateParmDecl *
885TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
886 SourceLocation L, unsigned D, unsigned P,
887 IdentifierInfo *Id, TemplateNameKind Kind,
888 bool Typename, TemplateParameterList *Params,
889 ArrayRef<TemplateParameterList *> Expansions) {
890 return new (C, DC,
891 additionalSizeToAlloc<TemplateParameterList *>(Counts: Expansions.size()))
892 TemplateTemplateParmDecl(DC, L, D, P, Id, Kind, Typename, Params,
893 Expansions);
894}
895
896TemplateTemplateParmDecl *
897TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
898 return new (C, ID) TemplateTemplateParmDecl(
899 nullptr, SourceLocation(), 0, 0, false, nullptr,
900 TemplateNameKind::TNK_Type_template, false, nullptr);
901}
902
903TemplateTemplateParmDecl *
904TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
905 unsigned NumExpansions) {
906 auto *TTP =
907 new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(Counts: NumExpansions))
908 TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr,
909 TemplateNameKind::TNK_Type_template, false,
910 nullptr, {});
911 TTP->NumExpandedParams = NumExpansions;
912 return TTP;
913}
914
915SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
916 return hasDefaultArgument() ? getDefaultArgument().getLocation()
917 : SourceLocation();
918}
919
920void TemplateTemplateParmDecl::setDefaultArgument(
921 const ASTContext &C, const TemplateArgumentLoc &DefArg) {
922 if (DefArg.getArgument().isNull())
923 DefaultArgument.set(nullptr);
924 else
925 DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg));
926}
927
928//===----------------------------------------------------------------------===//
929// TemplateArgumentList Implementation
930//===----------------------------------------------------------------------===//
931TemplateArgumentList::TemplateArgumentList(ArrayRef<TemplateArgument> Args)
932 : NumArguments(Args.size()) {
933 llvm::uninitialized_copy(Src&: Args, Dst: getTrailingObjects());
934}
935
936TemplateArgumentList *
937TemplateArgumentList::CreateCopy(ASTContext &Context,
938 ArrayRef<TemplateArgument> Args) {
939 void *Mem = Context.Allocate(Size: totalSizeToAlloc<TemplateArgument>(Counts: Args.size()));
940 return new (Mem) TemplateArgumentList(Args);
941}
942
943FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create(
944 ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
945 TemplateSpecializationKind TSK, TemplateArgumentList *TemplateArgs,
946 const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI,
947 MemberSpecializationInfo *MSInfo) {
948 const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
949 if (TemplateArgsAsWritten)
950 ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C,
951 List: *TemplateArgsAsWritten);
952
953 void *Mem =
954 C.Allocate(Size: totalSizeToAlloc<MemberSpecializationInfo *>(Counts: MSInfo ? 1 : 0));
955 return new (Mem) FunctionTemplateSpecializationInfo(
956 FD, Template, TSK, TemplateArgs, ArgsAsWritten, POI, MSInfo);
957}
958
959//===----------------------------------------------------------------------===//
960// ClassTemplateSpecializationDecl Implementation
961//===----------------------------------------------------------------------===//
962
963ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(
964 ASTContext &Context, Kind DK, TagKind TK, DeclContext *DC,
965 SourceLocation StartLoc, SourceLocation IdLoc,
966 ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
967 bool StrictPackMatch, ClassTemplateSpecializationDecl *PrevDecl)
968 : CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc,
969 SpecializedTemplate->getIdentifier(), PrevDecl),
970 SpecializedTemplate(SpecializedTemplate),
971 TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
972 SpecializationKind(TSK_Undeclared), StrictPackMatch(StrictPackMatch) {
973 assert(DK == Kind::ClassTemplateSpecialization || StrictPackMatch == false);
974}
975
976ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
977 Kind DK)
978 : CXXRecordDecl(DK, TagTypeKind::Struct, C, nullptr, SourceLocation(),
979 SourceLocation(), nullptr, nullptr),
980 SpecializationKind(TSK_Undeclared) {}
981
982ClassTemplateSpecializationDecl *ClassTemplateSpecializationDecl::Create(
983 ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
984 SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate,
985 ArrayRef<TemplateArgument> Args, bool StrictPackMatch,
986 ClassTemplateSpecializationDecl *PrevDecl) {
987 auto *Result = new (Context, DC) ClassTemplateSpecializationDecl(
988 Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
989 SpecializedTemplate, Args, StrictPackMatch, PrevDecl);
990
991 // If the template decl is incomplete, copy the external lexical storage from
992 // the base template. This allows instantiations of incomplete types to
993 // complete using the external AST if the template's declaration came from an
994 // external AST.
995 if (!SpecializedTemplate->getTemplatedDecl()->isCompleteDefinition())
996 Result->setHasExternalLexicalStorage(
997 SpecializedTemplate->getTemplatedDecl()->hasExternalLexicalStorage());
998
999 return Result;
1000}
1001
1002ClassTemplateSpecializationDecl *
1003ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
1004 GlobalDeclID ID) {
1005 return new (C, ID)
1006 ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
1007}
1008
1009void ClassTemplateSpecializationDecl::getNameForDiagnostic(
1010 raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
1011 NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
1012
1013 const auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(Val: this);
1014 if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
1015 PS ? PS->getTemplateArgsAsWritten() : nullptr) {
1016 printTemplateArgumentList(
1017 OS, Args: ArgsAsWritten->arguments(), Policy,
1018 TPL: getSpecializedTemplate()->getTemplateParameters());
1019 } else {
1020 const TemplateArgumentList &TemplateArgs = getTemplateArgs();
1021 printTemplateArgumentList(
1022 OS, Args: TemplateArgs.asArray(), Policy,
1023 TPL: getSpecializedTemplate()->getTemplateParameters());
1024 }
1025}
1026
1027ClassTemplateDecl *
1028ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
1029 if (const auto *PartialSpec =
1030 SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
1031 return PartialSpec->PartialSpecialization->getSpecializedTemplate();
1032 return cast<ClassTemplateDecl *>(Val: SpecializedTemplate);
1033}
1034
1035SourceRange
1036ClassTemplateSpecializationDecl::getSourceRange() const {
1037 switch (getSpecializationKind()) {
1038 case TSK_Undeclared:
1039 case TSK_ImplicitInstantiation: {
1040 llvm::PointerUnion<ClassTemplateDecl *,
1041 ClassTemplatePartialSpecializationDecl *>
1042 Pattern = getSpecializedTemplateOrPartial();
1043 assert(!Pattern.isNull() &&
1044 "Class template specialization without pattern?");
1045 if (const auto *CTPSD =
1046 dyn_cast<ClassTemplatePartialSpecializationDecl *>(Val&: Pattern))
1047 return CTPSD->getSourceRange();
1048 return cast<ClassTemplateDecl *>(Val&: Pattern)->getSourceRange();
1049 }
1050 case TSK_ExplicitSpecialization: {
1051 SourceRange Range = CXXRecordDecl::getSourceRange();
1052 if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten();
1053 !isThisDeclarationADefinition() && Args)
1054 Range.setEnd(Args->getRAngleLoc());
1055 return Range;
1056 }
1057 case TSK_ExplicitInstantiationDeclaration:
1058 case TSK_ExplicitInstantiationDefinition: {
1059 SourceRange Range = CXXRecordDecl::getSourceRange();
1060 if (SourceLocation ExternKW = getExternKeywordLoc(); ExternKW.isValid())
1061 Range.setBegin(ExternKW);
1062 else if (SourceLocation TemplateKW = getTemplateKeywordLoc();
1063 TemplateKW.isValid())
1064 Range.setBegin(TemplateKW);
1065 if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten())
1066 Range.setEnd(Args->getRAngleLoc());
1067 return Range;
1068 }
1069 }
1070 llvm_unreachable("unhandled template specialization kind");
1071}
1072
1073void ClassTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) {
1074 auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(Val&: ExplicitInfo);
1075 if (!Info) {
1076 // Don't allocate if the location is invalid.
1077 if (Loc.isInvalid())
1078 return;
1079 Info = new (getASTContext()) ExplicitInstantiationInfo;
1080 Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
1081 ExplicitInfo = Info;
1082 }
1083 Info->ExternKeywordLoc = Loc;
1084}
1085
1086void ClassTemplateSpecializationDecl::setTemplateKeywordLoc(
1087 SourceLocation Loc) {
1088 auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(Val&: ExplicitInfo);
1089 if (!Info) {
1090 // Don't allocate if the location is invalid.
1091 if (Loc.isInvalid())
1092 return;
1093 Info = new (getASTContext()) ExplicitInstantiationInfo;
1094 Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
1095 ExplicitInfo = Info;
1096 }
1097 Info->TemplateKeywordLoc = Loc;
1098}
1099
1100//===----------------------------------------------------------------------===//
1101// ConceptDecl Implementation
1102//===----------------------------------------------------------------------===//
1103ConceptDecl *ConceptDecl::Create(ASTContext &C, DeclContext *DC,
1104 SourceLocation L, DeclarationName Name,
1105 TemplateParameterList *Params,
1106 Expr *ConstraintExpr) {
1107 bool Invalid = AdoptTemplateParameterList(Params, Owner: DC);
1108 auto *TD = new (C, DC) ConceptDecl(DC, L, Name, Params, ConstraintExpr);
1109 if (Invalid)
1110 TD->setInvalidDecl();
1111 return TD;
1112}
1113
1114ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
1115 ConceptDecl *Result = new (C, ID) ConceptDecl(nullptr, SourceLocation(),
1116 DeclarationName(),
1117 nullptr, nullptr);
1118
1119 return Result;
1120}
1121
1122//===----------------------------------------------------------------------===//
1123// ImplicitConceptSpecializationDecl Implementation
1124//===----------------------------------------------------------------------===//
1125ImplicitConceptSpecializationDecl::ImplicitConceptSpecializationDecl(
1126 DeclContext *DC, SourceLocation SL,
1127 ArrayRef<TemplateArgument> ConvertedArgs)
1128 : Decl(ImplicitConceptSpecialization, DC, SL),
1129 NumTemplateArgs(ConvertedArgs.size()) {
1130 setTemplateArguments(ConvertedArgs);
1131}
1132
1133ImplicitConceptSpecializationDecl::ImplicitConceptSpecializationDecl(
1134 EmptyShell Empty, unsigned NumTemplateArgs)
1135 : Decl(ImplicitConceptSpecialization, Empty),
1136 NumTemplateArgs(NumTemplateArgs) {}
1137
1138ImplicitConceptSpecializationDecl *ImplicitConceptSpecializationDecl::Create(
1139 const ASTContext &C, DeclContext *DC, SourceLocation SL,
1140 ArrayRef<TemplateArgument> ConvertedArgs) {
1141 return new (C, DC,
1142 additionalSizeToAlloc<TemplateArgument>(Counts: ConvertedArgs.size()))
1143 ImplicitConceptSpecializationDecl(DC, SL, ConvertedArgs);
1144}
1145
1146ImplicitConceptSpecializationDecl *
1147ImplicitConceptSpecializationDecl::CreateDeserialized(
1148 const ASTContext &C, GlobalDeclID ID, unsigned NumTemplateArgs) {
1149 return new (C, ID, additionalSizeToAlloc<TemplateArgument>(Counts: NumTemplateArgs))
1150 ImplicitConceptSpecializationDecl(EmptyShell{}, NumTemplateArgs);
1151}
1152
1153void ImplicitConceptSpecializationDecl::setTemplateArguments(
1154 ArrayRef<TemplateArgument> Converted) {
1155 assert(Converted.size() == NumTemplateArgs);
1156 llvm::uninitialized_copy(Src&: Converted, Dst: getTrailingObjects());
1157}
1158
1159//===----------------------------------------------------------------------===//
1160// ClassTemplatePartialSpecializationDecl Implementation
1161//===----------------------------------------------------------------------===//
1162void ClassTemplatePartialSpecializationDecl::anchor() {}
1163
1164ClassTemplatePartialSpecializationDecl::ClassTemplatePartialSpecializationDecl(
1165 ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
1166 SourceLocation IdLoc, TemplateParameterList *Params,
1167 ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
1168 CanQualType CanonInjectedTST,
1169 ClassTemplatePartialSpecializationDecl *PrevDecl)
1170 : ClassTemplateSpecializationDecl(
1171 Context, ClassTemplatePartialSpecialization, TK, DC, StartLoc, IdLoc,
1172 // Tracking StrictPackMatch for Partial
1173 // Specializations is not needed.
1174 SpecializedTemplate, Args, /*StrictPackMatch=*/false, PrevDecl),
1175 TemplateParams(Params), InstantiatedFromMember(nullptr, false),
1176 CanonInjectedTST(CanonInjectedTST) {
1177 if (AdoptTemplateParameterList(Params, Owner: this))
1178 setInvalidDecl();
1179}
1180
1181ClassTemplatePartialSpecializationDecl *
1182ClassTemplatePartialSpecializationDecl::Create(
1183 ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
1184 SourceLocation IdLoc, TemplateParameterList *Params,
1185 ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
1186 CanQualType CanonInjectedTST,
1187 ClassTemplatePartialSpecializationDecl *PrevDecl) {
1188 auto *Result = new (Context, DC) ClassTemplatePartialSpecializationDecl(
1189 Context, TK, DC, StartLoc, IdLoc, Params, SpecializedTemplate, Args,
1190 CanonInjectedTST, PrevDecl);
1191 Result->setSpecializationKind(TSK_ExplicitSpecialization);
1192 return Result;
1193}
1194
1195ClassTemplatePartialSpecializationDecl *
1196ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
1197 GlobalDeclID ID) {
1198 return new (C, ID) ClassTemplatePartialSpecializationDecl(C);
1199}
1200
1201CanQualType
1202ClassTemplatePartialSpecializationDecl::getCanonicalInjectedSpecializationType(
1203 const ASTContext &Ctx) const {
1204 if (CanonInjectedTST.isNull()) {
1205 CanonInjectedTST =
1206 CanQualType::CreateUnsafe(Other: Ctx.getCanonicalTemplateSpecializationType(
1207 Keyword: ElaboratedTypeKeyword::None,
1208 T: TemplateName(getSpecializedTemplate()->getCanonicalDecl()),
1209 CanonicalArgs: getTemplateArgs().asArray()));
1210 }
1211 return CanonInjectedTST;
1212}
1213
1214SourceRange ClassTemplatePartialSpecializationDecl::getSourceRange() const {
1215 if (const ClassTemplatePartialSpecializationDecl *MT =
1216 getInstantiatedFromMember();
1217 MT && !isMemberSpecialization())
1218 return MT->getSourceRange();
1219 SourceRange Range = ClassTemplateSpecializationDecl::getSourceRange();
1220 if (const TemplateParameterList *TPL = getTemplateParameters();
1221 TPL && !getNumTemplateParameterLists())
1222 Range.setBegin(TPL->getTemplateLoc());
1223 return Range;
1224}
1225
1226//===----------------------------------------------------------------------===//
1227// FriendTemplateDecl Implementation
1228//===----------------------------------------------------------------------===//
1229
1230void FriendTemplateDecl::anchor() {}
1231
1232FriendTemplateDecl *
1233FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC,
1234 SourceLocation L,
1235 MutableArrayRef<TemplateParameterList *> Params,
1236 FriendUnion Friend, SourceLocation FLoc) {
1237 TemplateParameterList **TPL = nullptr;
1238 if (!Params.empty()) {
1239 TPL = new (Context) TemplateParameterList *[Params.size()];
1240 llvm::copy(Range&: Params, Out: TPL);
1241 }
1242 return new (Context, DC)
1243 FriendTemplateDecl(DC, L, TPL, Params.size(), Friend, FLoc);
1244}
1245
1246FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C,
1247 GlobalDeclID ID) {
1248 return new (C, ID) FriendTemplateDecl(EmptyShell());
1249}
1250
1251//===----------------------------------------------------------------------===//
1252// TypeAliasTemplateDecl Implementation
1253//===----------------------------------------------------------------------===//
1254
1255TypeAliasTemplateDecl *
1256TypeAliasTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
1257 DeclarationName Name,
1258 TemplateParameterList *Params, NamedDecl *Decl) {
1259 bool Invalid = AdoptTemplateParameterList(Params, Owner: DC);
1260 auto *TD = new (C, DC) TypeAliasTemplateDecl(C, DC, L, Name, Params, Decl);
1261 if (Invalid)
1262 TD->setInvalidDecl();
1263 return TD;
1264}
1265
1266TypeAliasTemplateDecl *
1267TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
1268 return new (C, ID) TypeAliasTemplateDecl(C, nullptr, SourceLocation(),
1269 DeclarationName(), nullptr, nullptr);
1270}
1271
1272RedeclarableTemplateDecl::CommonBase *
1273TypeAliasTemplateDecl::newCommon(ASTContext &C) const {
1274 auto *CommonPtr = new (C) Common;
1275 C.addDestruction(Ptr: CommonPtr);
1276 return CommonPtr;
1277}
1278
1279//===----------------------------------------------------------------------===//
1280// VarTemplateDecl Implementation
1281//===----------------------------------------------------------------------===//
1282
1283VarTemplateDecl *VarTemplateDecl::getDefinition() {
1284 VarTemplateDecl *CurD = this;
1285 while (CurD) {
1286 if (CurD->isThisDeclarationADefinition())
1287 return CurD;
1288 CurD = CurD->getPreviousDecl();
1289 }
1290 return nullptr;
1291}
1292
1293VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC,
1294 SourceLocation L, DeclarationName Name,
1295 TemplateParameterList *Params,
1296 VarDecl *Decl) {
1297 bool Invalid = AdoptTemplateParameterList(Params, Owner: DC);
1298 auto *TD = new (C, DC) VarTemplateDecl(C, DC, L, Name, Params, Decl);
1299 if (Invalid)
1300 TD->setInvalidDecl();
1301 return TD;
1302}
1303
1304VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
1305 GlobalDeclID ID) {
1306 return new (C, ID) VarTemplateDecl(C, nullptr, SourceLocation(),
1307 DeclarationName(), nullptr, nullptr);
1308}
1309
1310void VarTemplateDecl::LoadLazySpecializations(
1311 bool OnlyPartial /*=false*/) const {
1312 loadLazySpecializationsImpl(OnlyPartial);
1313}
1314
1315llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
1316VarTemplateDecl::getSpecializations() const {
1317 LoadLazySpecializations();
1318 return getCommonPtr()->Specializations;
1319}
1320
1321llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
1322VarTemplateDecl::getPartialSpecializations() const {
1323 LoadLazySpecializations(/*PartialOnly = */ OnlyPartial: true);
1324 return getCommonPtr()->PartialSpecializations;
1325}
1326
1327RedeclarableTemplateDecl::CommonBase *
1328VarTemplateDecl::newCommon(ASTContext &C) const {
1329 auto *CommonPtr = new (C) Common;
1330 C.addDestruction(Ptr: CommonPtr);
1331 return CommonPtr;
1332}
1333
1334VarTemplateSpecializationDecl *
1335VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
1336 void *&InsertPos) {
1337 auto *Common = getCommonPtr();
1338 return findSpecializationImpl(Specs&: Common->Specializations, InsertPos, ProfileArgs: Args);
1339}
1340
1341void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D,
1342 void *InsertPos) {
1343 auto *Common = getCommonPtr();
1344 addSpecializationImpl<VarTemplateDecl>(Specializations&: Common->Specializations, Entry: D, InsertPos);
1345}
1346
1347VarTemplatePartialSpecializationDecl *
1348VarTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args,
1349 TemplateParameterList *TPL, void *&InsertPos) {
1350 return findSpecializationImpl(Specs&: getPartialSpecializations(), InsertPos, ProfileArgs: Args,
1351 ProfileArgs: TPL);
1352}
1353
1354void VarTemplatePartialSpecializationDecl::Profile(
1355 llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
1356 TemplateParameterList *TPL, const ASTContext &Context) {
1357 ID.AddInteger(I: TemplateArgs.size());
1358 for (const TemplateArgument &TemplateArg : TemplateArgs)
1359 TemplateArg.Profile(ID, Context);
1360 TPL->Profile(ID, C: Context);
1361}
1362
1363void VarTemplateDecl::AddPartialSpecialization(
1364 VarTemplatePartialSpecializationDecl *D, void *InsertPos) {
1365 if (InsertPos)
1366 getPartialSpecializations().InsertNode(N: D, InsertPos);
1367 else {
1368 VarTemplatePartialSpecializationDecl *Existing =
1369 getPartialSpecializations().GetOrInsertNode(N: D);
1370 (void)Existing;
1371 assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
1372 }
1373
1374 if (ASTMutationListener *L = getASTMutationListener())
1375 L->AddedCXXTemplateSpecialization(TD: this, D);
1376}
1377
1378void VarTemplateDecl::getPartialSpecializations(
1379 SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS) const {
1380 llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &PartialSpecs =
1381 getPartialSpecializations();
1382 PS.clear();
1383 PS.reserve(N: PartialSpecs.size());
1384 for (VarTemplatePartialSpecializationDecl &P : PartialSpecs)
1385 PS.push_back(Elt: P.getMostRecentDecl());
1386}
1387
1388VarTemplatePartialSpecializationDecl *
1389VarTemplateDecl::findPartialSpecInstantiatedFromMember(
1390 VarTemplatePartialSpecializationDecl *D) {
1391 Decl *DCanon = D->getCanonicalDecl();
1392 for (VarTemplatePartialSpecializationDecl &P : getPartialSpecializations()) {
1393 if (P.getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
1394 return P.getMostRecentDecl();
1395 }
1396
1397 return nullptr;
1398}
1399
1400//===----------------------------------------------------------------------===//
1401// VarTemplateSpecializationDecl Implementation
1402//===----------------------------------------------------------------------===//
1403
1404VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(
1405 Kind DK, ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1406 SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
1407 TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args)
1408 : VarDecl(DK, Context, DC, StartLoc, IdLoc,
1409 SpecializedTemplate->getIdentifier(), T, TInfo, S),
1410 SpecializedTemplate(SpecializedTemplate),
1411 TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
1412 SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {}
1413
1414VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK,
1415 ASTContext &C)
1416 : VarDecl(DK, C, nullptr, SourceLocation(), SourceLocation(), nullptr,
1417 QualType(), nullptr, SC_None),
1418 SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {}
1419
1420VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create(
1421 ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1422 SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
1423 TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args) {
1424 return new (Context, DC) VarTemplateSpecializationDecl(
1425 VarTemplateSpecialization, Context, DC, StartLoc, IdLoc,
1426 SpecializedTemplate, T, TInfo, S, Args);
1427}
1428
1429VarTemplateSpecializationDecl *
1430VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
1431 GlobalDeclID ID) {
1432 return new (C, ID)
1433 VarTemplateSpecializationDecl(VarTemplateSpecialization, C);
1434}
1435
1436void VarTemplateSpecializationDecl::getNameForDiagnostic(
1437 raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
1438 NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
1439
1440 const auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(Val: this);
1441 if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
1442 PS ? PS->getTemplateArgsAsWritten() : nullptr) {
1443 printTemplateArgumentList(
1444 OS, Args: ArgsAsWritten->arguments(), Policy,
1445 TPL: getSpecializedTemplate()->getTemplateParameters());
1446 } else {
1447 const TemplateArgumentList &TemplateArgs = getTemplateArgs();
1448 printTemplateArgumentList(
1449 OS, Args: TemplateArgs.asArray(), Policy,
1450 TPL: getSpecializedTemplate()->getTemplateParameters());
1451 }
1452}
1453
1454VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
1455 if (const auto *PartialSpec =
1456 SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
1457 return PartialSpec->PartialSpecialization->getSpecializedTemplate();
1458 return cast<VarTemplateDecl *>(Val: SpecializedTemplate);
1459}
1460
1461SourceRange VarTemplateSpecializationDecl::getSourceRange() const {
1462 switch (getSpecializationKind()) {
1463 case TSK_Undeclared:
1464 case TSK_ImplicitInstantiation: {
1465 llvm::PointerUnion<VarTemplateDecl *,
1466 VarTemplatePartialSpecializationDecl *>
1467 Pattern = getSpecializedTemplateOrPartial();
1468 assert(!Pattern.isNull() &&
1469 "Variable template specialization without pattern?");
1470 if (const auto *VTPSD =
1471 dyn_cast<VarTemplatePartialSpecializationDecl *>(Val&: Pattern))
1472 return VTPSD->getSourceRange();
1473 VarTemplateDecl *VTD = cast<VarTemplateDecl *>(Val&: Pattern);
1474 if (hasInit()) {
1475 if (VarTemplateDecl *Definition = VTD->getDefinition())
1476 return Definition->getSourceRange();
1477 }
1478 return VTD->getCanonicalDecl()->getSourceRange();
1479 }
1480 case TSK_ExplicitSpecialization: {
1481 SourceRange Range = VarDecl::getSourceRange();
1482 if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten();
1483 !hasInit() && Args)
1484 Range.setEnd(Args->getRAngleLoc());
1485 return Range;
1486 }
1487 case TSK_ExplicitInstantiationDeclaration:
1488 case TSK_ExplicitInstantiationDefinition: {
1489 SourceRange Range = VarDecl::getSourceRange();
1490 if (SourceLocation ExternKW = getExternKeywordLoc(); ExternKW.isValid())
1491 Range.setBegin(ExternKW);
1492 else if (SourceLocation TemplateKW = getTemplateKeywordLoc();
1493 TemplateKW.isValid())
1494 Range.setBegin(TemplateKW);
1495 if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten())
1496 Range.setEnd(Args->getRAngleLoc());
1497 return Range;
1498 }
1499 }
1500 llvm_unreachable("unhandled template specialization kind");
1501}
1502
1503void VarTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) {
1504 auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(Val&: ExplicitInfo);
1505 if (!Info) {
1506 // Don't allocate if the location is invalid.
1507 if (Loc.isInvalid())
1508 return;
1509 Info = new (getASTContext()) ExplicitInstantiationInfo;
1510 Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
1511 ExplicitInfo = Info;
1512 }
1513 Info->ExternKeywordLoc = Loc;
1514}
1515
1516void VarTemplateSpecializationDecl::setTemplateKeywordLoc(SourceLocation Loc) {
1517 auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(Val&: ExplicitInfo);
1518 if (!Info) {
1519 // Don't allocate if the location is invalid.
1520 if (Loc.isInvalid())
1521 return;
1522 Info = new (getASTContext()) ExplicitInstantiationInfo;
1523 Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
1524 ExplicitInfo = Info;
1525 }
1526 Info->TemplateKeywordLoc = Loc;
1527}
1528
1529//===----------------------------------------------------------------------===//
1530// VarTemplatePartialSpecializationDecl Implementation
1531//===----------------------------------------------------------------------===//
1532
1533void VarTemplatePartialSpecializationDecl::anchor() {}
1534
1535VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl(
1536 ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1537 SourceLocation IdLoc, TemplateParameterList *Params,
1538 VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
1539 StorageClass S, ArrayRef<TemplateArgument> Args)
1540 : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context,
1541 DC, StartLoc, IdLoc, SpecializedTemplate, T,
1542 TInfo, S, Args),
1543 TemplateParams(Params), InstantiatedFromMember(nullptr, false) {
1544 if (AdoptTemplateParameterList(Params, Owner: DC))
1545 setInvalidDecl();
1546}
1547
1548VarTemplatePartialSpecializationDecl *
1549VarTemplatePartialSpecializationDecl::Create(
1550 ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1551 SourceLocation IdLoc, TemplateParameterList *Params,
1552 VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
1553 StorageClass S, ArrayRef<TemplateArgument> Args) {
1554 auto *Result = new (Context, DC) VarTemplatePartialSpecializationDecl(
1555 Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo, S,
1556 Args);
1557 Result->setSpecializationKind(TSK_ExplicitSpecialization);
1558 return Result;
1559}
1560
1561VarTemplatePartialSpecializationDecl *
1562VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
1563 GlobalDeclID ID) {
1564 return new (C, ID) VarTemplatePartialSpecializationDecl(C);
1565}
1566
1567SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const {
1568 if (const VarTemplatePartialSpecializationDecl *MT =
1569 getInstantiatedFromMember();
1570 MT && !isMemberSpecialization())
1571 return MT->getSourceRange();
1572 SourceRange Range = VarTemplateSpecializationDecl::getSourceRange();
1573 if (const TemplateParameterList *TPL = getTemplateParameters();
1574 TPL && !getNumTemplateParameterLists())
1575 Range.setBegin(TPL->getTemplateLoc());
1576 return Range;
1577}
1578
1579static TemplateParameterList *createBuiltinTemplateParameterList(
1580 const ASTContext &C, DeclContext *DC, BuiltinTemplateKind BTK) {
1581 switch (BTK) {
1582#define CREATE_BUILTIN_TEMPLATE_PARAMETER_LIST
1583#include "clang/Basic/BuiltinTemplates.inc"
1584 }
1585
1586 llvm_unreachable("unhandled BuiltinTemplateKind!");
1587}
1588
1589void BuiltinTemplateDecl::anchor() {}
1590
1591BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
1592 DeclarationName Name,
1593 BuiltinTemplateKind BTK)
1594 : TemplateDecl(BuiltinTemplate, DC, SourceLocation(), Name,
1595 createBuiltinTemplateParameterList(C, DC, BTK)),
1596 BTK(BTK) {}
1597
1598bool BuiltinTemplateDecl::isPackProducingBuiltinTemplate() const {
1599 return getBuiltinTemplateKind() == clang::BTK__builtin_dedup_pack;
1600}
1601
1602bool clang::isPackProducingBuiltinTemplateName(TemplateName N) {
1603 auto *T = dyn_cast_or_null<BuiltinTemplateDecl>(
1604 Val: N.getAsTemplateDecl(/*IgnoreDeduced=*/true));
1605 return T && T->isPackProducingBuiltinTemplate();
1606}
1607
1608TemplateParamObjectDecl *TemplateParamObjectDecl::Create(const ASTContext &C,
1609 QualType T,
1610 const APValue &V) {
1611 DeclContext *DC = C.getTranslationUnitDecl();
1612 auto *TPOD = new (C, DC) TemplateParamObjectDecl(DC, T, V);
1613 C.addDestruction(Ptr: &TPOD->Value);
1614 return TPOD;
1615}
1616
1617TemplateParamObjectDecl *
1618TemplateParamObjectDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
1619 auto *TPOD = new (C, ID) TemplateParamObjectDecl(nullptr, QualType(), APValue());
1620 C.addDestruction(Ptr: &TPOD->Value);
1621 return TPOD;
1622}
1623
1624void TemplateParamObjectDecl::printName(llvm::raw_ostream &OS,
1625 const PrintingPolicy &Policy) const {
1626 OS << "<template param ";
1627 printAsExpr(OS, Policy);
1628 OS << ">";
1629}
1630
1631void TemplateParamObjectDecl::printAsExpr(llvm::raw_ostream &OS) const {
1632 printAsExpr(OS, Policy: getASTContext().getPrintingPolicy());
1633}
1634
1635void TemplateParamObjectDecl::printAsExpr(llvm::raw_ostream &OS,
1636 const PrintingPolicy &Policy) const {
1637 getType().getUnqualifiedType().print(OS, Policy);
1638 printAsInit(OS, Policy);
1639}
1640
1641void TemplateParamObjectDecl::printAsInit(llvm::raw_ostream &OS) const {
1642 printAsInit(OS, Policy: getASTContext().getPrintingPolicy());
1643}
1644
1645void TemplateParamObjectDecl::printAsInit(llvm::raw_ostream &OS,
1646 const PrintingPolicy &Policy) const {
1647 getValue().printPretty(OS, Policy, Ty: getType(), Ctx: &getASTContext());
1648}
1649
1650std::tuple<NamedDecl *, TemplateArgument>
1651clang::getReplacedTemplateParameter(Decl *D, unsigned Index) {
1652 switch (D->getKind()) {
1653 case Decl::Kind::BuiltinTemplate:
1654 case Decl::Kind::ClassTemplate:
1655 case Decl::Kind::Concept:
1656 case Decl::Kind::FunctionTemplate:
1657 case Decl::Kind::TemplateTemplateParm:
1658 case Decl::Kind::TypeAliasTemplate:
1659 case Decl::Kind::VarTemplate:
1660 return {cast<TemplateDecl>(Val: D)->getTemplateParameters()->getParam(Idx: Index),
1661 {}};
1662 case Decl::Kind::ClassTemplateSpecialization: {
1663 const auto *CTSD = cast<ClassTemplateSpecializationDecl>(Val: D);
1664 auto P = CTSD->getSpecializedTemplateOrPartial();
1665 TemplateParameterList *TPL;
1666 if (const auto *CTPSD =
1667 dyn_cast<ClassTemplatePartialSpecializationDecl *>(Val&: P)) {
1668 TPL = CTPSD->getTemplateParameters();
1669 // FIXME: Obtain Args deduced for the partial specialization.
1670 return {TPL->getParam(Idx: Index), {}};
1671 }
1672 TPL = cast<ClassTemplateDecl *>(Val&: P)->getTemplateParameters();
1673 return {TPL->getParam(Idx: Index), CTSD->getTemplateArgs()[Index]};
1674 }
1675 case Decl::Kind::VarTemplateSpecialization: {
1676 const auto *VTSD = cast<VarTemplateSpecializationDecl>(Val: D);
1677 auto P = VTSD->getSpecializedTemplateOrPartial();
1678 TemplateParameterList *TPL;
1679 if (const auto *VTPSD =
1680 dyn_cast<VarTemplatePartialSpecializationDecl *>(Val&: P)) {
1681 TPL = VTPSD->getTemplateParameters();
1682 // FIXME: Obtain Args deduced for the partial specialization.
1683 return {TPL->getParam(Idx: Index), {}};
1684 }
1685 TPL = cast<VarTemplateDecl *>(Val&: P)->getTemplateParameters();
1686 return {TPL->getParam(Idx: Index), VTSD->getTemplateArgs()[Index]};
1687 }
1688 case Decl::Kind::ClassTemplatePartialSpecialization:
1689 return {cast<ClassTemplatePartialSpecializationDecl>(Val: D)
1690 ->getTemplateParameters()
1691 ->getParam(Idx: Index),
1692 {}};
1693 case Decl::Kind::VarTemplatePartialSpecialization:
1694 return {cast<VarTemplatePartialSpecializationDecl>(Val: D)
1695 ->getTemplateParameters()
1696 ->getParam(Idx: Index),
1697 {}};
1698 // This is used as the AssociatedDecl for placeholder type deduction.
1699 case Decl::TemplateTypeParm:
1700 return {cast<NamedDecl>(Val: D), {}};
1701 // FIXME: Always use the template decl as the AssociatedDecl.
1702 case Decl::Kind::CXXRecord:
1703 return getReplacedTemplateParameter(
1704 D: cast<CXXRecordDecl>(Val: D)->getDescribedClassTemplate(), Index);
1705 case Decl::Kind::CXXDeductionGuide:
1706 case Decl::Kind::CXXConversion:
1707 case Decl::Kind::CXXConstructor:
1708 case Decl::Kind::CXXDestructor:
1709 case Decl::Kind::CXXMethod:
1710 case Decl::Kind::Function:
1711 return getReplacedTemplateParameter(
1712 D: cast<FunctionDecl>(Val: D)->getTemplateSpecializationInfo()->getTemplate(),
1713 Index);
1714 default:
1715 llvm_unreachable("Unhandled templated declaration kind");
1716 }
1717}
1718
1719const Decl &clang::adjustDeclToTemplate(const Decl &D) {
1720 if (const auto *FD = dyn_cast<FunctionDecl>(Val: &D)) {
1721 // Is this function declaration part of a function template?
1722 if (const FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate())
1723 return *FTD;
1724
1725 // Nothing to do if function is not an implicit instantiation.
1726 if (FD->getTemplateSpecializationKind() != TSK_ImplicitInstantiation)
1727 return D;
1728
1729 // Function is an implicit instantiation of a function template?
1730 if (const FunctionTemplateDecl *FTD = FD->getPrimaryTemplate())
1731 return *FTD;
1732
1733 // Function is instantiated from a member definition of a class template?
1734 if (const FunctionDecl *MemberDecl =
1735 FD->getInstantiatedFromMemberFunction())
1736 return *MemberDecl;
1737
1738 return D;
1739 }
1740 if (const auto *VD = dyn_cast<VarDecl>(Val: &D)) {
1741 // Static data member is instantiated from a member definition of a class
1742 // template?
1743 if (VD->isStaticDataMember())
1744 if (const VarDecl *MemberDecl = VD->getInstantiatedFromStaticDataMember())
1745 return *MemberDecl;
1746
1747 return D;
1748 }
1749 if (const auto *CRD = dyn_cast<CXXRecordDecl>(Val: &D)) {
1750 // Is this class declaration part of a class template?
1751 if (const ClassTemplateDecl *CTD = CRD->getDescribedClassTemplate())
1752 return *CTD;
1753
1754 // Class is an implicit instantiation of a class template or partial
1755 // specialization?
1756 if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Val: CRD)) {
1757 if (CTSD->getSpecializationKind() != TSK_ImplicitInstantiation)
1758 return D;
1759 llvm::PointerUnion<ClassTemplateDecl *,
1760 ClassTemplatePartialSpecializationDecl *>
1761 PU = CTSD->getSpecializedTemplateOrPartial();
1762 return isa<ClassTemplateDecl *>(Val: PU)
1763 ? *static_cast<const Decl *>(cast<ClassTemplateDecl *>(Val&: PU))
1764 : *static_cast<const Decl *>(
1765 cast<ClassTemplatePartialSpecializationDecl *>(Val&: PU));
1766 }
1767
1768 // Class is instantiated from a member definition of a class template?
1769 if (const MemberSpecializationInfo *Info =
1770 CRD->getMemberSpecializationInfo())
1771 return *Info->getInstantiatedFrom();
1772
1773 return D;
1774 }
1775 if (const auto *ED = dyn_cast<EnumDecl>(Val: &D)) {
1776 // Enum is instantiated from a member definition of a class template?
1777 if (const EnumDecl *MemberDecl = ED->getInstantiatedFromMemberEnum())
1778 return *MemberDecl;
1779
1780 return D;
1781 }
1782 // FIXME: Adjust alias templates?
1783 return D;
1784}
1785