aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-05-02 14:38:44 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-05-02 14:38:44 -0400
commit9257f35f7bf0c9272fbbc54bcc4c266db56a48c8 (patch)
tree715ea8c7a89c8624ccdf8797a48e0f708db6c0b9 /gcc
parent6fb380f70867fe2a693361320ad4e0055d2d2321 (diff)
downloadgcc-9257f35f7bf0c9272fbbc54bcc4c266db56a48c8.zip
gcc-9257f35f7bf0c9272fbbc54bcc4c266db56a48c8.tar.gz
gcc-9257f35f7bf0c9272fbbc54bcc4c266db56a48c8.tar.bz2
re PR c++/48446 (internal compiler error: in gimplify_var_or_parm_decl, at gimplify.c:1946)
PR c++/48446 * decl.c (stabilize_save_expr_r, stabilize_vla_size): New. (compute_array_index_type): Revert earlier 48446 changes. (grokdeclarator): Use stabilize_vla_size. From-SVN: r173264
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/decl.c59
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/c-c++-common/vla-1.c21
4 files changed, 80 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index fc64e7d..983939e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2011-05-02 Jason Merrill <jason@redhat.com>
+
+ PR c++/48446
+ * decl.c (stabilize_save_expr_r, stabilize_vla_size): New.
+ (compute_array_index_type): Revert earlier 48446 changes.
+ (grokdeclarator): Use stabilize_vla_size.
+
2011-05-02 Dmitry Gorbachev <d.g.gorbachev@gmail.com>
Eric Botcazou <ebotcazou@adacore.com>
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 0a2e1dd..f9dd6de 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7576,6 +7576,38 @@ check_static_variable_definition (tree decl, tree type)
return 0;
}
+/* *expr_p is part of the TYPE_SIZE of a variably-sized array. If any
+ SAVE_EXPRs in *expr_p wrap expressions with side-effects, break those
+ expressions out into temporary variables so that walk_tree doesn't
+ step into them (c++/15764). */
+
+static tree
+stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data)
+{
+ struct pointer_set_t *pset = (struct pointer_set_t *)data;
+ tree expr = *expr_p;
+ if (TREE_CODE (expr) == SAVE_EXPR)
+ {
+ tree op = TREE_OPERAND (expr, 0);
+ cp_walk_tree (&op, stabilize_save_expr_r, data, pset);
+ if (TREE_SIDE_EFFECTS (op))
+ TREE_OPERAND (expr, 0) = get_temp_regvar (TREE_TYPE (op), op);
+ }
+ else if (!EXPR_P (expr))
+ *walk_subtrees = 0;
+ return NULL;
+}
+
+/* Entry point for the above. */
+
+static void
+stabilize_vla_size (tree size)
+{
+ struct pointer_set_t *pset = pointer_set_create ();
+ /* Break out any function calls into temporary variables. */
+ cp_walk_tree (&size, stabilize_save_expr_r, pset, pset);
+}
+
/* Given the SIZE (i.e., number of elements) in an array, compute an
appropriate index type for the array. If non-NULL, NAME is the
name of the thing being declared. */
@@ -7769,16 +7801,8 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
processing_template_decl = saved_processing_template_decl;
if (!TREE_CONSTANT (itype))
- {
- /* A variable sized array. */
- if (TREE_SIDE_EFFECTS (itype))
- /* Use get_temp_regvar rather than variable_size here so that
- people walking expressions that use a variable of this type
- don't walk into this expression. */
- itype = get_temp_regvar (TREE_TYPE (itype), itype);
- else
- itype = variable_size (itype);
- }
+ /* A variable sized array. */
+ itype = variable_size (itype);
/* Make sure that there was no overflow when creating to a signed
index type. (For example, on a 32-bit machine, an array with
size 2^32 - 1 is too big.) */
@@ -9051,7 +9075,12 @@ grokdeclarator (const cp_declarator *declarator,
&& (decl_context == NORMAL || decl_context == FIELD)
&& at_function_scope_p ()
&& variably_modified_type_p (type, NULL_TREE))
- finish_expr_stmt (TYPE_SIZE (type));
+ {
+ /* First break out any side-effects. */
+ stabilize_vla_size (TYPE_SIZE (type));
+ /* And then force evaluation of the SAVE_EXPR. */
+ finish_expr_stmt (TYPE_SIZE (type));
+ }
if (declarator->kind == cdk_reference)
{
@@ -9126,6 +9155,14 @@ grokdeclarator (const cp_declarator *declarator,
}
}
+ /* We need to stabilize side-effects in VLA sizes for regular array
+ declarations too, not just pointers to arrays. */
+ if (type != error_mark_node && !TYPE_NAME (type)
+ && (decl_context == NORMAL || decl_context == FIELD)
+ && at_function_scope_p ()
+ && variably_modified_type_p (type, NULL_TREE))
+ stabilize_vla_size (TYPE_SIZE (type));
+
/* A `constexpr' specifier used in an object declaration declares
the object as `const'. */
if (constexpr_p && innermost_code != cdk_function)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 02722cf..e6cdd3f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2011-05-02 Jason Merrill <jason@redhat.com>
+
+ * c-c++-common/vla-1.c: New.
+
2011-05-02 Richard Guenther <rguenther@suse.de>
PR tree-optimization/48822
diff --git a/gcc/testsuite/c-c++-common/vla-1.c b/gcc/testsuite/c-c++-common/vla-1.c
new file mode 100644
index 0000000..401c4e0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/vla-1.c
@@ -0,0 +1,21 @@
+/* Test that changes to a variable are reflected in a VLA later in the
+ expression. */
+/* { dg-options "" } */
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void abort();
+
+int i = 4;
+int f()
+{
+ return i;
+}
+
+int main()
+{
+ if (i+=2, sizeof(*(int(*)[f()])0) != 6*sizeof(int))
+ abort();
+ return 0;
+}