This is a regression present on the mainline and 4.7 branch. When a discriminated record type with a variant part has a partial representation clause, the compiler may drop some fields when it is laying out subtypes of this record type.
Tested on x86_64-suse-linux, applied on the mainline and 4.7 branch. 2012-07-19 Eric Botcazou <ebotca...@adacore.com> * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Record_Subtype>: Do not look up the REP part of the base type in advance. Deal with that of the variant types. (get_rep_part): Be prepared for record types with fields. 2012-07-19 Eric Botcazou <ebotca...@adacore.com> * gnat.dg/discr38.adb: New test. -- Eric Botcazou
Index: gcc-interface/decl.c =================================================================== --- gcc-interface/decl.c (revision 189607) +++ gcc-interface/decl.c (working copy) @@ -3287,9 +3287,6 @@ gnat_to_gnu_entity (Entity_Id gnat_entit else gnu_unpad_base_type = gnu_base_type; - /* Look for a REP part in the base type. */ - gnu_rep_part = get_rep_part (gnu_unpad_base_type); - /* Look for a variant part in the base type. */ gnu_variant_part = get_variant_part (gnu_unpad_base_type); @@ -3415,7 +3412,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entit and put the field either in the new type if there is a selected variant or in one of the new variants. */ if (gnu_context == gnu_unpad_base_type - || (gnu_rep_part + || ((gnu_rep_part = get_rep_part (gnu_unpad_base_type)) && gnu_context == TREE_TYPE (gnu_rep_part))) gnu_cont_type = gnu_type; else @@ -3425,7 +3422,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entit t = NULL_TREE; FOR_EACH_VEC_ELT (variant_desc, gnu_variant_list, i, v) - if (v->type == gnu_context) + if (gnu_context == v->type + || ((gnu_rep_part = get_rep_part (v->type)) + && gnu_context == TREE_TYPE (gnu_rep_part))) { t = v->type; break; @@ -8172,7 +8171,8 @@ get_rep_part (tree record_type) /* The REP part is the first field, internal, another record, and its name starts with an 'R'. */ - if (DECL_INTERNAL_P (field) + if (field + && DECL_INTERNAL_P (field) && TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE && IDENTIFIER_POINTER (DECL_NAME (field)) [0] == 'R') return field;
-- { dg-do compile } procedure Discr38 is type Enum is (OK, NOT_CONNECTED, DISCONNECTED, REQUEST_Q_EMPTY, SERVER_UNAVAILABLE, BUFFER_TOO_SMALL, NO_FREE_SLOT, RAISE_EXCEPTION, REQUEST_CANCELLED, REQUEST_IN_PROGRESS, SERVER_BUSY, BLOCK_ACKNOWLEDGE); type R (Status : Enum := OK) is record Status_Block : Integer; case Status is when RAISE_EXCEPTION => I : Integer; when OK => Length : Natural; Data : Integer; when others => null; end case; end record; for R use record Status at 0 range 0 .. 7; Status_Block at 4 range 0 .. 31; Length at 8 range 0 .. 31; end record; Nil : constant R := (OK, 1, 0, 1); begin null; end;