This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Ada] Fix layout of variant record types with aliased components
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 23 Nov 2012 11:35:49 +0100
- Subject: [Ada] Fix layout of variant record types with aliased components
The layout of variant record types doesn't always guarantee the proper
alignment of aliased components if the record types are also packed.
Fixed thusly, tested on x86_64-suse-linux, applied on the mainline.
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-23 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/discr39.adb: New test.
--
Eric Botcazou
Index: gcc-interface/decl.c
===================================================================
--- gcc-interface/decl.c (revision 193720)
+++ gcc-interface/decl.c (working copy)
@@ -6650,6 +6650,30 @@ gnat_to_gnu_field (Entity_Id gnat_field,
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_ty
"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_ty
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_ty
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_ty
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);
-- { 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;