From 258462cc65403af147bb47cbeb95210df8e18cd3 Mon Sep 17 00:00:00 2001 From: hobois Date: Fri, 15 Sep 2023 09:28:21 +0200 Subject: [PATCH 1/6] Choose the correct deduction guide If there are two guides, one of them generated from a non-templated constructor and the other from a templated constructor, then the standard gives priority to the first. Clang detected ambiguity before, now the correct guide is chosen. As an unrelated minor change, fix the issue #64020, which could've led to incorrect behavior if further development inserted code after a call to isAddressSpaceSubsetOf() which specified the two parameters in the wrong order. --- clang/lib/Sema/SemaOverload.cpp | 17 ++++++++++++++++- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 +- .../over.match.class.deduct/p2.cpp | 10 ++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 45a9e5dc98c03..1bb8123852017 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -10153,6 +10153,21 @@ bool clang::isBetterOverloadCandidate( // -- F1 is the copy deduction candidate(16.3.1.8) and F2 is not if (Guide1->getDeductionCandidateKind() == DeductionCandidate::Copy) return true; + if (Guide2->getDeductionCandidateKind() == DeductionCandidate::Copy) + return false; + + // --F1 is generated from a non-template constructor and F2 is generated + // from a constructor template + const auto *Constructor1 = Guide1->getCorrespondingConstructor(); + const auto *Constructor2 = Guide2->getCorrespondingConstructor(); + if (Constructor1 && Constructor2) { + bool isC1Templated = Constructor1->getTemplatedKind() != + FunctionDecl::TemplatedKind::TK_NonTemplate; + bool isC2Templated = Constructor2->getTemplatedKind() != + FunctionDecl::TemplatedKind::TK_NonTemplate; + if (isC1Templated != isC2Templated) + return isC2Templated; + } } } @@ -10196,7 +10211,7 @@ bool clang::isBetterOverloadCandidate( if (AS1 != AS2) { if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1)) return true; - if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1)) + if (Qualifiers::isAddressSpaceSupersetOf(AS1, AS2)) return false; } } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 9e5f85b0f9166..b9c4a9db842b9 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2129,7 +2129,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( Function = CXXDeductionGuideDecl::Create( SemaRef.Context, DC, D->getInnerLocStart(), InstantiatedExplicitSpecifier, NameInfo, T, TInfo, - D->getSourceRange().getEnd(), /*Ctor=*/nullptr, + D->getSourceRange().getEnd(), DGuide->getCorrespondingConstructor(), DGuide->getDeductionCandidateKind()); Function->setAccess(D->getAccess()); } else { diff --git a/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp b/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp index 4eac0a1ac510f..d939d724dc7a0 100644 --- a/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp +++ b/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp @@ -85,3 +85,13 @@ int main() { } + +namespace deduceTemplatedConstructor{ +template struct A { + A(T, T, int); + template + A(int, T, U); +}; + +A x(1, 2, 3); // no-error +} From 877678b01d05eb301ac49a2a39186a743ca9012d Mon Sep 17 00:00:00 2001 From: hobois Date: Tue, 3 Oct 2023 18:20:11 +0200 Subject: [PATCH 2/6] Added the fix to relasenotes --- clang/docs/ReleaseNotes.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 6be824771c583..84eb3301deb4b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -390,6 +390,11 @@ Bug Fixes to C++ Support we now produce a diagnostic. Fixes: (`#65522 `_) +- Fixed a bug where clang incorrectly considered implicitly generated deduction + guides from a non-templated constructor and a templated constructor as ambiguous, + rather than prefer the non-templated constructor as specified in + [standard.group]p3 + Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ - Fixed an import failure of recursive friend class template. From fc425a9be52b9278cd66e123019da2aaa3a0ee9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Botond=20Istv=C3=A1n=20Hprv=C3=A1th?= <56926027+HoBoIs@users.noreply.github.com> Date: Tue, 3 Oct 2023 18:26:17 +0200 Subject: [PATCH 3/6] Update ReleaseNotes.rst --- clang/docs/ReleaseNotes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 84eb3301deb4b..47984a1b385e4 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -393,7 +393,7 @@ Bug Fixes to C++ Support - Fixed a bug where clang incorrectly considered implicitly generated deduction guides from a non-templated constructor and a templated constructor as ambiguous, rather than prefer the non-templated constructor as specified in - [standard.group]p3 + [standard.group]p3. Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ From cb032a77662c070cb89ee959ed2f52a5f91ecd52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Botond=20Istv=C3=A1n=20Hprv=C3=A1th?= <56926027+HoBoIs@users.noreply.github.com> Date: Tue, 3 Oct 2023 18:43:41 +0200 Subject: [PATCH 4/6] Formated ReleaseNotes.rst --- clang/docs/ReleaseNotes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 47984a1b385e4..f79c0fcf23118 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -392,7 +392,7 @@ Bug Fixes to C++ Support - Fixed a bug where clang incorrectly considered implicitly generated deduction guides from a non-templated constructor and a templated constructor as ambiguous, - rather than prefer the non-templated constructor as specified in + rather than prefer the non-templated constructor as specified in [standard.group]p3. Bug Fixes to AST Handling From 289c269d9c42fc43062fcb3fb950deb0a6cb11e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Botond=20Istv=C3=A1n=20Hprv=C3=A1th?= <56926027+HoBoIs@users.noreply.github.com> Date: Wed, 4 Oct 2023 10:52:05 +0200 Subject: [PATCH 5/6] Added tests to p2.cpp --- .../over.match.class.deduct/p2.cpp | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp b/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp index d939d724dc7a0..57fef7d4cc7da 100644 --- a/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp +++ b/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp @@ -87,11 +87,36 @@ int main() { } namespace deduceTemplatedConstructor{ +template struct IsSame { + static constexpr bool value = false; +}; + +template struct IsSame { + static constexpr bool value = true; +}; template struct A { + using value_type = T; + A(value_type); + A(const A&); A(T, T, int); template - A(int, T, U); + A(int, T, U); }; A x(1, 2, 3); // no-error +static_assert(IsSame>::value); + +template +A(T) -> A; + +A a(42); +static_assert(IsSame>::value); +A b = a; +static_assert(IsSame>::value); + +template +A(A) -> A>; + +A b2 = a; +static_assert(IsSame>>::value); } From d6b37e457b3465c8653f4ba0012536b02ca0cf34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Botond=20Istv=C3=A1n=20Hprv=C3=A1th?= <56926027+HoBoIs@users.noreply.github.com> Date: Wed, 4 Oct 2023 17:28:09 +0200 Subject: [PATCH 6/6] Formating p2.cpp --- .../over.match/over.match.funcs/over.match.class.deduct/p2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp b/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp index 57fef7d4cc7da..49fde292f6a36 100644 --- a/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp +++ b/clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp @@ -86,7 +86,7 @@ int main() { } -namespace deduceTemplatedConstructor{ +namespace deduceTemplatedConstructor { template struct IsSame { static constexpr bool value = false; };