https://gcc.gnu.org/g:b2dcb85380b606e4064089bb79dde2c9ff271ad0

commit r16-1932-gb2dcb85380b606e4064089bb79dde2c9ff271ad0
Author: Eric Botcazou <ebotca...@adacore.com>
Date:   Tue Jun 3 18:54:03 2025 +0200

    ada: Fix spurious Constraint_Error raised by 'Value of fixed-point types
    
    This happens for very large Smalls with regard to the size of the mantissa,
    because the prerequisites of the implementation used in this case are not
    met, although they are documented in the head comment of Integer_To_Fixed.
    
    This change documents them at the beginning of the body of System.Value_F
    and adjusts the compiler interface accordingly.
    
    gcc/ada/ChangeLog:
    
            * libgnat/s-valuef.adb: Document the prerequisites more precisely.
            * libgnat/a-tifiio.adb (OK_Get_32): Adjust to the prerequisites.
            (OK_Get_64): Likewise.
            * libgnat/a-tifiio__128.adb (OK_Get_32): Likewise.
            (OK_Get_64): Likewise.
            (OK_Get_128): Likewise.
            * libgnat/a-wtfiio.adb (OK_Get_32): Likewise.
            (OK_Get_64): Likewise.
            * libgnat/a-wtfiio__128.adb (OK_Get_32): Likewise.
            (OK_Get_64): Likewise.
            (OK_Get_128): Likewise.
            * libgnat/a-ztfiio.adb (OK_Get_32): Likewise.
            (OK_Get_64): Likewise.
            * libgnat/a-ztfiio__128.adb (OK_Get_32): Likewise.
            (OK_Get_64): Likewise.
            (OK_Get_128): Likewise.
            * exp_imgv.adb (Expand_Value_Attribute): Adjust the conditions under
            which the RE_Value_Fixed{32,64,128} routines are called for ordinary
            fixed-point types.

Diff:
---
 gcc/ada/exp_imgv.adb              |  7 +++----
 gcc/ada/libgnat/a-tifiio.adb      |  6 ------
 gcc/ada/libgnat/a-tifiio__128.adb |  9 ---------
 gcc/ada/libgnat/a-wtfiio.adb      |  6 ------
 gcc/ada/libgnat/a-wtfiio__128.adb |  9 ---------
 gcc/ada/libgnat/a-ztfiio.adb      |  6 ------
 gcc/ada/libgnat/a-ztfiio__128.adb |  9 ---------
 gcc/ada/libgnat/s-valuef.adb      | 16 ++++++++++------
 8 files changed, 13 insertions(+), 55 deletions(-)

diff --git a/gcc/ada/exp_imgv.adb b/gcc/ada/exp_imgv.adb
index c7cf06ba444f..6c2b940736ba 100644
--- a/gcc/ada/exp_imgv.adb
+++ b/gcc/ada/exp_imgv.adb
@@ -1640,23 +1640,22 @@ package body Exp_Imgv is
             Num : constant Uint := Norm_Num (Small_Value (Rtyp));
             Den : constant Uint := Norm_Den (Small_Value (Rtyp));
             Max : constant Uint := UI_Max (Num, Den);
-            Min : constant Uint := UI_Min (Num, Den);
             Siz : constant Uint := Esize (Rtyp);
 
          begin
             if Siz <= 32
               and then Max <= Uint_2 ** 31
-              and then (Min = Uint_1 or else Max <= Uint_2 ** 27)
+              and then (Num = Uint_1 or else Max <= Uint_2 ** 27)
             then
                Vid := RE_Value_Fixed32;
             elsif Siz <= 64
               and then Max <= Uint_2 ** 63
-              and then (Min = Uint_1 or else Max <= Uint_2 ** 59)
+              and then (Num = Uint_1 or else Max <= Uint_2 ** 59)
             then
                Vid := RE_Value_Fixed64;
             elsif System_Max_Integer_Size = 128
               and then Max <= Uint_2 ** 127
-              and then (Min = Uint_1 or else Max <= Uint_2 ** 123)
+              and then (Num = Uint_1 or else Max <= Uint_2 ** 123)
             then
                Vid := RE_Value_Fixed128;
             else
