diff mbox

[Ada] Incorrect handling of type conversion with endianness change

Message ID 20130411125919.GA9683@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet April 11, 2013, 12:59 p.m. UTC
This change fixes an oversight in the predicate that determines whether two
composite types have the same representation (difference of scalar storage
order was ignored, causing the compiler to incorrectly omit a per-component
assignment in this case).

The following test case must compile and execute as shown:

$ gnatmake conv_endianness
$ ./conv_endianness
X_L = (S => 12345, C => 'a')
X_H = (S => 23456, C => 'b')
X_H = (S => 12345, C => 'a')

with System; use System;
with Ada.Text_IO; use Ada.Text_IO;

procedure Conv_Endianness is
   type Short is mod 2**16;

   type R_L is record
      S : Short;
      C : Character;
   end record;
   for R_L'Bit_Order use Low_Order_First;
   for R_L'Scalar_Storage_Order use Low_Order_First;
   for R_L use record
      S at 0 range 0 .. 15;
      C at 2 range 0 .. 7;
   end record;

   type R_H is new R_L;
   for R_H'Bit_Order use High_Order_First;
   for R_H'Scalar_Storage_Order use High_Order_First;
   for R_H use record
      S at 0 range 0 .. 15;
      C at 2 range 0 .. 7;
   end record;

   procedure Dump (Name : String; S : Short; C : Character) is
   begin
      Put_Line (Name & " = (S =>" & S'Img & ", C => '" & C & "')");
   end Dump;

   X_L : R_L;
   X_H : R_H;
begin
   X_L.S := 12345;
   X_L.C := 'a';
   Dump ("X_L", X_L.S, X_L.C);

   X_H.S := 23456;
   X_H.C := 'b';
   Dump ("X_H", X_H.S, X_H.C);

   X_H := R_H (X_L);
   Dump ("X_H", X_H.S, X_H.C);

end Conv_Endianness;

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

2013-04-11  Thomas Quinot  <quinot@adacore.com>

	* sem_ch13.adb (Same_Representation): Two types with different scalar
	storage order never have the same representation.
diff mbox

Patch

Index: sem_ch13.adb
===================================================================
--- sem_ch13.adb	(revision 197781)
+++ sem_ch13.adb	(working copy)
@@ -9448,12 +9448,16 @@ 
          return False;
       end if;
 
-      --  Representations are different if component alignments differ
+      --  Representations are different if component alignments or scalar
+      --  storage orders differ.
 
       if (Is_Record_Type (T1) or else Is_Array_Type (T1))
         and then
          (Is_Record_Type (T2) or else Is_Array_Type (T2))
-        and then Component_Alignment (T1) /= Component_Alignment (T2)
+        and then
+         (Component_Alignment (T1) /= Component_Alignment (T2)
+            or else
+          Reverse_Storage_Order (T1) /= Reverse_Storage_Order (T2))
       then
          return False;
       end if;
@@ -9530,7 +9534,7 @@ 
 
                function Same_Rep return Boolean;
                --  CD1 and CD2 are either components or discriminants. This
-               --  function tests whether the two have the same representation
+               --  function tests whether they have the same representation.
 
                --------------
                -- Same_Rep --
@@ -9540,8 +9544,11 @@ 
                begin
                   if No (Component_Clause (CD1)) then
                      return No (Component_Clause (CD2));
+                  else
+                     --  Note: at this point, component clauses have been
+                     --  normalized to the default bit order, so that the
+                     --  comparison of Component_Bit_Offsets is meaningful.
 
-                  else
                      return
                         Present (Component_Clause (CD2))
                           and then