Test and support all cpp operator types.

2010-06-07  Sami Wagiaalla  <swagiaal@redhat.com>

	* value.h: Created oload_search_type enum.
	(find_overload_match): Use oload_search_type enum.
	* valops.c (find_overload_match): Support combined member and
	non-member search.
	* eval.c (evaluate_subexp_standard): Calls to
	find_overload_match now use oload_search_type enum.
	(oload_method_static): Verify index is a proper value.
	* valarith.c (value_user_defined_cpp_op): Search for and handle
	both member and non-member operators.
	(value_user_defined_cpp_op): New function.
	(value_user_defined_op): New function.
	(value_x_unop): Use value_user_defined_op.
	(value_x_binop): Ditto.
	* cp-support.c (make_symbol_overload_list_using): Added block
	iteration.
	Add check for namespace aliases and imported declarations.

2010-06-07  Sami Wagiaalla  <swagiaal@redhat.com>

	* gdb.cp/koenig.exp: Test for ADL operators.
	* gdb.cp/koenig.cc: Added ADL operators.
	* gdb.cp/operator.exp: New test.
	* gdb.cp/operator.cc: New test.
This commit is contained in:
Sami Wagiaalla
2010-06-07 16:11:35 +00:00
parent 0f32ea4ce3
commit 4c3376c849
11 changed files with 554 additions and 69 deletions

View File

