1286 lines
		
	
	
		
			52 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			1286 lines
		
	
	
		
			52 KiB
		
	
	
	
		
			C++
		
	
	
	
//===- DeclTemplate.cpp - Template Declaration AST Node Implementation ----===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This file implements the C++ related Decl classes for templates.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "clang/AST/DeclTemplate.h"
 | 
						|
#include "clang/AST/ASTContext.h"
 | 
						|
#include "clang/AST/ASTMutationListener.h"
 | 
						|
#include "clang/AST/DeclCXX.h"
 | 
						|
#include "clang/AST/DeclarationName.h"
 | 
						|
#include "clang/AST/Expr.h"
 | 
						|
#include "clang/AST/ExternalASTSource.h"
 | 
						|
#include "clang/AST/TemplateBase.h"
 | 
						|
#include "clang/AST/TemplateName.h"
 | 
						|
#include "clang/AST/Type.h"
 | 
						|
#include "clang/AST/TypeLoc.h"
 | 
						|
#include "clang/Basic/Builtins.h"
 | 
						|
#include "clang/Basic/LLVM.h"
 | 
						|
#include "clang/Basic/SourceLocation.h"
 | 
						|
#include "llvm/ADT/ArrayRef.h"
 | 
						|
#include "llvm/ADT/FoldingSet.h"
 | 
						|
#include "llvm/ADT/None.h"
 | 
						|
#include "llvm/ADT/PointerUnion.h"
 | 
						|
#include "llvm/ADT/SmallVector.h"
 | 
						|
#include "llvm/Support/Casting.h"
 | 
						|
#include "llvm/Support/ErrorHandling.h"
 | 
						|
#include <algorithm>
 | 
						|
#include <cassert>
 | 
						|
#include <cstdint>
 | 
						|
#include <memory>
 | 
						|
#include <utility>
 | 
						|
 | 
						|
using namespace clang;
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// TemplateParameterList Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
 | 
						|
                                             SourceLocation LAngleLoc,
 | 
						|
                                             ArrayRef<NamedDecl *> Params,
 | 
						|
                                             SourceLocation RAngleLoc,
 | 
						|
                                             Expr *RequiresClause)
 | 
						|
    : TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
 | 
						|
      NumParams(Params.size()), ContainsUnexpandedParameterPack(false),
 | 
						|
      HasRequiresClause(static_cast<bool>(RequiresClause)) {
 | 
						|
  for (unsigned Idx = 0; Idx < NumParams; ++Idx) {
 | 
						|
    NamedDecl *P = Params[Idx];
 | 
						|
    begin()[Idx] = P;
 | 
						|
 | 
						|
    if (!P->isTemplateParameterPack()) {
 | 
						|
      if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
 | 
						|
        if (NTTP->getType()->containsUnexpandedParameterPack())
 | 
						|
          ContainsUnexpandedParameterPack = true;
 | 
						|
 | 
						|
      if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
 | 
						|
        if (TTP->getTemplateParameters()->containsUnexpandedParameterPack())
 | 
						|
          ContainsUnexpandedParameterPack = true;
 | 
						|
 | 
						|
      // FIXME: If a default argument contains an unexpanded parameter pack, the
 | 
						|
      // template parameter list does too.
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (RequiresClause) {
 | 
						|
    *getTrailingObjects<Expr *>() = RequiresClause;
 | 
						|
    if (RequiresClause->containsUnexpandedParameterPack())
 | 
						|
      ContainsUnexpandedParameterPack = true;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
TemplateParameterList *
 | 
						|
TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc,
 | 
						|
                              SourceLocation LAngleLoc,
 | 
						|
                              ArrayRef<NamedDecl *> Params,
 | 
						|
                              SourceLocation RAngleLoc, Expr *RequiresClause) {
 | 
						|
  void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *, Expr *>(
 | 
						|
                             Params.size(), RequiresClause ? 1u : 0u),
 | 
						|
                         alignof(TemplateParameterList));
 | 
						|
  return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params,
 | 
						|
                                         RAngleLoc, RequiresClause);
 | 
						|
}
 | 
						|
 | 
						|
unsigned TemplateParameterList::getMinRequiredArguments() const {
 | 
						|
  unsigned NumRequiredArgs = 0;
 | 
						|
  for (const NamedDecl *P : asArray()) {
 | 
						|
    if (P->isTemplateParameterPack()) {
 | 
						|
      if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
 | 
						|
        if (NTTP->isExpandedParameterPack()) {
 | 
						|
          NumRequiredArgs += NTTP->getNumExpansionTypes();
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
 | 
						|
      if (TTP->hasDefaultArgument())
 | 
						|
        break;
 | 
						|
    } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
 | 
						|
      if (NTTP->hasDefaultArgument())
 | 
						|
        break;
 | 
						|
    } else if (cast<TemplateTemplateParmDecl>(P)->hasDefaultArgument())
 | 
						|
      break;
 | 
						|
 | 
						|
    ++NumRequiredArgs;
 | 
						|
  }
 | 
						|
 | 
						|
  return NumRequiredArgs;
 | 
						|
}
 | 
						|
 | 
						|
unsigned TemplateParameterList::getDepth() const {
 | 
						|
  if (size() == 0)
 | 
						|
    return 0;
 | 
						|
 | 
						|
  const NamedDecl *FirstParm = getParam(0);
 | 
						|
  if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(FirstParm))
 | 
						|
    return TTP->getDepth();
 | 
						|
  else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(FirstParm))
 | 
						|
    return NTTP->getDepth();
 | 
						|
  else
 | 
						|
    return cast<TemplateTemplateParmDecl>(FirstParm)->getDepth();
 | 
						|
}
 | 
						|
 | 
						|
static void AdoptTemplateParameterList(TemplateParameterList *Params,
 | 
						|
                                       DeclContext *Owner) {
 | 
						|
  for (NamedDecl *P : *Params) {
 | 
						|
    P->setDeclContext(Owner);
 | 
						|
 | 
						|
    if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
 | 
						|
      AdoptTemplateParameterList(TTP->getTemplateParameters(), Owner);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TemplateParameterList::
 | 
						|
getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
 | 
						|
  // TODO: Concepts: Collect immediately-introduced constraints.
 | 
						|
  if (HasRequiresClause)
 | 
						|
    AC.push_back(getRequiresClause());
 | 
						|
}
 | 
						|
 | 
						|
bool TemplateParameterList::hasAssociatedConstraints() const {
 | 
						|
  // TODO: Concepts: Regard immediately-introduced constraints.
 | 
						|
  return HasRequiresClause;
 | 
						|
}
 | 
						|
 | 
						|
namespace clang {
 | 
						|
 | 
						|
void *allocateDefaultArgStorageChain(const ASTContext &C) {
 | 
						|
  return new (C) char[sizeof(void*) * 2];
 | 
						|
}
 | 
						|
 | 
						|
} // namespace clang
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// TemplateDecl Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
TemplateDecl::TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
 | 
						|
                           DeclarationName Name, TemplateParameterList *Params,
 | 
						|
                           NamedDecl *Decl)
 | 
						|
    : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), TemplateParams(Params) {}
 | 
						|
 | 
						|
void TemplateDecl::anchor() {}
 | 
						|
 | 
						|
void TemplateDecl::
 | 
						|
getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
 | 
						|
  // TODO: Concepts: Append function trailing requires clause.
 | 
						|
  TemplateParams->getAssociatedConstraints(AC);
 | 
						|
}
 | 
						|
 | 
						|
