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