Author: Botond István Hprváth Date: 2023-10-04T09:11:43-07:00 New Revision: 66c19167f127013f6834ea1a316b783e57490939
URL: https://github.com/llvm/llvm-project/commit/66c19167f127013f6834ea1a316b783e57490939 DIFF: https://github.com/llvm/llvm-project/commit/66c19167f127013f6834ea1a316b783e57490939.diff LOG: [clang] Choose non-templated ctor as deduction guide unambiguously (#66487) 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. The correct behavior is described in this paper: http://wg21.link/P0620R0 Example for the bug: http://godbolt.org/z/ee3e9qG78 As an unrelated minor change, fix the issue https://github.com/llvm/llvm-project/issues/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. --------- Co-authored-by: hobois <horvath.botond.ist...@gmial.com> Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaOverload.cpp clang/lib/Sema/SemaTemplateInstantiateDecl.cpp clang/test/CXX/over/over.match/over.match.funcs/over.match.class.deduct/p2.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index ce63fbd386218e6..6f410c48bd1ffe9 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -435,6 +435,11 @@ Bug Fixes to C++ Support we now produce a diagnostic. Fixes: (`#65522 <https://github.com/llvm/llvm-project/issues/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. diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 5ddae2d15518d29..ce78994e6553814 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -10440,6 +10440,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; + } } } @@ -10483,7 +10498,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 0b2b775f19a0166..071366ac0ee9834 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2140,7 +2140,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 4eac0a1ac510f1d..49fde292f6a36de 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,38 @@ int main() { } + +namespace deduceTemplatedConstructor { +template <typename X, typename Y> struct IsSame { + static constexpr bool value = false; +}; + +template <typename Z> struct IsSame<Z, Z> { + static constexpr bool value = true; +}; +template <class T> struct A { + using value_type = T; + A(value_type); + A(const A&); + A(T, T, int); + template<class U> + A(int, T, U); +}; + +A x(1, 2, 3); // no-error +static_assert(IsSame<decltype(x),A<int>>::value); + +template <class T> +A(T) -> A<T>; + +A a(42); +static_assert(IsSame<decltype(a),A<int>>::value); +A b = a; +static_assert(IsSame<decltype(b),A<int>>::value); + +template <class T> +A(A<T>) -> A<A<T>>; + +A b2 = a; +static_assert(IsSame<decltype(b2),A<A<int>>>::value); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits