Complex types (mathematical sense) weren't correctly handled, in particular 
they were reversed as a whole instead of piecewise so a big-endian complex 
field on a little-endian target didn't have the same representation in memory 
as on a big-endian target.

Tested on x86_64-suse-linux. applied on the branch.


        * expmed.c (flip_storage_order): Deal with complex modes specially.
        Use the precision of the mode instead of its size to find an integral
        counterpart.
        (extract_bit_field_1): Deal with complex modes specially.
        * expr.c (read_complex_part): Make public.
        (get_inner_reference): Call reverse_storage_order_for_component_p.
        (expand_expr_real_1): Allow early exit for CONCATs as well.
        * expr.h (read_complex_part): Declare.
        * tree-dfa.c (get_ref_base_and_extent): Call
        reverse_storage_order_for_component_p.
        * tree.h (reverse_storage_order_for_component_p): New inline predicate.
ada/
        * freeze.adb (Check_Component_Storage_Order): Skip a record component
        if it has Complex_Representation.
        (Freeze_Record_Type): If the type has Complex_Representation, skip
        the regular treatment of Scalar_Storage_Order attribute and instead
        issue a warning if it is present.
testsuite/
        * c-c++-common/sso/init13.h: New helper.
        * c-c++-common/sso/p13.c: New test.
        * c-c++-common/sso/q13.c: Likewise.
        * c-c++-common/sso/t13.c: Likewise.
        * gnat.dg/sso/init13.ads: New helper.
        * gnat.dg/sso/p13.adb: New test.
        * gnat.dg/sso/q13.adb: Likewise.
        * gnat.dg/sso/t13.adb: Likewise.

-- 
Eric Botcazou
Index: tree.h
===================================================================
--- tree.h	(revision 225434)
+++ tree.h	(working copy)
@@ -4306,23 +4306,56 @@ handled_component_p (const_tree t)
     }
 }
 
-/* Return true if REF is a storage order barrier, i.e. a VIEW_CONVERT_EXPR
+/* Return true T is a component with reverse storage order.  */
+
+static inline bool
+reverse_storage_order_for_component_p (tree t)
+{
+  /* The storage order only applies to scalar components.  */
+  if (AGGREGATE_TYPE_P (TREE_TYPE (t)))
+    return false;
+
+  if (TREE_CODE (t) == REALPART_EXPR || TREE_CODE (t) == IMAGPART_EXPR)
+    t = TREE_OPERAND (t, 0);
+
+  switch (TREE_CODE (t))
+    {
+    case ARRAY_REF:
+    case COMPONENT_REF:
+      /* ??? Fortran can take COMPONENT_REF of a void type.  */
+      return !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (t, 0)))
+	     && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (t, 0)));
+
+    case BIT_FIELD_REF:
+    case MEM_REF:
+      return REF_REVERSE_STORAGE_ORDER (t);
+
+    case ARRAY_RANGE_REF:
+    case VIEW_CONVERT_EXPR:
+    default:
+      return false;
+    }
+
+  gcc_unreachable ();
+}
+
+/* Return true if T is a storage order barrier, i.e. a VIEW_CONVERT_EXPR
    that can modify the storage order of objects.  Note that, even if the
    TYPE_REVERSE_STORAGE_ORDER flag is set on both the inner type and the
    outer type, a VIEW_CONVERT_EXPR can modify the storage order because
    it can change the partition of the aggregate object into scalars.  */
 
 static inline bool
-storage_order_barrier_p (const_tree ref)
+storage_order_barrier_p (const_tree t)
 {
-  if (TREE_CODE (ref) != VIEW_CONVERT_EXPR)
+  if (TREE_CODE (t) != VIEW_CONVERT_EXPR)
     return false;
 
-  if (AGGREGATE_TYPE_P (TREE_TYPE (ref))
-      && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (ref)))
+  if (AGGREGATE_TYPE_P (TREE_TYPE (t))
+      && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (t)))
     return true;
 
-  tree op = TREE_OPERAND (ref, 0);
+  tree op = TREE_OPERAND (t, 0);
 
   if (AGGREGATE_TYPE_P (TREE_TYPE (op))
       && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (op)))
