Removing mark_used from resolve_nondeduced_context as Patrick and Jason
suggested caused no regressions.

Regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

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.

This patch removes the mark_used call from resolve_nondeduced_context
and adds error_mark_node checks to mark_used and mark_single_function.

        PR c++/119343

gcc/cp/ChangeLog:

        * pt.cc (resolve_nondeduced_context): Remove mark_used call.
        * decl2.cc (mark_used): Return false for error_mark_node.
        (mark_single_function): Likewise.

gcc/testsuite/ChangeLog:

        * g++.dg/DRs/dr3061.C: Remove cascading error expectation.
        * g++.dg/cpp0x/initlist31.C: Likewise.
        * g++.dg/template/sfinae-deleted-pr119343.C: New test.

Signed-off-by: Egas Ribeiro <[email protected]>
---
 gcc/cp/decl2.cc                               |  7 ++++-
 gcc/cp/pt.cc                                  |  2 --
 gcc/testsuite/g++.dg/DRs/dr3061.C             |  2 +-
 gcc/testsuite/g++.dg/cpp0x/initlist31.C       |  2 +-
 .../g++.dg/template/sfinae-deleted-pr119343.C | 31 +++++++++++++++++++
 5 files changed, 39 insertions(+), 5 deletions(-)
 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..08f39e7ce87 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))
@@ -6340,10 +6343,12 @@ fn_template_being_defined (tree decl)
 bool
 mark_used (tree decl, tsubst_flags_t complain /* = tf_warning_or_error */)
 {
+  if (decl == error_mark_node)
+    return false;
   /* If we're just testing conversions or resolving overloads, we
      don't want any permanent effects like forcing functions to be
      output or instantiating templates.  */
-  if ((complain & tf_conv))
+  if (complain & tf_conv)
     return true;
 
   /* If DECL is a BASELINK for a single function, then treat it just
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 7a019d33bda..f992bf5c0bb 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -24815,8 +24815,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/DRs/dr3061.C 
b/gcc/testsuite/g++.dg/DRs/dr3061.C
index 728829848f5..bd8b74cdafb 100644
--- a/gcc/testsuite/g++.dg/DRs/dr3061.C
+++ b/gcc/testsuite/g++.dg/DRs/dr3061.C
@@ -12,7 +12,7 @@ foo ()
   template for (int x : { 1, })                // { dg-warning "'template for' 
only available with" "" { target c++23_down } }
     ;
   for (int x : { , })                  // { dg-error "expected 
primary-expression before ',' token" }
-    ;                                  // { dg-error "unable to deduce" "" { 
target *-*-* } .-1 }
+    ;
   template for (int x : { , })         // { dg-warning "'template for' only 
available with" "" { target c++23_down } }
     ;                                  // { dg-error "expected 
primary-expression before ',' token" "" { target *-*-* } .-1 }
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist31.C 
b/gcc/testsuite/g++.dg/cpp0x/initlist31.C
index a8a29f9c853..6d88edb397f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist31.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist31.C
@@ -9,5 +9,5 @@ void f() {
   auto y =
   {
     string(Equation()) // { dg-error "12:'Equation' was not declared" }
-  }; // { dg-error "unable to deduce" }
+  };
 }
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