Author: antangelo Date: 2024-01-17T18:03:20-05:00 New Revision: 04a69a10f63dae3c03cdfa5e199d8ea4458398b5
URL: https://github.com/llvm/llvm-project/commit/04a69a10f63dae3c03cdfa5e199d8ea4458398b5 DIFF: https://github.com/llvm/llvm-project/commit/04a69a10f63dae3c03cdfa5e199d8ea4458398b5.diff LOG: [clang] Fix CTAD for aggregates for nested template classes (#78387) Use the template pattern in determining whether to synthesize the aggregate deduction guide, and update DeclareImplicitDeductionGuideFromInitList to substitute outer template arguments. Fixes #77599 Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaInit.cpp clang/lib/Sema/SemaTemplate.cpp clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index bff1124889f606c..3d3e78e2889e976 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -942,6 +942,9 @@ Bug Fixes to C++ Support (`#57410 <https://github.com/llvm/llvm-project/issues/57410>`_) and (`#76604 <https://github.com/llvm/llvm-project/issues/57410>`_) +- Fixes CTAD for aggregates on nested template classes. Fixes: + (`#77599 <https://github.com/llvm/llvm-project/issues/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 408ee5f775804b6..48235941f62aa23 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<CXXRecordDecl>(Template->getTemplatedDecl()); + auto *Pattern = Template; + while (Pattern->getInstantiatedFromMemberTemplate()) { + if (Pattern->isMemberSpecialization()) + break; + Pattern = Pattern->getInstantiatedFromMemberTemplate(); + } + + auto *RD = cast<CXXRecordDecl>(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 0655d3633520676..839d508b911f063 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<FunctionProtoTypeLoc>(); @@ -2425,9 +2428,13 @@ struct ConvertConstructorToDeductionGuideTransform { // Build the parameters, needed during deduction / substitution. SmallVector<ParmVarDecl*, 4> 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<FunctionTemplateDecl>( + ClassTemplateDecl *Pattern = + Transform.NestedPattern ? Transform.NestedPattern : Transform.Template; + ContextRAII SavedContext(*this, Pattern->getTemplatedDecl()); + + auto *DG = cast<FunctionTemplateDecl>( 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 c44ec6918c7afb1..f3af6e8d6c17da0 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<class T> struct S { template<class U> struct N { @@ -58,3 +57,21 @@ template<class X> struct requires_clause { requires_clause<int>::B req(1, 2); using RC = decltype(req); using RC = requires_clause<int>::B<int>; + +template<typename X> struct nested_init_list { + template<C<X> Y> + struct B { // #INIT_LIST_INNER + X x; + Y y; + }; +}; + +nested_init_list<int>::B nil {1, 2}; +using NIL = decltype(nil); +using NIL = nested_init_list<int>::B<int>; + +// expected-error@+1 {{no viable constructor or deduction guide for deduction of template arguments of 'B'}} +nested_init_list<int>::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}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits