diff mbox series

[Ada] Fix Max_Size_In_Storage_Elements for unconstrained array types

Message ID 2478632.0aPzeAe4HX@polaris
State New
Headers show
Series [Ada] Fix Max_Size_In_Storage_Elements for unconstrained array types | expand

Commit Message

Eric Botcazou Dec. 14, 2018, 11:08 a.m. UTC
It appears that GNAT was not fully compliant with the intent of the RM here 
because it wouldn't include the size of the bounds added in front of the data 
in an allocation in the value of Max_Size_In_Storage_Elements.

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


2018-12-14  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc-interface/decl.c (rm_size): Take into account the padding in
	the case of a record type containing a template.
	* gcc-interface/trans.c (Attribute_to_gnu) <Attr_Size>: Likewise.
	Do not subtract the padded size for Max_Size_In_Storage_Elements.
	<Attr_Descriptor_Size>: Tweak comment.


2018-12-14  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/max_size.adb: New test.
	* gnat.dg/max_size_pkg.ads: Likewise.
diff mbox series

Patch

Index: gcc-interface/decl.c
===================================================================
--- gcc-interface/decl.c	(revision 267130)
+++ gcc-interface/decl.c	(working copy)
@@ -10049,13 +10049,14 @@  rm_size (tree gnu_type)
   if (INTEGRAL_TYPE_P (gnu_type) && TYPE_RM_SIZE (gnu_type))
     return TYPE_RM_SIZE (gnu_type);
 
-  /* Return the RM size of the actual data plus the size of the template.  */
+  /* If the type contains a template, return the padded size of the template
+     plus the RM size of the actual data.  */
   if (TREE_CODE (gnu_type) == RECORD_TYPE
       && TYPE_CONTAINS_TEMPLATE_P (gnu_type))
     return
       size_binop (PLUS_EXPR,
-		  rm_size (TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (gnu_type)))),
-		  DECL_SIZE (TYPE_FIELDS (gnu_type)));
+		  bit_position (DECL_CHAIN (TYPE_FIELDS (gnu_type))),
+		  rm_size (TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (gnu_type)))));
 
   /* For record or union types, we store the size explicitly.  */
   if (RECORD_OR_UNION_TYPE_P (gnu_type)
Index: gcc-interface/trans.c
===================================================================
--- gcc-interface/trans.c	(revision 267062)
+++ gcc-interface/trans.c	(working copy)
@@ -2308,10 +2308,8 @@  Attribute_to_gnu (Node_Id gnat_node, tre
       gnu_type = TREE_TYPE (gnu_prefix);
 
       /* Replace an unconstrained array type with the type of the underlying
-	 array.  We can't do this with a call to maybe_unconstrained_array
-	 since we may have a TYPE_DECL.  For 'Max_Size_In_Storage_Elements,
-	 use the record type that will be used to allocate the object and its
-	 template.  */
+	 array, except for 'Max_Size_In_Storage_Elements because we need to
+	 return the (maximum) size requested for an allocator.  */
       if (TREE_CODE (gnu_type) == UNCONSTRAINED_ARRAY_TYPE)
 	{
 	  gnu_type = TYPE_OBJECT_RECORD_TYPE (gnu_type);
@@ -2375,11 +2373,15 @@  Attribute_to_gnu (Node_Id gnat_node, tre
 	    gnu_result = substitute_placeholder_in_expr (gnu_result, gnu_expr);
 	}
 
-      /* If the type contains a template, subtract its size.  */
+      /* If the type contains a template, subtract the padded size of the
+	 template, except for 'Max_Size_In_Storage_Elements because we need
+	 to return the (maximum) size requested for an allocator.  */
       if (TREE_CODE (gnu_type) == RECORD_TYPE
-	  && TYPE_CONTAINS_TEMPLATE_P (gnu_type))
-	gnu_result = size_binop (MINUS_EXPR, gnu_result,
-				 DECL_SIZE (TYPE_FIELDS (gnu_type)));
+	  && TYPE_CONTAINS_TEMPLATE_P (gnu_type)
+	  && attribute != Attr_Max_Size_In_Storage_Elements)
+	gnu_result
+	  = size_binop (MINUS_EXPR, gnu_result,
+			bit_position (DECL_CHAIN (TYPE_FIELDS (gnu_type))));
 
       /* For 'Max_Size_In_Storage_Elements, adjust the unit.  */
       if (attribute == Attr_Max_Size_In_Storage_Elements)
@@ -2856,8 +2858,7 @@  Attribute_to_gnu (Node_Id gnat_node, tre
       gnu_type = TREE_TYPE (gnu_prefix);
       gcc_assert (TREE_CODE (gnu_type) == UNCONSTRAINED_ARRAY_TYPE);
 
-      /* What we want is the offset of the ARRAY field in the record
-	 that the thin pointer designates.  */
+      /* Return the padded size of the template in the object record type.  */
       gnu_type = TYPE_OBJECT_RECORD_TYPE (gnu_type);
       gnu_result = bit_position (DECL_CHAIN (TYPE_FIELDS (gnu_type)));
       gnu_result_type = get_unpadded_type (Etype (gnat_node));