https://gcc.gnu.org/g:d9f352582a0f3516509a2cd26d130f1dcfa8d048
commit r17-4944-gd9f352582a0f3516509a2cd26d130f1dcfa8d048 Author: Jason Merrill <[email protected]> Date: Wed Oct 7 00:21:56 2026 -0400 c++: eligible vs explicit [PR127627] We assume that a non-"eligible" special member function cannot be selected by overload resolution, but that isn't the case here due to the difference in "explicit". So check for that when filtering in add_method. PR c++/127627 gcc/cp/ChangeLog: * class.cc (add_method): Don't remove a less-explicit function. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/explicit21.C: New test. Diff: --- gcc/cp/class.cc | 12 +++++++++++- gcc/testsuite/g++.dg/cpp2a/explicit21.C | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index e913a780cddf..f4f2c4aa2351 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -1418,7 +1418,17 @@ add_method (tree type, tree method, bool via_using) if (losem || losef) win = losem - losef; else - win = more_constrained (fn, method); + { + win = more_constrained (fn, method); + if (win) + { + /* The winner can't be more explicit. */ + int ex = (DECL_NONCONVERTING_P (method) + - DECL_NONCONVERTING_P (fn)); + if (ex && ex != win) + win = 0; + } + } if (win > 0) /* Leave FN in the method vec, discard METHOD. */ return false; diff --git a/gcc/testsuite/g++.dg/cpp2a/explicit21.C b/gcc/testsuite/g++.dg/cpp2a/explicit21.C new file mode 100644 index 000000000000..a96a214df675 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/explicit21.C @@ -0,0 +1,19 @@ +// PR c++/127627 +// { dg-do compile { target c++20 } } + +template <class T> +struct X +{ + X() = default; + X(const X&) { throw; } +private: + explicit X(const X&) requires (T::value) = default; +}; + +struct S { static constexpr bool value = true; }; + +int main() +{ + const X<S> x; + X<S> x2 = x; +}