bool TemplateDecl::hasAssociatedConstraints() const {
 | 
						|
  // TODO: Concepts: Regard function trailing requires clause.
 | 
						|
  return TemplateParams->hasAssociatedConstraints();
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// RedeclarableTemplateDecl Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
void RedeclarableTemplateDecl::anchor() {}
 | 
						|
 | 
						|
RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() const {
 | 
						|
  if (Common)
 | 
						|
    return Common;
 | 
						|
 | 
						|
  // Walk the previous-declaration chain until we either find a declaration
 | 
						|
  // with a common pointer or we run out of previous declarations.
 | 
						|
  SmallVector<const RedeclarableTemplateDecl *, 2> PrevDecls;
 | 
						|
  for (const RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev;
 | 
						|
       Prev = Prev->getPreviousDecl()) {
 | 
						|
    if (Prev->Common) {
 | 
						|
      Common = Prev->Common;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    PrevDecls.push_back(Prev);
 | 
						|
  }
 | 
						|
 | 
						|
  // If we never found a common pointer, allocate one now.
 | 
						|
  if (!Common) {
 | 
						|
    // FIXME: If any of the declarations is from an AST file, we probably
 | 
						|
    // need an update record to add the common data.
 | 
						|
 | 
						|
    Common = newCommon(getASTContext());
 | 
						|
  }
 | 
						|
 | 
						|
  // Update any previous declarations we saw with the common pointer.
 | 
						|
  for (const RedeclarableTemplateDecl *Prev : PrevDecls)
 | 
						|
    Prev->Common = Common;
 | 
						|
 | 
						|
  return Common;
 | 
						|
}
 | 
						|
 | 
						|
void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
 | 
						|
  // Grab the most recent declaration to ensure we've loaded any lazy
 | 
						|
  // redeclarations of this template.
 | 
						|
  CommonBase *CommonBasePtr = getMostRecentDecl()->getCommonPtr();
 | 
						|
  if (CommonBasePtr->LazySpecializations) {
 | 
						|
    ASTContext &Context = getASTContext();
 | 
						|
    uint32_t *Specs = CommonBasePtr->LazySpecializations;
 | 
						|
    CommonBasePtr->LazySpecializations = nullptr;
 | 
						|
    for (uint32_t I = 0, N = *Specs++; I != N; ++I)
 | 
						|
      (void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
template<class EntryType>
 | 
						|
typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
 | 
						|
RedeclarableTemplateDecl::findSpecializationImpl(
 | 
						|
    llvm::FoldingSetVector<EntryType> &Specs, ArrayRef<TemplateArgument> Args,
 | 
						|
    void *&InsertPos) {
 | 
						|
  using SETraits = SpecEntryTraits<EntryType>;
 | 
						|
 | 
						|
  llvm::FoldingSetNodeID ID;
 | 
						|
  EntryType::Profile(ID, Args, getASTContext());
 | 
						|
  EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
 | 
						|
  return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr;
 | 
						|
}
 | 
						|
 | 
						|
template<class Derived, class EntryType>
 | 
						|
void RedeclarableTemplateDecl::addSpecializationImpl(
 | 
						|
    llvm::FoldingSetVector<EntryType> &Specializations, EntryType *Entry,
 | 
						|
    void *InsertPos) {
 | 
						|
  using SETraits = SpecEntryTraits<EntryType>;
 | 
						|
 | 
						|
  if (InsertPos) {
 | 
						|
#ifndef NDEBUG
 | 
						|
    void *CorrectInsertPos;
 | 
						|
    assert(!findSpecializationImpl(Specializations,
 | 
						|
                                   SETraits::getTemplateArgs(Entry),
 | 
						|
                                   CorrectInsertPos) &&
 | 
						|
           InsertPos == CorrectInsertPos &&
 | 
						|
           "given incorrect InsertPos for specialization");
 | 
						|
#endif
 | 
						|
    Specializations.InsertNode(Entry, InsertPos);
 | 
						|
  } else {
 | 
						|
    EntryType *Existing = Specializations.GetOrInsertNode(Entry);
 | 
						|
    (void)Existing;
 | 
						|
    assert(SETraits::getDecl(Existing)->isCanonicalDecl() &&
 | 
						|
           "non-canonical specialization?");
 | 
						|
  }
 | 
						|
 | 
						|
  if (ASTMutationListener *L = getASTMutationListener())
 | 
						|
    L->AddedCXXTemplateSpecialization(cast<Derived>(this),
 | 
						|
                                      SETraits::getDecl(Entry));
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// FunctionTemplateDecl Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
 | 
						|
                                                   DeclContext *DC,
 | 
						|
                                                   SourceLocation L,
 | 
						|
                                                   DeclarationName Name,
 | 
						|
                                               TemplateParameterList *Params,
 | 
						|
                                                   NamedDecl *Decl) {
 | 
						|
  AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
 | 
						|
  return new (C, DC) FunctionTemplateDecl(C, DC, L, Name, Params, Decl);
 | 
						|
}
 | 
						|
 | 
						|
FunctionTemplateDecl *FunctionTemplateDecl::CreateDeserialized(ASTContext &C,
 | 
						|
                                                               unsigned ID) {
 | 
						|
  return new (C, ID) FunctionTemplateDecl(C, nullptr, SourceLocation(),
 | 
						|
                                          DeclarationName(), nullptr, nullptr);
 | 
						|
}
 | 
						|
 | 
						|
RedeclarableTemplateDecl::CommonBase *
 | 
						|
FunctionTemplateDecl::newCommon(ASTContext &C) const {
 | 
						|
  auto *CommonPtr = new (C) Common;
 | 
						|
  C.addDestruction(CommonPtr);
 | 
						|
  return CommonPtr;
 | 
						|
}
 | 
						|
 | 
						|
void FunctionTemplateDecl::LoadLazySpecializations() const {
 | 
						|
  loadLazySpecializationsImpl();
 | 
						|
}
 | 
						|
 | 
						|
llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
 | 
						|
FunctionTemplateDecl::getSpecializations() const {
 | 
						|
  LoadLazySpecializations();
 | 
						|
  return getCommonPtr()->Specializations;
 | 
						|
}
 | 
						|
 | 
						|
FunctionDecl *
 | 
						|
FunctionTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
 | 
						|
                                         void *&InsertPos) {
 | 
						|
  return findSpecializationImpl(getSpecializations(), Args, InsertPos);
 | 
						|
}
 | 
						|
 | 
						|
void FunctionTemplateDecl::addSpecialization(
 | 
						|
      FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
 | 
						|
  addSpecializationImpl<FunctionTemplateDecl>(getSpecializations(), Info,
 | 
						|
                                              InsertPos);
 | 
						|
}
 | 
						|
 | 
						|
ArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() {
 | 
						|
  TemplateParameterList *Params = getTemplateParameters();
 | 
						|
  Common *CommonPtr = getCommonPtr();
 | 
						|
  if (!CommonPtr->InjectedArgs) {
 | 
						|
    auto &Context = getASTContext();
 | 
						|
    SmallVector<TemplateArgument, 16> TemplateArgs;
 | 
						|
    Context.getInjectedTemplateArgs(Params, TemplateArgs);
 | 
						|
    CommonPtr->InjectedArgs =
 | 
						|
        new (Context) TemplateArgument[TemplateArgs.size()];
 | 
						|
    std::copy(TemplateArgs.begin(), TemplateArgs.end(),
 | 
						|
              CommonPtr->InjectedArgs);
 | 
						|
  }
 | 
						|
 | 
						|
  return llvm::makeArrayRef(CommonPtr->InjectedArgs, Params->size());
 | 
						|
}
 | 
						|
 | 
						|
void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
 | 
						|
  using Base = RedeclarableTemplateDecl;
 | 
						|
 | 
						|
  // If we haven't created a common pointer yet, then it can just be created
 | 
						|
  // with the usual method.
 | 
						|
  if (!Base::Common)
 | 
						|
    return;
 | 
						|
 | 
						|
  Common *ThisCommon = static_cast<Common *>(Base::Common);
 | 
						|
  Common *PrevCommon = nullptr;
 | 
						|
  SmallVector<FunctionTemplateDecl *, 8> PreviousDecls;
 | 
						|
  for (; Prev; Prev = Prev->getPreviousDecl()) {
 | 
						|
    if (Prev->Base::Common) {
 | 
						|
      PrevCommon = static_cast<Common *>(Prev->Base::Common);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    PreviousDecls.push_back(Prev);
 | 
						|
  }
 | 
						|
 | 
						|
  // If the previous redecl chain hasn't created a common pointer yet, then just
 | 
						|
  // use this common pointer.
 | 
						|
  if (!PrevCommon) {
 | 
						|
    for (auto *D : PreviousDecls)
 | 
						|
      D->Base::Common = ThisCommon;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  // Ensure we don't leak any important state.
 | 
						|
  assert(ThisCommon->Specializations.size() == 0 &&
 | 
						|
         "Can't merge incompatible declarations!");
 | 
						|
 | 
						|
  Base::Common = PrevCommon;
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// ClassTemplateDecl Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
 | 
						|
                                             DeclContext *DC,
 | 
						|
                                             SourceLocation L,
 | 
						|
                                             DeclarationName Name,
 | 
						|
                                             TemplateParameterList *Params,
 | 
						|
                                             NamedDecl *Decl) {
 | 
						|
  AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
 | 
						|
 | 
						|
  return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
 | 
						|
}
 | 
						|
 | 
						|
ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
 | 
						|
                                                         unsigned ID) {
 | 
						|
  return new (C, ID) ClassTemplateDecl(C, nullptr, SourceLocation(),
 | 
						|
                                       DeclarationName(), nullptr, nullptr);
 | 
						|
}
 | 
						|
 | 
						|
void ClassTemplateDecl::LoadLazySpecializations() const {
 | 
						|
  loadLazySpecializationsImpl();
 | 
						|
}
 | 
						|
 | 
						|
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
 | 
						|
ClassTemplateDecl::getSpecializations() const {
 | 
						|
  LoadLazySpecializations();
 | 
						|
  return getCommonPtr()->Specializations;
 | 
						|
}
 | 
						|
 | 
						|
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
 | 
						|
ClassTemplateDecl::getPartialSpecializations() {
 | 
						|
  LoadLazySpecializations();
 | 
						|
  return getCommonPtr()->PartialSpecializations;
 | 
						|
}
 | 
						|
 | 
						|
RedeclarableTemplateDecl::CommonBase *
 | 
						|
ClassTemplateDecl::newCommon(ASTContext &C) const {
 | 
						|
  auto *CommonPtr = new (C) Common;
 | 
						|
  C.addDestruction(CommonPtr);
 | 
						|
  return CommonPtr;
 | 
						|
}
 | 
						|
 | 
						|
ClassTemplateSpecializationDecl *
 | 
						|
ClassTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
 | 
						|
                                      void *&InsertPos) {
 | 
						|
  return findSpecializationImpl(getSpecializations(), Args, InsertPos);
 | 
						|
}
 | 
						|
 | 
						|
void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D,
 | 
						|
                                          void *InsertPos) {
 | 
						|
  addSpecializationImpl<ClassTemplateDecl>(getSpecializations(), D, InsertPos);
 | 
						|
}
 | 
						|
 | 
						|
ClassTemplatePartialSpecializationDecl *
 | 
						|
ClassTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args,
 | 
						|
                                             void *&InsertPos) {
 | 
						|
  return findSpecializationImpl(getPartialSpecializations(), Args, InsertPos);
 | 
						|
}
 | 
						|
 | 
						|
