@@ -2755,23 +2755,42 @@ bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) {
2755
2755
return false ;
2756
2756
}
2757
2757
2758
- // Build deduction guides for a type alias template.
2759
- void DeclareImplicitDeductionGuidesForTypeAlias (
2760
- Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
2761
- if (AliasTemplate->isInvalidDecl ())
2762
- return ;
2763
- auto &Context = SemaRef.Context ;
2764
- // FIXME: if there is an explicit deduction guide after the first use of the
2765
- // type alias usage, we will not cover this explicit deduction guide. fix this
2766
- // case.
2767
- if (hasDeclaredDeductionGuides (
2768
- Context.DeclarationNames .getCXXDeductionGuideName (AliasTemplate),
2769
- AliasTemplate->getDeclContext ()))
2770
- return ;
2758
+ NamedDecl *transformTemplateParameter (Sema &SemaRef, DeclContext *DC,
2759
+ NamedDecl *TemplateParam,
2760
+ MultiLevelTemplateArgumentList &Args,
2761
+ unsigned NewIndex) {
2762
+ if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam))
2763
+ return transformTemplateTypeParam (SemaRef, DC, TTP, Args, TTP->getDepth (),
2764
+ NewIndex);
2765
+ if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam))
2766
+ return transformTemplateParam (SemaRef, DC, TTP, Args, NewIndex,
2767
+ TTP->getDepth ());
2768
+ if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam))
2769
+ return transformTemplateParam (SemaRef, DC, NTTP, Args, NewIndex,
2770
+ NTTP->getDepth ());
2771
+ return nullptr ;
2772
+ }
2773
+
2774
+ Expr *transformRequireClause (Sema &SemaRef, FunctionTemplateDecl *FTD,
2775
+ llvm::ArrayRef<TemplateArgument> TransformedArgs) {
2776
+ Expr *RC = FTD->getTemplateParameters ()->getRequiresClause ();
2777
+ if (!RC)
2778
+ return nullptr ;
2779
+ MultiLevelTemplateArgumentList Args;
2780
+ Args.setKind (TemplateSubstitutionKind::Rewrite);
2781
+ Args.addOuterTemplateArguments (TransformedArgs);
2782
+ ExprResult E = SemaRef.SubstExpr (RC, Args);
2783
+ if (E.isInvalid ())
2784
+ return nullptr ;
2785
+ return E.getAs <Expr>();
2786
+ }
2787
+
2788
+ std::pair<TemplateDecl *, llvm::ArrayRef<TemplateArgument>>
2789
+ getRHSTemplateDeclAndArgs (Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) {
2771
2790
// Unwrap the sugared ElaboratedType.
2772
2791
auto RhsType = AliasTemplate->getTemplatedDecl ()
2773
2792
->getUnderlyingType ()
2774
- .getSingleStepDesugaredType (Context);
2793
+ .getSingleStepDesugaredType (SemaRef. Context );
2775
2794
TemplateDecl *Template = nullptr ;
2776
2795
llvm::ArrayRef<TemplateArgument> AliasRhsTemplateArgs;
2777
2796
if (const auto *TST = RhsType->getAs <TemplateSpecializationType>()) {
@@ -2792,6 +2811,24 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
2792
2811
} else {
2793
2812
assert (false && " unhandled RHS type of the alias" );
2794
2813
}
2814
+ return {Template, AliasRhsTemplateArgs};
2815
+ }
2816
+
2817
+ // Build deduction guides for a type alias template.
2818
+ void DeclareImplicitDeductionGuidesForTypeAlias (
2819
+ Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate, SourceLocation Loc) {
2820
+ if (AliasTemplate->isInvalidDecl ())
2821
+ return ;
2822
+ auto &Context = SemaRef.Context ;
2823
+ // FIXME: if there is an explicit deduction guide after the first use of the
2824
+ // type alias usage, we will not cover this explicit deduction guide. fix this
2825
+ // case.
2826
+ if (hasDeclaredDeductionGuides (
2827
+ Context.DeclarationNames .getCXXDeductionGuideName (AliasTemplate),
2828
+ AliasTemplate->getDeclContext ()))
2829
+ return ;
2830
+ auto [Template, AliasRhsTemplateArgs] =
2831
+ getRHSTemplateDeclAndArgs (SemaRef, AliasTemplate);
2795
2832
if (!Template)
2796
2833
return ;
2797
2834
DeclarationNameInfo NameInfo (
@@ -2804,6 +2841,13 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
2804
2841
FunctionTemplateDecl *F = dyn_cast<FunctionTemplateDecl>(G);
2805
2842
if (!F)
2806
2843
continue ;
2844
+ // The **aggregate** deduction guides are handled in a different code path
2845
+ // (DeclareImplicitDeductionGuideFromInitList), which involves the tricky
2846
+ // cache.
2847
+ if (cast<CXXDeductionGuideDecl>(F->getTemplatedDecl ())
2848
+ ->getDeductionCandidateKind () == DeductionCandidate::Aggregate)
2849
+ continue ;
2850
+
2807
2851
auto RType = F->getTemplatedDecl ()->getReturnType ();
2808
2852
// The (trailing) return type of the deduction guide.
2809
2853
const TemplateSpecializationType *FReturnType =
@@ -2886,21 +2930,6 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
2886
2930
// parameters, used for building `TemplateArgsForBuildingFPrime`.
2887
2931
SmallVector<TemplateArgument, 16 > TransformedDeducedAliasArgs (
2888
2932
AliasTemplate->getTemplateParameters ()->size ());
2889
- auto TransformTemplateParameter =
2890
- [&SemaRef](DeclContext *DC, NamedDecl *TemplateParam,
2891
- MultiLevelTemplateArgumentList &Args,
2892
- unsigned NewIndex) -> NamedDecl * {
2893
- if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam))
2894
- return transformTemplateTypeParam (SemaRef, DC, TTP, Args,
2895
- TTP->getDepth (), NewIndex);
2896
- if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam))
2897
- return transformTemplateParam (SemaRef, DC, TTP, Args, NewIndex,
2898
- TTP->getDepth ());
2899
- if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam))
2900
- return transformTemplateParam (SemaRef, DC, NTTP, Args, NewIndex,
2901
- NTTP->getDepth ());
2902
- return nullptr ;
2903
- };
2904
2933
2905
2934
for (unsigned AliasTemplateParamIdx : DeducedAliasTemplateParams) {
2906
2935
auto *TP = AliasTemplate->getTemplateParameters ()->getParam (
@@ -2910,9 +2939,9 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
2910
2939
MultiLevelTemplateArgumentList Args;
2911
2940
Args.setKind (TemplateSubstitutionKind::Rewrite);
2912
2941
Args.addOuterTemplateArguments (TransformedDeducedAliasArgs);
2913
- NamedDecl *NewParam =
2914
- TransformTemplateParameter ( AliasTemplate->getDeclContext (), TP, Args,
2915
- /* NewIndex*/ FPrimeTemplateParams.size ());
2942
+ NamedDecl *NewParam = transformTemplateParameter (
2943
+ SemaRef, AliasTemplate->getDeclContext (), TP, Args,
2944
+ /* NewIndex*/ FPrimeTemplateParams.size ());
2916
2945
FPrimeTemplateParams.push_back (NewParam);
2917
2946
2918
2947
auto NewTemplateArgument = Context.getCanonicalTemplateArgument (
@@ -2928,8 +2957,8 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
2928
2957
// We take a shortcut here, it is ok to reuse the
2929
2958
// TemplateArgsForBuildingFPrime.
2930
2959
Args.addOuterTemplateArguments (TemplateArgsForBuildingFPrime);
2931
- NamedDecl *NewParam = TransformTemplateParameter (
2932
- F->getDeclContext (), TP, Args, FPrimeTemplateParams.size ());
2960
+ NamedDecl *NewParam = transformTemplateParameter (
2961
+ SemaRef, F->getDeclContext (), TP, Args, FPrimeTemplateParams.size ());
2933
2962
FPrimeTemplateParams.push_back (NewParam);
2934
2963
2935
2964
assert (TemplateArgsForBuildingFPrime[FTemplateParamIdx].isNull () &&
@@ -2939,16 +2968,8 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
2939
2968
Context.getInjectedTemplateArg (NewParam));
2940
2969
}
2941
2970
// Substitute new template parameters into requires-clause if present.
2942
- Expr *RequiresClause = nullptr ;
2943
- if (Expr *InnerRC = F->getTemplateParameters ()->getRequiresClause ()) {
2944
- MultiLevelTemplateArgumentList Args;
2945
- Args.setKind (TemplateSubstitutionKind::Rewrite);
2946
- Args.addOuterTemplateArguments (TemplateArgsForBuildingFPrime);
2947
- ExprResult E = SemaRef.SubstExpr (InnerRC, Args);
2948
- if (E.isInvalid ())
2949
- return ;
2950
- RequiresClause = E.getAs <Expr>();
2951
- }
2971
+ Expr *RequiresClause =
2972
+ transformRequireClause (SemaRef, F, TemplateArgsForBuildingFPrime);
2952
2973
// FIXME: implement the is_deducible constraint per C++
2953
2974
// [over.match.class.deduct]p3.3:
2954
2975
// ... and a constraint that is satisfied if and only if the arguments
@@ -3014,8 +3035,78 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
3014
3035
}
3015
3036
}
3016
3037
3038
+ // Build an aggregate deduction guide for a type alias template.
3039
+ FunctionTemplateDecl *DeclareAggrecateDeductionGuideForTypeAlias (
3040
+ Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate,
3041
+ MutableArrayRef<QualType> ParamTypes, SourceLocation Loc) {
3042
+ TemplateDecl *RHSTemplate =
3043
+ getRHSTemplateDeclAndArgs (SemaRef, AliasTemplate).first ;
3044
+ if (!RHSTemplate)
3045
+ return nullptr ;
3046
+ auto *RHSDeductionGuide = SemaRef.DeclareImplicitDeductionGuideFromInitList (
3047
+ RHSTemplate, ParamTypes, Loc);
3048
+ if (!RHSDeductionGuide)
3049
+ return nullptr ;
3050
+
3051
+ LocalInstantiationScope Scope (SemaRef);
3052
+
3053
+ // Build a new template parameter list for the synthesized aggregate deduction
3054
+ // guide by transforming the one from RHSDeductionGuide.
3055
+ SmallVector<NamedDecl *> TransformedTemplateParams;
3056
+ // Template args that refer to the rebuilt template parameters.
3057
+ // All template arguments must be initialized in advance.
3058
+ SmallVector<TemplateArgument> TransformedTemplateArgs (
3059
+ RHSDeductionGuide->getTemplateParameters ()->size ());
3060
+ for (auto *TP : *RHSDeductionGuide->getTemplateParameters ()) {
3061
+ // Rebuild any internal references to earlier parameters and reindex as
3062
+ // we go.
3063
+ MultiLevelTemplateArgumentList Args;
3064
+ Args.setKind (TemplateSubstitutionKind::Rewrite);
3065
+ Args.addOuterTemplateArguments (TransformedTemplateArgs);
3066
+ NamedDecl *NewParam = transformTemplateParameter (
3067
+ SemaRef, AliasTemplate->getDeclContext (), TP, Args,
3068
+ /* NewIndex=*/ TransformedTemplateParams.size ());
3069
+
3070
+ TransformedTemplateArgs[TransformedTemplateParams.size ()] =
3071
+ SemaRef.Context .getCanonicalTemplateArgument (
3072
+ SemaRef.Context .getInjectedTemplateArg (NewParam));
3073
+ TransformedTemplateParams.push_back (NewParam);
3074
+ }
3075
+ // FIXME: implement the is_deducible constraint per C++
3076
+ // [over.match.class.deduct]p3.3.
3077
+ Expr *TransformedRequiresClause = transformRequireClause (
3078
+ SemaRef, RHSDeductionGuide, TransformedTemplateArgs);
3079
+ auto *TransformedTemplateParameterList = TemplateParameterList::Create (
3080
+ SemaRef.Context , AliasTemplate->getTemplateParameters ()->getTemplateLoc (),
3081
+ AliasTemplate->getTemplateParameters ()->getLAngleLoc (),
3082
+ TransformedTemplateParams,
3083
+ AliasTemplate->getTemplateParameters ()->getRAngleLoc (),
3084
+ TransformedRequiresClause);
3085
+ auto *TransformedTemplateArgList = TemplateArgumentList::CreateCopy (
3086
+ SemaRef.Context , TransformedTemplateArgs);
3087
+
3088
+ if (auto *TransformedDeductionGuide = SemaRef.InstantiateFunctionDeclaration (
3089
+ RHSDeductionGuide, TransformedTemplateArgList,
3090
+ AliasTemplate->getLocation (),
3091
+ Sema::CodeSynthesisContext::BuildingDeductionGuides)) {
3092
+ auto *GD =
3093
+ llvm::dyn_cast<clang::CXXDeductionGuideDecl>(TransformedDeductionGuide);
3094
+ FunctionTemplateDecl *Result = buildDeductionGuide (
3095
+ SemaRef, AliasTemplate, TransformedTemplateParameterList,
3096
+ GD->getCorrespondingConstructor (), GD->getExplicitSpecifier (),
3097
+ GD->getTypeSourceInfo (), AliasTemplate->getBeginLoc (),
3098
+ AliasTemplate->getLocation (), AliasTemplate->getEndLoc (),
3099
+ GD->isImplicit ());
3100
+ cast<CXXDeductionGuideDecl>(Result->getTemplatedDecl ())
3101
+ ->setDeductionCandidateKind (DeductionCandidate::Aggregate);
3102
+ return Result;
3103
+ }
3104
+ return nullptr ;
3105
+ }
3106
+
3017
3107
} // namespace
3018
3108
3109
+ // FIXME: rename to DeclareAggrecateDeductionGuide.
3019
3110
FunctionTemplateDecl *Sema::DeclareImplicitDeductionGuideFromInitList (
3020
3111
TemplateDecl *Template, MutableArrayRef<QualType> ParamTypes,
3021
3112
SourceLocation Loc) {
@@ -3024,17 +3115,22 @@ FunctionTemplateDecl *Sema::DeclareImplicitDeductionGuideFromInitList(
3024
3115
for (auto &T : ParamTypes)
3025
3116
T.getCanonicalType ().Profile (ID);
3026
3117
unsigned Hash = ID.ComputeHash ();
3027
-
3118
+
3028
3119
auto Found = AggregateDeductionCandidates.find (Hash);
3029
3120
if (Found != AggregateDeductionCandidates.end ()) {
3030
3121
CXXDeductionGuideDecl *GD = Found->getSecond ();
3031
3122
return GD->getDescribedFunctionTemplate ();
3032
3123
}
3033
-
3034
- // if (auto *AliasTemplate = llvm::dyn_cast<TypeAliasTemplateDecl>(Template)) {
3035
- // DeclareImplicitDeductionGuidesForTypeAlias(*this, AliasTemplate, Loc);
3036
- // return;
3037
- // }
3124
+
3125
+ if (auto *AliasTemplate = llvm::dyn_cast<TypeAliasTemplateDecl>(Template)) {
3126
+ if (auto *FTD = DeclareAggrecateDeductionGuideForTypeAlias (
3127
+ *this , AliasTemplate, ParamTypes, Loc)) {
3128
+ auto *GD = cast<CXXDeductionGuideDecl>(FTD->getTemplatedDecl ());
3129
+ GD->setDeductionCandidateKind (DeductionCandidate::Aggregate);
3130
+ AggregateDeductionCandidates[Hash] = GD;
3131
+ return FTD;
3132
+ }
3133
+ }
3038
3134
3039
3135
if (CXXRecordDecl *DefRecord =
3040
3136
cast<CXXRecordDecl>(Template->getTemplatedDecl ())->getDefinition ()) {
0 commit comments