diff mbox

[Ada] Fix double elaboration of qualified expression in allocator

Message ID 133202762.Q9MXPlqZYA@polaris
State New
Headers show

Commit Message

Eric Botcazou June 6, 2016, 9:44 a.m. UTC
This is a regression present on the mainline and 6 branch: under some peculiar 
circumstances, the qualified expression of an allocator can be elaborated 
twice by gigi.

Tested on x86_64-suse-linux, applied on the mainline and 6 branch.


2016-06-06  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc-interface/utils2.c (build_call_alloc_dealloc): Do not
	substitute placeholder expressions here but...
	* gcc-interface/trans.c (gnat_to_gnu) <N_Free_Statement>: ...here.
	Make an exception to the protection of a CALL_EXPR result with an
	unconstrained type only in the same cases as Call_to_gnu.
diff mbox

Patch

Index: gcc-interface/trans.c
===================================================================
--- gcc-interface/trans.c	(revision 237123)
+++ gcc-interface/trans.c	(working copy)
@@ -7640,10 +7640,11 @@  gnat_to_gnu (Node_Id gnat_node)
 	  else
 	    gnu_actual_obj_type = gnu_obj_type;
 
+	  tree gnu_size = TYPE_SIZE_UNIT (gnu_actual_obj_type);
+	  gnu_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_size, gnu_ptr);
+
 	  gnu_result
-	      = build_call_alloc_dealloc (gnu_ptr,
-					  TYPE_SIZE_UNIT (gnu_actual_obj_type),
-					  gnu_obj_type,
+	      = build_call_alloc_dealloc (gnu_ptr, gnu_size, gnu_obj_type,
 					  Procedure_To_Call (gnat_node),
 					  Storage_Pool (gnat_node),
 					  gnat_node);
@@ -7729,16 +7730,22 @@  gnat_to_gnu (Node_Id gnat_node)
 				    N_Raise_Constraint_Error));
     }
 
-  /* If the result has side-effects and is of an unconstrained type, make a
-     SAVE_EXPR so that we can be sure it will only be referenced once.  But
-     this is useless for a call to a function that returns an unconstrained
-     type with default discriminant, as we cannot compute the size of the
-     actual returned object.  We must do this before any conversions.  */
+  /* If the result has side-effects and is of an unconstrained type, protect
+     the expression in case it will be referenced multiple times, i.e. for
+     its value and to compute the size of an object.  But do it neither for
+     an object nor a renaming declaration, nor a return statement of a call
+     to a function that returns an unconstrained record type with default
+     discriminant, because there is no size to be computed in these cases
+     and this will create a useless temporary.  We must do this before any
+     conversions.  */
   if (TREE_SIDE_EFFECTS (gnu_result)
-      && !(TREE_CODE (gnu_result) == CALL_EXPR
-	   && type_is_padding_self_referential (TREE_TYPE (gnu_result)))
       && (TREE_CODE (gnu_result_type) == UNCONSTRAINED_ARRAY_TYPE
-	  || CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_result_type))))
+	  || CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_result_type)))
+      && !(TREE_CODE (gnu_result) == CALL_EXPR
+	   && type_is_padding_self_referential (TREE_TYPE (gnu_result))
+	   && (Nkind (Parent (gnat_node)) == N_Object_Declaration
+	       || Nkind (Parent (gnat_node)) == N_Object_Renaming_Declaration
+	       || Nkind (Parent (gnat_node)) == N_Simple_Return_Statement)))
     gnu_result = gnat_protect_expr (gnu_result);
 
   /* Now convert the result to the result type, unless we are in one of the
Index: gcc-interface/utils2.c
===================================================================
--- gcc-interface/utils2.c	(revision 237088)
+++ gcc-interface/utils2.c	(working copy)
@@ -2268,8 +2268,6 @@  build_call_alloc_dealloc (tree gnu_obj,
                           Entity_Id gnat_proc, Entity_Id gnat_pool,
                           Node_Id gnat_node)
 {
-  gnu_size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (gnu_size, gnu_obj);
-
   /* Explicit proc to call ?  This one is assumed to deal with the type
      alignment constraints.  */
   if (Present (gnat_proc))