aboutsummaryrefslogtreecommitdiff
path: root/gdb/valops.c
diff options
context:
space:
mode:
authorKeith Seitz <keiths@redhat.com>2009-11-10 22:17:58 +0000
committerKeith Seitz <keiths@redhat.com>2009-11-10 22:17:58 +0000
commit072bba3b0f3e2ee8d2cfc94e256d0f0ebc627afc (patch)
tree85866ec9e0e9094885d8fd85f03e0bb96bbab06c /gdb/valops.c
parent85feb311d32bf996c4da799a89be375b31d1b3e7 (diff)
downloadgdb-072bba3b0f3e2ee8d2cfc94e256d0f0ebc627afc.zip
gdb-072bba3b0f3e2ee8d2cfc94e256d0f0ebc627afc.tar.gz
gdb-072bba3b0f3e2ee8d2cfc94e256d0f0ebc627afc.tar.bz2
* 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.
Diffstat (limited to 'gdb/valops.c')
-rw-r--r--gdb/valops.c100
1 files changed, 87 insertions, 13 deletions
diff --git a/gdb/valops.c b/gdb/valops.c
index 012ea6a..2771688 100644
--- a/gdb/valops.c
+++ b/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))
{