to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
1242 lines
50 KiB
C++
1242 lines
50 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;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
namespace clang {
|
|
|
|
void *allocateDefaultArgStorageChain(const ASTContext &C) {
|
|
return new (C) char[sizeof(void*) * 2];
|
|
}
|
|
|
|
} // namespace clang
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// 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,
|
|
Expr *AssociatedConstraints) {
|
|
AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
|
|
|
|
if (!AssociatedConstraints) {
|
|
return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
|
|
}
|
|
|
|
auto *const CTDI = new (C) ConstrainedTemplateDeclInfo;
|
|
auto *const New =
|
|
new (C, DC) ClassTemplateDecl(CTDI, C, DC, L, Name, Params, Decl);
|
|
New->setAssociatedConstraints(AssociatedConstraints);
|
|
return New;
|
|
}
|
|
|
|
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());
|
|
else
|
|
return TypeDecl::getSourceRange();
|
|
}
|
|
|
|
unsigned TemplateTypeParmDecl::getDepth() const {
|
|
return getTypeForDecl()->getAs<TemplateTypeParmType>()->getDepth();
|
|
}
|
|
|
|
unsigned TemplateTypeParmDecl::getIndex() const {
|
|
return getTypeForDecl()->getAs<TemplateTypeParmType>()->getIndex();
|
|
}
|
|
|
|
bool TemplateTypeParmDecl::isParameterPack() const {
|
|
return getTypeForDecl()->getAs<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) {
|
|
const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
|
|
if (TemplateArgsAsWritten)
|
|
ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C,
|
|
*TemplateArgsAsWritten);
|
|
|
|
return new (C) FunctionTemplateSpecializationInfo(FD, Template, TSK,
|
|
TemplateArgs,
|
|
ArgsAsWritten,
|
|
POI);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// TemplateDecl Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void TemplateDecl::anchor() {}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// 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();
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// 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, false, TemplateArgumentListInfo());
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// 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) {
|
|
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) {}
|