[rfc][08/37] Eliminate builtin_type_ macros: Make pointer arithmetic explicit

uweigand
2008-08-31T17:53:30Z

[-- Attachment #1: diff-type-ptrmath --]
[-- Type: text/plain, Size: 16178 bytes --]

Hello,

this patch removes the functions value_add and value_sub which handle
both integer and pointer arithmetic, and replaces them by functions
value_ptradd, value_ptrsub, and value_ptrdiff that solely take care
of C-style pointer arithmetic. (For integer arithmetic, value_binop
can be used.)

This moves the type to be used for pointer difference operations up
eval.c (this should at some point be replaces by a per-gdbarch
"ptrdiff_t" type). It also makes the subsequent patches to remove
current_gdbarch references from value_binop simpler.

Bye,
Ulrich

ChangeLog:

* value.h (value_add, value_sub): Remove.
(value_ptradd, value_ptrsub, value_ptrdiff): Add prototypes.
* valarith.c (value_add, value_sub): Remove.
(value_ptradd, value_ptrsub, value_ptrdiff): New functions.
(find_size_for_pointer_math): Add assertion. Update comment.
(value_binop): Update comment.

* eval.c (ptrmath_type_p): New function.
(evaluate_subexp_standard): Replace value_add and value_sub
by value_ptradd, value_ptrsub, value_ptrdiff or value_binop.
Use builtin_type_uint8 instead of builtin_type_char to hold
the increment for BINOP_{PRE,POST}{IN,DE}CREMENT operations.
* valarith.c (value_subscript): Replace value_add by
value_ptradd. Replace value_sub by value_binop.
* ada-lang.c (ada_value_ptr_subscript): Likewise.
(ada_tag_name_2): Replace value_add by value_ptradd.
(ada_evaluate_subexp): Replace value_add and value_sub by
value_binop.
* m2-lang.c (evaluate_subexp_modula2): Replace value_add
by value_ptradd.
* gnu-v2-abi.c (gnuv2_virtual_fn_field): Likewise.
* gnu-v3-abi.c (gnuv3_method_ptr_to_value): Likewise.

Index: gdb-head/gdb/ada-lang.c
===================================================================
--- gdb-head.orig/gdb/ada-lang.c
+++ gdb-head/gdb/ada-lang.c
@@ -2371,8 +2371,10 @@ ada_value_ptr_subscript (struct value *a
get_discrete_bounds (TYPE_INDEX_TYPE (type), &lwb, &upb);
idx = value_pos_atr (ind[k]);
if (lwb != 0)
- idx = value_sub (idx, value_from_longest (builtin_type_int, lwb));
- arr = value_add (arr, idx);
+ idx = value_binop (idx, value_from_longest (value_type (idx), lwb),
+ BINOP_SUB);
+
+ arr = value_ptradd (arr, idx);
type = TYPE_TARGET_TYPE (type);
}

@@ -5798,7 +5800,8 @@ ada_tag_name_2 (struct tag_args *args)
valp = value_cast (info_type, args->tag);
if (valp == NULL)
return 0;
- val = value_ind (value_add (valp, value_from_longest (builtin_type_int, -1)));
+ val = value_ind (value_ptradd (valp,
+ value_from_longest (builtin_type_int8, -1)));
if (val == NULL)
return 0;
val = ada_value_struct_elt (val, "expanded_name", 1);
@@ -8518,7 +8521,7 @@ ada_evaluate_subexp (struct type *expect
type = value_type (arg1);
while (TYPE_CODE (type) == TYPE_CODE_REF)
type = TYPE_TARGET_TYPE (type);
- return value_cast (type, value_add (arg1, arg2));
+ return value_cast (type, value_binop (arg1, arg2, BINOP_ADD));

case BINOP_SUB:
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
@@ -8535,7 +8538,7 @@ ada_evaluate_subexp (struct type *expect
type = value_type (arg1);
while (TYPE_CODE (type) == TYPE_CODE_REF)
type = TYPE_TARGET_TYPE (type);
- return value_cast (type, value_sub (arg1, arg2));
+ return value_cast (type, value_binop (arg1, arg2, BINOP_SUB));

case BINOP_MUL:
case BINOP_DIV:
Index: gdb-head/gdb/eval.c
===================================================================
--- gdb-head.orig/gdb/eval.c
+++ gdb-head/gdb/eval.c
@@ -439,6 +439,27 @@ value_f90_subarray (struct value *array,
return value_slice (array, low_bound, high_bound - low_bound + 1);
}

+static int
+ptrmath_type_p (struct type *type)
+{
+ type = check_typedef (type);
+ if (TYPE_CODE (type) == TYPE_CODE_REF)
+ type = TYPE_TARGET_TYPE (type);
+
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_PTR:
+ case TYPE_CODE_FUNC:
+ return 1;
+
+ case TYPE_CODE_ARRAY:
+ return current_language->c_style_arrays;
+
+ default:
+ return 0;
+ }
+}
+
struct value *
evaluate_subexp_standard (struct type *expect_type,
struct expression *exp, int *pos,
@@ -1506,10 +1527,10 @@ evaluate_subexp_standard (struct type *e
op = exp->elts[pc + 1].opcode;
if (binop_user_defined_p (op, arg1, arg2))
return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op, noside);
- else if (op == BINOP_ADD)
- arg2 = value_add (arg1, arg2);
- else if (op == BINOP_SUB)
- arg2 = value_sub (arg1, arg2);
+ else if (op == BINOP_ADD && ptrmath_type_p (value_type (arg1)))
+ arg2 = value_ptradd (arg1, arg2);
+ else if (op == BINOP_SUB && ptrmath_type_p (value_type (arg1)))
+ arg2 = value_ptrsub (arg1, arg2);
else
arg2 = value_binop (arg1, arg2, op);
return value_assign (arg1, arg2);
@@ -1521,8 +1542,12 @@ evaluate_subexp_standard (struct type *e
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ else if (ptrmath_type_p (value_type (arg1)))
+ return value_ptradd (arg1, arg2);
+ else if (ptrmath_type_p (value_type (arg2)))
+ return value_ptradd (arg2, arg1);
else
- return value_add (arg1, arg2);
+ return value_binop (arg1, arg2, BINOP_ADD);

case BINOP_SUB:
arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
@@ -1531,8 +1556,19 @@ evaluate_subexp_standard (struct type *e
goto nosideret;
if (binop_user_defined_p (op, arg1, arg2))
return value_x_binop (arg1, arg2, op, OP_NULL, noside);
+ else if (ptrmath_type_p (value_type (arg1))
+ && ptrmath_type_p (value_type (arg2)))
+ {
+ /* FIXME -- should be ptrdiff_t */
+ type = builtin_type (exp->gdbarch)->builtin_long;
+ return value_from_longest (type, value_ptrdiff (arg1, arg2));
+ }
+ else if (ptrmath_type_p (value_type (arg1)))
+ return value_ptrsub (arg1, arg2);
+ else if (ptrmath_type_p (value_type (arg2)))
+ return value_ptrsub (arg2, arg1);
else
- return value_sub (arg1, arg2);
+ return value_binop (arg1, arg2, BINOP_SUB);

case BINOP_EXP:
case BINOP_MUL:
@@ -2091,8 +2127,12 @@ evaluate_subexp_standard (struct type *e
}
else
{
- arg2 = value_add (arg1, value_from_longest (builtin_type_char,
- (LONGEST) 1));
+ arg2 = value_from_longest (builtin_type_uint8, (LONGEST) 1);
+ if (ptrmath_type_p (value_type (arg1)))
+ arg2 = value_ptradd (arg1, arg2);
+ else
+ arg2 = value_binop (arg1, arg2, BINOP_ADD);
+
return value_assign (arg1, arg2);
}

@@ -2106,8 +2146,12 @@ evaluate_subexp_standard (struct type *e
}
else
{
- arg2 = value_sub (arg1, value_from_longest (builtin_type_char,
- (LONGEST) 1));
+ arg2 = value_from_longest (builtin_type_uint8, (LONGEST) 1);
+ if (ptrmath_type_p (value_type (arg1)))
+ arg2 = value_ptrsub (arg1, arg2);
+ else
+ arg2 = value_binop (arg1, arg2, BINOP_SUB);
+
return value_assign (arg1, arg2);
}

@@ -2121,8 +2165,12 @@ evaluate_subexp_standard (struct type *e
}
else
{
- arg2 = value_add (arg1, value_from_longest (builtin_type_char,
- (LONGEST) 1));
+ arg2 = value_from_longest (builtin_type_uint8, (LONGEST) 1);
+ if (ptrmath_type_p (value_type (arg1)))
+ arg2 = value_ptradd (arg1, arg2);
+ else
+ arg2 = value_binop (arg1, arg2, BINOP_ADD);
+
value_assign (arg1, arg2);
return arg1;
}
@@ -2137,8 +2185,12 @@ evaluate_subexp_standard (struct type *e
}
else
{
- arg2 = value_sub (arg1, value_from_longest (builtin_type_char,
- (LONGEST) 1));
+ arg2 = value_from_longest (builtin_type_uint8, (LONGEST) 1);
+ if (ptrmath_type_p (value_type (arg1)))
+ arg2 = value_ptrsub (arg1, arg2);
+ else
+ arg2 = value_binop (arg1, arg2, BINOP_SUB);
+
value_assign (arg1, arg2);
return arg1;
}
Index: gdb-head/gdb/gnu-v2-abi.c
===================================================================
--- gdb-head.orig/gdb/gnu-v2-abi.c
+++ gdb-head/gdb/gnu-v2-abi.c
@@ -151,7 +151,7 @@ gnuv2_virtual_fn_field (struct value **a
else
{
/* Handle the case where the vtbl field points directly to a structure. */
- vtbl = value_add (vtbl, vi);
+ vtbl = value_ptradd (vtbl, vi);
entry = value_ind (vtbl);
}

Index: gdb-head/gdb/gnu-v3-abi.c
===================================================================
--- gdb-head.orig/gdb/gnu-v3-abi.c
+++ gdb-head/gdb/gnu-v3-abi.c
@@ -662,7 +662,7 @@ gnuv3_method_ptr_to_value (struct value
instance. */
*this_p = value_cast (builtin_type_void_data_ptr, *this_p);
adjval = value_from_longest (builtin_type_long, adjustment);
- *this_p = value_add (*this_p, adjval);
+ *this_p = value_ptradd (*this_p, adjval);
*this_p = value_cast (final_type, *this_p);

if (vbit)
Index: gdb-head/gdb/m2-lang.c
===================================================================
--- gdb-head.orig/gdb/m2-lang.c
+++ gdb-head/gdb/m2-lang.c
@@ -251,7 +251,7 @@ evaluate_subexp_modula2 (struct type *ex
arg1 = value_cast (type, arg1);

type = check_typedef (value_type (arg1));
- return value_ind (value_add (arg1, arg2));
+ return value_ind (value_ptradd (arg1, arg2));
}
else
if (TYPE_CODE (type) != TYPE_CODE_ARRAY)
Index: gdb-head/gdb/valarith.c
===================================================================
--- gdb-head.orig/gdb/valarith.c
+++ gdb-head/gdb/valarith.c
@@ -50,7 +50,7 @@ void _initialize_valarith (void);
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.
+ helper for value_ptrsub & value_ptradd.
*/

static LONGEST
@@ -59,6 +59,7 @@ find_size_for_pointer_math (struct type
LONGEST sz = -1;
struct type *ptr_target;

+ gdb_assert (TYPE_CODE (ptr_type) == TYPE_CODE_PTR);
ptr_target = check_typedef (TYPE_TARGET_TYPE (ptr_type));

sz = TYPE_LENGTH (ptr_target);
@@ -84,90 +85,73 @@ find_size_for_pointer_math (struct type
return sz;
}

+/* Given a pointer ARG1 and an integral value ARG2, return the
+ result of C-style pointer arithmetic ARG1 + ARG2. */
+
struct value *
-value_add (struct value *arg1, struct value *arg2)
+value_ptradd (struct value *arg1, struct value *arg2)
{
- struct value *valint;
- struct value *valptr;
+ struct type *valptrtype;
LONGEST sz;
- struct type *type1, *type2, *valptrtype;

arg1 = coerce_array (arg1);
- arg2 = coerce_array (arg2);
- type1 = check_typedef (value_type (arg1));
- type2 = check_typedef (value_type (arg2));
+ valptrtype = check_typedef (value_type (arg1));
+ sz = find_size_for_pointer_math (valptrtype);

- if ((TYPE_CODE (type1) == TYPE_CODE_PTR
- || TYPE_CODE (type2) == TYPE_CODE_PTR)
- &&
- (is_integral_type (type1) || is_integral_type (type2)))
- /* Exactly one argument is a pointer, and one is an integer. */
- {
- struct value *retval;
-
- if (TYPE_CODE (type1) == TYPE_CODE_PTR)
- {
- valptr = arg1;
- valint = arg2;
- valptrtype = type1;
- }
- else
- {
- valptr = arg2;
- valint = arg1;
- valptrtype = type2;
- }
+ if (!is_integral_type (value_type (arg2)))
+ error (_("Argument to arithmetic operation not a number or boolean."));
+
+ return value_from_pointer (valptrtype,
+ value_as_address (arg1)
+ + (sz * value_as_long (arg2)));
+}

- sz = find_size_for_pointer_math (valptrtype);
+/* Given a pointer ARG1 and an integral value ARG2, return the
+ result of C-style pointer arithmetic ARG1 - ARG2. */

- retval = value_from_pointer (valptrtype,
- value_as_address (valptr)
- + (sz * value_as_long (valint)));
- return retval;
- }
+struct value *
+value_ptrsub (struct value *arg1, struct value *arg2)
+{
+ struct type *valptrtype;
+ LONGEST sz;

- return value_binop (arg1, arg2, BINOP_ADD);
+ arg1 = coerce_array (arg1);
+ valptrtype = check_typedef (value_type (arg1));
+ sz = find_size_for_pointer_math (valptrtype);
+
+ if (!is_integral_type (value_type (arg2)))
+ error (_("Argument to arithmetic operation not a number or boolean."));
+
+ return value_from_pointer (valptrtype,
+ value_as_address (arg1)
+ - (sz * value_as_long (arg2)));
}

-struct value *
-value_sub (struct value *arg1, struct value *arg2)
+/* Given two compatible pointer values ARG1 and ARG2, return the
+ result of C-style pointer arithmetic ARG1 - ARG2. */
+
+LONGEST
+value_ptrdiff (struct value *arg1, struct value *arg2)
{
struct type *type1, *type2;
+ LONGEST sz;
+
arg1 = coerce_array (arg1);
arg2 = coerce_array (arg2);
type1 = check_typedef (value_type (arg1));
type2 = check_typedef (value_type (arg2));

- if (TYPE_CODE (type1) == TYPE_CODE_PTR)
- {
- if (is_integral_type (type2))
- {
- /* pointer - integer. */
- LONGEST sz = find_size_for_pointer_math (type1);
+ gdb_assert (TYPE_CODE (type1) == TYPE_CODE_PTR);
+ gdb_assert (TYPE_CODE (type2) == TYPE_CODE_PTR);

- return value_from_pointer (type1,
- (value_as_address (arg1)
- - (sz * value_as_long (arg2))));
- }
- else if (TYPE_CODE (type2) == TYPE_CODE_PTR
- && TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type1)))
- == TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type2))))
- {
- /* pointer to <type x> - pointer to <type x>. */
- LONGEST sz = TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type1)));
- return value_from_longest
- (builtin_type_long, /* FIXME -- should be ptrdiff_t */
- (value_as_long (arg1) - value_as_long (arg2)) / sz);
- }
- else
- {
- error (_("\
+ if (TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type1)))
+ != TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type2))))
+ error (_("\
First argument of `-' is a pointer and second argument is neither\n\
an integer nor a pointer of the same type."));
- }
- }

