decl.c (components_to_record): Add specific handling for fields with zero size and...
authorEric Botcazou <ebotcazou@adacore.com>
Wed, 4 Dec 2013 11:27:25 +0000 (11:27 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Wed, 4 Dec 2013 11:27:25 +0000 (11:27 +0000)
* gcc-interface/decl.c (components_to_record): Add specific handling
for fields with zero size and no representation clause.

From-SVN: r205665

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

index 504f358..f9d6e31 100644 (file)
@@ -1,5 +1,10 @@
 2013-12-04  Eric Botcazou  <ebotcazou@adacore.com>
 
+       * gcc-interface/decl.c (components_to_record): Add specific handling
+       for fields with zero size and no representation clause.
+
+2013-12-04  Eric Botcazou  <ebotcazou@adacore.com>
+
        * gcc-interface/trans.c (Case_Statement_to_gnu): Do not push a binding
        level for each branch if this is a case expression in Ada 2012.
        (gnat_to_gnu) <case N_Expression_With_Actions>: Adjust comment.
index ee76a9d..a80d1a9 100644 (file)
@@ -6932,6 +6932,7 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
   tree gnu_rep_list = NULL_TREE;
   tree gnu_var_list = NULL_TREE;
   tree gnu_self_list = NULL_TREE;
+  tree gnu_zero_list = NULL_TREE;
 
   /* For each component referenced in a component declaration create a GCC
      field and add it to the list, skipping pragmas in the GNAT list.  */
@@ -7262,6 +7263,10 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
      to do this in a separate pass since we want to handle the discriminants
      but can't play with them until we've used them in debugging data above.
 
+     Similarly, pull out the fields with zero size and no rep clause, as they
+     would otherwise modify the layout and thus very likely run afoul of the
+     Ada semantics, which are different from those of C here.
+
      ??? If we reorder them, debugging information will be wrong but there is
      nothing that can be done about this at the moment.  */
   gnu_last = NULL_TREE;
@@ -7300,6 +7305,19 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
          continue;
        }
 
+      if (DECL_SIZE (gnu_field) && integer_zerop (DECL_SIZE (gnu_field)))
+       {
+         DECL_FIELD_OFFSET (gnu_field) = size_zero_node;
+         SET_DECL_OFFSET_ALIGN (gnu_field, BIGGEST_ALIGNMENT);
+         DECL_FIELD_BIT_OFFSET (gnu_field) = bitsize_zero_node;
+         if (field_is_aliased (gnu_field))
+           TYPE_ALIGN (gnu_record_type)
+             = MAX (TYPE_ALIGN (gnu_record_type),
+                    TYPE_ALIGN (TREE_TYPE (gnu_field)));
+         MOVE_FROM_FIELD_LIST_TO (gnu_zero_list);
+         continue;
+       }
+
       gnu_last = gnu_field;
     }
 
@@ -7392,6 +7410,11 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
   finish_record_type (gnu_record_type, gnu_field_list, layout_with_rep ? 1 : 0,
                      debug_info && !maybe_unused);
 
+  /* Chain the fields with zero size at the beginning of the field list.  */
+  if (gnu_zero_list)
+    TYPE_FIELDS (gnu_record_type)
+      = chainon (gnu_zero_list, TYPE_FIELDS (gnu_record_type));
+
   return (gnu_rep_list && !p_gnu_rep_list) || variants_have_rep;
 }
 \f
index 912b117..3fe3212 100644 (file)
@@ -1,3 +1,7 @@
+2013-12-04  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/pack19.adb: New test.
+
 2013-12-04  Jakub Jelinek  <jakub@redhat.com>
 
        PR rtl-optimization/58726
diff --git a/gcc/testsuite/gnat.dg/pack19.adb b/gcc/testsuite/gnat.dg/pack19.adb
new file mode 100644 (file)
index 0000000..601039a
--- /dev/null
@@ -0,0 +1,56 @@
+-- { dg-do run }
+
+procedure Pack19 is
+
+   subtype Always_False is Boolean range False .. False;
+
+   type Rec1 is record
+      B1 : Boolean;
+      B2 : Boolean;
+      B3 : Boolean;
+      B4 : Boolean;
+      B5 : Boolean;
+      B6 : Boolean;
+      B7 : Always_False;
+      B8 : Boolean;
+   end record;
+   pragma Pack (Rec1);
+
+   subtype Always_True is Boolean range True .. True;
+
+   type Rec2 is record
+      B1 : Boolean;
+      B2 : Boolean;
+      B3 : Boolean;
+      B4 : Boolean;
+      B5 : Boolean;
+      B6 : Boolean;
+      B7 : Always_True;
+      B8 : Boolean;
+   end record;
+   pragma Pack (Rec2);
+
+   R1 : Rec1 := (True, True, True, True, True, True, False, False);
+   R2 : Rec2 := (False, False, False, False, False, False, True, True);
+
+begin
+   R1.B8 := True;
+   if R1.B7 /= False then
+      raise Program_Error;
+   end if;
+
+   R1.B7 := False;
+   if R1.B7 /= False then
+      raise Program_Error;
+   end if;
+
+   R2.B8 := False;
+   if R2.B7 /= True then
+      raise Program_Error;
+   end if;
+
+   R2.B7 := True;
+   if R2.B7 /= True then
+      raise Program_Error;
+   end if;
+end;