From 29e100b31a77dcee0c57f7438e3a71007b18b52b Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 23 Nov 2012 10:42:50 +0000 Subject: [PATCH] decl.c (components_need_strict_alignment): New. * 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 | 11 +++++++-- gcc/ada/gcc-interface/decl.c | 52 +++++++++++++++++++++++++++++++++------ gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gnat.dg/discr39.adb | 22 +++++++++++++++++ 4 files changed, 80 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/discr39.adb diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 9b5eabd..b835918 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,8 +1,15 @@ +2012-11-23 Eric Botcazou + + * 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 Jakub Jelinek - * gcc-interface/decl.c: Replace all vec() - initializers with vNULL. + * gcc-interface/decl.c: Replace all vec() initializers with vNULL. 2012-11-18 Eric Botcazou diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 88afccf..a5205ce 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -6650,6 +6650,30 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed, return gnu_field; } +/* 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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1f0988f..7bc16ad 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-11-23 Eric Botcazou + + * gnat.dg/discr39.adb: New test. + 2012-11-23 Georg-Johann Lay PR testsuite/52641 diff --git a/gcc/testsuite/gnat.dg/discr39.adb b/gcc/testsuite/gnat.dg/discr39.adb new file mode 100644 index 0000000..1ffb972 --- /dev/null +++ b/gcc/testsuite/gnat.dg/discr39.adb @@ -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; -- 2.7.4