From 4a3b4c2a453369f7c72b0b3be8567134533c01bb Mon Sep 17 00:00:00 2001 From: Arnaud Charlet Date: Thu, 5 Nov 2020 04:48:28 -0500 Subject: [PATCH] [Ada] Wrong compile time evaluation of Shift_Right gcc/ada/ * sem_eval.adb (Fold_Shift): Fix evaluation of Shift_Right on negative values. --- gcc/ada/sem_eval.adb | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/gcc/ada/sem_eval.adb b/gcc/ada/sem_eval.adb index c54c49ac9a8..198f72fe085 100644 --- 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); -- 2.30.2