forked from Imagelibrary/binutils-gdb
* 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:
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. */
|
||||
|
||||
struct value *
|
||||
value_aggregate_elt (struct type *curtype,
|
||||
char *name, int want_address,
|
||||
value_aggregate_elt (struct type *curtype, char *name,
|
||||
struct type *expect_type, int want_address,
|
||||
enum noside noside)
|
||||
{
|
||||
switch (TYPE_CODE (curtype))
|
||||
@@ -2545,7 +2545,7 @@ value_aggregate_elt (struct type *curtype,
|
||||
case TYPE_CODE_STRUCT:
|
||||
case TYPE_CODE_UNION:
|
||||
return value_struct_elt_for_reference (curtype, 0, curtype,
|
||||
name, NULL,
|
||||
name, expect_type,
|
||||
want_address, noside);
|
||||
case TYPE_CODE_NAMESPACE:
|
||||
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,
|
||||
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
|
||||
@@ -2633,23 +2684,46 @@ value_struct_elt_for_reference (struct type *domain, int offset,
|
||||
}
|
||||
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);
|
||||
|
||||
check_stub_method_group (t, i);
|
||||
|
||||
if (intype == 0 && j > 1)
|
||||
error (_("non-unique member `%s' requires type instantiation"), name);
|
||||
if (intype)
|
||||
{
|
||||
while (j--)
|
||||
if (TYPE_FN_FIELD_TYPE (f, j) == intype)
|
||||
break;
|
||||
if (j < 0)
|
||||
error (_("no member function matches that type instantiation"));
|
||||
}
|
||||
for (j = 0; j < len; ++j)
|
||||
{
|
||||
if (compare_parameters (TYPE_FN_FIELD_TYPE (f, j), intype, 0)
|
||||
|| compare_parameters (TYPE_FN_FIELD_TYPE (f, j), intype, 1))
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == len)
|
||||
error (_("no member function matches that type instantiation")); }
|
||||
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))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user