]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
ada: Fix unexpected overflow check before fixed-point multiplication
authorEric Botcazou <ebotcazou@adacore.com>
Fri, 26 Sep 2025 17:45:10 +0000 (19:45 +0200)
committerMarc Poulhiès <dkm@gcc.gnu.org>
Tue, 28 Oct 2025 10:24:05 +0000 (11:24 +0100)
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.

gcc/ada/exp_fixd.adb

index 8759099c193eb4c7e4198ade37713111c7b3810f..1107af3e003f23efed5f43fdab335bd04713c68f 100644 (file)
@@ -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,