From 7322dca9c16dfce7e9019240ac21037f2a4d6cb7 Mon Sep 17 00:00:00 2001 From: Sami Wagiaalla Date: Fri, 7 May 2010 14:46:28 +0000 Subject: [PATCH] Add ADL support 2010-05-07 Sami Wagiaalla PR C++/7943: * valops.c (find_overload_match): Handle fsym == NULL case. Add int no_adl argument. (find_oload_champ_namespace_loop): Call make_symbol_overload_list_adl when appropriate. Add int no_adl argument. (find_oload_champ_namespace): Add int no_adl argument. * parse.c (operator_length_standard): Return length for OP_ADL_FUNC expression. * expprint.c (op_name_standard): Added string for OP_ADL_FUNC case. * eval.c (evaluate_subexp_standard): Added OP_ADL_FUNC case. Evaluate arguments and use them to perform ADL lookup. Pass no_adl argument to find_overload_match. Disable adl lookup when evaluating a fully qualified OP_FUNCALL. * cp-support.h: Added prototype for make_symbol_overload_list_namespace. * cp-support.c (make_symbol_overload_list_namespace): New function. (make_symbol_overload_list_adl_namespace): New function. (make_symbol_overload_list_adl): New function. (make_symbol_overload_list_using): Moved code to add function to overload set to make_symbol_overload_list_namespace. * c-exp.y: create UNKNOWN_CPP_NAME token. Add parse rule for ADL functions. (classify_name): Recognize an UNKNOWN_CPP_NAME. 2010-05-07 Sami Wagiaalla * gdb.cp/koenig.exp: New test. * gdb.cp/koenig.cc: New test program. --- gdb/ChangeLog | 27 ++++ gdb/c-exp.y | 32 +++++ gdb/cp-support.c | 98 +++++++++++-- gdb/cp-support.h | 4 + gdb/eval.c | 47 +++++- gdb/expprint.c | 2 + gdb/expression.h | 4 + gdb/parse.c | 7 + gdb/testsuite/ChangeLog | 5 + gdb/testsuite/gdb.cp/koenig.cc | 245 ++++++++++++++++++++++++++++++++ gdb/testsuite/gdb.cp/koenig.exp | 109 ++++++++++++++ gdb/valops.c | 101 ++++++++----- gdb/value.h | 2 +- 13 files changed, 632 insertions(+), 51 deletions(-) create mode 100644 gdb/testsuite/gdb.cp/koenig.cc create mode 100644 gdb/testsuite/gdb.cp/koenig.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8a4703e732e..d5a9fb61d3e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,30 @@ +2010-05-07 Sami Wagiaalla + + PR C++/7943: + * valops.c (find_overload_match): Handle fsym == NULL case. + Add int no_adl argument. + (find_oload_champ_namespace_loop): Call make_symbol_overload_list_adl + when appropriate. + Add int no_adl argument. + (find_oload_champ_namespace): Add int no_adl argument. + * parse.c (operator_length_standard): Return length for OP_ADL_FUNC + expression. + * expprint.c (op_name_standard): Added string for OP_ADL_FUNC case. + * eval.c (evaluate_subexp_standard): Added OP_ADL_FUNC case. + Evaluate arguments and use them to perform ADL lookup. + Pass no_adl argument to find_overload_match. + Disable adl lookup when evaluating a fully qualified OP_FUNCALL. + * cp-support.h: Added prototype for + make_symbol_overload_list_namespace. + * cp-support.c (make_symbol_overload_list_namespace): New function. + (make_symbol_overload_list_adl_namespace): New function. + (make_symbol_overload_list_adl): New function. + (make_symbol_overload_list_using): Moved code to add function to + overload set to make_symbol_overload_list_namespace. + * c-exp.y: create UNKNOWN_CPP_NAME token. + Add parse rule for ADL functions. + (classify_name): Recognize an UNKNOWN_CPP_NAME. + 2010-05-07 Jan Kratochvil * fbsd-nat.c (fbsd_make_corefile_notes): Add cast to NULL used as diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 44fa6905446..4db41033db4 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -186,6 +186,7 @@ static struct stoken operator_stoken (const char *); %token STRING %token CHAR %token NAME /* BLOCKNAME defined below to give it higher precedence. */ +%token UNKNOWN_CPP_NAME %token COMPLETE %token TYPENAME %type name @@ -391,6 +392,29 @@ exp : exp '(' write_exp_elt_opcode (OP_FUNCALL); } ; +exp : UNKNOWN_CPP_NAME '(' + { + /* This could potentially be a an argument defined + lookup function (Koenig). */ + write_exp_elt_opcode (OP_ADL_FUNC); + write_exp_elt_block (expression_context_block); + write_exp_elt_sym (NULL); /* Placeholder. */ + write_exp_string ($1.stoken); + write_exp_elt_opcode (OP_ADL_FUNC); + + /* This is to save the value of arglist_len + being accumulated by an outer function call. */ + + start_arglist (); + } + arglist ')' %prec ARROW + { + write_exp_elt_opcode (OP_FUNCALL); + write_exp_elt_longcst ((LONGEST) end_arglist ()); + write_exp_elt_opcode (OP_FUNCALL); + } + ; + lcurly : '{' { start_arglist (); } ; @@ -1224,6 +1248,7 @@ name : NAME { $$ = $1.stoken; } | BLOCKNAME { $$ = $1.stoken; } | TYPENAME { $$ = $1.stoken; } | NAME_OR_INT { $$ = $1.stoken; } + | UNKNOWN_CPP_NAME { $$ = $1.stoken; } | operator { $$ = $1; } ; @@ -1244,6 +1269,7 @@ name_not_typename : NAME VAR_DOMAIN, &$$.is_a_field_of_this); } + | UNKNOWN_CPP_NAME ; %% @@ -2387,6 +2413,12 @@ classify_name (struct block *block) /* Any other kind of symbol */ yylval.ssym.sym = sym; yylval.ssym.is_a_field_of_this = is_a_field_of_this; + + if (sym == NULL + && parse_language->la_language == language_cplus + && !lookup_minimal_symbol (copy, NULL, NULL)) + return UNKNOWN_CPP_NAME; + return NAME; } diff --git a/gdb/cp-support.c b/gdb/cp-support.c index b5db6e0c747..8f447caa226 100644 --- a/gdb/cp-support.c +++ b/gdb/cp-support.c @@ -52,7 +52,7 @@ static void demangled_name_complaint (const char *name); /* Functions/variables related to overload resolution. */ -static int sym_return_val_size; +static int sym_return_val_size = -1; static int sym_return_val_index; static struct symbol **sym_return_val; @@ -709,6 +709,87 @@ make_symbol_overload_list (const char *func_name, return sym_return_val; } +/* Adds the function FUNC_NAME from NAMESPACE to the overload set. */ + +static void +make_symbol_overload_list_namespace (const char *func_name, + const char *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); + } +} + +/* Search the namespace of the given type and namespace of and public base + types. */ + +static void +make_symbol_overload_list_adl_namespace (struct type *type, + const char *func_name) +{ + char *namespace; + char *type_name; + int i, prefix_len; + + while (TYPE_CODE (type) == TYPE_CODE_PTR || TYPE_CODE (type) == TYPE_CODE_REF + || TYPE_CODE (type) == TYPE_CODE_ARRAY + || TYPE_CODE (type) == TYPE_CODE_TYPEDEF) + { + if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) + type = check_typedef(type); + else + type = TYPE_TARGET_TYPE (type); + } + + type_name = TYPE_NAME (type); + + prefix_len = cp_entire_prefix_len (type_name); + + if (prefix_len != 0) + { + namespace = alloca (prefix_len + 1); + strncpy (namespace, type_name, prefix_len); + namespace[prefix_len] = '\0'; + + make_symbol_overload_list_namespace (func_name, namespace); + } + + /* Check public base type */ + if (TYPE_CODE (type) == TYPE_CODE_CLASS) + for (i = 0; i < TYPE_N_BASECLASSES (type); i++) + { + if (BASETYPE_VIA_PUBLIC (type, i)) + make_symbol_overload_list_adl_namespace (TYPE_BASECLASS (type, i), + func_name); + } +} + +/* Adds the the overload list overload candidates for FUNC_NAME found through + argument dependent lookup. */ + +struct symbol ** +make_symbol_overload_list_adl (struct type **arg_types, int nargs, + const char *func_name) +{ + int i; + + gdb_assert (sym_return_val_size != -1); + + for (i = 1; i <= nargs; i++) + make_symbol_overload_list_adl_namespace (arg_types[i - 1], func_name); + + 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 @@ -736,20 +817,7 @@ make_symbol_overload_list_using (const char *func_name, } /* 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); - } + make_symbol_overload_list_namespace (func_name, namespace); } /* This does the bulk of the work of finding overloaded symbols. diff --git a/gdb/cp-support.h b/gdb/cp-support.h index dd4df842df1..ddc4c9377c5 100644 --- a/gdb/cp-support.h +++ b/gdb/cp-support.h @@ -110,6 +110,10 @@ extern char *cp_remove_params (const char *demangled_name); extern struct symbol **make_symbol_overload_list (const char *, const char *); +extern struct symbol **make_symbol_overload_list_adl (struct type **arg_types, + int nargs, + const char *func_name); + extern struct type *cp_lookup_rtti_type (const char *name, struct block *block); diff --git a/gdb/eval.c b/gdb/eval.c index b5c2012c9af..985e653ddf6 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -731,6 +731,7 @@ evaluate_subexp_standard (struct type *expect_type, return value_from_decfloat (exp->elts[pc + 1].type, exp->elts[pc + 2].decfloatconst); + case OP_ADL_FUNC: case OP_VAR_VALUE: (*pos) += 3; if (noside == EVAL_SKIP) @@ -1452,6 +1453,17 @@ evaluate_subexp_standard (struct type *expect_type, tem = 2; } } + else if (op == OP_ADL_FUNC) + { + /* Save the function position and move pos so that the arguments + can be evaluated. */ + int func_name_len; + save_pos1 = *pos; + tem = 1; + + func_name_len = longest_to_int (exp->elts[save_pos1 + 3].longconst); + (*pos) += 6 + BYTES_TO_EXP_ELEM (func_name_len + 1); + } else { /* Non-method function call */ @@ -1482,6 +1494,32 @@ evaluate_subexp_standard (struct type *expect_type, /* signal end of arglist */ argvec[tem] = 0; + if (op == OP_ADL_FUNC) + { + struct symbol *symp; + char *func_name; + int name_len; + int string_pc = save_pos1 + 3; + + /* Extract the function name. */ + name_len = longest_to_int (exp->elts[string_pc].longconst); + func_name = (char *) alloca (name_len + 1); + strcpy (func_name, &exp->elts[string_pc + 1].string); + + /* Prepare list of argument types for overload resolution */ + arg_types = (struct type **) alloca (nargs * (sizeof (struct type *))); + for (ix = 1; ix <= nargs; ix++) + arg_types[ix - 1] = value_type (argvec[ix]); + + find_overload_match (arg_types, nargs, func_name, + 0 /* not method */ , 0 /* strict match */ , + NULL, NULL /* pass NULL symbol since symbol is unknown */ , + NULL, &symp, NULL, 0); + + /* Now fix the expression being evaluated. */ + exp->elts[save_pos1 + 2].symbol = symp; + argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1, noside); + } if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR || (op == OP_SCOPE && function_name != NULL)) @@ -1513,7 +1551,7 @@ evaluate_subexp_standard (struct type *expect_type, (void) find_overload_match (arg_types, nargs, tstr, 1 /* method */ , 0 /* strict match */ , &arg2 /* the object */ , NULL, - &valp, NULL, &static_memfuncp); + &valp, NULL, &static_memfuncp, 0); if (op == OP_SCOPE && !static_memfuncp) { @@ -1565,6 +1603,11 @@ evaluate_subexp_standard (struct type *expect_type, { /* Language is C++, do some overload resolution before evaluation */ struct symbol *symp; + int no_adl = 0; + + /* If a scope has been specified disable ADL. */ + if (op == OP_SCOPE) + no_adl = 1; if (op == OP_VAR_VALUE) function = exp->elts[save_pos1+2].symbol; @@ -1577,7 +1620,7 @@ evaluate_subexp_standard (struct type *expect_type, (void) find_overload_match (arg_types, nargs, NULL /* no need for name */ , 0 /* not method */ , 0 /* strict match */ , NULL, function /* the function */ , - NULL, &symp, NULL); + NULL, &symp, NULL, no_adl); if (op == OP_VAR_VALUE) { diff --git a/gdb/expprint.c b/gdb/expprint.c index e378831b84a..45deffe4ab5 100644 --- a/gdb/expprint.c +++ b/gdb/expprint.c @@ -816,6 +816,8 @@ op_name_standard (enum exp_opcode opcode) return "OP_TYPE"; case OP_LABELED: return "OP_LABELED"; + case OP_ADL_FUNC: + return "OP_ADL_FUNC"; } } diff --git a/gdb/expression.h b/gdb/expression.h index ca216cf13e0..29ebde46b0e 100644 --- a/gdb/expression.h +++ b/gdb/expression.h @@ -347,6 +347,10 @@ enum exp_opcode Then comes another OP_DECFLOAT. */ OP_DECFLOAT, + /* OP_ADL_FUNC specifies that the function is to be looked up in an + Argument Dependent manner (Koenig lookup). */ + OP_ADL_FUNC, + /* First extension operator. Individual language modules define extra operators in *.inc include files below always starting with numbering at OP_EXTENDED0: diff --git a/gdb/parse.c b/gdb/parse.c index 5319555072c..7db6e926bf0 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -890,6 +890,13 @@ operator_length_standard (struct expression *expr, int endpos, args = 1; break; + case OP_ADL_FUNC: + oplen = longest_to_int (expr->elts[endpos - 2].longconst); + oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1); + oplen++; + oplen++; + break; + case OP_LABELED: case STRUCTOP_STRUCT: case STRUCTOP_PTR: diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 457a6282c35..013f5eb8e98 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-05-07 Sami Wagiaalla + + * gdb.cp/koenig.exp: New test. + * gdb.cp/koenig.cc: New test program. + 2010-05-05 Joel Brobecker Remove the use of prms_id and bug_id throughout the testsuite. diff --git a/gdb/testsuite/gdb.cp/koenig.cc b/gdb/testsuite/gdb.cp/koenig.cc new file mode 100644 index 00000000000..6cfa3f588c2 --- /dev/null +++ b/gdb/testsuite/gdb.cp/koenig.cc @@ -0,0 +1,245 @@ +namespace A +{ + class C + { + public: + static const int x = 11; + }; + + int + first (C c) + { + return 11; + } + + int + first (int a, C c) + { + return 22; + } + + int + second (int a, int b, C cc, int c, int d) + { + return 33; + } + +} + +struct B +{ + A::C c; +}; + +//------------ + +namespace E +{ + class O{}; + int foo (O o){return 1; } + int foo (O o, O o2){return 2; } + int foo (O o, O o2, int i){return 3; } +} + +namespace F +{ + class O{}; + int foo ( O fo, ::E::O eo){ return 4;} + int foo (int i, O fo, ::E::O eo){ return 5;} +} + +namespace G +{ + class O{}; + int foo (O go, ::F::O fo, ::E::O eo){ return 6; } +} + +//------------ + +namespace H +{ + class O{}; + int foo (O){ return 7;} +} + +namespace I +{ + class O: public H::O {}; + class X: H::O{}; +} + +//------------ + +namespace J +{ + union U{}; + struct S{}; + enum E{}; + + class A{ + public: + class B{}; + }; + + class C{}; + + int foo (U){ return 8;} + int foo (S){ return 9;} + int foo (E){ return 10;} + int foo (A::B){ return 11;} + int foo (A*){ return 12;} + int foo (A**){ return 13;} + int foo (C[]){ return 14;} + +} +//------------ + +namespace K{ + class O{}; + + int foo(O, int){ + return 15; + } + + int bar(O, int){ + return 15; + } +} + +int foo(K::O, float){ + return 16; +} + +int bar(K::O, int){ + return 16; +} +//------------ + +namespace L { + namespace A{ + namespace B{ + class O {}; + + int foo (O){ + return 17; + } + + } + } +} + +//------------ + +namespace M { + class A{ + public: + int foo(char) { + return 18; + } + }; + + int foo(A,char){ + return 19; + } + + int foo(A *,char){ + return 23; + } + + int bar(char){ + return 21; + } + + namespace N { + int foo(::M::A,int){ + return 20; + } + + int bar(int){ + return 22; + } + } +} +//------------ + +namespace O { + class A{}; + + int foo(A,int){ + return 23; + } + +} + +typedef O::A TOA; +typedef TOA TTOA; + +//------------ +int +main () +{ + A::C c; + B b; + + A::first (c); + first (0, c); + second (0, 0, c, 0, 0); + A::first (b.c); + + E::O eo; + F::O fo; + G::O go; + + foo (eo); + foo (eo, eo); + foo (eo, eo, 1); + foo (fo, eo); + foo (1 ,fo, eo); + foo (go, fo, eo); + + I::O io; + I::X ix; + + foo (io); +//foo (ix); + + J::U ju; + J::S js; + J::E je; + J::A::B jab; + J::A *jap; + J::A **japp; + J::C jca[3]; + + foo (ju); + foo (js); + foo (je); + foo (jab); + foo (jap); + foo (japp); + foo (jca); + + K::O ko; + foo (ko, 1); + foo (ko, 1.0f); + //bar(ko,1); + + L::A::B::O labo; + foo (labo); + + M::A ma; + foo(ma,'a'); + ma.foo('a'); + M::N::foo(ma,'a'); + + M::bar('a'); + M::N::bar('a'); + + TTOA ttoa; + foo (ttoa, 'a'); + + return first (0, c) + foo (eo) + + foo (eo, eo) + foo (eo, eo, 1) + + foo (fo, eo) + foo (1 ,fo, eo) + + foo (go, fo, eo); +} diff --git a/gdb/testsuite/gdb.cp/koenig.exp b/gdb/testsuite/gdb.cp/koenig.exp new file mode 100644 index 00000000000..b13ffbc2ce0 --- /dev/null +++ b/gdb/testsuite/gdb.cp/koenig.exp @@ -0,0 +1,109 @@ +# Copyright 2008 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +set testfile koenig +set srcfile ${testfile}.cc +set binfile ${objdir}/${subdir}/${testfile} +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } { + untested "Couldn't compile test program" + return -1 +} + +# Get things started. + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +############################################ + +if ![runto_main] then { + perror "couldn't run to breakpoint main" + continue +} + +# Test that koenig lookup finds correct function +gdb_test "p first(c)" "= 11" + +# Change the number of parameters and position of +# the qualifying parameter +gdb_test "p second(0,0,c,0,0)" "= 33" + +# Test that koenig lookup finds correct function +# even if it is overloaded +gdb_test "p first(0,c)" "= 22" + +# Test that koenig lookup finds correct function +# when the argument is an expression +gdb_test "p first(b.c)" "= 11" + +# test that resolutions can be made across namespaces +gdb_test "p foo(eo)" "= 1" +gdb_test "p foo(eo, eo)" "= 2" +gdb_test "p foo(eo, eo, 1)" "= 3" +gdb_test "p foo(fo, eo)" "= 4" +gdb_test "p foo(1 ,fo, eo)" "= 5" +gdb_test "p foo(go, fo, eo)" "= 6" + +#test that gdb fails gracefully +gdb_test "p fake(eo)" "No symbol \"fake\" in current context." + +#test that namespaces of base classes are searched +gdb_test "p foo(io)" "= 7" +gdb_test "p foo(ix)" "Cannot resolve function foo to any overloaded instance" + +#test for other types +gdb_test "p foo(ju)" "= 8" +gdb_test "p foo(js)" "= 9" +gdb_test "p foo(je)" "= 10" + +#test for class members +setup_xfail "*-*-*" +gdb_test "p foo(jab)" "= 11" + +gdb_test "p foo(jap)" "= 12" +gdb_test "p foo(japp)" "= 13" +gdb_test "p foo(jca)" "= 14" + +#test overload resolution +gdb_test "p foo(ko,1)" "= 15" +gdb_test "p foo(ko,1.0f)" "= 16" +setup_xfail "*-*-*" +gdb_test "p bar(ko,1)" "= -1" + +#test lookup of objects belonging to nested namespaces +gdb_test "p foo(labo)" "= 17" + +#test koenig found function do not compete with qualified +#names +gdb_test "p ma.foo('a')" "= 18" +gdb_test "p foo(ma,'a')" "= 19" +gdb_test "p M::N::foo(ma,'a')" "= 20" +gdb_test "p M::FAKE::foo(ma,'a')" "No type \"FAKE\" within class or namespace \"M\"." +gdb_test "p M::N::fake(ma,'a')" "No symbol \"fake\" in namespace \"M::N\"." + +gdb_test "p M::bar('a')" "= 21" +gdb_test "p M::N::bar('a')" "= 22" + +#test that lookup supports typedef +gdb_test "p foo(ttoa, 'a')" "= 23" diff --git a/gdb/valops.c b/gdb/valops.c index 65706c5ff2e..7979db91c00 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -63,13 +63,15 @@ static struct value *search_struct_method (const char *, struct value **, static int find_oload_champ_namespace (struct type **, int, const char *, const char *, struct symbol ***, - struct badness_vector **); + struct badness_vector **, + const int no_adl); static int find_oload_champ_namespace_loop (struct type **, int, const char *, const char *, int, struct symbol ***, - struct badness_vector **, int *); + struct badness_vector **, int *, + const int no_adl); static int find_oload_champ (struct type **, int, int, int, struct fn_field *, struct symbol **, @@ -2306,6 +2308,10 @@ value_find_oload_method_list (struct value **argp, const char *method, If a method is being searched for, and it is a static method, then STATICP will point to a non-zero value. + If NO_ADL argument dependent lookup is disabled. This is used to prevent + ADL overload candidates when performing overload resolution for a fully + qualified name. + Note: This function does *not* check the value of overload_resolution. Caller must check it to see whether overload resolution is permitted. @@ -2316,7 +2322,7 @@ find_overload_match (struct type **arg_types, int nargs, const char *name, int method, int lax, struct value **objp, struct symbol *fsym, struct value **valp, struct symbol **symp, - int *staticp) + int *staticp, const int no_adl) { struct value *obj = (objp ? *objp : NULL); /* Index of best overloaded function. */ @@ -2332,10 +2338,11 @@ find_overload_match (struct type **arg_types, int nargs, int num_fns = 0; struct type *basetype = NULL; int boffset; - struct cleanup *old_cleanups = NULL; + + struct cleanup *all_cleanups = make_cleanup (null_cleanup, NULL); const char *obj_type_name = NULL; - char *func_name = NULL; + const char *func_name = NULL; enum oload_classification match_quality; /* Get the list of overloaded methods or functions. */ @@ -2380,24 +2387,39 @@ find_overload_match (struct type **arg_types, int nargs, } else { - const char *qualified_name = SYMBOL_NATURAL_NAME (fsym); + const char *qualified_name = NULL; - /* If we have a function with a C++ name, try to extract just - the function part. Do not try this for non-functions (e.g. - function pointers). */ - if (qualified_name - && TYPE_CODE (check_typedef (SYMBOL_TYPE (fsym))) == TYPE_CODE_FUNC) + if (fsym) + { + qualified_name = SYMBOL_NATURAL_NAME (fsym); + + /* If we have a function with a C++ name, try to extract just + the function part. Do not try this for non-functions (e.g. + function pointers). */ + if (qualified_name + && TYPE_CODE (check_typedef (SYMBOL_TYPE (fsym))) == TYPE_CODE_FUNC) + { + char *temp; + + temp = cp_func_name (qualified_name); + + /* If cp_func_name did not remove anything, the name of the + symbol did not include scope or argument types - it was + probably a C-style function. */ + if (temp) + { + make_cleanup (xfree, temp); + if (strcmp (temp, qualified_name) == 0) + func_name = NULL; + else + func_name = temp; + } + } + } + else { - func_name = cp_func_name (qualified_name); - - /* If cp_func_name did not remove anything, the name of the - symbol did not include scope or argument types - it was - probably a C-style function. */ - if (func_name && strcmp (func_name, qualified_name) == 0) - { - xfree (func_name); - func_name = NULL; - } + func_name = name; + qualified_name = name; } /* If there was no C++ name, this must be a C-style function or @@ -2409,7 +2431,6 @@ find_overload_match (struct type **arg_types, int nargs, return 0; } - old_cleanups = make_cleanup (xfree, func_name); make_cleanup (xfree, oload_syms); make_cleanup (xfree, oload_champ_bv); @@ -2417,11 +2438,15 @@ find_overload_match (struct type **arg_types, int nargs, func_name, qualified_name, &oload_syms, - &oload_champ_bv); + &oload_champ_bv, + no_adl); } - /* Check how bad the best match is. */ + /* Did we find a match ? */ + if (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, @@ -2478,8 +2503,8 @@ find_overload_match (struct type **arg_types, int nargs, } *objp = temp; } - if (old_cleanups != NULL) - do_cleanups (old_cleanups); + + do_cleanups (all_cleanups); switch (match_quality) { @@ -2497,14 +2522,16 @@ find_overload_match (struct type **arg_types, int nargs, 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. */ + *OLOAD_CHAMP_BV. If NO_ADL, argument dependent lookup is not + performned. */ 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) + struct badness_vector **oload_champ_bv, + const int no_adl) { int oload_champ; @@ -2512,7 +2539,8 @@ find_oload_champ_namespace (struct type **arg_types, int nargs, func_name, qualified_name, 0, oload_syms, oload_champ_bv, - &oload_champ); + &oload_champ, + no_adl); return oload_champ; } @@ -2520,7 +2548,8 @@ find_oload_champ_namespace (struct type **arg_types, int nargs, /* 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. + if it isn't. Other arguments are the same as in + find_oload_champ_namespace It is the caller's responsibility to free *OLOAD_SYMS and *OLOAD_CHAMP_BV. */ @@ -2532,7 +2561,8 @@ find_oload_champ_namespace_loop (struct type **arg_types, int nargs, int namespace_len, struct symbol ***oload_syms, struct badness_vector **oload_champ_bv, - int *oload_champ) + int *oload_champ, + const int no_adl) { int next_namespace_len = namespace_len; int searched_deeper = 0; @@ -2566,7 +2596,7 @@ find_oload_champ_namespace_loop (struct type **arg_types, int nargs, func_name, qualified_name, next_namespace_len, oload_syms, oload_champ_bv, - oload_champ)) + oload_champ, no_adl)) { return 1; } @@ -2587,6 +2617,12 @@ find_oload_champ_namespace_loop (struct type **arg_types, int nargs, new_namespace[namespace_len] = '\0'; new_oload_syms = make_symbol_overload_list (func_name, new_namespace); + + /* If we have reached the deepest level perform argument + determined lookup. */ + if (!searched_deeper && !no_adl) + make_symbol_overload_list_adl (arg_types, nargs, func_name); + while (new_oload_syms[num_fns]) ++num_fns; @@ -2619,7 +2655,6 @@ find_oload_champ_namespace_loop (struct type **arg_types, int nargs, } else { - gdb_assert (new_oload_champ != -1); *oload_syms = new_oload_syms; *oload_champ = new_oload_champ; *oload_champ_bv = new_oload_champ_bv; diff --git a/gdb/value.h b/gdb/value.h index 1f2086e9317..57b4dd726f2 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -451,7 +451,7 @@ extern int find_overload_match (struct type **arg_types, int nargs, const char *name, int method, int lax, struct value **objp, struct symbol *fsym, struct value **valp, struct symbol **symp, - int *staticp); + int *staticp, const int no_adl); extern struct value *value_field (struct value *arg1, int fieldno); -- 2.30.2