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 Max_Size_In_Storage_Elements for unconstrained array types


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.

-- 
Eric Botcazou
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));
-- { dg-do run }

with Max_Size_Pkg; use Max_Size_Pkg;

procedure Max_Size is
begin
  if Arr1'Max_Size_In_Storage_Elements /= 7 then
    raise Program_Error;
  end if;
  if Arr2'Max_Size_In_Storage_Elements /= 24 then
    raise Program_Error;
  end if;
end;
package Max_Size_Pkg is

  type Index is range 1 .. 5;

  type Arr1 is array (Index range <>) of Short_Short_Integer;

  type Arr2 is array (Index range <>) of Integer;

end Max_Size_Pkg;

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