void ClassTemplateDecl::AddPartialSpecialization(
 | 
						|
                                      ClassTemplatePartialSpecializationDecl *D,
 | 
						|
                                      void *InsertPos) {
 | 
						|
  if (InsertPos)
 | 
						|
    getPartialSpecializations().InsertNode(D, InsertPos);
 | 
						|
  else {
 | 
						|
    ClassTemplatePartialSpecializationDecl *Existing
 | 
						|
      = getPartialSpecializations().GetOrInsertNode(D);
 | 
						|
    (void)Existing;
 | 
						|
    assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
 | 
						|
  }
 | 
						|
 | 
						|
  if (ASTMutationListener *L = getASTMutationListener())
 | 
						|
    L->AddedCXXTemplateSpecialization(this, D);
 | 
						|
}
 | 
						|
 | 
						|
void ClassTemplateDecl::getPartialSpecializations(
 | 
						|
          SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) {
 | 
						|
  llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &PartialSpecs
 | 
						|
    = getPartialSpecializations();
 | 
						|
  PS.clear();
 | 
						|
  PS.reserve(PartialSpecs.size());
 | 
						|
  for (ClassTemplatePartialSpecializationDecl &P : PartialSpecs)
 | 
						|
    PS.push_back(P.getMostRecentDecl());
 | 
						|
}
 | 
						|
 | 
						|
ClassTemplatePartialSpecializationDecl *
 | 
						|
ClassTemplateDecl::findPartialSpecialization(QualType T) {
 | 
						|
  ASTContext &Context = getASTContext();
 | 
						|
  for (ClassTemplatePartialSpecializationDecl &P :
 | 
						|
       getPartialSpecializations()) {
 | 
						|
    if (Context.hasSameType(P.getInjectedSpecializationType(), T))
 | 
						|
      return P.getMostRecentDecl();
 | 
						|
  }
 | 
						|
 | 
						|
  return nullptr;
 | 
						|
}
 | 
						|
 | 
						|
ClassTemplatePartialSpecializationDecl *
 | 
						|
ClassTemplateDecl::findPartialSpecInstantiatedFromMember(
 | 
						|
                                    ClassTemplatePartialSpecializationDecl *D) {
 | 
						|
  Decl *DCanon = D->getCanonicalDecl();
 | 
						|
  for (ClassTemplatePartialSpecializationDecl &P : getPartialSpecializations()) {
 | 
						|
    if (P.getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
 | 
						|
      return P.getMostRecentDecl();
 | 
						|
  }
 | 
						|
 | 
						|
  return nullptr;
 | 
						|
}
 | 
						|
 | 
						|
QualType
 | 
						|
ClassTemplateDecl::getInjectedClassNameSpecialization() {
 | 
						|
  Common *CommonPtr = getCommonPtr();
 | 
						|
  if (!CommonPtr->InjectedClassNameType.isNull())
 | 
						|
    return CommonPtr->InjectedClassNameType;
 | 
						|
 | 
						|
  // C++0x [temp.dep.type]p2:
 | 
						|
  //  The template argument list of a primary template is a template argument
 | 
						|
  //  list in which the nth template argument has the value of the nth template
 | 
						|
  //  parameter of the class template. If the nth template parameter is a
 | 
						|
  //  template parameter pack (14.5.3), the nth template argument is a pack
 | 
						|
  //  expansion (14.5.3) whose pattern is the name of the template parameter
 | 
						|
  //  pack.
 | 
						|
  ASTContext &Context = getASTContext();
 | 
						|
  TemplateParameterList *Params = getTemplateParameters();
 | 
						|
  SmallVector<TemplateArgument, 16> TemplateArgs;
 | 
						|
  Context.getInjectedTemplateArgs(Params, TemplateArgs);
 | 
						|
  CommonPtr->InjectedClassNameType
 | 
						|
    = Context.getTemplateSpecializationType(TemplateName(this),
 | 
						|
                                            TemplateArgs);
 | 
						|
  return CommonPtr->InjectedClassNameType;
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// TemplateTypeParm Allocation/Deallocation Method Implementations
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
TemplateTypeParmDecl *
 | 
						|
TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC,
 | 
						|
                             SourceLocation KeyLoc, SourceLocation NameLoc,
 | 
						|
                             unsigned D, unsigned P, IdentifierInfo *Id,
 | 
						|
                             bool Typename, bool ParameterPack) {
 | 
						|
  auto *TTPDecl =
 | 
						|
      new (C, DC) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename);
 | 
						|
  QualType TTPType = C.getTemplateTypeParmType(D, P, ParameterPack, TTPDecl);
 | 
						|
  TTPDecl->setTypeForDecl(TTPType.getTypePtr());
 | 
						|
  return TTPDecl;
 | 
						|
}
 | 
						|
 | 
						|
