diff options
Diffstat (limited to 'clang/lib/AST/DeclTemplate.cpp')
-rw-r--r-- | clang/lib/AST/DeclTemplate.cpp | 212 |
1 files changed, 169 insertions, 43 deletions
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 7e013c6c54d8..95a2e26e0df8 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -43,35 +43,46 @@ using namespace clang; // TemplateParameterList Implementation //===----------------------------------------------------------------------===// -TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc, + +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(static_cast<bool>(RequiresClause)) { + HasRequiresClause(RequiresClause != nullptr), + HasConstrainedParameters(false) { for (unsigned Idx = 0; Idx < NumParams; ++Idx) { NamedDecl *P = Params[Idx]; begin()[Idx] = P; - if (!P->isTemplateParameterPack()) { - if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) - if (NTTP->getType()->containsUnexpandedParameterPack()) - ContainsUnexpandedParameterPack = true; - - if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P)) - if (TTP->getTemplateParameters()->containsUnexpandedParameterPack()) - ContainsUnexpandedParameterPack = true; - - // FIXME: If a default argument contains an unexpanded parameter pack, the - // template parameter list does too. + 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 (RequiresClause) { - *getTrailingObjects<Expr *>() = RequiresClause; + + if (HasRequiresClause) { if (RequiresClause->containsUnexpandedParameterPack()) ContainsUnexpandedParameterPack = true; + *getTrailingObjects<Expr *>() = RequiresClause; } } @@ -83,7 +94,7 @@ TemplateParameterList::Create(const ASTContext &C, SourceLocation TemplateLoc, void *Mem = C.Allocate(totalSizeToAlloc<NamedDecl *, Expr *>( Params.size(), RequiresClause ? 1u : 0u), alignof(TemplateParameterList)); - return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params, + return new (Mem) TemplateParameterList(C, TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause); } @@ -91,11 +102,23 @@ unsigned TemplateParameterList::getMinRequiredArguments() const { unsigned NumRequiredArgs = 0; for (const NamedDecl *P : asArray()) { if (P->isTemplateParameterPack()) { - if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) + 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; } @@ -140,14 +163,17 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params, void TemplateParameterList:: getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const { - // TODO: Concepts: Collect immediately-introduced constraints. + 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()); if (HasRequiresClause) AC.push_back(getRequiresClause()); } bool TemplateParameterList::hasAssociatedConstraints() const { - // TODO: Concepts: Regard immediately-introduced constraints. - return HasRequiresClause; + return HasRequiresClause || HasConstrainedParameters; } namespace clang { @@ -171,13 +197,18 @@ void TemplateDecl::anchor() {} void TemplateDecl:: getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const { - // TODO: Concepts: Append function trailing requires clause. 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 { - // TODO: Concepts: Regard function trailing requires clause. - return TemplateParams->hasAssociatedConstraints(); + if (TemplateParams->hasAssociatedConstraints()) + return true; + if (auto *FD = dyn_cast_or_null<FunctionDecl>(getTemplatedDecl())) + return FD->getTrailingRequiresClause(); + return false; } //===----------------------------------------------------------------------===// @@ -231,15 +262,16 @@ void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const { } } -template<class EntryType> +template<class EntryType, typename... ProfileArguments> typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType * RedeclarableTemplateDecl::findSpecializationImpl( - llvm::FoldingSetVector<EntryType> &Specs, ArrayRef<TemplateArgument> Args, - void *&InsertPos) { + llvm::FoldingSetVector<EntryType> &Specs, void *&InsertPos, + ProfileArguments&&... ProfileArgs) { using SETraits = SpecEntryTraits<EntryType>; llvm::FoldingSetNodeID ID; - EntryType::Profile(ID, Args, getASTContext()); + EntryType::Profile(ID, std::forward<ProfileArguments>(ProfileArgs)..., + getASTContext()); EntryType *Entry = Specs.FindNodeOrInsertPos(ID, InsertPos); return Entry ? SETraits::getDecl(Entry)->getMostRecentDecl() : nullptr; } @@ -254,8 +286,8 @@ void RedeclarableTemplateDecl::addSpecializationImpl( #ifndef NDEBUG void *CorrectInsertPos; assert(!findSpecializationImpl(Specializations, - SETraits::getTemplateArgs(Entry), - CorrectInsertPos) && + CorrectInsertPos, + SETraits::getTemplateArgs(Entry)) && InsertPos == CorrectInsertPos && "given incorrect InsertPos for specialization"); #endif @@ -312,7 +344,7 @@ FunctionTemplateDecl::getSpecializations() const { FunctionDecl * FunctionTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos) { - return findSpecializationImpl(getSpecializations(), Args, InsertPos); + return findSpecializationImpl(getSpecializations(), InsertPos, Args); } void FunctionTemplateDecl::addSpecialization( @@ -418,7 +450,7 @@ ClassTemplateDecl::newCommon(ASTContext &C) const { ClassTemplateSpecializationDecl * ClassTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos) { - return findSpecializationImpl(getSpecializations(), Args, InsertPos); + return findSpecializationImpl(getSpecializations(), InsertPos, Args); } void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D, @@ -427,9 +459,48 @@ void ClassTemplateDecl::AddSpecialization(ClassTemplateSpecializationDecl *D, } ClassTemplatePartialSpecializationDecl * -ClassTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args, - void *&InsertPos) { - return findSpecializationImpl(getPartialSpecializations(), Args, InsertPos); +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()); + // TODO: Concepts: profile type-constraints. + 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( @@ -513,9 +584,14 @@ TemplateTypeParmDecl * TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC, SourceLocation KeyLoc, SourceLocation NameLoc, unsigned D, unsigned P, IdentifierInfo *Id, - bool Typename, bool ParameterPack) { + bool Typename, bool ParameterPack, + bool HasTypeConstraint, + Optional<unsigned> NumExpanded) { auto *TTPDecl = - new (C, DC) TemplateTypeParmDecl(DC, KeyLoc, NameLoc, Id, Typename); + 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; @@ -524,7 +600,17 @@ TemplateTypeParmDecl::Create(const ASTContext &C, DeclContext *DC, TemplateTypeParmDecl * TemplateTypeParmDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { return new (C, ID) TemplateTypeParmDecl(nullptr, SourceLocation(), - SourceLocation(), nullptr, false); + 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 { @@ -557,6 +643,20 @@ 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 //===----------------------------------------------------------------------===// @@ -1035,7 +1135,7 @@ VarTemplateDecl::newCommon(ASTContext &C) const { VarTemplateSpecializationDecl * VarTemplateDecl::findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos) { - return findSpecializationImpl(getSpecializations(), Args, InsertPos); + return findSpecializationImpl(getSpecializations(), InsertPos, Args); } void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D, @@ -1045,8 +1145,19 @@ void VarTemplateDecl::AddSpecialization(VarTemplateSpecializationDecl *D, VarTemplatePartialSpecializationDecl * VarTemplateDecl::findPartialSpecialization(ArrayRef<TemplateArgument> Args, - void *&InsertPos) { - return findSpecializationImpl(getPartialSpecializations(), Args, InsertPos); + 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( @@ -1200,7 +1311,8 @@ 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); + /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false, + /*HasTypeConstraint=*/false); T->setImplicit(true); // T ...Ints @@ -1225,7 +1337,8 @@ createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) { // typename T auto *TemplateTypeParm = TemplateTypeParmDecl::Create( C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1, - /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false); + /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false, + /*HasTypeConstraint=*/false); TemplateTypeParm->setImplicit(true); // T N @@ -1253,7 +1366,8 @@ createTypePackElementParameterList(const ASTContext &C, DeclContext *DC) { // typename ...T auto *Ts = TemplateTypeParmDecl::Create( C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1, - /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/true); + /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/true, + /*HasTypeConstraint=*/false); Ts->setImplicit(true); // template <std::size_t Index, typename ...T> @@ -1283,3 +1397,15 @@ BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC, : 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 |