From: Eric Botcazou <[email protected]>

The problem is that the code generating the fixed-point multiply uses the
subtypes of the operands to size the operation, while operations are to be
performed in base types, which are signed per the RM 3.5.9(12) subclause.
As a consequence, when the subtypes are fully asymmetric unsigned, the size
is too small and an incorrect overflow check is generated.

The code generating the divide was fixed a long time ago, this aligns the
code generating the multiply and the code generating the remainder, which
in turn requires a couple of adjustments to related routines.

gcc/ada/ChangeLog:

        PR ada/122063
        * exp_fixd.adb (Build_Double_Divide_Code): Convert the result of the
        multiply.
        (Build_Multiply): Use base types of operands to size the operation.
        (Build_Rem): Likewise.
        (Build_Scaled_Divide_Code): Convert the result of the multiply.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/ada/exp_fixd.adb | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/gcc/ada/exp_fixd.adb b/gcc/ada/exp_fixd.adb
index 8759099c193..1107af3e003 100644
--- a/gcc/ada/exp_fixd.adb
+++ b/gcc/ada/exp_fixd.adb
@@ -595,7 +595,8 @@ package body Exp_Fixd is
              Defining_Identifier => Dnn,
              Object_Definition   => New_Occurrence_Of (QR_Typ, Loc),
              Constant_Present    => True,
-             Expression          => Build_Multiply (N, Y, Z)));
+             Expression          =>
+               Build_Conversion (N, QR_Typ, Build_Multiply (N, Y, Z))));
 
          Quo :=
            Build_Divide (N,
@@ -656,8 +657,8 @@ package body Exp_Fixd is
 
    function Build_Multiply (N : Node_Id; L, R : Node_Id) return Node_Id is
       Loc         : constant Source_Ptr := Sloc (N);
-      Left_Type   : constant Entity_Id  := Etype (L);
-      Right_Type  : constant Entity_Id  := Etype (R);
+      Left_Type   : constant Entity_Id  := Base_Type (Etype (L));
+      Right_Type  : constant Entity_Id  := Base_Type (Etype (R));
       Left_Size   : Int;
       Right_Size  : Int;
       Result_Type : Entity_Id;
@@ -746,8 +747,8 @@ package body Exp_Fixd is
 
    function Build_Rem (N : Node_Id; L, R : Node_Id) return Node_Id is
       Loc         : constant Source_Ptr := Sloc (N);
-      Left_Type   : constant Entity_Id  := Etype (L);
-      Right_Type  : constant Entity_Id  := Etype (R);
+      Left_Type   : constant Entity_Id  := Base_Type (Etype (L));
+      Right_Type  : constant Entity_Id  := Base_Type (Etype (R));
       Result_Type : Entity_Id;
       Rnode       : Node_Id;
 
@@ -959,7 +960,8 @@ package body Exp_Fixd is
              Defining_Identifier => Nnn,
              Object_Definition   => New_Occurrence_Of (QR_Typ, Loc),
              Constant_Present    => True,
-             Expression          => Build_Multiply (N, X, Y)),
+             Expression          =>
+               Build_Conversion (N, QR_Typ, Build_Multiply (N, X, Y))),
 
            Make_Object_Declaration (Loc,
              Defining_Identifier => Dnn,
-- 
2.51.0

Reply via email to