summaryrefslogtreecommitdiff
path: root/gas/expr.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/expr.c')
-rw-r--r--gas/expr.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/gas/expr.c b/gas/expr.c
index 680ec13b192..05b210ba98b 100644
--- a/gas/expr.c
+++ b/gas/expr.c
@@ -1954,14 +1954,6 @@ expr (int rankarg, /* Larger # is higher rank. */
as_warn (_("division by zero"));
v = 1;
}
- if ((valueT) v >= sizeof(valueT) * CHAR_BIT
- && (op_left == O_left_shift || op_left == O_right_shift))
- {
- as_warn_value_out_of_range (_("shift count"), v, 0,
- sizeof(valueT) * CHAR_BIT - 1,
- NULL, 0);
- resultP->X_add_number = v = 0;
- }
switch (op_left)
{
default: goto general;
@@ -1974,6 +1966,7 @@ expr (int rankarg, /* Larger # is higher rank. */
case O_divide: resultP->X_add_number /= v; break;
case O_modulus: resultP->X_add_number %= v; break;
case O_left_shift:
+ case O_right_shift:
/* We always use unsigned shifts. According to the ISO
C standard, left shift of a signed type having a
negative value is undefined behaviour, and right
@@ -1982,12 +1975,19 @@ expr (int rankarg, /* Larger # is higher rank. */
when the result overflows is also undefined
behaviour. So don't trigger ubsan warnings or rely
on characteristics of the compiler. */
- resultP->X_add_number
- = (valueT) resultP->X_add_number << (valueT) v;
- break;
- case O_right_shift:
- resultP->X_add_number
- = (valueT) resultP->X_add_number >> (valueT) v;
+ if ((valueT) v >= sizeof (valueT) * CHAR_BIT)
+ {
+ as_warn_value_out_of_range (_("shift count"), v, 0,
+ sizeof (valueT) * CHAR_BIT - 1,
+ NULL, 0);
+ resultP->X_add_number = 0;
+ }
+ else if (op_left == O_left_shift)
+ resultP->X_add_number
+ = (valueT) resultP->X_add_number << (valueT) v;
+ else
+ resultP->X_add_number
+ = (valueT) resultP->X_add_number >> (valueT) v;
break;
case O_bit_inclusive_or: resultP->X_add_number |= v; break;
case O_bit_or_not: resultP->X_add_number |= ~v; break;