This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR c++/44613


Hi,

This patch fixes a wrong code issue in the code generated for VLAs in
the C++ frontend.  This exact issue was fixed in the C frontend with
r85849, and this patch is essentially a port of r85849 for the C++
frontend.

The issue is that this C++ code:

  {
foo:
    int x[n];
    f ();
  }

gets gimplified into this:

  {
    int x[n];
    void *saved_stack;
    saved_stack = __builtin_stack_save ();
    try
    {
foo:                      // <-- jump to foo will bypass initialization of saved_stack
      x = alloca (...);
      f ();
    } finally
    {
      __builtin_stack_restore (saved_stack);
    }
  }

In order to ensure that labels such as "foo" that occur before the
initialization of a VLA are emitted in the right place by the
gimplifier, the C++ frontend is changed to handle the above C++ code
as if it looked like this:

  {
foo:
    {
      int x[n];
      f ();
    }
  }

thereby forcing the label "foo" to be placed before the initialization
of saved_stack during gimplification.  This is the same approach that
the C frontend uses (see r85849).

I bootstrapped and regtested this patch on x86_64-unknown-linux-gnu.

2014-04-03  Patrick Palka  <patrick@parcs.ath.cx>

	PR c++/44613
	* semantics.c (add_stmt): Set STATEMENT_LIST_HAS_LABEL.
	* decl.c (cp_finish_decl): Create a new BIND_EXPR before
	instantiating a variable-sized type.
---
 gcc/cp/decl.c                    | 19 ++++++++++++++++++-
 gcc/cp/semantics.c               |  3 +++
 gcc/testsuite/g++.dg/ext/vla15.C | 20 ++++++++++++++++++++
 3 files changed, 41 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/vla15.C

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index f3a081b..5bd33c5 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6441,7 +6441,24 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
      after the call to check_initializer so that the DECL_EXPR for a
      reference temp is added before the DECL_EXPR for the reference itself.  */
   if (DECL_FUNCTION_SCOPE_P (decl))
-    add_decl_expr (decl);
+    {
+      /* If we're building a variable sized type, and we might be
+	 reachable other than via the top of the current binding
+	 level, then create a new BIND_EXPR so that we deallocate
+	 the object at the right time.  */
+      if (VAR_P (decl)
+	  && DECL_SIZE (decl)
+	  && !TREE_CONSTANT (DECL_SIZE (decl))
+	  && STATEMENT_LIST_HAS_LABEL (cur_stmt_list))
+	{
+	  tree bind;
+	  bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
+	  TREE_SIDE_EFFECTS (bind) = 1;
+	  add_stmt (bind);
+	  BIND_EXPR_BODY (bind) = push_stmt_list ();
+	}
+      add_decl_expr (decl);
+    }
 
   /* Let the middle end know about variables and functions -- but not
      static data members in uninstantiated class templates.  */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index fb1e404..b00294e 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -386,6 +386,9 @@ add_stmt (tree t)
       STMT_IS_FULL_EXPR_P (t) = stmts_are_full_exprs_p ();
     }
 
+  if (code == LABEL_EXPR || code == CASE_LABEL_EXPR)
+    STATEMENT_LIST_HAS_LABEL (cur_stmt_list) = 1;
+
   /* Add T to the statement-tree.  Non-side-effect statements need to be
      recorded during statement expressions.  */
   gcc_checking_assert (!stmt_list_stack->is_empty ());
diff --git a/gcc/testsuite/g++.dg/ext/vla15.C b/gcc/testsuite/g++.dg/ext/vla15.C
new file mode 100644
index 0000000..feeb49f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/vla15.C
@@ -0,0 +1,20 @@
+// PR c++/44613
+// { dg-do run }
+// { dg-options "" }
+
+void *volatile p;
+
+int
+main (void)
+{
+  int n = 0;
+ lab:;
+  int x[n % 1000 + 1];
+  x[0] = 1;
+  x[n % 1000] = 2;
+  p = x;
+  n++;
+  if (n < 1000000)
+    goto lab;
+  return 0;
+}
-- 
1.9.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]