@@ -2250,10 +2250,24 @@ class ExtractTypeForDeductionGuide
2250
2250
struct ConvertConstructorToDeductionGuideTransform {
2251
2251
ConvertConstructorToDeductionGuideTransform (Sema &S,
2252
2252
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
+ }
2254
2267
2255
2268
Sema &SemaRef;
2256
2269
ClassTemplateDecl *Template;
2270
+ ClassTemplateDecl *NestedPattern = nullptr ;
2257
2271
2258
2272
DeclContext *DC = Template->getDeclContext ();
2259
2273
CXXRecordDecl *Primary = Template->getTemplatedDecl ();
@@ -2266,6 +2280,10 @@ struct ConvertConstructorToDeductionGuideTransform {
2266
2280
// depth-0 template parameters.
2267
2281
unsigned Depth1IndexAdjustment = Template->getTemplateParameters ()->size();
2268
2282
2283
+ // Instantiation arguments for the outermost depth-1 templates
2284
+ // when the template is nested
2285
+ MultiLevelTemplateArgumentList OuterInstantiationArgs;
2286
+
2269
2287
// / Transform a constructor declaration into a deduction guide.
2270
2288
NamedDecl *transformConstructor (FunctionTemplateDecl *FTD,
2271
2289
CXXConstructorDecl *CD) {
@@ -2284,21 +2302,43 @@ struct ConvertConstructorToDeductionGuideTransform {
2284
2302
if (FTD) {
2285
2303
TemplateParameterList *InnerParams = FTD->getTemplateParameters ();
2286
2304
SmallVector<NamedDecl *, 16 > AllParams;
2305
+ SmallVector<TemplateArgument, 16 > Depth1Args;
2287
2306
AllParams.reserve (TemplateParams->size () + InnerParams->size ());
2288
2307
AllParams.insert (AllParams.begin (),
2289
2308
TemplateParams->begin (), TemplateParams->end ());
2290
2309
SubstArgs.reserve (InnerParams->size ());
2310
+ Depth1Args.reserve (InnerParams->size ());
2291
2311
2292
2312
// Later template parameters could refer to earlier ones, so build up
2293
2313
// a list of substituted template arguments as we go.
2294
2314
for (NamedDecl *Param : *InnerParams) {
2295
2315
MultiLevelTemplateArgumentList Args;
2296
2316
Args.setKind (TemplateSubstitutionKind::Rewrite);
2297
- Args.addOuterTemplateArguments(SubstArgs );
2317
+ Args.addOuterTemplateArguments (Depth1Args );
2298
2318
Args.addOuterRetainedLevel ();
2319
+ if (NestedPattern)
2320
+ Args.addOuterRetainedLevels (NestedPattern->getTemplateDepth ());
2299
2321
NamedDecl *NewParam = transformTemplateParameter (Param, Args);
2300
2322
if (!NewParam)
2301
2323
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
+
2302
2342
AllParams.push_back (NewParam);
2303
2343
SubstArgs.push_back (SemaRef.Context .getCanonicalTemplateArgument (
2304
2344
SemaRef.Context .getInjectedTemplateArg (NewParam)));
@@ -2309,8 +2349,10 @@ struct ConvertConstructorToDeductionGuideTransform {
2309
2349
if (Expr *InnerRC = InnerParams->getRequiresClause ()) {
2310
2350
MultiLevelTemplateArgumentList Args;
2311
2351
Args.setKind (TemplateSubstitutionKind::Rewrite);
2312
- Args.addOuterTemplateArguments(SubstArgs );
2352
+ Args.addOuterTemplateArguments (Depth1Args );
2313
2353
Args.addOuterRetainedLevel ();
2354
+ if (NestedPattern)
2355
+ Args.addOuterRetainedLevels (NestedPattern->getTemplateDepth ());
2314
2356
ExprResult E = SemaRef.SubstExpr (InnerRC, Args);
2315
2357
if (E.isInvalid ())
2316
2358
return nullptr ;
@@ -2333,6 +2375,9 @@ struct ConvertConstructorToDeductionGuideTransform {
2333
2375
Args.addOuterRetainedLevel ();
2334
2376
}
2335
2377
2378
+ if (NestedPattern)
2379
+ Args.addOuterRetainedLevels (NestedPattern->getTemplateDepth ());
2380
+
2336
2381
FunctionProtoTypeLoc FPTL = CD->getTypeSourceInfo ()->getTypeLoc ()
2337
2382
.getAsAdjusted <FunctionProtoTypeLoc>();
2338
2383
assert (FPTL && " no prototype for constructor declaration" );
@@ -2394,7 +2439,7 @@ struct ConvertConstructorToDeductionGuideTransform {
2394
2439
// substitute it directly.
2395
2440
auto *NewTTP = TemplateTypeParmDecl::Create (
2396
2441
SemaRef.Context , DC, TTP->getBeginLoc (), TTP->getLocation (),
2397
- /*Depth*/ 0 , Depth1IndexAdjustment + TTP->getIndex(),
2442
+ TTP-> getDepth () - 1 , Depth1IndexAdjustment + TTP->getIndex (),
2398
2443
TTP->getIdentifier (), TTP->wasDeclaredWithTypename (),
2399
2444
TTP->isParameterPack (), TTP->hasTypeConstraint (),
2400
2445
TTP->isExpandedParameterPack ()
@@ -2429,7 +2474,8 @@ struct ConvertConstructorToDeductionGuideTransform {
2429
2474
// the index of the parameter once it's done.
2430
2475
auto *NewParam =
2431
2476
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" );
2433
2479
NewParam->setPosition (NewParam->getPosition () + Depth1IndexAdjustment);
2434
2480
return NewParam;
2435
2481
}
@@ -2446,6 +2492,9 @@ struct ConvertConstructorToDeductionGuideTransform {
2446
2492
for (auto *OldParam : TL.getParams ()) {
2447
2493
ParmVarDecl *NewParam =
2448
2494
transformFunctionTypeParam (OldParam, Args, MaterializedTypedefs);
2495
+ if (NestedPattern && NewParam)
2496
+ NewParam = transformFunctionTypeParam (NewParam, OuterInstantiationArgs,
2497
+ MaterializedTypedefs);
2449
2498
if (!NewParam)
2450
2499
return QualType ();
2451
2500
ParamTypes.push_back (NewParam->getType ());
@@ -2655,9 +2704,12 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
2655
2704
// FIXME: Skip constructors for which deduction must necessarily fail (those
2656
2705
// for which some class template parameter without a default argument never
2657
2706
// appears in a deduced context).
2707
+ ClassTemplateDecl *Pattern =
2708
+ Transform.NestedPattern ? Transform.NestedPattern : Transform.Template ;
2709
+ ContextRAII SavedContext (*this , Pattern->getTemplatedDecl ());
2658
2710
llvm::SmallPtrSet<NamedDecl *, 8 > ProcessedCtors;
2659
2711
bool AddedAny = false ;
2660
- for (NamedDecl *D : LookupConstructors(Transform.Primary )) {
2712
+ for (NamedDecl *D : LookupConstructors (Pattern-> getTemplatedDecl () )) {
2661
2713
D = D->getUnderlyingDecl ();
2662
2714
if (D->isInvalidDecl () || D->isImplicit ())
2663
2715
continue ;
@@ -2703,6 +2755,8 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
2703
2755
Transform.buildSimpleDeductionGuide (Transform.DeducedType ))
2704
2756
->getTemplatedDecl ())
2705
2757
->setDeductionCandidateKind (DeductionCandidate::Copy);
2758
+
2759
+ SavedContext.pop ();
2706
2760
}
2707
2761
2708
2762
// / Diagnose the presence of a default template argument on a
0 commit comments