Patchwork [Ada] Fix PR ada/44892

login
register
mail settings
Submitter Eric Botcazou
Date July 22, 2010, 7:28 p.m.
Message ID <201007222128.36813.ebotcazou@adacore.com>
Download mbox | patch
Permalink /patch/59633/
State New
Headers show

Comments

Eric Botcazou - July 22, 2010, 7:28 p.m.
This is the regression of gnat.dg/unchecked_convert5.adb visible on big-endian 
platforms, caused by a stronger internal check introduced on the mem-ref2 
branch.  Fixed by teaching gigi to avoid generating a class of problematic 
VIEW_CONVERT_EXPRs.

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


2010-07-22  Eric Botcazou  <ebotcazou@adacore.com>

	PR ada/44892
	* gcc-interface/utils.c (convert): Fix thinko in test.
	(unchecked_convert): When converting from a scalar type to a type with
	a different size, pad to have the same size on both sides.


2010-07-22  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/unchecked_convert5b.adb: New test.
	* gnat.dg/unchecked_convert6.adb: Likewise.
	* gnat.dg/unchecked_convert6b.adb: Likewise.

Patch

Index: gcc-interface/utils.c
===================================================================
--- gcc-interface/utils.c	(revision 162424)
+++ gcc-interface/utils.c	(working copy)
@@ -3702,9 +3702,10 @@  convert (tree type, tree expr)
       if (ecode == RECORD_TYPE
 	  && CONTAINS_PLACEHOLDER_P (DECL_SIZE (TYPE_FIELDS (type))))
 	{
-	  if (TREE_CONSTANT (TYPE_SIZE (etype)))
+	  if (TREE_CODE (TYPE_SIZE (etype)) == INTEGER_CST)
 	    expr = convert (maybe_pad_type (etype, TYPE_SIZE (type), 0, Empty,
-			    false, false, false, true), expr);
+					    false, false, false, true),
+			    expr);
 	  return unchecked_convert (type, expr, false);
 	}
 
@@ -4353,6 +4354,7 @@  unchecked_convert (tree type, tree expr,
   tree etype = TREE_TYPE (expr);
   enum tree_code ecode = TREE_CODE (etype);
   enum tree_code code = TREE_CODE (type);
+  int c;
 
   /* If the expression is already of the right type, we are done.  */
   if (etype == type)
@@ -4393,7 +4395,8 @@  unchecked_convert (tree type, tree expr,
   /* If we are converting to an integral type whose precision is not equal
      to its size, first unchecked convert to a record that contains an
      object of the output type.  Then extract the field. */
-  else if (INTEGRAL_TYPE_P (type) && TYPE_RM_SIZE (type)
+  else if (INTEGRAL_TYPE_P (type)
+	   && TYPE_RM_SIZE (type)
 	   && 0 != compare_tree_int (TYPE_RM_SIZE (type),
 				     GET_MODE_BITSIZE (TYPE_MODE (type))))
     {
@@ -4410,9 +4413,10 @@  unchecked_convert (tree type, tree expr,
 
   /* Similarly if we are converting from an integral type whose precision
      is not equal to its size.  */
-  else if (INTEGRAL_TYPE_P (etype) && TYPE_RM_SIZE (etype)
-      && 0 != compare_tree_int (TYPE_RM_SIZE (etype),
-				GET_MODE_BITSIZE (TYPE_MODE (etype))))
+  else if (INTEGRAL_TYPE_P (etype)
+	   && TYPE_RM_SIZE (etype)
+	   && 0 != compare_tree_int (TYPE_RM_SIZE (etype),
+				     GET_MODE_BITSIZE (TYPE_MODE (etype))))
     {
       tree rec_type = make_node (RECORD_TYPE);
       tree field = create_field_decl (get_identifier ("OBJ"), etype, rec_type,
@@ -4427,6 +4431,38 @@  unchecked_convert (tree type, tree expr,
       expr = unchecked_convert (type, expr, notrunc_p);
     }
 
+  /* If we are converting from a scalar type to a type with a different size,
+     we need to pad to have the same size on both sides.
+
+     ??? We cannot do it unconditionally because unchecked conversions are
+     used liberally by the front-end to implement polymorphism, e.g. in:
+
+       S191s : constant ada__tags__addr_ptr := ada__tags__addr_ptr!(S190s);
+       return p___size__4 (p__object!(S191s.all));
+
+     so we skip all expressions that are references.  */
+  else if (!REFERENCE_CLASS_P (expr)
+	   && !AGGREGATE_TYPE_P (etype)
+	   && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+	   && (c = tree_int_cst_compare (TYPE_SIZE (etype), TYPE_SIZE (type))))
+    {
+      if (c < 0)
+	{
+	  expr = convert (maybe_pad_type (etype, TYPE_SIZE (type), 0, Empty,
+					  false, false, false, true),
+			  expr);
+	  expr = unchecked_convert (type, expr, notrunc_p);
+	}
+      else
+	{
+	  tree rec_type = maybe_pad_type (type, TYPE_SIZE (etype), 0, Empty,
+					  false, false, false, true);
+	  expr = unchecked_convert (rec_type, expr, notrunc_p);
+	  expr = build_component_ref (expr, NULL_TREE, TYPE_FIELDS (rec_type),
+				      false);
+	}
+    }
+
   /* We have a special case when we are converting between two unconstrained
      array types.  In that case, take the address, convert the fat pointer
      types, and dereference.  */