@@ -2250,10 +2250,24 @@ class ExtractTypeForDeductionGuide
22502250struct ConvertConstructorToDeductionGuideTransform {
22512251 ConvertConstructorToDeductionGuideTransform (Sema &S,
22522252 ClassTemplateDecl *Template)
2253- : SemaRef(S), Template(Template) {}
2253+ : SemaRef(S), Template(Template) {
2254+ // If the template is nested, then we need to use the original
2255+ // pattern to iterate over the constructors.
2256+ ClassTemplateDecl *Pattern = Template;
2257+ while (Pattern->getInstantiatedFromMemberTemplate ()) {
2258+ if (Pattern->isMemberSpecialization ())
2259+ break ;
2260+ Pattern = Pattern->getInstantiatedFromMemberTemplate ();
2261+ NestedPattern = Pattern;
2262+ }
2263+
2264+ if (NestedPattern)
2265+ OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs (Template);
2266+ }
22542267
22552268 Sema &SemaRef;
22562269 ClassTemplateDecl *Template;
2270+ ClassTemplateDecl *NestedPattern = nullptr ;
22572271
22582272 DeclContext *DC = Template->getDeclContext ();
22592273 CXXRecordDecl *Primary = Template->getTemplatedDecl ();
@@ -2266,6 +2280,10 @@ struct ConvertConstructorToDeductionGuideTransform {
22662280 // depth-0 template parameters.
22672281 unsigned Depth1IndexAdjustment = Template->getTemplateParameters ()->size();
22682282
2283+ // Instantiation arguments for the outermost depth-1 templates
2284+ // when the template is nested
2285+ MultiLevelTemplateArgumentList OuterInstantiationArgs;
2286+
22692287 // / Transform a constructor declaration into a deduction guide.
22702288 NamedDecl *transformConstructor (FunctionTemplateDecl *FTD,
22712289 CXXConstructorDecl *CD) {
@@ -2284,21 +2302,43 @@ struct ConvertConstructorToDeductionGuideTransform {
22842302 if (FTD) {
22852303 TemplateParameterList *InnerParams = FTD->getTemplateParameters ();
22862304 SmallVector<NamedDecl *, 16 > AllParams;
2305+ SmallVector<TemplateArgument, 16 > Depth1Args;
22872306 AllParams.reserve (TemplateParams->size () + InnerParams->size ());
22882307 AllParams.insert (AllParams.begin (),
22892308 TemplateParams->begin (), TemplateParams->end ());
22902309 SubstArgs.reserve (InnerParams->size ());
2310+ Depth1Args.reserve (InnerParams->size ());
22912311
22922312 // Later template parameters could refer to earlier ones, so build up
22932313 // a list of substituted template arguments as we go.
22942314 for (NamedDecl *Param : *InnerParams) {
22952315 MultiLevelTemplateArgumentList Args;
22962316 Args.setKind (TemplateSubstitutionKind::Rewrite);
2297- Args.addOuterTemplateArguments (SubstArgs );
2317+ Args.addOuterTemplateArguments (Depth1Args );
22982318 Args.addOuterRetainedLevel ();
2319+ if (NestedPattern)
2320+ Args.addOuterRetainedLevels (NestedPattern->getTemplateDepth ());
22992321 NamedDecl *NewParam = transformTemplateParameter (Param, Args);
23002322 if (!NewParam)
23012323 return nullptr ;
2324+
2325+ // Constraints require that we substitute depth-1 arguments
2326+ // to match depths when substituted for evaluation later
2327+ Depth1Args.push_back (SemaRef.Context .getCanonicalTemplateArgument (
2328+ SemaRef.Context .getInjectedTemplateArg (NewParam)));
2329+
2330+ if (NestedPattern) {
2331+ TemplateDeclInstantiator Instantiator (SemaRef, DC,
2332+ OuterInstantiationArgs);
2333+ Instantiator.setEvaluateConstraints (false );
2334+ SemaRef.runWithSufficientStackSpace (NewParam->getLocation (), [&] {
2335+ NewParam = cast<NamedDecl>(Instantiator.Visit (NewParam));
2336+ });
2337+ }
2338+
2339+ assert (NewParam->getTemplateDepth () == 0 &&
2340+ " Unexpected template parameter depth" );
2341+
23022342 AllParams.push_back (NewParam);
23032343 SubstArgs.push_back (SemaRef.Context .getCanonicalTemplateArgument (
23042344 SemaRef.Context .getInjectedTemplateArg (NewParam)));
@@ -2309,8 +2349,10 @@ struct ConvertConstructorToDeductionGuideTransform {
23092349 if (Expr *InnerRC = InnerParams->getRequiresClause ()) {
23102350 MultiLevelTemplateArgumentList Args;
23112351 Args.setKind (TemplateSubstitutionKind::Rewrite);
2312- Args.addOuterTemplateArguments (SubstArgs );
2352+ Args.addOuterTemplateArguments (Depth1Args );
23132353 Args.addOuterRetainedLevel ();
2354+ if (NestedPattern)
2355+ Args.addOuterRetainedLevels (NestedPattern->getTemplateDepth ());
23142356 ExprResult E = SemaRef.SubstExpr (InnerRC, Args);
23152357 if (E.isInvalid ())
23162358 return nullptr ;
@@ -2333,6 +2375,9 @@ struct ConvertConstructorToDeductionGuideTransform {
23332375 Args.addOuterRetainedLevel ();
23342376 }
23352377
2378+ if (NestedPattern)
2379+ Args.addOuterRetainedLevels (NestedPattern->getTemplateDepth ());
2380+
23362381 FunctionProtoTypeLoc FPTL = CD->getTypeSourceInfo ()->getTypeLoc ()
23372382 .getAsAdjusted <FunctionProtoTypeLoc>();
23382383 assert (FPTL && " no prototype for constructor declaration" );
@@ -2394,7 +2439,7 @@ struct ConvertConstructorToDeductionGuideTransform {
23942439 // substitute it directly.
23952440 auto *NewTTP = TemplateTypeParmDecl::Create (
23962441 SemaRef.Context , DC, TTP->getBeginLoc (), TTP->getLocation (),
2397- /* Depth */ 0 , Depth1IndexAdjustment + TTP->getIndex (),
2442+ TTP-> getDepth () - 1 , Depth1IndexAdjustment + TTP->getIndex (),
23982443 TTP->getIdentifier (), TTP->wasDeclaredWithTypename (),
23992444 TTP->isParameterPack (), TTP->hasTypeConstraint (),
24002445 TTP->isExpandedParameterPack ()
@@ -2429,7 +2474,8 @@ struct ConvertConstructorToDeductionGuideTransform {
24292474 // the index of the parameter once it's done.
24302475 auto *NewParam =
24312476 cast<TemplateParmDecl>(SemaRef.SubstDecl (OldParam, DC, Args));
2432- assert (NewParam->getDepth () == 0 && " unexpected template param depth" );
2477+ assert (NewParam->getDepth () == OldParam->getDepth () - 1 &&
2478+ " unexpected template param depth" );
24332479 NewParam->setPosition (NewParam->getPosition () + Depth1IndexAdjustment);
24342480 return NewParam;
24352481 }
@@ -2446,6 +2492,9 @@ struct ConvertConstructorToDeductionGuideTransform {
24462492 for (auto *OldParam : TL.getParams ()) {
24472493 ParmVarDecl *NewParam =
24482494 transformFunctionTypeParam (OldParam, Args, MaterializedTypedefs);
2495+ if (NestedPattern && NewParam)
2496+ NewParam = transformFunctionTypeParam (NewParam, OuterInstantiationArgs,
2497+ MaterializedTypedefs);
24492498 if (!NewParam)
24502499 return QualType ();
24512500 ParamTypes.push_back (NewParam->getType ());
@@ -2655,9 +2704,12 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
26552704 // FIXME: Skip constructors for which deduction must necessarily fail (those
26562705 // for which some class template parameter without a default argument never
26572706 // appears in a deduced context).
2707+ ClassTemplateDecl *Pattern =
2708+ Transform.NestedPattern ? Transform.NestedPattern : Transform.Template ;
2709+ ContextRAII SavedContext (*this , Pattern->getTemplatedDecl ());
26582710 llvm::SmallPtrSet<NamedDecl *, 8 > ProcessedCtors;
26592711 bool AddedAny = false ;
2660- for (NamedDecl *D : LookupConstructors (Transform. Primary )) {
2712+ for (NamedDecl *D : LookupConstructors (Pattern-> getTemplatedDecl () )) {
26612713 D = D->getUnderlyingDecl ();
26622714 if (D->isInvalidDecl () || D->isImplicit ())
26632715 continue ;
@@ -2703,6 +2755,8 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
27032755 Transform.buildSimpleDeductionGuide (Transform.DeducedType ))
27042756 ->getTemplatedDecl ())
27052757 ->setDeductionCandidateKind (DeductionCandidate::Copy);
2758+
2759+ SavedContext.pop ();
27062760}
27072761
27082762// / Diagnose the presence of a default template argument on a
0 commit comments