TemplateTypeParmDecl *
 | 
						|
TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
 | 
						|
  return new (C, ID) TemplateTypeParmDecl(nullptr, SourceLocation(),
 | 
						|
                                          SourceLocation(), nullptr, false);
 | 
						|
}
 | 
						|
 | 
						|
SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
 | 
						|
  return hasDefaultArgument()
 | 
						|
             ? getDefaultArgumentInfo()->getTypeLoc().getBeginLoc()
 | 
						|
             : SourceLocation();
 | 
						|
}
 | 
						|
 | 
						|
SourceRange TemplateTypeParmDecl::getSourceRange() const {
 | 
						|
  if (hasDefaultArgument() && !defaultArgumentWasInherited())
 | 
						|
    return SourceRange(getBeginLoc(),
 | 
						|
                       getDefaultArgumentInfo()->getTypeLoc().getEndLoc());
 | 
						|
  // TypeDecl::getSourceRange returns a range containing name location, which is
 | 
						|
  // wrong for unnamed template parameters. e.g:
 | 
						|
  // it will return <[[typename>]] instead of <[[typename]]>
 | 
						|
  else if (getDeclName().isEmpty())
 | 
						|
    return SourceRange(getBeginLoc());
 | 
						|
  return TypeDecl::getSourceRange();
 | 
						|
}
 | 
						|
 | 
						|
unsigned TemplateTypeParmDecl::getDepth() const {
 | 
						|
  return getTypeForDecl()->castAs<TemplateTypeParmType>()->getDepth();
 | 
						|
}
 | 
						|
 | 
						|
unsigned TemplateTypeParmDecl::getIndex() const {
 | 
						|
  return getTypeForDecl()->castAs<TemplateTypeParmType>()->getIndex();
 | 
						|
}
 | 
						|
 | 
						|
bool TemplateTypeParmDecl::isParameterPack() const {
 | 
						|
  return getTypeForDecl()->castAs<TemplateTypeParmType>()->isParameterPack();
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// NonTypeTemplateParmDecl Method Implementations
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(
 | 
						|
    DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D,
 | 
						|
    unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo,
 | 
						|
    ArrayRef<QualType> ExpandedTypes, ArrayRef<TypeSourceInfo *> ExpandedTInfos)
 | 
						|
    : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc),
 | 
						|
      TemplateParmPosition(D, P), ParameterPack(true),
 | 
						|
      ExpandedParameterPack(true), NumExpandedTypes(ExpandedTypes.size()) {
 | 
						|
  if (!ExpandedTypes.empty() && !ExpandedTInfos.empty()) {
 | 
						|
    auto TypesAndInfos =
 | 
						|
        getTrailingObjects<std::pair<QualType, TypeSourceInfo *>>();
 | 
						|
    for (unsigned I = 0; I != NumExpandedTypes; ++I) {
 | 
						|
      new (&TypesAndInfos[I].first) QualType(ExpandedTypes[I]);
 | 
						|
      TypesAndInfos[I].second = ExpandedTInfos[I];
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
NonTypeTemplateParmDecl *
 | 
						|
NonTypeTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
 | 
						|
                                SourceLocation StartLoc, SourceLocation IdLoc,
 | 
						|
                                unsigned D, unsigned P, IdentifierInfo *Id,
 | 
						|
                                QualType T, bool ParameterPack,
 | 
						|
                                TypeSourceInfo *TInfo) {
 | 
						|
  return new (C, DC) NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id,
 | 
						|
                                             T, ParameterPack, TInfo);
 | 
						|
}
 | 
						|
 | 
						|
NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::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) {
 | 
						|
  return new (C, DC,
 | 
						|
              additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>>(
 | 
						|
                  ExpandedTypes.size()))
 | 
						|
      NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T, TInfo,
 | 
						|
                              ExpandedTypes, ExpandedTInfos);
 | 
						|
}
 | 
						|
 | 
						|
NonTypeTemplateParmDecl *
 | 
						|
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
 | 
						|
  return new (C, ID) NonTypeTemplateParmDecl(nullptr, SourceLocation(),
 | 
						|
                                             SourceLocation(), 0, 0, nullptr,
 | 
						|
                                             QualType(), false, nullptr);
 | 
						|
}
 | 
						|
 | 
						|
NonTypeTemplateParmDecl *
 | 
						|
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
 | 
						|
                                            unsigned NumExpandedTypes) {
 | 
						|
  auto *NTTP =
 | 
						|
      new (C, ID, additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>>(
 | 
						|
                      NumExpandedTypes))
 | 
						|
          NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(),
 | 
						|
                                  0, 0, nullptr, QualType(), nullptr, None,
 | 
						|
                                  None);
 | 
						|
  NTTP->NumExpandedTypes = NumExpandedTypes;
 | 
						|
  return NTTP;
 | 
						|
}
 | 
						|
 | 
						|
SourceRange NonTypeTemplateParmDecl::getSourceRange() const {
 | 
						|
  if (hasDefaultArgument() && !defaultArgumentWasInherited())
 | 
						|
    return SourceRange(getOuterLocStart(),
 | 
						|
                       getDefaultArgument()->getSourceRange().getEnd());
 | 
						|
  return DeclaratorDecl::getSourceRange();
 | 
						|
}
 | 
						|
 | 
						|
SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
 | 
						|
  return hasDefaultArgument()
 | 
						|
    ? getDefaultArgument()->getSourceRange().getBegin()
 | 
						|
    : SourceLocation();
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// TemplateTemplateParmDecl Method Implementations
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
void TemplateTemplateParmDecl::anchor() {}
 | 
						|
 | 
						|
TemplateTemplateParmDecl::TemplateTemplateParmDecl(
 | 
						|
    DeclContext *DC, SourceLocation L, unsigned D, unsigned P,
 | 
						|
    IdentifierInfo *Id, TemplateParameterList *Params,
 | 
						|
    ArrayRef<TemplateParameterList *> Expansions)
 | 
						|
    : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
 | 
						|
      TemplateParmPosition(D, P), ParameterPack(true),
 | 
						|
      ExpandedParameterPack(true), NumExpandedParams(Expansions.size()) {
 | 
						|
  if (!Expansions.empty())
 | 
						|
    std::uninitialized_copy(Expansions.begin(), Expansions.end(),
 | 
						|
                            getTrailingObjects<TemplateParameterList *>());
 | 
						|
}
 | 
						|
 | 
						|
