Commit 4911b24d by David Malcolm Committed by David Malcolm

C++: special-case single non-viable candidate (more PR c++/85110)

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
parent 3b582f1f
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>
......
......@@ -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
......
......@@ -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
......
......@@ -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)
{
......
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
......
......@@ -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" }
}
......@@ -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 "" } */
}
......@@ -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" }
}
};
......@@ -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; }
......@@ -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" }
}
......@@ -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;
}
......@@ -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)
......
......@@ -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.
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment