C++: special-case single non-viable candidate (more PR c++/85110)
authorDavid Malcolm <dmalcolm@redhat.com>
Wed, 12 Sep 2018 18:50:08 +0000 (18:50 +0000)
committerDavid Malcolm <dmalcolm@gcc.gnu.org>
Wed, 12 Sep 2018 18:50:08 +0000 (18:50 +0000)
I broke out the "no viable candidates" case in build_new_method_call_1
into a subroutine, and added special-case handling for when there's
a single non-viable candidate where there's an argument conversion
error.  I turned the error-handling from convert_for_assignment into
a subroutine, calling it from this new special-case.

This converts:

demo.cc: In function 'int test_4(int, const char*, float)':
demo.cc:5:44: error: no matching function for call to 's4::member_1(int&, const char*&, float&)'
5 |   return s4::member_1 (first, second, third);
  |                                            ^
demo.cc:1:24: note: candidate: 'static int s4::member_1(int, const char**, float)'
1 | struct s4 { static int member_1 (int one, const char **two, float three); };
  |                        ^~~~~~~~
demo.cc:1:56: note:   no known conversion for argument 2 from 'const char*' to 'const char**'
1 | struct s4 { static int member_1 (int one, const char **two, float three); };
  |                                           ~~~~~~~~~~~~~^~~

to:

demo.cc: In function 'int test_4(int, const char*, float)':
demo.cc:5:31: error: cannot convert 'const char*' to 'const char**'
5 |   return s4::member_1 (first, second, third);
  |                               ^~~~~~
  |                               |
  |                               const char*
demo.cc:1:56: note:   initializing argument 2 of 'static int s4::member_1(int, const char**, float)'
1 | struct s4 { static int member_1 (int one, const char **two, float three); };
  |                                           ~~~~~~~~~~~~~^~~

thus highlighting the problematic argument at the callsite (and its type).

gcc/cp/ChangeLog:
PR c++/85110
* call.c (struct conversion_info): Add "loc" field.
(arg_conversion_rejection): Add "loc" param, using it to
initialize the new field.
(bad_arg_conversion_rejection): Likewise.
(explicit_conversion_rejection): Initialize the new field to
UNKNOWN_LOCATION.
(template_conversion_rejection): Likewise.
(add_function_candidate): Pass on the argument location to the new
param of arg_conversion_rejection.
(add_conv_candidate): Likewise.
(build_builtin_candidate): Likewise.
(build_user_type_conversion_1): Likewise.
(single_z_candidate): New function.
(maybe_get_bad_conversion_for_unmatched_call): New function.
(complain_about_bad_argument): New function, based on part of
convert_for_assignment.
(build_new_method_call_1): Split out handling of the "no viable
candidates" case into...
(complain_about_no_candidates_for_method_call): ...this new
function, and use the new functions above to special-case the
handling of a single non-viable candidate due to a bad argument.
* cp-tree.h (complain_about_bad_argument): New decl.
* typeck.c (convert_for_assignment): Split out one error-handling
case into complain_about_bad_argument.

gcc/testsuite/ChangeLog:
PR c++/85110
* g++.dg/cpp0x/explicit4.C: Update expected output to reflect
special-casing of diagnostic for a single non-viable candidate due
to a bad argument.
* g++.dg/diagnostic/param-type-mismatch-2.C: Likewise.
Add test coverage for an unmatched overloaded operator.
* g++.dg/expr/pmf-1.C: Likewise.
* g++.old-deja/g++.bugs/900330_02.C: Likewise.
* g++.old-deja/g++.jason/conversion11.C: Likewise.
* g++.old-deja/g++.law/arg11.C: Likewise.
* g++.old-deja/g++.law/arm9.C: Likewise.
* g++.old-deja/g++.robertl/eb131.C: Likewise.

From-SVN: r264250

13 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/explicit4.C
gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
gcc/testsuite/g++.dg/expr/pmf-1.C
gcc/testsuite/g++.old-deja/g++.bugs/900330_02.C
gcc/testsuite/g++.old-deja/g++.jason/conversion11.C
gcc/testsuite/g++.old-deja/g++.law/arg11.C
gcc/testsuite/g++.old-deja/g++.law/arm9.C
gcc/testsuite/g++.old-deja/g++.robertl/eb131.C

