diff options
-rw-r--r-- | gcc/ada/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/ada/gcc-interface/decl.c | 23 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/pack19.adb | 56 |
4 files changed, 88 insertions, 0 deletions
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 504f358..f9d6e31 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -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. diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index ee76a9d..a80d1a9 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 912b117..3fe3212 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..601039a --- /dev/null +++ b/gcc/testsuite/gnat.dg/pack19.adb @@ -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; |