@@ -283,8 +283,7 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD,
283
283
return Response::ChangeDecl (FTD->getLexicalDeclContext ());
284
284
}
285
285
286
- Response HandleRecordDecl (Sema &SemaRef,
287
- const CXXRecordDecl *Rec,
286
+ Response HandleRecordDecl (Sema &SemaRef, const CXXRecordDecl *Rec,
288
287
MultiLevelTemplateArgumentList &Result,
289
288
ASTContext &Context,
290
289
bool ForConstraintInstantiation) {
@@ -318,35 +317,68 @@ Response HandleRecordDecl(Sema &SemaRef,
318
317
if (Rec->isLambda ()) {
319
318
if (const Decl *LCD = Rec->getLambdaContextDecl ())
320
319
return Response::ChangeDecl (LCD);
320
+ // Attempt to retrieve the template arguments for a using alias declaration.
321
+ // This is necessary for constraint checking, since we always keep
322
+ // constraints relative to the primary template.
321
323
if (ForConstraintInstantiation && !SemaRef.CodeSynthesisContexts .empty ()) {
322
324
for (auto &CSC : llvm::reverse (SemaRef.CodeSynthesisContexts )) {
323
- if (CSC.Kind == Sema::CodeSynthesisContext::SynthesisKind::TypeAliasTemplateInstantiation) {
324
- auto *TATD = cast<TypeAliasTemplateDecl>(CSC.Entity ), *CurrentTATD = TATD;
325
- FunctionDecl *LambdaCallOperator = Rec->getLambdaCallOperator ();
326
- while (true ) {
327
- auto *FTD = dyn_cast_if_present<FunctionTemplateDecl>(
328
- LambdaCallOperator->getDescribedTemplate ());
329
- if (FTD && FTD->getInstantiatedFromMemberTemplate ()) {
330
- LambdaCallOperator =
331
- FTD->getInstantiatedFromMemberTemplate ()->getTemplatedDecl ();
332
- } else if (auto *Prev = cast<CXXMethodDecl>(LambdaCallOperator)
333
- ->getInstantiatedFromMemberFunction ())
334
- LambdaCallOperator = Prev;
335
- else
336
- break ;
337
- }
338
- while (TATD->getInstantiatedFromMemberTemplate ())
339
- TATD = TATD->getInstantiatedFromMemberTemplate ();
340
- // Constraint template parameters have a deeper depth.
341
- if (cast<CXXRecordDecl>(LambdaCallOperator->getDeclContext ())
342
- ->getTemplateDepth () == TATD->getTemplateDepth () &&
343
- getLambdaAwareParentOfDeclContext (LambdaCallOperator) ==
344
- TATD->getDeclContext ()) {
345
- Result.addOuterTemplateArguments (CurrentTATD,
346
- CSC.template_arguments (),
347
- /* Final=*/ false );
348
- return Response::ChangeDecl (CurrentTATD->getDeclContext ());
349
- }
325
+ if (CSC.Kind != Sema::CodeSynthesisContext::SynthesisKind::
326
+ TypeAliasTemplateInstantiation)
327
+ continue ;
328
+ auto *TATD = cast<TypeAliasTemplateDecl>(CSC.Entity ),
329
+ *CurrentTATD = TATD;
330
+ FunctionDecl *LambdaCallOperator = Rec->getLambdaCallOperator ();
331
+ // Retrieve the 'primary' template for a lambda call operator. It's
332
+ // unfortunate that we only have the mappings of call operators rather
333
+ // than lambda classes.
334
+ while (true ) {
335
+ auto *FTD = dyn_cast_if_present<FunctionTemplateDecl>(
336
+ LambdaCallOperator->getDescribedTemplate ());
337
+ if (FTD && FTD->getInstantiatedFromMemberTemplate ()) {
338
+ LambdaCallOperator =
339
+ FTD->getInstantiatedFromMemberTemplate ()->getTemplatedDecl ();
340
+ } else if (auto *Prev = cast<CXXMethodDecl>(LambdaCallOperator)
341
+ ->getInstantiatedFromMemberFunction ())
342
+ LambdaCallOperator = Prev;
343
+ else
344
+ break ;
345
+ }
346
+ // Same applies for type alias Decl. We perform this to obtain the
347
+ // "canonical" template parameter depths.
348
+ while (TATD->getInstantiatedFromMemberTemplate ())
349
+ TATD = TATD->getInstantiatedFromMemberTemplate ();
350
+ // Tell if we're currently inside of a lambda expression that is
351
+ // surrounded by a using alias declaration. e.g.
352
+ // template <class> using type = decltype([](auto) { ^ }());
353
+ // By checking if:
354
+ // 1. The lambda expression and the using alias declaration share the
355
+ // same declaration context.
356
+ // 2. They have the same template depth.
357
+ // Then we assume the template arguments from the using alias
358
+ // declaration are essential for constraint instantiation. We have to do
359
+ // so since a TypeAliasTemplateDecl (or a TypeAliasDecl) is never a
360
+ // DeclContext, nor does it have an associated specialization Decl from
361
+ // which we could collect these template arguments.
362
+ if (cast<CXXRecordDecl>(LambdaCallOperator->getDeclContext ())
363
+ ->getTemplateDepth () == TATD->getTemplateDepth () &&
364
+ getLambdaAwareParentOfDeclContext (LambdaCallOperator) ==
365
+ TATD->getDeclContext ()) {
366
+ Result.addOuterTemplateArguments (CurrentTATD,
367
+ CSC.template_arguments (),
368
+ /* Final=*/ false );
369
+ // Visit the parent of the current type alias declaration rather than
370
+ // the lambda thereof. We have the following case:
371
+ // struct S {
372
+ // template <class> using T = decltype([]<Concept> {} ());
373
+ // };
374
+ // void foo() {
375
+ // S::T var;
376
+ // }
377
+ // The instantiated lambda expression (which we're visiting at 'var')
378
+ // has a function DeclContext 'foo' rather than the Record DeclContext
379
+ // S. This seems to be an oversight that we may want to set a Sema
380
+ // Context from the CXXScopeSpec before substituting into T to me.
381
+ return Response::ChangeDecl (CurrentTATD->getDeclContext ());
350
382
}
351
383
}
352
384
}
@@ -447,7 +479,8 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
447
479
R = HandleFunction (Function, Result, Pattern, RelativeToPrimary,
448
480
ForConstraintInstantiation);
449
481
} else if (const auto *Rec = dyn_cast<CXXRecordDecl>(CurDecl)) {
450
- R = HandleRecordDecl (*this , Rec, Result, Context, ForConstraintInstantiation);
482
+ R = HandleRecordDecl (*this , Rec, Result, Context,
483
+ ForConstraintInstantiation);
451
484
} else if (const auto *CSD =
452
485
dyn_cast<ImplicitConceptSpecializationDecl>(CurDecl)) {
453
486
R = HandleImplicitConceptSpecializationDecl (CSD, Result);
@@ -1583,7 +1616,8 @@ namespace {
1583
1616
CXXRecordDecl::LambdaDependencyKind
1584
1617
ComputeLambdaDependency (LambdaScopeInfo *LSI) {
1585
1618
auto &CCS = SemaRef.CodeSynthesisContexts .back ();
1586
- if (CCS.Kind == Sema::CodeSynthesisContext::TypeAliasTemplateInstantiation) {
1619
+ if (CCS.Kind ==
1620
+ Sema::CodeSynthesisContext::TypeAliasTemplateInstantiation) {
1587
1621
unsigned TypeAliasDeclDepth = CCS.Entity ->getTemplateDepth ();
1588
1622
if (TypeAliasDeclDepth >= TemplateArgs.getNumSubstitutedLevels ())
1589
1623
return CXXRecordDecl::LambdaDependencyKind::LDK_AlwaysDependent;
0 commit comments