This fixes an implementation quirk in gigi which results in an unexpected 
error issued on the position of a component in a record type whose type is 
another record which contains aliased fields and is subject to a size clause.

The patch also contains a minor cleanup in gcc-interface/Makefile.in.

Tested on x86_64-suse-linux, applied on the mainline.


2015-11-30  Eric Botcazou  <ebotca...@adacore.com>

        * gcc-interface/ada-tree.h (TYPE_MAX_ALIGN): New macro.
        * gcc-interface/decl.c (gnat_to_gnu_entity): Do not set PACKED to -2.
        Remove obsolete code setting the alignment on some atomic types.
        When the type has no alignment but needs strict alignment and has a
        size clause, compute a maximum alignment and set it on the type.
        (adjust_packed): Remove handling of -2 argument.  Deal with TYPE_ALIGN
        and TYPE_MAX_ALIGN directly.
        (gnat_to_gnu_field): Do not document -2 as argument.
        (components_to_record): Likewise.
        * gcc-interface/utils.c (finish_record_type): Do not bump alignment of
        the record type beyond TYPE_MAX_ALIGN.  Reset the latter on exit.

        * gcc-interface/Makefile.in (PICFLAG_FOR_TARGET): Move around.
        (GNATLIBCFLAGS_FOR_C): Reformat.
        (GCC_CFLAGS): Delete.


2015-11-30  Eric Botcazou  <ebotca...@adacore.com>

        * gnat.dg/specs/rep_clause5.ads: New test.

-- 
Eric Botcazou
Index: gcc-interface/Makefile.in
===================================================================
--- gcc-interface/Makefile.in	(revision 231010)
+++ gcc-interface/Makefile.in	(working copy)
@@ -111,13 +111,12 @@ NO_SIBLING_ADAFLAGS = -fno-optimize-sibl
 NO_REORDER_ADAFLAGS = -fno-toplevel-reorder
 GNATLIBFLAGS = -W -Wall -gnatpg -nostdinc
 GNATLIBCFLAGS = -g -O2
-PICFLAG_FOR_TARGET = @PICFLAG_FOR_TARGET@
-
 # Pretend that _Unwind_GetIPInfo is available for the target by default.  This
 # should be autodetected during the configuration of libada and passed down to
 # here, but we need something for --disable-libada and hope for the best.
-GNATLIBCFLAGS_FOR_C = -W -Wall $(GNATLIBCFLAGS) \
-	-fexceptions -DIN_RTS -DHAVE_GETIPINFO
+GNATLIBCFLAGS_FOR_C = \
+  -W -Wall $(GNATLIBCFLAGS) -fexceptions -DIN_RTS -DHAVE_GETIPINFO
+PICFLAG_FOR_TARGET = @PICFLAG_FOR_TARGET@
 ALL_ADAFLAGS = $(CFLAGS) $(ADA_CFLAGS) $(ADAFLAGS)
 THREAD_KIND = native
 THREADSLIB =
@@ -132,22 +131,6 @@ soext  = .so
 shext  =
 hyphen = -
 
-# Define this as & to perform parallel make on a Sequent.
-# Note that this has some bugs, and it seems currently necessary
-# to compile all the gen* files first by hand to avoid erroneous results.
-P =
-
-# This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET.
-# It specifies -B./.
-# It also specifies -B$(tooldir)/ to find as and ld for a cross compiler.
-GCC_CFLAGS = $(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS)
-
-# Tools to use when building a cross-compiler.
-# These are used because `configure' appends `cross-make'
-# to the makefile when making a cross-compiler.
-
-# We don't use cross-make.  Instead we use the tools from the build tree,
-# if they are available.
 # program_transform_name and objdir are set by configure.ac.
 program_transform_name =
 objdir = .
Index: gcc-interface/ada-tree.h
===================================================================
--- gcc-interface/ada-tree.h	(revision 231010)
+++ gcc-interface/ada-tree.h	(working copy)
@@ -176,6 +176,10 @@ do {							 \
 /* True if TYPE can alias any other types.  */
 #define TYPE_UNIVERSAL_ALIASING_P(NODE) TYPE_LANG_FLAG_6 (NODE)
 
+/* For RECORD_TYPE, UNION_TYPE, and QUAL_UNION_TYPE, this holds the maximum
+   alignment value the type ought to have.  */
+#define TYPE_MAX_ALIGN(NODE) (TYPE_PRECISION (RECORD_OR_UNION_CHECK (NODE)))
+
 /* For an UNCONSTRAINED_ARRAY_TYPE, this is the record containing both the
    template and the object.
 
Index: gcc-interface/decl.c
===================================================================
--- gcc-interface/decl.c	(revision 231010)
+++ gcc-interface/decl.c	(working copy)
@@ -2829,11 +2829,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
 	    ? 1
 	    : Component_Alignment (gnat_entity) == Calign_Storage_Unit
 	      ? -1
-	      : (Known_Alignment (gnat_entity)
-		 || (Strict_Alignment (gnat_entity)
-		     && Known_RM_Size (gnat_entity)))
-		? -2
-		: 0;
+	      : 0;
+	const bool has_align = Known_Alignment (gnat_entity);
 	const bool has_discr = Has_Discriminants (gnat_entity);
 	const bool has_rep = Has_Specified_Layout (gnat_entity);
 	const bool is_extension
@@ -2872,7 +2869,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
 	   suppress expanding incomplete types.  */
 	gnu_type = make_node (tree_code_for_record_type (gnat_entity));
 	TYPE_NAME (gnu_type) = gnu_entity_name;
-	TYPE_PACKED (gnu_type) = (packed != 0) || has_rep;
+	TYPE_PACKED (gnu_type) = (packed != 0) || has_align || has_rep;
 	TYPE_REVERSE_STORAGE_ORDER (gnu_type)
 	  = Reverse_Storage_Order (gnat_entity);
 	process_attributes (&gnu_type, &attr_list, true, gnat_entity);
@@ -2883,38 +2880,32 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
 	    this_deferred = true;
 	  }
 