diff --git a/gcc/ada/libgnat/a-tifiio.adb b/gcc/ada/libgnat/a-tifiio.adb
index 735859c3f150..26f04ed726ee 100644
--- a/gcc/ada/libgnat/a-tifiio.adb
+++ b/gcc/ada/libgnat/a-tifiio.adb
@@ -194,9 +194,6 @@ package body Ada.Text_IO.Fixed_IO with SPARK_Mode => Off is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**31)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**31)
-           or else
           (Num'Base'Small_Numerator <= 2**27
             and then Num'Base'Small_Denominator <= 2**27));
    --  These conditions are derived from the prerequisites of System.Value_F
@@ -223,9 +220,6 @@ package body Ada.Text_IO.Fixed_IO with SPARK_Mode => Off is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**63)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**63)
-           or else
           (Num'Base'Small_Numerator <= 2**59
             and then Num'Base'Small_Denominator <= 2**59));
    --  These conditions are derived from the prerequisites of System.Value_F
diff --git a/gcc/ada/libgnat/a-tifiio__128.adb 
b/gcc/ada/libgnat/a-tifiio__128.adb
index 7424346fe3d6..78c25f29bc8b 100644
--- a/gcc/ada/libgnat/a-tifiio__128.adb
+++ b/gcc/ada/libgnat/a-tifiio__128.adb
@@ -201,9 +201,6 @@ package body Ada.Text_IO.Fixed_IO with SPARK_Mode => Off is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**31)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**31)
-           or else
           (Num'Base'Small_Numerator <= 2**27
             and then Num'Base'Small_Denominator <= 2**27));
    --  These conditions are derived from the prerequisites of System.Value_F
@@ -230,9 +227,6 @@ package body Ada.Text_IO.Fixed_IO with SPARK_Mode => Off is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**63)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**63)
-           or else
           (Num'Base'Small_Numerator <= 2**59
             and then Num'Base'Small_Denominator <= 2**59));
    --  These conditions are derived from the prerequisites of System.Value_F
@@ -259,9 +253,6 @@ package body Ada.Text_IO.Fixed_IO with SPARK_Mode => Off is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**127)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**127)
-           or else
           (Num'Base'Small_Numerator <= 2**123
             and then Num'Base'Small_Denominator <= 2**123));
    --  These conditions are derived from the prerequisites of System.Value_F
diff --git a/gcc/ada/libgnat/a-wtfiio.adb b/gcc/ada/libgnat/a-wtfiio.adb
index ed69d65df09d..3ceda12b9ec3 100644
--- a/gcc/ada/libgnat/a-wtfiio.adb
+++ b/gcc/ada/libgnat/a-wtfiio.adb
@@ -73,9 +73,6 @@ package body Ada.Wide_Text_IO.Fixed_IO is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**31)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**31)
-           or else
           (Num'Base'Small_Numerator <= 2**27
             and then Num'Base'Small_Denominator <= 2**27));
    --  These conditions are derived from the prerequisites of System.Value_F
@@ -102,9 +99,6 @@ package body Ada.Wide_Text_IO.Fixed_IO is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**63)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**63)
-           or else
           (Num'Base'Small_Numerator <= 2**59
             and then Num'Base'Small_Denominator <= 2**59));
    --  These conditions are derived from the prerequisites of System.Value_F
diff --git a/gcc/ada/libgnat/a-wtfiio__128.adb 
b/gcc/ada/libgnat/a-wtfiio__128.adb
index ec8deca6ca4e..8757ffb25149 100644
--- a/gcc/ada/libgnat/a-wtfiio__128.adb
+++ b/gcc/ada/libgnat/a-wtfiio__128.adb
@@ -80,9 +80,6 @@ package body Ada.Wide_Text_IO.Fixed_IO is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**31)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**31)
-           or else
           (Num'Base'Small_Numerator <= 2**27
             and then Num'Base'Small_Denominator <= 2**27));
    --  These conditions are derived from the prerequisites of System.Value_F
@@ -109,9 +106,6 @@ package body Ada.Wide_Text_IO.Fixed_IO is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**63)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**63)
-           or else
           (Num'Base'Small_Numerator <= 2**59
             and then Num'Base'Small_Denominator <= 2**59));
    --  These conditions are derived from the prerequisites of System.Value_F
@@ -138,9 +132,6 @@ package body Ada.Wide_Text_IO.Fixed_IO is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**127)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**127)
-           or else
           (Num'Base'Small_Numerator <= 2**123
             and then Num'Base'Small_Denominator <= 2**123));
    --  These conditions are derived from the prerequisites of System.Value_F