index e4d635d..9201d67 100644 (file)
@@ -1,3 +1,31 @@
+2018-09-12  David Malcolm  <dmalcolm@redhat.com>
+
+       PR c++/85110
+       * call.c (struct conversion_info): Add "loc" field.
+       (arg_conversion_rejection): Add "loc" param, using it to
+       initialize the new field.
+       (bad_arg_conversion_rejection): Likewise.
+       (explicit_conversion_rejection): Initialize the new field to
+       UNKNOWN_LOCATION.
+       (template_conversion_rejection): Likewise.
+       (add_function_candidate): Pass on the argument location to the new
+       param of arg_conversion_rejection.
+       (add_conv_candidate): Likewise.
+       (build_builtin_candidate): Likewise.
+       (build_user_type_conversion_1): Likewise.
+       (single_z_candidate): New function.
+       (maybe_get_bad_conversion_for_unmatched_call): New function.
+       (complain_about_bad_argument): New function, based on part of
+       convert_for_assignment.
+       (build_new_method_call_1): Split out handling of the "no viable
+       candidates" case into...
+       (complain_about_no_candidates_for_method_call): ...this new
+       function, and use the new functions above to special-case the
+       handling of a single non-viable candidate due to a bad argument.
+       * cp-tree.h (complain_about_bad_argument): New decl.
+       * typeck.c (convert_for_assignment): Split out one error-handling
+       case into complain_about_bad_argument.
+
 2018-09-09  Cesar Philippidis  <cesar@codesourcery.com>
             Julian Brown  <julian@codesourcery.com>
 
index 03b4c5a..69503ca 100644 (file)
@@ -436,6 +436,8 @@ struct conversion_info {
   tree from;
   /* The type of the parameter.  */
   tree to_type;
+  /* The location of the argument.  */
+  location_t loc;
 };
   
 struct rejection_reason {
@@ -627,24 +629,28 @@ arity_rejection (tree first_arg, int expected, int actual)
 }
 
 static struct rejection_reason *
-arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to)
+arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to,
+                         location_t loc)
 {
   struct rejection_reason *r = alloc_rejection (rr_arg_conversion);
   int adjust = first_arg != NULL_TREE;
   r->u.conversion.n_arg = n_arg - adjust;
   r->u.conversion.from = from;
   r->u.conversion.to_type = to;
+  r->u.conversion.loc = loc;
   return r;
 }
 
 static struct rejection_reason *
-bad_arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to)
+bad_arg_conversion_rejection (tree first_arg, int n_arg, tree from, tree to,
+                             location_t loc)
 {
   struct rejection_reason *r = alloc_rejection (rr_bad_arg_conversion);
   int adjust = first_arg != NULL_TREE;
   r->u.bad_conversion.n_arg = n_arg - adjust;
   r->u.bad_conversion.from = from;
   r->u.bad_conversion.to_type = to;
+  r->u.bad_conversion.loc = loc;
   return r;
 }
 
@@ -655,6 +661,7 @@ explicit_conversion_rejection (tree from, tree to)
   r->u.conversion.n_arg = 0;
   r->u.conversion.from = from;
   r->u.conversion.to_type = to;
+  r->u.conversion.loc = UNKNOWN_LOCATION;
   return r;
 }
 
@@ -665,6 +672,7 @@ template_conversion_rejection (tree from, tree to)
   r->u.conversion.n_arg = 0;
   r->u.conversion.from = from;
   r->u.conversion.to_type = to;
+  r->u.conversion.loc = UNKNOWN_LOCATION;
   return r;
 }
 
@@ -2257,14 +2265,17 @@ add_function_candidate (struct z_candidate **candidates,
       if (! t)
        {
          viable = 0;
-         reason = arg_conversion_rejection (first_arg, i, argtype, to_type);
+         reason = arg_conversion_rejection (first_arg, i, argtype, to_type,
+                                            EXPR_LOCATION (arg));
          break;
        }
 
       if (t->bad_p)
        {
          viable = -1;
-         reason = bad_arg_conversion_rejection (first_arg, i, arg, to_type);
+         reason = bad_arg_conversion_rejection (first_arg, i, arg, to_type,
+                                                EXPR_LOCATION (arg));
+
        }
     }
 