Index: testsuite/gnat.dg/sso/q13.adb
===================================================================
--- testsuite/gnat.dg/sso/q13.adb	(revision 0)
+++ testsuite/gnat.dg/sso/q13.adb	(revision 0)
@@ -0,0 +1,53 @@
+-- { dg-do run }
+
+with Init13; use Init13;
+with Ada.Numerics; use Ada.Numerics;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure Q13 is
+
+  A1 : R1 := My_R1;
+  B1 : R1 := My_R1;
+
+  A2 : R2 := My_R2;
+  B2 : R2 := My_R2;
+
+begin
+  Put ("A1 :");
+  Dump (A1'Address, R1'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "A1 : db 0f 49 40 db 0f 49 c0\n" }
+
+  Put ("B1 :");
+  Dump (B1'Address, R1'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "B1 : db 0f 49 40 db 0f 49 c0\n" }
+
+  Put ("A2 :");
+  Dump (A2'Address, R2'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "A2 : 40 49 0f db c0 49 0f db\n" }
+
+  Put ("B2 :");
+  Dump (B2'Address, R2'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "B2 : 40 49 0f db c0 49 0f db\n" }
+
+  if A1.F /= B1.F then
+    raise Program_Error;
+  end if;
+
+  if A1.F /= (Pi, -Pi) then
+    raise Program_Error;
+  end if;
+
+  if A2.F /= B2.F then
+    raise Program_Error;
+  end if;
+
+  if A2.F /= (Pi, -Pi) then
+    raise Program_Error;
+  end if;
+
+end;
Index: testsuite/gnat.dg/sso/init13.ads
===================================================================
--- testsuite/gnat.dg/sso/init13.ads	(revision 0)
+++ testsuite/gnat.dg/sso/init13.ads	(revision 0)
@@ -0,0 +1,33 @@
+with Ada.Numerics; use Ada.Numerics;
+with System;
+
+package Init13 is
+
+  type Complex is record
+    R : Float;
+    I : Float;
+  end record;
+  pragma Complex_Representation (Complex);
+
+  type R1 is record
+    F : Complex;
+  end record;
+  for R1'Bit_Order use System.Low_Order_First;
+  for R1'Scalar_Storage_Order use System.Low_Order_First;
+  for R1 use record
+    F at 0 range 0 .. 63;
+  end record;
+
+  type R2 is record
+    F : Complex;
+  end record;
+  for R2'Bit_Order use System.High_Order_First;
+  for R2'Scalar_Storage_Order use System.High_Order_First;
+  for R2 use record
+    F at 0 range 0 .. 63;
+  end record;
+
+  My_R1 : constant R1 := (F => (Pi, -Pi));
+  My_R2 : constant R2 := (F => (Pi, -Pi));
+
+end Init13;
Index: testsuite/gnat.dg/sso/p13.adb
===================================================================
--- testsuite/gnat.dg/sso/p13.adb	(revision 0)
+++ testsuite/gnat.dg/sso/p13.adb	(revision 0)
@@ -0,0 +1,63 @@
+-- { dg-do run }
+
+with Init13; use Init13;
+with Ada.Numerics; use Ada.Numerics;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure P13 is
+
+  Local_R1 : R1;
+  Local_R2 : R2;
+
+begin
+  Put ("My_R1    :");
+  Dump (My_R1'Address, R1'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "My_R1    : db 0f 49 40 db 0f 49 c0\n" }
+
+  Put ("My_R2    :");
+  Dump (My_R2'Address, R2'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "My_R2    : 40 49 0f db c0 49 0f db\n" }
+
+  Local_R1 := My_R1;
+  Put ("Local_R1 :");
+  Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" }
+
+  Local_R2 := My_R2;
+  Put ("Local_R2 :");
+  Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" }
+
+  Local_R1.F := (Pi, -Pi);
+
+  Put ("Local_R1 :");
+  Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" }
+
+  Local_R2.F := (Pi, -Pi);
+
+  Put ("Local_R2 :");
+  Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" }
+
+  Local_R1.F := Local_R2.F;
+
+  Put ("Local_R1 :");
+  Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" }
+
+  Local_R2.F := Local_R1.F;
+
+  Put ("Local_R2 :");
+  Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" }
+end;
Index: testsuite/gnat.dg/sso/t13.adb
===================================================================
--- testsuite/gnat.dg/sso/t13.adb	(revision 0)
+++ testsuite/gnat.dg/sso/t13.adb	(revision 0)
@@ -0,0 +1,56 @@
+-- { dg-do run }
+
+with Init13; use Init13;
+with Ada.Numerics; use Ada.Numerics;
+with Text_IO; use Text_IO;
+with Dump;
+
+procedure T13 is
+
+  Local_R1 : R1;
+  Local_R2 : R2;
+
+begin
+  Local_R1.F := (My_R1.F.R + 1.0, My_R1.F.I + 1.0);
+
+  Put ("Local_R1 :");
+  Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "Local_R1 : ee 87 84 40 db 0f 09 c0\n" }
+
+  Local_R2.F := (My_R2.F.R + 1.0, My_R2.F.I + 1.0);
+
+  Put ("Local_R2 :");
+  Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "Local_R2 : 40 84 87 ee c0 09 0f db\n" }
+
+  Local_R1.F := (Pi, -Pi);
+
+  Put ("Local_R1 :");
+  Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" }
+
+  Local_R2.F := (Pi, -Pi);
+
+  Put ("Local_R2 :");
+  Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" }
+
+  Local_R1.F := (Local_R1.F.R + 1.0, Local_R1.F.I + 1.0);
+
+  Put ("Local_R1 :");
+  Dump (Local_R1'Address, R1'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "Local_R1 : ee 87 84 40 db 0f 09 c0\n" }
+
+  Local_R2.F := (Local_R2.F.R + 1.0, Local_R2.F.I + 1.0);
+
+  Put ("Local_R2 :");
+  Dump (Local_R2'Address, R2'Max_Size_In_Storage_Elements);
+  New_Line;
+  -- { dg-output "Local_R2 : 40 84 87 ee c0 09 0f db\n" }
+
+end;
Index: testsuite/c-c++-common/sso/p13.c
===================================================================
--- testsuite/c-c++-common/sso/p13.c	(revision 0)
+++ testsuite/c-c++-common/sso/p13.c	(revision 0)
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init13.h"
+#include "dump.h"
+
+int main (void)
+{
+  struct R1 Local_R1;
+  struct R2 Local_R2;
+
+  put ("My_R1    :");
+  dump (&My_R1, sizeof (struct R1));
+  new_line ();
+  /* { dg-output "My_R1    : db 0f 49 40 db 0f 49 c0\n" } */
+
+  put ("My_R2    :");
+  dump (&My_R2, sizeof (struct R2));
+  new_line ();
+  /* { dg-output "My_R2    : 40 49 0f db c0 49 0f db\n" } */
+
+  Local_R1 = My_R1;
+  put ("Local_R1 :");
+  dump (&Local_R1, sizeof (struct R1));
+  new_line ();
+  /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
+
+  Local_R2 = My_R2;
+  put ("Local_R2 :");
+  dump (&Local_R2, sizeof (struct R2));
+  new_line ();
+  /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
+
+  Local_R1.F = Pi - Pi * I;
+
+  put ("Local_R1 :");
+  dump (&Local_R1, sizeof (struct R1));
+  new_line ();
+  /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
+
+  Local_R2.F = Pi - Pi * I;
+
+  put ("Local_R2 :");
+  dump (&Local_R2, sizeof (struct R2));
+  new_line ();
+  /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
+
+  Local_R1.F = Local_R2.F;
+
+  put ("Local_R1 :");
+  dump (&Local_R1, sizeof (struct R1));
+  new_line ();
+  /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
+
+  Local_R2.F = Local_R1.F;
+
+  put ("Local_R2 :");
+  dump (&Local_R2, sizeof (struct R2));
+  new_line ();
+  /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
+
+  return 0;
+}
Index: testsuite/c-c++-common/sso/q13.c
===================================================================
--- testsuite/c-c++-common/sso/q13.c	(revision 0)
+++ testsuite/c-c++-common/sso/q13.c	(revision 0)
@@ -0,0 +1,50 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init13.h"
+#include "dump.h"
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort (void);
+
+int main (void)
+{
+  struct R1 A1 = My_R1;
+  struct R1 B1 = My_R1;
+
+  struct R2 A2 = My_R2;
+  struct R2 B2 = My_R2;
+
+  put ("A1 :");
+  dump (&A1, sizeof (struct R1));
+  new_line ();
+  /* { dg-output "A1 : db 0f 49 40 db 0f 49 c0\n" } */
+
+  put ("B1 :");
+  dump (&B1, sizeof (struct R1));
+  new_line ();
+  /* { dg-output "B1 : db 0f 49 40 db 0f 49 c0\n" } */
+
+  put ("A2 :");
+  dump (&A2, sizeof (struct R2));
+  new_line ();
+  /* { dg-output "A2 : 40 49 0f db c0 49 0f db\n" } */
+
+  put ("B2 :");
+  dump (&B2, sizeof (struct R2));
+  new_line ();
+  /* { dg-output "B2 : 40 49 0f db c0 49 0f db\n" } */
+
+  if (A1.F != B1.F) abort ();
+
+  if (A1.F != Pi - Pi * I) abort ();
+
+  if (A2.F != B2.F) abort ();
+
+  if (A2.F != Pi - Pi * I) abort ();
+
+  return 0;
+}
Index: testsuite/c-c++-common/sso/t13.c
===================================================================
--- testsuite/c-c++-common/sso/t13.c	(revision 0)
+++ testsuite/c-c++-common/sso/t13.c	(revision 0)
@@ -0,0 +1,56 @@
+/* { dg-do run } */
+
+#include <stdio.h>
+
+#include "init13.h"
+#include "dump.h"
+
+int main (void)
+{
+  struct R1 Local_R1;
+  struct R2 Local_R2;
+
+  Local_R1.F = My_R1.F + (1.0f + 1.0f * I);
+
+  put ("Local_R1 :");
+  dump (&Local_R1, sizeof (struct R1));
+  new_line ();
+  /* { dg-output "Local_R1 : ee 87 84 40 db 0f 09 c0\n" } */
+
+  Local_R2.F = My_R2.F + (1.0f + 1.0f * I);
+
+  put ("Local_R2 :");
+  dump (&Local_R2, sizeof (struct R2));
+  new_line ();
+  /* { dg-output "Local_R2 : 40 84 87 ee c0 09 0f db\n" } */
+
+  Local_R1.F = Pi - Pi * I;
+
+  put ("Local_R1 :");
+  dump (&Local_R1, sizeof (struct R1));
+  new_line ();
+  /* { dg-output "Local_R1 : db 0f 49 40 db 0f 49 c0\n" } */
+
+  Local_R2.F = Pi - Pi * I;
+
+  put ("Local_R2 :");
+  dump (&Local_R2, sizeof (struct R2));
+  new_line ();
+  /* { dg-output "Local_R2 : 40 49 0f db c0 49 0f db\n" } */
+
+  Local_R1.F = Local_R1.F + (1.0f + 1.0f * I);
+
+  put ("Local_R1 :");
+  dump (&Local_R1, sizeof (struct R1));
+  new_line ();
+  /* { dg-output "Local_R1 : ee 87 84 40 db 0f 09 c0\n" } */
+
+  Local_R2.F = Local_R2.F + (1.0f + 1.0f * I);
+
+  put ("Local_R2 :");
+  dump (&Local_R2, sizeof (struct R2));
+  new_line ();
+  /* { dg-output "Local_R2 : 40 84 87 ee c0 09 0f db\n" } */
+
+  return 0;
+}
Index: testsuite/c-c++-common/sso/init13.h
===================================================================
--- testsuite/c-c++-common/sso/init13.h	(revision 0)
+++ testsuite/c-c++-common/sso/init13.h	(revision 0)
@@ -0,0 +1,15 @@
+#define I (__extension__ 1.0iF)
+#define Pi 3.1415927f
+
+struct __attribute__((scalar_storage_order("little-endian"))) R1
+{
+  _Complex float F;
+};
+
+struct __attribute__((scalar_storage_order("big-endian"))) R2
+{
+  _Complex float F;
+};
+
+struct R1 My_R1 = { Pi - Pi * I };
+struct R2 My_R2 = { Pi - Pi * I };
Index: expr.c
===================================================================
--- expr.c	(revision 225795)
+++ expr.c	(working copy)
@@ -3047,7 +3047,7 @@ write_complex_part (rtx cplx, rtx val, b
 /* Extract one of the components of the complex value CPLX.  Extract the
    real part if IMAG_P is false, and the imaginary part if it's true.  */
 
-static rtx
+rtx
 read_complex_part (rtx cplx, bool imag_p)
 {
   machine_mode cmode, imode;
@@ -6889,18 +6889,12 @@ get_inner_reference (tree exp, HOST_WIDE
 	blkmode_bitfield = true;
 
       *punsignedp = DECL_UNSIGNED (field);
-      /* ??? Fortran can take COMPONENT_REF of a void type.  */
-      *preversep
-        = !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0)))
-	  && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (exp, 0)))
-	  && !AGGREGATE_TYPE_P (TREE_TYPE (exp));
     }
   else if (TREE_CODE (exp) == BIT_FIELD_REF)
     {
       size_tree = TREE_OPERAND (exp, 1);
       *punsignedp = (! INTEGRAL_TYPE_P (TREE_TYPE (exp))
 		     || TYPE_UNSIGNED (TREE_TYPE (exp)));
-      *preversep = REF_REVERSE_STORAGE_ORDER (exp);
 
       /* For vector types, with the correct size of access, use the mode of
 	 inner type.  */
@@ -6913,12 +6907,6 @@ get_inner_reference (tree exp, HOST_WIDE
     {
       mode = TYPE_MODE (TREE_TYPE (exp));
       *punsignedp = TYPE_UNSIGNED (TREE_TYPE (exp));
-      *preversep
-	= ((TREE_CODE (exp) == ARRAY_REF
-	    && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (exp, 0))))
-	   || (TREE_CODE (exp) == MEM_REF
-	       && REF_REVERSE_STORAGE_ORDER (exp)))
-	  && !AGGREGATE_TYPE_P (TREE_TYPE (exp));
 
       if (mode == BLKmode)
 	size_tree = TYPE_SIZE (TREE_TYPE (exp));
@@ -6934,6 +6922,8 @@ get_inner_reference (tree exp, HOST_WIDE
 	*pbitsize = tree_to_uhwi (size_tree);
     }
 
+  *preversep = reverse_storage_order_for_component_p (exp);
+
   /* Compute cumulative bit-offset for nested component-refs and array-refs,
      and find the ultimate containing object.  */
   while (1)
@@ -10182,9 +10172,12 @@ expand_expr_real_1 (tree exp, rtx target
 	if (GET_CODE (op0) == CONCAT && !must_force_mem)
 	  {
 	    if (bitpos == 0
-		&& bitsize == GET_MODE_BITSIZE (GET_MODE (op0))
-		&& !reversep)
-	      return op0;
+		&& bitsize == GET_MODE_BITSIZE (GET_MODE (op0)))
+	      {
+		if (reversep)
+		  op0 = flip_storage_order (GET_MODE (op0), op0);
+		return op0;
+	      }
 	    if (bitpos == 0
 		&& bitsize == GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0)))
 		&& bitsize)
