https://github.com/hokein created https://github.com/llvm/llvm-project/pull/85904
Fixes https://github.com/llvm/llvm-project/issues/85767. >From ff697e2a159a4959deb11031111d9d8442ef544a Mon Sep 17 00:00:00 2001 From: Haojian Wu <hokein...@gmail.com> Date: Fri, 15 Mar 2024 10:47:09 +0100 Subject: [PATCH 1/2] [clang] Move the aggreate deduction guide cache login to SemaTemplate.cpp, NFC. this is a NFC refactoring change, which is needed for the upcoming fix for alias templates. --- clang/lib/Sema/SemaInit.cpp | 27 +++++---------------------- clang/lib/Sema/SemaTemplate.cpp | 24 ++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 24 deletions(-) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index aa470adb30b47f..763cc5dd17129c 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -10918,32 +10918,15 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( Context.getLValueReferenceType(ElementTypes[I].withConst()); } - llvm::FoldingSetNodeID ID; - ID.AddPointer(Template); - for (auto &T : ElementTypes) - T.getCanonicalType().Profile(ID); - unsigned Hash = ID.ComputeHash(); - if (AggregateDeductionCandidates.count(Hash) == 0) { - if (FunctionTemplateDecl *TD = - DeclareImplicitDeductionGuideFromInitList( - Template, ElementTypes, - TSInfo->getTypeLoc().getEndLoc())) { - auto *GD = cast<CXXDeductionGuideDecl>(TD->getTemplatedDecl()); - GD->setDeductionCandidateKind(DeductionCandidate::Aggregate); - AggregateDeductionCandidates[Hash] = GD; - addDeductionCandidate(TD, GD, DeclAccessPair::make(TD, AS_public), - OnlyListConstructors, - /*AllowAggregateDeductionCandidate=*/true); - } - } else { - CXXDeductionGuideDecl *GD = AggregateDeductionCandidates[Hash]; - FunctionTemplateDecl *TD = GD->getDescribedFunctionTemplate(); - assert(TD && "aggregate deduction candidate is function template"); + if (FunctionTemplateDecl *TD = + DeclareImplicitDeductionGuideFromInitList( + Template, ElementTypes, TSInfo->getTypeLoc().getEndLoc())) { + auto *GD = cast<CXXDeductionGuideDecl>(TD->getTemplatedDecl()); addDeductionCandidate(TD, GD, DeclAccessPair::make(TD, AS_public), OnlyListConstructors, /*AllowAggregateDeductionCandidate=*/true); + HasAnyDeductionGuide = true; } - HasAnyDeductionGuide = true; } }; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 51e8db2dfbaac8..0a4c16f2f09f09 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2987,6 +2987,23 @@ void DeclareImplicitDeductionGuidesForTypeAlias( FunctionTemplateDecl *Sema::DeclareImplicitDeductionGuideFromInitList( TemplateDecl *Template, MutableArrayRef<QualType> ParamTypes, SourceLocation Loc) { + llvm::FoldingSetNodeID ID; + ID.AddPointer(Template); + for (auto &T : ParamTypes) + T.getCanonicalType().Profile(ID); + unsigned Hash = ID.ComputeHash(); + + auto Found = AggregateDeductionCandidates.find(Hash); + if (Found != AggregateDeductionCandidates.end()) { + CXXDeductionGuideDecl *GD = Found->getSecond(); + return GD->getDescribedFunctionTemplate(); + } + + // if (auto *AliasTemplate = llvm::dyn_cast<TypeAliasTemplateDecl>(Template)) { + // DeclareImplicitDeductionGuidesForTypeAlias(*this, AliasTemplate, Loc); + // return; + // } + if (CXXRecordDecl *DefRecord = cast<CXXRecordDecl>(Template->getTemplatedDecl())->getDefinition()) { if (TemplateDecl *DescribedTemplate = @@ -3019,10 +3036,13 @@ FunctionTemplateDecl *Sema::DeclareImplicitDeductionGuideFromInitList( Transform.NestedPattern ? Transform.NestedPattern : Transform.Template; ContextRAII SavedContext(*this, Pattern->getTemplatedDecl()); - auto *DG = cast<FunctionTemplateDecl>( + auto *FTD = cast<FunctionTemplateDecl>( Transform.buildSimpleDeductionGuide(ParamTypes)); SavedContext.pop(); - return DG; + auto *GD = cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl()); + GD->setDeductionCandidateKind(DeductionCandidate::Aggregate); + AggregateDeductionCandidates[Hash] = GD; + return FTD; } void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template, >From 9355ff3d75221659a33ca5e7571849ff3135353a Mon Sep 17 00:00:00 2001 From: Haojian Wu <hokein...@gmail.com> Date: Tue, 19 Mar 2024 23:07:09 +0100 Subject: [PATCH 2/2] [clang] CTAD: build aggregate deduction guides for alias templates. Fixes https://github.com/llvm/llvm-project/issues/85767. --- clang/lib/Sema/SemaInit.cpp | 2 +- clang/lib/Sema/SemaTemplate.cpp | 183 +++++++++++++++----- clang/test/SemaTemplate/deduction-guide.cpp | 15 ++ 3 files changed, 153 insertions(+), 47 deletions(-) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 763cc5dd17129c..a2d5bad1300d1f 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -10920,7 +10920,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( if (FunctionTemplateDecl *TD = DeclareImplicitDeductionGuideFromInitList( - Template, ElementTypes, TSInfo->getTypeLoc().getEndLoc())) { + LookupTemplateDecl, ElementTypes, TSInfo->getTypeLoc().getEndLoc())) { auto *GD = cast<CXXDeductionGuideDecl>(TD->getTemplatedDecl()); addDeductionCandidate(TD, GD, DeclAccessPair::make(TD, AS_public), OnlyListConstructors, diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 0a4c16f2f09f09..86d07dd3a2187a 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2725,21 +2725,43 @@ bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) { return false; } -// Build deduction guides for a type alias template. -void DeclareImplicitDeductionGuidesForTypeAlias( - Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) { - auto &Context = SemaRef.Context; - // FIXME: if there is an explicit deduction guide after the first use of the - // type alias usage, we will not cover this explicit deduction guide. fix this - // case. - if (hasDeclaredDeductionGuides( - Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate), - AliasTemplate->getDeclContext())) - return; +NamedDecl *TransformTemplateParameter(Sema &SemaRef, DeclContext *DC, + NamedDecl *TemplateParam, + MultiLevelTemplateArgumentList &Args, + unsigned NewIndex) { + if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) + return transformTemplateTypeParam(SemaRef, DC, TTP, Args, TTP->getDepth(), + NewIndex); + if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam)) + return transformTemplateParam(SemaRef, DC, TTP, Args, NewIndex, + TTP->getDepth()); + if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam)) + return transformTemplateParam(SemaRef, DC, NTTP, Args, NewIndex, + NTTP->getDepth()); + return nullptr; +} + +Expr *TransformRequireClause(Sema &SemaRef, FunctionTemplateDecl *FTD, + llvm::ArrayRef<TemplateArgument> TransformedArgs) { + Expr *RC = + FTD->getTemplateParameters()->getRequiresClause(); + if (!RC) + return nullptr; + MultiLevelTemplateArgumentList Args; + Args.setKind(TemplateSubstitutionKind::Rewrite); + Args.addOuterTemplateArguments(TransformedArgs); + ExprResult E = SemaRef.SubstExpr(RC, Args); + if (E.isInvalid()) + return nullptr; + return E.getAs<Expr>(); +} + +std::pair<TemplateDecl *, llvm::ArrayRef<TemplateArgument>> +GetRHSTemplateDeclAndArgs(Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) { // Unwrap the sugared ElaboratedType. auto RhsType = AliasTemplate->getTemplatedDecl() ->getUnderlyingType() - .getSingleStepDesugaredType(Context); + .getSingleStepDesugaredType(SemaRef.Context); TemplateDecl *Template = nullptr; llvm::ArrayRef<TemplateArgument> AliasRhsTemplateArgs; if (const auto *TST = RhsType->getAs<TemplateSpecializationType>()) { @@ -2760,6 +2782,22 @@ void DeclareImplicitDeductionGuidesForTypeAlias( } else { assert(false && "unhandled RHS type of the alias"); } + return {Template, AliasRhsTemplateArgs}; +} + +// Build deduction guides for a type alias template. +void DeclareImplicitDeductionGuidesForTypeAlias( + Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) { + auto &Context = SemaRef.Context; + // FIXME: if there is an explicit deduction guide after the first use of the + // type alias usage, we will not cover this explicit deduction guide. fix this + // case. + if (hasDeclaredDeductionGuides( + Context.DeclarationNames.getCXXDeductionGuideName(AliasTemplate), + AliasTemplate->getDeclContext())) + return; + auto [Template, AliasRhsTemplateArgs] = + GetRHSTemplateDeclAndArgs(SemaRef, AliasTemplate); if (!Template) return; DeclarationNameInfo NameInfo( @@ -2854,21 +2892,6 @@ void DeclareImplicitDeductionGuidesForTypeAlias( // parameters, used for building `TemplateArgsForBuildingFPrime`. SmallVector<TemplateArgument, 16> TransformedDeducedAliasArgs( AliasTemplate->getTemplateParameters()->size()); - auto TransformTemplateParameter = - [&SemaRef](DeclContext *DC, NamedDecl *TemplateParam, - MultiLevelTemplateArgumentList &Args, - unsigned NewIndex) -> NamedDecl * { - if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) - return transformTemplateTypeParam(SemaRef, DC, TTP, Args, - TTP->getDepth(), NewIndex); - if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam)) - return transformTemplateParam(SemaRef, DC, TTP, Args, NewIndex, - TTP->getDepth()); - if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam)) - return transformTemplateParam(SemaRef, DC, NTTP, Args, NewIndex, - NTTP->getDepth()); - return nullptr; - }; for (unsigned AliasTemplateParamIdx : DeducedAliasTemplateParams) { auto *TP = AliasTemplate->getTemplateParameters()->getParam( @@ -2878,9 +2901,9 @@ void DeclareImplicitDeductionGuidesForTypeAlias( MultiLevelTemplateArgumentList Args; Args.setKind(TemplateSubstitutionKind::Rewrite); Args.addOuterTemplateArguments(TransformedDeducedAliasArgs); - NamedDecl *NewParam = - TransformTemplateParameter(AliasTemplate->getDeclContext(), TP, Args, - /*NewIndex*/ FPrimeTemplateParams.size()); + NamedDecl *NewParam = TransformTemplateParameter( + SemaRef, AliasTemplate->getDeclContext(), TP, Args, + /*NewIndex*/ FPrimeTemplateParams.size()); FPrimeTemplateParams.push_back(NewParam); auto NewTemplateArgument = Context.getCanonicalTemplateArgument( @@ -2897,7 +2920,7 @@ void DeclareImplicitDeductionGuidesForTypeAlias( // TemplateArgsForBuildingFPrime. Args.addOuterTemplateArguments(TemplateArgsForBuildingFPrime); NamedDecl *NewParam = TransformTemplateParameter( - F->getDeclContext(), TP, Args, FPrimeTemplateParams.size()); + SemaRef, F->getDeclContext(), TP, Args, FPrimeTemplateParams.size()); FPrimeTemplateParams.push_back(NewParam); assert(TemplateArgsForBuildingFPrime[FTemplateParamIdx].isNull() && @@ -2907,16 +2930,8 @@ void DeclareImplicitDeductionGuidesForTypeAlias( Context.getInjectedTemplateArg(NewParam)); } // Substitute new template parameters into requires-clause if present. - Expr *RequiresClause = nullptr; - if (Expr *InnerRC = F->getTemplateParameters()->getRequiresClause()) { - MultiLevelTemplateArgumentList Args; - Args.setKind(TemplateSubstitutionKind::Rewrite); - Args.addOuterTemplateArguments(TemplateArgsForBuildingFPrime); - ExprResult E = SemaRef.SubstExpr(InnerRC, Args); - if (E.isInvalid()) - return; - RequiresClause = E.getAs<Expr>(); - } + Expr *RequiresClause = + TransformRequireClause(SemaRef, F, TemplateArgsForBuildingFPrime); // FIXME: implement the is_deducible constraint per C++ // [over.match.class.deduct]p3.3: // ... and a constraint that is satisfied if and only if the arguments @@ -2982,8 +2997,79 @@ void DeclareImplicitDeductionGuidesForTypeAlias( } } +// Build an aggregate deduction guide for a type alias template. +FunctionTemplateDecl *DeclareAggrecateDeductionGuideForTypeAlias( + Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, + MutableArrayRef<QualType> ParamTypes, SourceLocation Loc) { + TemplateDecl *RHSTemplate = + GetRHSTemplateDeclAndArgs(SemaRef, AliasTemplate).first; + if (!RHSTemplate) + return nullptr; + auto *RHSDeductionGuide = + SemaRef.DeclareImplicitDeductionGuideFromInitList(RHSTemplate, ParamTypes, + Loc); + if (!RHSDeductionGuide) + return nullptr; + + LocalInstantiationScope Scope(SemaRef); + + // Build a new template parameter list for the synthesized aggregate deduction + // guide by transforming the one from RHSDeductionGuide. + SmallVector<NamedDecl *> TransformedTemplateParams; + // Template args that refers to the rebuilt template parameters. + // All template arguments must be initialized in advance. + SmallVector<TemplateArgument> TransformedTemplateArgs( + RHSDeductionGuide->getTemplateParameters()->size()); + for (auto *TP : *RHSDeductionGuide->getTemplateParameters()) { + // Rebuild any internal references to earlier parameters and reindex as + // we go. + MultiLevelTemplateArgumentList Args; + Args.setKind(TemplateSubstitutionKind::Rewrite); + Args.addOuterTemplateArguments(TransformedTemplateArgs); + NamedDecl *NewParam = TransformTemplateParameter( + SemaRef, AliasTemplate->getDeclContext(), TP, Args, + /*NewIndex=*/ TransformedTemplateParams.size()); + + TransformedTemplateArgs[TransformedTemplateParams.size()] = + SemaRef.Context.getCanonicalTemplateArgument( + SemaRef.Context.getInjectedTemplateArg(NewParam)); + TransformedTemplateParams.push_back(NewParam); + } + // FIXME: implement the is_deducible constraint per C++ + // [over.match.class.deduct]p3.3. + Expr *TransformedRequiresClause = TransformRequireClause( + SemaRef, RHSDeductionGuide, TransformedTemplateArgs); + auto *TransformedTemplateParameterList = TemplateParameterList::Create( + SemaRef.Context, AliasTemplate->getTemplateParameters()->getTemplateLoc(), + AliasTemplate->getTemplateParameters()->getLAngleLoc(), + TransformedTemplateParams, + AliasTemplate->getTemplateParameters()->getRAngleLoc(), + TransformedRequiresClause); + auto *TransformedTemplateArgList = TemplateArgumentList::CreateCopy( + SemaRef.Context, TransformedTemplateArgs); + + if (auto *TransformedDeductionGuide = SemaRef.InstantiateFunctionDeclaration( + RHSDeductionGuide, TransformedTemplateArgList, + AliasTemplate->getLocation(), + Sema::CodeSynthesisContext::BuildingDeductionGuides)) { + auto *GD = + llvm::dyn_cast<clang::CXXDeductionGuideDecl>(TransformedDeductionGuide); + FunctionTemplateDecl *Result = buildDeductionGuide( + SemaRef, AliasTemplate, TransformedTemplateParameterList, + GD->getCorrespondingConstructor(), GD->getExplicitSpecifier(), + GD->getTypeSourceInfo(), AliasTemplate->getBeginLoc(), + AliasTemplate->getLocation(), AliasTemplate->getEndLoc(), + GD->isImplicit()); + cast<CXXDeductionGuideDecl>(Result->getTemplatedDecl()) + ->setDeductionCandidateKind(DeductionCandidate::Aggregate); + return Result; + } + return nullptr; +} + } // namespace +// FIXME: rename to DeclareAggrecateDeductionGuide. FunctionTemplateDecl *Sema::DeclareImplicitDeductionGuideFromInitList( TemplateDecl *Template, MutableArrayRef<QualType> ParamTypes, SourceLocation Loc) { @@ -2998,11 +3084,16 @@ FunctionTemplateDecl *Sema::DeclareImplicitDeductionGuideFromInitList( CXXDeductionGuideDecl *GD = Found->getSecond(); return GD->getDescribedFunctionTemplate(); } - - // if (auto *AliasTemplate = llvm::dyn_cast<TypeAliasTemplateDecl>(Template)) { - // DeclareImplicitDeductionGuidesForTypeAlias(*this, AliasTemplate, Loc); - // return; - // } + + if (auto *AliasTemplate = llvm::dyn_cast<TypeAliasTemplateDecl>(Template)) { + if (auto *FTD = DeclareAggrecateDeductionGuideForTypeAlias( + *this, AliasTemplate, ParamTypes, Loc)) { + auto *GD = cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl()); + GD->setDeductionCandidateKind(DeductionCandidate::Aggregate); + AggregateDeductionCandidates[Hash] = GD; + return FTD; + } + } if (CXXRecordDecl *DefRecord = cast<CXXRecordDecl>(Template->getTemplatedDecl())->getDefinition()) { diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp index 16c7083df29d0c..bf1a6939203f4e 100644 --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -239,3 +239,18 @@ F s(0); // CHECK: |-InjectedClassNameType {{.*}} 'F<>' dependent // CHECK: | `-CXXRecord {{.*}} 'F' // CHECK: `-TemplateTypeParmType {{.*}} 'type-parameter-0-1' dependent depth 0 index 1 + +template <typename T> +struct G { T t1; }; +template<typename X> +using AG = G<X>; + +AG ag = {1}; +// Verify that the aggregate deduction guide for alias templates is built. +// CHECK-LABEL: Dumping <deduction guide for AG> +// CHECK: FunctionTemplateDecl +// CHECK: |-CXXDeductionGuideDecl {{.*}} 'auto (type-parameter-0-0) -> G<type-parameter-0-0>' +// CHECK: `-CXXDeductionGuideDecl {{.*}} 'auto (int) -> G<int>' implicit_instantiation +// CHECK: |-TemplateArgument type 'int' +// CHECK: | `-BuiltinType {{.*}} 'int' +// CHECK: `-ParmVarDecl {{.*}} 'int' _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits