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

Reply via email to