]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/51060 (Temporary object stack space is not re-used)
authorJason Merrill <jason@redhat.com>
Sun, 13 Nov 2011 00:44:39 +0000 (19:44 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Sun, 13 Nov 2011 00:44:39 +0000 (19:44 -0500)
PR c++/51060
* gimplify.c (gimplify_target_expr): Add a clobber to the cleanup.
(gimplify_modify_expr): Don't try to simplify it.
* cp/cp-gimplify.c (cp_gimplify_expr): Leave clobbers alone.

From-SVN: r181332

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/cp-gimplify.c
gcc/gimplify.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/stack2.C [new file with mode: 0644]
libstdc++-v3/ChangeLog
libstdc++-v3/testsuite/25_algorithms/max/1.cc
libstdc++-v3/testsuite/25_algorithms/min/1.cc
libstdc++-v3/testsuite/25_algorithms/minmax/1.cc

index f3e745fcb5e356ebbff720ff8114f0717c26c64d..e90d1f68944c40c7dfc19ea294544e4e2a767923 100644 (file)
@@ -1,3 +1,9 @@
+2011-11-12  Jason Merrill  <jason@redhat.com>
+
+       PR c++/51060
+       * gimplify.c (gimplify_target_expr): Add a clobber to the cleanup.
+       (gimplify_modify_expr): Don't try to simplify it.
+
 2011-11-12  Dimitrios Apostolou  <jimis@gmx.net>
 
        PR bootstrap/51094
index 291487fad63ef746a6b3a0add9bd469c834cb2d2..21f64476d96245cae5de26efaebf08b5b5d90446 100644 (file)
@@ -1,3 +1,8 @@
+2011-11-12  Jason Merrill  <jason@redhat.com>
+
+       PR c++/51060
+       * cp-gimplify.c (cp_gimplify_expr): Leave clobbers alone.
+
 2011-11-11  Ed Smith-Rowland  <3dw4rd@verizon.net>
 
        PR c++/50976
index af45f5918468b16d0219895e48e61f36de20b3ba..9968c3dd7ee122e020887a2d1f05d70404ef12c8 100644 (file)
@@ -569,7 +569,8 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 
        else if ((is_gimple_lvalue (op1) || INDIRECT_REF_P (op1)
                  || (TREE_CODE (op1) == CONSTRUCTOR
-                     && CONSTRUCTOR_NELTS (op1) == 0)
+                     && CONSTRUCTOR_NELTS (op1) == 0
+                     && !TREE_CLOBBER_P (op1))
                  || (TREE_CODE (op1) == CALL_EXPR
                      && !CALL_EXPR_RETURN_SLOT_OPT (op1)))
                 && is_really_empty_class (TREE_TYPE (op0)))
index 9845b6922117cb3925739a5b236f7369c39cad36..cfe6696f59040ecf091ec8e387ff933bb2f5b8bc 100644 (file)
@@ -4554,6 +4554,16 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
   gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
              || TREE_CODE (*expr_p) == INIT_EXPR);
 
+  /* Trying to simplify a clobber using normal logic doesn't work,
+     so handle it here.  */
+  if (TREE_CLOBBER_P (*from_p))
+    {
+      gcc_assert (!want_value && TREE_CODE (*to_p) == VAR_DECL);
+      gimplify_seq_add_stmt (pre_p, gimple_build_assign (*to_p, *from_p));
+      *expr_p = NULL;
+      return GS_ALL_DONE;
+    }
+
   /* Insert pointer conversions required by the middle-end that are not
      required by the frontend.  This fixes middle-end type checking for
      for example gcc.dg/redecl-6.c.  */
@@ -5335,6 +5345,8 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 
   if (init)
     {
+      tree cleanup = NULL_TREE;
+
       /* TARGET_EXPR temps aren't part of the enclosing block, so add it
         to the temps list.  Handle also variable length TARGET_EXPRs.  */
       if (TREE_CODE (DECL_SIZE (temp)) != INTEGER_CST)
@@ -5369,8 +5381,30 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
 
       /* If needed, push the cleanup for the temp.  */
       if (TARGET_EXPR_CLEANUP (targ))
-       gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
-                            CLEANUP_EH_ONLY (targ), pre_p);
+       {
+         if (CLEANUP_EH_ONLY (targ))
+           gimple_push_cleanup (temp, TARGET_EXPR_CLEANUP (targ),
+                                CLEANUP_EH_ONLY (targ), pre_p);
+         else
+           cleanup = TARGET_EXPR_CLEANUP (targ);
+       }
+
+      /* Add a clobber for the temporary going out of scope, like
+        gimplify_bind_expr.  */
+      if (needs_to_live_in_memory (temp))
+       {
+         tree clobber = build_constructor (TREE_TYPE (temp), NULL);
+         TREE_THIS_VOLATILE (clobber) = true;
+         clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
+         if (cleanup)
+           cleanup = build2 (COMPOUND_EXPR, void_type_node, cleanup,
+                             clobber);
+         else
+           cleanup = clobber;
+       }
+
+      if (cleanup)
+       gimple_push_cleanup (temp, cleanup, false, pre_p);
 
       /* Only expand this once.  */
       TREE_OPERAND (targ, 3) = init;
