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, 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 (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

Reply via email to