diff options
author | Yannick Moy <moy@adacore.com> | 2019-09-17 08:02:30 +0000 |
---|---|---|
committer | Pierre-Marie de Rodat <pmderodat@gcc.gnu.org> | 2019-09-17 08:02:30 +0000 |
commit | d4ba72cbad263d9b4fd211534c117343ed5333a1 (patch) | |
tree | 7a0e5a8389c0d2c6332239dfe378189aa472a311 /gcc/ada | |
parent | 7197e2db28f10dec509967bb1cbd2d74cb03ee7e (diff) | |
download | gcc-d4ba72cbad263d9b4fd211534c117343ed5333a1.zip gcc-d4ba72cbad263d9b4fd211534c117343ed5333a1.tar.gz gcc-d4ba72cbad263d9b4fd211534c117343ed5333a1.tar.bz2 |
[Ada] Raise Constraint_Error in overflow case involving rounding
Function Scaled_Divide in s-arith runtime unit computes the combined
multiplication and division of its arguments ((X*Y) / Z). In a very
special case where the quotient computed before rounding is 2**64-1,
then rounding may lead to undesirable wrap-around, leading to a computed
quotient of 0 instead of raising Constraint_Error as expected.
This function is only called in the runtime for arithmetic operations
involving fixed-point types. Rounding is performed only when the target
type is of a decimal fixed-point type, and the attribute 'Round of the
type is used to round the result of the arithmetic operation.
This fix correctly raises Constraint_Error in this special case.
2019-09-17 Yannick Moy <moy@adacore.com>
gcc/ada/
* libgnat/s-arit64.adb (Scaled_Divide): Add protection against
undesirable wrap-around.
gcc/testsuite/
* gnat.dg/multfixed.adb: New testcase.
From-SVN: r275791
Diffstat (limited to 'gcc/ada')
-rw-r--r-- | gcc/ada/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/ada/libgnat/s-arit64.adb | 8 |
2 files changed, 13 insertions, 0 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 913b30f..9a07751 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,10 @@ 2019-09-17 Yannick Moy <moy@adacore.com> + * libgnat/s-arit64.adb (Scaled_Divide): Add protection against + undesirable wrap-around. + +2019-09-17 Yannick Moy <moy@adacore.com> + * libgnat/s-arit64.adb (Double_Divide): Fix two possible overflows. diff --git a/gcc/ada/libgnat/s-arit64.adb b/gcc/ada/libgnat/s-arit64.adb index a35a40d..6773dd8 100644 --- a/gcc/ada/libgnat/s-arit64.adb +++ b/gcc/ada/libgnat/s-arit64.adb @@ -511,6 +511,14 @@ package body System.Arith_64 is -- Deal with rounding case if Round and then Ru > (Zu - Uns64'(1)) / Uns64'(2) then + + -- Protect against wrapping around when rounding, by signaling + -- an overflow when the quotient is too large. + + if Qu = Uns64'Last then + Raise_Error; + end if; + Qu := Qu + Uns64 (1); end if; |