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 0000000000..c27ea1c398 --- /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 @@ | |||
1 | From dfb9470529df202844f4b5dfe757ff07fa9bd27f Mon Sep 17 00:00:00 2001 | ||
2 | From: jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | ||
3 | Date: Fri, 6 May 2011 21:58:30 +0000 | ||
4 | Subject: [PATCH] PR c++/48446 | ||
5 | * decl.c (stabilize_save_expr_r, stabilize_vla_size): New. | ||
6 | (grokdeclarator): Use stabilize_vla_size. | ||
7 | * init.c (get_temp_regvar): No longer static. | ||
8 | * cp-tree.h: Declare it. | ||
9 | |||
10 | git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch@173514 138bc75d-0d04-0410-961f-82ee72b054a4 | ||
11 | |||
12 | index 9fbca57..be61dad 100644 | ||
13 | --- a/gcc/cp/cp-tree.h | ||
14 | +++ b/gcc/cp/cp-tree.h | ||
15 | @@ -4958,6 +4958,7 @@ extern tree build_offset_ref (tree, tree, bool); | ||
16 | extern tree build_new (VEC(tree,gc) **, tree, tree, | ||
17 | VEC(tree,gc) **, int, | ||
18 | tsubst_flags_t); | ||
19 | +extern tree get_temp_regvar (tree, tree); | ||
20 | extern tree build_vec_init (tree, tree, tree, bool, int, | ||
21 | tsubst_flags_t); | ||
22 | extern tree build_delete (tree, tree, | ||
23 | diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c | ||
24 | index 6f8bb9f..74bae0b 100644 | ||
25 | --- a/gcc/cp/decl.c | ||
26 | +++ b/gcc/cp/decl.c | ||
27 | @@ -7499,6 +7499,39 @@ check_static_variable_definition (tree decl, tree type) | ||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | +/* *expr_p is part of the TYPE_SIZE of a variably-sized array. If any | ||
32 | + SAVE_EXPRs in *expr_p wrap expressions with side-effects, break those | ||
33 | + expressions out into temporary variables so that walk_tree doesn't | ||
34 | + step into them (c++/15764). */ | ||
35 | + | ||
36 | +static tree | ||
37 | +stabilize_save_expr_r (tree *expr_p, int *walk_subtrees, void *data) | ||
38 | +{ | ||
39 | + struct pointer_set_t *pset = (struct pointer_set_t *)data; | ||
40 | + tree expr = *expr_p; | ||
41 | + if (TREE_CODE (expr) == SAVE_EXPR) | ||
42 | + { | ||
43 | + tree op = TREE_OPERAND (expr, 0); | ||
44 | + cp_walk_tree (&op, stabilize_save_expr_r, data, pset); | ||
45 | + if (TREE_SIDE_EFFECTS (op)) | ||
46 | + TREE_OPERAND (expr, 0) = get_temp_regvar (TREE_TYPE (op), op); | ||
47 | + *walk_subtrees = 0; | ||
48 | + } | ||
49 | + else if (!EXPR_P (expr) || !TREE_SIDE_EFFECTS (expr)) | ||
50 | + *walk_subtrees = 0; | ||
51 | + return NULL; | ||
52 | +} | ||
53 | + | ||
54 | +/* Entry point for the above. */ | ||
55 | + | ||
56 | +static void | ||
57 | +stabilize_vla_size (tree size) | ||
58 | +{ | ||
59 | + struct pointer_set_t *pset = pointer_set_create (); | ||
60 | + /* Break out any function calls into temporary variables. */ | ||
61 | + cp_walk_tree (&size, stabilize_save_expr_r, pset, pset); | ||
62 | +} | ||
63 | + | ||
64 | /* Given the SIZE (i.e., number of elements) in an array, compute an | ||
65 | appropriate index type for the array. If non-NULL, NAME is the | ||
66 | name of the thing being declared. */ | ||
67 | @@ -8951,7 +8984,12 @@ grokdeclarator (const cp_declarator *declarator, | ||
68 | && (decl_context == NORMAL || decl_context == FIELD) | ||
69 | && at_function_scope_p () | ||
70 | && variably_modified_type_p (type, NULL_TREE)) | ||
71 | - finish_expr_stmt (TYPE_SIZE (type)); | ||
72 | + { | ||
73 | + /* First break out any side-effects. */ | ||
74 | + stabilize_vla_size (TYPE_SIZE (type)); | ||
75 | + /* And then force evaluation of the SAVE_EXPR. */ | ||
76 | + finish_expr_stmt (TYPE_SIZE (type)); | ||
77 | + } | ||
78 | |||
79 | if (declarator->kind == cdk_reference) | ||
80 | { | ||
81 | @@ -9026,6 +9064,14 @@ grokdeclarator (const cp_declarator *declarator, | ||
82 | } | ||
83 | } | ||
84 | |||
85 | + /* We need to stabilize side-effects in VLA sizes for regular array | ||
86 | + declarations too, not just pointers to arrays. */ | ||
87 | + if (type != error_mark_node && !TYPE_NAME (type) | ||
88 | + && (decl_context == NORMAL || decl_context == FIELD) | ||
89 | + && at_function_scope_p () | ||
90 | + && variably_modified_type_p (type, NULL_TREE)) | ||
91 | + stabilize_vla_size (TYPE_SIZE (type)); | ||
92 | + | ||
93 | /* A `constexpr' specifier used in an object declaration declares | ||
94 | the object as `const'. */ | ||
95 | if (constexpr_p && innermost_code != cdk_function) | ||
96 | diff --git a/gcc/cp/init.c b/gcc/cp/init.c | ||
97 | index 4798257..ff94b71 100644 | ||
98 | --- a/gcc/cp/init.c | ||
99 | +++ b/gcc/cp/init.c | ||
100 | @@ -45,7 +45,6 @@ static void expand_virtual_init (tree, tree); | ||
101 | static tree sort_mem_initializers (tree, tree); | ||
102 | static tree initializing_context (tree); | ||
103 | static void expand_cleanup_for_base (tree, tree); | ||
104 | -static tree get_temp_regvar (tree, tree); | ||
105 | static tree dfs_initialize_vtbl_ptrs (tree, void *); | ||
106 | static tree build_dtor_call (tree, special_function_kind, int); | ||
107 | static tree build_field_list (tree, tree, int *); | ||
108 | @@ -2871,7 +2870,7 @@ create_temporary_var (tree type) | ||
109 | things when it comes time to do final cleanups (which take place | ||
110 | "outside" the binding contour of the function). */ | ||
111 | |||
112 | -static tree | ||
113 | +tree | ||
114 | get_temp_regvar (tree type, tree init) | ||
115 | { | ||
116 | tree decl; | ||
117 | new file mode 100644 | ||
118 | index 0000000..401c4e0 | ||
119 | --- /dev/null | ||
120 | +++ b/gcc/testsuite/c-c++-common/vla-1.c | ||
121 | @@ -0,0 +1,21 @@ | ||
122 | +/* Test that changes to a variable are reflected in a VLA later in the | ||
123 | + expression. */ | ||
124 | +/* { dg-options "" } */ | ||
125 | + | ||
126 | +#ifdef __cplusplus | ||
127 | +extern "C" | ||
128 | +#endif | ||
129 | +void abort(); | ||
130 | + | ||
131 | +int i = 4; | ||
132 | +int f() | ||
133 | +{ | ||
134 | + return i; | ||
135 | +} | ||
136 | + | ||
137 | +int main() | ||
138 | +{ | ||
139 | + if (i+=2, sizeof(*(int(*)[f()])0) != 6*sizeof(int)) | ||
140 | + abort(); | ||
141 | + return 0; | ||
142 | +} | ||
143 | diff --git a/gcc/testsuite/g++.dg/ext/vla10.C b/gcc/testsuite/g++.dg/ext/vla10.C | ||
144 | new file mode 100644 | ||
145 | index 0000000..17cdb2f | ||
146 | --- /dev/null | ||
147 | +++ b/gcc/testsuite/g++.dg/ext/vla10.C | ||
148 | @@ -0,0 +1,32 @@ | ||
149 | +// PR c++/48446 | ||
150 | +// { dg-options "" } | ||
151 | + | ||
152 | +template<typename T> | ||
153 | +struct A | ||
154 | +{ | ||
155 | + ~A (); | ||
156 | + T *operator-> () const; | ||
157 | +}; | ||
158 | + | ||
159 | +struct B | ||
160 | +{ | ||
161 | + typedef A <B> P; | ||
162 | + static P foo (int); | ||
163 | +}; | ||
164 | + | ||
165 | +struct C | ||
166 | +{ | ||
167 | + typedef A<C> P; | ||
168 | + static const int c = 80; | ||
169 | +}; | ||
170 | + | ||
171 | +C::P bar (); | ||
172 | + | ||
173 | +void | ||
174 | +baz () | ||
175 | +{ | ||
176 | + char z[bar ()->c]; | ||
177 | + { | ||
178 | + B::P m = B::foo (sizeof (z)); | ||
179 | + } | ||
180 | +} | ||
181 | -- | ||
182 | 1.7.0.4 | ||
183 | |||