summaryrefslogtreecommitdiff
path: root/meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0233-PR-c-48446.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0233-PR-c-48446.patch')
-rw-r--r--meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0233-PR-c-48446.patch183
1 files changed, 183 insertions, 0 deletions
diff --git a/meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0233-PR-c-48446.patch b/meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0233-PR-c-48446.patch
new file mode 100644
index 000000000..c27ea1c39
--- /dev/null
+++ b/meta/recipes-devtools/gcc/gcc-4.6.0/gcc-4_6-branch-backports/0233-PR-c-48446.patch
@@ -0,0 +1,183 @@
+From dfb9470529df202844f4b5dfe757ff07fa9bd27f Mon Sep 17 00:00:00 2001
+From: jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
+Date: Fri, 6 May 2011 21:58:30 +0000
+Subject: [PATCH] PR c++/48446
+ * decl.c (stabilize_save_expr_r, stabilize_vla_size): New.
+ (grokdeclarator): Use stabilize_vla_size.
+ * init.c (get_temp_regvar): No longer static.
+ * cp-tree.h: Declare it.
+
+git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch@173514 138bc75d-0d04-0410-961f-82ee72b054a4
+
+index 9fbca57..be61dad 100644
+--- a/gcc/cp/cp-tree.h
++++ b/gcc/cp/cp-tree.h
+@@ -4958,6 +4958,7 @@ extern tree build_offset_ref (tree, tree, bool);
+ extern tree build_new (VEC(tree,gc) **, tree, tree,
+ VEC(tree,gc) **, int,
+ tsubst_flags_t);
++extern tree get_temp_regvar (tree, tree);
+ extern tree build_vec_init (tree, tree, tree, bool, int,
+ tsubst_flags_t);
+ extern tree build_delete (tree, tree,
+diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
+index 6f8bb9f..74bae0b 100644
+--- a/gcc/cp/decl.c
++++ b/gcc/cp/decl.c
+@@ -7499,6 +7499,39 @@ 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);
++ *walk_subtrees = 0;
++ }
++ else if (!EXPR_P (expr) || !TREE_SIDE_EFFECTS (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. */
+@@ -8951,7 +8984,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)
+ {
+@@ -9026,6 +9064,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/cp/init.c b/gcc/cp/init.c
+index 4798257..ff94b71 100644
+--- a/gcc/cp/init.c
++++ b/gcc/cp/init.c
+@@ -45,7 +45,6 @@ static void expand_virtual_init (tree, tree);
+ static tree sort_mem_initializers (tree, tree);
+ static tree initializing_context (tree);
+ static void expand_cleanup_for_base (tree, tree);
+-static tree get_temp_regvar (tree, tree);
+ static tree dfs_initialize_vtbl_ptrs (tree, void *);
+ static tree build_dtor_call (tree, special_function_kind, int);
+ static tree build_field_list (tree, tree, int *);
+@@ -2871,7 +2870,7 @@ create_temporary_var (tree type)
+ things when it comes time to do final cleanups (which take place
+ "outside" the binding contour of the function). */
+
+-static tree
++tree
+ get_temp_regvar (tree type, tree init)
+ {
+ tree decl;
+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;
++}
+diff --git a/gcc/testsuite/g++.dg/ext/vla10.C b/gcc/testsuite/g++.dg/ext/vla10.C
+new file mode 100644
+index 0000000..17cdb2f
+--- /dev/null
++++ b/gcc/testsuite/g++.dg/ext/vla10.C
+@@ -0,0 +1,32 @@
++// PR c++/48446
++// { dg-options "" }
++
++template<typename T>
++struct A
++{
++ ~A ();
++ T *operator-> () const;
++};
++
++struct B
++{
++ typedef A <B> P;
++ static P foo (int);
++};
++
++struct C
++{
++ typedef A<C> P;
++ static const int c = 80;
++};
++
++C::P bar ();
++
++void
++baz ()
++{
++ char z[bar ()->c];
++ {
++ B::P m = B::foo (sizeof (z));
++ }
++}
+--
+1.7.0.4
+