diff options
Diffstat (limited to 'gdb/valarith.c')
-rw-r--r-- | gdb/valarith.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/gdb/valarith.c b/gdb/valarith.c index c3d537a..cc067cb 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -43,12 +43,50 @@ static struct value *value_subscripted_rvalue (struct value *, struct value *, i void _initialize_valarith (void); +/* Given a pointer, return the size of its target. + If the pointer type is void *, then return 1. + If the target type is incomplete, then error out. + This isn't a general purpose function, but just a + helper for value_sub & value_add. +*/ + +static LONGEST +find_size_for_pointer_math (struct type *ptr_type) +{ + LONGEST sz = -1; + struct type *ptr_target; + + ptr_target = check_typedef (TYPE_TARGET_TYPE (ptr_type)); + + sz = TYPE_LENGTH (ptr_target); + if (sz == 0) + { + if (TYPE_CODE (ptr_type) == TYPE_CODE_VOID) + sz = 1; + else + { + char *name; + + name = TYPE_NAME (ptr_target); + if (name == NULL) + name = TYPE_TAG_NAME (ptr_target); + if (name == NULL) + error ("Cannot perform pointer math on incomplete types, " + "try casting to a known type, or void *."); + else + error ("Cannot perform pointer math on incomplete type \"%s\", " + "try casting to a known type, or void *.", name); + } + } + return sz; +} + struct value * value_add (struct value *arg1, struct value *arg2) { struct value *valint; struct value *valptr; - register int len; + LONGEST sz; struct type *type1, *type2, *valptrtype; COERCE_NUMBER (arg1); @@ -77,12 +115,12 @@ value_add (struct value *arg1, struct value *arg2) valint = arg1; valptrtype = type2; } - len = TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (valptrtype))); - if (len == 0) - len = 1; /* For (void *) */ + + sz = find_size_for_pointer_math (valptrtype); + retval = value_from_pointer (valptrtype, value_as_address (valptr) - + (len * value_as_long (valint))); + + (sz * value_as_long (valint))); VALUE_BFD_SECTION (retval) = VALUE_BFD_SECTION (valptr); return retval; } @@ -104,7 +142,8 @@ value_sub (struct value *arg1, struct value *arg2) if (TYPE_CODE (type2) == TYPE_CODE_INT) { /* pointer - integer. */ - LONGEST sz = TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type1))); + LONGEST sz = find_size_for_pointer_math (type1); + return value_from_pointer (type1, (value_as_address (arg1) - (sz * value_as_long (arg2)))); |