public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Ada] Wrong compile time evaluation of Shift_Right
@ 2020-11-27  9:18 Pierre-Marie de Rodat
  0 siblings, 0 replies; only message in thread
From: Pierre-Marie de Rodat @ 2020-11-27  9:18 UTC (permalink / raw)
  To: gcc-patches; +Cc: Arnaud Charlet

[-- Attachment #1: Type: text/plain, Size: 355 bytes --]

When using the Shift_Right operator on negative values (e.g. -1 on a
signed type), the wrong value is incorrectly folded after recent changes
in sem_eval.adb to add compile time evaluation of the shift operators.

Tested on x86_64-pc-linux-gnu, committed on trunk

gcc/ada/

	* sem_eval.adb (Fold_Shift): Fix evaluation of Shift_Right on
	negative values.

[-- Attachment #2: patch.diff --]
[-- Type: text/x-diff, Size: 1930 bytes --]

diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb
--- a/gcc/ada/sem_eval.adb
+++ b/gcc/ada/sem_eval.adb
@@ -4805,6 +4805,8 @@ package body Sem_Eval is
          end if;
       end Check_Elab_Call;
 
+      Modulus : Uint;
+
    begin
       if Compile_Time_Known_Value (Left)
         and then Compile_Time_Known_Value (Right)
@@ -4835,19 +4837,34 @@ package body Sem_Eval is
          elsif Op = N_Op_Shift_Right then
             Check_Elab_Call;
 
-            --  Fold Shift_Right (X, Y) by computing abs X / 2**Y
+            --  X >> 0 is a no-op
 
-            Fold_Uint
-              (N,
-               abs Expr_Value (Left) / (Uint_2 ** Expr_Value (Right)),
-               Static => Static);
+            if Expr_Value (Right) = Uint_0 then
+               Fold_Uint (N, Expr_Value (Left), Static => Static);
+            else
+               if Is_Modular_Integer_Type (Typ) then
+                  Modulus := Einfo.Modulus (Typ);
+               else
+                  Modulus := Uint_2 ** RM_Size (Typ);
+               end if;
+
+               --  Fold X >> Y by computing (X [+ Modulus]) / 2**Y
+               --  Note that after a Shift_Right operation (with Y > 0), the
+               --  result is always positive, even if the original operand was
+               --  negative.
 
+               Fold_Uint
+                 (N,
+                  (Expr_Value (Left) +
+                     (if Expr_Value (Left) >= Uint_0 then Uint_0 else Modulus))
+                  / (Uint_2 ** Expr_Value (Right)),
+                  Static => Static);
+            end if;
          elsif Op = N_Op_Shift_Right_Arithmetic then
             Check_Elab_Call;
 
             declare
                Two_Y   : constant Uint := Uint_2 ** Expr_Value (Right);
-               Modulus : Uint;
             begin
                if Is_Modular_Integer_Type (Typ) then
                   Modulus := Einfo.Modulus (Typ);



^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-11-27  9:18 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-27  9:18 [Ada] Wrong compile time evaluation of Shift_Right Pierre-Marie de Rodat

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).