TemplateTemplateParmDecl *
 | 
						|
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
 | 
						|
                                 SourceLocation L, unsigned D, unsigned P,
 | 
						|
                                 bool ParameterPack, IdentifierInfo *Id,
 | 
						|
                                 TemplateParameterList *Params) {
 | 
						|
  return new (C, DC) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id,
 | 
						|
                                              Params);
 | 
						|
}
 | 
						|
 | 
						|
TemplateTemplateParmDecl *
 | 
						|
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
 | 
						|
                                 SourceLocation L, unsigned D, unsigned P,
 | 
						|
                                 IdentifierInfo *Id,
 | 
						|
                                 TemplateParameterList *Params,
 | 
						|
                                 ArrayRef<TemplateParameterList *> Expansions) {
 | 
						|
  return new (C, DC,
 | 
						|
              additionalSizeToAlloc<TemplateParameterList *>(Expansions.size()))
 | 
						|
      TemplateTemplateParmDecl(DC, L, D, P, Id, Params, Expansions);
 | 
						|
}
 | 
						|
 | 
						|
TemplateTemplateParmDecl *
 | 
						|
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
 | 
						|
  return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0,
 | 
						|
                                              false, nullptr, nullptr);
 | 
						|
}
 | 
						|
 | 
						|
TemplateTemplateParmDecl *
 | 
						|
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID,
 | 
						|
                                             unsigned NumExpansions) {
 | 
						|
  auto *TTP =
 | 
						|
      new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(NumExpansions))
 | 
						|
          TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr,
 | 
						|
                                   nullptr, None);
 | 
						|
  TTP->NumExpandedParams = NumExpansions;
 | 
						|
  return TTP;
 | 
						|
}
 | 
						|
 | 
						|
SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
 | 
						|
  return hasDefaultArgument() ? getDefaultArgument().getLocation()
 | 
						|
                              : SourceLocation();
 | 
						|
}
 | 
						|
 | 
						|
void TemplateTemplateParmDecl::setDefaultArgument(
 | 
						|
    const ASTContext &C, const TemplateArgumentLoc &DefArg) {
 | 
						|
  if (DefArg.getArgument().isNull())
 | 
						|
    DefaultArgument.set(nullptr);
 | 
						|
  else
 | 
						|
    DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg));
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// TemplateArgumentList Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
TemplateArgumentList::TemplateArgumentList(ArrayRef<TemplateArgument> Args)
 | 
						|
    : Arguments(getTrailingObjects<TemplateArgument>()),
 | 
						|
      NumArguments(Args.size()) {
 | 
						|
  std::uninitialized_copy(Args.begin(), Args.end(),
 | 
						|
                          getTrailingObjects<TemplateArgument>());
 | 
						|
}
 | 
						|
 | 
						|
TemplateArgumentList *
 | 
						|
TemplateArgumentList::CreateCopy(ASTContext &Context,
 | 
						|
                                 ArrayRef<TemplateArgument> Args) {
 | 
						|
  void *Mem = Context.Allocate(totalSizeToAlloc<TemplateArgument>(Args.size()));
 | 
						|
  return new (Mem) TemplateArgumentList(Args);
 | 
						|
}
 | 
						|
 | 
						|
FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create(
 | 
						|
    ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
 | 
						|
    TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs,
 | 
						|
    const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI,
 | 
						|
    MemberSpecializationInfo *MSInfo) {
 | 
						|
  const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
 | 
						|
  if (TemplateArgsAsWritten)
 | 
						|
    ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C,
 | 
						|
                                                        *TemplateArgsAsWritten);
 | 
						|
 | 
						|
  void *Mem =
 | 
						|
      C.Allocate(totalSizeToAlloc<MemberSpecializationInfo *>(MSInfo ? 1 : 0));
 | 
						|
  return new (Mem) FunctionTemplateSpecializationInfo(
 | 
						|
      FD, Template, TSK, TemplateArgs, ArgsAsWritten, POI, MSInfo);
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// ClassTemplateSpecializationDecl Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
ClassTemplateSpecializationDecl::
 | 
						|
ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
 | 
						|
                                DeclContext *DC, SourceLocation StartLoc,
 | 
						|
                                SourceLocation IdLoc,
 | 
						|
                                ClassTemplateDecl *SpecializedTemplate,
 | 
						|
                                ArrayRef<TemplateArgument> Args,
 | 
						|
                                ClassTemplateSpecializationDecl *PrevDecl)
 | 
						|
    : CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc,
 | 
						|
                    SpecializedTemplate->getIdentifier(), PrevDecl),
 | 
						|
    SpecializedTemplate(SpecializedTemplate),
 | 
						|
    TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
 | 
						|
    SpecializationKind(TSK_Undeclared) {
 | 
						|
}
 | 
						|
 | 
						|
ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
 | 
						|
                                                                 Kind DK)
 | 
						|
    : CXXRecordDecl(DK, TTK_Struct, C, nullptr, SourceLocation(),
 | 
						|
                    SourceLocation(), nullptr, nullptr),
 | 
						|
      SpecializationKind(TSK_Undeclared) {}
 | 
						|
 | 
						|
ClassTemplateSpecializationDecl *
 | 
						|
ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
 | 
						|
                                        DeclContext *DC,
 | 
						|
                                        SourceLocation StartLoc,
 | 
						|
                                        SourceLocation IdLoc,
 | 
						|
                                        ClassTemplateDecl *SpecializedTemplate,
 | 
						|
                                        ArrayRef<TemplateArgument> Args,
 | 
						|
                                   ClassTemplateSpecializationDecl *PrevDecl) {
 | 
						|
  auto *Result =
 | 
						|
      new (Context, DC) ClassTemplateSpecializationDecl(
 | 
						|
          Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
 | 
						|
          SpecializedTemplate, Args, PrevDecl);
 | 
						|
  Result->setMayHaveOutOfDateDef(false);
 | 
						|
 | 
						|
  Context.getTypeDeclType(Result, PrevDecl);
 | 
						|
  return Result;
 | 
						|
}
 | 
						|
 | 
						|
ClassTemplateSpecializationDecl *
 | 
						|
ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
 | 
						|
                                                    unsigned ID) {
 | 
						|
  auto *Result =
 | 
						|
    new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
 | 
						|
  Result->setMayHaveOutOfDateDef(false);
 | 
						|
  return Result;
 | 
						|
}
 | 
						|
 | 
						|
