diff options
| author | Egas Ribeiro <egas.g.ribeiro@tecnico.ulisboa.pt> | 2025-12-07 23:35:00 +0000 |
|---|---|---|
| committer | Patrick Palka <ppalka@redhat.com> | 2025-12-08 12:11:44 -0500 |
| commit | bae0ed69e1862add152f1b0618148f931611a9ca (patch) | |
| tree | 3c4aefc06ca413ef7b9e647de146909d553beb0c | |
| parent | a7b8c5faa6ff3d9bcc15457113e611ec377c6f5f (diff) | |
| download | gcc-bae0ed69e1862add152f1b0618148f931611a9ca.zip gcc-bae0ed69e1862add152f1b0618148f931611a9ca.tar.gz gcc-bae0ed69e1862add152f1b0618148f931611a9ca.tar.bz2 | |
c++: Fix SFINAE for deleted explicit specializations [PR119343]
When checking a deleted explicit specialization in a SFINAE context,
we were incorrectly selecting a partial specialization because
resolve_nondeduced_context was calling mark_used. But resolving an
overload to a single function (per DR 115) does not constitute ODR-use,
so mark_used shouldn't be called there. Instead callers should call
mark_used or mark_single_function on the result to uniformly handle all
resolvable overloads (even non-template-id ones).
This turns out to fix the below testcase because it causes convert_to_void
for void(X::template g<0>) to properly propagate ODR-use failure (due to
deleted g<0>) and return error_mark_node instead of returning void_node.
PR c++/119343
gcc/cp/ChangeLog:
* pt.cc (resolve_nondeduced_context): Remove mark_used call.
gcc/testsuite/ChangeLog:
* g++.dg/template/sfinae-deleted-pr119343.C: New test.
Signed-off-by: Egas Ribeiro <egas.g.ribeiro@tecnico.ulisboa.pt>
Reviewed-by: Patrick Palka <ppalka@redhat.com>
| -rw-r--r-- | gcc/cp/pt.cc | 2 | ||||
| -rw-r--r-- | gcc/testsuite/g++.dg/template/sfinae-deleted-pr119343.C | 31 |
2 files changed, 31 insertions, 2 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 8498730..a9b311b 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -24816,8 +24816,6 @@ resolve_nondeduced_context (tree orig_expr, tsubst_flags_t complain) } if (good == 1) { - if (!mark_used (goodfn, complain) && !(complain & tf_error)) - return error_mark_node; expr = goodfn; if (baselink) expr = build_baselink (BASELINK_BINFO (baselink), 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 0000000..065ad60 --- /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, ""); |
