Patchwork [Ada] Fix ICE on discriminated record with representation clause

login
register
mail settings
Submitter Eric Botcazou
Date July 19, 2012, 3:40 p.m.
Message ID <201207191740.22710.ebotcazou@adacore.com>
Download mbox | patch
Permalink /patch/171963/
State New
Headers show

Comments

Eric Botcazou - July 19, 2012, 3:40 p.m.
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.

Patch

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;