diff options
Diffstat (limited to 'contrib/gdb/gdb/valarith.c')
-rw-r--r-- | contrib/gdb/gdb/valarith.c | 102 |
1 files changed, 66 insertions, 36 deletions
diff --git a/contrib/gdb/gdb/valarith.c b/contrib/gdb/gdb/valarith.c index 5852ac6..03282ea 100644 --- a/contrib/gdb/gdb/valarith.c +++ b/contrib/gdb/gdb/valarith.c @@ -1,7 +1,8 @@ /* Perform arithmetic and other operations on values, for GDB. + Copyright 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002 - Free Software Foundation, Inc. + 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software + Foundation, Inc. This file is part of GDB. @@ -30,6 +31,7 @@ #include "gdb_string.h" #include "doublest.h" #include <math.h> +#include "infcall.h" /* Define whether or not the C operator '/' truncates towards zero for differently signed operands (truncation direction is undefined in C). */ @@ -43,12 +45,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 +117,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 +144,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)))); @@ -236,6 +277,7 @@ value_subscripted_rvalue (struct value *array, struct value *idx, int lowerbound else VALUE_LVAL (v) = VALUE_LVAL (array); VALUE_ADDRESS (v) = VALUE_ADDRESS (array); + VALUE_REGNO (v) = VALUE_REGNO (array); VALUE_OFFSET (v) = VALUE_OFFSET (array) + elt_offs; return v; } @@ -759,7 +801,7 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) case BINOP_EXP: v = pow (v1, v2); if (errno) - error ("Cannot perform exponentiation: %s", strerror (errno)); + error ("Cannot perform exponentiation: %s", safe_strerror (errno)); break; default: @@ -820,7 +862,7 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) /* Integral operations here. */ /* FIXME: Also mixed integral/booleans, with result an integer. */ /* FIXME: This implements ANSI C rules (also correct for C++). - What about FORTRAN and chill? */ + What about FORTRAN and (the deleted) chill ? */ { unsigned int promoted_len1 = TYPE_LENGTH (type1); unsigned int promoted_len2 = TYPE_LENGTH (type2); @@ -897,7 +939,7 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) case BINOP_EXP: v = pow (v1, v2); if (errno) - error ("Cannot perform exponentiation: %s", strerror (errno)); + error ("Cannot perform exponentiation: %s", safe_strerror (errno)); break; case BINOP_REM: @@ -907,12 +949,6 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) case BINOP_MOD: /* Knuth 1.2.4, integer only. Note that unlike the C '%' op, v1 mod 0 has a defined value, v1. */ - /* Chill specifies that v2 must be > 0, so check for that. */ - if (current_language->la_language == language_chill - && value_as_long (arg2) <= 0) - { - error ("Second operand of MOD must be greater than zero."); - } if (v2 == 0) { v = v1; @@ -1021,7 +1057,7 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) case BINOP_EXP: v = pow (v1, v2); if (errno) - error ("Cannot perform exponentiation: %s", strerror (errno)); + error ("Cannot perform exponentiation: %s", safe_strerror (errno)); break; case BINOP_REM: @@ -1031,12 +1067,6 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) case BINOP_MOD: /* Knuth 1.2.4, integer only. Note that unlike the C '%' op, X mod 0 has a defined value, X. */ - /* Chill specifies that v2 must be > 0, so check for that. */ - if (current_language->la_language == language_chill - && v2 <= 0) - { - error ("Second operand of MOD must be greater than zero."); - } if (v2 == 0) { v = v1; @@ -1128,8 +1158,8 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) int value_logical_not (struct value *arg1) { - register int len; - register char *p; + int len; + char *p; struct type *type1; COERCE_NUMBER (arg1); @@ -1186,8 +1216,8 @@ value_strcmp (struct value *arg1, struct value *arg2) int value_equal (struct value *arg1, struct value *arg2) { - register int len; - register char *p1, *p2; + int len; + char *p1, *p2; struct type *type1, *type2; enum type_code code1; enum type_code code2; @@ -1245,8 +1275,8 @@ value_equal (struct value *arg1, struct value *arg2) int value_less (struct value *arg1, struct value *arg2) { - register enum type_code code1; - register enum type_code code2; + enum type_code code1; + enum type_code code2; struct type *type1, *type2; COERCE_NUMBER (arg1); @@ -1287,8 +1317,8 @@ value_less (struct value *arg1, struct value *arg2) struct value * value_neg (struct value *arg1) { - register struct type *type; - register struct type *result_type = VALUE_TYPE (arg1); + struct type *type; + struct type *result_type = VALUE_TYPE (arg1); COERCE_REF (arg1); COERCE_ENUM (arg1); @@ -1299,8 +1329,8 @@ value_neg (struct value *arg1) return value_from_double (result_type, -value_as_double (arg1)); else if (TYPE_CODE (type) == TYPE_CODE_INT || TYPE_CODE (type) == TYPE_CODE_BOOL) { - /* Perform integral promotion for ANSI C/C++. - FIXME: What about FORTRAN and chill ? */ + /* Perform integral promotion for ANSI C/C++. FIXME: What about + FORTRAN and (the deleted) chill ? */ if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int)) result_type = builtin_type_int; @@ -1316,8 +1346,8 @@ value_neg (struct value *arg1) struct value * value_complement (struct value *arg1) { - register struct type *type; - register struct type *result_type = VALUE_TYPE (arg1); + struct type *type; + struct type *result_type = VALUE_TYPE (arg1); int typecode; COERCE_REF (arg1); |