- return value_binop (arg1, arg2, BINOP_SUB);
+ sz = TYPE_LENGTH (check_typedef (TYPE_TARGET_TYPE (type1)));
+ return (value_as_long (arg1) - value_as_long (arg2)) / sz;
}

/* Return the value of ARRAY[IDX].
@@ -211,15 +195,15 @@ value_subscript (struct value *array, st

if (lowerbound != 0)
{
- bound = value_from_longest (builtin_type_int, (LONGEST) lowerbound);
- idx = value_sub (idx, bound);
+ bound = value_from_longest (value_type (idx), (LONGEST) lowerbound);
+ idx = value_binop (idx, bound, BINOP_SUB);
}

array = value_coerce_array (array);
}

if (c_style)
- return value_ind (value_add (array, idx));
+ return value_ind (value_ptradd (array, idx));
else
error (_("not an array or string"));
}
@@ -1171,7 +1155,7 @@ value_args_as_decimal (struct value *arg
representations as integers or floats. This includes booleans,
characters, integers, or floats.
Does not support addition and subtraction on pointers;
- use value_add or value_sub if you want to handle those possibilities. */
+ use value_ptradd, value_ptrsub or value_ptrdiff for those operations. */

struct value *
value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
Index: gdb-head/gdb/value.h
===================================================================
--- gdb-head.orig/gdb/value.h
+++ gdb-head/gdb/value.h
@@ -331,9 +331,11 @@ extern struct value *value_concat (struc
extern struct value *value_binop (struct value *arg1, struct value *arg2,
enum exp_opcode op);

-extern struct value *value_add (struct value *arg1, struct value *arg2);
+extern struct value *value_ptradd (struct value *arg1, struct value *arg2);

-extern struct value *value_sub (struct value *arg1, struct value *arg2);
+extern struct value *value_ptrsub (struct value *arg1, struct value *arg2);
+
+extern LONGEST value_ptrdiff (struct value *arg1, struct value *arg2);

extern int value_must_coerce_to_target (struct value *arg1);