-	/* If both a size and rep clause was specified, put the size in
-	   the record type now so that it can get the proper mode.  */
+	/* If both a size and rep clause were specified, put the size on
+	   the record type now so that it can get the proper layout.  */
 	if (has_rep && Known_RM_Size (gnat_entity))
 	  TYPE_SIZE (gnu_type)
 	    = UI_To_gnu (RM_Size (gnat_entity), bitsizetype);
 
-	/* Always set the alignment here so that it can be used to
-	   set the mode, if it is making the alignment stricter.  If
-	   it is invalid, it will be checked again below.  If this is to
-	   be Atomic, choose a default alignment of a word unless we know
-	   the size and it's smaller.  */
-	if (Known_Alignment (gnat_entity))
+	/* Always set the alignment on the record type here so that it can
+	   get the proper layout.  */
+	if (has_align)
 	  TYPE_ALIGN (gnu_type)
 	    = validate_alignment (Alignment (gnat_entity), gnat_entity, 0);
-	else if (Is_Atomic_Or_VFA (gnat_entity) && Known_Esize (gnat_entity))
-	  {
-	    unsigned int size = UI_To_Int (Esize (gnat_entity));
-	    TYPE_ALIGN (gnu_type)
-	      = size >= BITS_PER_WORD ? BITS_PER_WORD : ceil_pow2 (size);
-	  }
-	/* If a type needs strict alignment, the minimum size will be the
-	   type size instead of the RM size (see validate_size).  Cap the
-	   alignment, lest it causes this type size to become too large.  */
-	else if (Strict_Alignment (gnat_entity) && Known_RM_Size (gnat_entity))
+	else
 	  {
-	    unsigned int raw_size = UI_To_Int (RM_Size (gnat_entity));
-	    unsigned int raw_align = raw_size & -raw_size;
-	    if (raw_align < BIGGEST_ALIGNMENT)
-	      TYPE_ALIGN (gnu_type) = raw_align;
+	    TYPE_ALIGN (gnu_type) = 0;
+
+	    /* If a type needs strict alignment, the minimum size will be the
+	       type size instead of the RM size (see validate_size).  Cap the
+	       alignment lest it causes this type size to become too large.  */
+	    if (Strict_Alignment (gnat_entity) && Known_RM_Size (gnat_entity))
+	      {
+		unsigned int max_size = UI_To_Int (RM_Size (gnat_entity));
+		unsigned int max_align = max_size & -max_size;
+		if (max_align < BIGGEST_ALIGNMENT)
+		  TYPE_MAX_ALIGN (gnu_type) = max_align;
+	      }
 	  }
-	else
-	  TYPE_ALIGN (gnu_type) = 0;
 
 	/* If we have a Parent_Subtype, make a field for the parent.  If
 	   this record has rep clauses, force the position to zero.  */
