forked from Imagelibrary/binutils-gdb
* 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:
@@ -1,5 +1,17 @@
|
|||||||
2008-02-03 Doug Evans <dje@google.com>
|
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
|
PR 2384
|
||||||
* gdbtypes.c (get_vptr_fieldno): Renamed from fill_in_vptr_fieldno.
|
* gdbtypes.c (get_vptr_fieldno): Renamed from fill_in_vptr_fieldno.
|
||||||
Return basetype, fieldno if found. All callers updated.
|
Return basetype, fieldno if found. All callers updated.
|
||||||
|
|||||||
26
gdb/eval.c
26
gdb/eval.c
@@ -1518,12 +1518,30 @@ evaluate_subexp_standard (struct type *expect_type,
|
|||||||
goto nosideret;
|
goto nosideret;
|
||||||
if (binop_user_defined_p (op, arg1, arg2))
|
if (binop_user_defined_p (op, arg1, arg2))
|
||||||
return value_x_binop (arg1, arg2, op, OP_NULL, noside);
|
return value_x_binop (arg1, arg2, op, OP_NULL, noside);
|
||||||
else if (noside == EVAL_AVOID_SIDE_EFFECTS
|
else
|
||||||
&& (op == BINOP_DIV || op == BINOP_REM || op == BINOP_MOD
|
{
|
||||||
|| op == BINOP_INTDIV))
|
/* If EVAL_AVOID_SIDE_EFFECTS and we're dividing by zero,
|
||||||
return value_zero (value_type (arg1), not_lval);
|
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
|
else
|
||||||
return value_binop (arg1, arg2, op);
|
return value_binop (arg1, arg2, op);
|
||||||
|
}
|
||||||
|
|
||||||
case BINOP_RANGE:
|
case BINOP_RANGE:
|
||||||
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
|
arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
2008-02-03 Doug Evans <dje@google.com>
|
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.exp: New file.
|
||||||
* gdb.cp/gdb2384.cc: New file.
|
* gdb.cp/gdb2384.cc: New file.
|
||||||
* gdb.cp/gdb2384-base.h: New file.
|
* gdb.cp/gdb2384-base.h: New file.
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ gdb_expect {
|
|||||||
|
|
||||||
send_gdb "whatis x+y\n"
|
send_gdb "whatis x+y\n"
|
||||||
gdb_expect {
|
gdb_expect {
|
||||||
-re ".*type = long.*$gdb_prompt $" {
|
-re ".*type = int.*$gdb_prompt $" {
|
||||||
pass "whatis value of x+y"
|
pass "whatis value of x+y"
|
||||||
}
|
}
|
||||||
-re ".*$gdb_prompt $" { fail "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"
|
send_gdb "whatis x-y\n"
|
||||||
gdb_expect {
|
gdb_expect {
|
||||||
-re ".*type = long.*$gdb_prompt $" {
|
-re ".*type = int.*$gdb_prompt $" {
|
||||||
pass "whatis value of x-y"
|
pass "whatis value of x-y"
|
||||||
}
|
}
|
||||||
-re ".*$gdb_prompt $" { fail "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"
|
send_gdb "whatis x*y\n"
|
||||||
gdb_expect {
|
gdb_expect {
|
||||||
-re ".*type = long.*$gdb_prompt $" {
|
-re ".*type = int.*$gdb_prompt $" {
|
||||||
pass "whatis value of x*y"
|
pass "whatis value of x*y"
|
||||||
}
|
}
|
||||||
-re ".*$gdb_prompt $" { fail "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
|
#endif
|
||||||
|
|
||||||
static struct value *value_subscripted_rvalue (struct value *, struct value *, int);
|
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);
|
void _initialize_valarith (void);
|
||||||
|
|
||||||
@@ -742,6 +745,293 @@ value_concat (struct value *arg1, struct value *arg2)
|
|||||||
return (outval);
|
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
|
/* Integer exponentiation: V1**V2, where both arguments are
|
||||||
integers. Requires V1 != 0 if V2 < 0. Returns 1 for 0 ** 0. */
|
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)
|
value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
|
||||||
{
|
{
|
||||||
struct value *val;
|
struct value *val;
|
||||||
struct type *type1, *type2;
|
struct type *result_type;
|
||||||
|
|
||||||
arg1 = coerce_ref (arg1);
|
arg1 = coerce_ref (arg1);
|
||||||
arg2 = coerce_ref (arg2);
|
arg2 = coerce_ref (arg2);
|
||||||
type1 = check_typedef (value_type (arg1));
|
|
||||||
type2 = check_typedef (value_type (arg2));
|
|
||||||
|
|
||||||
if ((TYPE_CODE (type1) != TYPE_CODE_FLT
|
result_type = binop_result_type (op, value_type (arg1), value_type (arg2));
|
||||||
&& 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
|
if (TYPE_CODE (result_type) == TYPE_CODE_DECFLOAT)
|
||||||
||
|
|
||||||
TYPE_CODE (type2) == TYPE_CODE_DECFLOAT)
|
|
||||||
{
|
{
|
||||||
struct type *v_type;
|
struct type *v_type;
|
||||||
int len_v1, len_v2, len_v;
|
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."));
|
error (_("Operation not valid for decimal floating point number."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TYPE_CODE (type1) != TYPE_CODE_DECFLOAT)
|
val = value_from_decfloat (result_type, v);
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
else if (TYPE_CODE (type1) == TYPE_CODE_FLT
|
else if (TYPE_CODE (result_type) == TYPE_CODE_FLT)
|
||||||
||
|
|
||||||
TYPE_CODE (type2) == TYPE_CODE_FLT)
|
|
||||||
{
|
{
|
||||||
/* FIXME-if-picky-about-floating-accuracy: Should be doing this
|
/* FIXME-if-picky-about-floating-accuracy: Should be doing this
|
||||||
in target format. real.c in GCC probably has the necessary
|
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;
|
DOUBLEST v1, v2, v = 0;
|
||||||
v1 = value_as_double (arg1);
|
v1 = value_as_double (arg1);
|
||||||
v2 = value_as_double (arg2);
|
v2 = value_as_double (arg2);
|
||||||
|
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case BINOP_ADD:
|
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."));
|
error (_("Integer-only operation on floating point number."));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If either arg was long double, make sure that value is also long
|
val = allocate_value (result_type);
|
||||||
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);
|
|
||||||
|
|
||||||
store_typed_floating (value_contents_raw (val), value_type (val), v);
|
store_typed_floating (value_contents_raw (val), value_type (val), v);
|
||||||
}
|
}
|
||||||
else if (TYPE_CODE (type1) == TYPE_CODE_BOOL
|
else if (TYPE_CODE (result_type) == TYPE_CODE_BOOL)
|
||||||
&&
|
|
||||||
TYPE_CODE (type2) == TYPE_CODE_BOOL)
|
|
||||||
{
|
{
|
||||||
LONGEST v1, v2, v = 0;
|
LONGEST v1, v2, v = 0;
|
||||||
v1 = value_as_long (arg1);
|
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."));
|
error (_("Invalid operation on booleans."));
|
||||||
}
|
}
|
||||||
|
|
||||||
val = allocate_value (type1);
|
val = allocate_value (result_type);
|
||||||
store_signed_integer (value_contents_raw (val),
|
store_signed_integer (value_contents_raw (val),
|
||||||
TYPE_LENGTH (type1),
|
TYPE_LENGTH (result_type),
|
||||||
v);
|
v);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* Integral operations here. */
|
/* 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);
|
int unsigned_operation = TYPE_UNSIGNED (result_type);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unsigned_operation)
|
if (unsigned_operation)
|
||||||
{
|
{
|
||||||
|
unsigned int len1, len2, result_len;
|
||||||
LONGEST v2_signed = value_as_long (arg2);
|
LONGEST v2_signed = value_as_long (arg2);
|
||||||
ULONGEST v1, v2, v = 0;
|
ULONGEST v1, v2, v = 0;
|
||||||
v1 = (ULONGEST) value_as_long (arg1);
|
v1 = (ULONGEST) value_as_long (arg1);
|
||||||
v2 = (ULONGEST) v2_signed;
|
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))
|
if (result_len < sizeof (ULONGEST))
|
||||||
{
|
{
|
||||||
v1 &= ((LONGEST) 1 << HOST_CHAR_BIT * result_len) - 1;
|
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."));
|
error (_("Invalid binary operation on numbers."));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is a kludge to get around the fact that we don't
|
val = allocate_value (result_type);
|
||||||
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);
|
|
||||||
store_unsigned_integer (value_contents_raw (val),
|
store_unsigned_integer (value_contents_raw (val),
|
||||||
TYPE_LENGTH (value_type (val)),
|
TYPE_LENGTH (value_type (val)),
|
||||||
v);
|
v);
|
||||||
@@ -1312,19 +1517,7 @@ value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
|
|||||||
error (_("Invalid binary operation on numbers."));
|
error (_("Invalid binary operation on numbers."));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is a kludge to get around the fact that we don't
|
val = allocate_value (result_type);
|
||||||
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);
|
|
||||||
store_signed_integer (value_contents_raw (val),
|
store_signed_integer (value_contents_raw (val),
|
||||||
TYPE_LENGTH (value_type (val)),
|
TYPE_LENGTH (value_type (val)),
|
||||||
v);
|
v);
|
||||||
@@ -1536,23 +1729,19 @@ struct value *
|
|||||||
value_pos (struct value *arg1)
|
value_pos (struct value *arg1)
|
||||||
{
|
{
|
||||||
struct type *type;
|
struct type *type;
|
||||||
|
struct type *result_type;
|
||||||
|
|
||||||
arg1 = coerce_ref (arg1);
|
arg1 = coerce_ref (arg1);
|
||||||
|
|
||||||
type = check_typedef (value_type (arg1));
|
type = check_typedef (value_type (arg1));
|
||||||
|
result_type = unop_result_type (UNOP_PLUS, value_type (arg1));
|
||||||
|
|
||||||
if (TYPE_CODE (type) == TYPE_CODE_FLT)
|
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)
|
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))
|
else if (is_integral_type (type))
|
||||||
{
|
{
|
||||||
/* Perform integral promotion for ANSI C/C++. FIXME: What about
|
return value_from_longest (result_type, value_as_long (arg1));
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1565,11 +1754,11 @@ struct value *
|
|||||||
value_neg (struct value *arg1)
|
value_neg (struct value *arg1)
|
||||||
{
|
{
|
||||||
struct type *type;
|
struct type *type;
|
||||||
struct type *result_type = value_type (arg1);
|
struct type *result_type;
|
||||||
|
|
||||||
arg1 = coerce_ref (arg1);
|
arg1 = coerce_ref (arg1);
|
||||||
|
|
||||||
type = check_typedef (value_type (arg1));
|
type = check_typedef (value_type (arg1));
|
||||||
|
result_type = unop_result_type (UNOP_NEG, value_type (arg1));
|
||||||
|
|
||||||
if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
|
if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
|
||||||
{
|
{
|
||||||
@@ -1587,16 +1776,10 @@ value_neg (struct value *arg1)
|
|||||||
memcpy (value_contents_raw (val), decbytes, len);
|
memcpy (value_contents_raw (val), decbytes, len);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
else if (TYPE_CODE (type) == TYPE_CODE_FLT)
|
||||||
if (TYPE_CODE (type) == TYPE_CODE_FLT)
|
|
||||||
return value_from_double (result_type, -value_as_double (arg1));
|
return value_from_double (result_type, -value_as_double (arg1));
|
||||||
else if (is_integral_type (type))
|
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));
|
return value_from_longest (result_type, -value_as_long (arg1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1610,20 +1793,15 @@ struct value *
|
|||||||
value_complement (struct value *arg1)
|
value_complement (struct value *arg1)
|
||||||
{
|
{
|
||||||
struct type *type;
|
struct type *type;
|
||||||
struct type *result_type = value_type (arg1);
|
struct type *result_type;
|
||||||
|
|
||||||
arg1 = coerce_ref (arg1);
|
arg1 = coerce_ref (arg1);
|
||||||
|
|
||||||
type = check_typedef (value_type (arg1));
|
type = check_typedef (value_type (arg1));
|
||||||
|
result_type = unop_result_type (UNOP_COMPLEMENT, value_type (arg1));
|
||||||
|
|
||||||
if (!is_integral_type (type))
|
if (!is_integral_type (type))
|
||||||
error (_("Argument to complement operation not an integer or boolean."));
|
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));
|
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;
|
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.
|
/* Return a value with type TYPE located at ADDR.
|
||||||
|
|
||||||
Call value_at only if the data needs to be fetched immediately;
|
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_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_repeat (struct value *arg1, int count);
|
||||||
|
|
||||||
extern struct value *value_subscript (struct value *array, struct value *idx);
|
extern struct value *value_subscript (struct value *array, struct value *idx);
|
||||||
|
|||||||
Reference in New Issue
Block a user