@@ -2754,23 +2754,42 @@ bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
27542754 return false ;
27552755}
27562756
2757- // Build deduction guides for a type alias template.
2758- void DeclareImplicitDeductionGuidesForTypeAlias (
2759- Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
2760- if (AliasTemplate->isInvalidDecl ())
2761- return ;
2762- auto &Context = SemaRef.Context ;
2763- // FIXME: if there is an explicit deduction guide after the first use of the
2764- // type alias usage, we will not cover this explicit deduction guide. fix this
2765- // case.
2766- if (hasDeclaredDeductionGuides (
2767- Context.DeclarationNames .getCXXDeductionGuideName (AliasTemplate),
2768- AliasTemplate->getDeclContext ()))
2769- return ;
2757+ NamedDecl *transformTemplateParameter (Sema &SemaRef, DeclContext *DC,
2758+ NamedDecl *TemplateParam,
2759+ MultiLevelTemplateArgumentList &Args,
2760+ unsigned NewIndex) {
2761+ if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam))
2762+ return transformTemplateTypeParam (SemaRef, DC, TTP, Args, TTP->getDepth (),
2763+ NewIndex);
2764+ if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam))
2765+ return transformTemplateParam (SemaRef, DC, TTP, Args, NewIndex,
2766+ TTP->getDepth ());
2767+ if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam))
2768+ return transformTemplateParam (SemaRef, DC, NTTP, Args, NewIndex,
2769+ NTTP->getDepth ());
2770+ llvm_unreachable (" Unhandled template parameter types" );
2771+ }
2772+
2773+ Expr *transformRequireClause (Sema &SemaRef, FunctionTemplateDecl *FTD,
2774+ llvm::ArrayRef<TemplateArgument> TransformedArgs) {
2775+ Expr *RC = FTD->getTemplateParameters ()->getRequiresClause ();
2776+ if (!RC)
2777+ return nullptr ;
2778+ MultiLevelTemplateArgumentList Args;
2779+ Args.setKind (TemplateSubstitutionKind::Rewrite);
2780+ Args.addOuterTemplateArguments (TransformedArgs);
2781+ ExprResult E = SemaRef.SubstExpr (RC, Args);
2782+ if (E.isInvalid ())
2783+ return nullptr ;
2784+ return E.getAs <Expr>();
2785+ }
2786+
2787+ std::pair<TemplateDecl *, llvm::ArrayRef<TemplateArgument>>
2788+ getRHSTemplateDeclAndArgs (Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) {
27702789 // Unwrap the sugared ElaboratedType.
27712790 auto RhsType = AliasTemplate->getTemplatedDecl ()
27722791 ->getUnderlyingType ()
2773- .getSingleStepDesugaredType (Context);
2792+ .getSingleStepDesugaredType (SemaRef. Context );
27742793 TemplateDecl *Template = nullptr ;
27752794 llvm::ArrayRef<TemplateArgument> AliasRhsTemplateArgs;
27762795 if (const auto *TST = RhsType->getAs <TemplateSpecializationType>()) {
@@ -2791,6 +2810,24 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
27912810 } else {
27922811 assert (false && " unhandled RHS type of the alias" );
27932812 }
2813+ return {Template, AliasRhsTemplateArgs};
2814+ }
2815+
2816+ // Build deduction guides for a type alias template.
2817+ void DeclareImplicitDeductionGuidesForTypeAlias (
2818+ Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
2819+ if (AliasTemplate->isInvalidDecl ())
2820+ return ;
2821+ auto &Context = SemaRef.Context ;
2822+ // FIXME: if there is an explicit deduction guide after the first use of the
2823+ // type alias usage, we will not cover this explicit deduction guide. fix this
2824+ // case.
2825+ if (hasDeclaredDeductionGuides (
2826+ Context.DeclarationNames .getCXXDeductionGuideName (AliasTemplate),
2827+ AliasTemplate->getDeclContext ()))
2828+ return ;
2829+ auto [Template, AliasRhsTemplateArgs] =
2830+ getRHSTemplateDeclAndArgs (SemaRef, AliasTemplate);
27942831 if (!Template)
27952832 return ;
27962833 DeclarationNameInfo NameInfo (
@@ -2803,6 +2840,13 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
28032840 FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(G);
28042841 if (!F)
28052842 continue ;
2843+ // The **aggregate** deduction guides are handled in a different code path
2844+ // (DeclareImplicitDeductionGuideFromInitList), which involves the tricky
2845+ // cache.
2846+ if (cast<CXXDeductionGuideDecl>(F->getTemplatedDecl ())
2847+ ->getDeductionCandidateKind () == DeductionCandidate::Aggregate)
2848+ continue ;
2849+
28062850 auto RType = F->getTemplatedDecl ()->getReturnType ();
28072851 // The (trailing) return type of the deduction guide.
28082852 const TemplateSpecializationType *FReturnType =
@@ -2885,21 +2929,6 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
28852929 // parameters, used for building `TemplateArgsForBuildingFPrime`.
28862930 SmallVector<TemplateArgument, 16 > TransformedDeducedAliasArgs (
28872931 AliasTemplate->getTemplateParameters ()->size ());
2888- auto TransformTemplateParameter =
2889- [&SemaRef](DeclContext *DC, NamedDecl *TemplateParam,
2890- MultiLevelTemplateArgumentList &Args,
2891- unsigned NewIndex) -> NamedDecl * {
2892- if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam))
2893- return transformTemplateTypeParam (SemaRef, DC, TTP, Args,
2894- TTP->getDepth (), NewIndex);
2895- if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam))
2896- return transformTemplateParam (SemaRef, DC, TTP, Args, NewIndex,
2897- TTP->getDepth ());
2898- if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam))
2899- return transformTemplateParam (SemaRef, DC, NTTP, Args, NewIndex,
2900- NTTP->getDepth ());
2901- return nullptr ;
2902- };
29032932
29042933 for (unsigned AliasTemplateParamIdx : DeducedAliasTemplateParams) {
29052934 auto *TP = AliasTemplate->getTemplateParameters ()->getParam (
@@ -2909,9 +2938,9 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
29092938 MultiLevelTemplateArgumentList Args;
29102939 Args.setKind (TemplateSubstitutionKind::Rewrite);
29112940 Args.addOuterTemplateArguments (TransformedDeducedAliasArgs);
2912- NamedDecl *NewParam =
2913- TransformTemplateParameter ( AliasTemplate->getDeclContext (), TP, Args,
2914- /* NewIndex*/ FPrimeTemplateParams.size ());
2941+ NamedDecl *NewParam = transformTemplateParameter (
2942+ SemaRef, AliasTemplate->getDeclContext (), TP, Args,
2943+ /* NewIndex*/ FPrimeTemplateParams.size ());
29152944 FPrimeTemplateParams.push_back (NewParam);
29162945
29172946 auto NewTemplateArgument = Context.getCanonicalTemplateArgument (
@@ -2927,8 +2956,8 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
29272956 // We take a shortcut here, it is ok to reuse the
29282957 // TemplateArgsForBuildingFPrime.
29292958 Args.addOuterTemplateArguments (TemplateArgsForBuildingFPrime);
2930- NamedDecl *NewParam = TransformTemplateParameter (
2931- F->getDeclContext (), TP, Args, FPrimeTemplateParams.size ());
2959+ NamedDecl *NewParam = transformTemplateParameter (
2960+ SemaRef, F->getDeclContext (), TP, Args, FPrimeTemplateParams.size ());
29322961 FPrimeTemplateParams.push_back (NewParam);
29332962
29342963 assert (TemplateArgsForBuildingFPrime[FTemplateParamIdx].isNull () &&
@@ -2938,16 +2967,8 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
29382967 Context.getInjectedTemplateArg (NewParam));
29392968 }
29402969 // Substitute new template parameters into requires-clause if present.
2941- Expr *RequiresClause = nullptr ;
2942- if (Expr *InnerRC = F->getTemplateParameters ()->getRequiresClause ()) {
2943- MultiLevelTemplateArgumentList Args;
2944- Args.setKind (TemplateSubstitutionKind::Rewrite);
2945- Args.addOuterTemplateArguments (TemplateArgsForBuildingFPrime);
2946- ExprResult E = SemaRef.SubstExpr (InnerRC, Args);
2947- if (E.isInvalid ())
2948- return ;
2949- RequiresClause = E.getAs <Expr>();
2950- }
2970+ Expr *RequiresClause =
2971+ transformRequireClause (SemaRef, F, TemplateArgsForBuildingFPrime);
29512972 // FIXME: implement the is_deducible constraint per C++
29522973 // [over.match.class.deduct]p3.3:
29532974 // ... and a constraint that is satisfied if and only if the arguments
@@ -3013,11 +3034,102 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
30133034 }
30143035}
30153036
3037+ // Build an aggregate deduction guide for a type alias template.
3038+ FunctionTemplateDecl *DeclareAggregateDeductionGuideForTypeAlias (
3039+ Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate,
3040+ MutableArrayRef<QualType> ParamTypes, SourceLocation Loc) {
3041+ TemplateDecl *RHSTemplate =
3042+ getRHSTemplateDeclAndArgs (SemaRef, AliasTemplate).first ;
3043+ if (!RHSTemplate)
3044+ return nullptr ;
3045+ auto *RHSDeductionGuide = SemaRef.DeclareAggregateDeductionGuideFromInitList (
3046+ RHSTemplate, ParamTypes, Loc);
3047+ if (!RHSDeductionGuide)
3048+ return nullptr ;
3049+
3050+ LocalInstantiationScope Scope (SemaRef);
3051+
3052+ // Build a new template parameter list for the synthesized aggregate deduction
3053+ // guide by transforming the one from RHSDeductionGuide.
3054+ SmallVector<NamedDecl *> TransformedTemplateParams;
3055+ // Template args that refer to the rebuilt template parameters.
3056+ // All template arguments must be initialized in advance.
3057+ SmallVector<TemplateArgument> TransformedTemplateArgs (
3058+ RHSDeductionGuide->getTemplateParameters ()->size ());
3059+ for (auto *TP : *RHSDeductionGuide->getTemplateParameters ()) {
3060+ // Rebuild any internal references to earlier parameters and reindex as
3061+ // we go.
3062+ MultiLevelTemplateArgumentList Args;
3063+ Args.setKind (TemplateSubstitutionKind::Rewrite);
3064+ Args.addOuterTemplateArguments (TransformedTemplateArgs);
3065+ NamedDecl *NewParam = transformTemplateParameter (
3066+ SemaRef, AliasTemplate->getDeclContext (), TP, Args,
3067+ /* NewIndex=*/ TransformedTemplateParams.size ());
3068+
3069+ TransformedTemplateArgs[TransformedTemplateParams.size ()] =
3070+ SemaRef.Context .getCanonicalTemplateArgument (
3071+ SemaRef.Context .getInjectedTemplateArg (NewParam));
3072+ TransformedTemplateParams.push_back (NewParam);
3073+ }
3074+ // FIXME: implement the is_deducible constraint per C++
3075+ // [over.match.class.deduct]p3.3.
3076+ Expr *TransformedRequiresClause = transformRequireClause (
3077+ SemaRef, RHSDeductionGuide, TransformedTemplateArgs);
3078+ auto *TransformedTemplateParameterList = TemplateParameterList::Create (
3079+ SemaRef.Context , AliasTemplate->getTemplateParameters ()->getTemplateLoc (),
3080+ AliasTemplate->getTemplateParameters ()->getLAngleLoc (),
3081+ TransformedTemplateParams,
3082+ AliasTemplate->getTemplateParameters ()->getRAngleLoc (),
3083+ TransformedRequiresClause);
3084+ auto *TransformedTemplateArgList = TemplateArgumentList::CreateCopy (
3085+ SemaRef.Context , TransformedTemplateArgs);
3086+
3087+ if (auto *TransformedDeductionGuide = SemaRef.InstantiateFunctionDeclaration (
3088+ RHSDeductionGuide, TransformedTemplateArgList,
3089+ AliasTemplate->getLocation (),
3090+ Sema::CodeSynthesisContext::BuildingDeductionGuides)) {
3091+ auto *GD =
3092+ llvm::dyn_cast<clang::CXXDeductionGuideDecl>(TransformedDeductionGuide);
3093+ FunctionTemplateDecl *Result = buildDeductionGuide (
3094+ SemaRef, AliasTemplate, TransformedTemplateParameterList,
3095+ GD->getCorrespondingConstructor (), GD->getExplicitSpecifier (),
3096+ GD->getTypeSourceInfo (), AliasTemplate->getBeginLoc (),
3097+ AliasTemplate->getLocation (), AliasTemplate->getEndLoc (),
3098+ GD->isImplicit ());
3099+ cast<CXXDeductionGuideDecl>(Result->getTemplatedDecl ())
3100+ ->setDeductionCandidateKind (DeductionCandidate::Aggregate);
3101+ return Result;
3102+ }
3103+ return nullptr ;
3104+ }
3105+
30163106} // namespace
30173107
3018- FunctionTemplateDecl *Sema::DeclareImplicitDeductionGuideFromInitList (
3108+ FunctionTemplateDecl *Sema::DeclareAggregateDeductionGuideFromInitList (
30193109 TemplateDecl *Template, MutableArrayRef<QualType> ParamTypes,
30203110 SourceLocation Loc) {
3111+ llvm::FoldingSetNodeID ID;
3112+ ID.AddPointer (Template);
3113+ for (auto &T : ParamTypes)
3114+ T.getCanonicalType ().Profile (ID);
3115+ unsigned Hash = ID.ComputeHash ();
3116+
3117+ auto Found = AggregateDeductionCandidates.find (Hash);
3118+ if (Found != AggregateDeductionCandidates.end ()) {
3119+ CXXDeductionGuideDecl *GD = Found->getSecond ();
3120+ return GD->getDescribedFunctionTemplate ();
3121+ }
3122+
3123+ if (auto *AliasTemplate = llvm::dyn_cast<TypeAliasTemplateDecl>(Template)) {
3124+ if (auto *FTD = DeclareAggregateDeductionGuideForTypeAlias (
3125+ *this , AliasTemplate, ParamTypes, Loc)) {
3126+ auto *GD = cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl ());
3127+ GD->setDeductionCandidateKind (DeductionCandidate::Aggregate);
3128+ AggregateDeductionCandidates[Hash] = GD;
3129+ return FTD;
3130+ }
3131+ }
3132+
30213133 if (CXXRecordDecl *DefRecord =
30223134 cast<CXXRecordDecl>(Template->getTemplatedDecl ())->getDefinition ()) {
30233135 if (TemplateDecl *DescribedTemplate =
@@ -3050,10 +3162,13 @@ FunctionTemplateDecl *Sema::DeclareImplicitDeductionGuideFromInitList(
30503162 Transform.NestedPattern ? Transform.NestedPattern : Transform.Template ;
30513163 ContextRAII SavedContext (*this , Pattern->getTemplatedDecl ());
30523164
3053- auto *DG = cast<FunctionTemplateDecl>(
3165+ auto *FTD = cast<FunctionTemplateDecl>(
30543166 Transform.buildSimpleDeductionGuide (ParamTypes));
30553167 SavedContext.pop ();
3056- return DG;
3168+ auto *GD = cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl ());
3169+ GD->setDeductionCandidateKind (DeductionCandidate::Aggregate);
3170+ AggregateDeductionCandidates[Hash] = GD;
3171+ return FTD;
30573172}
30583173
30593174void Sema::DeclareImplicitDeductionGuides (TemplateDecl *Template,
0 commit comments