Index: expr.h
===================================================================
--- expr.h	(revision 225434)
+++ expr.h	(working copy)
@@ -212,6 +212,7 @@ extern rtx_insn *emit_move_insn_1 (rtx,
 extern rtx_insn *emit_move_complex_push (machine_mode, rtx, rtx);
 extern rtx_insn *emit_move_complex_parts (rtx, rtx);
 extern void write_complex_part (rtx, rtx, bool);
+extern rtx read_complex_part (rtx, bool);
 extern rtx emit_move_resolve_push (machine_mode, rtx);
 
 /* Push a block of length SIZE (perhaps variable)
Index: ada/freeze.adb
===================================================================
--- ada/freeze.adb	(revision 225434)
+++ ada/freeze.adb	(working copy)
@@ -1196,9 +1196,14 @@ package body Freeze is
                      Attribute_Scalar_Storage_Order);
       Comp_ADC_Present := Present (Comp_ADC);
 
-      --  Case of record or array component: check storage order compatibility
-
-      if Is_Record_Type (Comp_Type) or else Is_Array_Type (Comp_Type) then
+      --  Case of record or array component: check storage order compatibility.
+      --  But, if the record has Complex_Representation, then it is treated as
+      --  a scalar in the back end so the storage order is irrelevant.
+
+      if (Is_Record_Type (Comp_Type)
+            and then not Has_Complex_Representation (Comp_Type))
+        or else Is_Array_Type (Comp_Type)
+      then
          Comp_SSO_Differs :=
            Reverse_Storage_Order (Encl_Type)
              /=
@@ -3958,61 +3963,73 @@ package body Freeze is
             Next_Entity (Comp);
          end loop;
 
-         --  Deal with default setting of reverse storage order
+         SSO_ADC := Get_Attribute_Definition_Clause
+                      (Rec, Attribute_Scalar_Storage_Order);
 
-         Set_SSO_From_Default (Rec);
+         --  If the record type has Complex_Representation, then it is treated
+         --  as a scalar in the back end so the storage order is irrelevant.
 
-         --  Check consistent attribute setting on component types
+         if Has_Complex_Representation (Rec) then
+            if Present (SSO_ADC) then
+               Error_Msg_N
+                  ("??storage order has no effect with "
+                   & "Complex_Representation", SSO_ADC);
+            end if;
 
-         SSO_ADC := Get_Attribute_Definition_Clause
-                      (Rec, Attribute_Scalar_Storage_Order);
+         else
+            --  Deal with default setting of reverse storage order
 
-         declare
-            Comp_ADC_Present : Boolean;
-         begin
-            Comp := First_Component (Rec);
-            while Present (Comp) loop
-               Check_Component_Storage_Order
-                 (Encl_Type        => Rec,
-                  Comp             => Comp,
-                  ADC              => SSO_ADC,
-                  Comp_ADC_Present => Comp_ADC_Present);
-               SSO_ADC_Component := SSO_ADC_Component or Comp_ADC_Present;
-               Next_Component (Comp);
-            end loop;
-         end;
+            Set_SSO_From_Default (Rec);
+
+            --  Check consistent attribute setting on component types
 
-         --  Now deal with reverse storage order/bit order issues
+            declare
+               Comp_ADC_Present : Boolean;
+            begin
+               Comp := First_Component (Rec);
+               while Present (Comp) loop
+                  Check_Component_Storage_Order
+                    (Encl_Type        => Rec,
+                     Comp             => Comp,
+                     ADC              => SSO_ADC,
+                     Comp_ADC_Present => Comp_ADC_Present);
+                  SSO_ADC_Component := SSO_ADC_Component or Comp_ADC_Present;
+                  Next_Component (Comp);
+               end loop;
+            end;
 
-         if Present (SSO_ADC) then
+            --  Now deal with reverse storage order/bit order issues
 
-            --  Check compatibility of Scalar_Storage_Order with Bit_Order, if
-            --  the former is specified.
+            if Present (SSO_ADC) then
 
-            if Reverse_Bit_Order (Rec) /= Reverse_Storage_Order (Rec) then
+               --  Check compatibility of Scalar_Storage_Order with Bit_Order,
+               --  if the former is specified.
 
-               --  Note: report error on Rec, not on SSO_ADC, as ADC may apply
-               --  to some ancestor type.
+               if Reverse_Bit_Order (Rec) /= Reverse_Storage_Order (Rec) then
 
-               Error_Msg_Sloc := Sloc (SSO_ADC);
-               Error_Msg_N
-                 ("scalar storage order for& specified# inconsistent with "
-                  & "bit order", Rec);
-            end if;
+                  --  Note: report error on Rec, not on SSO_ADC, as ADC may
+                  --  apply to some ancestor type.
 
-            --  Warn if there is an Scalar_Storage_Order attribute definition
-            --  clause but no component clause, no component that itself has
-            --  such an attribute definition, and no pragma Pack.
-
-            if not (Placed_Component
-                      or else
-                    SSO_ADC_Component
-                      or else
-                    Is_Packed (Rec))
-            then
-               Error_Msg_N
-                 ("??scalar storage order specified but no component clause",
-                  SSO_ADC);
+                  Error_Msg_Sloc := Sloc (SSO_ADC);
+                  Error_Msg_N
+                    ("scalar storage order for& specified# inconsistent with "
+                     & "bit order", Rec);
+               end if;
+
+               --  Warn if there is a Scalar_Storage_Order attribute definition
+               --  clause but no component clause, no component that itself has
+               --  such an attribute definition, and no pragma Pack.
+
+               if not (Placed_Component
+                         or else
+                       SSO_ADC_Component
+                         or else
+                       Is_Packed (Rec))
+               then
+                  Error_Msg_N
+                    ("??scalar storage order specified but no component "
+                     & "clause", SSO_ADC);
+               end if;
             end if;
          end if;
 
Index: expmed.c
===================================================================
--- expmed.c	(revision 225434)
+++ expmed.c	(working copy)
@@ -380,6 +380,17 @@ flip_storage_order (enum machine_mode mo
   if (mode == QImode)
     return x;
 
+  if (COMPLEX_MODE_P (mode))
+    {
+      rtx real = read_complex_part (x, false);
+      rtx imag = read_complex_part (x, true);
+
+      real = flip_storage_order (GET_MODE_INNER (mode), real);
+      imag = flip_storage_order (GET_MODE_INNER (mode), imag);
+
+      return gen_rtx_CONCAT (mode, real, imag);
+    }
+
   if (__builtin_expect (reverse_storage_order_supported < 0, 0))
     check_reverse_storage_order_support ();
 
@@ -391,8 +402,12 @@ flip_storage_order (enum machine_mode mo
 	  && __builtin_expect (reverse_float_storage_order_supported < 0, 0))
 	check_reverse_float_storage_order_support ();
 
-      int_mode = int_mode_for_mode (mode);
-      gcc_assert (int_mode != BLKmode);
+      int_mode = mode_for_size (GET_MODE_PRECISION (mode), MODE_INT, 0);
+      if (int_mode == BLKmode)
+	{
+	  sorry ("reverse storage order for %smode", GET_MODE_NAME (mode));
+	  return x;
+	}
       x = gen_lowpart (int_mode, x);
     }
 
@@ -1867,9 +1882,21 @@ extract_bit_field_1 (rtx str_rtx, unsign
   /* Should probably push op0 out to memory and then do a load.  */
   gcc_assert (int_mode != BLKmode);
 
-  target = extract_fixed_bit_field (int_mode, op0, bitsize, bitnum,
-				    target, unsignedp, reverse);
-  return convert_extracted_bit_field (target, mode, tmode, unsignedp);
+  target = extract_fixed_bit_field (int_mode, op0, bitsize, bitnum, target,
+				    unsignedp, reverse);
+
+  /* Complex values must be reversed piecewise, so we need to undo the global
+     reversal, convert to the complex mode and reverse again.  */
+  if (reverse && COMPLEX_MODE_P (tmode))
+    {
+      target = flip_storage_order (int_mode, target);
+      target = convert_extracted_bit_field (target, mode, tmode, unsignedp);
+      target = flip_storage_order (tmode, target);
+    }
+  else
+    target = convert_extracted_bit_field (target, mode, tmode, unsignedp);
+
+  return target;
 }
 
 /* Generate code to extract a byte-field from STR_RTX
Index: tree-dfa.c
===================================================================
--- tree-dfa.c	(revision 225434)
+++ tree-dfa.c	(working copy)
@@ -416,17 +416,9 @@ get_ref_base_and_extent (tree exp, HOST_
   /* First get the final access size and the storage order from just the
      outermost expression.  */
   if (TREE_CODE (exp) == COMPONENT_REF)