index 9f151d1c08b6177364f4559766009b2b2183ff74..0582e49e0e5cbfae62cf871dbc59a49aa5737fb6 100644 (file)
@@ -1,3 +1,8 @@
+2011-11-12  Jason Merrill  <jason@redhat.com>
+
+       PR c++/51060
+       * g++.dg/opt/stack2.C: New.
+
 2011-11-12  Uros Bizjak  <ubizjak@gmail.com>
 
        * lib/gcc-simulate-thread.exp (simulate-thread): Do not run on
diff --git a/gcc/testsuite/g++.dg/opt/stack2.C b/gcc/testsuite/g++.dg/opt/stack2.C
new file mode 100644 (file)
index 0000000..8468e1a
--- /dev/null
@@ -0,0 +1,33 @@
+// PR c++/51060
+// { dg-options "-Os -Wframe-larger-than=2000 -Werror" }
+
+// Shows a problem of not re-using stack space:
+// Compile as: g++ -c test_stack_reuse.cpp -o /dev/null -Wframe-larger-than=2048 -Werror -Os
+// Result: warning: the frame size of 10240 bytes is larger than 2048 bytes [-Wframe-larger-than=]
+//
+
+struct StackObject
+{
+  StackObject();
+  char buffer[1024];
+};
+
+void Test()
+{
+#define TEST_SUB() \
+  StackObject();
+
+#define TEST() \
+       TEST_SUB() \
+       TEST_SUB() \
+       TEST_SUB() \
+       TEST_SUB() \
+       TEST_SUB() \
+       TEST_SUB() \
+       TEST_SUB() \
+       TEST_SUB() \
+       TEST_SUB() \
+       TEST_SUB()
+
+  TEST()
+}
index 22663da3cac842548538735af3e4502452f3cfbf..782284365b3af1b3e0713c93d28d0730b01ddd8a 100644 (file)
@@ -1,3 +1,10 @@
+2011-11-12  Jason Merrill  <jason@redhat.com>
+
+       PR c++/51060
+       * testsuite/25_algorithms/max/1.cc (test01): Drop references.
+       * testsuite/25_algorithms/min/1.cc (test01): Drop references.
+       * testsuite/25_algorithms/minmax/1.cc (test01): Drop references.
+
 2011-11-12  Jonathan Wakely  <jwakely.gcc@gmail.com>
 
        PR libstdc++/51083
index 978466f1b076d030689d79300d2ef6725466d749..1757b6a49f6b88136e0efa2ad987e54880f651d7 100644 (file)
@@ -25,13 +25,13 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
 
-  const int& x = std::max(1, 2);
-  const int& y = std::max(4, 3);
+  const int x = std::max(1, 2);
+  const int y = std::max(4, 3);
   VERIFY( x == 2 );
   VERIFY( y == 4 );
 
-  const int& xc = std::max(1, 2, std::greater<int>());
-  const int& yc = std::max(4, 3, std::greater<int>());
+  const int xc = std::max(1, 2, std::greater<int>());
+  const int yc = std::max(4, 3, std::greater<int>());
   VERIFY( xc == 1 );
   VERIFY( yc == 3 );
 }
index 23bc7216173c32a99ce0c26114de81cb4e83aaa8..ca52e4972451bd1c444355a2027577c48fe526e8 100644 (file)
@@ -25,13 +25,13 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
 
-  const int& z = std::min(1, 2);
-  const int& w = std::min(4, 3);
+  const int z = std::min(1, 2);
+  const int w = std::min(4, 3);
   VERIFY( z == 1 );
   VERIFY( w == 3 );
 
-  const int& zc = std::min(1, 2, std::greater<int>());
-  const int& wc = std::min(4, 3, std::greater<int>());
+  const int zc = std::min(1, 2, std::greater<int>());
+  const int wc = std::min(4, 3, std::greater<int>());
   VERIFY( zc == 2 );
   VERIFY( wc == 4 );
 }
index 52122415e70041763c1c5315a71b562d2fe47c53..5e581927d699d90d2d37cc3dbbefde9e490d549f 100644 (file)
@@ -27,15 +27,15 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
 
-  std::pair<const int&, const int&> z = std::minmax(1, 2);
-  std::pair<const int&, const int&> w = std::minmax(4, 3);
+  std::pair<const int, const int> z = std::minmax(1, 2);
+  std::pair<const int, const int> w = std::minmax(4, 3);
   VERIFY( z.first == 1 );
   VERIFY( z.second == 2 );
   VERIFY( w.first == 3 );
   VERIFY( w.second == 4 );
 
-  std::pair<const int&, const int&> zc = std::minmax(1, 2, std::greater<int>());
-  std::pair<const int&, const int&> wc = std::minmax(4, 3, std::greater<int>());
+  std::pair<const int, const int> zc = std::minmax(1, 2, std::greater<int>());
+  std::pair<const int, const int> wc = std::minmax(4, 3, std::greater<int>());
   VERIFY( zc.first == 2 );
   VERIFY( zc.second == 1 );
   VERIFY( wc.first == 4 );