void ClassTemplateSpecializationDecl::getNameForDiagnostic(
 | 
						|
    raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
 | 
						|
  NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
 | 
						|
 | 
						|
  const auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this);
 | 
						|
  if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
 | 
						|
          PS ? PS->getTemplateArgsAsWritten() : nullptr) {
 | 
						|
    printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy);
 | 
						|
  } else {
 | 
						|
    const TemplateArgumentList &TemplateArgs = getTemplateArgs();
 | 
						|
    printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
ClassTemplateDecl *
 | 
						|
ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
 | 
						|
  if (const auto *PartialSpec =
 | 
						|
          SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
 | 
						|
    return PartialSpec->PartialSpecialization->getSpecializedTemplate();
 | 
						|
  return SpecializedTemplate.get<ClassTemplateDecl*>();
 | 
						|
}
 | 
						|
 | 
						|
SourceRange
 | 
						|
ClassTemplateSpecializationDecl::getSourceRange() const {
 | 
						|
  if (ExplicitInfo) {
 | 
						|
    SourceLocation Begin = getTemplateKeywordLoc();
 | 
						|
    if (Begin.isValid()) {
 | 
						|
      // Here we have an explicit (partial) specialization or instantiation.
 | 
						|
      assert(getSpecializationKind() == TSK_ExplicitSpecialization ||
 | 
						|
             getSpecializationKind() == TSK_ExplicitInstantiationDeclaration ||
 | 
						|
             getSpecializationKind() == TSK_ExplicitInstantiationDefinition);
 | 
						|
      if (getExternLoc().isValid())
 | 
						|
        Begin = getExternLoc();
 | 
						|
      SourceLocation End = getBraceRange().getEnd();
 | 
						|
      if (End.isInvalid())
 | 
						|
        End = getTypeAsWritten()->getTypeLoc().getEndLoc();
 | 
						|
      return SourceRange(Begin, End);
 | 
						|
    }
 | 
						|
    // An implicit instantiation of a class template partial specialization
 | 
						|
    // uses ExplicitInfo to record the TypeAsWritten, but the source
 | 
						|
    // locations should be retrieved from the instantiation pattern.
 | 
						|
    using CTPSDecl = ClassTemplatePartialSpecializationDecl;
 | 
						|
    auto *ctpsd = const_cast<CTPSDecl *>(cast<CTPSDecl>(this));
 | 
						|
    CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember();
 | 
						|
    assert(inst_from != nullptr);
 | 
						|
    return inst_from->getSourceRange();
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    // No explicit info available.
 | 
						|
    llvm::PointerUnion<ClassTemplateDecl *,
 | 
						|
                       ClassTemplatePartialSpecializationDecl *>
 | 
						|
      inst_from = getInstantiatedFrom();
 | 
						|
    if (inst_from.isNull())
 | 
						|
      return getSpecializedTemplate()->getSourceRange();
 | 
						|
    if (const auto *ctd = inst_from.dyn_cast<ClassTemplateDecl *>())
 | 
						|
      return ctd->getSourceRange();
 | 
						|
    return inst_from.get<ClassTemplatePartialSpecializationDecl *>()
 | 
						|
      ->getSourceRange();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// ConceptDecl Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
ConceptDecl *ConceptDecl::Create(ASTContext &C, DeclContext *DC,
 | 
						|
                                 SourceLocation L, DeclarationName Name,
 | 
						|
                                 TemplateParameterList *Params,
 | 
						|
                                 Expr *ConstraintExpr) {
 | 
						|
  AdoptTemplateParameterList(Params, DC);
 | 
						|
  return new (C, DC) ConceptDecl(DC, L, Name, Params, ConstraintExpr);
 | 
						|
}
 | 
						|
 | 
						|
ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C,
 | 
						|
                                             unsigned ID) {
 | 
						|
  ConceptDecl *Result = new (C, ID) ConceptDecl(nullptr, SourceLocation(),
 | 
						|
                                                DeclarationName(),
 | 
						|
                                                nullptr, nullptr);
 | 
						|
 | 
						|
  return Result;
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// ClassTemplatePartialSpecializationDecl Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
void ClassTemplatePartialSpecializationDecl::anchor() {}
 | 
						|
 | 
						|
ClassTemplatePartialSpecializationDecl::
 | 
						|
ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
 | 
						|
                                       DeclContext *DC,
 | 
						|
                                       SourceLocation StartLoc,
 | 
						|
                                       SourceLocation IdLoc,
 | 
						|
                                       TemplateParameterList *Params,
 | 
						|
                                       ClassTemplateDecl *SpecializedTemplate,
 | 
						|
                                       ArrayRef<TemplateArgument> Args,
 | 
						|
                               const ASTTemplateArgumentListInfo *ArgInfos,
 | 
						|
                               ClassTemplatePartialSpecializationDecl *PrevDecl)
 | 
						|
    : ClassTemplateSpecializationDecl(Context,
 | 
						|
                                      ClassTemplatePartialSpecialization,
 | 
						|
                                      TK, DC, StartLoc, IdLoc,
 | 
						|
                                      SpecializedTemplate, Args, PrevDecl),
 | 
						|
      TemplateParams(Params), ArgsAsWritten(ArgInfos),
 | 
						|
      InstantiatedFromMember(nullptr, false) {
 | 
						|
  AdoptTemplateParameterList(Params, this);
 | 
						|
}
 | 
						|
 | 
						|
ClassTemplatePartialSpecializationDecl *
 | 
						|
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) {
 | 
						|
  const ASTTemplateArgumentListInfo *ASTArgInfos =
 | 
						|
    ASTTemplateArgumentListInfo::Create(Context, ArgInfos);
 | 
						|
 | 
						|
  auto *Result = new (Context, DC)
 | 
						|
      ClassTemplatePartialSpecializationDecl(Context, TK, DC, StartLoc, IdLoc,
 | 
						|
                                             Params, SpecializedTemplate, Args,
 | 
						|
                                             ASTArgInfos, PrevDecl);
 | 
						|
  Result->setSpecializationKind(TSK_ExplicitSpecialization);
 | 
						|
  Result->setMayHaveOutOfDateDef(false);
 | 
						|
 | 
						|
  Context.getInjectedClassNameType(Result, CanonInjectedType);
 | 
						|
  return Result;
 | 
						|
}
 | 
						|
 | 
						|
ClassTemplatePartialSpecializationDecl *
 | 
						|
ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
 | 
						|
                                                           unsigned ID) {
 | 
						|
  auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C);
 | 
						|
  Result->setMayHaveOutOfDateDef(false);
 | 
						|
  return Result;
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// FriendTemplateDecl Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
void FriendTemplateDecl::anchor() {}
 | 
						|
 | 
						|
FriendTemplateDecl *
 | 
						|
FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC,
 | 
						|
                           SourceLocation L,
 | 
						|
                           MutableArrayRef<TemplateParameterList *> Params,
 | 
						|
                           FriendUnion Friend, SourceLocation FLoc) {
 | 
						|
  return new (Context, DC) FriendTemplateDecl(DC, L, Params, Friend, FLoc);
 | 
						|
}
 | 
						|
 | 
						|
FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C,
 | 
						|
                                                           unsigned ID) {
 | 
						|
  return new (C, ID) FriendTemplateDecl(EmptyShell());
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// TypeAliasTemplateDecl Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C,
 | 
						|
                                                     DeclContext *DC,
 | 
						|
                                                     SourceLocation L,
 | 
						|
                                                     DeclarationName Name,
 | 
						|
                                                  TemplateParameterList *Params,
 | 
						|
                                                     NamedDecl *Decl) {
 | 
						|
  AdoptTemplateParameterList(Params, DC);
 | 
						|
  return new (C, DC) TypeAliasTemplateDecl(C, DC, L, Name, Params, Decl);
 | 
						|
}
 | 
						|
 | 
						|
TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C,
 | 
						|
                                                                 unsigned ID) {
 | 
						|
  return new (C, ID) TypeAliasTemplateDecl(C, nullptr, SourceLocation(),
 | 
						|
                                           DeclarationName(), nullptr, nullptr);
 | 
						|
}
 | 
						|
 | 
						|
RedeclarableTemplateDecl::CommonBase *
 | 
						|
