* 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. 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. * gdb.base/whatis-exp.exp: Fix expected result of whatis x+y, x-y, x*y.
This commit is contained in:
parent
e44a2c9c3d
commit
301f0ecf99
@ -1,5 +1,17 @@
|
||||
2008-02-03 Doug Evans <dje@google.com>
|
||||
|
||||
* 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.
|
||||
|
||||
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.
|
||||
|
||||
PR 2384
|
||||
* gdbtypes.c (get_vptr_fieldno): Renamed from fill_in_vptr_fieldno.
|
||||
Return basetype, fieldno if found. All callers updated.
|
||||
|
28
gdb/eval.c
28
gdb/eval.c
@ -1518,12 +1518,30 @@ evaluate_subexp_standard (struct type *expect_type,
|
||||
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
|
||||
|| op == BINOP_INTDIV))
|
||||
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_INTDIV
|
||||
|| op == BINOP_REM
|
||||
|| op == BINOP_MOD)
|
||||
&& value_logical_not (arg2))
|
||||
{
|
||||
struct value *v_one, *retval;
|
||||
|
||||
v_one = value_one (value_type (arg2), not_lval);
|
||||
retval = value_binop (arg1, v_one, op);
|
||||
return retval;
|
||||
}
|
||||
else
|
||||
return value_binop (arg1, arg2, op);
|
||||
}
|
||||
|
||||
case BINOP_RANGE:
|
||||
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
|
||||
|
@ -1,5 +1,7 @@
|
||||
2008-02-03 Doug Evans <dje@google.com>
|
||||
|
||||
* gdb.base/whatis-exp.exp: Fix expected result of whatis x+y, x-y, x*y.
|
||||
|
||||
* gdb.cp/gdb2384.exp: New file.
|
||||
* gdb.cp/gdb2384.cc: New file.
|
||||
* gdb.cp/gdb2384-base.h: New file.
|
||||
|
@ -112,7 +112,7 @@ gdb_expect {
|
||||
|
||||
send_gdb "whatis x+y\n"
|
||||
gdb_expect {
|
||||
-re ".*type = long.*$gdb_prompt $" {
|
||||
-re ".*type = int.*$gdb_prompt $" {
|
||||
pass "whatis value of x+y"
|
||||
}
|
||||
-re ".*$gdb_prompt $" { fail "whatis value of x+y" }
|
||||
@ -121,7 +121,7 @@ gdb_expect {
|
||||
|
||||
send_gdb "whatis x-y\n"
|
||||
gdb_expect {
|
||||
-re ".*type = long.*$gdb_prompt $" {
|
||||
-re ".*type = int.*$gdb_prompt $" {
|
||||
pass "whatis value of x-y"
|
||||
}
|
||||
-re ".*$gdb_prompt $" { fail "whatis value of x-y" }
|
||||
@ -130,7 +130,7 @@ gdb_expect {
|
||||
|
||||
send_gdb "whatis x*y\n"
|
||||
gdb_expect {
|
||||
-re ".*type = long.*$gdb_prompt $" {
|
||||
-re ".*type = int.*$gdb_prompt $" {
|
||||
pass "whatis value of x*y"
|
||||
}
|
||||
-re ".*$gdb_prompt $" { fail "whatis value of x*y" }
|
||||
|
468
gdb/valarith.c
468
gdb/valarith.c
@ -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);
|
||||
|
||||
@ -742,6 +745,293 @@ value_concat (struct value *arg1, struct value *arg2)
|
||||
return (outval);
|
||||
}
|
||||
|
||||
/* Return result 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
|
||||
modify this function to return the correct result for it. */
|
||||
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 result type of OP performed on TYPE1, TYPE2.
|
||||
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)
|
||||
{
|
||||
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. */
|
||||
return type2;
|
||||
else if (TYPE_CODE (type2) != TYPE_CODE_DECFLOAT)
|
||||
/* Same logic, for the case where type2 is not a decimal float. */
|
||||
return type1;
|
||||
else
|
||||
/* Both are decimal floats, the type of the result is the bigger
|
||||
of the two. */
|
||||
return (TYPE_LENGTH (type1) > TYPE_LENGTH (type2)) ? type1 : type2;
|
||||
}
|
||||
else if (TYPE_CODE (type1) == TYPE_CODE_FLT
|
||||
|| TYPE_CODE (type2) == TYPE_CODE_FLT)
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case BINOP_ADD:
|
||||
case BINOP_SUB:
|
||||
case BINOP_MUL:
|
||||
case BINOP_DIV:
|
||||
case BINOP_EXP:
|
||||
case BINOP_MIN:
|
||||
case BINOP_MAX:
|
||||
break;
|
||||
default:
|
||||
error (_("Integer-only operation on floating point number."));
|
||||
}
|
||||
|
||||
switch (current_language->la_language)
|
||||
{
|
||||
case language_c:
|
||||
case language_cplus:
|
||||
case language_asm:
|
||||
case language_objc:
|
||||
/* Perform ANSI/ISO-C promotions.
|
||||
If only one type is float, use its type.
|
||||
Otherwise use the bigger type. */
|
||||
if (TYPE_CODE (type1) != TYPE_CODE_FLT)
|
||||
return type2;
|
||||
else if (TYPE_CODE (type2) != TYPE_CODE_FLT)
|
||||
return type1;
|
||||
else
|
||||
return (TYPE_LENGTH (type1) > TYPE_LENGTH (type2)) ? type1 : type2;
|
||||
|
||||
default:
|
||||
/* For other languages the result type is unchanged from gdb
|
||||
version 6.7 for backward compatibility.
|
||||
If either arg was long double, make sure that value is also long
|
||||
double. Otherwise use double. */
|
||||
if (TYPE_LENGTH (type1) * 8 > gdbarch_double_bit (current_gdbarch)
|
||||
|| TYPE_LENGTH (type2) * 8 > gdbarch_double_bit (current_gdbarch))
|
||||
return builtin_type_long_double;
|
||||
else
|
||||
return builtin_type_double;
|
||||
}
|
||||
}
|
||||
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. For exponentiation and shift operators,
|
||||
use the length and type of the left operand. Otherwise,
|
||||
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 || op == BINOP_EXP)
|
||||
{
|
||||
/* In case of the shift operators and exponentiation 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:
|
||||
case 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:
|
||||
/* For other languages the result type is unchanged from gdb
|
||||
version 6.7 for backward compatibility.
|
||||
If either arg was long long, make sure that value is also long
|
||||
long. Otherwise use long. */
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL; /* avoid -Wall warning */
|
||||
}
|
||||
|
||||
/* Integer exponentiation: V1**V2, where both arguments are
|
||||
integers. Requires V1 != 0 if V2 < 0. Returns 1 for 0 ** 0. */
|
||||
@ -870,23 +1160,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;
|
||||
@ -909,23 +1190,9 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
|
||||
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
|
||||
@ -933,6 +1200,7 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
|
||||
DOUBLEST v1, v2, v = 0;
|
||||
v1 = value_as_double (arg1);
|
||||
v2 = value_as_double (arg2);
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case BINOP_ADD:
|
||||
@ -970,20 +1238,10 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
|
||||
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);
|
||||
@ -1015,74 +1273,33 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
|
||||
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. For exponentiation and shift operators,
|
||||
use the length and type of the left operand. Otherwise,
|
||||
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 || op == BINOP_EXP)
|
||||
{
|
||||
/* In case of the shift operators and exponentiation 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;
|
||||
LONGEST v2_signed = value_as_long (arg2);
|
||||
ULONGEST v1, v2, v = 0;
|
||||
v1 = (ULONGEST) value_as_long (arg1);
|
||||
v2 = (ULONGEST) v2_signed;
|
||||
|
||||
/* Truncate values to the type length of the result. */
|
||||
/* Truncate values to the type length of the result.
|
||||
Things are mildly tricky 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;
|
||||
@ -1189,19 +1406,7 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
|
||||
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);
|
||||
@ -1312,19 +1517,7 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
|
||||
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);
|
||||
@ -1536,23 +1729,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
|
||||
{
|
||||
@ -1565,11 +1754,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)
|
||||
{
|
||||
@ -1587,16 +1776,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
|
||||
@ -1610,20 +1793,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));
|
||||
}
|
||||
|
||||
|
34
gdb/valops.c
34
gdb/valops.c
@ -471,6 +471,40 @@ value_zero (struct type *type, enum lval_type lv)
|
||||
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 = NULL; /* avoid -Wall warning */
|
||||
|
||||
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);
|
||||
}
|
||||
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;
|
||||
|
@ -392,6 +392,8 @@ extern struct value *value_cast (struct type *type, struct value *arg2);
|
||||
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user