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 issues with rep clauses in -gnatct mode


In -gnatct mode, the compiler doesn't generate code and gigi is only invoked to 
lay out and back-annotate types.  There were old issues when representation 
clauses are present: fields are shifted, sizes are wrong, component clauses 
are overridden.

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


2012-04-30  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc-interface/decl.c (gnat_to_gnu_entity): In type annotation mode,
	do not adjust the size of a tagged type if there is a representation
	clause on it.  Otherwise, round the adjustment up to the alignment
	of the first field and use the appropriate helper routine.
	(maybe_pad_type): Do not warn in type annotation mode on a tagged type.
	(gnat_to_gnu_field): Do not error out under the same circumstances.
	(annotate_rep): In type annotation mode, do not adjust the offset of
	components of a tagged type with representation clause.  Otherwise,
	round the adjustment up to the alignment of the first field.


-- 
Eric Botcazou
Index: gcc-interface/decl.c
===================================================================
--- gcc-interface/decl.c	(revision 186956)
+++ gcc-interface/decl.c	(working copy)
@@ -5027,28 +5027,33 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
 	  if (CONTAINS_PLACEHOLDER_P (gnu_size))
 	    gnu_size = max_size (gnu_size, true);
 
-	  if (type_annotate_only && Is_Tagged_Type (gnat_entity))
+	  /* If we are just annotating types and the type is tagged, the tag
+	     and the parent components are not generated by the front-end so
+	     sizes must be adjusted if there is no representation clause.  */
+	  if (type_annotate_only
+	      && Is_Tagged_Type (gnat_entity)
+	      && !VOID_TYPE_P (gnu_type)
+	      && (!TYPE_FIELDS (gnu_type)
+		  || integer_zerop (bit_position (TYPE_FIELDS (gnu_type)))))
 	    {
-	      /* In this mode, the tag and the parent components are not
-		 generated by the front-end so the sizes must be adjusted.  */
 	      tree pointer_size = bitsize_int (POINTER_SIZE), offset;
 	      Uint uint_size;
 
 	      if (Is_Derived_Type (gnat_entity))
 		{
-		  offset = UI_To_gnu (Esize (Etype (Base_Type (gnat_entity))),
-				      bitsizetype);
-		  Set_Alignment (gnat_entity,
-				 Alignment (Etype (Base_Type (gnat_entity))));
+		  Entity_Id gnat_parent = Etype (Base_Type (gnat_entity));
+		  offset = UI_To_gnu (Esize (gnat_parent), bitsizetype);
+		  Set_Alignment (gnat_entity, Alignment (gnat_parent));
 		}
 	      else
 		offset = pointer_size;
 
+	      if (TYPE_FIELDS (gnu_type))
+		offset
+		  = round_up (offset, DECL_ALIGN (TYPE_FIELDS (gnu_type)));
+
 	      gnu_size = size_binop (PLUS_EXPR, gnu_size, offset);
-	      gnu_size = size_binop (MULT_EXPR, pointer_size,
-						size_binop (CEIL_DIV_EXPR,
-							    gnu_size,
-							    pointer_size));
+	      gnu_size = round_up (gnu_size, POINTER_SIZE);
 	      uint_size = annotate_value (gnu_size);
 	      Set_Esize (gnat_entity, uint_size);
 	      Set_RM_Size (gnat_entity, uint_size);
@@ -6619,7 +6624,9 @@ maybe_pad_type (tree type, tree size, un
   /* If the size was widened explicitly, maybe give a warning.  Take the
      original size as the maximum size of the input if there was an
      unconstrained record involved and round it up to the specified alignment,
-     if one was specified.  */
+     if one was specified.  But don't do it if we are just annotating types
+     and the type is tagged, since tagged types aren't fully laid out in this
+     mode.  */
   if (CONTAINS_PLACEHOLDER_P (orig_size))
     orig_size = max_size (orig_size, true);
 
@@ -6635,7 +6642,8 @@ maybe_pad_type (tree type, tree size, un
 	   && TREE_CODE (orig_size) == INTEGER_CST
 	   && (TREE_OVERFLOW (size)
 	       || TREE_OVERFLOW (orig_size)
-	       || tree_int_cst_lt (size, orig_size))))
+	       || tree_int_cst_lt (size, orig_size)))
+      && !(type_annotate_only && Is_Tagged_Type (Etype (gnat_entity))))
     {
       Node_Id gnat_error_node = Empty;
 
@@ -6901,10 +6909,13 @@ gnat_to_gnu_field (Entity_Id gnat_field,
 	    }
 	}
 
-      /* If this field needs strict alignment, ensure the record is
-	 sufficiently aligned and that that position and size are
-	 consistent with the alignment.  */
-      if (needs_strict_alignment)
+      /* If this field needs strict alignment, check that the record is
+	 sufficiently aligned and that position and size are consistent
+	 with the alignment.  But don't do it if we are just annotating
+	 types and the field's type is tagged, since tagged types aren't
+	 fully laid out in this mode.  */
+      if (needs_strict_alignment
+	  && !(type_annotate_only && Is_Tagged_Type (gnat_field_type)))
 	{
 	  TYPE_ALIGN (gnu_record_type)
 	    = MAX (TYPE_ALIGN (gnu_record_type), TYPE_ALIGN (gnu_field_type));
@@ -7839,12 +7850,16 @@ annotate_rep (Entity_Id gnat_entity, tre
 	  {
 	    tree parent_offset;
 
-	    if (type_annotate_only && Is_Tagged_Type (gnat_entity))
+	    /* If we are just annotating types and the type is tagged, the tag
+	       and the parent components are not generated by the front-end so
+	       we need to add the appropriate offset to each component without
+	       representation clause.  */
+	    if (type_annotate_only
+		&& Is_Tagged_Type (gnat_entity)
+		&& No (Component_Clause (gnat_field)))
 	      {
-		/* In this mode the tag and parent components are not
-		   generated, so we add the appropriate offset to each
-		   component.  For a component appearing in the current
-		   extension, the offset is the size of the parent.  */
+		/* For a component appearing in the current extension, the
+		   offset is the size of the parent.  */
 		if (Is_Derived_Type (gnat_entity)
 		    && Original_Record_Component (gnat_field) == gnat_field)
 		  parent_offset
@@ -7852,6 +7867,11 @@ annotate_rep (Entity_Id gnat_entity, tre
 				 bitsizetype);
 		else
 		  parent_offset = bitsize_int (POINTER_SIZE);
+
+		if (TYPE_FIELDS (gnu_type))
+		  parent_offset
+		    = round_up (parent_offset,
+				DECL_ALIGN (TYPE_FIELDS (gnu_type)));
 	      }
 	    else
 	      parent_offset = bitsize_zero_node;

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