@@ -6502,25 +6493,29 @@ adjust_packed (tree field_type, tree rec
   if (type_has_variable_size (field_type))
     return 0;
 
+  /* In the other cases, we can honor the packing.  */
+  if (packed)
+    return packed;
+
   /* If the alignment of the record is specified and the field type
      is over-aligned, request Storage_Unit alignment for the field.  */
-  if (packed == -2)
-    {
-      if (TYPE_ALIGN (field_type) > TYPE_ALIGN (record_type))
-	return -1;
-      else
-	return 0;
-    }
+  if (TYPE_ALIGN (record_type)
+      && TYPE_ALIGN (field_type) > TYPE_ALIGN (record_type))
+    return -1;
+
+  /* Likewise if the maximum alignment of the record is specified.  */
+  if (TYPE_MAX_ALIGN (record_type)
+      && TYPE_ALIGN (field_type) > TYPE_MAX_ALIGN (record_type))
+    return -1;
 
-  return packed;
+  return 0;
 }
 
 /* Return a GCC tree for a field corresponding to GNAT_FIELD to be
    placed in GNU_RECORD_TYPE.
 
-   PACKED is 1 if the enclosing record is packed, -1 if the enclosing
-   record has Component_Alignment of Storage_Unit, -2 if the enclosing
-   record has a specified alignment.
+   PACKED is 1 if the enclosing record is packed or -1 if the enclosing
+   record has Component_Alignment of Storage_Unit.
 
    DEFINITION is true if this field is for a record being defined.
 
@@ -6989,9 +6984,8 @@ typedef struct vinfo
    GNU_FIELD_LIST.  The other calls to this function are recursive calls for
    the component list of a variant and, in this case, GNU_FIELD_LIST is empty.
 
-   PACKED is 1 if this is for a packed record, -1 if this is for a record
-   with Component_Alignment of Storage_Unit, -2 if this is for a record
-   with a specified alignment.
+   PACKED is 1 if this is for a packed record or -1 if this is for a record
+   with Component_Alignment of Storage_Unit.
 
    DEFINITION is true if we are defining this record type.
 
Index: gcc-interface/utils.c
===================================================================
--- gcc-interface/utils.c	(revision 231010)
+++ gcc-interface/utils.c	(working copy)
@@ -1694,7 +1694,8 @@ finish_record_type (tree record_type, tr
 	      /* The enclosing record type must be sufficiently aligned.
 		 Otherwise, if no alignment was specified for it and it
 		 has been laid out already, bump its alignment to the
-		 desired one if this is compatible with its size.  */
+		 desired one if this is compatible with its size and
+		 maximum alignment, if any.  */
 	      if (TYPE_ALIGN (record_type) >= align)
 		{
 		  DECL_ALIGN (field) = MAX (DECL_ALIGN (field), align);
@@ -1702,7 +1703,9 @@ finish_record_type (tree record_type, tr
 		}
 	      else if (!had_align
 		       && rep_level == 0
-		       && value_factor_p (TYPE_SIZE (record_type), align))
+		       && value_factor_p (TYPE_SIZE (record_type), align)
+		       && (!TYPE_MAX_ALIGN (record_type)
+			   || TYPE_MAX_ALIGN (record_type) >= align))
 		{
 		  TYPE_ALIGN (record_type) = align;
 		  DECL_ALIGN (field) = MAX (DECL_ALIGN (field), align);
@@ -1800,6 +1803,9 @@ finish_record_type (tree record_type, tr
 	}
     }
 
+  /* Reset the TYPE_MAX_ALIGN field since it's private to gigi.  */
+  TYPE_MAX_ALIGN (record_type) = 0;
+
   if (debug_info_p)
     rest_of_record_type_compilation (record_type);
 }
-- { dg-do compile }

pragma Implicit_Packing;

package Rep_Clause5 is

   type Modes_Type is (Mode_0, Mode_1);
   for  Modes_Type'size use 8;

   type Mode_Record_Type is
      record
         Mode_1 : aliased Modes_Type;
         Mode_2 : aliased Modes_Type;
         Mode_3 : aliased Modes_Type;
         Mode_4 : aliased Modes_Type;
         Time   : aliased Float;
      end record;

   for Mode_Record_Type use
      record
         Mode_1 at 00 range 00 .. 07;
         Mode_2 at 01 range 00 .. 07;
         Mode_3 at 02 range 00 .. 07;
         Mode_4 at 03 range 00 .. 07;
         Time   at 04 range 00 .. 31;
      end record;

   for Mode_Record_Type'Size use 64;
   for Mode_Record_Type'Alignment use 4;

   type Array_1_Type is array (0 .. 31) of Boolean;
   for  Array_1_Type'size use 32;

   type Array_2_Type is array (0 .. 127) of Boolean;
   for  Array_2_Type'size use 128;

   type Array_3_Type is array (0 .. 31) of Boolean;
   for  Array_3_Type'size use 32;

   type Unsigned_Long is mod 2 ** 32;
   type Array_4_Type is array (1 .. 6) of unsigned_Long;

   type Primary_Data_Type is
      record
         Array_1           : aliased Array_1_Type;
         Mode_Record       : aliased Mode_Record_Type;
         Array_2           : aliased Array_2_Type;
         Array_3           : Array_3_Type;
         Array_4           : Array_4_Type;
      end record;

   for Primary_Data_Type use
      record
         Array_1           at  0 range  0 ..  31; -- WORD 1
         Mode_Record       at  4 range  0 ..  63; -- WORD 2 ..  3
         Array_2           at 12 range  0 .. 127; -- WORD 4 ..  7
         Array_3           at 28 range  0 ..  31; -- WORD 8
         Array_4           at 32 range  0 .. 191; -- WORD 9 .. 14
      end record;

   for Primary_Data_Type'Size use 448;

   type Results_Record_Type is
      record
        Thirty_Two_Bit_Pad : Float;
        Result             : Primary_Data_Type;
      end record;

   for Results_Record_Type use
      record
         Thirty_Two_Bit_Pad at 0 range 0 ..  31;
         Result             at 4 range 0 .. 447;
      end record;

end Rep_Clause5;

Reply via email to