-    {
-      size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
-      *preverse
-	= TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (exp, 0)))
-	  && !AGGREGATE_TYPE_P (TREE_TYPE (exp));
-    }
+    size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
   else if (TREE_CODE (exp) == BIT_FIELD_REF)
-    {
-      size_tree = TREE_OPERAND (exp, 1);
-      *preverse = REF_REVERSE_STORAGE_ORDER (exp);
-    }
+    size_tree = TREE_OPERAND (exp, 1);
   else if (!VOID_TYPE_P (TREE_TYPE (exp)))
     {
       machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
@@ -434,20 +426,13 @@ get_ref_base_and_extent (tree exp, HOST_
 	size_tree = TYPE_SIZE (TREE_TYPE (exp));
       else
 	bitsize = int (GET_MODE_PRECISION (mode));
-      *preverse
-	= ((TREE_CODE (exp) == ARRAY_REF
-	    && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (TREE_OPERAND (exp, 0))))
-	   || (TREE_CODE (exp) == MEM_REF
-	       && REF_REVERSE_STORAGE_ORDER (exp)))
-	  && !AGGREGATE_TYPE_P (TREE_TYPE (exp));
     }
-  else
-    *preverse = false;
-
   if (size_tree != NULL_TREE
       && TREE_CODE (size_tree) == INTEGER_CST)
     bitsize = wi::to_offset (size_tree);
 
+  *preverse = reverse_storage_order_for_component_p (exp);
+
   /* Initially, maxsize is the same as the accessed element size.
      In the following it will only grow (or become -1).  */
   maxsize = bitsize;

Reply via email to