summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorswagiaal <swagiaal>2010-05-07 14:46:24 +0000
committerswagiaal <swagiaal>2010-05-07 14:46:24 +0000
commit3c30632200b0021f6fd6673553c3d124de629f68 (patch)
tree1fbe79e612b4748434aeca631f9463a41d95d955
parent87bebabc94a5e45723313af0c2427ed3711715b1 (diff)
downloadgdb-3c30632200b0021f6fd6673553c3d124de629f68.tar.gz
Add ADL support
2010-05-07 Sami Wagiaalla <swagiaal@redhat.com> 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 <swagiaal@redhat.com> * gdb.cp/koenig.exp: New test. * gdb.cp/koenig.cc: New test program.
-rw-r--r--gdb/ChangeLog27
-rw-r--r--gdb/c-exp.y32
-rw-r--r--gdb/cp-support.c98
-rw-r--r--gdb/cp-support.h4
-rw-r--r--gdb/eval.c47
-rw-r--r--gdb/expprint.c2
-rw-r--r--gdb/expression.h4
-rw-r--r--gdb/parse.c7
-rw-r--r--gdb/testsuite/ChangeLog5
-rw-r--r--gdb/testsuite/gdb.cp/koenig.cc245
-rw-r--r--gdb/testsuite/gdb.cp/koenig.exp109
-rw-r--r--gdb/valops.c101
-rw-r--r--gdb/value.h2
13 files changed, 632 insertions, 51 deletions
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 <swagiaal@redhat.com>
+
+ 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 <jan.kratochvil@redhat.com>
* 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 <tsval> STRING
%token <tsval> CHAR
%token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
+%token <ssym> UNKNOWN_CPP_NAME
%token <voidval> COMPLETE
%token <tsym> TYPENAME
%type <sval> 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 <swagiaal@redhat.com>
+
+ * gdb.cp/koenig.exp: New test.
+ * gdb.cp/koenig.cc: New test program.
+
2010-05-05 Joel Brobecker <brobecker@adacore.com>
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 <http://www.gnu.org/licenses/>.
+
+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);