[RFA] BINOP_DIV and ptyp command

Doug Evans
2008-01-30T03:32:13Z

Daniel Jacobowitz wrote:
> That's not a value-dependent error. 1 / 0 has a sensible type (it's
> an int), but no sensible value; 1 >> 3.0 has no sensible type (it's a
> syntax error).
>
> I think of it this way:
>
> drow@caradoc:~% cat a.c
> int a = sizeof (1/0);
> int b = sizeof (1 >> 3.0);
> drow@caradoc:~% gcc -Wall -c a.c
> a.c:2: error: invalid operands to binary >>

True.

As an exercise I wrote a patch that added hooks to language_defn
to compute the result type. I'll append that patch separately.
It's a bit excessive, though there is value in using the language vector.
There's also value in localizing the changes to valarith.c.
Tell me what you want and I'll rework the patch as necessary.

Below is the patch I'm submitting for review/approval.
It moves the result type computation to another function
and fixes the result type for c-like languages.
This patch also handles "whatis 1/0" by watching for zero and
converting it to one. [I realize the INTDIV eval.c patch touches
this part of the code - I can wait until the INTDIV patch goes in
and update this one before checking in.]

2008-01-29 Doug Evans <dje@google.com>

Fix argument promotion for binary arithmetic ops for C.
* valarith.c (unop_result_type): New fn.
(binop_result_type): New fn.
(value_binop): Move result type computation to binop_result_type.
(value_pos, value_neg, value_complement): Move result type
computation to unop_result_type.

* eval.c (evaluate_subexp_standard): Fix type of result of mixed
integer/float division operations when EVAL_AVOID_SIDE_EFFECTS.
* valops.c (value_one): New function.
* value.h (value_one): Declare.

* gdb.base/whatis-exp.exp: Fix expected result of whatis x+y, x-y,
x*y, x/y, x%y.

Index: eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.77
diff -u -p -r1.77 eval.c
--- eval.c 18 Jan 2008 17:07:39 -0000 1.77
+++ eval.c 30 Jan 2008 02:14:59 -0000
@@ -1509,11 +1509,20 @@ 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 (noside == EVAL_AVOID_SIDE_EFFECTS
- && (op == BINOP_DIV || op == BINOP_REM || op == BINOP_MOD))
- return value_zero (value_type (arg1), not_lval);
else
- return value_binop (arg1, arg2, op);
+ {
+ /* If EVAL_AVOID_SIDE_EFFECTS and we're dividing by zero,
+ fudge arg2 to avoid division-by-zero, the caller is
+ (theoretically) only looking for the type of the result. */
+ if (noside == EVAL_AVOID_SIDE_EFFECTS
+ /* ??? Do we really want to test for BINOP_MOD here?
+ The implementation of value_binop gives it a well-defined
+ value. */
+ && (op == BINOP_DIV || op == BINOP_REM || op == BINOP_MOD)
+ && value_logical_not (arg2))
+ arg2 = value_one (value_type (arg2), not_lval);
+ return value_binop (arg1, arg2, op);
+ }

case BINOP_RANGE:
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
Index: valarith.c
===================================================================
RCS file: /cvs/src/src/gdb/valarith.c,v
retrieving revision 1.55
diff -u -p -r1.55 valarith.c
--- valarith.c 29 Jan 2008 14:24:43 -0000 1.55
+++ valarith.c 30 Jan 2008 02:15:00 -0000
@@ -40,6 +40,9 @@
#endif

static struct value *value_subscripted_rvalue (struct value *, struct value *, int);
+static struct type *unop_result_type (enum exp_opcode op, struct type *type1);
+static struct type *binop_result_type (enum exp_opcode op, struct type *type1,
+ struct type *type2);