@@ -2353,7 +2364,8 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
       if (t->bad_p)
        {
          viable = -1;
-         reason = bad_arg_conversion_rejection (NULL_TREE, i, arg, convert_type);
+         reason = bad_arg_conversion_rejection (NULL_TREE, i, arg, convert_type,
+                                                EXPR_LOCATION (arg));
        }
 
       if (i == 0)
@@ -2414,13 +2426,14 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
          /* We need something for printing the candidate.  */
          t = build_identity_conv (types[i], NULL_TREE);
          reason = arg_conversion_rejection (NULL_TREE, i, argtypes[i],
-                                            types[i]);
+                                            types[i], EXPR_LOCATION (args[i]));
        }
       else if (t->bad_p)
        {
          viable = 0;
          reason = bad_arg_conversion_rejection (NULL_TREE, i, args[i],
-                                                types[i]);
+                                                types[i],
+                                                EXPR_LOCATION (args[i]));
        }
       convs[i] = t;
     }
@@ -2439,7 +2452,8 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
        {
          viable = 0;
          reason = arg_conversion_rejection (NULL_TREE, 0, argtypes[2],
-                                            boolean_type_node);
+                                            boolean_type_node,
+                                            EXPR_LOCATION (args[2]));
        }
     }
 
@@ -3930,7 +3944,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
            {
              cand->viable = 0;
              cand->reason = arg_conversion_rejection (NULL_TREE, -2,
-                                                      rettype, totype);
+                                                      rettype, totype,
+                                                      EXPR_LOCATION (expr));
            }
          else if (DECL_NONCONVERTING_P (cand->fn)
                   && ics->rank > cr_exact)
@@ -3950,7 +3965,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags,
              cand->viable = -1;
              cand->reason
                = bad_arg_conversion_rejection (NULL_TREE, -2,
-                                               rettype, totype);
+                                               rettype, totype,
+                                               EXPR_LOCATION (expr));
            }
          else if (primary_template_specialization_p (cand->fn)
                   && ics->rank > cr_exact)
@@ -9165,6 +9181,129 @@ name_as_c_string (tree name, tree type, bool *free_p)
   return CONST_CAST (char *, pretty_name);
 }
 
