diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index bff1124889f60..3d3e78e2889e9 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -942,6 +942,9 @@ Bug Fixes to C++ Support (`#57410 `_) and (`#76604 `_) +- Fixes CTAD for aggregates on nested template classes. Fixes: + (`#77599 `_) + Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ - Fixed an import failure of recursive friend class template. diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 408ee5f775804..48235941f62aa 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -10718,7 +10718,14 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( bool HasAnyDeductionGuide = false; auto SynthesizeAggrGuide = [&](InitListExpr *ListInit) { - auto *RD = cast(Template->getTemplatedDecl()); + auto *Pattern = Template; + while (Pattern->getInstantiatedFromMemberTemplate()) { + if (Pattern->isMemberSpecialization()) + break; + Pattern = Pattern->getInstantiatedFromMemberTemplate(); + } + + auto *RD = cast(Pattern->getTemplatedDecl()); if (!(RD->getDefinition() && RD->isAggregate())) return; QualType Ty = Context.getRecordType(RD); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 0655d36335206..839d508b911f0 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2418,6 +2418,9 @@ struct ConvertConstructorToDeductionGuideTransform { QualType Result = SemaRef.BuildFunctionType(DeducedType, ParamTypes, Loc, DeductionGuideName, EPI); TypeSourceInfo *TSI = SemaRef.Context.getTrivialTypeSourceInfo(Result, Loc); + if (NestedPattern) + TSI = SemaRef.SubstType(TSI, OuterInstantiationArgs, Loc, + DeductionGuideName); FunctionProtoTypeLoc FPTL = TSI->getTypeLoc().castAs(); @@ -2425,9 +2428,13 @@ struct ConvertConstructorToDeductionGuideTransform { // Build the parameters, needed during deduction / substitution. SmallVector Params; for (auto T : ParamTypes) { - ParmVarDecl *NewParam = ParmVarDecl::Create( - SemaRef.Context, DC, Loc, Loc, nullptr, T, - SemaRef.Context.getTrivialTypeSourceInfo(T, Loc), SC_None, nullptr); + auto *TSI = SemaRef.Context.getTrivialTypeSourceInfo(T, Loc); + if (NestedPattern) + TSI = SemaRef.SubstType(TSI, OuterInstantiationArgs, Loc, + DeclarationName()); + ParmVarDecl *NewParam = + ParmVarDecl::Create(SemaRef.Context, DC, Loc, Loc, nullptr, + TSI->getType(), TSI, SC_None, nullptr); NewParam->setScopeInfo(0, Params.size()); FPTL.setParam(Params.size(), NewParam); Params.push_back(NewParam); @@ -2670,8 +2677,14 @@ FunctionTemplateDecl *Sema::DeclareImplicitDeductionGuideFromInitList( if (BuildingDeductionGuides.isInvalid()) return nullptr; - return cast( + ClassTemplateDecl *Pattern = + Transform.NestedPattern ? Transform.NestedPattern : Transform.Template; + ContextRAII SavedContext(*this, Pattern->getTemplatedDecl()); + + auto *DG = cast( Transform.buildSimpleDeductionGuide(ParamTypes)); + SavedContext.pop(); + return DG; } void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template, diff --git a/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp b/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp index c44ec6918c7af..f3af6e8d6c17d 100644 --- a/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp +++ b/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -std=c++20 -verify %s -// expected-no-diagnostics template struct S { template struct N { @@ -58,3 +57,21 @@ template struct requires_clause { requires_clause::B req(1, 2); using RC = decltype(req); using RC = requires_clause::B; + +template struct nested_init_list { + template Y> + struct B { // #INIT_LIST_INNER + X x; + Y y; + }; +}; + +nested_init_list::B nil {1, 2}; +using NIL = decltype(nil); +using NIL = nested_init_list::B; + +// expected-error@+1 {{no viable constructor or deduction guide for deduction of template arguments of 'B'}} +nested_init_list::B nil_invalid {1, ""}; +// expected-note@#INIT_LIST_INNER {{candidate template ignored: substitution failure [with Y = const char *]: constraints not satisfied for class template 'B' [with Y = const char *]}} +// expected-note@#INIT_LIST_INNER {{candidate function template not viable: requires 1 argument, but 2 were provided}} +// expected-note@#INIT_LIST_INNER {{candidate function template not viable: requires 0 arguments, but 2 were provided}}