https://github.com/antangelo updated https://github.com/llvm/llvm-project/pull/68379
>From 8e37e6f9e9d2cd2cd142165fe886c11a0bd1f3ab Mon Sep 17 00:00:00 2001 From: Antonio Abbatangelo <cont...@antangelo.com> Date: Thu, 5 Oct 2023 21:07:37 -0400 Subject: [PATCH 1/2] [clang][Sema] Use original template pattern when declaring implicit deduction guides for nested template classes When a nested template is instantiated, the template pattern of the inner class is not copied into the outer class ClassTemplateSpecializationDecl. The specialization contains a ClassTemplateDecl with an empty record that points to the original template pattern instead. As a result, when looking up the constructors of the inner class, no results are returned. This patch finds the original template pattern and uses that for the lookup instead. Based on CWG2471 we must also substitute the known outer template arguments when creating deduction guides for the inner class. Fixes #46200 Fixes #57812 --- clang/lib/Sema/SemaTemplate.cpp | 22 ++++++++++++++++++- .../nested-implicit-deduction-guides.cpp | 12 ++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index ff370dd1e080b2b..fba5b2213917065 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2250,6 +2250,7 @@ struct ConvertConstructorToDeductionGuideTransform { Sema &SemaRef; ClassTemplateDecl *Template; + ClassTemplateDecl *NestedPattern = nullptr; DeclContext *DC = Template->getDeclContext(); CXXRecordDecl *Primary = Template->getTemplatedDecl(); @@ -2327,6 +2328,8 @@ struct ConvertConstructorToDeductionGuideTransform { if (FTD) { Args.addOuterTemplateArguments(SubstArgs); Args.addOuterRetainedLevel(); + if (NestedPattern) + Args.addOuterRetainedLevels(NestedPattern->getTemplateDepth()); } FunctionProtoTypeLoc FPTL = CD->getTypeSourceInfo()->getTypeLoc() @@ -2438,10 +2441,17 @@ struct ConvertConstructorToDeductionGuideTransform { SmallVector<QualType, 4> ParamTypes; const FunctionProtoType *T = TL.getTypePtr(); + MultiLevelTemplateArgumentList OuterInstantiationArgs; + if (NestedPattern) + OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(Template); + // -- The types of the function parameters are those of the constructor. for (auto *OldParam : TL.getParams()) { ParmVarDecl *NewParam = transformFunctionTypeParam(OldParam, Args, MaterializedTypedefs); + if (NestedPattern && NewParam) + NewParam = transformFunctionTypeParam(NewParam, OuterInstantiationArgs, + MaterializedTypedefs); if (!NewParam) return QualType(); ParamTypes.push_back(NewParam->getType()); @@ -2647,13 +2657,23 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template, if (BuildingDeductionGuides.isInvalid()) return; + // If the template is nested, then we need to use the original + // pattern to iterate over the constructors. + ClassTemplateDecl *Pattern = Transform.Template; + while (Pattern->getInstantiatedFromMemberTemplate()) { + if (Pattern->isMemberSpecialization()) + break; + Pattern = Pattern->getInstantiatedFromMemberTemplate(); + Transform.NestedPattern = Pattern; + } + // Convert declared constructors into deduction guide templates. // FIXME: Skip constructors for which deduction must necessarily fail (those // for which some class template parameter without a default argument never // appears in a deduced context). llvm::SmallPtrSet<NamedDecl *, 8> ProcessedCtors; bool AddedAny = false; - for (NamedDecl *D : LookupConstructors(Transform.Primary)) { + for (NamedDecl *D : LookupConstructors(Pattern->getTemplatedDecl())) { D = D->getUnderlyingDecl(); if (D->isInvalidDecl() || D->isImplicit()) continue; diff --git a/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp b/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp new file mode 100644 index 000000000000000..4915c687cf4c4ef --- /dev/null +++ b/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++17 -verify %s +// expected-no-diagnostics + +template<class T> struct S { + template<class U> struct N { + N(T) {} + N(T, U) {} + template<class V> N(V, U) {} + }; +}; + +S<int>::N x{"a", 1}; >From 67b8a02140cf1e8819822c3b95495531f97f6591 Mon Sep 17 00:00:00 2001 From: Antonio Abbatangelo <cont...@antangelo.com> Date: Fri, 6 Oct 2023 15:33:19 -0400 Subject: [PATCH 2/2] Add release note --- clang/docs/ReleaseNotes.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 9782c123f4c9372..11d0c443610ce79 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -513,6 +513,11 @@ Bug Fixes to C++ Support rather than prefer the non-templated constructor as specified in [standard.group]p3. +- Fix a bug where implicit deduction guides are not correctly generated for nested template + classes. Fixes: + (`#46200 <https://github.com/llvm/llvm-project/issues/46200>`_) + (`#57812 <https://github.com/llvm/llvm-project/issues/57812>`_) + Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ - Fixed an import failure of recursive friend class template. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits