diff options
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.patch | 183 |
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 + |