decl.c (components_need_strict_alignment): New.
authorEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 23 Nov 2012 10:42:50 +0000 (10:42 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 23 Nov 2012 10:42:50 +0000 (10:42 +0000)
* gcc-interface/decl.c (components_need_strict_alignment): New.
(components_to_record): Do not pack the variants if one of the fields
needs strict alignment.  Likewise for the variant part as a whole.
Specify the position of the variants even if the size isn't specified,
but do not specify the size of the variant part in this case.

From-SVN: r193750

gcc/ada/ChangeLog
gcc/ada/gcc-interface/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/discr39.adb [new file with mode: 0644]

index 9b5eabdcc678f7b6f91769c521c1187da6d308a1..b8359188efe0c72734fdd293d8073660fe768f92 100644 (file)
@@ -1,8 +1,15 @@
+2012-11-23  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc-interface/decl.c (components_need_strict_alignment): New.
+       (components_to_record): Do not pack the variants if one of the fields
+       needs strict alignment.  Likewise for the variant part as a whole.
+       Specify the position of the variants even if the size isn't specified,
+       but do not specify the size of the variant part in this case.
+
 2012-11-20  Diego Novillo  <dnovillo@google.com>
            Jakub Jelinek  <jakub@redhat.com>
 
-       * gcc-interface/decl.c: Replace all vec<T,A>()
-       initializers with vNULL.
+       * gcc-interface/decl.c: Replace all vec<T,A>() initializers with vNULL.
 
 2012-11-18  Eric Botcazou  <ebotcazou@adacore.com>
 
index 88afccfb20d5485849f44b0ebe5f5de73477e965..a5205ceeb66e63bbd89cb3e1d2076fd6670334a0 100644 (file)
@@ -6650,6 +6650,30 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed,
   return gnu_field;
 }
 \f
+/* Return true if at least one member of COMPONENT_LIST needs strict
+   alignment.  */
+
+static bool
+components_need_strict_alignment (Node_Id component_list)
+{
+  Node_Id component_decl;
+
+  for (component_decl = First_Non_Pragma (Component_Items (component_list));
+       Present (component_decl);
+       component_decl = Next_Non_Pragma (component_decl))
+    {
+      Entity_Id gnat_field = Defining_Entity (component_decl);
+
+      if (Is_Aliased (gnat_field))
+       return True;
+
+      if (Strict_Alignment (Etype (gnat_field)))
+       return True;
+    }
+
+  return False;
+}
+
 /* Return true if TYPE is a type with variable size or a padding type with a
    field of variable size or a record that has a field with such a type.  */
 
@@ -6880,6 +6904,7 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
                       "XVN");
       tree gnu_union_type, gnu_union_name;
       tree this_first_free_pos, gnu_variant_list = NULL_TREE;
+      bool union_field_needs_strict_alignment = false;
 
       if (TREE_CODE (gnu_name) == TYPE_DECL)
        gnu_name = DECL_NAME (gnu_name);
@@ -6980,8 +7005,18 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
          else
            {
              /* Deal with packedness like in gnat_to_gnu_field.  */
-             int field_packed
-               = adjust_packed (gnu_variant_type, gnu_record_type, packed);
+             bool field_needs_strict_alignment
+               = components_need_strict_alignment (Component_List (variant));
+             int field_packed;
+
+             if (field_needs_strict_alignment)
+               {
+                 field_packed = 0;
+                 union_field_needs_strict_alignment = true;
+               }
+             else
+               field_packed
+                 = adjust_packed (gnu_variant_type, gnu_record_type, packed);
 
              /* Finalize the record type now.  We used to throw away
                 empty records but we no longer do that because we need
@@ -6997,8 +7032,7 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
                                     gnu_union_type,
                                     all_rep_and_size
                                     ? TYPE_SIZE (gnu_variant_type) : 0,
-                                    all_rep_and_size
-                                    ? bitsize_zero_node : 0,
+                                    all_rep ? bitsize_zero_node : 0,
                                     field_packed, 0);
 
              DECL_INTERNAL_P (gnu_field) = 1;
@@ -7041,12 +7075,16 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
                            NULL, true, debug_info, gnat_component_list);
 
          /* Deal with packedness like in gnat_to_gnu_field.  */
-         union_field_packed
-           = adjust_packed (gnu_union_type, gnu_record_type, packed);
+         if (union_field_needs_strict_alignment)
+           union_field_packed = 0;
+         else
+           union_field_packed
+             = adjust_packed (gnu_union_type, gnu_record_type, packed);
 
          gnu_variant_part
            = create_field_decl (gnu_var_name, gnu_union_type, gnu_record_type,
-                                all_rep ? TYPE_SIZE (gnu_union_type) : 0,
+                                all_rep_and_size
+                                ? TYPE_SIZE (gnu_union_type) : 0,
                                 all_rep || this_first_free_pos
                                 ? bitsize_zero_node : 0,
                                 union_field_packed, 0);
index 1f0988faac804f2ff1f09923d59f50080d7059c1..7bc16ad3faee3edd1bdd2261bed82be58c7d7522 100644 (file)
@@ -1,3 +1,7 @@
+2012-11-23  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/discr39.adb: New test.
+
 2012-11-23  Georg-Johann Lay  <avr@gjlay.de>
 
        PR testsuite/52641
diff --git a/gcc/testsuite/gnat.dg/discr39.adb b/gcc/testsuite/gnat.dg/discr39.adb
new file mode 100644 (file)
index 0000000..1ffb972
--- /dev/null
@@ -0,0 +1,22 @@
+-- { dg-do run }
+
+with System.Storage_Elements; use System.Storage_Elements;
+
+procedure Discr39 is
+
+  type Rec (Has_Src : Boolean) is record
+     case Has_Src is
+        when True  => Src : aliased Integer;
+        when False => null;
+     end case;
+  end record;
+  pragma Pack(Rec);
+  for Rec'Alignment use Integer'Alignment;
+
+  R : Rec (Has_Src => True);
+
+begin
+  if R.Src'Address mod Integer'Alignment /= 0 then
+     raise Program_Error;
+  end if;
+end;