+/* If CANDIDATES contains exactly one candidate, return it, otherwise
+   return NULL.  */
+
+static z_candidate *
+single_z_candidate (z_candidate *candidates)
+{
+  if (candidates == NULL)
+    return NULL;
+
+  if (candidates->next)
+    return NULL;
+
+  return candidates;
+}
+
+/* If CANDIDATE is invalid due to a bad argument type, return the
+   pertinent conversion_info.
+
+   Otherwise, return NULL.  */
+
+static const conversion_info *
+maybe_get_bad_conversion_for_unmatched_call (const z_candidate *candidate)
+{
+  /* Must be an rr_arg_conversion or rr_bad_arg_conversion.  */
+  rejection_reason *r = candidate->reason;
+
+  if (r == NULL)
+    return NULL;
+
+  switch (r->code)
+    {
+    default:
+      return NULL;
+
+    case rr_arg_conversion:
+      return &r->u.conversion;
+
+    case rr_bad_arg_conversion:
+      return &r->u.bad_conversion;
+    }
+}
+
+/* Issue an error and note complaining about a bad argument type at a
+   callsite with a single candidate FNDECL.
+
+   ARG_LOC is the location of the argument (or UNKNOWN_LOCATION, in which
+   case input_location is used).
+   FROM_TYPE is the type of the actual argument; TO_TYPE is the type of
+   the formal parameter.  */
+
+void
+complain_about_bad_argument (location_t arg_loc,
+                            tree from_type, tree to_type,
+                            tree fndecl, int parmnum)
+{
+  auto_diagnostic_group d;
+  range_label_for_type_mismatch rhs_label (from_type, to_type);
+  range_label *label = &rhs_label;
+  if (arg_loc == UNKNOWN_LOCATION)
+    {
+      arg_loc = input_location;
+      label = NULL;
+    }
+  gcc_rich_location richloc (arg_loc, label);
+  error_at (&richloc,
+           "cannot convert %qH to %qI",
+           from_type, to_type);
+  inform (get_fndecl_argument_location (fndecl, parmnum),
+         "  initializing argument %P of %qD", parmnum, fndecl);
+}
+
+/* Subroutine of build_new_method_call_1, for where there are no viable
+   candidates for the call.  */
+
+static void
+complain_about_no_candidates_for_method_call (tree instance,
+                                             z_candidate *candidates,
+                                             tree explicit_targs,
+                                             tree basetype,
+                                             tree optype, tree name,
+                                             bool skip_first_for_error,
+                                             vec<tree, va_gc> *user_args)
+{
+  auto_diagnostic_group d;
+  if (!COMPLETE_OR_OPEN_TYPE_P (basetype))
+    cxx_incomplete_type_error (instance, basetype);
+  else if (optype)
+    error ("no matching function for call to %<%T::operator %T(%A)%#V%>",
+          basetype, optype, build_tree_list_vec (user_args),
+          TREE_TYPE (instance));
+  else
+    {
+      /* Special-case for when there's a single candidate that's failing
+        due to a bad argument type.  */
+      if (z_candidate *candidate = single_z_candidate (candidates))
+         if (const conversion_info *conv
+               = maybe_get_bad_conversion_for_unmatched_call (candidate))
+           {
+             complain_about_bad_argument (conv->loc,
+                                          conv->from, conv->to_type,
+                                          candidate->fn, conv->n_arg);
+             return;
+           }
+
+      tree arglist = build_tree_list_vec (user_args);
+      tree errname = name;
+      bool twiddle = false;
+      if (IDENTIFIER_CDTOR_P (errname))
+       {
+         twiddle = IDENTIFIER_DTOR_P (errname);
+         errname = constructor_name (basetype);
+       }
+      if (explicit_targs)
+       errname = lookup_template_function (errname, explicit_targs);
+      if (skip_first_for_error)
+       arglist = TREE_CHAIN (arglist);
+      error ("no matching function for call to %<%T::%s%E(%A)%#V%>",
+            basetype, &"~"[!twiddle], errname, arglist,
+            TREE_TYPE (instance));
+    }
+  print_z_candidates (location_of (name), candidates);
+}
+
 /* Build a call to "INSTANCE.FN (ARGS)".  If FN_P is non-NULL, it will
    be set, upon return, to the function called.  ARGS may be NULL.
    This may change ARGS.  */
@@ -9382,34 +9521,11 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
   if (!any_viable_p)
     {
       if (complain & tf_error)
-       {
-         auto_diagnostic_group d;
-         if (!COMPLETE_OR_OPEN_TYPE_P (basetype))
-           cxx_incomplete_type_error (instance, basetype);
-         else if (optype)
-           error ("no matching function for call to %<%T::operator %T(%A)%#V%>",
-                  basetype, optype, build_tree_list_vec (user_args),
-                  TREE_TYPE (instance));
-         else
-           {
-             tree arglist = build_tree_list_vec (user_args);
-             tree errname = name;
-             bool twiddle = false;
-             if (IDENTIFIER_CDTOR_P (errname))
-               {
-                 twiddle = IDENTIFIER_DTOR_P (errname);
-                 errname = constructor_name (basetype);
-               }
-             if (explicit_targs)
-               errname = lookup_template_function (errname, explicit_targs);
-             if (skip_first_for_error)
-               arglist = TREE_CHAIN (arglist);
-             error ("no matching function for call to %<%T::%s%E(%A)%#V%>",
-                    basetype, &"~"[!twiddle], errname, arglist,
-                    TREE_TYPE (instance));
-           }
-         print_z_candidates (location_of (name), candidates);
-       }
+       complain_about_no_candidates_for_method_call (instance, candidates,
+                                                     explicit_targs, basetype,
+                                                     optype, name,
+                                                     skip_first_for_error,
+                                                     user_args);
       call = error_mark_node;
     }
   else
