aboutsummaryrefslogtreecommitdiff
path: root/gdb/valops.c
diff options
context:
space:
mode:
authorSami Wagiaalla <swagiaal@redhat.com>2010-06-07 16:11:35 +0000
committerSami Wagiaalla <swagiaal@redhat.com>2010-06-07 16:11:35 +0000
commit4c3376c84943b8102da4237141dab7f1595912ca (patch)
treefc4936a3a61d60b2a60379e534e7081099969bb2 /gdb/valops.c
parent0f32ea4ce3309801590068305e7c8d7aeb495f2f (diff)
downloadgdb-4c3376c84943b8102da4237141dab7f1595912ca.zip
gdb-4c3376c84943b8102da4237141dab7f1595912ca.tar.gz
gdb-4c3376c84943b8102da4237141dab7f1595912ca.tar.bz2
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.
Diffstat (limited to 'gdb/valops.c')
-rw-r--r--gdb/valops.c148
1 files changed, 111 insertions, 37 deletions
diff --git a/gdb/valops.c b/gdb/valops.c
index 6cd66dd..08a64ce 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -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;