diff options
author | 2020-08-03 14:31:31 +0000 | |
---|---|---|
committer | 2020-08-03 14:31:31 +0000 | |
commit | e5dd70708596ae51455a0ffa086a00c5b29f8583 (patch) | |
tree | 5d676f27b570bacf71e786c3b5cff3e6f6679b59 /gnu/llvm/clang/lib/AST/DeclTemplate.cpp | |
parent | Import LLVM 10.0.0 release including clang, lld and lldb. (diff) | |
download | wireguard-openbsd-e5dd70708596ae51455a0ffa086a00c5b29f8583.tar.xz wireguard-openbsd-e5dd70708596ae51455a0ffa086a00c5b29f8583.zip |
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom
tested by plenty
Diffstat (limited to 'gnu/llvm/clang/lib/AST/DeclTemplate.cpp')
-rwxr-xr-x | gnu/llvm/clang/lib/AST/DeclTemplate.cpp | 1433 |
1 files changed, 1433 insertions, 0 deletions
diff --git a/gnu/llvm/clang/lib/AST/DeclTemplate.cpp b/gnu/llvm/clang/lib/AST/DeclTemplate.cpp new file mode 100755 index 00000000000..b5e4ec2d7f4 --- /dev/null +++ b/gnu/llvm/clang/lib/AST/DeclTemplate.cpp @@ -0,0 +1,1433 @@ +//===- 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(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()) + ContainsUnexpandedParameterPack = true; + if (NTTP->hasPlaceholderTypeConstraint()) + HasConstrainedParameters = true; + } else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P)) { + if (!IsPack && + TTP->getTemplateParameters()->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + } else if (const TypeConstraint *TC = + cast<TemplateTypeParmDecl>(P)->getTypeConstraint()) { + if (TC->getImmediatelyDeclaredConstraint() + ->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + HasConstrainedParameters = true; + } + // FIXME: If a default argument contains an unexpanded parameter pack, the + // template parameter list does too. + } + + if (HasRequiresClause) { + if (RequiresClause->containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + *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(C, 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; + } + } else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) { + if (TTP->isExpandedParameterPack()) { + NumRequiredArgs += TTP->getNumExpansionParameters(); + continue; + } + } else { + const auto *TP = cast<TemplateTemplateParmDecl>(P); + if (TP->isExpandedParameterPack()) { + NumRequiredArgs += TP->getNumExpansionTemplateParameters(); + continue; + } + } + + break; + } + + if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) { + if (TTP->hasDefaultArgument()) + break; + } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) { + if (NTTP->hasDefaultArgument()) + break; + } else if (cast<TemplateTemplateParmDecl>(P)->hasDefaultArgument()) + break; + + ++NumRequiredArgs; + } + + return NumRequiredArgs; +} + +unsigned TemplateParameterList::getDepth() const { + if (size() == 0) + return 0; + + const NamedDecl *FirstParm = getParam(0); + if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(FirstParm)) + return TTP->getDepth(); + else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(FirstParm)) + return NTTP->getDepth(); + else + return cast<TemplateTemplateParmDecl>(FirstParm)->getDepth(); +} + +static void AdoptTemplateParameterList(TemplateParameterList *Params, + DeclContext *Owner) { + for (NamedDecl *P : *Params) { + P->setDeclContext(Owner); + + if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P)) + AdoptTemplateParameterList(TTP->getTemplateParameters(), Owner); + } +} + +void TemplateParameterList:: +getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const { + if (HasConstrainedParameters) + for (const NamedDecl *Param : *this) { + if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { + if (const auto *TC = TTP->getTypeConstraint()) + AC.push_back(TC->getImmediatelyDeclaredConstraint()); + } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + if (const Expr *E = NTTP->getPlaceholderTypeConstraint()) + AC.push_back(E); + } + } + if (HasRequiresClause) + AC.push_back(getRequiresClause()); +} + +bool TemplateParameterList::hasAssociatedConstraints() const { + return HasRequiresClause || HasConstrainedParameters; +} + +namespace clang { + +void *allocateDefaultArgStorageChain(const ASTContext &C) { + return new (C) char[sizeof(void*) * 2]; +} + +} // namespace clang + +//===----------------------------------------------------------------------===// +// TemplateDecl Implementation +//===----------------------------------------------------------------------===// + +TemplateDecl::TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params, + NamedDecl *Decl) + : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), TemplateParams(Params) {} + +void TemplateDecl::anchor() {} + +void TemplateDecl:: +getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const { + TemplateParams->getAssociatedConstraints(AC); + if (auto *FD = dyn_cast_or_null<FunctionDecl>(getTemplatedDecl())) + if (const Expr *TRC = FD->getTrailingRequiresClause()) + AC.push_back(TRC); +} + +bool TemplateDecl::hasAssociatedConstraints() const { + if (TemplateParams->hasAssociatedConstraints()) + return true; + if (auto *FD = dyn_cast_or_null<FunctionDecl>(getTemplatedDecl())) + return FD->getTrailingRequiresClause(); + 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() 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... ProfileArguments> +typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType * +RedeclarableTemplateDecl::findSpecializationImpl( + llvm::FoldingSetVector<EntryType> &Specs, void *&InsertPos, + ProfileArguments&&... ProfileArgs) { + using SETraits = 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 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, + CorrectInsertPos, + SETraits::getTemplateArgs(Entry)) && + 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(), InsertPos, Args); +} + +void FunctionTemplateDecl::addSpecialization( + FunctionTemplateSpecializationInfo *Info, void *InsertPos) { + addSpecializationImpl<FunctionTemplateDecl>(getSpecializations(), Info, + InsertPos); +} + +ArrayRef<TemplateArgument> FunctionTemplateDecl::getInjectedTemplateArgs() { + TemplateParameterList *Params = getTemplateParameters(); + Common *CommonPtr = getCommonPtr(); + if (!CommonPtr->InjectedArgs) { + auto &Context = getASTContext(); + SmallVector<TemplateArgument, 16> TemplateArgs; + Context.getInjectedTemplateArgs(Params, TemplateArgs); + CommonPtr->InjectedArgs = + new (Context) TemplateArgument[TemplateArgs.size()]; + std::copy(TemplateArgs.begin(), TemplateArgs.end(), + CommonPtr->InjectedArgs); + } + + return llvm::makeArrayRef(CommonPtr->InjectedArgs, Params->size()); +} + +void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) { + using Base = RedeclarableTemplateDecl; + + // If we haven't created a common pointer yet, then it can just be created + // with the usual method. + if (!Base::Common) + return; + + Common *ThisCommon = static_cast<Common *>(Base::Common); + Common *PrevCommon = nullptr; + SmallVector<FunctionTemplateDecl *, 8> PreviousDecls; + for (; Prev; Prev = Prev->getPreviousDecl()) { + if (Prev->Base::Common) { + PrevCommon = static_cast<Common *>(Prev->Base::Common); + break; + } + PreviousDecls.push_back(Prev); + } + + // If the previous redecl chain hasn't created a common pointer yet, then just + // use this common pointer. + if (!PrevCommon) { + for (auto *D : PreviousDecls) + D->Base::Common = ThisCommon; + return; + } + + // Ensure we don't leak any important state. + assert(ThisCommon->Specializations.size() == 0 && + "Can't merge incompatible declarations!"); + + Base::Common = PrevCommon; +} + +//===----------------------------------------------------------------------===// +// ClassTemplateDecl Implementation +//===----------------------------------------------------------------------===// + +ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, + DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl) { + AdoptTemplateParameterList(Params, cast<DeclContext>(Decl)); + + return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl); +} + +ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) ClassTemplateDecl(C, nullptr, SourceLocation(), + DeclarationName(), nullptr, nullptr); +} + +void ClassTemplateDecl::LoadLazySpecializations() const { + loadLazySpecializationsImpl(); +} + +llvm::FoldingSetVector<ClassTemplateSpecializationDecl> & +ClassTemplateDecl::getSpecializations() const { + LoadLazySpecializations(); + return getCommonPtr()->Specializations; +} + +llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> & +ClassTemplateDecl::getPartialSpecializations() { + LoadLazySpecializations(); + return getCommonPtr()->PartialSpecializations; +} + +RedeclarableTemplateDecl::CommonBase * +ClassTemplateDecl::newCommon(ASTContext &C) const { + auto *CommonPtr = new (C) Common; + C.addDestruction(CommonPtr); + return CommonPtr; +} + +ClassTemplateSpecializationDecl * +ClassTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args, + void *&InsertPos) { + return findSpecializationImpl(getSpecializations(), InsertPos, Args); +} + +void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D, + void *InsertPos) { + addSpecializationImpl<ClassTemplateDecl>(getSpecializations(), D, InsertPos); +} + +ClassTemplatePartialSpecializationDecl * +ClassTemplateDecl::findPartialSpecialization( + ArrayRef<TemplateArgument> Args, + TemplateParameterList *TPL, void *&InsertPos) { + return findSpecializationImpl(getPartialSpecializations(), InsertPos, Args, + TPL); +} + +static void ProfileTemplateParameterList(ASTContext &C, + llvm::FoldingSetNodeID &ID, const TemplateParameterList *TPL) { + const Expr *RC = TPL->getRequiresClause(); + ID.AddBoolean(RC != nullptr); + if (RC) + RC->Profile(ID, C, /*Canonical=*/true); + ID.AddInteger(TPL->size()); + for (NamedDecl *D : *TPL) { + if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { + ID.AddInteger(0); + ID.AddBoolean(NTTP->isParameterPack()); + NTTP->getType().getCanonicalType().Profile(ID); + 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()); + ProfileTemplateParameterList(C, ID, TTP->getTemplateParameters()); + } +} + +void +ClassTemplatePartialSpecializationDecl::Profile(llvm::FoldingSetNodeID &ID, + ArrayRef<TemplateArgument> TemplateArgs, TemplateParameterList *TPL, + ASTContext &Context) { + ID.AddInteger(TemplateArgs.size()); + for (const TemplateArgument &TemplateArg : TemplateArgs) + TemplateArg.Profile(ID, Context); + ProfileTemplateParameterList(Context, ID, TPL); +} + +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, + bool HasTypeConstraint, + Optional<unsigned> 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, unsigned ID) { + return new (C, ID) TemplateTypeParmDecl(nullptr, SourceLocation(), + SourceLocation(), nullptr, false, + false, None); +} + +TemplateTypeParmDecl * +TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID, + bool HasTypeConstraint) { + return new (C, ID, + additionalSizeToAlloc<TypeConstraint>(HasTypeConstraint ? 1 : 0)) + TemplateTypeParmDecl(nullptr, SourceLocation(), SourceLocation(), + nullptr, false, HasTypeConstraint, None); +} + +SourceLocation TemplateTypeParmDecl::getDefaultArgumentLoc() const { + return hasDefaultArgument() + ? getDefaultArgumentInfo()->getTypeLoc().getBeginLoc() + : SourceLocation(); +} + +SourceRange TemplateTypeParmDecl::getSourceRange() const { + if (hasDefaultArgument() && !defaultArgumentWasInherited()) + return SourceRange(getBeginLoc(), + getDefaultArgumentInfo()->getTypeLoc().getEndLoc()); + // TypeDecl::getSourceRange returns a range containing name location, which is + // wrong for unnamed template parameters. e.g: + // it will return <[[typename>]] instead of <[[typename]]> + else if (getDeclName().isEmpty()) + return SourceRange(getBeginLoc()); + return TypeDecl::getSourceRange(); +} + +unsigned TemplateTypeParmDecl::getDepth() const { + return getTypeForDecl()->castAs<TemplateTypeParmType>()->getDepth(); +} + +unsigned TemplateTypeParmDecl::getIndex() const { + return getTypeForDecl()->castAs<TemplateTypeParmType>()->getIndex(); +} + +bool TemplateTypeParmDecl::isParameterPack() const { + return getTypeForDecl()->castAs<TemplateTypeParmType>()->isParameterPack(); +} + +void TemplateTypeParmDecl::setTypeConstraint(NestedNameSpecifierLoc NNS, + DeclarationNameInfo NameInfo, NamedDecl *FoundDecl, ConceptDecl *CD, + const ASTTemplateArgumentListInfo *ArgsAsWritten, + Expr *ImmediatelyDeclaredConstraint) { + assert(HasTypeConstraint && + "HasTypeConstraint=true must be passed at construction in order to " + "call setTypeConstraint"); + assert(!TypeConstraintInitialized && + "TypeConstraint was already initialized!"); + new (getTrailingObjects<TypeConstraint>()) TypeConstraint(NNS, NameInfo, + FoundDecl, CD, ArgsAsWritten, ImmediatelyDeclaredConstraint); + TypeConstraintInitialized = true; +} + +//===----------------------------------------------------------------------===// +// 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) { + AutoType *AT = + C.getLangOpts().CPlusPlus2a ? T->getContainedAutoType() : nullptr; + return new (C, DC, + additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, + Expr *>(0, + AT && AT->isConstrained() ? 1 : 0)) + 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) { + AutoType *AT = TInfo->getType()->getContainedAutoType(); + return new (C, DC, + additionalSizeToAlloc<std::pair<QualType, TypeSourceInfo *>, + Expr *>( + ExpandedTypes.size(), AT && AT->isConstrained() ? 1 : 0)) + NonTypeTemplateParmDecl(DC, StartLoc, IdLoc, D, P, Id, T, TInfo, + ExpandedTypes, ExpandedTInfos); +} + +NonTypeTemplateParmDecl * +NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID, + bool HasTypeConstraint) { + return new (C, ID, additionalSizeToAlloc<std::pair<QualType, + TypeSourceInfo *>, + Expr *>(0, + HasTypeConstraint ? 1 : 0)) + NonTypeTemplateParmDecl(nullptr, SourceLocation(), SourceLocation(), + 0, 0, nullptr, QualType(), false, nullptr); +} + +NonTypeTemplateParmDecl * +NonTypeTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned 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, None, + None); + NTTP->NumExpandedTypes = NumExpandedTypes; + return NTTP; +} + +SourceRange NonTypeTemplateParmDecl::getSourceRange() const { + if (hasDefaultArgument() && !defaultArgumentWasInherited()) + return SourceRange(getOuterLocStart(), + getDefaultArgument()->getSourceRange().getEnd()); + return DeclaratorDecl::getSourceRange(); +} + +SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const { + return hasDefaultArgument() + ? getDefaultArgument()->getSourceRange().getBegin() + : SourceLocation(); +} + +//===----------------------------------------------------------------------===// +// TemplateTemplateParmDecl Method Implementations +//===----------------------------------------------------------------------===// + +void TemplateTemplateParmDecl::anchor() {} + +TemplateTemplateParmDecl::TemplateTemplateParmDecl( + DeclContext *DC, SourceLocation L, unsigned D, unsigned P, + IdentifierInfo *Id, TemplateParameterList *Params, + ArrayRef<TemplateParameterList *> Expansions) + : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), + TemplateParmPosition(D, P), ParameterPack(true), + ExpandedParameterPack(true), NumExpandedParams(Expansions.size()) { + if (!Expansions.empty()) + std::uninitialized_copy(Expansions.begin(), Expansions.end(), + getTrailingObjects<TemplateParameterList *>()); +} + +TemplateTemplateParmDecl * +TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, unsigned P, + bool ParameterPack, IdentifierInfo *Id, + TemplateParameterList *Params) { + return new (C, DC) TemplateTemplateParmDecl(DC, L, D, P, ParameterPack, Id, + Params); +} + +TemplateTemplateParmDecl * +TemplateTemplateParmDecl::Create(const ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, unsigned P, + IdentifierInfo *Id, + TemplateParameterList *Params, + ArrayRef<TemplateParameterList *> Expansions) { + return new (C, DC, + additionalSizeToAlloc<TemplateParameterList *>(Expansions.size())) + TemplateTemplateParmDecl(DC, L, D, P, Id, Params, Expansions); +} + +TemplateTemplateParmDecl * +TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID) { + return new (C, ID) TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, + false, nullptr, nullptr); +} + +TemplateTemplateParmDecl * +TemplateTemplateParmDecl::CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NumExpansions) { + auto *TTP = + new (C, ID, additionalSizeToAlloc<TemplateParameterList *>(NumExpansions)) + TemplateTemplateParmDecl(nullptr, SourceLocation(), 0, 0, nullptr, + nullptr, None); + TTP->NumExpandedParams = NumExpansions; + return TTP; +} + +SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const { + return hasDefaultArgument() ? getDefaultArgument().getLocation() + : SourceLocation(); +} + +void TemplateTemplateParmDecl::setDefaultArgument( + const ASTContext &C, const TemplateArgumentLoc &DefArg) { + if (DefArg.getArgument().isNull()) + DefaultArgument.set(nullptr); + else + DefaultArgument.set(new (C) TemplateArgumentLoc(DefArg)); +} + +//===----------------------------------------------------------------------===// +// TemplateArgumentList Implementation +//===----------------------------------------------------------------------===// +TemplateArgumentList::TemplateArgumentList(ArrayRef<TemplateArgument> Args) + : Arguments(getTrailingObjects<TemplateArgument>()), + NumArguments(Args.size()) { + std::uninitialized_copy(Args.begin(), Args.end(), + getTrailingObjects<TemplateArgument>()); +} + +TemplateArgumentList * +TemplateArgumentList::CreateCopy(ASTContext &Context, + ArrayRef<TemplateArgument> Args) { + void *Mem = Context.Allocate(totalSizeToAlloc<TemplateArgument>(Args.size())); + return new (Mem) TemplateArgumentList(Args); +} + +FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create( + ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template, + TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs, + const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI, + MemberSpecializationInfo *MSInfo) { + const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; + if (TemplateArgsAsWritten) + ArgsAsWritten = ASTTemplateArgumentListInfo::Create(C, + *TemplateArgsAsWritten); + + void *Mem = + C.Allocate(totalSizeToAlloc<MemberSpecializationInfo *>(MSInfo ? 1 : 0)); + return new (Mem) FunctionTemplateSpecializationInfo( + FD, Template, TSK, TemplateArgs, ArgsAsWritten, POI, MSInfo); +} + +//===----------------------------------------------------------------------===// +// ClassTemplateSpecializationDecl Implementation +//===----------------------------------------------------------------------===// + +ClassTemplateSpecializationDecl:: +ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, + ClassTemplateDecl *SpecializedTemplate, + ArrayRef<TemplateArgument> Args, + ClassTemplateSpecializationDecl *PrevDecl) + : CXXRecordDecl(DK, TK, Context, DC, StartLoc, IdLoc, + SpecializedTemplate->getIdentifier(), PrevDecl), + SpecializedTemplate(SpecializedTemplate), + TemplateArgs(TemplateArgumentList::CreateCopy(Context, Args)), + SpecializationKind(TSK_Undeclared) { +} + +ClassTemplateSpecializationDecl::ClassTemplateSpecializationDecl(ASTContext &C, + Kind DK) + : CXXRecordDecl(DK, TTK_Struct, C, nullptr, SourceLocation(), + SourceLocation(), nullptr, nullptr), + SpecializationKind(TSK_Undeclared) {} + +ClassTemplateSpecializationDecl * +ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK, + DeclContext *DC, + SourceLocation StartLoc, + SourceLocation IdLoc, + ClassTemplateDecl *SpecializedTemplate, + ArrayRef<TemplateArgument> Args, + ClassTemplateSpecializationDecl *PrevDecl) { + auto *Result = + new (Context, DC) ClassTemplateSpecializationDecl( + Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc, + SpecializedTemplate, Args, PrevDecl); + Result->setMayHaveOutOfDateDef(false); + + Context.getTypeDeclType(Result, PrevDecl); + return Result; +} + +ClassTemplateSpecializationDecl * +ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + auto *Result = + new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization); + Result->setMayHaveOutOfDateDef(false); + return Result; +} + +void ClassTemplateSpecializationDecl::getNameForDiagnostic( + raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const { + NamedDecl::getNameForDiagnostic(OS, Policy, Qualified); + + const auto *PS = dyn_cast<ClassTemplatePartialSpecializationDecl>(this); + if (const ASTTemplateArgumentListInfo *ArgsAsWritten = + PS ? PS->getTemplateArgsAsWritten() : nullptr) { + printTemplateArgumentList(OS, ArgsAsWritten->arguments(), Policy); + } else { + const TemplateArgumentList &TemplateArgs = getTemplateArgs(); + printTemplateArgumentList(OS, TemplateArgs.asArray(), Policy); + } +} + +ClassTemplateDecl * +ClassTemplateSpecializationDecl::getSpecializedTemplate() const { + if (const auto *PartialSpec = + SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) + return PartialSpec->PartialSpecialization->getSpecializedTemplate(); + return SpecializedTemplate.get<ClassTemplateDecl*>(); +} + +SourceRange +ClassTemplateSpecializationDecl::getSourceRange() const { + if (ExplicitInfo) { + SourceLocation Begin = getTemplateKeywordLoc(); + if (Begin.isValid()) { + // Here we have an explicit (partial) specialization or instantiation. + assert(getSpecializationKind() == TSK_ExplicitSpecialization || + getSpecializationKind() == TSK_ExplicitInstantiationDeclaration || + getSpecializationKind() == TSK_ExplicitInstantiationDefinition); + if (getExternLoc().isValid()) + Begin = getExternLoc(); + SourceLocation End = getBraceRange().getEnd(); + if (End.isInvalid()) + End = getTypeAsWritten()->getTypeLoc().getEndLoc(); + return SourceRange(Begin, End); + } + // An implicit instantiation of a class template partial specialization + // uses ExplicitInfo to record the TypeAsWritten, but the source + // locations should be retrieved from the instantiation pattern. + using CTPSDecl = ClassTemplatePartialSpecializationDecl; + auto *ctpsd = const_cast<CTPSDecl *>(cast<CTPSDecl>(this)); + CTPSDecl *inst_from = ctpsd->getInstantiatedFromMember(); + assert(inst_from != nullptr); + return inst_from->getSourceRange(); + } + else { + // No explicit info available. + llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *> + inst_from = getInstantiatedFrom(); + if (inst_from.isNull()) + return getSpecializedTemplate()->getSourceRange(); + if (const auto *ctd = inst_from.dyn_cast<ClassTemplateDecl *>()) + return ctd->getSourceRange(); + return inst_from.get<ClassTemplatePartialSpecializationDecl *>() + ->getSourceRange(); + } +} + +//===----------------------------------------------------------------------===// +// ConceptDecl Implementation +//===----------------------------------------------------------------------===// +ConceptDecl *ConceptDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, + Expr *ConstraintExpr) { + AdoptTemplateParameterList(Params, DC); + return new (C, DC) ConceptDecl(DC, L, Name, Params, ConstraintExpr); +} + +ConceptDecl *ConceptDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + ConceptDecl *Result = new (C, ID) ConceptDecl(nullptr, SourceLocation(), + DeclarationName(), + nullptr, nullptr); + + return Result; +} + +//===----------------------------------------------------------------------===// +// ClassTemplatePartialSpecializationDecl Implementation +//===----------------------------------------------------------------------===// +void ClassTemplatePartialSpecializationDecl::anchor() {} + +ClassTemplatePartialSpecializationDecl:: +ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, + DeclContext *DC, + SourceLocation StartLoc, + SourceLocation IdLoc, + TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, + ArrayRef<TemplateArgument> Args, + const ASTTemplateArgumentListInfo *ArgInfos, + ClassTemplatePartialSpecializationDecl *PrevDecl) + : ClassTemplateSpecializationDecl(Context, + ClassTemplatePartialSpecialization, + TK, DC, StartLoc, IdLoc, + SpecializedTemplate, Args, PrevDecl), + TemplateParams(Params), ArgsAsWritten(ArgInfos), + InstantiatedFromMember(nullptr, false) { + AdoptTemplateParameterList(Params, this); +} + +ClassTemplatePartialSpecializationDecl * +ClassTemplatePartialSpecializationDecl:: +Create(ASTContext &Context, TagKind TK,DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + TemplateParameterList *Params, + ClassTemplateDecl *SpecializedTemplate, + ArrayRef<TemplateArgument> Args, + const TemplateArgumentListInfo &ArgInfos, + QualType CanonInjectedType, + ClassTemplatePartialSpecializationDecl *PrevDecl) { + const ASTTemplateArgumentListInfo *ASTArgInfos = + ASTTemplateArgumentListInfo::Create(Context, ArgInfos); + + auto *Result = new (Context, DC) + ClassTemplatePartialSpecializationDecl(Context, TK, DC, StartLoc, IdLoc, + Params, SpecializedTemplate, Args, + ASTArgInfos, PrevDecl); + Result->setSpecializationKind(TSK_ExplicitSpecialization); + Result->setMayHaveOutOfDateDef(false); + + Context.getInjectedClassNameType(Result, CanonInjectedType); + return Result; +} + +ClassTemplatePartialSpecializationDecl * +ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C); + Result->setMayHaveOutOfDateDef(false); + return Result; +} + +//===----------------------------------------------------------------------===// +// FriendTemplateDecl Implementation +//===----------------------------------------------------------------------===// + +void FriendTemplateDecl::anchor() {} + +FriendTemplateDecl * +FriendTemplateDecl::Create(ASTContext &Context, DeclContext *DC, + SourceLocation L, + MutableArrayRef<TemplateParameterList *> Params, + FriendUnion Friend, SourceLocation FLoc) { + return new (Context, DC) FriendTemplateDecl(DC, L, Params, Friend, FLoc); +} + +FriendTemplateDecl *FriendTemplateDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) FriendTemplateDecl(EmptyShell()); +} + +//===----------------------------------------------------------------------===// +// TypeAliasTemplateDecl Implementation +//===----------------------------------------------------------------------===// + +TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C, + DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl) { + AdoptTemplateParameterList(Params, DC); + return new (C, DC) TypeAliasTemplateDecl(C, DC, L, Name, Params, Decl); +} + +TypeAliasTemplateDecl *TypeAliasTemplateDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) TypeAliasTemplateDecl(C, nullptr, SourceLocation(), + DeclarationName(), nullptr, nullptr); +} + +RedeclarableTemplateDecl::CommonBase * +TypeAliasTemplateDecl::newCommon(ASTContext &C) const { + auto *CommonPtr = new (C) Common; + C.addDestruction(CommonPtr); + return CommonPtr; +} + +//===----------------------------------------------------------------------===// +// ClassScopeFunctionSpecializationDecl Implementation +//===----------------------------------------------------------------------===// + +void ClassScopeFunctionSpecializationDecl::anchor() {} + +ClassScopeFunctionSpecializationDecl * +ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) ClassScopeFunctionSpecializationDecl( + nullptr, SourceLocation(), nullptr, nullptr); +} + +//===----------------------------------------------------------------------===// +// VarTemplateDecl Implementation +//===----------------------------------------------------------------------===// + +VarTemplateDecl *VarTemplateDecl::getDefinition() { + VarTemplateDecl *CurD = this; + while (CurD) { + if (CurD->isThisDeclarationADefinition()) + return CurD; + CurD = CurD->getPreviousDecl(); + } + return nullptr; +} + +VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, + VarDecl *Decl) { + AdoptTemplateParameterList(Params, DC); + return new (C, DC) VarTemplateDecl(C, DC, L, Name, Params, Decl); +} + +VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C, + unsigned ID) { + return new (C, ID) VarTemplateDecl(C, nullptr, SourceLocation(), + DeclarationName(), nullptr, nullptr); +} + +void VarTemplateDecl::LoadLazySpecializations() const { + loadLazySpecializationsImpl(); +} + +llvm::FoldingSetVector<VarTemplateSpecializationDecl> & +VarTemplateDecl::getSpecializations() const { + LoadLazySpecializations(); + return getCommonPtr()->Specializations; +} + +llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> & +VarTemplateDecl::getPartialSpecializations() { + LoadLazySpecializations(); + return getCommonPtr()->PartialSpecializations; +} + +RedeclarableTemplateDecl::CommonBase * +VarTemplateDecl::newCommon(ASTContext &C) const { + auto *CommonPtr = new (C) Common; + C.addDestruction(CommonPtr); + return CommonPtr; +} + +VarTemplateSpecializationDecl * +VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args, + void *&InsertPos) { + return findSpecializationImpl(getSpecializations(), InsertPos, Args); +} + +void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D, + void *InsertPos) { + addSpecializationImpl<VarTemplateDecl>(getSpecializations(), 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, + ASTContext &Context) { + ID.AddInteger(TemplateArgs.size()); + for (const TemplateArgument &TemplateArg : TemplateArgs) + TemplateArg.Profile(ID, Context); + ProfileTemplateParameterList(Context, ID, TPL); +} + +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, + /*HasTypeConstraint=*/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, + /*HasTypeConstraint=*/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, + /*HasTypeConstraint=*/false); + 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) {} + +void TypeConstraint::print(llvm::raw_ostream &OS, PrintingPolicy Policy) const { + if (NestedNameSpec) + NestedNameSpec.getNestedNameSpecifier()->print(OS, Policy); + ConceptName.printName(OS, Policy); + if (hasExplicitTemplateArgs()) { + OS << "<"; + for (auto &ArgLoc : ArgsAsWritten->arguments()) + ArgLoc.getArgument().print(Policy, OS); + OS << ">"; + } +}
\ No newline at end of file |