void _initialize_valarith (void);
\f
@@ -742,6 +745,277 @@ value_concat (struct value *arg1, struct
return (outval);
}
\f
+/* Return type of OP performed on TYPE1.
+ The result type follows ANSI C rules.
+ If the result is not appropropriate for any particular language then it
+ needs to patch this function to return the correct type. */
+
+static struct type *
+unop_result_type (enum exp_opcode op, struct type *type1)
+{
+ struct type *result_type;
+
+ type1 = check_typedef (type1);
+ result_type = type1;
+
+ switch (op)
+ {
+ case UNOP_PLUS:
+ case UNOP_NEG:
+ break;
+ case UNOP_COMPLEMENT:
+ /* Reject floats and decimal floats. */
+ if (!is_integral_type (type1))
+ error (_("Argument to complement operation not an integer or boolean."));
+ break;
+ default:
+ error (_("Invalid unary operation on numbers."));
+ }
+
+ if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT
+ || TYPE_CODE (type1) == TYPE_CODE_FLT)
+ {
+ return result_type;
+ }
+ else if (is_integral_type (type1))
+ {
+ /* Perform integral promotion for ANSI C/C++.
+ If not appropropriate for any particular language it needs to
+ supply its own la_unop_result_type function. */
+ if (TYPE_LENGTH (type1) < TYPE_LENGTH (builtin_type_int))
+ result_type = builtin_type_int;
+
+ return result_type;
+ }
+ else
+ {
+ error (_("Argument to unary operation not a number."));
+ return 0; /* For lint -- never reached */
+ }
+}
+
+/* Return type of OP performed on TYPE1, TYPE2.
+ For C-like languages the result follows ANSI C.
+ For other languages the result type is unchanged from 6.6 for backward
+ compatibility.
+ If the result is not appropropriate for any particular language then it
+ needs to patch this function to return the correct type. */
+
+static struct type *
+binop_result_type (enum exp_opcode op, struct type *type1, struct type *type2)
+{
+ type1 = check_typedef (type1);
+ type2 = check_typedef (type2);
+
+ if ((TYPE_CODE (type1) != TYPE_CODE_FLT
+ && TYPE_CODE (type1) != TYPE_CODE_DECFLOAT
+ && !is_integral_type (type1))
+ ||
+ (TYPE_CODE (type2) != TYPE_CODE_FLT
+ && TYPE_CODE (type2) != TYPE_CODE_DECFLOAT
+ && !is_integral_type (type2)))
+ error (_("Argument to arithmetic operation not a number or boolean."));
+
+ if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT
+ || TYPE_CODE (type2) == TYPE_CODE_DECFLOAT)
+ {
+ struct type *result_type;
+
+ switch (op)
+ {
+ case BINOP_ADD:
+ case BINOP_SUB:
+ case BINOP_MUL:
+ case BINOP_DIV:
+ case BINOP_EXP:
+ break;
+ default:
+ error (_("Operation not valid for decimal floating point number."));
+ }
+
+ if (TYPE_CODE (type1) != TYPE_CODE_DECFLOAT)
+ /* If type1 is not a decimal float, the type of the result is the type
+ of the decimal float argument, type2. */
+ result_type = type2;
+ else if (TYPE_CODE (type2) != TYPE_CODE_DECFLOAT)
+ /* Same logic, for the case where type2 is not a decimal float. */
+ result_type = type1;
+ else
+ /* Both are decimal floats, the type of the result is the bigger
+ of the two. */
+ result_type =
+ (TYPE_LENGTH (type1) > TYPE_LENGTH (type2)) ? type1 : type2;
+
+ return result_type;
+ }
+ else if (TYPE_CODE (type1) == TYPE_CODE_FLT
+ || TYPE_CODE (type2) == TYPE_CODE_FLT)
+ {
+ struct type *result_type;
+
+ switch (op)
+ {
+ case BINOP_ADD:
+ case BINOP_SUB:
+ case BINOP_MUL:
+ case BINOP_DIV:
+ case BINOP_EXP:
+ break;
+ default:
+ error (_("Integer-only operation on floating point number."));
+ }
+
+ /* If either arg was long double, make sure that value is also long
+ double. */
+
+ if (TYPE_LENGTH (type1) * 8 > gdbarch_double_bit (current_gdbarch)
+ || TYPE_LENGTH (type2) * 8 > gdbarch_double_bit (current_gdbarch))
+ result_type = builtin_type_long_double;
+ else
+ result_type = builtin_type_double;
+
+ return result_type;
+ }
+ else if (TYPE_CODE (type1) == TYPE_CODE_BOOL
+ && TYPE_CODE (type2) == TYPE_CODE_BOOL)
+ {
+ switch (op)
+ {
+ case BINOP_BITWISE_AND:
+ case BINOP_BITWISE_IOR:
+ case BINOP_BITWISE_XOR:
+ case BINOP_EQUAL:
+ case BINOP_NOTEQUAL:
+ break;
+ default:
+ error (_("Invalid operation on booleans."));
+ }
+
+ return type1;
+ }
+ else
+ /* Integral operations here. */
+ /* FIXME: Also mixed integral/booleans, with result an integer. */
+ {
+ unsigned int promoted_len1 = TYPE_LENGTH (type1);
+ unsigned int promoted_len2 = TYPE_LENGTH (type2);
+ int is_unsigned1 = TYPE_UNSIGNED (type1);
+ int is_unsigned2 = TYPE_UNSIGNED (type2);
+ unsigned int result_len;
+ int unsigned_operation;
+
+ /* Determine type length and signedness after promotion for
+ both operands. */
+ if (promoted_len1 < TYPE_LENGTH (builtin_type_int))
+ {
+ is_unsigned1 = 0;
+ promoted_len1 = TYPE_LENGTH (builtin_type_int);
+ }
+ if (promoted_len2 < TYPE_LENGTH (builtin_type_int))
+ {
+ is_unsigned2 = 0;
+ promoted_len2 = TYPE_LENGTH (builtin_type_int);
+ }
+
+ /* Determine type length of the result, and if the operation should
+ be done unsigned.
+ Use the signedness of the operand with the greater length.
+ If both operands are of equal length, use unsigned operation
+ if one of the operands is unsigned. */
+ if (op == BINOP_RSH || op == BINOP_LSH)
+ {
+ /* In case of the shift operators the type of the result only
+ depends on the type of the left operand. */
+ unsigned_operation = is_unsigned1;
+ result_len = promoted_len1;
+ }
+ else if (promoted_len1 > promoted_len2)
+ {
+ unsigned_operation = is_unsigned1;
+ result_len = promoted_len1;
+ }
+ else if (promoted_len2 > promoted_len1)
+ {
+ unsigned_operation = is_unsigned2;
+ result_len = promoted_len2;
+ }
+ else
+ {
+ unsigned_operation = is_unsigned1 || is_unsigned2;
+ result_len = promoted_len1;
+ }
+
+ switch (op)
+ {
+ case BINOP_ADD:
+ case BINOP_SUB:
+ case BINOP_MUL:
+ case BINOP_DIV:
+ case BINOP_INTDIV:
+ case BINOP_EXP:
+ case BINOP_REM:
+ case BINOP_MOD:
+ case BINOP_LSH:
+ case BINOP_RSH:
+ case BINOP_BITWISE_AND:
+ case BINOP_BITWISE_IOR:
+ case BINOP_BITWISE_XOR:
+ case BINOP_LOGICAL_AND:
+ case BINOP_LOGICAL_OR:
+ case BINOP_MIN:
+ case BINOP_MAX:
+ case BINOP_EQUAL:
+ case BINOP_NOTEQUAL:
+ case BINOP_LESS:
+ break;
+
+ default:
+ error (_("Invalid binary operation on numbers."));
+ }
+
+ switch (current_language->la_language)
+ {
+ case language_c:
+ case language_cplus:
+ case language_asm:
+ /* ??? language_objc? */
+ if (result_len <= TYPE_LENGTH (builtin_type_int))
+ {
+ return (unsigned_operation
+ ? builtin_type_unsigned_int
+ : builtin_type_int);
+ }
+ else if (result_len <= TYPE_LENGTH (builtin_type_long))
+ {
+ return (unsigned_operation
+ ? builtin_type_unsigned_long
+ : builtin_type_long);
+ }
+ else
+ {
+ return (unsigned_operation
+ ? builtin_type_unsigned_long_long
+ : builtin_type_long_long);
+ }
+
+ default:
+ if (unsigned_operation)
+ {
+ if (result_len > gdbarch_long_bit (current_gdbarch) / HOST_CHAR_BIT)
+ return builtin_type_unsigned_long_long;
+ else
+ return builtin_type_unsigned_long;
+ }
+ else
+ {
+ if (result_len > gdbarch_long_bit (current_gdbarch) / HOST_CHAR_BIT)
+ return builtin_type_long_long;
+ else
+ return builtin_type_long;
+ }
+ }
+ }
+}

