From ca361dec8f52c32553ce31f58acb414869b0b7a8 Mon Sep 17 00:00:00 2001
From: Eric Botcazou <ebotcazou@adacore.com>
Date: Wed, 5 May 2010 17:48:01 +0000
Subject: [PATCH] gimplify.c (gimplify_return_expr): Gimplify the size
 expressions of a variable-sized RESULT_DECL.

	* gimplify.c (gimplify_return_expr): Gimplify the size expressions of
	a variable-sized RESULT_DECL.

From-SVN: r159074
---
 gcc/ChangeLog                  |  5 +++++
 gcc/gimplify.c                 | 19 ++++++++++++++++---
 gcc/testsuite/ChangeLog        |  4 ++++
 gcc/testsuite/gnat.dg/lto2.adb | 28 ++++++++++++++++++++++++++++
 4 files changed, 53 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gnat.dg/lto2.adb

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e2c1081f8149..9f656df92294 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2010-05-05  Eric Botcazou  <ebotcazou@adacore.com>
+
+	* gimplify.c (gimplify_return_expr): Gimplify the size expressions of
+	a variable-sized RESULT_DECL.
+
 2010-05-05  Maxim Kuvyrkov  <maxim@codesourcery.com>
 
 	* doc/invoke.texi (-mfix-cortex-m3-ldrd): Move from ARC section to ARM.
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 8f7ff89d44cc..8d2bc582a7a8 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1228,9 +1228,22 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p)
      hard_function_value generates a PARALLEL, we'll die during normal
      expansion of structure assignments; there's special code in expand_return
      to handle this case that does not exist in expand_expr.  */
-  if (!result_decl
-      || aggregate_value_p (result_decl, TREE_TYPE (current_function_decl)))
-    result = result_decl;
+  if (!result_decl)
+    result = NULL_TREE;
+  else if (aggregate_value_p (result_decl, TREE_TYPE (current_function_decl)))
+    {
+      if (TREE_CODE (DECL_SIZE (result_decl)) != INTEGER_CST)
+	{
+	  if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (result_decl)))
+	    gimplify_type_sizes (TREE_TYPE (result_decl), pre_p);
+	  /* Note that we don't use gimplify_vla_decl because the RESULT_DECL
+	     should be effectively allocated by the caller, i.e. all calls to
+	     this function must be subject to the Return Slot Optimization.  */
+	  gimplify_one_sizepos (&DECL_SIZE (result_decl), pre_p);
+	  gimplify_one_sizepos (&DECL_SIZE_UNIT (result_decl), pre_p);
+	}
+      result = result_decl;
+    }
   else if (gimplify_ctxp->return_temp)
     result = gimplify_ctxp->return_temp;
   else
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ebba7731f1c2..9cee6901d9d2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2010-05-05  Eric Botcazou  <ebotcazou@adacore.com>
+
+	* gnat.dg/lto2.adb: New test.
+
 2010-05-05  Jason Merrill  <jason@redhat.com>
 
 	PR c++/43787
diff --git a/gcc/testsuite/gnat.dg/lto2.adb b/gcc/testsuite/gnat.dg/lto2.adb
new file mode 100644
index 000000000000..8738e2314266
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/lto2.adb
@@ -0,0 +1,28 @@
+-- { dg-do compile }
+-- { dg-options "-flto" }
+
+procedure Lto2 (Nbytes : Natural) is
+
+   type Message_T (Length : Natural) is record
+      case Length is
+         when 0 => null;
+         when others => Id : Natural;
+      end case;
+   end record;
+
+   type Local_Message_T is new Message_T (Nbytes);
+
+   function One_message return Local_Message_T is
+      M : Local_Message_T;
+   begin
+      if M.Length > 0 then
+         M.Id := 1;
+      end if;
+      return M;
+   end;
+
+   procedure Process (X : Local_Message_T) is begin null; end;
+
+begin
+   Process (One_Message);
+end;
-- 
GitLab