TypeAliasTemplateDecl::newCommon(ASTContext &C) const {
 | 
						|
  auto *CommonPtr = new (C) Common;
 | 
						|
  C.addDestruction(CommonPtr);
 | 
						|
  return CommonPtr;
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// ClassScopeFunctionSpecializationDecl Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
void ClassScopeFunctionSpecializationDecl::anchor() {}
 | 
						|
 | 
						|
ClassScopeFunctionSpecializationDecl *
 | 
						|
ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C,
 | 
						|
                                                         unsigned ID) {
 | 
						|
  return new (C, ID) ClassScopeFunctionSpecializationDecl(
 | 
						|
      nullptr, SourceLocation(), nullptr, nullptr);
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// VarTemplateDecl Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
VarTemplateDecl *VarTemplateDecl::getDefinition() {
 | 
						|
  VarTemplateDecl *CurD = this;
 | 
						|
  while (CurD) {
 | 
						|
    if (CurD->isThisDeclarationADefinition())
 | 
						|
      return CurD;
 | 
						|
    CurD = CurD->getPreviousDecl();
 | 
						|
  }
 | 
						|
  return nullptr;
 | 
						|
}
 | 
						|
 | 
						|
VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC,
 | 
						|
                                         SourceLocation L, DeclarationName Name,
 | 
						|
                                         TemplateParameterList *Params,
 | 
						|
                                         VarDecl *Decl) {
 | 
						|
  AdoptTemplateParameterList(Params, DC);
 | 
						|
  return new (C, DC) VarTemplateDecl(C, DC, L, Name, Params, Decl);
 | 
						|
}
 | 
						|
 | 
						|
VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
 | 
						|
                                                     unsigned ID) {
 | 
						|
  return new (C, ID) VarTemplateDecl(C, nullptr, SourceLocation(),
 | 
						|
                                     DeclarationName(), nullptr, nullptr);
 | 
						|
}
 | 
						|
 | 
						|
void VarTemplateDecl::LoadLazySpecializations() const {
 | 
						|
  loadLazySpecializationsImpl();
 | 
						|
}
 | 
						|
 | 
						|
llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
 | 
						|
VarTemplateDecl::getSpecializations() const {
 | 
						|
  LoadLazySpecializations();
 | 
						|
  return getCommonPtr()->Specializations;
 | 
						|
}
 | 
						|
 | 
						|
llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
 | 
						|
VarTemplateDecl::getPartialSpecializations() {
 | 
						|
  LoadLazySpecializations();
 | 
						|
  return getCommonPtr()->PartialSpecializations;
 | 
						|
}
 | 
						|
 | 
						|
RedeclarableTemplateDecl::CommonBase *
 | 
						|
VarTemplateDecl::newCommon(ASTContext &C) const {
 | 
						|
  auto *CommonPtr = new (C) Common;
 | 
						|
  C.addDestruction(CommonPtr);
 | 
						|
  return CommonPtr;
 | 
						|
}
 | 
						|
 | 
						|
VarTemplateSpecializationDecl *
 | 
						|
VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args,
 | 
						|
                                    void *&InsertPos) {
 | 
						|
  return findSpecializationImpl(getSpecializations(), Args, InsertPos);
 | 
						|
}
 | 
						|
 | 
						|
void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D,
 | 
						|
                                        void *InsertPos) {
 | 
						|
  addSpecializationImpl<VarTemplateDecl>(getSpecializations(), D, InsertPos);
 | 
						|
}
 | 
						|
 | 
						|
VarTemplatePartialSpecializationDecl *
 | 
						|
VarTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args,
 | 
						|
                                           void *&InsertPos) {
 | 
						|
  return findSpecializationImpl(getPartialSpecializations(), Args, InsertPos);
 | 
						|
}
 | 
						|
 | 
						|
void VarTemplateDecl::AddPartialSpecialization(
 | 
						|
    VarTemplatePartialSpecializationDecl *D, void *InsertPos) {
 | 
						|
  if (InsertPos)
 | 
						|
    getPartialSpecializations().InsertNode(D, InsertPos);
 | 
						|
  else {
 | 
						|
    VarTemplatePartialSpecializationDecl *Existing =
 | 
						|
        getPartialSpecializations().GetOrInsertNode(D);
 | 
						|
    (void)Existing;
 | 
						|
    assert(Existing->isCanonicalDecl() && "Non-canonical specialization?");
 | 
						|
  }
 | 
						|
 | 
						|
  if (ASTMutationListener *L = getASTMutationListener())
 | 
						|
    L->AddedCXXTemplateSpecialization(this, D);
 | 
						|
}
 | 
						|
 | 
						|
void VarTemplateDecl::getPartialSpecializations(
 | 
						|
    SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS) {
 | 
						|
  llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &PartialSpecs =
 | 
						|
      getPartialSpecializations();
 | 
						|
  PS.clear();
 | 
						|
  PS.reserve(PartialSpecs.size());
 | 
						|
  for (VarTemplatePartialSpecializationDecl &P : PartialSpecs)
 | 
						|
    PS.push_back(P.getMostRecentDecl());
 | 
						|
}
 | 
						|
 | 
						|
VarTemplatePartialSpecializationDecl *
 | 
						|
VarTemplateDecl::findPartialSpecInstantiatedFromMember(
 | 
						|
    VarTemplatePartialSpecializationDecl *D) {
 | 
						|
  Decl *DCanon = D->getCanonicalDecl();
 | 
						|
  for (VarTemplatePartialSpecializationDecl &P : getPartialSpecializations()) {
 | 
						|
    if (P.getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
 | 
						|
      return P.getMostRecentDecl();
 | 
						|
  }
 | 
						|
 | 
						|
  return nullptr;
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// VarTemplateSpecializationDecl Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(
 | 
						|
    Kind DK, ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
 | 
						|
    SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
 | 
						|
    TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args)
 | 
						|
    : VarDecl(DK, Context, DC, StartLoc, IdLoc,
 | 
						|
              SpecializedTemplate->getIdentifier(), T, TInfo, S),
 | 
						|
      SpecializedTemplate(SpecializedTemplate),
 | 
						|
      TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
 | 
						|
      SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {}
 | 
						|
 | 
						|
VarTemplateSpecializationDecl::VarTemplateSpecializationDecl(Kind DK,
 | 
						|
                                                             ASTContext &C)
 | 
						|
    : VarDecl(DK, C, nullptr, SourceLocation(), SourceLocation(), nullptr,
 | 
						|
              QualType(), nullptr, SC_None),
 | 
						|
      SpecializationKind(TSK_Undeclared), IsCompleteDefinition(false) {}
 | 
						|
 | 
						|
VarTemplateSpecializationDecl *VarTemplateSpecializationDecl::Create(
 | 
						|
    ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
 | 
						|
    SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
 | 
						|
    TypeSourceInfo *TInfo, StorageClass S, ArrayRef<TemplateArgument> Args) {
 | 
						|
  return new (Context, DC) VarTemplateSpecializationDecl(
 | 
						|
      VarTemplateSpecialization, Context, DC, StartLoc, IdLoc,
 | 
						|
      SpecializedTemplate, T, TInfo, S, Args);
 | 
						|
}
 | 
						|
 | 
						|
VarTemplateSpecializationDecl *
 | 
						|
VarTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
 | 
						|
  return new (C, ID)
 | 
						|
      VarTemplateSpecializationDecl(VarTemplateSpecialization, C);
 | 
						|
}
 | 
						|
 | 
						|
