This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR c++/44613
- From: Patrick Palka <patrick at parcs dot ath dot cx>
- To: gcc-patches at gcc dot gnu dot org
- Cc: jason at redhat dot com, Patrick Palka <patrick at parcs dot ath dot cx>
- Date: Thu, 3 Apr 2014 11:25:09 -0400
- Subject: [PATCH] Fix PR c++/44613
- Authentication-results: sourceware.org; auth=none
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