index b78e9eb..6cd6e5f 100644 (file)
@@ -6088,6 +6088,9 @@ extern bool can_convert_arg_bad                   (tree, tree, tree, int,
 extern int conv_flags                          (int, int, tree, tree, int);
 extern struct conversion * good_conversion     (tree, tree, tree, int, tsubst_flags_t);
 extern location_t get_fndecl_argument_location  (tree, int);
+extern void complain_about_bad_argument        (location_t arg_loc,
+                                                tree from_type, tree to_type,
+                                                tree fndecl, int parmnum);
 
 
 /* A class for recording information about access failures (e.g. private
index 9fa4c16..e993220 100644 (file)
@@ -8820,23 +8820,9 @@ convert_for_assignment (tree type, tree rhs,
                                                   parmnum, complain, flags);
                }
              else if (fndecl)
-               {
-                 auto_diagnostic_group d;
-                 location_t loc = cp_expr_location (rhs);
-                 range_label_for_type_mismatch rhs_label (rhstype, type);
-                 range_label *label = &rhs_label;
-                 if (loc == UNKNOWN_LOCATION)
-                   {
-                     loc = input_location;
-                     label = NULL;
-                   }
-                 gcc_rich_location richloc (loc, label);
-                 error_at (&richloc,
-                           "cannot convert %qH to %qI",
-                           rhstype, type);
-                 inform (get_fndecl_argument_location (fndecl, parmnum),
-                         "  initializing argument %P of %qD", parmnum, fndecl);
-               }
+               complain_about_bad_argument (cp_expr_location (rhs),
+                                            rhstype, type,
+                                            fndecl, parmnum);
              else
                switch (errtype)
                  {
index 4cd8859..5a50c80 100644 (file)
@@ -1,3 +1,18 @@
+2018-09-12  David Malcolm  <dmalcolm@redhat.com>
+
+       PR c++/85110
+       * g++.dg/cpp0x/explicit4.C: Update expected output to reflect
+       special-casing of diagnostic for a single non-viable candidate due
+       to a bad argument.
+       * g++.dg/diagnostic/param-type-mismatch-2.C: Likewise.
+       Add test coverage for an unmatched overloaded operator.
+       * g++.dg/expr/pmf-1.C: Likewise.
+       * g++.old-deja/g++.bugs/900330_02.C: Likewise.
+       * g++.old-deja/g++.jason/conversion11.C: Likewise.
+       * g++.old-deja/g++.law/arg11.C: Likewise.
+       * g++.old-deja/g++.law/arm9.C: Likewise.
+       * g++.old-deja/g++.robertl/eb131.C: Likewise.
+
 2018-09-12  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/87284
index 346a6e2..065a473 100644 (file)
@@ -13,5 +13,5 @@ int main()
 {
   B b;
   (A(b));                      // OK
-  (A(b,1));                    // { dg-error "no match" }
+  (A(b,1));                    // { dg-error "cannot convert" }
 }
index 4957f61..f74f8d3 100644 (file)
@@ -71,17 +71,14 @@ struct s4 { static int member_1 (int one, const char **two, float three); }; //
 
 int test_4 (int first, const char *second, float third)
 {
-  return s4::member_1 (first, second, third); // { dg-error "no matching function for call to 's4::member_1\\(int&, const char\\*&, float&\\)'" }
+  return s4::member_1 (first, second, third); // { dg-error "31: cannot convert 'const char\\*' to 'const char\\*\\*'" }
   /* { dg-begin-multiline-output "" }
    return s4::member_1 (first, second, third);
-                                            ^
+                               ^~~~~~
+                               |
+                               const char*
      { dg-end-multiline-output "" } */
-  // { dg-message "candidate: 'static int s4::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s4_member_1 }
-  /* { dg-begin-multiline-output "" }
- struct s4 { static int member_1 (int one, const char **two, float three); };
-                        ^~~~~~~~
-     { dg-end-multiline-output "" } */
-  // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s4_member_1 }
+  // { dg-message "initializing argument 2 of 'static int s4::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s4_member_1 } 
   /* { dg-begin-multiline-output "" } 
  struct s4 { static int member_1 (int one, const char **two, float three); };
                                            ~~~~~~~~~~~~~^~~
@@ -95,19 +92,16 @@ struct s5 { int member_1 (int one, const char **two, float three); }; // { dg-li
 int test_5 (int first, const char *second, float third)
 {
   s5 inst;
-  return inst.member_1 (first, second, third); // { dg-error "no matching function for call to 's5::member_1\\(int&, const char\\*&, float&\\)'" }
+  return inst.member_1 (first, second, third); // { dg-error "32: cannot convert 'const char\\*' to 'const char\\*\\*'" }
   /* { dg-begin-multiline-output "" }
    return inst.member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
+                                |
+                                const char*
      { dg-end-multiline-output "" } */
-  // { dg-message "candidate: 'int s5::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s5_member_1 }
+  // { dg-message "initializing argument 2 of 'int s5::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s5_member_1 } 
   /* { dg-begin-multiline-output "" }
  struct s5 { int member_1 (int one, const char **two, float three); };
-                 ^~~~~~~~
-     { dg-end-multiline-output "" } */
-  // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s5_member_1 }
-  /* { dg-begin-multiline-output "" } 
- struct s5 { int member_1 (int one, const char **two, float three); };
                                     ~~~~~~~~~~~~~^~~
      { dg-end-multiline-output "" } */
 }