/* Obtain decimal value of arguments for binary operation, converting from
other types if one of them is not decimal floating point. */
@@ -810,23 +1084,14 @@ struct value *
value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
{
struct value *val;
- struct type *type1, *type2;
+ struct type *result_type;

arg1 = coerce_ref (arg1);
arg2 = coerce_ref (arg2);
- type1 = check_typedef (value_type (arg1));
- type2 = check_typedef (value_type (arg2));

- if ((TYPE_CODE (type1) != TYPE_CODE_FLT
- && TYPE_CODE (type1) != TYPE_CODE_DECFLOAT && !is_integral_type (type1))
- ||
- (TYPE_CODE (type2) != TYPE_CODE_FLT
- && TYPE_CODE (type2) != TYPE_CODE_DECFLOAT && !is_integral_type (type2)))
- error (_("Argument to arithmetic operation not a number or boolean."));
+ result_type = binop_result_type (op, value_type (arg1), value_type (arg2));

- if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT
- ||
- TYPE_CODE (type2) == TYPE_CODE_DECFLOAT)
+ if (TYPE_CODE (result_type) == TYPE_CODE_DECFLOAT)
{
struct type *v_type;
int len_v1, len_v2, len_v;
@@ -849,23 +1114,9 @@ value_binop (struct value *arg1, struct
error (_("Operation not valid for decimal floating point number."));
}

- if (TYPE_CODE (type1) != TYPE_CODE_DECFLOAT)
- /* If arg1 is not a decimal float, the type of the result is the type
- of the decimal float argument, arg2. */
- v_type = type2;
- else if (TYPE_CODE (type2) != TYPE_CODE_DECFLOAT)
- /* Same logic, for the case where arg2 is not a decimal float. */
- v_type = type1;
- else
- /* len_v is equal either to len_v1 or to len_v2. the type of the
- result is the type of the argument with the same length as v. */
- v_type = (len_v == len_v1)? type1 : type2;
-
- val = value_from_decfloat (v_type, v);
+ val = value_from_decfloat (result_type, v);
}
- else if (TYPE_CODE (type1) == TYPE_CODE_FLT
- ||
- TYPE_CODE (type2) == TYPE_CODE_FLT)
+ else if (TYPE_CODE (result_type) == TYPE_CODE_FLT)
{
/* FIXME-if-picky-about-floating-accuracy: Should be doing this
in target format. real.c in GCC probably has the necessary
@@ -902,20 +1153,10 @@ value_binop (struct value *arg1, struct
error (_("Integer-only operation on floating point number."));
}

- /* If either arg was long double, make sure that value is also long
- double. */
-
- if (TYPE_LENGTH (type1) * 8 > gdbarch_double_bit (current_gdbarch)
- || TYPE_LENGTH (type2) * 8 > gdbarch_double_bit (current_gdbarch))
- val = allocate_value (builtin_type_long_double);
- else
- val = allocate_value (builtin_type_double);
-
+ val = allocate_value (result_type);
store_typed_floating (value_contents_raw (val), value_type (val), v);
}
- else if (TYPE_CODE (type1) == TYPE_CODE_BOOL
- &&
- TYPE_CODE (type2) == TYPE_CODE_BOOL)
+ else if (TYPE_CODE (result_type) == TYPE_CODE_BOOL)
{
LONGEST v1, v2, v = 0;
v1 = value_as_long (arg1);
@@ -947,72 +1188,32 @@ value_binop (struct value *arg1, struct
error (_("Invalid operation on booleans."));
}

- val = allocate_value (type1);
+ val = allocate_value (result_type);
store_signed_integer (value_contents_raw (val),
- TYPE_LENGTH (type1),
+ TYPE_LENGTH (result_type),
v);
}
else
/* 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 (the deleted) chill ? */
{
- unsigned int promoted_len1 = TYPE_LENGTH (type1);
- unsigned int promoted_len2 = TYPE_LENGTH (type2);
- int is_unsigned1 = TYPE_UNSIGNED (type1);
- int is_unsigned2 = TYPE_UNSIGNED (type2);
- unsigned int result_len;
- int unsigned_operation;
-
- /* Determine type length and signedness after promotion for
- both operands. */
- if (promoted_len1 < TYPE_LENGTH (builtin_type_int))
- {
- is_unsigned1 = 0;
- promoted_len1 = TYPE_LENGTH (builtin_type_int);
- }
- if (promoted_len2 < TYPE_LENGTH (builtin_type_int))
- {
- is_unsigned2 = 0;
- promoted_len2 = TYPE_LENGTH (builtin_type_int);
- }
-
- /* Determine type length of the result, and if the operation should
- be done unsigned.
- Use the signedness of the operand with the greater length.
- If both operands are of equal length, use unsigned operation
- if one of the operands is unsigned. */
- if (op == BINOP_RSH || op == BINOP_LSH)
- {
- /* In case of the shift operators the type of the result only
- depends on the type of the left operand. */
- unsigned_operation = is_unsigned1;
- result_len = promoted_len1;
- }
- else if (promoted_len1 > promoted_len2)
- {
- unsigned_operation = is_unsigned1;
- result_len = promoted_len1;
- }
- else if (promoted_len2 > promoted_len1)
- {
- unsigned_operation = is_unsigned2;
- result_len = promoted_len2;
- }
- else
- {
- unsigned_operation = is_unsigned1 || is_unsigned2;
- result_len = promoted_len1;
- }
+ int unsigned_operation = TYPE_UNSIGNED (result_type);

if (unsigned_operation)
{
+ unsigned int len1, len2, result_len;
ULONGEST v1, v2, v = 0;
v1 = (ULONGEST) value_as_long (arg1);
v2 = (ULONGEST) value_as_long (arg2);

- /* Truncate values to the type length of the result. */
+ /* Truncate values to the type length of the result.
+ Things are mildly trick because binop_result_type may
+ return a long which on amd64 is 8 bytes, and that's a problem if
+ ARG1, ARG2 are both <= 4 bytes. We need to truncate the values
+ at 4 bytes not 8. So fetch the lengths of the original types
+ and truncate at the larger of the two. */
+ len1 = TYPE_LENGTH (value_type (arg1));
+ len2 = TYPE_LENGTH (value_type (arg1));
+ result_len = len1 > len2 ? len1 : len2;
if (result_len < sizeof (ULONGEST))
{
v1 &= ((LONGEST) 1 << HOST_CHAR_BIT * result_len) - 1;
@@ -1119,19 +1320,7 @@ value_binop (struct value *arg1, struct
error (_("Invalid binary operation on numbers."));
}

- /* This is a kludge to get around the fact that we don't
- know how to determine the result type from the types of
- the operands. (I'm not really sure how much we feel the
- need to duplicate the exact rules of the current
- language. They can get really hairy. But not to do so
- makes it hard to document just what we *do* do). */
-
- /* Can't just call init_type because we wouldn't know what
- name to give the type. */
- val = allocate_value
- (result_len > gdbarch_long_bit (current_gdbarch) / HOST_CHAR_BIT
- ? builtin_type_unsigned_long_long
- : builtin_type_unsigned_long);
+ val = allocate_value (result_type);
store_unsigned_integer (value_contents_raw (val),
TYPE_LENGTH (value_type (val)),
v);
@@ -1245,19 +1434,7 @@ value_binop (struct value *arg1, struct
error (_("Invalid binary operation on numbers."));
}

- /* This is a kludge to get around the fact that we don't
- know how to determine the result type from the types of
- the operands. (I'm not really sure how much we feel the
- need to duplicate the exact rules of the current
- language. They can get really hairy. But not to do so
- makes it hard to document just what we *do* do). */
-
- /* Can't just call init_type because we wouldn't know what
- name to give the type. */
- val = allocate_value
- (result_len > gdbarch_long_bit (current_gdbarch) / HOST_CHAR_BIT
- ? builtin_type_long_long
- : builtin_type_long);
+ val = allocate_value (result_type);
store_signed_integer (value_contents_raw (val),
TYPE_LENGTH (value_type (val)),
v);
@@ -1469,23 +1646,19 @@ struct value *
value_pos (struct value *arg1)
{
struct type *type;
+ struct type *result_type;

arg1 = coerce_ref (arg1);
-
type = check_typedef (value_type (arg1));
+ result_type = unop_result_type (UNOP_PLUS, value_type (arg1));

if (TYPE_CODE (type) == TYPE_CODE_FLT)
- return value_from_double (type, value_as_double (arg1));
+ return value_from_double (result_type, value_as_double (arg1));
else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
- return value_from_decfloat (type, value_contents (arg1));
+ return value_from_decfloat (result_type, value_contents (arg1));
else if (is_integral_type (type))
{
- /* Perform integral promotion for ANSI C/C++. FIXME: What about
- FORTRAN and (the deleted) chill ? */
- if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
- type = builtin_type_int;
-
- return value_from_longest (type, value_as_long (arg1));
+ return value_from_longest (result_type, value_as_long (arg1));
}
else
{
@@ -1498,11 +1671,11 @@ struct value *
value_neg (struct value *arg1)
{
struct type *type;
- struct type *result_type = value_type (arg1);
+ struct type *result_type;

arg1 = coerce_ref (arg1);
-
type = check_typedef (value_type (arg1));
+ result_type = unop_result_type (UNOP_NEG, value_type (arg1));

if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
{
@@ -1520,16 +1693,10 @@ value_neg (struct value *arg1)
memcpy (value_contents_raw (val), decbytes, len);
return val;
}
-
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ else if (TYPE_CODE (type) == TYPE_CODE_FLT)
return value_from_double (result_type, -value_as_double (arg1));
else if (is_integral_type (type))
{
- /* 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;
-
return value_from_longest (result_type, -value_as_long (arg1));
}
else
@@ -1543,20 +1710,15 @@ struct value *
value_complement (struct value *arg1)
{
struct type *type;
- struct type *result_type = value_type (arg1);
+ struct type *result_type;

arg1 = coerce_ref (arg1);
-
type = check_typedef (value_type (arg1));
+ result_type = unop_result_type (UNOP_COMPLEMENT, value_type (arg1));

if (!is_integral_type (type))
error (_("Argument to complement operation not an integer or boolean."));

- /* Perform integral promotion for ANSI C/C++.
- FIXME: What about FORTRAN ? */
- if (TYPE_LENGTH (type) < TYPE_LENGTH (builtin_type_int))
- result_type = builtin_type_int;
-
return value_from_longest (result_type, ~value_as_long (arg1));
}
\f
Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.182
diff -u -p -r1.182 valops.c
--- valops.c 18 Jan 2008 17:07:40 -0000 1.182
+++ valops.c 30 Jan 2008 02:15:02 -0000
@@ -471,6 +471,41 @@ value_zero (struct type *type, enum lval
return val;
}

+/* Create a value of numeric type TYPE that is one, and return it. */
+
+struct value *
+value_one (struct type *type, enum lval_type lv)
+{
+ struct type *type1 = check_typedef (type);
+ struct value *val;
+
+ if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT)
+ {
+ struct value *int_one = value_from_longest (builtin_type_int, 1);
+ struct value *val;
+ gdb_byte v[16];
+
+ decimal_from_integral (int_one, v, TYPE_LENGTH (builtin_type_int));
+ val = value_from_decfloat (type, v);
+ value_free (int_one);
+ }
+ else if (TYPE_CODE (type1) == TYPE_CODE_FLT)
+ {
+ val = value_from_double (type, (DOUBLEST) 1);
+ }
+ else if (is_integral_type (type1))
+ {
+ val = value_from_longest (type, (LONGEST) 1);
+ }
+ else
+ {
+ error (_("Not a numeric type."));
+ }
+
+ VALUE_LVAL (val) = lv;
+ return val;
+}
+
/* Return a value with type TYPE located at ADDR.

Call value_at only if the data needs to be fetched immediately;
Index: value.h
===================================================================
RCS file: /cvs/src/src/gdb/value.h,v
retrieving revision 1.107
diff -u -p -r1.107 value.h
--- value.h 18 Jan 2008 17:07:40 -0000 1.107
+++ value.h 30 Jan 2008 02:15:03 -0000
@@ -392,6 +392,8 @@ extern struct value *value_cast (struct

extern struct value *value_zero (struct type *type, enum lval_type lv);

+extern struct value *value_one (struct type *type, enum lval_type lv);
+
extern struct value *value_repeat (struct value *arg1, int count);

extern struct value *value_subscript (struct value *array, struct value *idx);
Index: testsuite/gdb.base/whatis-exp.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/whatis-exp.exp,v
retrieving revision 1.7
diff -u -p -r1.7 whatis-exp.exp
--- testsuite/gdb.base/whatis-exp.exp 1 Jan 2008 22:53:19 -0000 1.7
+++ testsuite/gdb.base/whatis-exp.exp 30 Jan 2008 02:15:04 -0000