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