[Ada] Crash on right shift operator for signed integers

gcc/ada/

	* doc/gnat_rm/intrinsic_subprograms.rst (Shifts and Rotates):
	Document behavior on negative numbers
	* gnat_rm.texi: Regenerate.
	* sem_eval.adb (Fold_Shift): Set modulus to be based on the RM
	size for non-modular integer types.
This commit is contained in:
Justin Squirek 2020-10-12 12:06:08 -04:00 committed by Pierre-Marie de Rodat
parent 4d617c3f2a
commit e480bca240
3 changed files with 22 additions and 8 deletions

View File

@ -217,7 +217,9 @@ The formal parameter names can be anything.
A more convenient way of providing these shift operators is to use
the Provide_Shift_Operators pragma, which provides the function declarations
and corresponding pragma Import's for all five shift functions.
and corresponding pragma Import's for all five shift functions. Note that in
using these provided shift operations, shifts performed on negative numbers
will result in modification of the sign bit.
.. _Source_Location:

View File

@ -17862,7 +17862,9 @@ The formal parameter names can be anything.
A more convenient way of providing these shift operators is to use
the Provide_Shift_Operators pragma, which provides the function declarations
and corresponding pragma Import's for all five shift functions.
and corresponding pragma Import's for all five shift functions. Note that in
using these provided shift operations, shifts performed on negative numbers
will result in modification of the sign bit.
@node Source_Location,,Shifts and Rotates,Intrinsic Subprograms
@anchor{gnat_rm/intrinsic_subprograms source-location}@anchor{271}@anchor{gnat_rm/intrinsic_subprograms id13}@anchor{272}

View File

@ -4815,13 +4815,23 @@ package body Sem_Eval is
if Op = N_Op_Shift_Left then
Check_Elab_Call;
-- Fold Shift_Left (X, Y) by computing (X * 2**Y) rem modulus
declare
Modulus : Uint;
begin
if Is_Modular_Integer_Type (Typ) then
Modulus := Einfo.Modulus (Typ);
else
Modulus := Uint_2 ** RM_Size (Typ);
end if;
Fold_Uint
(N,
(Expr_Value (Left) * (Uint_2 ** Expr_Value (Right)))
rem Modulus (Typ),
Static => Static);
-- Fold Shift_Left (X, Y) by computing (X * 2**Y) rem modulus
Fold_Uint
(N,
(Expr_Value (Left) * (Uint_2 ** Expr_Value (Right)))
rem Modulus,
Static => Static);
end;
elsif Op = N_Op_Shift_Right then
Check_Elab_Call;