@@ -2315,6 +2315,16 @@ value_find_oload_method_list (struct value **argp, const char *method,
matches on the argument types according to the overload resolution
rules.
METHOD can be one of three values:
NON_METHOD for non-member functions.
METHOD: for member functions.
BOTH: used for overload resolution of operators where the
candidates are expected to be either member or non member
functions. In this case the first argument ARGTYPES
(representing 'this') is expected to be a reference to the
target object, and will be dereferenced when attempting the
non-member search.
In the case of class methods, the parameter OBJ is an object value
in which to search for overloaded methods.
@@ -2342,16 +2352,20 @@ value_find_oload_method_list (struct value **argp, const char *method,
int
find_overload_match (struct type **arg_types, int nargs,
const char *name, int method, int lax,
struct value **objp, struct symbol *fsym,
const char *name, enum oload_search_type method,
int lax, struct value **objp, struct symbol *fsym,
struct value **valp, struct symbol **symp,
int *staticp, const int no_adl)
{
struct value *obj = (objp ? *objp : NULL);
/* Index of best overloaded function. */
int oload_champ;
int func_oload_champ = -1;
int method_oload_champ = -1;
/* The measure for the current best match. */
struct badness_vector *oload_champ_bv = NULL;
struct badness_vector *method_badness = NULL;
struct badness_vector *func_badness = NULL;
struct value *temp = obj;
/* For methods, the list of overloaded methods. */
struct fn_field *fns_ptr = NULL;
@@ -2367,9 +2381,11 @@ find_overload_match (struct type **arg_types, int nargs,
const char *obj_type_name = NULL;
const char *func_name = NULL;
enum oload_classification match_quality;
enum oload_classification method_match_quality = INCOMPATIBLE;
enum oload_classification func_match_quality = INCOMPATIBLE;
/* Get the list of overloaded methods or functions. */
if (method)
if (method == METHOD || method == BOTH)
{
gdb_assert (obj);
@@ -2392,10 +2408,13 @@ find_overload_match (struct type **arg_types, int nargs,
}
}
/* Retrieve the list of methods with the name NAME. */
fns_ptr = value_find_oload_method_list (&temp, name,
0, &num_fns,
&basetype, &boffset);
if (!fns_ptr || !num_fns)
/* If this is a method only search, and no methods were found
the search has faild. */
if (method == METHOD && (!fns_ptr || !num_fns))
error (_("Couldn't find method %s%s%s"),
obj_type_name,
(obj_type_name && *obj_type_name) ? "::" : "",
@@ -2403,15 +2422,33 @@ find_overload_match (struct type **arg_types, int nargs,
/* If we are dealing with stub method types, they should have
been resolved by find_method_list via
value_find_oload_method_list above. */
gdb_assert (TYPE_DOMAIN_TYPE (fns_ptr[0].type) != NULL);
oload_champ = find_oload_champ (arg_types, nargs, method,
num_fns, fns_ptr,
oload_syms, &oload_champ_bv);
if (fns_ptr)
{
gdb_assert (TYPE_DOMAIN_TYPE (fns_ptr[0].type) != NULL);
method_oload_champ = find_oload_champ (arg_types, nargs, method,
num_fns, fns_ptr,
oload_syms, &method_badness);
method_match_quality =
classify_oload_match (method_badness, nargs,
oload_method_static (method, fns_ptr,
method_oload_champ));
make_cleanup (xfree, method_badness);
}
}
else
if (method == NON_METHOD || method == BOTH)
{
const char *qualified_name = NULL;
/* If the the overload match is being search for both
as a method and non member function, the first argument
must now be dereferenced. */
if (method == BOTH)
arg_types[0] = TYPE_TARGET_TYPE (arg_types[0]);
if (fsym)
{
qualified_name = SYMBOL_NATURAL_NAME (fsym);
@@ -2454,30 +2491,67 @@ find_overload_match (struct type **arg_types, int nargs,
return 0;
}
make_cleanup (xfree, oload_syms);
make_cleanup (xfree, oload_champ_bv);
func_oload_champ = find_oload_champ_namespace (arg_types, nargs,
func_name,
qualified_name,
&oload_syms,
&func_badness,
no_adl);
oload_champ = find_oload_champ_namespace (arg_types, nargs,
func_name,
qualified_name,
&oload_syms,
&oload_champ_bv,
no_adl);
if (func_oload_champ >= 0)
func_match_quality = classify_oload_match (func_badness, nargs, 0);
make_cleanup (xfree, oload_syms);
make_cleanup (xfree, func_badness);
}
/* Did we find a match ? */
if (oload_champ == -1)
if (method_oload_champ == -1 && func_oload_champ == -1)
error (_("No symbol \"%s\" in current context."), name);
/* Check how bad the best match is. */
match_quality =
classify_oload_match (oload_champ_bv, nargs,
oload_method_static (method, fns_ptr,
oload_champ));
/* If we have found both a method match and a function
match, find out which one is better, and calculate match
quality. */
if (method_oload_champ >= 0 && func_oload_champ >= 0)
{
switch (compare_badness (func_badness, method_badness))
{
case 0: /* Top two contenders are equally good. */
/* FIXME: GDB does not support the general ambiguous
case. All candidates should be collected and presented
the the user. */
error (_("Ambiguous overload resolution"));
break;
case 1: /* Incomparable top contenders. */
/* This is an error incompatible candidates
should not have been proposed. */
error (_("Internal error: incompatible overload candidates proposed"));
break;
case 2: /* Function champion. */
method_oload_champ = -1;
match_quality = func_match_quality;
break;
case 3: /* Method champion. */
func_oload_champ = -1;
match_quality = method_match_quality;
break;
default:
error (_("Internal error: unexpected overload comparison result"));
break;
}
}
else
{
/* We have either a method match or a function match. */
if (method_oload_champ >= 0)
match_quality = method_match_quality;
else
match_quality = func_match_quality;
}
if (match_quality == INCOMPATIBLE)
{
if (method)
if (method == METHOD)
error (_("Cannot resolve method %s%s%s to any overloaded instance"),
obj_type_name,
(obj_type_name && *obj_type_name) ? "::" : "",
@@ -2488,7 +2562,7 @@ find_overload_match (struct type **arg_types, int nargs,
}
else if (match_quality == NON_STANDARD)
{
if (method)
if (method == METHOD)
warning (_("Using non-standard conversion to match method %s%s%s to supplied arguments"),
obj_type_name,
(obj_type_name && *obj_type_name) ? "::" : "",
@@ -2498,21 +2572,20 @@ find_overload_match (struct type **arg_types, int nargs,
func_name);
}
if (method)
if (staticp != NULL)
*staticp = oload_method_static (method, fns_ptr, method_oload_champ);
if (method_oload_champ >= 0)
{
if (staticp != NULL)
*staticp = oload_method_static (method, fns_ptr, oload_champ);
if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, oload_champ))
*valp = value_virtual_fn_field (&temp, fns_ptr, oload_champ,
if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, method_oload_champ))
*valp = value_virtual_fn_field (&temp, fns_ptr, method_oload_champ,
basetype, boffset);
else
*valp = value_fn_field (&temp, fns_ptr, oload_champ,
*valp = value_fn_field (&temp, fns_ptr, method_oload_champ,
basetype, boffset);
}
else
{
*symp = oload_syms[oload_champ];
}
*symp = oload_syms[func_oload_champ];
if (objp)
{
@@ -2801,7 +2874,8 @@ find_oload_champ (struct type **arg_types, int nargs, int method,
static int
oload_method_static (int method, struct fn_field *fns_ptr, int index)
{
if (method && TYPE_FN_FIELD_STATIC_P (fns_ptr, index))
if (method && fns_ptr && index >= 0
&& TYPE_FN_FIELD_STATIC_P (fns_ptr, index))
return 1;
else
return 0;