* c-exp.y: Add new rule for resolving method overloads.
* eval.c (make_params): New function. (free_param_types): New function. (evaluate_subexp_standard): Pass expect_type to value_aggregate_elt. Handle case TYPE_INSTANCE. (evaluate_subexp_for_address): Pass expect_type to value_aggregate_elt. * expression.h (enum exp_opcode): Add TYPE_INSTANCE. (compare_parameters): Add declaration. * parse.c (operator_length_standard): Add TYPE_INSTANCE. * valops.c (value_aggregate_elt): Add new expect_type parameter. Pass expect_type to value_struct_elt_for_reference. (value_struct_elt_for_reference): Add expect_type parameter and use compare_parameters. Check for overload matches with and without artificial parameters. Skip artificial methods. (compare_parameters): New function. * value.h (value_aggregate_elt): Add new expect_type parameter.
This commit is contained in:
parent
85feb311d3
commit
072bba3b0f
7 changed files with 173 additions and 15 deletions
|
@ -1,3 +1,23 @@
|
||||||
|
2009-11-10 Keith Seitz <keiths@redhat.com>
|
||||||
|
|
||||||
|
* c-exp.y: Add new rule for resolving method overloads.
|
||||||
|
* eval.c (make_params): New function.
|
||||||
|
(free_param_types): New function.
|
||||||
|
(evaluate_subexp_standard): Pass expect_type to value_aggregate_elt.
|
||||||
|
Handle case TYPE_INSTANCE.
|
||||||
|
(evaluate_subexp_for_address): Pass expect_type to value_aggregate_elt.
|
||||||
|
* expression.h (enum exp_opcode): Add TYPE_INSTANCE.
|
||||||
|
(compare_parameters): Add declaration.
|
||||||
|
* parse.c (operator_length_standard): Add TYPE_INSTANCE.
|
||||||
|
* valops.c (value_aggregate_elt): Add new expect_type parameter.
|
||||||
|
Pass expect_type to value_struct_elt_for_reference.
|
||||||
|
(value_struct_elt_for_reference): Add expect_type parameter and use
|
||||||
|
compare_parameters.
|
||||||
|
Check for overload matches with and without artificial parameters.
|
||||||
|
Skip artificial methods.
|
||||||
|
(compare_parameters): New function.
|
||||||
|
* value.h (value_aggregate_elt): Add new expect_type parameter.
|
||||||
|
|
||||||
2009-11-10 Joseph Myers <joseph@codesourcery.com>
|
2009-11-10 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
* solib-svr4.c (enable_break): Call
|
* solib-svr4.c (enable_break): Call
|
||||||
|
|
12
gdb/c-exp.y
12
gdb/c-exp.y
|
@ -401,6 +401,18 @@ arglist : arglist ',' exp %prec ABOVE_COMMA
|
||||||
{ arglist_len++; }
|
{ arglist_len++; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
exp : exp '(' nonempty_typelist ')' const_or_volatile
|
||||||
|
{ int i;
|
||||||
|
write_exp_elt_opcode (TYPE_INSTANCE);
|
||||||
|
write_exp_elt_longcst ((LONGEST) $<ivec>3[0]);
|
||||||
|
for (i = 0; i < $<ivec>3[0]; ++i)
|
||||||
|
write_exp_elt_type ($<tvec>3[i + 1]);
|
||||||
|
write_exp_elt_longcst((LONGEST) $<ivec>3[0]);
|
||||||
|
write_exp_elt_opcode (TYPE_INSTANCE);
|
||||||
|
free ($3);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
rcurly : '}'
|
rcurly : '}'
|
||||||
{ $$ = end_arglist () - 1; }
|
{ $$ = end_arglist () - 1; }
|
||||||
;
|
;
|
||||||
|
|
43
gdb/eval.c
43
gdb/eval.c
|
@ -40,6 +40,8 @@
|
||||||
#include "regcache.h"
|
#include "regcache.h"
|
||||||
#include "user-regs.h"
|
#include "user-regs.h"
|
||||||
#include "valprint.h"
|
#include "valprint.h"
|
||||||
|
#include "gdb_obstack.h"
|
||||||
|
#include "objfiles.h"
|
||||||
#include "python/python.h"
|
#include "python/python.h"
|
||||||
|
|
||||||
#include "gdb_assert.h"
|
#include "gdb_assert.h"
|
||||||
|
@ -651,6 +653,29 @@ ptrmath_type_p (struct type *type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Constructs a fake method with the given parameter types.
|
||||||
|
This function is used by the parser to construct an "expected"
|
||||||
|
type for method overload resolution. */
|
||||||
|
|
||||||
|
static struct type *
|
||||||
|
make_params (int num_types, struct type **param_types)
|
||||||
|
{
|
||||||
|
struct type *type = XZALLOC (struct type);
|
||||||
|
TYPE_MAIN_TYPE (type) = XZALLOC (struct main_type);
|
||||||
|
TYPE_LENGTH (type) = 1;
|
||||||
|
TYPE_CODE (type) = TYPE_CODE_METHOD;
|
||||||
|
TYPE_VPTR_FIELDNO (type) = -1;
|
||||||
|
TYPE_CHAIN (type) = type;
|
||||||
|
TYPE_NFIELDS (type) = num_types;
|
||||||
|
TYPE_FIELDS (type) = (struct field *)
|
||||||
|
TYPE_ZALLOC (type, sizeof (struct field) * num_types);
|
||||||
|
|
||||||
|
while (num_types-- > 0)
|
||||||
|
TYPE_FIELD_TYPE (type, num_types) = param_types[num_types];
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
struct value *
|
struct value *
|
||||||
evaluate_subexp_standard (struct type *expect_type,
|
evaluate_subexp_standard (struct type *expect_type,
|
||||||
struct expression *exp, int *pos,
|
struct expression *exp, int *pos,
|
||||||
|
@ -684,7 +709,7 @@ evaluate_subexp_standard (struct type *expect_type,
|
||||||
goto nosideret;
|
goto nosideret;
|
||||||
arg1 = value_aggregate_elt (exp->elts[pc + 1].type,
|
arg1 = value_aggregate_elt (exp->elts[pc + 1].type,
|
||||||
&exp->elts[pc + 3].string,
|
&exp->elts[pc + 3].string,
|
||||||
0, noside);
|
expect_type, 0, noside);
|
||||||
if (arg1 == NULL)
|
if (arg1 == NULL)
|
||||||
error (_("There is no field named %s"), &exp->elts[pc + 3].string);
|
error (_("There is no field named %s"), &exp->elts[pc + 3].string);
|
||||||
return arg1;
|
return arg1;
|
||||||
|
@ -1730,6 +1755,20 @@ evaluate_subexp_standard (struct type *expect_type,
|
||||||
error (_("non-pointer-to-member value used in pointer-to-member construct"));
|
error (_("non-pointer-to-member value used in pointer-to-member construct"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case TYPE_INSTANCE:
|
||||||
|
nargs = longest_to_int (exp->elts[pc + 1].longconst);
|
||||||
|
arg_types = (struct type **) alloca (nargs * sizeof (struct type *));
|
||||||
|
for (ix = 0; ix < nargs; ++ix)
|
||||||
|
arg_types[ix] = exp->elts[pc + 1 + ix + 1].type;
|
||||||
|
|
||||||
|
expect_type = make_params (nargs, arg_types);
|
||||||
|
*(pos) += 3 + nargs;
|
||||||
|
arg1 = evaluate_subexp_standard (expect_type, exp, pos, noside);
|
||||||
|
xfree (TYPE_FIELDS (expect_type));
|
||||||
|
xfree (TYPE_MAIN_TYPE (expect_type));
|
||||||
|
xfree (expect_type);
|
||||||
|
return arg1;
|
||||||
|
|
||||||
case BINOP_CONCAT:
|
case BINOP_CONCAT:
|
||||||
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
|
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||||
arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
|
arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
|
||||||
|
@ -2612,7 +2651,7 @@ evaluate_subexp_for_address (struct expression *exp, int *pos,
|
||||||
(*pos) += 5 + BYTES_TO_EXP_ELEM (tem + 1);
|
(*pos) += 5 + BYTES_TO_EXP_ELEM (tem + 1);
|
||||||
x = value_aggregate_elt (exp->elts[pc + 1].type,
|
x = value_aggregate_elt (exp->elts[pc + 1].type,
|
||||||
&exp->elts[pc + 3].string,
|
&exp->elts[pc + 3].string,
|
||||||
1, noside);
|
NULL, 1, noside);
|
||||||
if (x == NULL)
|
if (x == NULL)
|
||||||
error (_("There is no field named %s"), &exp->elts[pc + 3].string);
|
error (_("There is no field named %s"), &exp->elts[pc + 3].string);
|
||||||
return x;
|
return x;
|
||||||
|
|
|
@ -88,6 +88,13 @@ enum exp_opcode
|
||||||
when X is a pointer instead of an aggregate. */
|
when X is a pointer instead of an aggregate. */
|
||||||
STRUCTOP_MPTR,
|
STRUCTOP_MPTR,
|
||||||
|
|
||||||
|
/* TYPE_INSTANCE is used when the user specifies a specific
|
||||||
|
type instantiation for overloaded methods/functions.
|
||||||
|
|
||||||
|
The format is:
|
||||||
|
TYPE_INSTANCE num_types type0 ... typeN num_types TYPE_INSTANCE */
|
||||||
|
TYPE_INSTANCE,
|
||||||
|
|
||||||
/* end of C++. */
|
/* end of C++. */
|
||||||
|
|
||||||
/* For Modula-2 integer division DIV */
|
/* For Modula-2 integer division DIV */
|
||||||
|
|
|
@ -837,6 +837,11 @@ operator_length_standard (struct expression *expr, int endpos,
|
||||||
args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
|
args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TYPE_INSTANCE:
|
||||||
|
oplen = 4 + longest_to_int (expr->elts[endpos - 2].longconst);
|
||||||
|
args = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case OP_OBJC_MSGCALL: /* Objective C message (method) call */
|
case OP_OBJC_MSGCALL: /* Objective C message (method) call */
|
||||||
oplen = 4;
|
oplen = 4;
|
||||||
args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
|
args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
|
||||||
|
|
100
gdb/valops.c
100
gdb/valops.c
|
@ -2536,8 +2536,8 @@ check_field (struct type *type, const char *name)
|
||||||
the comment before value_struct_elt_for_reference. */
|
the comment before value_struct_elt_for_reference. */
|
||||||
|
|
||||||
struct value *
|
struct value *
|
||||||
value_aggregate_elt (struct type *curtype,
|
value_aggregate_elt (struct type *curtype, char *name,
|
||||||
char *name, int want_address,
|
struct type *expect_type, int want_address,
|
||||||
enum noside noside)
|
enum noside noside)
|
||||||
{
|
{
|
||||||
switch (TYPE_CODE (curtype))
|
switch (TYPE_CODE (curtype))
|
||||||
|
@ -2545,7 +2545,7 @@ value_aggregate_elt (struct type *curtype,
|
||||||
case TYPE_CODE_STRUCT:
|
case TYPE_CODE_STRUCT:
|
||||||
case TYPE_CODE_UNION:
|
case TYPE_CODE_UNION:
|
||||||
return value_struct_elt_for_reference (curtype, 0, curtype,
|
return value_struct_elt_for_reference (curtype, 0, curtype,
|
||||||
name, NULL,
|
name, expect_type,
|
||||||
want_address, noside);
|
want_address, noside);
|
||||||
case TYPE_CODE_NAMESPACE:
|
case TYPE_CODE_NAMESPACE:
|
||||||
return value_namespace_elt (curtype, name,
|
return value_namespace_elt (curtype, name,
|
||||||
|
@ -2556,6 +2556,57 @@ value_aggregate_elt (struct type *curtype,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compares the two method/function types T1 and T2 for "equality"
|
||||||
|
with respect to the the methods' parameters. If the types of the
|
||||||
|
two parameter lists are the same, returns 1; 0 otherwise. This
|
||||||
|
comparison may ignore any artificial parameters in T1 if
|
||||||
|
SKIP_ARTIFICIAL is non-zero. This function will ALWAYS skip
|
||||||
|
the first artificial parameter in T1, assumed to be a 'this' pointer.
|
||||||
|
|
||||||
|
The type T2 is expected to have come from make_params (in eval.c). */
|
||||||
|
|
||||||
|
static int
|
||||||
|
compare_parameters (struct type *t1, struct type *t2, int skip_artificial)
|
||||||
|
{
|
||||||
|
int start = 0;
|
||||||
|
|
||||||
|
if (TYPE_FIELD_ARTIFICIAL (t1, 0))
|
||||||
|
++start;
|
||||||
|
|
||||||
|
/* If skipping artificial fields, find the first real field
|
||||||
|
in T1. */
|
||||||
|
if (skip_artificial)
|
||||||
|
{
|
||||||
|
while (start < TYPE_NFIELDS (t1)
|
||||||
|
&& TYPE_FIELD_ARTIFICIAL (t1, start))
|
||||||
|
++start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now compare parameters */
|
||||||
|
|
||||||
|
/* Special case: a method taking void. T1 will contain no
|
||||||
|
non-artificial fields, and T2 will contain TYPE_CODE_VOID. */
|
||||||
|
if ((TYPE_NFIELDS (t1) - start) == 0 && TYPE_NFIELDS (t2) == 1
|
||||||
|
&& TYPE_CODE (TYPE_FIELD_TYPE (t2, 0)) == TYPE_CODE_VOID)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if ((TYPE_NFIELDS (t1) - start) == TYPE_NFIELDS (t2))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < TYPE_NFIELDS (t2); ++i)
|
||||||
|
{
|
||||||
|
if (rank_one_type (TYPE_FIELD_TYPE (t1, start + i),
|
||||||
|
TYPE_FIELD_TYPE (t2, i))
|
||||||
|
!= 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* C++: Given an aggregate type CURTYPE, and a member name NAME,
|
/* C++: Given an aggregate type CURTYPE, and a member name NAME,
|
||||||
return the address of this member as a "pointer to member" type.
|
return the address of this member as a "pointer to member" type.
|
||||||
If INTYPE is non-null, then it will be the type of the member we
|
If INTYPE is non-null, then it will be the type of the member we
|
||||||
|
@ -2633,23 +2684,46 @@ value_struct_elt_for_reference (struct type *domain, int offset,
|
||||||
}
|
}
|
||||||
if (t_field_name && strcmp (t_field_name, name) == 0)
|
if (t_field_name && strcmp (t_field_name, name) == 0)
|
||||||
{
|
{
|
||||||
int j = TYPE_FN_FIELDLIST_LENGTH (t, i);
|
int j;
|
||||||
|
int len = TYPE_FN_FIELDLIST_LENGTH (t, i);
|
||||||
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
|
struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
|
||||||
|
|
||||||
check_stub_method_group (t, i);
|
check_stub_method_group (t, i);
|
||||||
|
|
||||||
if (intype == 0 && j > 1)
|
|
||||||
error (_("non-unique member `%s' requires type instantiation"), name);
|
|
||||||
if (intype)
|
if (intype)
|
||||||
{
|
{
|
||||||
while (j--)
|
for (j = 0; j < len; ++j)
|
||||||
if (TYPE_FN_FIELD_TYPE (f, j) == intype)
|
{
|
||||||
break;
|
if (compare_parameters (TYPE_FN_FIELD_TYPE (f, j), intype, 0)
|
||||||
if (j < 0)
|
|| compare_parameters (TYPE_FN_FIELD_TYPE (f, j), intype, 1))
|
||||||
error (_("no member function matches that type instantiation"));
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (j == len)
|
||||||
|
error (_("no member function matches that type instantiation")); }
|
||||||
else
|
else
|
||||||
j = 0;
|
{
|
||||||
|
int ii;
|
||||||
|
/* Skip artificial methods. This is necessary if, for example,
|
||||||
|
the user wants to "print subclass::subclass" with only
|
||||||
|
one user-defined constructor. There is no ambiguity in this
|
||||||
|
case. */
|
||||||
|
for (ii = 0; ii < TYPE_FN_FIELDLIST_LENGTH (t, i);
|
||||||
|
++ii)
|
||||||
|
{
|
||||||
|
if (TYPE_FN_FIELD_ARTIFICIAL (f, ii))
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Desired method is ambiguous if more than one method is
|
||||||
|
defined. */
|
||||||
|
if (len > 1)
|
||||||
|
error (_("non-unique member `%s' requires type instantiation"), name);
|
||||||
|
|
||||||
|
/* This assumes, of course, that all artificial methods appear
|
||||||
|
BEFORE any concrete methods. */
|
||||||
|
j = TYPE_FN_FIELDLIST_LENGTH (t, i) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (TYPE_FN_FIELD_STATIC_P (f, j))
|
if (TYPE_FN_FIELD_STATIC_P (f, j))
|
||||||
{
|
{
|
||||||
|
|
|
@ -436,6 +436,7 @@ extern struct value *value_struct_elt (struct value **argp,
|
||||||
|
|
||||||
extern struct value *value_aggregate_elt (struct type *curtype,
|
extern struct value *value_aggregate_elt (struct type *curtype,
|
||||||
char *name,
|
char *name,
|
||||||
|
struct type *expect_type,
|
||||||
int want_address,
|
int want_address,
|
||||||
enum noside noside);
|
enum noside noside);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue