diff options
author | Sami Wagiaalla <swagiaal@redhat.com> | 2010-06-07 16:11:35 +0000 |
---|---|---|
committer | Sami Wagiaalla <swagiaal@redhat.com> | 2010-06-07 16:11:35 +0000 |
commit | 4c3376c84943b8102da4237141dab7f1595912ca (patch) | |
tree | fc4936a3a61d60b2a60379e534e7081099969bb2 /gdb/valops.c | |
parent | 0f32ea4ce3309801590068305e7c8d7aeb495f2f (diff) | |
download | gdb-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.c | 148 |
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; |