diff mbox

[Ada] Fix wrong code with discriminated types at -gnatp

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

Commit Message

Eric Botcazou Aug. 30, 2010, 4 p.m. UTC
This fixes a wrong code generation with -gnatp at any optimization level, a 
regression recently introduced on the mainline: we were assigning the max 
size when returning an aggregate of a discriminated record type with default 
discriminant.

Tested on x86-64-suse-linux, applied on the mainline.


2010-08-30  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc-interface/trans.c (call_to_gnu): Also force the return slot opt
	for the call to a function whose return type was unconstrained.


2010-08-30  Thomas Quinot  <quinot@adacore.com>

	* gnat.dg/discr24.adb: New test.
diff mbox

Patch

Index: gcc-interface/trans.c
===================================================================
--- gcc-interface/trans.c	(revision 163646)
+++ gcc-interface/trans.c	(working copy)
@@ -2992,6 +2992,7 @@  call_to_gnu (Node_Id gnat_node, tree *gn
       if (gnu_target)
 	{
 	  Node_Id gnat_parent = Parent (gnat_node);
+	  tree gnu_result_type = TREE_TYPE (gnu_subprog_type);
 	  enum tree_code op_code;
 
 	  /* If range check is needed, emit code to generate it.  */
@@ -3002,11 +3003,15 @@  call_to_gnu (Node_Id gnat_node, tree *gn
 
 	  /* ??? If the return type has non-constant size, then force the
 	     return slot optimization as we would not be able to generate
-	     a temporary.  That's what has been done historically.  */
-	  if (TREE_CONSTANT (TYPE_SIZE (TREE_TYPE (gnu_subprog_type))))
-	    op_code = MODIFY_EXPR;
-	  else
+	     a temporary.  Likewise if it was unconstrained as we would
+	     copy too much data.  That's what has been done historically.  */
+	  if (!TREE_CONSTANT (TYPE_SIZE (gnu_result_type))
+	      || (TYPE_IS_PADDING_P (gnu_result_type)
+		  && CONTAINS_PLACEHOLDER_P
+		     (TYPE_SIZE (TREE_TYPE (TYPE_FIELDS (gnu_result_type))))))
 	    op_code = INIT_EXPR;
+	  else
+	    op_code = MODIFY_EXPR;
 
 	  gnu_result
 	    = build_binary_op (op_code, NULL_TREE, gnu_target, gnu_result);