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/ExternalASTSource.h"
20#include "clang/AST/TemplateBase.h"
21#include "clang/AST/TemplateName.h"
22#include "clang/AST/Type.h"
23#include "clang/AST/TypeLoc.h"
24#include "clang/Basic/Builtins.h"
25#include "clang/Basic/LLVM.h"
26#include "clang/Basic/SourceLocation.h"
27#include "llvm/ADT/ArrayRef.h"
28#include "llvm/ADT/FoldingSet.h"
29#include "llvm/ADT/PointerUnion.h"
30#include "llvm/ADT/STLExtras.h"
31#include "llvm/ADT/SmallVector.h"
32#include "llvm/Support/Casting.h"
33#include "llvm/Support/ErrorHandling.h"
34#include <algorithm>
35#include <cassert>
36#include <cstdint>
37#include <memory>
38#include <optional>
39#include <utility>
40
41using namespace clang;
42
43//===----------------------------------------------------------------------===//
44// TemplateParameterList Implementation
45//===----------------------------------------------------------------------===//
46
47
48TemplateParameterList::TemplateParameterList(const ASTContext& C,
49 SourceLocation TemplateLoc,
50 SourceLocation LAngleLoc,
51 ArrayRef<NamedDecl *> Params,
52 SourceLocation RAngleLoc,
53 Expr *RequiresClause)
54 : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
55 NumParams(Params.size()), ContainsUnexpandedParameterPack(false),
56 HasRequiresClause(RequiresClause != nullptr),
57 HasConstrainedParameters(false) {
58 for (unsigned Idx = 0; Idx < NumParams; ++Idx) {
59 NamedDecl *P = Params[Idx];
60 begin()[Idx] = P;
61
62 bool IsPack = P->isTemplateParameterPack();
63 if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: P)) {
64 if (!IsPack && NTTP->getType()->containsUnexpandedParameterPack())
65 ContainsUnexpandedParameterPack = true;
66 if (NTTP->hasPlaceholderTypeConstraint())
67 HasConstrainedParameters = true;
68 } else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Val: P)) {
69 if (!IsPack &&
70 TTP->getTemplateParameters()->containsUnexpandedParameterPack())
71 ContainsUnexpandedParameterPack = true;
72 } else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Val: P)) {
73 if (const TypeConstraint *TC = TTP->getTypeConstraint()) {
74 if (TC->getImmediatelyDeclaredConstraint()
75 ->containsUnexpandedParameterPack())
76 ContainsUnexpandedParameterPack = true;
77 }
78 if (TTP->hasTypeConstraint())
79 HasConstrainedParameters = true;
80 } else {
81 llvm_unreachable("unexpected template parameter type");
82 }
83 // FIXME: If a default argument contains an unexpanded parameter pack, the
84 // template parameter list does too.
85 }
86
87 if (HasRequiresClause) {
88 if (RequiresClause->containsUnexpandedParameterPack())
89 ContainsUnexpandedParameterPack = true;
90 *getTrailingObjects<Expr *>() = RequiresClause;
91 }
92}
93
94bool TemplateParameterList::containsUnexpandedParameterPack() const {
95 if (ContainsUnexpandedParameterPack)
96 return true;
97 if (!HasConstrainedParameters)
98 return false;
99
100 // An implicit constrained parameter might have had a use of an unexpanded
101 // pack added to it after the template parameter list was created. All
102 // implicit parameters are at the end of the parameter list.
103 for (const NamedDecl *Param : llvm::reverse(C: asArray())) {
104 if (!Param->isImplicit())
105 break;
106
107 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Val: Param)) {
108 const auto *TC = TTP->getTypeConstraint();
109 if (TC && TC->getImmediatelyDeclaredConstraint()
110 ->containsUnexpandedParameterPack())
111 return true;
112 }
113 }
114
115 return false;
116}
117
118TemplateParameterList *
119TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc,
120 SourceLocation LAngleLoc,
121 ArrayRef<NamedDecl *> Params,
122 SourceLocation RAngleLoc, Expr *RequiresClause) {
123 void *Mem = C.Allocate(Size: totalSizeToAlloc<NamedDecl *, Expr *>(
124 Counts: Params.size(), Counts: RequiresClause ? 1u : 0u),
125 Align: alignof(TemplateParameterList));
126 return new (Mem) TemplateParameterList(C, TemplateLoc, LAngleLoc, Params,
127 RAngleLoc, RequiresClause);
128}
129
130void TemplateParameterList::Profile(llvm::FoldingSetNodeID &ID,
131 const ASTContext &C) const {
132 const Expr *RC = getRequiresClause();
133 ID.AddBoolean(B: RC != nullptr);
134 if (RC)
135 RC->Profile(ID, C, /*Canonical=*/true);
136 ID.AddInteger(I: size());
137 for (NamedDecl *D : *this) {
138 if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: D)) {
139 ID.AddInteger(I: 0);
140 ID.AddBoolean(B: NTTP->isParameterPack());
141 NTTP->getType().getCanonicalType().Profile(ID);
142 ID.AddBoolean(B: NTTP->hasPlaceholderTypeConstraint());
143 if (const Expr *E = NTTP->getPlaceholderTypeConstraint())
144 E->Profile(ID, C, /*Canonical=*/true);
145 continue;
146 }
147 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Val: D)) {
148 ID.AddInteger(I: 1);
149 ID.AddBoolean(B: TTP->isParameterPack());
150 ID.AddBoolean(B: TTP->hasTypeConstraint());
151 if (const TypeConstraint *TC = TTP->getTypeConstraint())
152 TC->getImmediatelyDeclaredConstraint()->Profile(ID, C,
153 /*Canonical=*/true);
154 continue;
155 }
156 const auto *TTP = cast<TemplateTemplateParmDecl>(Val: D);
157 ID.AddInteger(I: 2);
158 ID.AddBoolean(B: TTP->isParameterPack());
159 TTP->getTemplateParameters()->Profile(ID, C);
160 }
161}
162
163unsigned TemplateParameterList::getMinRequiredArguments() const {
164 unsigned NumRequiredArgs = 0;
165 for (const NamedDecl *P : asArray()) {
166 if (P->isTemplateParameterPack()) {
167 if (std::optional<unsigned> Expansions = getExpandedPackSize(Param: P)) {
168 NumRequiredArgs += *Expansions;
169 continue;
170 }
171 break;
172 }
173
174 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Val: P)) {
175 if (TTP->hasDefaultArgument())
176 break;
177 } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: P)) {
178 if (NTTP->hasDefaultArgument())
179 break;
180 } else if (cast<TemplateTemplateParmDecl>(Val: P)->hasDefaultArgument())
181 break;
182
183 ++NumRequiredArgs;
184 }
185
186 return NumRequiredArgs;
187}
188
189unsigned TemplateParameterList::getDepth() const {
190 if (size() == 0)
191 return 0;
192
193 const NamedDecl *FirstParm = getParam(Idx: 0);
194 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Val: FirstParm))
195 return TTP->getDepth();
196 else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: FirstParm))
197 return NTTP->getDepth();
198 else
199 return cast<TemplateTemplateParmDecl>(Val: FirstParm)->getDepth();
200}
201
202static bool AdoptTemplateParameterList(TemplateParameterList *Params,
203 DeclContext *Owner) {
204 bool Invalid = false;
205 for (NamedDecl *P : *Params) {
206 P->setDeclContext(Owner);
207
208 if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Val: P))
209 if (AdoptTemplateParameterList(TTP->getTemplateParameters(), Owner))
210 Invalid = true;
211
212 if (P->isInvalidDecl())
213 Invalid = true;
214 }
215 return Invalid;
216}
217
218void TemplateParameterList::
219getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
220 if (HasConstrainedParameters)
221 for (const NamedDecl *Param : *this) {
222 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Val: Param)) {
223 if (const auto *TC = TTP->getTypeConstraint())
224 AC.push_back(Elt: TC->getImmediatelyDeclaredConstraint());
225 } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Val: Param)) {
226 if (const Expr *E = NTTP->getPlaceholderTypeConstraint())
227 AC.push_back(Elt: E);
228 }
229 }
230 if (HasRequiresClause)
231 AC.push_back(Elt: getRequiresClause());
232}
233
234bool TemplateParameterList::hasAssociatedConstraints() const {
235 return HasRequiresClause || HasConstrainedParameters;
236}
237
238bool TemplateParameterList::shouldIncludeTypeForArgument(
239 const PrintingPolicy &Policy, const TemplateParameterList *TPL,
240 unsigned Idx) {
241 if (!TPL || Idx >= TPL->size() || Policy.AlwaysIncludeTypeForTemplateArgument)
242 return true;
243 const NamedDecl *TemplParam = TPL->getParam(Idx);
244 if (const auto *ParamValueDecl =
245 dyn_cast<NonTypeTemplateParmDecl>(Val: TemplParam))
246 if (ParamValueDecl->getType()->getContainedDeducedType())
247 return true;
248 return false;
249}
250
251namespace clang {
252
253void *allocateDefaultArgStorageChain(const ASTContext &C) {
254 return new (C) char[sizeof(void*) * 2];
255}
256
257} // namespace clang
258
259//===----------------------------------------------------------------------===//
260// TemplateDecl Implementation
261//===----------------------------------------------------------------------===//
262
263TemplateDecl::TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
264 DeclarationName Name, TemplateParameterList *Params,
265 NamedDecl *Decl)
266 : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), TemplateParams(Params) {}
267
268void TemplateDecl::anchor() {}
269
270void TemplateDecl::
271getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
272 TemplateParams->getAssociatedConstraints(AC);
273 if (auto *FD = dyn_cast_or_null<FunctionDecl>(Val: getTemplatedDecl()))
274 if (const Expr *TRC = FD->getTrailingRequiresClause())
275 AC.push_back(Elt: TRC);
276}
277
278bool TemplateDecl::hasAssociatedConstraints() const {
279 if (TemplateParams->hasAssociatedConstraints())
280 return true;
281 if (auto *FD = dyn_cast_or_null<FunctionDecl>(Val: getTemplatedDecl()))
282 return FD->getTrailingRequiresClause();
283 return false;
284}
285
286bool TemplateDecl::isTypeAlias() const {
287 switch (getKind()) {
288 case TemplateDecl::TypeAliasTemplate:
289 case TemplateDecl::BuiltinTemplate:
290 return true;
291 default:
292 return false;
293 };
294}
295
296//===----------------------------------------------------------------------===//
297// RedeclarableTemplateDecl Implementation
298//===----------------------------------------------------------------------===//
299
300void RedeclarableTemplateDecl::anchor() {}
301
302RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() const {
303 if (Common)
304 return Common;
305
306 // Walk the previous-declaration chain until we either find a declaration
307 // with a common pointer or we run out of previous declarations.
308 SmallVector<const RedeclarableTemplateDecl *, 2> PrevDecls;
309 for (const RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev;
310 Prev = Prev->getPreviousDecl()) {
311 if (Prev->Common) {
312 Common = Prev->Common;
313 break;
314 }
315
316 PrevDecls.push_back(Elt: Prev);
317 }
318
319 // If we never found a common pointer, allocate one now.
320 if (!Common) {
321 // FIXME: If any of the declarations is from an AST file, we probably
322 // need an update record to add the common data.
323
324 Common = newCommon(C&: getASTContext());
325 }
326
327 // Update any previous declarations we saw with the common pointer.
328 for (const RedeclarableTemplateDecl *Prev : PrevDecls)
329 Prev->Common = Common;
330
331 return Common;
332}
333
334void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
335 // Grab the most recent declaration to ensure we've loaded any lazy
336 // redeclarations of this template.
337 CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
338 if (CommonBasePtr->LazySpecializations) {
339 ASTContext &Context = getASTContext();
340 Decl::DeclID *Specs = CommonBasePtr->LazySpecializations;
341 CommonBasePtr->LazySpecializations = nullptr;
342 for (uint32_t I = 0, N = *Specs++; I != N; ++I)
343 (void)Context.getExternalSource()->GetExternalDecl(ID: Specs[I]);
344 }
345}
346
347template<class EntryType, typename... ProfileArguments>
348typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
349RedeclarableTemplateDecl::findSpecializationImpl(
350 llvm::FoldingSetVector<EntryType> &Specs, void *&InsertPos,
351 ProfileArguments&&... ProfileArgs) {
352 using SETraits = SpecEntryTraits<EntryType>;
353
354 llvm::FoldingSetNodeID ID;
355 EntryType::Profile(ID, std::forward<ProfileArguments>(ProfileArgs)...,
356 getASTContext());
357 EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
358 return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr;
359}
360
361template<class Derived, class EntryType>
362void RedeclarableTemplateDecl::addSpecializationImpl(
363 llvm::FoldingSetVector<EntryType> &Specializations, EntryType *Entry,
364 void *InsertPos) {
365 using SETraits = SpecEntryTraits<EntryType>;
366
367 if (InsertPos) {
368#ifndef NDEBUG
369 void *CorrectInsertPos;
370 assert(!findSpecializationImpl(Specializations,
371 CorrectInsertPos,
372 SETraits::getTemplateArgs(Entry)) &&
373 InsertPos == CorrectInsertPos &&
374 "given incorrect InsertPos for specialization");
375#endif
376 Specializations.InsertNode(Entry, InsertPos);
377 } else {
378 EntryType *Existing = Specializations.GetOrInsertNode(Entry);
379 (void)Existing;
380 assert(SETraits::getDecl(Existing)->isCanonicalDecl() &&
381 "non-canonical specialization?");
382 }
383
384 if (ASTMutationListener *L = getASTMutationListener())
385 L->AddedCXXTemplateSpecialization(cast<Derived>(this),
386 SETraits::getDecl(Entry));
387}
388
389ArrayRef<TemplateArgument> RedeclarableTemplateDecl::getInjectedTemplateArgs() {
390 TemplateParameterList *Params = getTemplateParameters();
391 auto *CommonPtr = getCommonPtr();
392 if (!CommonPtr->InjectedArgs) {
393 auto &Context = getASTContext();
394 SmallVector<TemplateArgument, 16> TemplateArgs;
395 Context.getInjectedTemplateArgs(Params, TemplateArgs);
396 CommonPtr->InjectedArgs =
397 new (Context) TemplateArgument[TemplateArgs.size()];
398 std::copy(first: TemplateArgs.begin(), last: TemplateArgs.end(),
399 result: CommonPtr->InjectedArgs);
400 }
401
402 return llvm::ArrayRef(CommonPtr->InjectedArgs, Params->size());
403}
404
405//===----------------------------------------------------------------------===//
406// FunctionTemplateDecl Implementation
407//===----------------------------------------------------------------------===//
408
409FunctionTemplateDecl *
410FunctionTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
411 DeclarationName Name,
412 TemplateParameterList *Params, NamedDecl *Decl) {
413 bool Invalid = AdoptTemplateParameterList(Params, Owner: cast<DeclContext>(Val: Decl));
414 auto *TD = new (C, DC) FunctionTemplateDecl(C, DC, L, Name, Params, Decl);
415 if (Invalid)
416 TD->setInvalidDecl();
417 return TD;
418}
419
420FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C,
421 Decl::DeclID ID) {
422 return new (C, ID) FunctionTemplateDecl(C, nullptr, SourceLocation(),
423 DeclarationName(), nullptr, nullptr);
424}
425
426RedeclarableTemplateDecl::CommonBase *
427FunctionTemplateDecl::newCommon(ASTContext &C) const {
428 auto *CommonPtr = new (C) Common;
429 C.addDestruction(Ptr: CommonPtr);
430 return CommonPtr;
431}
432
433void FunctionTemplateDecl::LoadLazySpecializations() const {
434 loadLazySpecializationsImpl();
435}
436
437llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
438FunctionTemplateDecl::getSpecializations() const {
439 LoadLazySpecializations();
440 return getCommonPtr()->Specializations;
441}
442
443FunctionDecl *
444FunctionTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
445 void *&InsertPos) {
446 return findSpecializationImpl(getSpecializations(), InsertPos, Args);
447}
448
449void FunctionTemplateDecl::addSpecialization(
450 FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
451 addSpecializationImpl<FunctionTemplateDecl>(getSpecializations(), Info,
452 InsertPos);
453}
454
455void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
456 using Base = RedeclarableTemplateDecl;
457
458 // If we haven't created a common pointer yet, then it can just be created
459 // with the usual method.
460 if (!Base::Common)
461 return;
462
463 Common *ThisCommon = static_cast<Common *>(Base::Common);
464 Common *PrevCommon = nullptr;
465 SmallVector<FunctionTemplateDecl *, 8> PreviousDecls;
466 for (; Prev; Prev = Prev->getPreviousDecl()) {
467 if (Prev->Base::Common) {
468 PrevCommon = static_cast<Common *>(Prev->Base::Common);
469 break;
470 }
471 PreviousDecls.push_back(Elt: Prev);
472 }
473
474 // If the previous redecl chain hasn't created a common pointer yet, then just
475 // use this common pointer.
476 if (!PrevCommon) {
477 for (auto *D : PreviousDecls)
478 D->Base::Common = ThisCommon;
479 return;
480 }
481
482 // Ensure we don't leak any important state.
483 assert(ThisCommon->Specializations.size() == 0 &&
484 "Can't merge incompatible declarations!");
485
486 Base::Common = PrevCommon;
487}
488
489//===----------------------------------------------------------------------===//
490// ClassTemplateDecl Implementation
491//===----------------------------------------------------------------------===//
492
493ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, DeclContext *DC,
494 SourceLocation L,
495 DeclarationName Name,
496 TemplateParameterList *Params,
497 NamedDecl *Decl) {
498 bool Invalid = AdoptTemplateParameterList(Params, Owner: cast<DeclContext>(Val: Decl));
499 auto *TD = new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
500 if (Invalid)
501 TD->setInvalidDecl();
502 return TD;
503}
504
505ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
506 Decl::DeclID ID) {
507 return new (C, ID) ClassTemplateDecl(C, nullptr, SourceLocation(),
508 DeclarationName(), nullptr, nullptr);
509}
510
511void ClassTemplateDecl::LoadLazySpecializations() const {
512 loadLazySpecializationsImpl();
513}
514
515llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
516ClassTemplateDecl::getSpecializations() const {
517 LoadLazySpecializations();
518 return getCommonPtr()->Specializations;
519}
520
521llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
522ClassTemplateDecl::getPartialSpecializations() const {
523 LoadLazySpecializations();
524 return getCommonPtr()->PartialSpecializations;
525}
526
527RedeclarableTemplateDecl::CommonBase *
528ClassTemplateDecl::newCommon(ASTContext &C) const {
529 auto *CommonPtr = new (C) Common;
530 C.addDestruction(Ptr: CommonPtr);
531 return CommonPtr;
532}
533
534ClassTemplateSpecializationDecl *
535ClassTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
536 void *&InsertPos) {
537 return findSpecializationImpl(getSpecializations(), InsertPos, Args);
538}
539
540void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D,
541 void *InsertPos) {
542 addSpecializationImpl<ClassTemplateDecl>(getSpecializations(), D, InsertPos);
543}
544
545ClassTemplatePartialSpecializationDecl *
546ClassTemplateDecl::findPartialSpecialization(
547 ArrayRef<TemplateArgument> Args,
548 TemplateParameterList *TPL, void *&InsertPos) {
549 return findSpecializationImpl(getPartialSpecializations(), InsertPos, Args,
550 TPL);
551}
552
553void ClassTemplatePartialSpecializationDecl::Profile(
554 llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
555 TemplateParameterList *TPL, const ASTContext &Context) {
556 ID.AddInteger(I: TemplateArgs.size());
557 for (const TemplateArgument &TemplateArg : TemplateArgs)
558 TemplateArg.Profile(ID, Context);
559 TPL->Profile(ID, C: Context);
560}
561
562void ClassTemplateDecl::AddPartialSpecialization(
563 ClassTemplatePartialSpecializationDecl *D,
564 void *InsertPos) {
565 if (InsertPos)
566 getPartialSpecializations().InsertNode(N: D, InsertPos);
567 else {
568 ClassTemplatePartialSpecializationDecl *Existing
569 = getPartialSpecializations().GetOrInsertNode(N: D);
570 (void)Existing;
571 assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
572 }
573
574 if (ASTMutationListener *L = getASTMutationListener())
575 L->AddedCXXTemplateSpecialization(this, D);
576}
577
578void ClassTemplateDecl::getPartialSpecializations(
579 SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) const {
580 llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &PartialSpecs
581 = getPartialSpecializations();
582 PS.clear();
583 PS.reserve(N: PartialSpecs.size());
584 for (ClassTemplatePartialSpecializationDecl &P : PartialSpecs)
585 PS.push_back(Elt: P.getMostRecentDecl());
586}
587
588ClassTemplatePartialSpecializationDecl *
589ClassTemplateDecl::findPartialSpecialization(QualType T) {
590 ASTContext &Context = getASTContext();
591 for (ClassTemplatePartialSpecializationDecl &P :
592 getPartialSpecializations()) {
593 if (Context.hasSameType(T1: P.getInjectedSpecializationType(), T2: T))
594 return P.getMostRecentDecl();
595 }
596
597 return nullptr;
598}
599
600ClassTemplatePartialSpecializationDecl *
601ClassTemplateDecl::findPartialSpecInstantiatedFromMember(
602 ClassTemplatePartialSpecializationDecl *D) {
603 Decl *DCanon = D->getCanonicalDecl();
604 for (ClassTemplatePartialSpecializationDecl &P : getPartialSpecializations()) {
605 if (P.getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
606 return P.getMostRecentDecl();
607 }
608
609 return nullptr;
610}
611
612QualType
613ClassTemplateDecl::getInjectedClassNameSpecialization() {
614 Common *CommonPtr = getCommonPtr();
615 if (!CommonPtr->InjectedClassNameType.isNull())
616 return CommonPtr->InjectedClassNameType;
617
618 // C++0x [temp.dep.type]p2:
619 // The template argument list of a primary template is a template argument
620 // list in which the nth template argument has the value of the nth template
621 // parameter of the class template. If the nth template parameter is a
622 // template parameter pack (14.5.3), the nth template argument is a pack
623 // expansion (14.5.3) whose pattern is the name of the template parameter
624 // pack.
625 ASTContext &Context = getASTContext();
626 TemplateParameterList *Params = getTemplateParameters();
627 SmallVector<TemplateArgument, 16> TemplateArgs;
628 Context.getInjectedTemplateArgs(Params, Args&: TemplateArgs);
629 CommonPtr->InjectedClassNameType
630 = Context.getTemplateSpecializationType(T: TemplateName(this),
631 Args: TemplateArgs);
632 return CommonPtr->InjectedClassNameType;
633}
634
635//===----------------------------------------------------------------------===//
636// TemplateTypeParm Allocation/Deallocation Method Implementations
637//===----------------------------------------------------------------------===//
638
639TemplateTypeParmDecl *TemplateTypeParmDecl::Create(
640 const ASTContext &C, DeclContext *DC, SourceLocation KeyLoc,
641 SourceLocation NameLoc, unsigned D, unsigned P, IdentifierInfo *Id,
642 bool Typename, bool ParameterPack, bool HasTypeConstraint,
643 std::optional<unsigned> NumExpanded) {
644 auto *TTPDecl =
645 new (C, DC,
646 additionalSizeToAlloc<TypeConstraint>(Counts: HasTypeConstraint ? 1 : 0))
647 TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename,
648 HasTypeConstraint, NumExpanded);
649 QualType TTPType = C.getTemplateTypeParmType(Depth: D, Index: P, ParameterPack, ParmDecl: TTPDecl);
650 TTPDecl->setTypeForDecl(TTPType.getTypePtr());
651 return TTPDecl;
652}
653
654TemplateTypeParmDecl *
655TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, Decl::DeclID ID) {
656 return new (C, ID)
657 TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), nullptr,
658 false, false, std::nullopt);
659}
660
661TemplateTypeParmDecl *
662TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, Decl::DeclID ID,
663 bool HasTypeConstraint) {
664 return new (C, ID,
665 additionalSizeToAlloc<TypeConstraint>(Counts: HasTypeConstraint ? 1 : 0))
666 TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), nullptr,
667 false, HasTypeConstraint, std::nullopt);
668}
669
670SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
671 return hasDefaultArgument()
672 ? getDefaultArgumentInfo()->getTypeLoc().getBeginLoc()
673 : SourceLocation();
674}
675
676SourceRange TemplateTypeParmDecl::getSourceRange() const {
677 if (hasDefaultArgument() && !defaultArgumentWasInherited())
678 return SourceRange(getBeginLoc(),
679 getDefaultArgumentInfo()->getTypeLoc().getEndLoc());
680 // TypeDecl::getSourceRange returns a range containing name location, which is
681 // wrong for unnamed template parameters. e.g:
682 // it will return <[[typename>]] instead of <[[typename]]>
683 else if (getDeclName().isEmpty())
684 return SourceRange(getBeginLoc());
685 return TypeDecl::getSourceRange();
686}
687
688unsigned TemplateTypeParmDecl::getDepth() const {
689 return getTypeForDecl()->castAs<TemplateTypeParmType>()->getDepth();
690}
691
692unsigned TemplateTypeParmDecl::getIndex() const {
693 return getTypeForDecl()->castAs<TemplateTypeParmType>()->getIndex();
694}
695
696bool TemplateTypeParmDecl::isParameterPack() const {
697 return getTypeForDecl()->castAs<TemplateTypeParmType>()->isParameterPack();
698}
699
700void TemplateTypeParmDecl::setTypeConstraint(
701 ConceptReference *Loc, Expr *ImmediatelyDeclaredConstraint) {
702 assert(HasTypeConstraint &&
703 "HasTypeConstraint=true must be passed at construction in order to "
704 "call setTypeConstraint");
705 assert(!TypeConstraintInitialized &&
706 "TypeConstraint was already initialized!");
707 new (getTrailingObjects<TypeConstraint>())
708 TypeConstraint(Loc, ImmediatelyDeclaredConstraint);
709 TypeConstraintInitialized = true;
710}
711
712//===----------------------------------------------------------------------===//
713// NonTypeTemplateParmDecl Method Implementations
714//===----------------------------------------------------------------------===//
715
716NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(
717 DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D,
718 unsigned P, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
719 ArrayRef<QualType> ExpandedTypes, ArrayRef<TypeSourceInfo *> ExpandedTInfos)
720 : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
721 TemplateParmPosition(D, P), ParameterPack(true),
722 ExpandedParameterPack(true), NumExpandedTypes(ExpandedTypes.size()) {
723 if (!ExpandedTypes.empty() && !ExpandedTInfos.empty()) {
724 auto TypesAndInfos =
725 getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
726 for (unsigned I = 0; I != NumExpandedTypes; ++I) {
727 new (&TypesAndInfos[I].first) QualType(ExpandedTypes[I]);
728 TypesAndInfos[I].second = ExpandedTInfos[I];
729 }
730 }
731}
732
733NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create(
734 const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
735 SourceLocation IdLoc, unsigned D, unsigned P, const IdentifierInfo *Id,
736 QualType T, bool ParameterPack, TypeSourceInfo *TInfo) {
737 AutoType *AT =
738 C.getLangOpts().CPlusPlus20 ? T->getContainedAutoType() : nullptr;
739 return new (C, DC,
740 additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>,
741 Expr *>(0,
742 AT && AT->isConstrained() ? 1 : 0))
743 NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T, ParameterPack,
744 TInfo);
745}
746
747NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create(
748 const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
749 SourceLocation IdLoc, unsigned D, unsigned P, const IdentifierInfo *Id,
750 QualType T, TypeSourceInfo *TInfo, ArrayRef<QualType> ExpandedTypes,
751 ArrayRef<TypeSourceInfo *> ExpandedTInfos) {
752 AutoType *AT = TInfo->getType()->getContainedAutoType();
753 return new (C, DC,
754 additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>,
755 Expr *>(
756 ExpandedTypes.size(), AT && AT->isConstrained() ? 1 : 0))
757 NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T, TInfo,
758 ExpandedTypes, ExpandedTInfos);
759}
760
761NonTypeTemplateParmDecl *
762NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,
763 bool HasTypeConstraint) {
764 return new (C, ID, additionalSizeToAlloc<std::pair<QualType,
765 TypeSourceInfo *>,
766 Expr *>(0,
767 HasTypeConstraint ? 1 : 0))
768 NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(),
769 0, 0, nullptr, QualType(), false, nullptr);
770}
771
772NonTypeTemplateParmDecl *
773NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,
774 unsigned NumExpandedTypes,
775 bool HasTypeConstraint) {
776 auto *NTTP =
777 new (C, ID,
778 additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, Expr *>(
779 NumExpandedTypes, HasTypeConstraint ? 1 : 0))
780 NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(),
781 0, 0, nullptr, QualType(), nullptr,
782 std::nullopt, std::nullopt);
783 NTTP->NumExpandedTypes = NumExpandedTypes;
784 return NTTP;
785}
786
787SourceRange NonTypeTemplateParmDecl::getSourceRange() const {
788 if (hasDefaultArgument() && !defaultArgumentWasInherited())
789 return SourceRange(getOuterLocStart(),
790 getDefaultArgument()->getSourceRange().getEnd());
791 return DeclaratorDecl::getSourceRange();
792}
793
794SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
795 return hasDefaultArgument()
796 ? getDefaultArgument()->getSourceRange().getBegin()
797 : SourceLocation();
798}
799
800//===----------------------------------------------------------------------===//
801// TemplateTemplateParmDecl Method Implementations
802//===----------------------------------------------------------------------===//
803
804void TemplateTemplateParmDecl::anchor() {}
805
806TemplateTemplateParmDecl::TemplateTemplateParmDecl(
807 DeclContext *DC, SourceLocation L, unsigned D, unsigned P,
808 IdentifierInfo *Id, bool Typename, TemplateParameterList *Params,
809 ArrayRef<TemplateParameterList *> Expansions)
810 : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
811 TemplateParmPosition(D, P), Typename(Typename), ParameterPack(true),
812 ExpandedParameterPack(true), NumExpandedParams(Expansions.size()) {
813 if (!Expansions.empty())
814 std::uninitialized_copy(Expansions.begin(), Expansions.end(),
815 getTrailingObjects<TemplateParameterList *>());
816}
817
818TemplateTemplateParmDecl *
819TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
820 SourceLocation L, unsigned D, unsigned P,
821 bool ParameterPack, IdentifierInfo *Id,
822 bool Typename, TemplateParameterList *Params) {
823 return new (C, DC) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id,
824 Typename, Params);
825}
826
827TemplateTemplateParmDecl *
828TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
829 SourceLocation L, unsigned D, unsigned P,
830 IdentifierInfo *Id, bool Typename,
831 TemplateParameterList *Params,
832 ArrayRef<TemplateParameterList *> Expansions) {
833 return new (C, DC,
834 additionalSizeToAlloc<TemplateParameterList *>(Counts: Expansions.size()))
835 TemplateTemplateParmDecl(DC, L, D, P, Id, Typename, Params, Expansions);
836}
837
838TemplateTemplateParmDecl *
839TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {
840 return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0,
841 false, nullptr, false, nullptr);
842}
843
844TemplateTemplateParmDecl *
845TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID,
846 unsigned NumExpansions) {
847 auto *TTP =
848 new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(Counts: NumExpansions))
849 TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr,
850 false, nullptr, std::nullopt);
851 TTP->NumExpandedParams = NumExpansions;
852 return TTP;
853}
854
855SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
856 return hasDefaultArgument() ? getDefaultArgument().getLocation()
857 : SourceLocation();
858}
859
860void TemplateTemplateParmDecl::setDefaultArgument(
861 const ASTContext &C, const TemplateArgumentLoc &DefArg) {
862 if (DefArg.getArgument().isNull())
863 DefaultArgument.set(nullptr);
864 else
865 DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg));
866}
867
868//===----------------------------------------------------------------------===//
869// TemplateArgumentList Implementation
870//===----------------------------------------------------------------------===//
871TemplateArgumentList::TemplateArgumentList(ArrayRef<TemplateArgument> Args)
872 : NumArguments(Args.size()) {
873 std::uninitialized_copy(first: Args.begin(), last: Args.end(),
874 result: getTrailingObjects<TemplateArgument>());
875}
876
877TemplateArgumentList *
878TemplateArgumentList::CreateCopy(ASTContext &Context,
879 ArrayRef<TemplateArgument> Args) {
880 void *Mem = Context.Allocate(Size: totalSizeToAlloc<TemplateArgument>(Counts: Args.size()));
881 return new (Mem) TemplateArgumentList(Args);
882}
883
884FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create(
885 ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
886 TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs,
887 const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI,
888 MemberSpecializationInfo *MSInfo) {
889 const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
890 if (TemplateArgsAsWritten)
891 ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C,
892 List: *TemplateArgsAsWritten);
893
894 void *Mem =
895 C.Allocate(Size: totalSizeToAlloc<MemberSpecializationInfo *>(Counts: MSInfo ? 1 : 0));
896 return new (Mem) FunctionTemplateSpecializationInfo(
897 FD, Template, TSK, TemplateArgs, ArgsAsWritten, POI, MSInfo);
898}
899
900//===----------------------------------------------------------------------===//
901// ClassTemplateSpecializationDecl Implementation
902//===----------------------------------------------------------------------===//
903
904ClassTemplateSpecializationDecl::
905ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
906 DeclContext *DC, SourceLocation StartLoc,
907 SourceLocation IdLoc,
908 ClassTemplateDecl *SpecializedTemplate,
909 ArrayRef<TemplateArgument> Args,
910 ClassTemplateSpecializationDecl *PrevDecl)
911 : CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc,
912 SpecializedTemplate->getIdentifier(), PrevDecl),
913 SpecializedTemplate(SpecializedTemplate),
914 TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
915 SpecializationKind(TSK_Undeclared) {
916}
917
918ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
919 Kind DK)
920 : CXXRecordDecl(DK, TagTypeKind::Struct, C, nullptr, SourceLocation(),
921 SourceLocation(), nullptr, nullptr),
922 SpecializationKind(TSK_Undeclared) {}
923
924ClassTemplateSpecializationDecl *
925ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
926 DeclContext *DC,
927 SourceLocation StartLoc,
928 SourceLocation IdLoc,
929 ClassTemplateDecl *SpecializedTemplate,
930 ArrayRef<TemplateArgument> Args,
931 ClassTemplateSpecializationDecl *PrevDecl) {
932 auto *Result =
933 new (Context, DC) ClassTemplateSpecializationDecl(
934 Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
935 SpecializedTemplate, Args, PrevDecl);
936 Result->setMayHaveOutOfDateDef(false);
937
938 // If the template decl is incomplete, copy the external lexical storage from
939 // the base template. This allows instantiations of incomplete types to
940 // complete using the external AST if the template's declaration came from an
941 // external AST.
942 if (!SpecializedTemplate->getTemplatedDecl()->isCompleteDefinition())
943 Result->setHasExternalLexicalStorage(
944 SpecializedTemplate->getTemplatedDecl()->hasExternalLexicalStorage());
945
946 Context.getTypeDeclType(Decl: Result, PrevDecl);
947 return Result;
948}
949
950ClassTemplateSpecializationDecl *
951ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
952 Decl::DeclID ID) {
953 auto *Result =
954 new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
955 Result->setMayHaveOutOfDateDef(false);
956 return Result;
957}
958
959void ClassTemplateSpecializationDecl::getNameForDiagnostic(
960 raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
961 NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
962
963 const auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(Val: this);
964 if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
965 PS ? PS->getTemplateArgsAsWritten() : nullptr) {
966 printTemplateArgumentList(
967 OS, ArgsAsWritten->arguments(), Policy,
968 getSpecializedTemplate()->getTemplateParameters());
969 } else {
970 const TemplateArgumentList &TemplateArgs = getTemplateArgs();
971 printTemplateArgumentList(
972 OS, TemplateArgs.asArray(), Policy,
973 getSpecializedTemplate()->getTemplateParameters());
974 }
975}
976
977ClassTemplateDecl *
978ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
979 if (const auto *PartialSpec =
980 SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
981 return PartialSpec->PartialSpecialization->getSpecializedTemplate();
982 return SpecializedTemplate.get<ClassTemplateDecl*>();
983}
984
985SourceRange
986ClassTemplateSpecializationDecl::getSourceRange() const {
987 if (ExplicitInfo) {
988 SourceLocation Begin = getTemplateKeywordLoc();
989 if (Begin.isValid()) {
990 // Here we have an explicit (partial) specialization or instantiation.
991 assert(getSpecializationKind() == TSK_ExplicitSpecialization ||
992 getSpecializationKind() == TSK_ExplicitInstantiationDeclaration ||
993 getSpecializationKind() == TSK_ExplicitInstantiationDefinition);
994 if (getExternLoc().isValid())
995 Begin = getExternLoc();
996 SourceLocation End = getBraceRange().getEnd();
997 if (End.isInvalid())
998 End = getTypeAsWritten()->getTypeLoc().getEndLoc();
999 return SourceRange(Begin, End);
1000 }
1001 // An implicit instantiation of a class template partial specialization
1002 // uses ExplicitInfo to record the TypeAsWritten, but the source
1003 // locations should be retrieved from the instantiation pattern.
1004 using CTPSDecl = ClassTemplatePartialSpecializationDecl;
1005 auto *ctpsd = const_cast<CTPSDecl *>(cast<CTPSDecl>(Val: this));
1006 CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember();
1007 assert(inst_from != nullptr);
1008 return inst_from->getSourceRange();
1009 }
1010 else {
1011 // No explicit info available.
1012 llvm::PointerUnion<ClassTemplateDecl *,
1013 ClassTemplatePartialSpecializationDecl *>
1014 inst_from = getInstantiatedFrom();
1015 if (inst_from.isNull())
1016 return getSpecializedTemplate()->getSourceRange();
1017 if (const auto *ctd = inst_from.dyn_cast<ClassTemplateDecl *>())
1018 return ctd->getSourceRange();
1019 return inst_from.get<ClassTemplatePartialSpecializationDecl *>()
1020 ->getSourceRange();
1021 }
1022}
1023
1024//===----------------------------------------------------------------------===//
1025// ConceptDecl Implementation
1026//===----------------------------------------------------------------------===//
1027ConceptDecl *ConceptDecl::Create(ASTContext &C, DeclContext *DC,
1028 SourceLocation L, DeclarationName Name,
1029 TemplateParameterList *Params,
1030 Expr *ConstraintExpr) {
1031 bool Invalid = AdoptTemplateParameterList(Params, Owner: DC);
1032 auto *TD = new (C, DC) ConceptDecl(DC, L, Name, Params, ConstraintExpr);
1033 if (Invalid)
1034 TD->setInvalidDecl();
1035 return TD;
1036}
1037
1038ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C,
1039 Decl::DeclID ID) {
1040 ConceptDecl *Result = new (C, ID) ConceptDecl(nullptr, SourceLocation(),
1041 DeclarationName(),
1042 nullptr, nullptr);
1043
1044 return Result;
1045}
1046
1047//===----------------------------------------------------------------------===//
1048// ImplicitConceptSpecializationDecl Implementation
1049//===----------------------------------------------------------------------===//
1050ImplicitConceptSpecializationDecl::ImplicitConceptSpecializationDecl(
1051 DeclContext *DC, SourceLocation SL,
1052 ArrayRef<TemplateArgument> ConvertedArgs)
1053 : Decl(ImplicitConceptSpecialization, DC, SL),
1054 NumTemplateArgs(ConvertedArgs.size()) {
1055 setTemplateArguments(ConvertedArgs);
1056}
1057
1058ImplicitConceptSpecializationDecl::ImplicitConceptSpecializationDecl(
1059 EmptyShell Empty, unsigned NumTemplateArgs)
1060 : Decl(ImplicitConceptSpecialization, Empty),
1061 NumTemplateArgs(NumTemplateArgs) {}
1062
1063ImplicitConceptSpecializationDecl *ImplicitConceptSpecializationDecl::Create(
1064 const ASTContext &C, DeclContext *DC, SourceLocation SL,
1065 ArrayRef<TemplateArgument> ConvertedArgs) {
1066 return new (C, DC,
1067 additionalSizeToAlloc<TemplateArgument>(Counts: ConvertedArgs.size()))
1068 ImplicitConceptSpecializationDecl(DC, SL, ConvertedArgs);
1069}
1070
1071ImplicitConceptSpecializationDecl *
1072ImplicitConceptSpecializationDecl::CreateDeserialized(
1073 const ASTContext &C, Decl::DeclID ID, unsigned NumTemplateArgs) {
1074 return new (C, ID, additionalSizeToAlloc<TemplateArgument>(Counts: NumTemplateArgs))
1075 ImplicitConceptSpecializationDecl(EmptyShell{}, NumTemplateArgs);
1076}
1077
1078void ImplicitConceptSpecializationDecl::setTemplateArguments(
1079 ArrayRef<TemplateArgument> Converted) {
1080 assert(Converted.size() == NumTemplateArgs);
1081 std::uninitialized_copy(Converted.begin(), Converted.end(),
1082 getTrailingObjects<TemplateArgument>());
1083}
1084
1085//===----------------------------------------------------------------------===//
1086// ClassTemplatePartialSpecializationDecl Implementation
1087//===----------------------------------------------------------------------===//
1088void ClassTemplatePartialSpecializationDecl::anchor() {}
1089
1090ClassTemplatePartialSpecializationDecl::
1091ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
1092 DeclContext *DC,
1093 SourceLocation StartLoc,
1094 SourceLocation IdLoc,
1095 TemplateParameterList *Params,
1096 ClassTemplateDecl *SpecializedTemplate,
1097 ArrayRef<TemplateArgument> Args,
1098 const ASTTemplateArgumentListInfo *ArgInfos,
1099 ClassTemplatePartialSpecializationDecl *PrevDecl)
1100 : ClassTemplateSpecializationDecl(Context,
1101 ClassTemplatePartialSpecialization,
1102 TK, DC, StartLoc, IdLoc,
1103 SpecializedTemplate, Args, PrevDecl),
1104 TemplateParams(Params), ArgsAsWritten(ArgInfos),
1105 InstantiatedFromMember(nullptr, false) {
1106 if (AdoptTemplateParameterList(Params, this))
1107 setInvalidDecl();
1108}
1109
1110ClassTemplatePartialSpecializationDecl *
1111ClassTemplatePartialSpecializationDecl::
1112Create(ASTContext &Context, TagKind TK,DeclContext *DC,
1113 SourceLocation StartLoc, SourceLocation IdLoc,
1114 TemplateParameterList *Params,
1115 ClassTemplateDecl *SpecializedTemplate,
1116 ArrayRef<TemplateArgument> Args,
1117 const TemplateArgumentListInfo &ArgInfos,
1118 QualType CanonInjectedType,
1119 ClassTemplatePartialSpecializationDecl *PrevDecl) {
1120 const ASTTemplateArgumentListInfo *ASTArgInfos =
1121 ASTTemplateArgumentListInfo::Create(C: Context, List: ArgInfos);
1122
1123 auto *Result = new (Context, DC)
1124 ClassTemplatePartialSpecializationDecl(Context, TK, DC, StartLoc, IdLoc,
1125 Params, SpecializedTemplate, Args,
1126 ASTArgInfos, PrevDecl);
1127 Result->setSpecializationKind(TSK_ExplicitSpecialization);
1128 Result->setMayHaveOutOfDateDef(false);
1129
1130 Context.getInjectedClassNameType(Result, CanonInjectedType);
1131 return Result;
1132}
1133
1134ClassTemplatePartialSpecializationDecl *
1135ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
1136 Decl::DeclID ID) {
1137 auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C);
1138 Result->setMayHaveOutOfDateDef(false);
1139 return Result;
1140}
1141
1142//===----------------------------------------------------------------------===//
1143// FriendTemplateDecl Implementation
1144//===----------------------------------------------------------------------===//
1145
1146void FriendTemplateDecl::anchor() {}
1147
1148FriendTemplateDecl *
1149FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC,
1150 SourceLocation L,
1151 MutableArrayRef<TemplateParameterList *> Params,
1152 FriendUnion Friend, SourceLocation FLoc) {
1153 TemplateParameterList **TPL = nullptr;
1154 if (!Params.empty()) {
1155 TPL = new (Context) TemplateParameterList *[Params.size()];
1156 llvm::copy(Range&: Params, Out: TPL);
1157 }
1158 return new (Context, DC)
1159 FriendTemplateDecl(DC, L, TPL, Params.size(), Friend, FLoc);
1160}
1161
1162FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C,
1163 Decl::DeclID ID) {
1164 return new (C, ID) FriendTemplateDecl(EmptyShell());
1165}
1166
1167//===----------------------------------------------------------------------===//
1168// TypeAliasTemplateDecl Implementation
1169//===----------------------------------------------------------------------===//
1170
1171TypeAliasTemplateDecl *
1172TypeAliasTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
1173 DeclarationName Name,
1174 TemplateParameterList *Params, NamedDecl *Decl) {
1175 bool Invalid = AdoptTemplateParameterList(Params, Owner: DC);
1176 auto *TD = new (C, DC) TypeAliasTemplateDecl(C, DC, L, Name, Params, Decl);
1177 if (Invalid)
1178 TD->setInvalidDecl();
1179 return TD;
1180}
1181
1182TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C,
1183 Decl::DeclID ID) {
1184 return new (C, ID) TypeAliasTemplateDecl(C, nullptr, SourceLocation(),
1185 DeclarationName(), nullptr, nullptr);
1186}
1187
1188RedeclarableTemplateDecl::CommonBase *
1189TypeAliasTemplateDecl::newCommon(ASTContext &C) const {
1190 auto *CommonPtr = new (C) Common;
1191 C.addDestruction(Ptr: CommonPtr);
1192 return CommonPtr;
1193}
1194
1195//===----------------------------------------------------------------------===//
1196// VarTemplateDecl Implementation
1197//===----------------------------------------------------------------------===//
1198
1199VarTemplateDecl *VarTemplateDecl::getDefinition() {
1200 VarTemplateDecl *CurD = this;
1201 while (CurD) {
1202 if (CurD->isThisDeclarationADefinition())
1203 return CurD;
1204 CurD = CurD->getPreviousDecl();
1205 }
1206 return nullptr;
1207}
1208
1209VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC,
1210 SourceLocation L, DeclarationName Name,
1211 TemplateParameterList *Params,
1212 VarDecl *Decl) {
1213 bool Invalid = AdoptTemplateParameterList(Params, Owner: DC);
1214 auto *TD = new (C, DC) VarTemplateDecl(C, DC, L, Name, Params, Decl);
1215 if (Invalid)
1216 TD->setInvalidDecl();
1217 return TD;
1218}
1219
1220VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
1221 Decl::DeclID ID) {
1222 return new (C, ID) VarTemplateDecl(C, nullptr, SourceLocation(),
1223 DeclarationName(), nullptr, nullptr);
1224}
1225
1226void VarTemplateDecl::LoadLazySpecializations() const {
1227 loadLazySpecializationsImpl();
1228}
1229
1230llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
1231VarTemplateDecl::getSpecializations() const {
1232 LoadLazySpecializations();
1233 return getCommonPtr()->Specializations;
1234}
1235
1236llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
1237VarTemplateDecl::getPartialSpecializations() const {
1238 LoadLazySpecializations();
1239 return getCommonPtr()->PartialSpecializations;
1240}
1241
1242RedeclarableTemplateDecl::CommonBase *
1243VarTemplateDecl::newCommon(ASTContext &C) const {
1244 auto *CommonPtr = new (C) Common;
1245 C.addDestruction(Ptr: CommonPtr);
1246 return CommonPtr;
1247}
1248
1249VarTemplateSpecializationDecl *
1250VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
1251 void *&InsertPos) {
1252 return findSpecializationImpl(getSpecializations(), InsertPos, Args);
1253}
1254
1255void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D,
1256 void *InsertPos) {
1257 addSpecializationImpl<VarTemplateDecl>(getSpecializations(), D, InsertPos);
1258}
1259
1260VarTemplatePartialSpecializationDecl *
1261VarTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args,
1262 TemplateParameterList *TPL, void *&InsertPos) {
1263 return findSpecializationImpl(getPartialSpecializations(), InsertPos, Args,
1264 TPL);
1265}
1266
1267void VarTemplatePartialSpecializationDecl::Profile(
1268 llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
1269 TemplateParameterList *TPL, const ASTContext &Context) {
1270 ID.AddInteger(I: TemplateArgs.size());
1271 for (const TemplateArgument &TemplateArg : TemplateArgs)
1272 TemplateArg.Profile(ID, Context);
1273 TPL->Profile(ID, C: Context);
1274}
1275
1276void VarTemplateDecl::AddPartialSpecialization(
1277 VarTemplatePartialSpecializationDecl *D, void *InsertPos) {
1278 if (InsertPos)
1279 getPartialSpecializations().InsertNode(N: D, InsertPos);
1280 else {
1281 VarTemplatePartialSpecializationDecl *Existing =
1282 getPartialSpecializations().GetOrInsertNode(N: D);
1283 (void)Existing;
1284 assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
1285 }
1286
1287 if (ASTMutationListener *L = getASTMutationListener())
1288 L->AddedCXXTemplateSpecialization(this, D);
1289}
1290
1291void VarTemplateDecl::getPartialSpecializations(
1292 SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS) const {
1293 llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &PartialSpecs =
1294 getPartialSpecializations();
1295 PS.clear();
1296 PS.reserve(N: PartialSpecs.size());
1297 for (VarTemplatePartialSpecializationDecl &P : PartialSpecs)
1298 PS.push_back(Elt: P.getMostRecentDecl());
1299}
1300
1301VarTemplatePartialSpecializationDecl *
1302VarTemplateDecl::findPartialSpecInstantiatedFromMember(
1303 VarTemplatePartialSpecializationDecl *D) {
1304 Decl *DCanon = D->getCanonicalDecl();
1305 for (VarTemplatePartialSpecializationDecl &P : getPartialSpecializations()) {
1306 if (P.getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
1307 return P.getMostRecentDecl();
1308 }
1309
1310 return nullptr;
1311}
1312
1313//===----------------------------------------------------------------------===//
1314// VarTemplateSpecializationDecl Implementation
1315//===----------------------------------------------------------------------===//
1316
1317VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(
1318 Kind DK, ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1319 SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
1320 TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args)
1321 : VarDecl(DK, Context, DC, StartLoc, IdLoc,
1322 SpecializedTemplate->getIdentifier(), T, TInfo, S),
1323 SpecializedTemplate(SpecializedTemplate),
1324 TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
1325 SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {}
1326
1327VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK,
1328 ASTContext &C)
1329 : VarDecl(DK, C, nullptr, SourceLocation(), SourceLocation(), nullptr,
1330 QualType(), nullptr, SC_None),
1331 SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {}
1332
1333VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create(
1334 ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1335 SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
1336 TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args) {
1337 return new (Context, DC) VarTemplateSpecializationDecl(
1338 VarTemplateSpecialization, Context, DC, StartLoc, IdLoc,
1339 SpecializedTemplate, T, TInfo, S, Args);
1340}
1341
1342VarTemplateSpecializationDecl *
1343VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {
1344 return new (C, ID)
1345 VarTemplateSpecializationDecl(VarTemplateSpecialization, C);
1346}
1347
1348void VarTemplateSpecializationDecl::getNameForDiagnostic(
1349 raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
1350 NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
1351
1352 const auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(Val: this);
1353 if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
1354 PS ? PS->getTemplateArgsAsWritten() : nullptr) {
1355 printTemplateArgumentList(
1356 OS, ArgsAsWritten->arguments(), Policy,
1357 getSpecializedTemplate()->getTemplateParameters());
1358 } else {
1359 const TemplateArgumentList &TemplateArgs = getTemplateArgs();
1360 printTemplateArgumentList(
1361 OS, TemplateArgs.asArray(), Policy,
1362 getSpecializedTemplate()->getTemplateParameters());
1363 }
1364}
1365
1366VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
1367 if (const auto *PartialSpec =
1368 SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
1369 return PartialSpec->PartialSpecialization->getSpecializedTemplate();
1370 return SpecializedTemplate.get<VarTemplateDecl *>();
1371}
1372
1373void VarTemplateSpecializationDecl::setTemplateArgsInfo(
1374 const TemplateArgumentListInfo &ArgsInfo) {
1375 TemplateArgsInfo =
1376 ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo);
1377}
1378
1379void VarTemplateSpecializationDecl::setTemplateArgsInfo(
1380 const ASTTemplateArgumentListInfo *ArgsInfo) {
1381 TemplateArgsInfo =
1382 ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo);
1383}
1384
1385SourceRange VarTemplateSpecializationDecl::getSourceRange() const {
1386 if (isExplicitSpecialization() && !hasInit()) {
1387 if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsInfo())
1388 return SourceRange(getOuterLocStart(), Info->getRAngleLoc());
1389 }
1390 return VarDecl::getSourceRange();
1391}
1392
1393
1394//===----------------------------------------------------------------------===//
1395// VarTemplatePartialSpecializationDecl Implementation
1396//===----------------------------------------------------------------------===//
1397
1398void VarTemplatePartialSpecializationDecl::anchor() {}
1399
1400VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl(
1401 ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1402 SourceLocation IdLoc, TemplateParameterList *Params,
1403 VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
1404 StorageClass S, ArrayRef<TemplateArgument> Args,
1405 const ASTTemplateArgumentListInfo *ArgInfos)
1406 : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context,
1407 DC, StartLoc, IdLoc, SpecializedTemplate, T,
1408 TInfo, S, Args),
1409 TemplateParams(Params), ArgsAsWritten(ArgInfos),
1410 InstantiatedFromMember(nullptr, false) {
1411 if (AdoptTemplateParameterList(Params, Owner: DC))
1412 setInvalidDecl();
1413}
1414
1415VarTemplatePartialSpecializationDecl *
1416VarTemplatePartialSpecializationDecl::Create(
1417 ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
1418 SourceLocation IdLoc, TemplateParameterList *Params,
1419 VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
1420 StorageClass S, ArrayRef<TemplateArgument> Args,
1421 const TemplateArgumentListInfo &ArgInfos) {
1422 const ASTTemplateArgumentListInfo *ASTArgInfos
1423 = ASTTemplateArgumentListInfo::Create(C: Context, List: ArgInfos);
1424
1425 auto *Result =
1426 new (Context, DC) VarTemplatePartialSpecializationDecl(
1427 Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo,
1428 S, Args, ASTArgInfos);
1429 Result->setSpecializationKind(TSK_ExplicitSpecialization);
1430 return Result;
1431}
1432
1433VarTemplatePartialSpecializationDecl *
1434VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
1435 Decl::DeclID ID) {
1436 return new (C, ID) VarTemplatePartialSpecializationDecl(C);
1437}
1438
1439SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const {
1440 if (isExplicitSpecialization() && !hasInit()) {
1441 if (const ASTTemplateArgumentListInfo *Info = getTemplateArgsAsWritten())
1442 return SourceRange(getOuterLocStart(), Info->getRAngleLoc());
1443 }
1444 return VarDecl::getSourceRange();
1445}
1446
1447static TemplateParameterList *
1448createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
1449 // typename T
1450 auto *T = TemplateTypeParmDecl::Create(
1451 C, DC, KeyLoc: SourceLocation(), NameLoc: SourceLocation(), /*Depth=*/D: 1, /*Position=*/P: 0,
1452 /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false,
1453 /*HasTypeConstraint=*/false);
1454 T->setImplicit(true);
1455
1456 // T ...Ints
1457 TypeSourceInfo *TI =
1458 C.getTrivialTypeSourceInfo(T: QualType(T->getTypeForDecl(), 0));
1459 auto *N = NonTypeTemplateParmDecl::Create(
1460 C, DC, StartLoc: SourceLocation(), IdLoc: SourceLocation(), /*Depth=*/D: 0, /*Position=*/P: 1,
1461 /*Id=*/nullptr, T: TI->getType(), /*ParameterPack=*/true, TInfo: TI);
1462 N->setImplicit(true);
1463
1464 // <typename T, T ...Ints>
1465 NamedDecl *P[2] = {T, N};
1466 auto *TPL = TemplateParameterList::Create(
1467 C, TemplateLoc: SourceLocation(), LAngleLoc: SourceLocation(), Params: P, RAngleLoc: SourceLocation(), RequiresClause: nullptr);
1468
1469 // template <typename T, ...Ints> class IntSeq
1470 auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create(
1471 C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/0,
1472 /*ParameterPack=*/false, /*Id=*/nullptr, /*Typename=*/false, TPL);
1473 TemplateTemplateParm->setImplicit(true);
1474
1475 // typename T
1476 auto *TemplateTypeParm = TemplateTypeParmDecl::Create(
1477 C, DC, KeyLoc: SourceLocation(), NameLoc: SourceLocation(), /*Depth=*/D: 0, /*Position=*/P: 1,
1478 /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false,
1479 /*HasTypeConstraint=*/false);
1480 TemplateTypeParm->setImplicit(true);
1481
1482 // T N
1483 TypeSourceInfo *TInfo = C.getTrivialTypeSourceInfo(
1484 T: QualType(TemplateTypeParm->getTypeForDecl(), 0));
1485 auto *NonTypeTemplateParm = NonTypeTemplateParmDecl::Create(
1486 C, DC, StartLoc: SourceLocation(), IdLoc: SourceLocation(), /*Depth=*/D: 0, /*Position=*/P: 2,
1487 /*Id=*/nullptr, T: TInfo->getType(), /*ParameterPack=*/false, TInfo);
1488 NamedDecl *Params[] = {TemplateTemplateParm, TemplateTypeParm,
1489 NonTypeTemplateParm};
1490
1491 // template <template <typename T, T ...Ints> class IntSeq, typename T, T N>
1492 return TemplateParameterList::Create(C, TemplateLoc: SourceLocation(), LAngleLoc: SourceLocation(),
1493 Params, RAngleLoc: SourceLocation(), RequiresClause: nullptr);
1494}
1495
1496static TemplateParameterList *
1497createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) {
1498 // std::size_t Index
1499 TypeSourceInfo *TInfo = C.getTrivialTypeSourceInfo(T: C.getSizeType());
1500 auto *Index = NonTypeTemplateParmDecl::Create(
1501 C, DC, StartLoc: SourceLocation(), IdLoc: SourceLocation(), /*Depth=*/D: 0, /*Position=*/P: 0,
1502 /*Id=*/nullptr, T: TInfo->getType(), /*ParameterPack=*/false, TInfo);
1503
1504 // typename ...T
1505 auto *Ts = TemplateTypeParmDecl::Create(
1506 C, DC, KeyLoc: SourceLocation(), NameLoc: SourceLocation(), /*Depth=*/D: 0, /*Position=*/P: 1,
1507 /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/true,
1508 /*HasTypeConstraint=*/false);
1509 Ts->setImplicit(true);
1510
1511 // template <std::size_t Index, typename ...T>
1512 NamedDecl *Params[] = {Index, Ts};
1513 return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
1514 llvm::ArrayRef(Params), SourceLocation(),
1515 nullptr);
1516}
1517
1518static TemplateParameterList *createBuiltinTemplateParameterList(
1519 const ASTContext &C, DeclContext *DC, BuiltinTemplateKind BTK) {
1520 switch (BTK) {
1521 case BTK__make_integer_seq:
1522 return createMakeIntegerSeqParameterList(C, DC);
1523 case BTK__type_pack_element:
1524 return createTypePackElementParameterList(C, DC);
1525 }
1526
1527 llvm_unreachable("unhandled BuiltinTemplateKind!");
1528}
1529
1530void BuiltinTemplateDecl::anchor() {}
1531
1532BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
1533 DeclarationName Name,
1534 BuiltinTemplateKind BTK)
1535 : TemplateDecl(BuiltinTemplate, DC, SourceLocation(), Name,
1536 createBuiltinTemplateParameterList(C, DC, BTK)),
1537 BTK(BTK) {}
1538
1539TemplateParamObjectDecl *TemplateParamObjectDecl::Create(const ASTContext &C,
1540 QualType T,
1541 const APValue &V) {
1542 DeclContext *DC = C.getTranslationUnitDecl();
1543 auto *TPOD = new (C, DC) TemplateParamObjectDecl(DC, T, V);
1544 C.addDestruction(&TPOD->Value);
1545 return TPOD;
1546}
1547
1548TemplateParamObjectDecl *
1549TemplateParamObjectDecl::CreateDeserialized(ASTContext &C, Decl::DeclID ID) {
1550 auto *TPOD = new (C, ID) TemplateParamObjectDecl(nullptr, QualType(), APValue());
1551 C.addDestruction(Ptr: &TPOD->Value);
1552 return TPOD;
1553}
1554
1555void TemplateParamObjectDecl::printName(llvm::raw_ostream &OS,
1556 const PrintingPolicy &Policy) const {
1557 OS << "<template param ";
1558 printAsExpr(OS, Policy);
1559 OS << ">";
1560}
1561
1562void TemplateParamObjectDecl::printAsExpr(llvm::raw_ostream &OS) const {
1563 printAsExpr(OS, getASTContext().getPrintingPolicy());
1564}
1565
1566void TemplateParamObjectDecl::printAsExpr(llvm::raw_ostream &OS,
1567 const PrintingPolicy &Policy) const {
1568 getType().getUnqualifiedType().print(OS, Policy);
1569 printAsInit(OS, Policy);
1570}
1571
1572void TemplateParamObjectDecl::printAsInit(llvm::raw_ostream &OS) const {
1573 printAsInit(OS, getASTContext().getPrintingPolicy());
1574}
1575
1576void TemplateParamObjectDecl::printAsInit(llvm::raw_ostream &OS,
1577 const PrintingPolicy &Policy) const {
1578 getValue().printPretty(OS, Policy, getType(), &getASTContext());
1579}
1580
1581TemplateParameterList *clang::getReplacedTemplateParameterList(Decl *D) {
1582 switch (D->getKind()) {
1583 case Decl::Kind::CXXRecord:
1584 return cast<CXXRecordDecl>(Val: D)
1585 ->getDescribedTemplate()
1586 ->getTemplateParameters();
1587 case Decl::Kind::ClassTemplate:
1588 return cast<ClassTemplateDecl>(Val: D)->getTemplateParameters();
1589 case Decl::Kind::ClassTemplateSpecialization: {
1590 const auto *CTSD = cast<ClassTemplateSpecializationDecl>(Val: D);
1591 auto P = CTSD->getSpecializedTemplateOrPartial();
1592 if (const auto *CTPSD =
1593 P.dyn_cast<ClassTemplatePartialSpecializationDecl *>())
1594 return CTPSD->getTemplateParameters();
1595 return cast<ClassTemplateDecl *>(Val&: P)->getTemplateParameters();
1596 }
1597 case Decl::Kind::ClassTemplatePartialSpecialization:
1598 return cast<ClassTemplatePartialSpecializationDecl>(Val: D)
1599 ->getTemplateParameters();
1600 case Decl::Kind::TypeAliasTemplate:
1601 return cast<TypeAliasTemplateDecl>(Val: D)->getTemplateParameters();
1602 case Decl::Kind::BuiltinTemplate:
1603 return cast<BuiltinTemplateDecl>(Val: D)->getTemplateParameters();
1604 case Decl::Kind::CXXDeductionGuide:
1605 case Decl::Kind::CXXConversion:
1606 case Decl::Kind::CXXConstructor:
1607 case Decl::Kind::CXXDestructor:
1608 case Decl::Kind::CXXMethod:
1609 case Decl::Kind::Function:
1610 return cast<FunctionDecl>(Val: D)
1611 ->getTemplateSpecializationInfo()
1612 ->getTemplate()
1613 ->getTemplateParameters();
1614 case Decl::Kind::FunctionTemplate:
1615 return cast<FunctionTemplateDecl>(Val: D)->getTemplateParameters();
1616 case Decl::Kind::VarTemplate:
1617 return cast<VarTemplateDecl>(Val: D)->getTemplateParameters();
1618 case Decl::Kind::VarTemplateSpecialization: {
1619 const auto *VTSD = cast<VarTemplateSpecializationDecl>(Val: D);
1620 auto P = VTSD->getSpecializedTemplateOrPartial();
1621 if (const auto *VTPSD =
1622 P.dyn_cast<VarTemplatePartialSpecializationDecl *>())
1623 return VTPSD->getTemplateParameters();
1624 return cast<VarTemplateDecl *>(Val&: P)->getTemplateParameters();
1625 }
1626 case Decl::Kind::VarTemplatePartialSpecialization:
1627 return cast<VarTemplatePartialSpecializationDecl>(Val: D)
1628 ->getTemplateParameters();
1629 case Decl::Kind::TemplateTemplateParm:
1630 return cast<TemplateTemplateParmDecl>(Val: D)->getTemplateParameters();
1631 case Decl::Kind::Concept:
1632 return cast<ConceptDecl>(Val: D)->getTemplateParameters();
1633 default:
1634 llvm_unreachable("Unhandled templated declaration kind");
1635 }
1636}
1637

source code of clang/lib/AST/DeclTemplate.cpp