@@ -118,17 +112,14 @@ struct s6 { int member_1 (int one, const char **two, float three); }; // { dg-li
 
 int test_6 (int first, const char *second, float third, s6 *ptr)
 {
-  return ptr->member_1 (first, second, third); // { dg-error "no matching function for call to 's6::member_1\\(int&, const char\\*&, float&\\)'" }
+  return ptr->member_1 (first, second, third); // { dg-error "32: cannot convert 'const char\\*' to 'const char\\*\\*'" }
   /* { dg-begin-multiline-output "" }
    return ptr->member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
+                                |
+                                const char*
      { dg-end-multiline-output "" } */
-  // { dg-message "candidate: 'int s6::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s6_member_1 }
-  /* { dg-begin-multiline-output "" }
- struct s6 { int member_1 (int one, const char **two, float three); };
-                 ^~~~~~~~
-     { dg-end-multiline-output "" } */
-  // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s6_member_1 }
+  // { dg-message "initializing argument 2 of 'int s6::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s6_member_1 } 
   /* { dg-begin-multiline-output "" } 
  struct s6 { int member_1 (int one, const char **two, float three); };
                                     ~~~~~~~~~~~~~^~~
@@ -168,17 +159,14 @@ struct s8 { static int member_1 (int one, T two, float three); }; // { dg-line s
 
 int test_8 (int first, const char *second, float third)
 {
-  return s8 <const char **>::member_1 (first, second, third); // { dg-error "no matching function for call to 's8<const char\\*\\*>::member_1\\(int&, const char\\*&, float&\\)'" }
+  return s8 <const char **>::member_1 (first, second, third); // { dg-error "47: cannot convert 'const char\\*' to 'const char\\*\\*'" }
   /* { dg-begin-multiline-output "" }
    return s8 <const char **>::member_1 (first, second, third);
-                                                            ^
-     { dg-end-multiline-output "" } */
-  // { dg-message "candidate: 'static int s8<T>::member_1\\(int, T, float\\)" "" { target *-*-* } s8_member_1 }
-  /* { dg-begin-multiline-output "" }
- struct s8 { static int member_1 (int one, T two, float three); };
-                        ^~~~~~~~
+                                               ^~~~~~
+                                               |
+                                               const char*
      { dg-end-multiline-output "" } */
-  // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s8_member_1 }
+  // { dg-message "initializing argument 2 of 'static int s8<T>::member_1\\(int, T, float\\) .with T = const char\\*\\*.'" "" { target *-*-* } s8_member_1 } 
   /* { dg-begin-multiline-output "" }
  struct s8 { static int member_1 (int one, T two, float three); };
                                            ~~^~~
@@ -193,19 +181,43 @@ struct s9 { int member_1 (int one, T two, float three); }; // { dg-line s9_membe
 int test_9 (int first, const char *second, float third)
 {
   s9 <const char **> inst;
-  return inst.member_1 (first, second, third); // { dg-error "no matching function for call to 's9<const char\\*\\*>::member_1\\(int&, const char\\*&, float&\\)'" }
+  return inst.member_1 (first, second, third); // { dg-error "32: cannot convert 'const char\\*' to 'const char\\*\\*'" }
   /* { dg-begin-multiline-output "" }
    return inst.member_1 (first, second, third);
-                                             ^
+                                ^~~~~~
+                                |
+                                const char*
      { dg-end-multiline-output "" } */
-  // { dg-message "candidate: 'int s9<T>::member_1\\(int, T, float\\)" "" { target *-*-* } s9_member_1 }
+  // { dg-message "initializing argument 2 of 'int s9<T>::member_1\\(int, T, float\\) .with T = const char\\*\\*.'" "" { target *-*-* } s9_member_1 } 
   /* { dg-begin-multiline-output "" }
  struct s9 { int member_1 (int one, T two, float three); };
-                 ^~~~~~~~
+                                    ~~^~~
      { dg-end-multiline-output "" } */
-  // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s9_member_1 }
+}
+
+/* Overloaded operator (with one candidate).  */
+
+struct s10 {};
+
+extern int operator- (const s10&, int); // { dg-line s10_operator }
+
+int test_10 ()
+{
+  s10 v10_a, v10_b;
+
+  return v10_a - v10_b; // { dg-error "no match for" }
   /* { dg-begin-multiline-output "" }
- struct s9 { int member_1 (int one, T two, float three); };
-                                    ~~^~~
+   return v10_a - v10_b;
+          ~~~~~~^~~~~~~
+     { dg-end-multiline-output "" } */
+  // { dg-message "candidate" "" { target *-*-* } s10_operator }
+  /* { dg-begin-multiline-output "" }
+ extern int operator- (const s10&, int);
+            ^~~~~~~~
+     { dg-end-multiline-output "" } */
+  // { dg-message "no known conversion for argument 2 from" "" { target *-*-* } s10_operator }
+  /* { dg-begin-multiline-output "" }
+ extern int operator- (const s10&, int);
+                                   ^~~
      { dg-end-multiline-output "" } */
 }