diff --git a/gcc/ada/libgnat/a-ztfiio.adb b/gcc/ada/libgnat/a-ztfiio.adb
index edf58ad85ead..b9f4f43226f0 100644
--- a/gcc/ada/libgnat/a-ztfiio.adb
+++ b/gcc/ada/libgnat/a-ztfiio.adb
@@ -73,9 +73,6 @@ package body Ada.Wide_Wide_Text_IO.Fixed_IO is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**31)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**31)
-           or else
           (Num'Base'Small_Numerator <= 2**27
             and then Num'Base'Small_Denominator <= 2**27));
    --  These conditions are derived from the prerequisites of System.Value_F
@@ -102,9 +99,6 @@ package body Ada.Wide_Wide_Text_IO.Fixed_IO is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**63)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**63)
-           or else
           (Num'Base'Small_Numerator <= 2**59
             and then Num'Base'Small_Denominator <= 2**59));
    --  These conditions are derived from the prerequisites of System.Value_F
diff --git a/gcc/ada/libgnat/a-ztfiio__128.adb 
b/gcc/ada/libgnat/a-ztfiio__128.adb
index bc0062f9d9f8..eb02a4a2cece 100644
--- a/gcc/ada/libgnat/a-ztfiio__128.adb
+++ b/gcc/ada/libgnat/a-ztfiio__128.adb
@@ -81,9 +81,6 @@ package body Ada.Wide_Wide_Text_IO.Fixed_IO is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**31)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**31)
-           or else
           (Num'Base'Small_Numerator <= 2**27
             and then Num'Base'Small_Denominator <= 2**27));
    --  These conditions are derived from the prerequisites of System.Value_F
@@ -110,9 +107,6 @@ package body Ada.Wide_Wide_Text_IO.Fixed_IO is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**63)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**63)
-           or else
           (Num'Base'Small_Numerator <= 2**59
             and then Num'Base'Small_Denominator <= 2**59));
    --  These conditions are derived from the prerequisites of System.Value_F
@@ -139,9 +133,6 @@ package body Ada.Wide_Wide_Text_IO.Fixed_IO is
          ((Num'Base'Small_Numerator = 1
             and then Num'Base'Small_Denominator <= 2**127)
            or else
-          (Num'Base'Small_Denominator = 1
-            and then Num'Base'Small_Numerator <= 2**127)
-           or else
           (Num'Base'Small_Numerator <= 2**123
             and then Num'Base'Small_Denominator <= 2**123));
    --  These conditions are derived from the prerequisites of System.Value_F
diff --git a/gcc/ada/libgnat/s-valuef.adb b/gcc/ada/libgnat/s-valuef.adb
index 1743749f5421..f38f2cc66ac3 100644
--- a/gcc/ada/libgnat/s-valuef.adb
+++ b/gcc/ada/libgnat/s-valuef.adb
@@ -36,12 +36,13 @@ with System.Value_R;
 package body System.Value_F is
 
    --  The prerequisite of the implementation is that the computation of the
-   --  operands of the scaled divide does not unduly overflow when the small
-   --  is neither an integer nor the reciprocal of an integer, which means
-   --  that its numerator and denominator must be both not larger than the
-   --  smallest divide 2**(Int'Size - 1) / Base where Base ranges over the
-   --  supported values for the base of the literal. Given that the largest
-   --  supported base is 16, this gives a limit of 2**(Int'Size - 5).
+   --  operands of the scaled divide does not unduly overflow, which means
+   --  that the numerator and the denominator of the small must be both not
+   --  larger than the smallest divide 2**(Int'Size - 1) / Base where Base
+   --  ranges over the supported values for the base of the literal, except
+   --  when the numerator is 1, in which case up to 2**(Int'Size - 1) is
+   --  permitted for the denominator. Given that the largest supported base
+   --  is 16, this gives a limit of 2**(Int'Size - 5) in the general case.
 
    pragma Assert (Int'Size <= Uns'Size);
    --  We need an unsigned type large enough to represent the mantissa
@@ -135,6 +136,9 @@ package body System.Value_F is
    --    Num * (Base ** -ScaleB) <= Num * (B ** N) < Den * B
 
    --  which means that the product does not overflow if Den <= 2**(M-1) / B.
+   --  Moreover, if 2**(M-1) / B < Den <= 2**(M-1), we can add 1 to ScaleB and
+   --  divide Val by B while preserving the rightmost B-digit of Val in Extra2
+   --  without changing the computation when Num = 1.
 
    ----------------------
    -- Integer_To_Fixed --

Reply via email to