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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

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