The parameter type for Shift_Left (etc.) intrinsics is required to have 'Size = 8, 16, 32, or 64 bits, but the compiler failed to check this rule. This patch checks the rule.
The following test should get a compile-time error. gnatmake -f -q shift_test.adb shift_test.adb:4:27: first argument for shift must have size 8, 16, 32 or 64 shift_test.adb:5:29: incorrect intrinsic subprogram, see spec gnatmake: "shift_test.adb" compilation error with Text_IO; use Text_IO; procedure Shift_Test is type M is mod 2**12; -- Illegal! function Shift_Left(X: M; Amount: Natural) return M; pragma Import(Intrinsic, Shift_Left); X : M := M'Last; begin Put_Line(M'Size'Img); for Amount in Natural range 0..100 loop Put_Line(Shift_Left(X, Amount)'Img); end loop; end Shift_Test; Tested on x86_64-pc-linux-gnu, committed on trunk 2012-01-10 Bob Duff <d...@adacore.com> * sem_intr.adb (Check_Shift): Use RM_Size instead of Esize, when checking that the 'Size is correct. If the type is "mod 2**12", for example, it's illegal, but Esize is the 'Object_Size, which will be something like 16 or 32, so the error ('Size = 12) was not detected. * gnat_rm.texi: Improve documentation of shift and rotate intrinsics.
Index: gnat_rm.texi =================================================================== --- gnat_rm.texi (revision 183051) +++ gnat_rm.texi (working copy) @@ -10385,11 +10385,7 @@ * Exception_Name:: * File:: * Line:: -* Rotate_Left:: -* Rotate_Right:: -* Shift_Left:: -* Shift_Right:: -* Shift_Right_Arithmetic:: +* Shifts and Rotates:: * Source_Location:: @end menu @@ -10506,62 +10502,36 @@ @code{GNAT.Source_Info.Line} to obtain the number of the current source line. -@node Rotate_Left -@section Rotate_Left +@node Shifts and Rotates +@section Shifts and Rotates +@cindex Shift_Left +@cindex Shift_Right +@cindex Shift_Right_Arithmetic @cindex Rotate_Left +@cindex Rotate_Right @noindent -In standard Ada, the @code{Rotate_Left} function is available only +In standard Ada, the shift and rotate functions are available only for the predefined modular types in package @code{Interfaces}. However, in -GNAT it is possible to define a Rotate_Left function for a user -defined modular type or any signed integer type as in this example: +GNAT it is possible to define these functions for any integer +type (signed or modular), as in this example: @smallexample @c ada function Shift_Left - (Value : My_Modular_Type; + (Value : T; Amount : Natural) - return My_Modular_Type; + return T; @end smallexample @noindent -The requirements are that the profile be exactly as in the example -above. The only modifications allowed are in the formal parameter -names, and in the type of @code{Value} and the return type, which -must be the same, and must be either a signed integer type, or -a modular integer type with a binary modulus, and the size must -be 8. 16, 32 or 64 bits. +The function name must be one of +Shift_Left, Shift_Right, Shift_Right_Arithmetic, Rotate_Left, or +Rotate_Right. T must be an integer type. T'Size must be +8, 16, 32 or 64 bits; if T is modular, the modulus +must be 2**8, 2**16, 2**32 or 2**64. +The result type must be the same as the type of @code{Value}. +The shift amount must be Natural. +The formal parameter names can be anything. -@node Rotate_Right -@section Rotate_Right -@cindex Rotate_Right -@noindent -A @code{Rotate_Right} function can be defined for any user defined -binary modular integer type, or signed integer type, as described -above for @code{Rotate_Left}. - -@node Shift_Left -@section Shift_Left -@cindex Shift_Left -@noindent -A @code{Shift_Left} function can be defined for any user defined -binary modular integer type, or signed integer type, as described -above for @code{Rotate_Left}. - -@node Shift_Right -@section Shift_Right -@cindex Shift_Right -@noindent -A @code{Shift_Right} function can be defined for any user defined -binary modular integer type, or signed integer type, as described -above for @code{Rotate_Left}. - -@node Shift_Right_Arithmetic -@section Shift_Right_Arithmetic -@cindex Shift_Right_Arithmetic -@noindent -A @code{Shift_Right_Arithmetic} function can be defined for any user -defined binary modular integer type, or signed integer type, as described -above for @code{Rotate_Left}. - @node Source_Location @section Source_Location @cindex Source_Location Index: sem_intr.adb =================================================================== --- sem_intr.adb (revision 183051) +++ sem_intr.adb (working copy) @@ -455,12 +455,14 @@ return; end if; - Size := UI_To_Int (Esize (Typ1)); + -- type'Size (not 'Object_Size!) must be one of the allowed values - if Size /= 8 - and then Size /= 16 - and then Size /= 32 - and then Size /= 64 + Size := UI_To_Int (RM_Size (Typ1)); + + if Size /= 8 and then + Size /= 16 and then + Size /= 32 and then + Size /= 64 then Errint ("first argument for shift must have size 8, 16, 32 or 64", @@ -469,8 +471,7 @@ elsif Non_Binary_Modulus (Typ1) then Errint - ("shifts not allowed for non-binary modular types", - Ptyp1, N); + ("shifts not allowed for non-binary modular types", Ptyp1, N); elsif Etype (Arg1) /= Etype (E) then Errint