diff mbox

[Ada] Fix ICE with unconstrained array types and inlining

Message ID 201109261118.19706.ebotcazou@adacore.com
State New
Headers show

Commit Message

Eric Botcazou Sept. 26, 2011, 9:18 a.m. UTC
It may arise on platforms with conditional execution because of an awkward CFG, 
but it ultimately comes from a discrepancy in the way we translate allocation 
expressions for unconstrained array types in gigi.

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


2011-09-26  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc-interface/utils2.c (build_allocator): Set TREE_THIS_NOTRAP on the
	dereference of the pointer to the storage area.  Remove useless type
	conversions and factor out common code.


2011-09-26  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/opt20.ad[sb]: New test.
	* gnat.dg/opt20_pkg.ads: New helper.
diff mbox

Patch

Index: gcc-interface/utils2.c
===================================================================
--- gcc-interface/utils2.c	(revision 179184)
+++ gcc-interface/utils2.c	(working copy)
@@ -2112,9 +2112,9 @@  build_call_alloc_dealloc (tree gnu_obj,
     }
 }
 
-/* Build a GCC tree to correspond to allocating an object of TYPE whose
+/* Build a GCC tree that corresponds to allocating an object of TYPE whose
    initial value is INIT, if INIT is nonzero.  Convert the expression to
-   RESULT_TYPE, which must be some type of pointer.  Return the tree.
+   RESULT_TYPE, which must be some pointer type, and return the result.
 
    GNAT_PROC and GNAT_POOL optionally give the procedure to call and
    the storage pool to use.  GNAT_NODE is used to provide an error
@@ -2127,8 +2127,7 @@  tree
 build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc,
                  Entity_Id gnat_pool, Node_Id gnat_node, bool ignore_init_type)
 {
-  tree size = TYPE_SIZE_UNIT (type);
-  tree result;
+  tree size, storage, storage_deref, storage_init;
 
   /* If the initializer, if present, is a NULL_EXPR, just return a new one.  */
   if (init && TREE_CODE (init) == NULL_EXPR)
@@ -2154,19 +2153,19 @@  build_allocator (tree type, tree init, t
 					  get_identifier ("ALLOC"), false);
       tree template_type = TREE_TYPE (TYPE_FIELDS (storage_type));
       tree storage_ptr_type = build_pointer_type (storage_type);
-      tree storage;
 
       size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (storage_type),
 					     init);
 
-      /* If the size overflows, pass -1 so the allocator will raise
-	 storage error.  */
+      /* If the size overflows, pass -1 so Storage_Error will be raised.  */
       if (TREE_CODE (size) == INTEGER_CST && TREE_OVERFLOW (size))
 	size = ssize_int (-1);
 
       storage = build_call_alloc_dealloc (NULL_TREE, size, storage_type,
 					  gnat_proc, gnat_pool, gnat_node);
       storage = convert (storage_ptr_type, gnat_protect_expr (storage));
+      storage_deref = build_unary_op (INDIRECT_REF, NULL_TREE, storage);
+      TREE_THIS_NOTRAP (storage_deref) = 1;
 
       /* If there is an initializing expression, then make a constructor for
 	 the entire object including the bounds and copy it into the object.
@@ -2179,29 +2178,24 @@  build_allocator (tree type, tree init, t
 				  build_template (template_type, type, init));
 	  CONSTRUCTOR_APPEND_ELT (v, DECL_CHAIN (TYPE_FIELDS (storage_type)),
 				  init);
-	  return convert
-	    (result_type,
-	     build2 (COMPOUND_EXPR, storage_ptr_type,
-		     build_binary_op
-		     (MODIFY_EXPR, NULL_TREE,
-		      build_unary_op (INDIRECT_REF, NULL_TREE,
-				      convert (storage_ptr_type, storage)),
-		      gnat_build_constructor (storage_type, v)),
-		     convert (storage_ptr_type, storage)));
+	  storage_init
+	    = build_binary_op (MODIFY_EXPR, NULL_TREE, storage_deref,
+			       gnat_build_constructor (storage_type, v));
 	}
       else
-	return build2
-	  (COMPOUND_EXPR, result_type,
-	   build_binary_op
-	   (MODIFY_EXPR, NULL_TREE,
-	    build_component_ref
-	    (build_unary_op (INDIRECT_REF, NULL_TREE,
-			     convert (storage_ptr_type, storage)),
-	     NULL_TREE, TYPE_FIELDS (storage_type), false),
-	    build_template (template_type, type, NULL_TREE)),
-	   convert (result_type, convert (storage_ptr_type, storage)));
+	storage_init
+	  = build_binary_op (MODIFY_EXPR, NULL_TREE,
+			     build_component_ref (storage_deref, NULL_TREE,
+						  TYPE_FIELDS (storage_type),
+						  false),
+			     build_template (template_type, type, NULL_TREE));
+
+      return build2 (COMPOUND_EXPR, result_type,
+		     storage_init, convert (result_type, storage));
     }
 
+  size = TYPE_SIZE_UNIT (type);
+
   /* If we have an initializing expression, see if its size is simpler
      than the size from the type.  */
   if (!ignore_init_type && init && TYPE_SIZE_UNIT (TREE_TYPE (init))
@@ -2221,32 +2215,28 @@  build_allocator (tree type, tree init, t
 	size = max_size (size, true);
     }
 
-  /* If the size overflows, pass -1 so the allocator will raise
-     storage error.  */
+  /* If the size overflows, pass -1 so Storage_Error will be raised.  */
   if (TREE_CODE (size) == INTEGER_CST && TREE_OVERFLOW (size))
     size = ssize_int (-1);
 
-  result = convert (result_type,
-		    build_call_alloc_dealloc (NULL_TREE, size, type,
-					      gnat_proc, gnat_pool,
-					      gnat_node));
+  storage = convert (result_type,
+		     build_call_alloc_dealloc (NULL_TREE, size, type,
+					       gnat_proc, gnat_pool,
+					       gnat_node));
 
   /* If we have an initial value, protect the new address, assign the value
      and return the address with a COMPOUND_EXPR.  */
   if (init)
     {
-      result = gnat_protect_expr (result);
-      result
-	= build2 (COMPOUND_EXPR, TREE_TYPE (result),
-		  build_binary_op
-		  (MODIFY_EXPR, NULL_TREE,
-		   build_unary_op (INDIRECT_REF,
-				   TREE_TYPE (TREE_TYPE (result)), result),
-		   init),
-		  result);
+      storage = gnat_protect_expr (storage);
+      storage_deref = build_unary_op (INDIRECT_REF, NULL_TREE, storage);
+      TREE_THIS_NOTRAP (storage_deref) = 1;
+      storage_init
+	= build_binary_op (MODIFY_EXPR, NULL_TREE, storage_deref, init);
+      return build2 (COMPOUND_EXPR, result_type, storage_init, storage);
     }
 
-  return convert (result_type, result);
+  return storage;
 }
 
 /* Indicate that we need to take the address of T and that it therefore