This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Ada] Fix ICE on discriminated record with representation clause


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  <ebotcazou@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  <ebotcazou@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;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]