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.
This commit is contained in:
parent
3f1f688424
commit
7322dca9c1
|
@ -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
|
||||
|
|
32
gdb/c-exp.y
32
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
47
gdb/eval.c
47
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)
|
||||
{
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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"
|
101
gdb/valops.c
101
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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue