From 301f0ecf99facbe3fd62ccefbc69a3dd3acc7235 Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Mon, 4 Feb 2008 00:23:05 +0000 Subject: [PATCH] * 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. --- gdb/ChangeLog | 12 + gdb/eval.c | 28 +- gdb/testsuite/ChangeLog | 2 + gdb/testsuite/gdb.base/whatis-exp.exp | 6 +- gdb/valarith.c | 468 ++++++++++++++++++-------- gdb/valops.c | 34 ++ gdb/value.h | 2 + 7 files changed, 399 insertions(+), 153 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 59c4f26f417..e100a1a984b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,17 @@ 2008-02-03 Doug Evans + * 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. diff --git a/gdb/eval.c b/gdb/eval.c index 6e5be65921c..efe1dc28d82 100644 --- a/gdb/eval.c +++ b/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); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 22c7030b9d5..f29e77cefc5 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,7 @@ 2008-02-03 Doug Evans + * 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. diff --git a/gdb/testsuite/gdb.base/whatis-exp.exp b/gdb/testsuite/gdb.base/whatis-exp.exp index 51b0e924dcc..1ad5e5af324 100644 --- a/gdb/testsuite/gdb.base/whatis-exp.exp +++ b/gdb/testsuite/gdb.base/whatis-exp.exp @@ -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" } diff --git a/gdb/valarith.c b/gdb/valarith.c index 62059122c07..7d6f35b2fbf 100644 --- a/gdb/valarith.c +++ b/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)); } diff --git a/gdb/valops.c b/gdb/valops.c index d4a0a9a27d4..69ebb15f821 100644 --- a/gdb/valops.c +++ b/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; diff --git a/gdb/value.h b/gdb/value.h index 6086917b409..1289a9726f7 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -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); -- 2.30.2