From 8d577d328a1339e8b7107206c058b852e083f16b Mon Sep 17 00:00:00 2001 From: David Carlton Date: Mon, 2 Feb 2004 20:44:53 +0000 Subject: [PATCH] 2004-02-02 David Carlton * valops.c (enum oload_classification): New. (find_overload_match): Break implementation into separate functions; delete #if 0'd code; look for symbols within namespaces. (find_oload_champ_namespace,find_oload_champ_namespace_loop) (find_oload_champ,oload_method_static,classify_oload_match): New. * cp-support.h: Add declaration for cp_func_name; update declaration for make_symbol_overload_list. * cp-support.c (cp_func_name): New. (overload_list_add_symbol): Fix comment, use SYMBOL_LINKAGE_NAME and SYMBOL_NATURAL_NAME. (make_symbol_overload_list): Take a function name and a namespace instead of a symbol; change implementation. (make_symbol_overload_list_using): New. (make_symbol_overload_list_qualified, read_in_psymtabs): New. 2004-02-02 David Carlton * gdb.cp/overload.exp: Add overloadNamespace tests. * gdb.cp/overload.cc (dummyClass, dummyInstance): New. (overloadNamespace, XXX): New. (main): Call XXX::marker2. --- gdb/ChangeLog | 18 ++ gdb/cp-support.c | 229 +++++++++++----- gdb/cp-support.h | 5 +- gdb/testsuite/ChangeLog | 7 + gdb/testsuite/gdb.cp/overload.cc | 28 +- gdb/testsuite/gdb.cp/overload.exp | 15 ++ gdb/valops.c | 420 ++++++++++++++++++++++-------- 7 files changed, 540 insertions(+), 182 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c15528e3985..a862bf06aad 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,21 @@ +2004-02-02 David Carlton + + * valops.c (enum oload_classification): New. + (find_overload_match): Break implementation into separate + functions; delete #if 0'd code; look for symbols within + namespaces. + (find_oload_champ_namespace,find_oload_champ_namespace_loop) + (find_oload_champ,oload_method_static,classify_oload_match): New. + * cp-support.h: Add declaration for cp_func_name; update + declaration for make_symbol_overload_list. + * cp-support.c (cp_func_name): New. + (overload_list_add_symbol): Fix comment, use + SYMBOL_LINKAGE_NAME and SYMBOL_NATURAL_NAME. + (make_symbol_overload_list): Take a function name and a namespace + instead of a symbol; change implementation. + (make_symbol_overload_list_using): New. + (make_symbol_overload_list_qualified, read_in_psymtabs): New. + 2004-02-02 Fred Fish * main.c (gdb_stdtarg): Move definition to group with other diff --git a/gdb/cp-support.c b/gdb/cp-support.c index bd76fae1851..4344545c3e9 100644 --- a/gdb/cp-support.c +++ b/gdb/cp-support.c @@ -52,7 +52,15 @@ static struct symbol **sym_return_val; static char *remove_params (const char *demangled_name); -static void overload_list_add_symbol (struct symbol *sym, char *oload_name); +static void overload_list_add_symbol (struct symbol *sym, + const char *oload_name); + +static void make_symbol_overload_list_using (const char *func_name, + const char *namespace); + +static void make_symbol_overload_list_qualified (const char *func_name); + +static void read_in_psymtabs (const char *oload_name); /* The list of "maint cplus" commands. */ @@ -386,6 +394,34 @@ cp_entire_prefix_len (const char *name) return previous_len; } +/* If FULL_NAME is the demangled name of a C++ function (including an + arg list, possibly including namespace/class qualifications), + return a new string containing only the function name (without the + arg list/class qualifications). Otherwise, return NULL. The + caller is responsible for freeing the memory in question. */ + +char * +cp_func_name (const char *full_name) +{ + const char *previous_component = full_name; + const char *next_component; + + if (!full_name) + return NULL; + + for (next_component = (previous_component + + cp_find_first_component (previous_component)); + *next_component == ':'; + next_component = (previous_component + + cp_find_first_component (previous_component))) + { + /* Skip '::'. */ + previous_component = next_component + 2; + } + + return remove_params (previous_component); +} + /* Overload resolution functions. */ static char * @@ -430,12 +466,12 @@ remove_params (const char *demangled_name) return new_name; } -/* Test to see if the symbol specified by SYMNAME (which is already - demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN - characters. If so, add it to the current completion list. */ +/* Test to see if SYM is a symbol that we haven't seen corresponding + to a function named OLOAD_NAME. If so, add it to the current + completion list. */ static void -overload_list_add_symbol (struct symbol *sym, char *oload_name) +overload_list_add_symbol (struct symbol *sym, const char *oload_name) { int newsize; int i; @@ -447,11 +483,12 @@ overload_list_add_symbol (struct symbol *sym, char *oload_name) /* skip any symbols that we've already considered. */ for (i = 0; i < sym_return_val_index; ++i) - if (!strcmp (DEPRECATED_SYMBOL_NAME (sym), DEPRECATED_SYMBOL_NAME (sym_return_val[i]))) + if (strcmp (SYMBOL_LINKAGE_NAME (sym), + SYMBOL_LINKAGE_NAME (sym_return_val[i])) == 0) return; /* Get the demangled name without parameters */ - sym_name = remove_params (SYMBOL_DEMANGLED_NAME (sym)); + sym_name = remove_params (SYMBOL_NATURAL_NAME (sym)); if (!sym_name) return; @@ -476,82 +513,108 @@ overload_list_add_symbol (struct symbol *sym, char *oload_name) } /* Return a null-terminated list of pointers to function symbols that - * match name of the supplied symbol FSYM. - * This is used in finding all overloaded instances of a function name. - * This has been modified from make_symbol_completion_list. */ - + are named FUNC_NAME and are visible within NAMESPACE. */ struct symbol ** -make_symbol_overload_list (struct symbol *fsym) +make_symbol_overload_list (const char *func_name, + const char *namespace) { - struct symbol *sym; - struct symtab *s; - struct partial_symtab *ps; - struct objfile *objfile; - struct block *b, *surrounding_static_block = 0; - struct dict_iterator iter; - /* The name we are completing on. */ - char *oload_name = NULL; - /* Length of name. */ - int oload_name_len = 0; + struct cleanup *old_cleanups; - /* Look for the symbol we are supposed to complete on. */ + sym_return_val_size = 100; + sym_return_val_index = 0; + sym_return_val = xmalloc ((sym_return_val_size + 1) * + sizeof (struct symbol *)); + sym_return_val[0] = NULL; - oload_name = remove_params (SYMBOL_DEMANGLED_NAME (fsym)); - if (!oload_name) - { - sym_return_val_size = 1; - sym_return_val = (struct symbol **) xmalloc (2 * sizeof (struct symbol *)); - sym_return_val[0] = fsym; - sym_return_val[1] = NULL; + old_cleanups = make_cleanup (xfree, sym_return_val); + + make_symbol_overload_list_using (func_name, namespace); + + discard_cleanups (old_cleanups); + + return sym_return_val; +} + +/* This applies the using directives to add namespaces to search in, + and then searches for overloads in all of those namespaces. It + adds the symbols found to sym_return_val. Arguments are as in + make_symbol_overload_list. */ + +static void +make_symbol_overload_list_using (const char *func_name, + const char *namespace) +{ + const struct using_direct *current; + + /* First, go through the using directives. If any of them apply, + look in the appropriate namespaces for new functions to match + on. */ - return sym_return_val; + for (current = block_using (get_selected_block (0)); + current != NULL; + current = current->next) + { + if (strcmp (namespace, current->outer) == 0) + { + make_symbol_overload_list_using (func_name, + current->inner); + } } - oload_name_len = strlen (oload_name); - sym_return_val_size = 100; - sym_return_val_index = 0; - sym_return_val = (struct symbol **) xmalloc ((sym_return_val_size + 1) * sizeof (struct symbol *)); - sym_return_val[0] = NULL; + /* Now, add names for this namespace. */ + + if (namespace[0] == '\0') + { + make_symbol_overload_list_qualified (func_name); + } + else + { + char *concatenated_name + = alloca (strlen (namespace) + 2 + strlen (func_name) + 1); + strcpy (concatenated_name, namespace); + strcat (concatenated_name, "::"); + strcat (concatenated_name, func_name); + make_symbol_overload_list_qualified (concatenated_name); + } +} - /* Read in all partial symtabs containing a partial symbol named - OLOAD_NAME. */ +/* This does the bulk of the work of finding overloaded symbols. + FUNC_NAME is the name of the overloaded function we're looking for + (possibly including namespace info). */ - ALL_PSYMTABS (objfile, ps) - { - struct partial_symbol **psym; +static void +make_symbol_overload_list_qualified (const char *func_name) +{ + struct symbol *sym; + struct symtab *s; + struct objfile *objfile; + const struct block *b, *surrounding_static_block = 0; + struct dict_iterator iter; + const struct dictionary *dict; - /* If the psymtab's been read in we'll get it when we search - through the blockvector. */ - if (ps->readin) - continue; + /* Look through the partial symtabs for all symbols which begin + by matching FUNC_NAME. Make sure we read that symbol table in. */ - if ((lookup_partial_symbol (ps, oload_name, NULL, 1, VAR_DOMAIN) - != NULL) - || (lookup_partial_symbol (ps, oload_name, NULL, 0, VAR_DOMAIN) - != NULL)) - PSYMTAB_TO_SYMTAB (ps); - } + read_in_psymtabs (func_name); /* Search upwards from currently selected frame (so that we can complete on local vars. */ for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b)) { - if (!BLOCK_SUPERBLOCK (b)) - { - surrounding_static_block = b; /* For elimination of dups */ - } + dict = BLOCK_DICT (b); - /* Also catch fields of types defined in this places which match our - text string. Only complete on types visible from current context. */ - - ALL_BLOCK_SYMBOLS (b, iter, sym) + for (sym = dict_iter_name_first (dict, func_name, &iter); + sym; + sym = dict_iter_name_next (func_name, &iter)) { - overload_list_add_symbol (sym, oload_name); + overload_list_add_symbol (sym, func_name); } } + surrounding_static_block = block_static_block (get_selected_block (0)); + /* Go through the symtabs and check the externs and statics for symbols which match. */ @@ -559,10 +622,14 @@ make_symbol_overload_list (struct symbol *fsym) { QUIT; b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); - ALL_BLOCK_SYMBOLS (b, iter, sym) - { - overload_list_add_symbol (sym, oload_name); - } + dict = BLOCK_DICT (b); + + for (sym = dict_iter_name_first (dict, func_name, &iter); + sym; + sym = dict_iter_name_next (func_name, &iter)) + { + overload_list_add_symbol (sym, func_name); + } } ALL_SYMTABS (objfile, s) @@ -572,15 +639,37 @@ make_symbol_overload_list (struct symbol *fsym) /* Don't do this block twice. */ if (b == surrounding_static_block) continue; - ALL_BLOCK_SYMBOLS (b, iter, sym) - { - overload_list_add_symbol (sym, oload_name); - } + dict = BLOCK_DICT (b); + + for (sym = dict_iter_name_first (dict, func_name, &iter); + sym; + sym = dict_iter_name_next (func_name, &iter)) + { + overload_list_add_symbol (sym, func_name); + } } +} + +/* Look through the partial symtabs for all symbols which begin + by matching FUNC_NAME. Make sure we read that symbol table in. */ + +static void +read_in_psymtabs (const char *func_name) +{ + struct partial_symtab *ps; + struct objfile *objfile; - xfree (oload_name); + ALL_PSYMTABS (objfile, ps) + { + if (ps->readin) + continue; - return (sym_return_val); + if ((lookup_partial_symbol (ps, func_name, NULL, 1, VAR_DOMAIN) + != NULL) + || (lookup_partial_symbol (ps, func_name, NULL, 0, VAR_DOMAIN) + != NULL)) + psymtab_to_symtab (ps); + } } /* Lookup the rtti type for a class name. */ diff --git a/gdb/cp-support.h b/gdb/cp-support.h index 49da26ccb2c..bbf911a387f 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -60,7 +60,10 @@ extern unsigned int cp_find_first_component (const char *name); extern unsigned int cp_entire_prefix_len (const char *name); -extern struct symbol **make_symbol_overload_list (struct symbol *); +extern char *cp_func_name (const char *full_name); + +extern struct symbol **make_symbol_overload_list (const char *, + const char *); extern struct type *cp_lookup_rtti_type (const char *name, struct block *block); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index d29616a94a5..9a611bc0bcd 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2004-02-02 David Carlton + + * gdb.cp/overload.exp: Add overloadNamespace tests. + * gdb.cp/overload.cc (dummyClass, dummyInstance): New. + (overloadNamespace, XXX): New. + (main): Call XXX::marker2. + 2004-02-01 Fred Fish * gdb.base/dump.exp: Use runto_main instead of "runto main". diff --git a/gdb/testsuite/gdb.cp/overload.cc b/gdb/testsuite/gdb.cp/overload.cc index 56afc96884e..a41e14dc198 100644 --- a/gdb/testsuite/gdb.cp/overload.cc +++ b/gdb/testsuite/gdb.cp/overload.cc @@ -53,6 +53,31 @@ int intToChar (char c) void marker1() {} +// Now test how overloading and namespaces interact. + +class dummyClass {}; + +dummyClass dummyInstance; + +int overloadNamespace(int i) +{ + return 1; +} + +int overloadNamespace(dummyClass d) +{ + return 2; +} + +namespace XXX { + int overloadNamespace (char c) + { + return 3; + } + + void marker2() {} +} + int main () { char arg2 = 2; @@ -81,7 +106,8 @@ int main () intToChar(1); marker1(); // marker1-returns-here - return 0; // marker1-returns-here + XXX::marker2(); // marker1-returns-here + return 0; } foo::foo (int i) { ifoo = i; ccpfoo = NULL; } diff --git a/gdb/testsuite/gdb.cp/overload.exp b/gdb/testsuite/gdb.cp/overload.exp index 2925b504b43..5ce9f81c9b9 100644 --- a/gdb/testsuite/gdb.cp/overload.exp +++ b/gdb/testsuite/gdb.cp/overload.exp @@ -296,6 +296,21 @@ gdb_test "list \"foo::overloadfnarg(int, int (*)(int))\"" \ "int foo::overloadfnarg.*\\(int arg, int \\(\\*foo\\) \\(int\\)\\).*" \ "list overloaded function with function ptr args - quotes around argument" +# Now some tests to see how overloading and namespaces interact. + +gdb_test "print overloadNamespace(1)" ".\[0-9\]* = 1" +gdb_test "print overloadNamespace('a')" ".\[0-9\]* = 1" +gdb_test "print overloadNamespace(dummyInstance)" ".\[0-9\]* = 2" + +if ![runto 'XXX::marker2'] then { + perror "couldn't run to XXX::marker2" + continue +} + +gdb_test "print overloadNamespace(1)" ".\[0-9\]* = 3" "print overloadNamespace(1) in XXX" +gdb_test "print overloadNamespace('a')" ".\[0-9\]* = 3" "print overloadNamespace('a') in XXX" +gdb_test "print overloadNamespace(dummyInstance)" ".\[0-9\]* = 2" "print overloadNamespace(dummyInstance) in XXX" + # One last mysterious test. # I wonder what this is for? diff --git a/gdb/valops.c b/gdb/valops.c index 14fefd90174..60422779a14 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -62,6 +62,38 @@ static struct value *search_struct_method (char *, struct value **, struct value **, int, int *, struct type *); +static int find_oload_champ_namespace (struct type **arg_types, int nargs, + const char *func_name, + const char *qualified_name, + struct symbol ***oload_syms, + struct badness_vector **oload_champ_bv); + +static +int find_oload_champ_namespace_loop (struct type **arg_types, int nargs, + const char *func_name, + const char *qualified_name, + int namespace_len, + struct symbol ***oload_syms, + struct badness_vector **oload_champ_bv, + int *oload_champ); + +static int find_oload_champ (struct type **arg_types, int nargs, int method, + int num_fns, + struct fn_field *fns_ptr, + struct symbol **oload_syms, + struct badness_vector **oload_champ_bv); + +static int oload_method_static (int method, struct fn_field *fns_ptr, + int index); + +enum oload_classification { STANDARD, NON_STANDARD, INCOMPATIBLE }; + +static enum +oload_classification classify_oload_match (struct badness_vector + * oload_champ_bv, + int nargs, + int static_offset); + static int check_field_in (struct type *, const char *); static struct value *value_struct_elt_for_reference (struct type *domain, @@ -1893,19 +1925,10 @@ find_overload_match (struct type **arg_types, int nargs, char *name, int method, int lax, struct value **objp, struct symbol *fsym, struct value **valp, struct symbol **symp, int *staticp) { - int nparms; - struct type **parm_types; - int champ_nparms = 0; struct value *obj = (objp ? *objp : NULL); - short oload_champ = -1; /* Index of best overloaded function */ - short oload_ambiguous = 0; /* Current ambiguity state for overload resolution */ - /* 0 => no ambiguity, 1 => two good funcs, 2 => incomparable funcs */ - short oload_ambig_champ = -1; /* 2nd contender for best match */ - short oload_non_standard = 0; /* did we have to use non-standard conversions? */ - short oload_incompatible = 0; /* are args supplied incompatible with any function? */ + int oload_champ; /* Index of best overloaded function */ - struct badness_vector *bv; /* A measure of how good an overloaded instance is */ struct badness_vector *oload_champ_bv = NULL; /* The measure for the current best match */ struct value *temp = obj; @@ -1914,13 +1937,13 @@ find_overload_match (struct type **arg_types, int nargs, char *name, int method, int num_fns = 0; /* Number of overloaded instances being considered */ struct type *basetype = NULL; int boffset; - int jj; int ix; int static_offset; - struct cleanup *cleanups = NULL; + struct cleanup *old_cleanups = NULL; - char *obj_type_name = NULL; + const char *obj_type_name = NULL; char *func_name = NULL; + enum oload_classification match_quality; /* Get the list of overloaded methods or functions */ if (method) @@ -1944,38 +1967,269 @@ find_overload_match (struct type **arg_types, int nargs, char *name, int method, 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); } else { - int i = -1; - func_name = cplus_demangle (DEPRECATED_SYMBOL_NAME (fsym), DMGL_NO_OPTS); + const char *qualified_name = SYMBOL_CPLUS_DEMANGLED_NAME (fsym); + func_name = cp_func_name (qualified_name); /* If the name is NULL this must be a C-style function. Just return the same symbol. */ - if (!func_name) + if (func_name == NULL) { *symp = fsym; return 0; } - oload_syms = make_symbol_overload_list (fsym); - cleanups = make_cleanup (xfree, oload_syms); - while (oload_syms[++i]) - num_fns++; - if (!num_fns) - error ("Couldn't find function %s", func_name); + old_cleanups = make_cleanup (xfree, func_name); + make_cleanup (xfree, oload_syms); + make_cleanup (xfree, oload_champ_bv); + + oload_champ = find_oload_champ_namespace (arg_types, nargs, + func_name, + qualified_name, + &oload_syms, + &oload_champ_bv); + } + + /* 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 (match_quality == INCOMPATIBLE) + { + if (method) + error ("Cannot resolve method %s%s%s to any overloaded instance", + obj_type_name, + (obj_type_name && *obj_type_name) ? "::" : "", + name); + else + error ("Cannot resolve function %s to any overloaded instance", + func_name); + } + else if (match_quality == NON_STANDARD) + { + if (method) + warning ("Using non-standard conversion to match method %s%s%s to supplied arguments", + obj_type_name, + (obj_type_name && *obj_type_name) ? "::" : "", + name); + else + warning ("Using non-standard conversion to match function %s to supplied arguments", + func_name); + } + + if (method) + { + 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, basetype, boffset); + else + *valp = value_fn_field (&temp, fns_ptr, oload_champ, basetype, boffset); + } + else + { + *symp = oload_syms[oload_champ]; + } + + if (objp) + { + if (TYPE_CODE (VALUE_TYPE (temp)) != TYPE_CODE_PTR + && TYPE_CODE (VALUE_TYPE (*objp)) == TYPE_CODE_PTR) + { + temp = value_addr (temp); + } + *objp = temp; + } + if (old_cleanups != NULL) + do_cleanups (old_cleanups); + + switch (match_quality) + { + case INCOMPATIBLE: + return 100; + case NON_STANDARD: + return 10; + default: /* STANDARD */ + return 0; + } +} + +/* Find the best overload match, searching for FUNC_NAME in namespaces + contained in QUALIFIED_NAME until it either finds a good match or + runs out of namespaces. It stores the overloaded functions in + *OLOAD_SYMS, and the badness vector in *OLOAD_CHAMP_BV. The + calling function is responsible for freeing *OLOAD_SYMS and + *OLOAD_CHAMP_BV. */ + +static int +find_oload_champ_namespace (struct type **arg_types, int nargs, + const char *func_name, + const char *qualified_name, + struct symbol ***oload_syms, + struct badness_vector **oload_champ_bv) +{ + int oload_champ; + + find_oload_champ_namespace_loop (arg_types, nargs, + func_name, + qualified_name, 0, + oload_syms, oload_champ_bv, + &oload_champ); + + return oload_champ; +} + +/* Helper function for find_oload_champ_namespace; NAMESPACE_LEN is + how deep we've looked for namespaces, and the champ is stored in + OLOAD_CHAMP. The return value is 1 if the champ is a good one, 0 + if it isn't. + + It is the caller's responsibility to free *OLOAD_SYMS and + *OLOAD_CHAMP_BV. */ + +static int +find_oload_champ_namespace_loop (struct type **arg_types, int nargs, + const char *func_name, + const char *qualified_name, + int namespace_len, + struct symbol ***oload_syms, + struct badness_vector **oload_champ_bv, + int *oload_champ) +{ + int next_namespace_len = namespace_len; + int searched_deeper = 0; + int num_fns = 0; + struct cleanup *old_cleanups; + int new_oload_champ; + struct symbol **new_oload_syms; + struct badness_vector *new_oload_champ_bv; + char *new_namespace; + + if (next_namespace_len != 0) + { + gdb_assert (qualified_name[next_namespace_len] == ':'); + next_namespace_len += 2; + } + next_namespace_len + += cp_find_first_component (qualified_name + next_namespace_len); + + /* Initialize these to values that can safely be xfree'd. */ + *oload_syms = NULL; + *oload_champ_bv = NULL; + + /* First, see if we have a deeper namespace we can search in. If we + get a good match there, use it. */ + + if (qualified_name[next_namespace_len] == ':') + { + searched_deeper = 1; + + if (find_oload_champ_namespace_loop (arg_types, nargs, + func_name, qualified_name, + next_namespace_len, + oload_syms, oload_champ_bv, + oload_champ)) + { + return 1; + } + }; + + /* If we reach here, either we're in the deepest namespace or we + didn't find a good match in a deeper namespace. But, in the + latter case, we still have a bad match in a deeper namespace; + note that we might not find any match at all in the current + namespace. (There's always a match in the deepest namespace, + because this overload mechanism only gets called if there's a + function symbol to start off with.) */ + + old_cleanups = make_cleanup (xfree, *oload_syms); + old_cleanups = make_cleanup (xfree, *oload_champ_bv); + new_namespace = alloca (namespace_len + 1); + strncpy (new_namespace, qualified_name, namespace_len); + new_namespace[namespace_len] = '\0'; + new_oload_syms = make_symbol_overload_list (func_name, + new_namespace); + while (new_oload_syms[num_fns]) + ++num_fns; + + new_oload_champ = find_oload_champ (arg_types, nargs, 0, num_fns, + NULL, new_oload_syms, + &new_oload_champ_bv); + + /* Case 1: We found a good match. Free earlier matches (if any), + and return it. Case 2: We didn't find a good match, but we're + not the deepest function. Then go with the bad match that the + deeper function found. Case 3: We found a bad match, and we're + the deepest function. Then return what we found, even though + it's a bad match. */ + + if (new_oload_champ != -1 + && classify_oload_match (new_oload_champ_bv, nargs, 0) == STANDARD) + { + *oload_syms = new_oload_syms; + *oload_champ = new_oload_champ; + *oload_champ_bv = new_oload_champ_bv; + do_cleanups (old_cleanups); + return 1; + } + else if (searched_deeper) + { + xfree (new_oload_syms); + xfree (new_oload_champ_bv); + discard_cleanups (old_cleanups); + return 0; + } + else + { + gdb_assert (new_oload_champ != -1); + *oload_syms = new_oload_syms; + *oload_champ = new_oload_champ; + *oload_champ_bv = new_oload_champ_bv; + discard_cleanups (old_cleanups); + return 0; } +} + +/* Look for a function to take NARGS args of types ARG_TYPES. Find + the best match from among the overloaded methods or functions + (depending on METHOD) given by FNS_PTR or OLOAD_SYMS, respectively. + The number of methods/functions in the list is given by NUM_FNS. + Return the index of the best match; store an indication of the + quality of the match in OLOAD_CHAMP_BV. + + It is the caller's responsibility to free *OLOAD_CHAMP_BV. */ + +static int +find_oload_champ (struct type **arg_types, int nargs, int method, + int num_fns, struct fn_field *fns_ptr, + struct symbol **oload_syms, + struct badness_vector **oload_champ_bv) +{ + int ix; + struct badness_vector *bv; /* A measure of how good an overloaded instance is */ + int oload_champ = -1; /* Index of best overloaded function */ + int oload_ambiguous = 0; /* Current ambiguity state for overload resolution */ + /* 0 => no ambiguity, 1 => two good funcs, 2 => incomparable funcs */ - oload_champ_bv = NULL; + *oload_champ_bv = NULL; /* Consider each candidate in turn */ for (ix = 0; ix < num_fns; ix++) { - static_offset = 0; + int jj; + int static_offset = oload_method_static (method, fns_ptr, ix); + int nparms; + struct type **parm_types; + if (method) { - if (TYPE_FN_FIELD_STATIC_P (fns_ptr, ix)) - static_offset = 1; nparms = TYPE_NFIELDS (TYPE_FN_FIELD_TYPE (fns_ptr, ix)); } else @@ -1996,30 +2250,25 @@ find_overload_match (struct type **arg_types, int nargs, char *name, int method, bv = rank_function (parm_types, nparms, arg_types + static_offset, nargs - static_offset); - if (!oload_champ_bv) + if (!*oload_champ_bv) { - oload_champ_bv = bv; + *oload_champ_bv = bv; oload_champ = 0; - champ_nparms = nparms; } else /* See whether current candidate is better or worse than previous best */ - switch (compare_badness (bv, oload_champ_bv)) + switch (compare_badness (bv, *oload_champ_bv)) { case 0: oload_ambiguous = 1; /* top two contenders are equally good */ - oload_ambig_champ = ix; break; case 1: oload_ambiguous = 2; /* incomparable top contenders */ - oload_ambig_champ = ix; break; case 2: - oload_champ_bv = bv; /* new champion, record details */ + *oload_champ_bv = bv; /* new champion, record details */ oload_ambiguous = 0; oload_champ = ix; - oload_ambig_champ = -1; - champ_nparms = nparms; break; case 3: default: @@ -2036,90 +2285,41 @@ find_overload_match (struct type **arg_types, int nargs, char *name, int method, fprintf_filtered (gdb_stderr,"...Badness @ %d : %d\n", jj, bv->rank[jj]); fprintf_filtered (gdb_stderr,"Overload resolution champion is %d, ambiguous? %d\n", oload_champ, oload_ambiguous); } - } /* end loop over all candidates */ - /* NOTE: dan/2000-03-10: Seems to be a better idea to just pick one - if they have the exact same goodness. This is because there is no - way to differentiate based on return type, which we need to in - cases like overloads of .begin() */ -#if 0 - if (oload_ambiguous) - { - if (method) - error ("Cannot resolve overloaded method %s%s%s to unique instance; disambiguate by specifying function signature", - obj_type_name, - (obj_type_name && *obj_type_name) ? "::" : "", - name); - else - error ("Cannot resolve overloaded function %s to unique instance; disambiguate by specifying function signature", - func_name); } -#endif - /* Check how bad the best match is. */ - static_offset = 0; - if (method && TYPE_FN_FIELD_STATIC_P (fns_ptr, oload_champ)) - static_offset = 1; - for (ix = 1; ix <= nargs - static_offset; ix++) - { - if (oload_champ_bv->rank[ix] >= 100) - oload_incompatible = 1; /* truly mismatched types */ + return oload_champ; +} - else if (oload_champ_bv->rank[ix] >= 10) - oload_non_standard = 1; /* non-standard type conversions needed */ - } - if (oload_incompatible) - { - if (method) - error ("Cannot resolve method %s%s%s to any overloaded instance", - obj_type_name, - (obj_type_name && *obj_type_name) ? "::" : "", - name); - else - error ("Cannot resolve function %s to any overloaded instance", - func_name); - } - else if (oload_non_standard) - { - if (method) - warning ("Using non-standard conversion to match method %s%s%s to supplied arguments", - obj_type_name, - (obj_type_name && *obj_type_name) ? "::" : "", - name); - else - warning ("Using non-standard conversion to match function %s to supplied arguments", - func_name); - } +/* Return 1 if we're looking at a static method, 0 if we're looking at + a non-static method or a function that isn't a method. */ - if (method) - { - if (staticp && TYPE_FN_FIELD_STATIC_P (fns_ptr, oload_champ)) - *staticp = 1; - else if (staticp) - *staticp = 0; - if (TYPE_FN_FIELD_VIRTUAL_P (fns_ptr, oload_champ)) - *valp = value_virtual_fn_field (&temp, fns_ptr, oload_champ, basetype, boffset); - else - *valp = value_fn_field (&temp, fns_ptr, oload_champ, basetype, boffset); - } +static int +oload_method_static (int method, struct fn_field *fns_ptr, int index) +{ + if (method && TYPE_FN_FIELD_STATIC_P (fns_ptr, index)) + return 1; else - { - *symp = oload_syms[oload_champ]; - xfree (func_name); - } + return 0; +} - if (objp) +/* Check how good an overload match OLOAD_CHAMP_BV represents. */ + +static enum oload_classification +classify_oload_match (struct badness_vector *oload_champ_bv, + int nargs, + int static_offset) +{ + int ix; + + for (ix = 1; ix <= nargs - static_offset; ix++) { - if (TYPE_CODE (VALUE_TYPE (temp)) != TYPE_CODE_PTR - && TYPE_CODE (VALUE_TYPE (*objp)) == TYPE_CODE_PTR) - { - temp = value_addr (temp); - } - *objp = temp; + if (oload_champ_bv->rank[ix] >= 100) + return INCOMPATIBLE; /* truly mismatched types */ + else if (oload_champ_bv->rank[ix] >= 10) + return NON_STANDARD; /* non-standard type conversions needed */ } - if (cleanups != NULL) - do_cleanups (cleanups); - return oload_incompatible ? 100 : (oload_non_standard ? 10 : 0); + return STANDARD; /* Only standard conversions needed. */ } /* C++: return 1 is NAME is a legitimate name for the destructor -- 2.30.2