Index: gdb/valops.c |
diff --git a/gdb/valops.c b/gdb/valops.c |
index 5453b1ae8988b3f3d8c552a6279179dcf75fd7d5..97d889b2bcf14e5504e2d75d783faef9712f4714 100644 |
--- a/gdb/valops.c |
+++ b/gdb/valops.c |
@@ -301,10 +301,14 @@ value_cast_structs (struct type *type, struct value *v2) |
/* Cast one pointer or reference type to another. Both TYPE and |
the type of ARG2 should be pointer types, or else both should be |
- reference types. Returns the new pointer or reference. */ |
+ reference types. If SUBCLASS_CHECK is non-zero, this will force a |
+ check to see whether TYPE is a superclass of ARG2's type. If |
+ SUBCLASS_CHECK is zero, then the subclass check is done only when |
+ ARG2 is itself non-zero. Returns the new pointer or reference. */ |
struct value * |
-value_cast_pointers (struct type *type, struct value *arg2) |
+value_cast_pointers (struct type *type, struct value *arg2, |
+ int subclass_check) |
{ |
struct type *type1 = check_typedef (type); |
struct type *type2 = check_typedef (value_type (arg2)); |
@@ -313,7 +317,7 @@ value_cast_pointers (struct type *type, struct value *arg2) |
if (TYPE_CODE (t1) == TYPE_CODE_STRUCT |
&& TYPE_CODE (t2) == TYPE_CODE_STRUCT |
- && !value_logical_not (arg2)) |
+ && (subclass_check || !value_logical_not (arg2))) |
{ |
struct value *v2; |
@@ -568,7 +572,7 @@ value_cast (struct type *type, struct value *arg2) |
else if (TYPE_LENGTH (type) == TYPE_LENGTH (type2)) |
{ |
if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR) |
- return value_cast_pointers (type, arg2); |
+ return value_cast_pointers (type, arg2, 0); |
arg2 = value_copy (arg2); |
deprecated_set_value_type (arg2, type); |
@@ -1295,9 +1299,7 @@ value_assign (struct value *toval, struct value *fromval) |
dest_buffer = value_contents (fromval); |
} |
- write_memory (changed_addr, dest_buffer, changed_len); |
- observer_notify_memory_changed (changed_addr, changed_len, |
- dest_buffer); |
+ write_memory_with_notification (changed_addr, dest_buffer, changed_len); |
} |
break; |
@@ -1772,15 +1774,7 @@ value_ind (struct value *arg1) |
(value_as_address (arg1) |
- value_pointed_to_offset (arg1))); |
- /* Re-adjust type. */ |
- deprecated_set_value_type (arg2, TYPE_TARGET_TYPE (base_type)); |
- /* Add embedding info. */ |
- set_value_enclosing_type (arg2, enc_type); |
- set_value_embedded_offset (arg2, value_pointed_to_offset (arg1)); |
- |
- /* We may be pointing to an object of some derived type. */ |
- arg2 = value_full_object (arg2, NULL, 0, 0, 0); |
- return arg2; |
+ return readjust_indirect_value_type (arg2, enc_type, base_type, arg1); |
} |
error (_("Attempt to take contents of a non-pointer value.")); |
@@ -1984,17 +1978,41 @@ typecmp (int staticp, int varargs, int nargs, |
return i + 1; |
} |
-/* Helper function used by value_struct_elt to recurse through |
- baseclasses. Look for a field NAME in ARG1. Adjust the address of |
- ARG1 by OFFSET bytes, and search in it assuming it has (class) type |
- TYPE. If found, return value, else return NULL. |
+/* Helper class for do_search_struct_field that updates *RESULT_PTR |
+ and *LAST_BOFFSET, and possibly throws an exception if the field |
+ search has yielded ambiguous results. */ |
- If LOOKING_FOR_BASECLASS, then instead of looking for struct |
- fields, look for a baseclass named NAME. */ |
+static void |
+update_search_result (struct value **result_ptr, struct value *v, |
+ int *last_boffset, int boffset, |
+ const char *name, struct type *type) |
+{ |
+ if (v != NULL) |
+ { |
+ if (*result_ptr != NULL |
+ /* The result is not ambiguous if all the classes that are |
+ found occupy the same space. */ |
+ && *last_boffset != boffset) |
+ error (_("base class '%s' is ambiguous in type '%s'"), |
+ name, TYPE_SAFE_NAME (type)); |
+ *result_ptr = v; |
+ *last_boffset = boffset; |
+ } |
+} |
-static struct value * |
-search_struct_field (const char *name, struct value *arg1, int offset, |
- struct type *type, int looking_for_baseclass) |
+/* A helper for search_struct_field. This does all the work; most |
+ arguments are as passed to search_struct_field. The result is |
+ stored in *RESULT_PTR, which must be initialized to NULL. |
+ OUTERMOST_TYPE is the type of the initial type passed to |
+ search_struct_field; this is used for error reporting when the |
+ lookup is ambiguous. */ |
+ |
+static void |
+do_search_struct_field (const char *name, struct value *arg1, int offset, |
+ struct type *type, int looking_for_baseclass, |
+ struct value **result_ptr, |
+ int *last_boffset, |
+ struct type *outermost_type) |
{ |
int i; |
int nbases; |
@@ -2005,7 +2023,7 @@ search_struct_field (const char *name, struct value *arg1, int offset, |
if (!looking_for_baseclass) |
for (i = TYPE_NFIELDS (type) - 1; i >= nbases; i--) |
{ |
- char *t_field_name = TYPE_FIELD_NAME (type, i); |
+ const char *t_field_name = TYPE_FIELD_NAME (type, i); |
if (t_field_name && (strcmp_iw (t_field_name, name) == 0)) |
{ |
@@ -2020,12 +2038,9 @@ search_struct_field (const char *name, struct value *arg1, int offset, |
name); |
} |
else |
- { |
- v = value_primitive_field (arg1, offset, i, type); |
- if (v == 0) |
- error (_("there is no field named %s"), name); |
- } |
- return v; |
+ v = value_primitive_field (arg1, offset, i, type); |
+ *result_ptr = v; |
+ return; |
} |
if (t_field_name |
@@ -2050,7 +2065,7 @@ search_struct_field (const char *name, struct value *arg1, int offset, |
represented as a struct, with a member for each |
<variant field>. */ |
- struct value *v; |
+ struct value *v = NULL; |
int new_offset = offset; |
/* This is pretty gross. In G++, the offset in an |
@@ -2064,18 +2079,23 @@ search_struct_field (const char *name, struct value *arg1, int offset, |
&& TYPE_FIELD_BITPOS (field_type, 0) == 0)) |
new_offset += TYPE_FIELD_BITPOS (type, i) / 8; |
- v = search_struct_field (name, arg1, new_offset, |
- field_type, |
- looking_for_baseclass); |
+ do_search_struct_field (name, arg1, new_offset, |
+ field_type, |
+ looking_for_baseclass, &v, |
+ last_boffset, |
+ outermost_type); |
if (v) |
- return v; |
+ { |
+ *result_ptr = v; |
+ return; |
+ } |
} |
} |
} |
for (i = 0; i < nbases; i++) |
{ |
- struct value *v; |
+ struct value *v = NULL; |
struct type *basetype = check_typedef (TYPE_BASECLASS (type, i)); |
/* If we are looking for baseclasses, this is what we get when |
we hit them. But it could happen that the base part's member |
@@ -2085,10 +2105,10 @@ search_struct_field (const char *name, struct value *arg1, int offset, |
&& (strcmp_iw (name, |
TYPE_BASECLASS_NAME (type, |
i)) == 0)); |
+ int boffset = value_embedded_offset (arg1) + offset; |
if (BASETYPE_VIA_VIRTUAL (type, i)) |
{ |
- int boffset; |
struct value *v2; |
boffset = baseclass_offset (type, i, |
@@ -2124,22 +2144,51 @@ search_struct_field (const char *name, struct value *arg1, int offset, |
} |
if (found_baseclass) |
- return v2; |
- v = search_struct_field (name, v2, 0, |
- TYPE_BASECLASS (type, i), |
- looking_for_baseclass); |
+ v = v2; |
+ else |
+ { |
+ do_search_struct_field (name, v2, 0, |
+ TYPE_BASECLASS (type, i), |
+ looking_for_baseclass, |
+ result_ptr, last_boffset, |
+ outermost_type); |
+ } |
} |
else if (found_baseclass) |
v = value_primitive_field (arg1, offset, i, type); |
else |
- v = search_struct_field (name, arg1, |
- offset + TYPE_BASECLASS_BITPOS (type, |
- i) / 8, |
- basetype, looking_for_baseclass); |
- if (v) |
- return v; |
+ { |
+ do_search_struct_field (name, arg1, |
+ offset + TYPE_BASECLASS_BITPOS (type, |
+ i) / 8, |
+ basetype, looking_for_baseclass, |
+ result_ptr, last_boffset, |
+ outermost_type); |
+ } |
+ |
+ update_search_result (result_ptr, v, last_boffset, |
+ boffset, name, outermost_type); |
} |
- return NULL; |
+} |
+ |
+/* Helper function used by value_struct_elt to recurse through |
+ baseclasses. Look for a field NAME in ARG1. Adjust the address of |
+ ARG1 by OFFSET bytes, and search in it assuming it has (class) type |
+ TYPE. If found, return value, else return NULL. |
+ |
+ If LOOKING_FOR_BASECLASS, then instead of looking for struct |
+ fields, look for a baseclass named NAME. */ |
+ |
+static struct value * |
+search_struct_field (const char *name, struct value *arg1, int offset, |
+ struct type *type, int looking_for_baseclass) |
+{ |
+ struct value *result = NULL; |
+ int boffset = 0; |
+ |
+ do_search_struct_field (name, arg1, offset, type, looking_for_baseclass, |
+ &result, &boffset, type); |
+ return result; |
} |
/* Helper function used by value_struct_elt to recurse through |
@@ -2163,7 +2212,7 @@ search_struct_method (const char *name, struct value **arg1p, |
CHECK_TYPEDEF (type); |
for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--) |
{ |
- char *t_field_name = TYPE_FN_FIELDLIST_NAME (type, i); |
+ const char *t_field_name = TYPE_FN_FIELDLIST_NAME (type, i); |
/* FIXME! May need to check for ARM demangling here. */ |
if (strncmp (t_field_name, "__", 2) == 0 || |
@@ -2407,7 +2456,7 @@ find_method_list (struct value **argp, const char *method, |
for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--) |
{ |
/* pai: FIXME What about operators and type conversions? */ |
- char *fn_field_name = TYPE_FN_FIELDLIST_NAME (type, i); |
+ const char *fn_field_name = TYPE_FN_FIELDLIST_NAME (type, i); |
if (fn_field_name && (strcmp_iw (fn_field_name, method) == 0)) |
{ |
@@ -2461,7 +2510,7 @@ find_method_list (struct value **argp, const char *method, |
method. |
BOFFSET is the offset of the base subobject which defines the method. */ |
-struct fn_field * |
+static struct fn_field * |
value_find_oload_method_list (struct value **argp, const char *method, |
int offset, int *num_fns, |
struct type **basetype, int *boffset) |
@@ -2630,8 +2679,7 @@ find_overload_match (struct value **args, int nargs, |
and non member function, the first argument must now be |
dereferenced. */ |
if (method == BOTH) |
- deprecated_set_value_type (args[0], |
- TYPE_TARGET_TYPE (value_type (args[0]))); |
+ args[0] = value_ind (args[0]); |
if (fsym) |
{ |
@@ -3154,7 +3202,7 @@ check_field (struct type *type, const char *name) |
for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--) |
{ |
- char *t_field_name = TYPE_FIELD_NAME (type, i); |
+ const char *t_field_name = TYPE_FIELD_NAME (type, i); |
if (t_field_name && (strcmp_iw (t_field_name, name) == 0)) |
return 1; |
@@ -3280,7 +3328,7 @@ value_struct_elt_for_reference (struct type *domain, int offset, |
for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--) |
{ |
- char *t_field_name = TYPE_FIELD_NAME (t, i); |
+ const char *t_field_name = TYPE_FIELD_NAME (t, i); |
if (t_field_name && strcmp (t_field_name, name) == 0) |
{ |
@@ -3317,7 +3365,7 @@ value_struct_elt_for_reference (struct type *domain, int offset, |
for (i = TYPE_NFN_FIELDS (t) - 1; i >= 0; --i) |
{ |
- char *t_field_name = TYPE_FN_FIELDLIST_NAME (t, i); |
+ const char *t_field_name = TYPE_FN_FIELDLIST_NAME (t, i); |
char dem_opname[64]; |
if (strncmp (t_field_name, "__", 2) == 0 |
@@ -3526,21 +3574,48 @@ value_maybe_namespace_elt (const struct type *curtype, |
return result; |
} |
-/* Given a pointer value V, find the real (RTTI) type of the object it |
- points to. |
+/* Given a pointer or a reference value V, find its real (RTTI) type. |
Other parameters FULL, TOP, USING_ENC as with value_rtti_type() |
and refer to the values computed for the object pointed to. */ |
struct type * |
-value_rtti_target_type (struct value *v, int *full, |
- int *top, int *using_enc) |
+value_rtti_indirect_type (struct value *v, int *full, |
+ int *top, int *using_enc) |
{ |
struct value *target; |
+ struct type *type, *real_type, *target_type; |
- target = value_ind (v); |
+ type = value_type (v); |
+ type = check_typedef (type); |
+ if (TYPE_CODE (type) == TYPE_CODE_REF) |
+ target = coerce_ref (v); |
+ else if (TYPE_CODE (type) == TYPE_CODE_PTR) |
+ target = value_ind (v); |
+ else |
+ return NULL; |
+ |
+ real_type = value_rtti_type (target, full, top, using_enc); |
+ |
+ if (real_type) |
+ { |
+ /* Copy qualifiers to the referenced object. */ |
+ target_type = value_type (target); |
+ real_type = make_cv_type (TYPE_CONST (target_type), |
+ TYPE_VOLATILE (target_type), real_type, NULL); |
+ if (TYPE_CODE (type) == TYPE_CODE_REF) |
+ real_type = lookup_reference_type (real_type); |
+ else if (TYPE_CODE (type) == TYPE_CODE_PTR) |
+ real_type = lookup_pointer_type (real_type); |
+ else |
+ internal_error (__FILE__, __LINE__, _("Unexpected value type.")); |
+ |
+ /* Copy qualifiers to the pointer/reference. */ |
+ real_type = make_cv_type (TYPE_CONST (type), TYPE_VOLATILE (type), |
+ real_type, NULL); |
+ } |
- return value_rtti_type (target, full, top, using_enc); |
+ return real_type; |
} |
/* Given a value pointed to by ARGP, check its real run-time type, and |