Hi Egas, thanks for tackling this bug! On Sun, 30 Nov 2025, Egas Ribeiro wrote:
> Regtested on x86_64-pc-linux-gnu, OK for trunk? > > -- >8 -- > > When checking a deleted explicit specialization in a SFINAE context, > we were failing to propagate the error from mark_used. The call to > resolve_nondeduced_context in convert_to_void correctly returned > error_mark_node, I wonder actually whether resolve_nondeduced_context is correct to return error_mark_node in this case. Sure the single X::g<0> overload selected by resolve_nondeduced_context is deleted, but should that imply an ODR-use of the overload? Maybe it should be the responsibility of the caller to call mark_used, and we should remove the mark_used in resolve_nondeduced_context. Note that resolve_nondeduced_context does not call mark_used when the overload set is _not_ a template-id. So the caller will likely have to call mark_used anyway to uniformly handle template-id and non-template-id overloads. Jason, what do you think? > but mark_single_function didn't check for this, > causing the error to be lost and the partial specialization to be > incorrectly selected. > > PR c++/119343 > > gcc/cp/ChangeLog: > > * decl2.cc (mark_single_function): Return false for error_mark_node. > > gcc/testsuite/ChangeLog: > > * g++.dg/template/sfinae-deleted-pr119343.C: New test. > > Signed-off-by: Egas Ribeiro <[email protected]> > --- > > gcc/cp/decl2.cc | 3 ++ > .../g++.dg/template/sfinae-deleted-pr119343.C | 31 +++++++++++++++++++ > 2 files changed, 34 insertions(+) > create mode 100644 gcc/testsuite/g++.dg/template/sfinae-deleted-pr119343.C > > diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc > index 9e135af41b3..17d905ab5b1 100644 > --- a/gcc/cp/decl2.cc > +++ b/gcc/cp/decl2.cc > @@ -6298,6 +6298,9 @@ mark_single_function (tree expr, tsubst_flags_t > complain) > expr = maybe_undo_parenthesized_ref (expr); > expr = tree_strip_any_location_wrapper (expr); > > + if (expr == error_mark_node) > + return false; If the above approach doesn't sound right then I agree that mark_single_function as well as mark_used should return false for error_mark_node. > + > if (is_overloaded_fn (expr) == 1 > && !mark_used (expr, complain) > && !(complain & tf_error)) > diff --git a/gcc/testsuite/g++.dg/template/sfinae-deleted-pr119343.C > b/gcc/testsuite/g++.dg/template/sfinae-deleted-pr119343.C > new file mode 100644 > index 00000000000..065ad605637 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/template/sfinae-deleted-pr119343.C > @@ -0,0 +1,31 @@ > +// { dg-do compile { target c++11 } } > +// PR c++/119343 - No SFINAE for deleted explicit specializations > + > +struct true_type { static constexpr bool value = true; }; > +struct false_type { static constexpr bool value = false; }; > + > +struct X { > + static void f()=delete; > + template<int> static void g(); > +}; > +template<> void X::g<0>()=delete; > +struct Y { > + static void f(); > + template<int> static void g(); > +}; > + > +template<class T,class=void> > +struct has_f : false_type {}; > +template<class T> > +struct has_f<T,decltype(void(T::f))> : true_type {}; > + > +static_assert(!has_f<X>::value, ""); > +static_assert(has_f<Y>::value, ""); > + > +template<class T,class=void> > +struct has_g0 : false_type {}; > +template<class T> > +struct has_g0<T,decltype(void(T::template g<0>))> : true_type {}; > + > +static_assert(!has_g0<X>::value, ""); > +static_assert(has_g0<Y>::value, ""); > -- > 2.52.0 > >