index e6b7219..35ebe52 100644 (file)
@@ -14,6 +14,6 @@ struct A
   {
     void (A::*p)() = &A::f;
     void (A::*q)() = &(A::f);       // { dg-error "parenthesized" }
-    foo(&g<int>);                   // { dg-error "no matching" }
+    foo(&g<int>);                   // { dg-error "cannot convert" }
   }
 };
index 588251d..f1591b2 100644 (file)
@@ -24,7 +24,7 @@ struct D : public B {
 
 void h(D* pd)
 {
-  pd->f(1);            // { dg-error "no matching" } D::f(struct B) hides B::f(int)
+  pd->f(1);            // { dg-error "cannot convert" } D::f(struct B) hides B::f(int)
 }
 
 int main () { return 0; }
index a7c0fbe..ccbd1f5 100644 (file)
@@ -22,6 +22,6 @@ void DoSomething(Ding A);
 void foo(Something* pX)
 {
   DoSomething(1);              // { dg-error "could not convert" }
-  pX->DoSomething(1);          // { dg-error "no matching" } 
-  (*pX).DoSomething(1);                // { dg-error "no matching" } 
+  pX->DoSomething(1);          // { dg-error "cannot convert" } 
+  (*pX).DoSomething(1);                // { dg-error "cannot convert" } 
 }
index bd88844..d68f184 100644 (file)
@@ -17,6 +17,6 @@ int
 foo(S *o)
 { // Neither call has a usable constructor for conversions of char[5] to Ack.
   function("adsf");// { dg-error "could not convert" }
-  o->method("adsf");// { dg-error "no matching" } 
+  o->method("adsf");// { dg-error "cannot convert" } 
   return 0;
 }
index c603aab..ab18189 100644 (file)
@@ -23,7 +23,7 @@ void B::set (f2 f) { std::cout << "called B\n|no known conversion";} // { dg-mes
 
 int main() {
     B b;
-    b.set(F1); // ARM page 309: should call A.set(f1) and that what g++ does,// { dg-error "match" }
+    b.set(F1); // ARM page 309: should call A.set(f1) and that what g++ does,// { dg-error "cannot convert" }
                // but 13.1 of ARM clearly states that it should call B::set()
                // or generate an error because overloading works only for
                // functions within the same scope (first page of chapter 13)
index 6a0f1c3..c2377fb 100644 (file)
@@ -15,6 +15,6 @@ struct a {
 
 a::a()
 {
-       foo( &junk ); // { dg-error "match" } junk is an unqualified-id.
-       foo( &bar );  // { dg-error "match" } bar is an unqualified-id.
+       foo( &junk ); // { dg-error "cannot convert" } junk is an unqualified-id.
+       foo( &bar );  // { dg-error "cannot convert" } bar is an unqualified-id.
 }