void VarTemplateSpecializationDecl::getNameForDiagnostic(
 | 
						|
    raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const {
 | 
						|
  NamedDecl::getNameForDiagnostic(OS, Policy, Qualified);
 | 
						|
 | 
						|
  const auto *PS = dyn_cast<VarTemplatePartialSpecializationDecl>(this);
 | 
						|
  if (const ASTTemplateArgumentListInfo *ArgsAsWritten =
 | 
						|
          PS ? PS->getTemplateArgsAsWritten() : nullptr) {
 | 
						|
    printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy);
 | 
						|
  } else {
 | 
						|
    const TemplateArgumentList &TemplateArgs = getTemplateArgs();
 | 
						|
    printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
 | 
						|
  if (const auto *PartialSpec =
 | 
						|
          SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
 | 
						|
    return PartialSpec->PartialSpecialization->getSpecializedTemplate();
 | 
						|
  return SpecializedTemplate.get<VarTemplateDecl *>();
 | 
						|
}
 | 
						|
 | 
						|
void VarTemplateSpecializationDecl::setTemplateArgsInfo(
 | 
						|
    const TemplateArgumentListInfo &ArgsInfo) {
 | 
						|
  TemplateArgsInfo.setLAngleLoc(ArgsInfo.getLAngleLoc());
 | 
						|
  TemplateArgsInfo.setRAngleLoc(ArgsInfo.getRAngleLoc());
 | 
						|
  for (const TemplateArgumentLoc &Loc : ArgsInfo.arguments())
 | 
						|
    TemplateArgsInfo.addArgument(Loc);
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// VarTemplatePartialSpecializationDecl Implementation
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
void VarTemplatePartialSpecializationDecl::anchor() {}
 | 
						|
 | 
						|
VarTemplatePartialSpecializationDecl::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)
 | 
						|
    : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context,
 | 
						|
                                    DC, StartLoc, IdLoc, SpecializedTemplate, T,
 | 
						|
                                    TInfo, S, Args),
 | 
						|
      TemplateParams(Params), ArgsAsWritten(ArgInfos),
 | 
						|
      InstantiatedFromMember(nullptr, false) {
 | 
						|
  // TODO: The template parameters should be in DC by now. Verify.
 | 
						|
  // AdoptTemplateParameterList(Params, DC);
 | 
						|
}
 | 
						|
 | 
						|
VarTemplatePartialSpecializationDecl *
 | 
						|
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) {
 | 
						|
  const ASTTemplateArgumentListInfo *ASTArgInfos
 | 
						|
    = ASTTemplateArgumentListInfo::Create(Context, ArgInfos);
 | 
						|
 | 
						|
  auto *Result =
 | 
						|
      new (Context, DC) VarTemplatePartialSpecializationDecl(
 | 
						|
          Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo,
 | 
						|
          S, Args, ASTArgInfos);
 | 
						|
  Result->setSpecializationKind(TSK_ExplicitSpecialization);
 | 
						|
  return Result;
 | 
						|
}
 | 
						|
 | 
						|
VarTemplatePartialSpecializationDecl *
 | 
						|
VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
 | 
						|
                                                         unsigned ID) {
 | 
						|
  return new (C, ID) VarTemplatePartialSpecializationDecl(C);
 | 
						|
}
 | 
						|
 | 
						|
static TemplateParameterList *
 | 
						|
createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
 | 
						|
  // typename T
 | 
						|
  auto *T = TemplateTypeParmDecl::Create(
 | 
						|
      C, DC, SourceLocation(), SourceLocation(), /*Depth=*/1, /*Position=*/0,
 | 
						|
      /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false);
 | 
						|
  T->setImplicit(true);
 | 
						|
 | 
						|
  // T ...Ints
 | 
						|
  TypeSourceInfo *TI =
 | 
						|
      C.getTrivialTypeSourceInfo(QualType(T->getTypeForDecl(), 0));
 | 
						|
  auto *N = NonTypeTemplateParmDecl::Create(
 | 
						|
      C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
 | 
						|
      /*Id=*/nullptr, TI->getType(), /*ParameterPack=*/true, TI);
 | 
						|
  N->setImplicit(true);
 | 
						|
 | 
						|
  // <typename T, T ...Ints>
 | 
						|
  NamedDecl *P[2] = {T, N};
 | 
						|
  auto *TPL = TemplateParameterList::Create(
 | 
						|
      C, SourceLocation(), SourceLocation(), P, SourceLocation(), nullptr);
 | 
						|
 | 
						|
  // template <typename T, ...Ints> class IntSeq
 | 
						|
  auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create(
 | 
						|
      C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/0,
 | 
						|
      /*ParameterPack=*/false, /*Id=*/nullptr, TPL);
 | 
						|
  TemplateTemplateParm->setImplicit(true);
 | 
						|
 | 
						|
  // typename T
 | 
						|
  auto *TemplateTypeParm = TemplateTypeParmDecl::Create(
 | 
						|
      C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
 | 
						|
      /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false);
 | 
						|
  TemplateTypeParm->setImplicit(true);
 | 
						|
 | 
						|
  // T N
 | 
						|
  TypeSourceInfo *TInfo = C.getTrivialTypeSourceInfo(
 | 
						|
      QualType(TemplateTypeParm->getTypeForDecl(), 0));
 | 
						|
  auto *NonTypeTemplateParm = NonTypeTemplateParmDecl::Create(
 | 
						|
      C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/2,
 | 
						|
      /*Id=*/nullptr, TInfo->getType(), /*ParameterPack=*/false, TInfo);
 | 
						|
  NamedDecl *Params[] = {TemplateTemplateParm, TemplateTypeParm,
 | 
						|
                         NonTypeTemplateParm};
 | 
						|
 | 
						|
  // template <template <typename T, T ...Ints> class IntSeq, typename T, T N>
 | 
						|
  return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
 | 
						|
                                       Params, SourceLocation(), nullptr);
 | 
						|
}
 | 
						|
 | 
						|
static TemplateParameterList *
 | 
						|
createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) {
 | 
						|
  // std::size_t Index
 | 
						|
  TypeSourceInfo *TInfo = C.getTrivialTypeSourceInfo(C.getSizeType());
 | 
						|
  auto *Index = NonTypeTemplateParmDecl::Create(
 | 
						|
      C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/0,
 | 
						|
      /*Id=*/nullptr, TInfo->getType(), /*ParameterPack=*/false, TInfo);
 | 
						|
 | 
						|
  // typename ...T
 | 
						|
  auto *Ts = TemplateTypeParmDecl::Create(
 | 
						|
      C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
 | 
						|
      /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/true);
 | 
						|
  Ts->setImplicit(true);
 | 
						|
 | 
						|
  // template <std::size_t Index, typename ...T>
 | 
						|
  NamedDecl *Params[] = {Index, Ts};
 | 
						|
  return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
 | 
						|
                                       llvm::makeArrayRef(Params),
 | 
						|
                                       SourceLocation(), nullptr);
 | 
						|
}
 | 
						|
 | 
						|
static TemplateParameterList *createBuiltinTemplateParameterList(
 | 
						|
    const ASTContext &C, DeclContext *DC, BuiltinTemplateKind BTK) {
 | 
						|
  switch (BTK) {
 | 
						|
  case BTK__make_integer_seq:
 | 
						|
    return createMakeIntegerSeqParameterList(C, DC);
 | 
						|
  case BTK__type_pack_element:
 | 
						|
    return createTypePackElementParameterList(C, DC);
 | 
						|
  }
 | 
						|
 | 
						|
  llvm_unreachable("unhandled BuiltinTemplateKind!");
 | 
						|
}
 | 
						|
 | 
						|
void BuiltinTemplateDecl::anchor() {}
 | 
						|
 | 
						|
BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC,
 | 
						|
                                         DeclarationName Name,
 | 
						|
                                         BuiltinTemplateKind BTK)
 | 
						|
    : TemplateDecl(BuiltinTemplate, DC, SourceLocation(), Name,
 | 
						|
                   createBuiltinTemplateParameterList(C, DC, BTK)),
 | 
						|
      BTK(BTK) {}
 |