This improves the diagnostic from

error: could not convert ‘((A<>*)(void)0)->A<>::e’ from
       ‘<unresolved overloaded function type>’ to ‘bool’

to

error: cannot convert ‘A<>::e’ from type ‘void (A<>::)()’ to type ‘bool’

Tested x86_64-pc-linux-gnu, applying to trunk.

gcc/cp/ChangeLog
2020-05-11  Jason Merrill  <ja...@redhat.com>

        * call.c (implicit_conversion_error): Split out from...
        (perform_implicit_conversion_flags): ...here.
        (build_converted_constant_expr_internal): Use it.
---
 gcc/cp/call.c                             | 41 +++++++++++++----------
 gcc/testsuite/g++.dg/cpp0x/noexcept30.C   |  2 +-
 gcc/testsuite/g++.dg/cpp0x/noexcept58.C   |  9 +++++
 gcc/testsuite/g++.dg/template/crash87.C   |  2 +-
 gcc/testsuite/g++.dg/template/nontype13.C |  2 +-
 5 files changed, 36 insertions(+), 20 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept58.C

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index aca12c74c25..85d670f52f9 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4282,6 +4282,28 @@ build_user_type_conversion (tree totype, tree expr, int 
flags,
   return ret;
 }
 
+/* Give a helpful diagnostic when implicit_conversion fails.  */
+
+static void
+implicit_conversion_error (location_t loc, tree type, tree expr)
+{
+  tsubst_flags_t complain = tf_warning_or_error;
+
+  /* If expr has unknown type, then it is an overloaded function.
+     Call instantiate_type to get good error messages.  */
+  if (TREE_TYPE (expr) == unknown_type_node)
+    instantiate_type (type, expr, complain);
+  else if (invalid_nonstatic_memfn_p (loc, expr, complain))
+    /* We gave an error.  */;
+  else
+    {
+      range_label_for_type_mismatch label (TREE_TYPE (expr), type);
+      gcc_rich_location rich_loc (loc, &label);
+      error_at (&rich_loc, "could not convert %qE from %qH to %qI",
+               expr, TREE_TYPE (expr), type);
+    }
+}
+
 /* Worker for build_converted_constant_expr.  */
 
 static tree
@@ -4397,8 +4419,7 @@ build_converted_constant_expr_internal (tree type, tree 
expr,
   else
     {
       if (complain & tf_error)
-       error_at (loc, "could not convert %qE from %qH to %qI", expr,
-                 TREE_TYPE (expr), type);
+       implicit_conversion_error (loc, type, expr);
       expr = error_mark_node;
     }
 
@@ -11845,21 +11866,7 @@ perform_implicit_conversion_flags (tree type, tree 
expr,
   if (!conv)
     {
       if (complain & tf_error)
-       {
-         /* If expr has unknown type, then it is an overloaded function.
-            Call instantiate_type to get good error messages.  */
-         if (TREE_TYPE (expr) == unknown_type_node)
-           instantiate_type (type, expr, complain);
-         else if (invalid_nonstatic_memfn_p (loc, expr, complain))
-           /* We gave an error.  */;
-         else
-           {
-             range_label_for_type_mismatch label (TREE_TYPE (expr), type);
-             gcc_rich_location rich_loc (loc, &label);
-             error_at (&rich_loc, "could not convert %qE from %qH to %qI",
-                       expr, TREE_TYPE (expr), type);
-           }
-       }
+       implicit_conversion_error (loc, type, expr);
       expr = error_mark_node;
     }
   else if (processing_template_decl && conv->kind != ck_identity)
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept30.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept30.C
index 6a9f7821092..1075c69a491 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept30.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept30.C
@@ -5,7 +5,7 @@
 template<typename A>
 struct F {
   template<typename B>
-  void f() noexcept(&F::template f<B>) {} // { dg-error "exception 
specification|convert" }
+  void f() noexcept(&F::template f<B>) {} // { dg-error "exception 
specification|convert|resolve" }
 };
 
 int main () {
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept58.C 
b/gcc/testsuite/g++.dg/cpp0x/noexcept58.C
new file mode 100644
index 00000000000..0a145e030a5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept58.C
@@ -0,0 +1,9 @@
+// PR c++/90748
+// { dg-do compile { target c++11 } }
+
+template <class ...> class A
+{
+  void e ();
+  bool f (int() noexcept(e));  // { dg-error "::e" }
+};
+A<> b;
diff --git a/gcc/testsuite/g++.dg/template/crash87.C 
b/gcc/testsuite/g++.dg/template/crash87.C
index af81edbfd80..7da6623612a 100644
--- a/gcc/testsuite/g++.dg/template/crash87.C
+++ b/gcc/testsuite/g++.dg/template/crash87.C
@@ -17,7 +17,7 @@ template <bool name>
 class BUG2 : BUG
 {
 public:
- typedef BUG1_5<name> ptr; // { dg-error "convert" }
+ typedef BUG1_5<name> ptr; // { dg-error "BUG::name" }
 };
 
 int main()
diff --git a/gcc/testsuite/g++.dg/template/nontype13.C 
b/gcc/testsuite/g++.dg/template/nontype13.C
index 3250109aa4a..4d6b323ed64 100644
--- a/gcc/testsuite/g++.dg/template/nontype13.C
+++ b/gcc/testsuite/g++.dg/template/nontype13.C
@@ -11,7 +11,7 @@ struct Dummy
   template<bool B>
   void tester()
   {
-    bar<evil>()(); // { dg-error "constant|template|convert" }
+    bar<evil>()(); // { dg-error "constant|template|convert|member function" }
   }
   template<bool B>
   struct bar

base-commit: 1422c2e4462c9b7c44aa035ac56af77565556181
-- 
2.18.1

Reply via email to