mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 09:46:06 +00:00

This introduces a new class 'UnsignedOrNone', which models a lite version of `std::optional<unsigned>`, but has the same size as 'unsigned'. This replaces most uses of `std::optional<unsigned>`, and similar schemes utilizing 'int' and '-1' as sentinel. Besides the smaller size advantage, this is simpler to serialize, as its internal representation is a single unsigned int as well.
1702 lines
66 KiB
C++
1702 lines
66 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/ExprCXX.h"
|
|
#include "clang/AST/ExternalASTSource.h"
|
|
#include "clang/AST/ODRHash.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/PointerUnion.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include <cassert>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <utility>
|
|
|
|
using namespace clang;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// TemplateParameterList Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
template <class TemplateParam>
|
|
static bool
|
|
DefaultTemplateArgumentContainsUnexpandedPack(const TemplateParam &P) {
|
|
return P.hasDefaultArgument() &&
|
|
P.getDefaultArgument().getArgument().containsUnexpandedParameterPack();
|
|
}
|
|
|
|
TemplateParameterList::TemplateParameterList(const ASTContext &C,
|
|
SourceLocation TemplateLoc,
|
|
SourceLocation LAngleLoc,
|
|
ArrayRef<NamedDecl *> Params,
|
|
SourceLocation RAngleLoc,
|
|
Expr *RequiresClause)
|
|
: TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
|
|
NumParams(Params.size()), ContainsUnexpandedParameterPack(false),
|
|
HasRequiresClause(RequiresClause != nullptr),
|
|
HasConstrainedParameters(false) {
|
|
for (unsigned Idx = 0; Idx < NumParams; ++Idx) {
|
|
NamedDecl *P = Params[Idx];
|
|
begin()[Idx] = P;
|
|
|
|
bool IsPack = P->isTemplateParameterPack();
|
|
if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
|
|
if (!IsPack && (NTTP->getType()->containsUnexpandedParameterPack() ||
|
|
DefaultTemplateArgumentContainsUnexpandedPack(*NTTP)))
|
|
ContainsUnexpandedParameterPack = true;
|
|
if (NTTP->hasPlaceholderTypeConstraint())
|
|
HasConstrainedParameters = true;
|
|
} else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P)) {
|
|
if (!IsPack &&
|
|
(TTP->getTemplateParameters()->containsUnexpandedParameterPack() ||
|
|
DefaultTemplateArgumentContainsUnexpandedPack(*TTP))) {
|
|
ContainsUnexpandedParameterPack = true;
|
|
}
|
|
} else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
|
|
if (!IsPack && DefaultTemplateArgumentContainsUnexpandedPack(*TTP)) {
|
|
ContainsUnexpandedParameterPack = true;
|
|
} else if (const TypeConstraint *TC = TTP->getTypeConstraint();
|
|
TC && TC->getImmediatelyDeclaredConstraint()
|
|
->containsUnexpandedParameterPack()) {
|
|
ContainsUnexpandedParameterPack = true;
|
|
}
|
|
if (TTP->hasTypeConstraint())
|
|
HasConstrainedParameters = true;
|
|
} else {
|
|
llvm_unreachable("unexpected template parameter type");
|
|
}
|
|
}
|
|
|
|
if (HasRequiresClause) {
|
|
if (RequiresClause->containsUnexpandedParameterPack())
|
|
ContainsUnexpandedParameterPack = true;
|
|
*getTrailingObjects<Expr *>() = RequiresClause;
|
|
}
|
|
}
|
|
|
|
bool TemplateParameterList::containsUnexpandedParameterPack() const {
|
|
if (ContainsUnexpandedParameterPack)
|
|
return true;
|
|
if (!HasConstrainedParameters)
|
|
return false;
|
|
|
|
// An implicit constrained parameter might have had a use of an unexpanded
|
|
// pack added to it after the template parameter list was created. All
|
|
// implicit parameters are at the end of the parameter list.
|
|
for (const NamedDecl *Param : llvm::reverse(asArray())) {
|
|
if (!Param->isImplicit())
|
|
break;
|
|
|
|
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
|
|
const auto *TC = TTP->getTypeConstraint();
|
|
if (TC && TC->getImmediatelyDeclaredConstraint()
|
|
->containsUnexpandedParameterPack())
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
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(C, TemplateLoc, LAngleLoc, Params,
|
|
RAngleLoc, RequiresClause);
|
|
}
|
|
|
|
void TemplateParameterList::Profile(llvm::FoldingSetNodeID &ID,
|
|
const ASTContext &C) const {
|
|
const Expr *RC = getRequiresClause();
|
|
ID.AddBoolean(RC != nullptr);
|
|
if (RC)
|
|
RC->Profile(ID, C, /*Canonical=*/true);
|
|
ID.AddInteger(size());
|
|
for (NamedDecl *D : *this) {
|
|
if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
|
|
ID.AddInteger(0);
|
|
ID.AddBoolean(NTTP->isParameterPack());
|
|
NTTP->getType().getCanonicalType().Profile(ID);
|
|
ID.AddBoolean(NTTP->hasPlaceholderTypeConstraint());
|
|
if (const Expr *E = NTTP->getPlaceholderTypeConstraint())
|
|
E->Profile(ID, C, /*Canonical=*/true);
|
|
continue;
|
|
}
|
|
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(D)) {
|
|
ID.AddInteger(1);
|
|
ID.AddBoolean(TTP->isParameterPack());
|
|
ID.AddBoolean(TTP->hasTypeConstraint());
|
|
if (const TypeConstraint *TC = TTP->getTypeConstraint())
|
|
TC->getImmediatelyDeclaredConstraint()->Profile(ID, C,
|
|
/*Canonical=*/true);
|
|
continue;
|
|
}
|
|
const auto *TTP = cast<TemplateTemplateParmDecl>(D);
|
|
ID.AddInteger(2);
|
|
ID.AddBoolean(TTP->isParameterPack());
|
|
TTP->getTemplateParameters()->Profile(ID, C);
|
|
}
|
|
}
|
|
|
|
unsigned TemplateParameterList::getMinRequiredArguments() const {
|
|
unsigned NumRequiredArgs = 0;
|
|
for (const NamedDecl *P : asArray()) {
|
|
if (P->isTemplateParameterPack()) {
|
|
if (UnsignedOrNone Expansions = getExpandedPackSize(P)) {
|
|
NumRequiredArgs += *Expansions;
|
|
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 bool AdoptTemplateParameterList(TemplateParameterList *Params,
|
|
DeclContext *Owner) {
|
|
bool Invalid = false;
|
|
for (NamedDecl *P : *Params) {
|
|
P->setDeclContext(Owner);
|
|
|
|
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P))
|
|
if (AdoptTemplateParameterList(TTP->getTemplateParameters(), Owner))
|
|
Invalid = true;
|
|
|
|
if (P->isInvalidDecl())
|
|
Invalid = true;
|
|
}
|
|
return Invalid;
|
|
}
|
|
|
|
void TemplateParameterList::getAssociatedConstraints(
|
|
llvm::SmallVectorImpl<AssociatedConstraint> &ACs) const {
|
|
if (HasConstrainedParameters)
|
|
for (const NamedDecl *Param : *this) {
|
|
if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
|
|
if (const auto *TC = TTP->getTypeConstraint())
|
|
ACs.emplace_back(TC->getImmediatelyDeclaredConstraint(),
|
|
TC->getArgPackSubstIndex());
|
|
} else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
|
|
if (const Expr *E = NTTP->getPlaceholderTypeConstraint())
|
|
ACs.emplace_back(E);
|
|
}
|
|
}
|
|
if (HasRequiresClause)
|
|
ACs.emplace_back(getRequiresClause());
|
|
}
|
|
|
|
bool TemplateParameterList::hasAssociatedConstraints() const {
|
|
return HasRequiresClause || HasConstrainedParameters;
|
|
}
|
|
|
|
ArrayRef<TemplateArgument>
|
|
TemplateParameterList::getInjectedTemplateArgs(const ASTContext &Context) {
|
|
if (!InjectedArgs) {
|
|
InjectedArgs = new (Context) TemplateArgument[size()];
|
|
llvm::transform(*this, InjectedArgs, [&](NamedDecl *ND) {
|
|
return Context.getInjectedTemplateArg(ND);
|
|
});
|
|
}
|
|
return {InjectedArgs, NumParams};
|
|
}
|
|
|
|
bool TemplateParameterList::shouldIncludeTypeForArgument(
|
|
const PrintingPolicy &Policy, const TemplateParameterList *TPL,
|
|
unsigned Idx) {
|
|
if (!TPL || Idx >= TPL->size() || Policy.AlwaysIncludeTypeForTemplateArgument)
|
|
return true;
|
|
const NamedDecl *TemplParam = TPL->getParam(Idx);
|
|
if (const auto *ParamValueDecl =
|
|
dyn_cast<NonTypeTemplateParmDecl>(TemplParam))
|
|
if (ParamValueDecl->getType()->getContainedDeducedType())
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
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<AssociatedConstraint> &ACs) const {
|
|
TemplateParams->getAssociatedConstraints(ACs);
|
|
if (auto *FD = dyn_cast_or_null<FunctionDecl>(getTemplatedDecl()))
|
|
if (const AssociatedConstraint &TRC = FD->getTrailingRequiresClause())
|
|
ACs.emplace_back(TRC);
|
|
}
|
|
|
|
bool TemplateDecl::hasAssociatedConstraints() const {
|
|
if (TemplateParams->hasAssociatedConstraints())
|
|
return true;
|
|
if (auto *FD = dyn_cast_or_null<FunctionDecl>(getTemplatedDecl()))
|
|
return static_cast<bool>(FD->getTrailingRequiresClause());
|
|
return false;
|
|
}
|
|
|
|
bool TemplateDecl::isTypeAlias() const {
|
|
switch (getKind()) {
|
|
case TemplateDecl::TypeAliasTemplate:
|
|
case TemplateDecl::BuiltinTemplate:
|
|
return true;
|
|
default:
|
|
return false;
|
|
};
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// 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(
|
|
bool OnlyPartial /*=false*/) const {
|
|
auto *ExternalSource = getASTContext().getExternalSource();
|
|
if (!ExternalSource)
|
|
return;
|
|
|
|
ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(),
|
|
OnlyPartial);
|
|
return;
|
|
}
|
|
|
|
bool RedeclarableTemplateDecl::loadLazySpecializationsImpl(
|
|
ArrayRef<TemplateArgument> Args, TemplateParameterList *TPL) const {
|
|
auto *ExternalSource = getASTContext().getExternalSource();
|
|
if (!ExternalSource)
|
|
return false;
|
|
|
|
// If TPL is not null, it implies that we're loading specializations for
|
|
// partial templates. We need to load all specializations in such cases.
|
|
if (TPL)
|
|
return ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(),
|
|
/*OnlyPartial=*/false);
|
|
|
|
return ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(),
|
|
Args);
|
|
}
|
|
|
|
template <class EntryType, typename... ProfileArguments>
|
|
typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
|
|
RedeclarableTemplateDecl::findSpecializationLocally(
|
|
llvm::FoldingSetVector<EntryType> &Specs, void *&InsertPos,
|
|
ProfileArguments &&...ProfileArgs) {
|
|
using SETraits = RedeclarableTemplateDecl::SpecEntryTraits<EntryType>;
|
|
|
|
llvm::FoldingSetNodeID ID;
|
|
EntryType::Profile(ID, std::forward<ProfileArguments>(ProfileArgs)...,
|
|
getASTContext());
|
|
EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos);
|
|
return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr;
|
|
}
|
|
|
|
template <class EntryType, typename... ProfileArguments>
|
|
typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
|
|
RedeclarableTemplateDecl::findSpecializationImpl(
|
|
llvm::FoldingSetVector<EntryType> &Specs, void *&InsertPos,
|
|
ProfileArguments &&...ProfileArgs) {
|
|
|
|
if (auto *Found = findSpecializationLocally(
|
|
Specs, InsertPos, std::forward<ProfileArguments>(ProfileArgs)...))
|
|
return Found;
|
|
|
|
if (!loadLazySpecializationsImpl(
|
|
std::forward<ProfileArguments>(ProfileArgs)...))
|
|
return nullptr;
|
|
|
|
return findSpecializationLocally(
|
|
Specs, InsertPos, std::forward<ProfileArguments>(ProfileArgs)...);
|
|
}
|
|
|
|
template<class Derived, class EntryType>
|
|
void RedeclarableTemplateDecl::addSpecializationImpl(
|
|
llvm::FoldingSetVector<EntryType> &Specializations, EntryType *Entry,
|
|
void *InsertPos) {
|
|
using SETraits = SpecEntryTraits<EntryType>;
|
|
|
|
if (InsertPos) {
|
|
#ifndef NDEBUG
|
|
auto Args = SETraits::getTemplateArgs(Entry);
|
|
// Due to hash collisions, it can happen that we load another template
|
|
// specialization with the same hash. This is fine, as long as the next
|
|
// call to findSpecializationImpl does not find a matching Decl for the
|
|
// template arguments.
|
|
loadLazySpecializationsImpl(Args);
|
|
void *CorrectInsertPos;
|
|
assert(!findSpecializationImpl(Specializations, CorrectInsertPos, Args) &&
|
|
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) {
|
|
bool Invalid = AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
|
|
auto *TD = new (C, DC) FunctionTemplateDecl(C, DC, L, Name, Params, Decl);
|
|
if (Invalid)
|
|
TD->setInvalidDecl();
|
|
return TD;
|
|
}
|
|
|
|
FunctionTemplateDecl *
|
|
FunctionTemplateDecl::CreateDeserialized(ASTContext &C, GlobalDeclID 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) {
|
|
auto *Common = getCommonPtr();
|
|
return findSpecializationImpl(Common->Specializations, InsertPos, Args);
|
|
}
|
|
|
|
void FunctionTemplateDecl::addSpecialization(
|
|
FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
|
|
auto *Common = getCommonPtr();
|
|
addSpecializationImpl<FunctionTemplateDecl>(Common->Specializations, Info,
|
|
InsertPos);
|
|
}
|
|
|
|
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) {
|
|
bool Invalid = AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
|
|
auto *TD = new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
|
|
if (Invalid)
|
|
TD->setInvalidDecl();
|
|
return TD;
|
|
}
|
|
|
|
ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
|
|
GlobalDeclID ID) {
|
|
return new (C, ID) ClassTemplateDecl(C, nullptr, SourceLocation(),
|
|
DeclarationName(), nullptr, nullptr);
|
|
}
|
|
|
|
void ClassTemplateDecl::LoadLazySpecializations(
|
|
bool OnlyPartial /*=false*/) const {
|
|
loadLazySpecializationsImpl(OnlyPartial);
|
|
}
|
|
|
|
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
|
|
ClassTemplateDecl::getSpecializations() const {
|
|
LoadLazySpecializations();
|
|
return getCommonPtr()->Specializations;
|
|
}
|
|
|
|
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
|
|
ClassTemplateDecl::getPartialSpecializations() const {
|
|
LoadLazySpecializations(/*PartialOnly = */ true);
|
|
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) {
|
|
auto *Common = getCommonPtr();
|
|
return findSpecializationImpl(Common->Specializations, InsertPos, Args);
|
|
}
|
|
|
|
void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D,
|
|
void *InsertPos) {
|
|
auto *Common = getCommonPtr();
|
|
addSpecializationImpl<ClassTemplateDecl>(Common->Specializations, D,
|
|
InsertPos);
|
|
}
|
|
|
|
ClassTemplatePartialSpecializationDecl *
|
|
ClassTemplateDecl::findPartialSpecialization(
|
|
ArrayRef<TemplateArgument> Args,
|
|
TemplateParameterList *TPL, void *&InsertPos) {
|
|
return findSpecializationImpl(getPartialSpecializations(), InsertPos, Args,
|
|
TPL);
|
|
}
|
|
|
|
void ClassTemplatePartialSpecializationDecl::Profile(
|
|
llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
|
|
TemplateParameterList *TPL, const ASTContext &Context) {
|
|
ID.AddInteger(TemplateArgs.size());
|
|
for (const TemplateArgument &TemplateArg : TemplateArgs)
|
|
TemplateArg.Profile(ID, Context);
|
|
TPL->Profile(ID, Context);
|
|
}
|
|
|
|
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) const {
|
|
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();
|
|
TemplateName Name = Context.getQualifiedTemplateName(
|
|
/*NNS=*/nullptr, /*TemplateKeyword=*/false, TemplateName(this));
|
|
CommonPtr->InjectedClassNameType = Context.getTemplateSpecializationType(
|
|
Name, getTemplateParameters()->getInjectedTemplateArgs(Context));
|
|
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, bool HasTypeConstraint,
|
|
UnsignedOrNone NumExpanded) {
|
|
auto *TTPDecl =
|
|
new (C, DC,
|
|
additionalSizeToAlloc<TypeConstraint>(HasTypeConstraint ? 1 : 0))
|
|
TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename,
|
|
HasTypeConstraint, NumExpanded);
|
|
QualType TTPType = C.getTemplateTypeParmType(D, P, ParameterPack, TTPDecl);
|
|
TTPDecl->setTypeForDecl(TTPType.getTypePtr());
|
|
return TTPDecl;
|
|
}
|
|
|
|
TemplateTypeParmDecl *
|
|
TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, GlobalDeclID ID) {
|
|
return new (C, ID)
|
|
TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), nullptr,
|
|
false, false, std::nullopt);
|
|
}
|
|
|
|
TemplateTypeParmDecl *
|
|
TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, GlobalDeclID ID,
|
|
bool HasTypeConstraint) {
|
|
return new (C, ID,
|
|
additionalSizeToAlloc<TypeConstraint>(HasTypeConstraint ? 1 : 0))
|
|
TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), nullptr,
|
|
false, HasTypeConstraint, std::nullopt);
|
|
}
|
|
|
|
SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const {
|
|
return hasDefaultArgument() ? getDefaultArgument().getLocation()
|
|
: SourceLocation();
|
|
}
|
|
|
|
SourceRange TemplateTypeParmDecl::getSourceRange() const {
|
|
if (hasDefaultArgument() && !defaultArgumentWasInherited())
|
|
return SourceRange(getBeginLoc(),
|
|
getDefaultArgument().getSourceRange().getEnd());
|
|
// TypeDecl::getSourceRange returns a range containing name location, which is
|
|
// wrong for unnamed template parameters. e.g:
|
|
// it will return <[[typename>]] instead of <[[typename]]>
|
|
if (getDeclName().isEmpty())
|
|
return SourceRange(getBeginLoc());
|
|
return TypeDecl::getSourceRange();
|
|
}
|
|
|
|
void TemplateTypeParmDecl::setDefaultArgument(
|
|
const ASTContext &C, const TemplateArgumentLoc &DefArg) {
|
|
if (DefArg.getArgument().isNull())
|
|
DefaultArgument.set(nullptr);
|
|
else
|
|
DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg));
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
void TemplateTypeParmDecl::setTypeConstraint(
|
|
ConceptReference *Loc, Expr *ImmediatelyDeclaredConstraint,
|
|
UnsignedOrNone ArgPackSubstIndex) {
|
|
assert(HasTypeConstraint &&
|
|
"HasTypeConstraint=true must be passed at construction in order to "
|
|
"call setTypeConstraint");
|
|
assert(!TypeConstraintInitialized &&
|
|
"TypeConstraint was already initialized!");
|
|
new (getTrailingObjects<TypeConstraint>())
|
|
TypeConstraint(Loc, ImmediatelyDeclaredConstraint, ArgPackSubstIndex);
|
|
TypeConstraintInitialized = true;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// NonTypeTemplateParmDecl Method Implementations
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
NonTypeTemplateParmDecl::NonTypeTemplateParmDecl(
|
|
DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D,
|
|
unsigned P, const 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, const IdentifierInfo *Id,
|
|
QualType T, bool ParameterPack, TypeSourceInfo *TInfo) {
|
|
AutoType *AT =
|
|
C.getLangOpts().CPlusPlus20 ? T->getContainedAutoType() : nullptr;
|
|
const bool HasConstraint = AT && AT->isConstrained();
|
|
auto *NTTP =
|
|
new (C, DC,
|
|
additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, Expr *>(
|
|
0, HasConstraint ? 1 : 0))
|
|
NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T,
|
|
ParameterPack, TInfo);
|
|
if (HasConstraint)
|
|
NTTP->setPlaceholderTypeConstraint(nullptr);
|
|
return NTTP;
|
|
}
|
|
|
|
NonTypeTemplateParmDecl *NonTypeTemplateParmDecl::Create(
|
|
const ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
|
SourceLocation IdLoc, unsigned D, unsigned P, const IdentifierInfo *Id,
|
|
QualType T, TypeSourceInfo *TInfo, ArrayRef<QualType> ExpandedTypes,
|
|
ArrayRef<TypeSourceInfo *> ExpandedTInfos) {
|
|
AutoType *AT = TInfo->getType()->getContainedAutoType();
|
|
const bool HasConstraint = AT && AT->isConstrained();
|
|
auto *NTTP =
|
|
new (C, DC,
|
|
additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, Expr *>(
|
|
ExpandedTypes.size(), HasConstraint ? 1 : 0))
|
|
NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T, TInfo,
|
|
ExpandedTypes, ExpandedTInfos);
|
|
if (HasConstraint)
|
|
NTTP->setPlaceholderTypeConstraint(nullptr);
|
|
return NTTP;
|
|
}
|
|
|
|
NonTypeTemplateParmDecl *
|
|
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
|
|
bool HasTypeConstraint) {
|
|
auto *NTTP =
|
|
new (C, ID,
|
|
additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, Expr *>(
|
|
0, HasTypeConstraint ? 1 : 0))
|
|
NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(),
|
|
0, 0, nullptr, QualType(), false, nullptr);
|
|
if (HasTypeConstraint)
|
|
NTTP->setPlaceholderTypeConstraint(nullptr);
|
|
return NTTP;
|
|
}
|
|
|
|
NonTypeTemplateParmDecl *
|
|
NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
|
|
unsigned NumExpandedTypes,
|
|
bool HasTypeConstraint) {
|
|
auto *NTTP =
|
|
new (C, ID,
|
|
additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, Expr *>(
|
|
NumExpandedTypes, HasTypeConstraint ? 1 : 0))
|
|
NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(),
|
|
0, 0, nullptr, QualType(), nullptr, {}, {});
|
|
NTTP->NumExpandedTypes = NumExpandedTypes;
|
|
if (HasTypeConstraint)
|
|
NTTP->setPlaceholderTypeConstraint(nullptr);
|
|
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();
|
|
}
|
|
|
|
void NonTypeTemplateParmDecl::setDefaultArgument(
|
|
const ASTContext &C, const TemplateArgumentLoc &DefArg) {
|
|
if (DefArg.getArgument().isNull())
|
|
DefaultArgument.set(nullptr);
|
|
else
|
|
DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg));
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// TemplateTemplateParmDecl Method Implementations
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void TemplateTemplateParmDecl::anchor() {}
|
|
|
|
TemplateTemplateParmDecl::TemplateTemplateParmDecl(
|
|
DeclContext *DC, SourceLocation L, unsigned D, unsigned P,
|
|
IdentifierInfo *Id, bool Typename, TemplateParameterList *Params,
|
|
ArrayRef<TemplateParameterList *> Expansions)
|
|
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
|
|
TemplateParmPosition(D, P), Typename(Typename), 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,
|
|
bool Typename, TemplateParameterList *Params) {
|
|
return new (C, DC) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id,
|
|
Typename, Params);
|
|
}
|
|
|
|
TemplateTemplateParmDecl *
|
|
TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC,
|
|
SourceLocation L, unsigned D, unsigned P,
|
|
IdentifierInfo *Id, bool Typename,
|
|
TemplateParameterList *Params,
|
|
ArrayRef<TemplateParameterList *> Expansions) {
|
|
return new (C, DC,
|
|
additionalSizeToAlloc<TemplateParameterList *>(Expansions.size()))
|
|
TemplateTemplateParmDecl(DC, L, D, P, Id, Typename, Params, Expansions);
|
|
}
|
|
|
|
TemplateTemplateParmDecl *
|
|
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
|
|
return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0,
|
|
false, nullptr, false, nullptr);
|
|
}
|
|
|
|
TemplateTemplateParmDecl *
|
|
TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID,
|
|
unsigned NumExpansions) {
|
|
auto *TTP =
|
|
new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(NumExpansions))
|
|
TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr,
|
|
false, nullptr, {});
|
|
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)
|
|
: 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, 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,
|
|
bool StrictPackMatch, ClassTemplateSpecializationDecl *PrevDecl)
|
|
: CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc,
|
|
SpecializedTemplate->getIdentifier(), PrevDecl),
|
|
SpecializedTemplate(SpecializedTemplate),
|
|
TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)),
|
|
SpecializationKind(TSK_Undeclared), StrictPackMatch(StrictPackMatch) {
|
|
assert(DK == Kind::ClassTemplateSpecialization || StrictPackMatch == false);
|
|
}
|
|
|
|
ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C,
|
|
Kind DK)
|
|
: CXXRecordDecl(DK, TagTypeKind::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, bool StrictPackMatch,
|
|
ClassTemplateSpecializationDecl *PrevDecl) {
|
|
auto *Result = new (Context, DC) ClassTemplateSpecializationDecl(
|
|
Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
|
|
SpecializedTemplate, Args, StrictPackMatch, PrevDecl);
|
|
Result->setMayHaveOutOfDateDef(false);
|
|
|
|
// If the template decl is incomplete, copy the external lexical storage from
|
|
// the base template. This allows instantiations of incomplete types to
|
|
// complete using the external AST if the template's declaration came from an
|
|
// external AST.
|
|
if (!SpecializedTemplate->getTemplatedDecl()->isCompleteDefinition())
|
|
Result->setHasExternalLexicalStorage(
|
|
SpecializedTemplate->getTemplatedDecl()->hasExternalLexicalStorage());
|
|
|
|
Context.getTypeDeclType(Result, PrevDecl);
|
|
return Result;
|
|
}
|
|
|
|
ClassTemplateSpecializationDecl *
|
|
ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
|
|
GlobalDeclID 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,
|
|
getSpecializedTemplate()->getTemplateParameters());
|
|
} else {
|
|
const TemplateArgumentList &TemplateArgs = getTemplateArgs();
|
|
printTemplateArgumentList(
|
|
OS, TemplateArgs.asArray(), Policy,
|
|
getSpecializedTemplate()->getTemplateParameters());
|
|
}
|
|
}
|
|
|
|
ClassTemplateDecl *
|
|
ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
|
|
if (const auto *PartialSpec =
|
|
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
|
|
return PartialSpec->PartialSpecialization->getSpecializedTemplate();
|
|
return cast<ClassTemplateDecl *>(SpecializedTemplate);
|
|
}
|
|
|
|
SourceRange
|
|
ClassTemplateSpecializationDecl::getSourceRange() const {
|
|
switch (getSpecializationKind()) {
|
|
case TSK_Undeclared:
|
|
case TSK_ImplicitInstantiation: {
|
|
llvm::PointerUnion<ClassTemplateDecl *,
|
|
ClassTemplatePartialSpecializationDecl *>
|
|
Pattern = getSpecializedTemplateOrPartial();
|
|
assert(!Pattern.isNull() &&
|
|
"Class template specialization without pattern?");
|
|
if (const auto *CTPSD =
|
|
dyn_cast<ClassTemplatePartialSpecializationDecl *>(Pattern))
|
|
return CTPSD->getSourceRange();
|
|
return cast<ClassTemplateDecl *>(Pattern)->getSourceRange();
|
|
}
|
|
case TSK_ExplicitSpecialization: {
|
|
SourceRange Range = CXXRecordDecl::getSourceRange();
|
|
if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten();
|
|
!isThisDeclarationADefinition() && Args)
|
|
Range.setEnd(Args->getRAngleLoc());
|
|
return Range;
|
|
}
|
|
case TSK_ExplicitInstantiationDeclaration:
|
|
case TSK_ExplicitInstantiationDefinition: {
|
|
SourceRange Range = CXXRecordDecl::getSourceRange();
|
|
if (SourceLocation ExternKW = getExternKeywordLoc(); ExternKW.isValid())
|
|
Range.setBegin(ExternKW);
|
|
else if (SourceLocation TemplateKW = getTemplateKeywordLoc();
|
|
TemplateKW.isValid())
|
|
Range.setBegin(TemplateKW);
|
|
if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten())
|
|
Range.setEnd(Args->getRAngleLoc());
|
|
return Range;
|
|
}
|
|
}
|
|
llvm_unreachable("unhandled template specialization kind");
|
|
}
|
|
|
|
void ClassTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) {
|
|
auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo);
|
|
if (!Info) {
|
|
// Don't allocate if the location is invalid.
|
|
if (Loc.isInvalid())
|
|
return;
|
|
Info = new (getASTContext()) ExplicitInstantiationInfo;
|
|
Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
|
|
ExplicitInfo = Info;
|
|
}
|
|
Info->ExternKeywordLoc = Loc;
|
|
}
|
|
|
|
void ClassTemplateSpecializationDecl::setTemplateKeywordLoc(
|
|
SourceLocation Loc) {
|
|
auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo);
|
|
if (!Info) {
|
|
// Don't allocate if the location is invalid.
|
|
if (Loc.isInvalid())
|
|
return;
|
|
Info = new (getASTContext()) ExplicitInstantiationInfo;
|
|
Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
|
|
ExplicitInfo = Info;
|
|
}
|
|
Info->TemplateKeywordLoc = Loc;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ConceptDecl Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
ConceptDecl *ConceptDecl::Create(ASTContext &C, DeclContext *DC,
|
|
SourceLocation L, DeclarationName Name,
|
|
TemplateParameterList *Params,
|
|
Expr *ConstraintExpr) {
|
|
bool Invalid = AdoptTemplateParameterList(Params, DC);
|
|
auto *TD = new (C, DC) ConceptDecl(DC, L, Name, Params, ConstraintExpr);
|
|
if (Invalid)
|
|
TD->setInvalidDecl();
|
|
return TD;
|
|
}
|
|
|
|
ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
|
|
ConceptDecl *Result = new (C, ID) ConceptDecl(nullptr, SourceLocation(),
|
|
DeclarationName(),
|
|
nullptr, nullptr);
|
|
|
|
return Result;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ImplicitConceptSpecializationDecl Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
ImplicitConceptSpecializationDecl::ImplicitConceptSpecializationDecl(
|
|
DeclContext *DC, SourceLocation SL,
|
|
ArrayRef<TemplateArgument> ConvertedArgs)
|
|
: Decl(ImplicitConceptSpecialization, DC, SL),
|
|
NumTemplateArgs(ConvertedArgs.size()) {
|
|
setTemplateArguments(ConvertedArgs);
|
|
}
|
|
|
|
ImplicitConceptSpecializationDecl::ImplicitConceptSpecializationDecl(
|
|
EmptyShell Empty, unsigned NumTemplateArgs)
|
|
: Decl(ImplicitConceptSpecialization, Empty),
|
|
NumTemplateArgs(NumTemplateArgs) {}
|
|
|
|
ImplicitConceptSpecializationDecl *ImplicitConceptSpecializationDecl::Create(
|
|
const ASTContext &C, DeclContext *DC, SourceLocation SL,
|
|
ArrayRef<TemplateArgument> ConvertedArgs) {
|
|
return new (C, DC,
|
|
additionalSizeToAlloc<TemplateArgument>(ConvertedArgs.size()))
|
|
ImplicitConceptSpecializationDecl(DC, SL, ConvertedArgs);
|
|
}
|
|
|
|
ImplicitConceptSpecializationDecl *
|
|
ImplicitConceptSpecializationDecl::CreateDeserialized(
|
|
const ASTContext &C, GlobalDeclID ID, unsigned NumTemplateArgs) {
|
|
return new (C, ID, additionalSizeToAlloc<TemplateArgument>(NumTemplateArgs))
|
|
ImplicitConceptSpecializationDecl(EmptyShell{}, NumTemplateArgs);
|
|
}
|
|
|
|
void ImplicitConceptSpecializationDecl::setTemplateArguments(
|
|
ArrayRef<TemplateArgument> Converted) {
|
|
assert(Converted.size() == NumTemplateArgs);
|
|
std::uninitialized_copy(Converted.begin(), Converted.end(),
|
|
getTrailingObjects<TemplateArgument>());
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ClassTemplatePartialSpecializationDecl Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
void ClassTemplatePartialSpecializationDecl::anchor() {}
|
|
|
|
ClassTemplatePartialSpecializationDecl::ClassTemplatePartialSpecializationDecl(
|
|
ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
|
|
SourceLocation IdLoc, TemplateParameterList *Params,
|
|
ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
|
|
ClassTemplatePartialSpecializationDecl *PrevDecl)
|
|
: ClassTemplateSpecializationDecl(
|
|
Context, ClassTemplatePartialSpecialization, TK, DC, StartLoc, IdLoc,
|
|
// Tracking StrictPackMatch for Partial
|
|
// Specializations is not needed.
|
|
SpecializedTemplate, Args, /*StrictPackMatch=*/false, PrevDecl),
|
|
TemplateParams(Params), InstantiatedFromMember(nullptr, false) {
|
|
if (AdoptTemplateParameterList(Params, this))
|
|
setInvalidDecl();
|
|
}
|
|
|
|
ClassTemplatePartialSpecializationDecl *
|
|
ClassTemplatePartialSpecializationDecl::Create(
|
|
ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
|
|
SourceLocation IdLoc, TemplateParameterList *Params,
|
|
ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
|
|
QualType CanonInjectedType,
|
|
ClassTemplatePartialSpecializationDecl *PrevDecl) {
|
|
auto *Result = new (Context, DC) ClassTemplatePartialSpecializationDecl(
|
|
Context, TK, DC, StartLoc, IdLoc, Params, SpecializedTemplate, Args,
|
|
PrevDecl);
|
|
Result->setSpecializationKind(TSK_ExplicitSpecialization);
|
|
Result->setMayHaveOutOfDateDef(false);
|
|
|
|
Context.getInjectedClassNameType(Result, CanonInjectedType);
|
|
return Result;
|
|
}
|
|
|
|
ClassTemplatePartialSpecializationDecl *
|
|
ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
|
|
GlobalDeclID ID) {
|
|
auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C);
|
|
Result->setMayHaveOutOfDateDef(false);
|
|
return Result;
|
|
}
|
|
|
|
SourceRange ClassTemplatePartialSpecializationDecl::getSourceRange() const {
|
|
if (const ClassTemplatePartialSpecializationDecl *MT =
|
|
getInstantiatedFromMember();
|
|
MT && !isMemberSpecialization())
|
|
return MT->getSourceRange();
|
|
SourceRange Range = ClassTemplateSpecializationDecl::getSourceRange();
|
|
if (const TemplateParameterList *TPL = getTemplateParameters();
|
|
TPL && !getNumTemplateParameterLists())
|
|
Range.setBegin(TPL->getTemplateLoc());
|
|
return Range;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// FriendTemplateDecl Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
void FriendTemplateDecl::anchor() {}
|
|
|
|
FriendTemplateDecl *
|
|
FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC,
|
|
SourceLocation L,
|
|
MutableArrayRef<TemplateParameterList *> Params,
|
|
FriendUnion Friend, SourceLocation FLoc) {
|
|
TemplateParameterList **TPL = nullptr;
|
|
if (!Params.empty()) {
|
|
TPL = new (Context) TemplateParameterList *[Params.size()];
|
|
llvm::copy(Params, TPL);
|
|
}
|
|
return new (Context, DC)
|
|
FriendTemplateDecl(DC, L, TPL, Params.size(), Friend, FLoc);
|
|
}
|
|
|
|
FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C,
|
|
GlobalDeclID ID) {
|
|
return new (C, ID) FriendTemplateDecl(EmptyShell());
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// TypeAliasTemplateDecl Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
TypeAliasTemplateDecl *
|
|
TypeAliasTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
|
|
DeclarationName Name,
|
|
TemplateParameterList *Params, NamedDecl *Decl) {
|
|
bool Invalid = AdoptTemplateParameterList(Params, DC);
|
|
auto *TD = new (C, DC) TypeAliasTemplateDecl(C, DC, L, Name, Params, Decl);
|
|
if (Invalid)
|
|
TD->setInvalidDecl();
|
|
return TD;
|
|
}
|
|
|
|
TypeAliasTemplateDecl *
|
|
TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C, GlobalDeclID 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;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// 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) {
|
|
bool Invalid = AdoptTemplateParameterList(Params, DC);
|
|
auto *TD = new (C, DC) VarTemplateDecl(C, DC, L, Name, Params, Decl);
|
|
if (Invalid)
|
|
TD->setInvalidDecl();
|
|
return TD;
|
|
}
|
|
|
|
VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
|
|
GlobalDeclID ID) {
|
|
return new (C, ID) VarTemplateDecl(C, nullptr, SourceLocation(),
|
|
DeclarationName(), nullptr, nullptr);
|
|
}
|
|
|
|
void VarTemplateDecl::LoadLazySpecializations(
|
|
bool OnlyPartial /*=false*/) const {
|
|
loadLazySpecializationsImpl(OnlyPartial);
|
|
}
|
|
|
|
llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
|
|
VarTemplateDecl::getSpecializations() const {
|
|
LoadLazySpecializations();
|
|
return getCommonPtr()->Specializations;
|
|
}
|
|
|
|
llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
|
|
VarTemplateDecl::getPartialSpecializations() const {
|
|
LoadLazySpecializations(/*PartialOnly = */ true);
|
|
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) {
|
|
auto *Common = getCommonPtr();
|
|
return findSpecializationImpl(Common->Specializations, InsertPos, Args);
|
|
}
|
|
|
|
void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D,
|
|
void *InsertPos) {
|
|
auto *Common = getCommonPtr();
|
|
addSpecializationImpl<VarTemplateDecl>(Common->Specializations, D, InsertPos);
|
|
}
|
|
|
|
VarTemplatePartialSpecializationDecl *
|
|
VarTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args,
|
|
TemplateParameterList *TPL, void *&InsertPos) {
|
|
return findSpecializationImpl(getPartialSpecializations(), InsertPos, Args,
|
|
TPL);
|
|
}
|
|
|
|
void VarTemplatePartialSpecializationDecl::Profile(
|
|
llvm::FoldingSetNodeID &ID, ArrayRef<TemplateArgument> TemplateArgs,
|
|
TemplateParameterList *TPL, const ASTContext &Context) {
|
|
ID.AddInteger(TemplateArgs.size());
|
|
for (const TemplateArgument &TemplateArg : TemplateArgs)
|
|
TemplateArg.Profile(ID, Context);
|
|
TPL->Profile(ID, Context);
|
|
}
|
|
|
|
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) const {
|
|
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,
|
|
GlobalDeclID 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,
|
|
getSpecializedTemplate()->getTemplateParameters());
|
|
} else {
|
|
const TemplateArgumentList &TemplateArgs = getTemplateArgs();
|
|
printTemplateArgumentList(
|
|
OS, TemplateArgs.asArray(), Policy,
|
|
getSpecializedTemplate()->getTemplateParameters());
|
|
}
|
|
}
|
|
|
|
VarTemplateDecl *VarTemplateSpecializationDecl::getSpecializedTemplate() const {
|
|
if (const auto *PartialSpec =
|
|
SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
|
|
return PartialSpec->PartialSpecialization->getSpecializedTemplate();
|
|
return cast<VarTemplateDecl *>(SpecializedTemplate);
|
|
}
|
|
|
|
SourceRange VarTemplateSpecializationDecl::getSourceRange() const {
|
|
switch (getSpecializationKind()) {
|
|
case TSK_Undeclared:
|
|
case TSK_ImplicitInstantiation: {
|
|
llvm::PointerUnion<VarTemplateDecl *,
|
|
VarTemplatePartialSpecializationDecl *>
|
|
Pattern = getSpecializedTemplateOrPartial();
|
|
assert(!Pattern.isNull() &&
|
|
"Variable template specialization without pattern?");
|
|
if (const auto *VTPSD =
|
|
dyn_cast<VarTemplatePartialSpecializationDecl *>(Pattern))
|
|
return VTPSD->getSourceRange();
|
|
VarTemplateDecl *VTD = cast<VarTemplateDecl *>(Pattern);
|
|
if (hasInit()) {
|
|
if (VarTemplateDecl *Definition = VTD->getDefinition())
|
|
return Definition->getSourceRange();
|
|
}
|
|
return VTD->getCanonicalDecl()->getSourceRange();
|
|
}
|
|
case TSK_ExplicitSpecialization: {
|
|
SourceRange Range = VarDecl::getSourceRange();
|
|
if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten();
|
|
!hasInit() && Args)
|
|
Range.setEnd(Args->getRAngleLoc());
|
|
return Range;
|
|
}
|
|
case TSK_ExplicitInstantiationDeclaration:
|
|
case TSK_ExplicitInstantiationDefinition: {
|
|
SourceRange Range = VarDecl::getSourceRange();
|
|
if (SourceLocation ExternKW = getExternKeywordLoc(); ExternKW.isValid())
|
|
Range.setBegin(ExternKW);
|
|
else if (SourceLocation TemplateKW = getTemplateKeywordLoc();
|
|
TemplateKW.isValid())
|
|
Range.setBegin(TemplateKW);
|
|
if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten())
|
|
Range.setEnd(Args->getRAngleLoc());
|
|
return Range;
|
|
}
|
|
}
|
|
llvm_unreachable("unhandled template specialization kind");
|
|
}
|
|
|
|
void VarTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) {
|
|
auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo);
|
|
if (!Info) {
|
|
// Don't allocate if the location is invalid.
|
|
if (Loc.isInvalid())
|
|
return;
|
|
Info = new (getASTContext()) ExplicitInstantiationInfo;
|
|
Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
|
|
ExplicitInfo = Info;
|
|
}
|
|
Info->ExternKeywordLoc = Loc;
|
|
}
|
|
|
|
void VarTemplateSpecializationDecl::setTemplateKeywordLoc(SourceLocation Loc) {
|
|
auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo);
|
|
if (!Info) {
|
|
// Don't allocate if the location is invalid.
|
|
if (Loc.isInvalid())
|
|
return;
|
|
Info = new (getASTContext()) ExplicitInstantiationInfo;
|
|
Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
|
|
ExplicitInfo = Info;
|
|
}
|
|
Info->TemplateKeywordLoc = 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)
|
|
: VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context,
|
|
DC, StartLoc, IdLoc, SpecializedTemplate, T,
|
|
TInfo, S, Args),
|
|
TemplateParams(Params), InstantiatedFromMember(nullptr, false) {
|
|
if (AdoptTemplateParameterList(Params, DC))
|
|
setInvalidDecl();
|
|
}
|
|
|
|
VarTemplatePartialSpecializationDecl *
|
|
VarTemplatePartialSpecializationDecl::Create(
|
|
ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
|
|
SourceLocation IdLoc, TemplateParameterList *Params,
|
|
VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
|
|
StorageClass S, ArrayRef<TemplateArgument> Args) {
|
|
auto *Result = new (Context, DC) VarTemplatePartialSpecializationDecl(
|
|
Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo, S,
|
|
Args);
|
|
Result->setSpecializationKind(TSK_ExplicitSpecialization);
|
|
return Result;
|
|
}
|
|
|
|
VarTemplatePartialSpecializationDecl *
|
|
VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
|
|
GlobalDeclID ID) {
|
|
return new (C, ID) VarTemplatePartialSpecializationDecl(C);
|
|
}
|
|
|
|
SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const {
|
|
if (const VarTemplatePartialSpecializationDecl *MT =
|
|
getInstantiatedFromMember();
|
|
MT && !isMemberSpecialization())
|
|
return MT->getSourceRange();
|
|
SourceRange Range = VarTemplateSpecializationDecl::getSourceRange();
|
|
if (const TemplateParameterList *TPL = getTemplateParameters();
|
|
TPL && !getNumTemplateParameterLists())
|
|
Range.setBegin(TPL->getTemplateLoc());
|
|
return Range;
|
|
}
|
|
|
|
static TemplateParameterList *createBuiltinTemplateParameterList(
|
|
const ASTContext &C, DeclContext *DC, BuiltinTemplateKind BTK) {
|
|
switch (BTK) {
|
|
#define CREATE_BUILTIN_TEMPLATE_PARAMETER_LIST
|
|
#include "clang/Basic/BuiltinTemplates.inc"
|
|
}
|
|
|
|
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) {}
|
|
|
|
TemplateParamObjectDecl *TemplateParamObjectDecl::Create(const ASTContext &C,
|
|
QualType T,
|
|
const APValue &V) {
|
|
DeclContext *DC = C.getTranslationUnitDecl();
|
|
auto *TPOD = new (C, DC) TemplateParamObjectDecl(DC, T, V);
|
|
C.addDestruction(&TPOD->Value);
|
|
return TPOD;
|
|
}
|
|
|
|
TemplateParamObjectDecl *
|
|
TemplateParamObjectDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
|
|
auto *TPOD = new (C, ID) TemplateParamObjectDecl(nullptr, QualType(), APValue());
|
|
C.addDestruction(&TPOD->Value);
|
|
return TPOD;
|
|
}
|
|
|
|
void TemplateParamObjectDecl::printName(llvm::raw_ostream &OS,
|
|
const PrintingPolicy &Policy) const {
|
|
OS << "<template param ";
|
|
printAsExpr(OS, Policy);
|
|
OS << ">";
|
|
}
|
|
|
|
void TemplateParamObjectDecl::printAsExpr(llvm::raw_ostream &OS) const {
|
|
printAsExpr(OS, getASTContext().getPrintingPolicy());
|
|
}
|
|
|
|
void TemplateParamObjectDecl::printAsExpr(llvm::raw_ostream &OS,
|
|
const PrintingPolicy &Policy) const {
|
|
getType().getUnqualifiedType().print(OS, Policy);
|
|
printAsInit(OS, Policy);
|
|
}
|
|
|
|
void TemplateParamObjectDecl::printAsInit(llvm::raw_ostream &OS) const {
|
|
printAsInit(OS, getASTContext().getPrintingPolicy());
|
|
}
|
|
|
|
void TemplateParamObjectDecl::printAsInit(llvm::raw_ostream &OS,
|
|
const PrintingPolicy &Policy) const {
|
|
getValue().printPretty(OS, Policy, getType(), &getASTContext());
|
|
}
|
|
|
|
TemplateParameterList *clang::getReplacedTemplateParameterList(const Decl *D) {
|
|
switch (D->getKind()) {
|
|
case Decl::Kind::CXXRecord:
|
|
return cast<CXXRecordDecl>(D)
|
|
->getDescribedTemplate()
|
|
->getTemplateParameters();
|
|
case Decl::Kind::ClassTemplate:
|
|
return cast<ClassTemplateDecl>(D)->getTemplateParameters();
|
|
case Decl::Kind::ClassTemplateSpecialization: {
|
|
const auto *CTSD = cast<ClassTemplateSpecializationDecl>(D);
|
|
auto P = CTSD->getSpecializedTemplateOrPartial();
|
|
if (const auto *CTPSD =
|
|
dyn_cast<ClassTemplatePartialSpecializationDecl *>(P))
|
|
return CTPSD->getTemplateParameters();
|
|
return cast<ClassTemplateDecl *>(P)->getTemplateParameters();
|
|
}
|
|
case Decl::Kind::ClassTemplatePartialSpecialization:
|
|
return cast<ClassTemplatePartialSpecializationDecl>(D)
|
|
->getTemplateParameters();
|
|
case Decl::Kind::TypeAliasTemplate:
|
|
return cast<TypeAliasTemplateDecl>(D)->getTemplateParameters();
|
|
case Decl::Kind::BuiltinTemplate:
|
|
return cast<BuiltinTemplateDecl>(D)->getTemplateParameters();
|
|
case Decl::Kind::CXXDeductionGuide:
|
|
case Decl::Kind::CXXConversion:
|
|
case Decl::Kind::CXXConstructor:
|
|
case Decl::Kind::CXXDestructor:
|
|
case Decl::Kind::CXXMethod:
|
|
case Decl::Kind::Function:
|
|
return cast<FunctionDecl>(D)
|
|
->getTemplateSpecializationInfo()
|
|
->getTemplate()
|
|
->getTemplateParameters();
|
|
case Decl::Kind::FunctionTemplate:
|
|
return cast<FunctionTemplateDecl>(D)->getTemplateParameters();
|
|
case Decl::Kind::VarTemplate:
|
|
return cast<VarTemplateDecl>(D)->getTemplateParameters();
|
|
case Decl::Kind::VarTemplateSpecialization: {
|
|
const auto *VTSD = cast<VarTemplateSpecializationDecl>(D);
|
|
auto P = VTSD->getSpecializedTemplateOrPartial();
|
|
if (const auto *VTPSD = dyn_cast<VarTemplatePartialSpecializationDecl *>(P))
|
|
return VTPSD->getTemplateParameters();
|
|
return cast<VarTemplateDecl *>(P)->getTemplateParameters();
|
|
}
|
|
case Decl::Kind::VarTemplatePartialSpecialization:
|
|
return cast<VarTemplatePartialSpecializationDecl>(D)
|
|
->getTemplateParameters();
|
|
case Decl::Kind::TemplateTemplateParm:
|
|
return cast<TemplateTemplateParmDecl>(D)->getTemplateParameters();
|
|
case Decl::Kind::Concept:
|
|
return cast<ConceptDecl>(D)->getTemplateParameters();
|
|
default:
|
|
llvm_unreachable("Unhandled templated declaration kind");
|
|
}
|
|
}
|