Skip to content

Commit 80079c9

Browse files
authored
[libc] Fix new warning in DyadicFloat::as_mantissa_type_rounded (#131148)
The affected line of code converts a float's exponent from `int` to `size_t`, negating it in the process. Following clang commit 773e88f, this provokes a warning, presumably because the conversion goes wrong if `size_t` is wider than `int` and the input value is `INT_MIN`: negating it within the `int` type is undefined behavior, with the likely (though not guaranteed) effect of leaving it still at `INT_MIN` and then sign-extending that on promotion to `size_t`. This fix adds a cast so that the promotion to `size_t` happens _before_ the negation, so that the negative input value will _always_ be sign-extended, and then the negation will make it positive again. (I don't believe this case will actually come up. `DyadicFloat` is a helper system used in processing ordinary float formats, so nothing is expected to generate an exponent with even a 16-bit absolute value, let alone 31. But it's as easy to fix it to be robust as it is to just suppress the warning!)
1 parent e45090e commit 80079c9

File tree

1 file changed

+5
-1
lines changed

1 file changed

+5
-1
lines changed

libc/src/__support/FPUtil/dyadic_float.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,11 @@ template <size_t Bits> struct DyadicFloat {
455455
if (exponent > 0) {
456456
new_mant <<= exponent;
457457
} else if (exponent < 0) {
458-
size_t shift = -exponent;
458+
// Cast the exponent to size_t before negating it, rather than after,
459+
// to avoid undefined behavior negating INT_MIN as an integer (although
460+
// exponents coming in to this function _shouldn't_ be that large). The
461+
// result should always end up as a positive size_t.
462+
size_t shift = -static_cast<size_t>(exponent);
459463
new_mant >>= shift;
460464
round_dir = rounding_direction(mantissa, shift, sign);
461465
if (round_dir > 0)

0 commit comments

Comments
 (0)