]>
Commit | Line | Data |
---|---|---|
eadf906f | 1 | /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c. |
6de9cd9a | 2 | |
f74d9c8f | 3 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 |
e77f031d | 4 | Free Software Foundation, Inc. |
6de9cd9a DN |
5 | Contributed by Jason Merrill <jason@redhat.com> |
6 | ||
7 | This file is part of GCC. | |
8 | ||
9 | GCC is free software; you can redistribute it and/or modify it under | |
10 | the terms of the GNU General Public License as published by the Free | |
e77f031d | 11 | Software Foundation; either version 3, or (at your option) any later |
6de9cd9a DN |
12 | version. |
13 | ||
14 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
15 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 | for more details. | |
18 | ||
19 | You should have received a copy of the GNU General Public License | |
e77f031d NC |
20 | along with GCC; see the file COPYING3. If not see |
21 | <http://www.gnu.org/licenses/>. */ | |
6de9cd9a DN |
22 | |
23 | #include "config.h" | |
24 | #include "system.h" | |
25 | #include "coretypes.h" | |
26 | #include "tm.h" | |
27 | #include "tree.h" | |
28 | #include "cp-tree.h" | |
29 | #include "c-common.h" | |
30 | #include "toplev.h" | |
726a989a RB |
31 | #include "tree-iterator.h" |
32 | #include "gimple.h" | |
d8472c75 | 33 | #include "hashtab.h" |
e09a5d62 | 34 | #include "pointer-set.h" |
934790cc | 35 | #include "flags.h" |
6de9cd9a | 36 | |
fbc315db ILT |
37 | /* Local declarations. */ |
38 | ||
39 | enum bc_t { bc_break = 0, bc_continue = 1 }; | |
40 | ||
1799e5d5 RH |
41 | /* Stack of labels which are targets for "break" or "continue", |
42 | linked through TREE_CHAIN. */ | |
43 | static tree bc_label[2]; | |
fbc315db ILT |
44 | |
45 | /* Begin a scope which can be exited by a break or continue statement. BC | |
46 | indicates which. | |
47 | ||
48 | Just creates a label and pushes it into the current context. */ | |
49 | ||
50 | static tree | |
51 | begin_bc_block (enum bc_t bc) | |
52 | { | |
c2255bc4 | 53 | tree label = create_artificial_label (input_location); |
1799e5d5 RH |
54 | TREE_CHAIN (label) = bc_label[bc]; |
55 | bc_label[bc] = label; | |
fbc315db ILT |
56 | return label; |
57 | } | |
58 | ||
59 | /* Finish a scope which can be exited by a break or continue statement. | |
60 | LABEL was returned from the most recent call to begin_bc_block. BODY is | |
61 | an expression for the contents of the scope. | |
62 | ||
63 | If we saw a break (or continue) in the scope, append a LABEL_EXPR to | |
64 | body. Otherwise, just forget the label. */ | |
65 | ||
726a989a RB |
66 | static gimple_seq |
67 | finish_bc_block (enum bc_t bc, tree label, gimple_seq body) | |
fbc315db | 68 | { |
1799e5d5 | 69 | gcc_assert (label == bc_label[bc]); |
fbc315db ILT |
70 | |
71 | if (TREE_USED (label)) | |
72 | { | |
726a989a | 73 | gimple_seq_add_stmt (&body, gimple_build_label (label)); |
fbc315db ILT |
74 | } |
75 | ||
1799e5d5 | 76 | bc_label[bc] = TREE_CHAIN (label); |
fbc315db ILT |
77 | TREE_CHAIN (label) = NULL_TREE; |
78 | return body; | |
79 | } | |
80 | ||
726a989a RB |
81 | /* Get the LABEL_EXPR to represent a break or continue statement |
82 | in the current block scope. BC indicates which. */ | |
fbc315db ILT |
83 | |
84 | static tree | |
726a989a | 85 | get_bc_label (enum bc_t bc) |
fbc315db | 86 | { |
1799e5d5 | 87 | tree label = bc_label[bc]; |
fbc315db ILT |
88 | |
89 | if (label == NULL_TREE) | |
90 | { | |
91 | if (bc == bc_break) | |
92 | error ("break statement not within loop or switch"); | |
93 | else | |
94 | error ("continue statement not within loop or switch"); | |
95 | ||
96 | return NULL_TREE; | |
97 | } | |
98 | ||
99 | /* Mark the label used for finish_bc_block. */ | |
100 | TREE_USED (label) = 1; | |
726a989a | 101 | return label; |
fbc315db ILT |
102 | } |
103 | ||
6de9cd9a DN |
104 | /* Genericize a TRY_BLOCK. */ |
105 | ||
106 | static void | |
107 | genericize_try_block (tree *stmt_p) | |
108 | { | |
109 | tree body = TRY_STMTS (*stmt_p); | |
110 | tree cleanup = TRY_HANDLERS (*stmt_p); | |
111 | ||
f293ce4b | 112 | *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup); |
6de9cd9a DN |
113 | } |
114 | ||
115 | /* Genericize a HANDLER by converting to a CATCH_EXPR. */ | |
116 | ||
117 | static void | |
118 | genericize_catch_block (tree *stmt_p) | |
119 | { | |
120 | tree type = HANDLER_TYPE (*stmt_p); | |
121 | tree body = HANDLER_BODY (*stmt_p); | |
122 | ||
6de9cd9a | 123 | /* FIXME should the caught type go in TREE_TYPE? */ |
f293ce4b | 124 | *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body); |
6de9cd9a DN |
125 | } |
126 | ||
726a989a RB |
127 | /* A terser interface for building a representation of an exception |
128 | specification. */ | |
129 | ||
130 | static tree | |
131 | build_gimple_eh_filter_tree (tree body, tree allowed, tree failure) | |
132 | { | |
133 | tree t; | |
134 | ||
135 | /* FIXME should the allowed types go in TREE_TYPE? */ | |
136 | t = build2 (EH_FILTER_EXPR, void_type_node, allowed, NULL_TREE); | |
137 | append_to_statement_list (failure, &EH_FILTER_FAILURE (t)); | |
138 | ||
139 | t = build2 (TRY_CATCH_EXPR, void_type_node, NULL_TREE, t); | |
140 | append_to_statement_list (body, &TREE_OPERAND (t, 0)); | |
141 | ||
142 | return t; | |
143 | } | |
144 | ||
6de9cd9a DN |
145 | /* Genericize an EH_SPEC_BLOCK by converting it to a |
146 | TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */ | |
147 | ||
148 | static void | |
149 | genericize_eh_spec_block (tree *stmt_p) | |
150 | { | |
151 | tree body = EH_SPEC_STMTS (*stmt_p); | |
152 | tree allowed = EH_SPEC_RAISES (*stmt_p); | |
94a0dd7b | 153 | tree failure = build_call_n (call_unexpected_node, 1, build_exc_ptr ()); |
6de9cd9a | 154 | |
726a989a | 155 | *stmt_p = build_gimple_eh_filter_tree (body, allowed, failure); |
d665b6e5 MLI |
156 | TREE_NO_WARNING (*stmt_p) = true; |
157 | TREE_NO_WARNING (TREE_OPERAND (*stmt_p, 1)) = true; | |
6de9cd9a DN |
158 | } |
159 | ||
5a508662 RH |
160 | /* Genericize an IF_STMT by turning it into a COND_EXPR. */ |
161 | ||
162 | static void | |
f74d9c8f | 163 | genericize_if_stmt (tree *stmt_p) |
5a508662 | 164 | { |
eeae0768 | 165 | tree stmt, cond, then_, else_; |
726a989a | 166 | location_t locus = EXPR_LOCATION (*stmt_p); |
5a508662 RH |
167 | |
168 | stmt = *stmt_p; | |
eeae0768 | 169 | cond = IF_COND (stmt); |
5a508662 RH |
170 | then_ = THEN_CLAUSE (stmt); |
171 | else_ = ELSE_CLAUSE (stmt); | |
172 | ||
173 | if (!then_) | |
c2255bc4 | 174 | then_ = build_empty_stmt (locus); |
5a508662 | 175 | if (!else_) |
c2255bc4 | 176 | else_ = build_empty_stmt (locus); |
5a508662 | 177 | |
eeae0768 RS |
178 | if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_)) |
179 | stmt = then_; | |
180 | else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_)) | |
181 | stmt = else_; | |
182 | else | |
183 | stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_); | |
726a989a RB |
184 | if (CAN_HAVE_LOCATION_P (stmt) && !EXPR_HAS_LOCATION (stmt)) |
185 | SET_EXPR_LOCATION (stmt, locus); | |
5a508662 RH |
186 | *stmt_p = stmt; |
187 | } | |
188 | ||
fbc315db ILT |
189 | /* Build a generic representation of one of the C loop forms. COND is the |
190 | loop condition or NULL_TREE. BODY is the (possibly compound) statement | |
191 | controlled by the loop. INCR is the increment expression of a for-loop, | |
192 | or NULL_TREE. COND_IS_FIRST indicates whether the condition is | |
193 | evaluated before the loop body as in while and for loops, or after the | |
194 | loop body as in do-while loops. */ | |
195 | ||
726a989a | 196 | static gimple_seq |
fbc315db ILT |
197 | gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first) |
198 | { | |
726a989a RB |
199 | gimple top, entry, stmt; |
200 | gimple_seq stmt_list, body_seq, incr_seq, exit_seq; | |
201 | tree cont_block, break_block; | |
fbc315db ILT |
202 | location_t stmt_locus; |
203 | ||
204 | stmt_locus = input_location; | |
726a989a RB |
205 | stmt_list = NULL; |
206 | body_seq = NULL; | |
207 | incr_seq = NULL; | |
208 | exit_seq = NULL; | |
209 | entry = NULL; | |
fbc315db ILT |
210 | |
211 | break_block = begin_bc_block (bc_break); | |
212 | cont_block = begin_bc_block (bc_continue); | |
213 | ||
214 | /* If condition is zero don't generate a loop construct. */ | |
215 | if (cond && integer_zerop (cond)) | |
216 | { | |
726a989a | 217 | top = NULL; |
fbc315db ILT |
218 | if (cond_is_first) |
219 | { | |
726a989a RB |
220 | stmt = gimple_build_goto (get_bc_label (bc_break)); |
221 | gimple_set_location (stmt, stmt_locus); | |
222 | gimple_seq_add_stmt (&stmt_list, stmt); | |
fbc315db ILT |
223 | } |
224 | } | |
225 | else | |
226 | { | |
227 | /* If we use a LOOP_EXPR here, we have to feed the whole thing | |
228 | back through the main gimplifier to lower it. Given that we | |
229 | have to gimplify the loop body NOW so that we can resolve | |
230 | break/continue stmts, seems easier to just expand to gotos. */ | |
c2255bc4 | 231 | top = gimple_build_label (create_artificial_label (stmt_locus)); |
fbc315db ILT |
232 | |
233 | /* If we have an exit condition, then we build an IF with gotos either | |
234 | out of the loop, or to the top of it. If there's no exit condition, | |
235 | then we just build a jump back to the top. */ | |
fbc315db ILT |
236 | if (cond && !integer_nonzerop (cond)) |
237 | { | |
726a989a RB |
238 | if (cond != error_mark_node) |
239 | { | |
240 | gimplify_expr (&cond, &exit_seq, NULL, is_gimple_val, fb_rvalue); | |
241 | stmt = gimple_build_cond (NE_EXPR, cond, | |
242 | build_int_cst (TREE_TYPE (cond), 0), | |
243 | gimple_label_label (top), | |
244 | get_bc_label (bc_break)); | |
245 | gimple_seq_add_stmt (&exit_seq, stmt); | |
246 | } | |
fbc315db ILT |
247 | |
248 | if (cond_is_first) | |
249 | { | |
250 | if (incr) | |
251 | { | |
c2255bc4 AH |
252 | entry = gimple_build_label |
253 | (create_artificial_label (stmt_locus)); | |
726a989a | 254 | stmt = gimple_build_goto (gimple_label_label (entry)); |
fbc315db ILT |
255 | } |
256 | else | |
726a989a RB |
257 | stmt = gimple_build_goto (get_bc_label (bc_continue)); |
258 | gimple_set_location (stmt, stmt_locus); | |
259 | gimple_seq_add_stmt (&stmt_list, stmt); | |
fbc315db ILT |
260 | } |
261 | } | |
726a989a RB |
262 | else |
263 | { | |
264 | stmt = gimple_build_goto (gimple_label_label (top)); | |
265 | gimple_seq_add_stmt (&exit_seq, stmt); | |
266 | } | |
fbc315db ILT |
267 | } |
268 | ||
726a989a RB |
269 | gimplify_stmt (&body, &body_seq); |
270 | gimplify_stmt (&incr, &incr_seq); | |
fbc315db | 271 | |
726a989a | 272 | body_seq = finish_bc_block (bc_continue, cont_block, body_seq); |
fbc315db | 273 | |
726a989a RB |
274 | gimple_seq_add_stmt (&stmt_list, top); |
275 | gimple_seq_add_seq (&stmt_list, body_seq); | |
276 | gimple_seq_add_seq (&stmt_list, incr_seq); | |
277 | gimple_seq_add_stmt (&stmt_list, entry); | |
278 | gimple_seq_add_seq (&stmt_list, exit_seq); | |
fbc315db | 279 | |
726a989a | 280 | annotate_all_with_location (stmt_list, stmt_locus); |
fbc315db ILT |
281 | |
282 | return finish_bc_block (bc_break, break_block, stmt_list); | |
283 | } | |
284 | ||
285 | /* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the | |
286 | prequeue and hand off to gimplify_cp_loop. */ | |
287 | ||
288 | static void | |
726a989a | 289 | gimplify_for_stmt (tree *stmt_p, gimple_seq *pre_p) |
fbc315db ILT |
290 | { |
291 | tree stmt = *stmt_p; | |
292 | ||
293 | if (FOR_INIT_STMT (stmt)) | |
294 | gimplify_and_add (FOR_INIT_STMT (stmt), pre_p); | |
295 | ||
726a989a RB |
296 | gimple_seq_add_seq (pre_p, |
297 | gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt), | |
298 | FOR_EXPR (stmt), 1)); | |
299 | *stmt_p = NULL_TREE; | |
fbc315db ILT |
300 | } |
301 | ||
302 | /* Gimplify a WHILE_STMT node. */ | |
303 | ||
304 | static void | |
726a989a | 305 | gimplify_while_stmt (tree *stmt_p, gimple_seq *pre_p) |
fbc315db ILT |
306 | { |
307 | tree stmt = *stmt_p; | |
726a989a RB |
308 | gimple_seq_add_seq (pre_p, |
309 | gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt), | |
310 | NULL_TREE, 1)); | |
311 | *stmt_p = NULL_TREE; | |
fbc315db ILT |
312 | } |
313 | ||
314 | /* Gimplify a DO_STMT node. */ | |
315 | ||
316 | static void | |
726a989a | 317 | gimplify_do_stmt (tree *stmt_p, gimple_seq *pre_p) |
fbc315db ILT |
318 | { |
319 | tree stmt = *stmt_p; | |
726a989a RB |
320 | gimple_seq_add_seq (pre_p, |
321 | gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt), | |
322 | NULL_TREE, 0)); | |
323 | *stmt_p = NULL_TREE; | |
fbc315db ILT |
324 | } |
325 | ||
326 | /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */ | |
327 | ||
328 | static void | |
726a989a | 329 | gimplify_switch_stmt (tree *stmt_p, gimple_seq *pre_p) |
fbc315db ILT |
330 | { |
331 | tree stmt = *stmt_p; | |
726a989a | 332 | tree break_block, body, t; |
fbc315db | 333 | location_t stmt_locus = input_location; |
726a989a | 334 | gimple_seq seq = NULL; |
fbc315db ILT |
335 | |
336 | break_block = begin_bc_block (bc_break); | |
337 | ||
338 | body = SWITCH_STMT_BODY (stmt); | |
339 | if (!body) | |
c2255bc4 | 340 | body = build_empty_stmt (stmt_locus); |
fbc315db | 341 | |
726a989a RB |
342 | t = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt), |
343 | SWITCH_STMT_COND (stmt), body, NULL_TREE); | |
344 | SET_EXPR_LOCATION (t, stmt_locus); | |
345 | gimplify_and_add (t, &seq); | |
fbc315db | 346 | |
726a989a RB |
347 | seq = finish_bc_block (bc_break, break_block, seq); |
348 | gimple_seq_add_seq (pre_p, seq); | |
349 | *stmt_p = NULL_TREE; | |
fbc315db ILT |
350 | } |
351 | ||
1799e5d5 RH |
352 | /* Hook into the middle of gimplifying an OMP_FOR node. This is required |
353 | in order to properly gimplify CONTINUE statements. Here we merely | |
354 | manage the continue stack; the rest of the job is performed by the | |
3db45ab5 | 355 | regular gimplifier. */ |
1799e5d5 RH |
356 | |
357 | static enum gimplify_status | |
726a989a | 358 | cp_gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) |
1799e5d5 RH |
359 | { |
360 | tree for_stmt = *expr_p; | |
361 | tree cont_block; | |
726a989a RB |
362 | gimple stmt; |
363 | gimple_seq seq = NULL; | |
1799e5d5 RH |
364 | |
365 | /* Protect ourselves from recursion. */ | |
366 | if (OMP_FOR_GIMPLIFYING_P (for_stmt)) | |
367 | return GS_UNHANDLED; | |
368 | OMP_FOR_GIMPLIFYING_P (for_stmt) = 1; | |
369 | ||
370 | /* Note that while technically the continue label is enabled too soon | |
371 | here, we should have already diagnosed invalid continues nested within | |
372 | statement expressions within the INIT, COND, or INCR expressions. */ | |
373 | cont_block = begin_bc_block (bc_continue); | |
374 | ||
726a989a RB |
375 | gimplify_and_add (for_stmt, &seq); |
376 | stmt = gimple_seq_last_stmt (seq); | |
377 | if (gimple_code (stmt) == GIMPLE_OMP_FOR) | |
378 | gimple_omp_set_body (stmt, finish_bc_block (bc_continue, cont_block, | |
379 | gimple_omp_body (stmt))); | |
380 | else | |
381 | seq = finish_bc_block (bc_continue, cont_block, seq); | |
382 | gimple_seq_add_seq (pre_p, seq); | |
1799e5d5 | 383 | |
1799e5d5 RH |
384 | OMP_FOR_GIMPLIFYING_P (for_stmt) = 0; |
385 | ||
386 | return GS_ALL_DONE; | |
387 | } | |
388 | ||
934790cc ILT |
389 | /* Gimplify an EXPR_STMT node. */ |
390 | ||
391 | static void | |
392 | gimplify_expr_stmt (tree *stmt_p) | |
393 | { | |
394 | tree stmt = EXPR_STMT_EXPR (*stmt_p); | |
395 | ||
396 | if (stmt == error_mark_node) | |
397 | stmt = NULL; | |
398 | ||
399 | /* Gimplification of a statement expression will nullify the | |
400 | statement if all its side effects are moved to *PRE_P and *POST_P. | |
401 | ||
402 | In this case we will not want to emit the gimplified statement. | |
403 | However, we may still want to emit a warning, so we do that before | |
404 | gimplification. */ | |
27f33b15 | 405 | if (stmt && warn_unused_value) |
934790cc ILT |
406 | { |
407 | if (!TREE_SIDE_EFFECTS (stmt)) | |
408 | { | |
409 | if (!IS_EMPTY_STMT (stmt) | |
410 | && !VOID_TYPE_P (TREE_TYPE (stmt)) | |
411 | && !TREE_NO_WARNING (stmt)) | |
27f33b15 | 412 | warning (OPT_Wunused_value, "statement with no effect"); |
934790cc | 413 | } |
27f33b15 | 414 | else |
934790cc ILT |
415 | warn_if_unused_value (stmt, input_location); |
416 | } | |
417 | ||
418 | if (stmt == NULL_TREE) | |
419 | stmt = alloc_stmt_list (); | |
420 | ||
421 | *stmt_p = stmt; | |
422 | } | |
423 | ||
6de9cd9a DN |
424 | /* Gimplify initialization from an AGGR_INIT_EXPR. */ |
425 | ||
426 | static void | |
726a989a | 427 | cp_gimplify_init_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) |
6de9cd9a DN |
428 | { |
429 | tree from = TREE_OPERAND (*expr_p, 1); | |
430 | tree to = TREE_OPERAND (*expr_p, 0); | |
0fcedd9c | 431 | tree t; |
6de9cd9a | 432 | |
6de9cd9a DN |
433 | /* What about code that pulls out the temp and uses it elsewhere? I |
434 | think that such code never uses the TARGET_EXPR as an initializer. If | |
435 | I'm wrong, we'll abort because the temp won't have any RTL. In that | |
436 | case, I guess we'll need to replace references somehow. */ | |
437 | if (TREE_CODE (from) == TARGET_EXPR) | |
db80e34e | 438 | from = TARGET_EXPR_INITIAL (from); |
6de9cd9a | 439 | |
c6c7698d JM |
440 | /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them |
441 | inside the TARGET_EXPR. */ | |
0fcedd9c JM |
442 | for (t = from; t; ) |
443 | { | |
444 | tree sub = TREE_CODE (t) == COMPOUND_EXPR ? TREE_OPERAND (t, 0) : t; | |
6de9cd9a | 445 | |
0fcedd9c JM |
446 | /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and |
447 | replace the slot operand with our target. | |
6de9cd9a | 448 | |
0fcedd9c JM |
449 | Should we add a target parm to gimplify_expr instead? No, as in this |
450 | case we want to replace the INIT_EXPR. */ | |
d5f4eddd JM |
451 | if (TREE_CODE (sub) == AGGR_INIT_EXPR |
452 | || TREE_CODE (sub) == VEC_INIT_EXPR) | |
0fcedd9c JM |
453 | { |
454 | gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue); | |
d5f4eddd JM |
455 | if (TREE_CODE (sub) == AGGR_INIT_EXPR) |
456 | AGGR_INIT_EXPR_SLOT (sub) = to; | |
457 | else | |
458 | VEC_INIT_EXPR_SLOT (sub) = to; | |
0fcedd9c JM |
459 | *expr_p = from; |
460 | ||
461 | /* The initialization is now a side-effect, so the container can | |
462 | become void. */ | |
463 | if (from != sub) | |
464 | TREE_TYPE (from) = void_type_node; | |
465 | } | |
0fcedd9c JM |
466 | |
467 | if (t == sub) | |
468 | break; | |
469 | else | |
470 | t = TREE_OPERAND (t, 1); | |
6de9cd9a | 471 | } |
0fcedd9c | 472 | |
6de9cd9a DN |
473 | } |
474 | ||
475 | /* Gimplify a MUST_NOT_THROW_EXPR. */ | |
476 | ||
726a989a RB |
477 | static enum gimplify_status |
478 | gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p) | |
6de9cd9a DN |
479 | { |
480 | tree stmt = *expr_p; | |
325c3691 | 481 | tree temp = voidify_wrapper_expr (stmt, NULL); |
6de9cd9a DN |
482 | tree body = TREE_OPERAND (stmt, 0); |
483 | ||
726a989a RB |
484 | stmt = build_gimple_eh_filter_tree (body, NULL_TREE, |
485 | build_call_n (terminate_node, 0)); | |
6de9cd9a | 486 | |
726a989a | 487 | gimplify_and_add (stmt, pre_p); |
6de9cd9a DN |
488 | if (temp) |
489 | { | |
6de9cd9a | 490 | *expr_p = temp; |
726a989a | 491 | return GS_OK; |
6de9cd9a | 492 | } |
726a989a RB |
493 | |
494 | *expr_p = NULL; | |
495 | return GS_ALL_DONE; | |
6de9cd9a | 496 | } |
7c34ced1 RH |
497 | |
498 | /* Do C++-specific gimplification. Args are as for gimplify_expr. */ | |
499 | ||
500 | int | |
726a989a | 501 | cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) |
7c34ced1 RH |
502 | { |
503 | int saved_stmts_are_full_exprs_p = 0; | |
504 | enum tree_code code = TREE_CODE (*expr_p); | |
505 | enum gimplify_status ret; | |
506 | ||
507 | if (STATEMENT_CODE_P (code)) | |
508 | { | |
509 | saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); | |
510 | current_stmt_tree ()->stmts_are_full_exprs_p | |
511 | = STMT_IS_FULL_EXPR_P (*expr_p); | |
512 | } | |
513 | ||
514 | switch (code) | |
515 | { | |
516 | case PTRMEM_CST: | |
517 | *expr_p = cplus_expand_constant (*expr_p); | |
518 | ret = GS_OK; | |
519 | break; | |
520 | ||
521 | case AGGR_INIT_EXPR: | |
522 | simplify_aggr_init_expr (expr_p); | |
523 | ret = GS_OK; | |
524 | break; | |
525 | ||
d5f4eddd JM |
526 | case VEC_INIT_EXPR: |
527 | { | |
528 | location_t loc = input_location; | |
529 | gcc_assert (EXPR_HAS_LOCATION (*expr_p)); | |
530 | input_location = EXPR_LOCATION (*expr_p); | |
531 | *expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE, | |
532 | VEC_INIT_EXPR_INIT (*expr_p), false, 1, | |
533 | tf_warning_or_error); | |
534 | ret = GS_OK; | |
535 | input_location = loc; | |
536 | } | |
537 | break; | |
538 | ||
7c34ced1 | 539 | case THROW_EXPR: |
3b426391 | 540 | /* FIXME communicate throw type to back end, probably by moving |
7c34ced1 RH |
541 | THROW_EXPR into ../tree.def. */ |
542 | *expr_p = TREE_OPERAND (*expr_p, 0); | |
543 | ret = GS_OK; | |
544 | break; | |
545 | ||
546 | case MUST_NOT_THROW_EXPR: | |
726a989a | 547 | ret = gimplify_must_not_throw_expr (expr_p, pre_p); |
7c34ced1 RH |
548 | break; |
549 | ||
726a989a | 550 | /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the |
dae7ec87 JM |
551 | LHS of an assignment might also be involved in the RHS, as in bug |
552 | 25979. */ | |
7c34ced1 | 553 | case INIT_EXPR: |
7c34ced1 | 554 | cp_gimplify_init_expr (expr_p, pre_p, post_p); |
85a52ea5 JM |
555 | if (TREE_CODE (*expr_p) != INIT_EXPR) |
556 | return GS_OK; | |
557 | /* Otherwise fall through. */ | |
1e2ddf80 JM |
558 | case MODIFY_EXPR: |
559 | { | |
560 | /* If the back end isn't clever enough to know that the lhs and rhs | |
561 | types are the same, add an explicit conversion. */ | |
562 | tree op0 = TREE_OPERAND (*expr_p, 0); | |
563 | tree op1 = TREE_OPERAND (*expr_p, 1); | |
564 | ||
0d08582e JM |
565 | if (!error_operand_p (op0) |
566 | && !error_operand_p (op1) | |
567 | && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0)) | |
568 | || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1))) | |
1e2ddf80 JM |
569 | && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0))) |
570 | TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR, | |
571 | TREE_TYPE (op0), op1); | |
6d729f28 JM |
572 | |
573 | else if ((rhs_predicate_for (op0)) (op1) | |
574 | && !(TREE_CODE (op1) == CALL_EXPR | |
575 | && CALL_EXPR_RETURN_SLOT_OPT (op1)) | |
576 | && is_really_empty_class (TREE_TYPE (op0))) | |
577 | { | |
578 | /* Remove any copies of empty classes. We check that the RHS | |
579 | has a simple form so that TARGET_EXPRs and CONSTRUCTORs get | |
580 | reduced properly, and we leave the return slot optimization | |
581 | alone because it isn't a copy. | |
582 | ||
583 | Also drop volatile variables on the RHS to avoid infinite | |
584 | recursion from gimplify_expr trying to load the value. */ | |
585 | if (!TREE_SIDE_EFFECTS (op1) | |
586 | || (DECL_P (op1) && TREE_THIS_VOLATILE (op1))) | |
587 | *expr_p = op0; | |
588 | else | |
589 | *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p), | |
590 | op0, op1); | |
591 | } | |
1e2ddf80 | 592 | } |
7c34ced1 RH |
593 | ret = GS_OK; |
594 | break; | |
595 | ||
596 | case EMPTY_CLASS_EXPR: | |
f7683d37 RG |
597 | /* We create an empty CONSTRUCTOR with RECORD_TYPE. */ |
598 | *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL); | |
7c34ced1 RH |
599 | ret = GS_OK; |
600 | break; | |
601 | ||
602 | case BASELINK: | |
603 | *expr_p = BASELINK_FUNCTIONS (*expr_p); | |
604 | ret = GS_OK; | |
605 | break; | |
606 | ||
607 | case TRY_BLOCK: | |
608 | genericize_try_block (expr_p); | |
609 | ret = GS_OK; | |
610 | break; | |
611 | ||
612 | case HANDLER: | |
613 | genericize_catch_block (expr_p); | |
614 | ret = GS_OK; | |
615 | break; | |
616 | ||
617 | case EH_SPEC_BLOCK: | |
618 | genericize_eh_spec_block (expr_p); | |
619 | ret = GS_OK; | |
620 | break; | |
621 | ||
622 | case USING_STMT: | |
ac3cbee5 | 623 | gcc_unreachable (); |
7c34ced1 | 624 | |
fbc315db ILT |
625 | case FOR_STMT: |
626 | gimplify_for_stmt (expr_p, pre_p); | |
726a989a | 627 | ret = GS_OK; |
fbc315db ILT |
628 | break; |
629 | ||
630 | case WHILE_STMT: | |
726a989a RB |
631 | gimplify_while_stmt (expr_p, pre_p); |
632 | ret = GS_OK; | |
fbc315db ILT |
633 | break; |
634 | ||
635 | case DO_STMT: | |
726a989a RB |
636 | gimplify_do_stmt (expr_p, pre_p); |
637 | ret = GS_OK; | |
fbc315db ILT |
638 | break; |
639 | ||
640 | case SWITCH_STMT: | |
726a989a RB |
641 | gimplify_switch_stmt (expr_p, pre_p); |
642 | ret = GS_OK; | |
fbc315db ILT |
643 | break; |
644 | ||
1799e5d5 | 645 | case OMP_FOR: |
726a989a | 646 | ret = cp_gimplify_omp_for (expr_p, pre_p); |
1799e5d5 RH |
647 | break; |
648 | ||
fbc315db | 649 | case CONTINUE_STMT: |
7299cb99 | 650 | gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_CONTINUE, NOT_TAKEN)); |
726a989a RB |
651 | gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_continue))); |
652 | *expr_p = NULL_TREE; | |
fbc315db ILT |
653 | ret = GS_ALL_DONE; |
654 | break; | |
655 | ||
656 | case BREAK_STMT: | |
726a989a RB |
657 | gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_break))); |
658 | *expr_p = NULL_TREE; | |
fbc315db ILT |
659 | ret = GS_ALL_DONE; |
660 | break; | |
661 | ||
934790cc ILT |
662 | case EXPR_STMT: |
663 | gimplify_expr_stmt (expr_p); | |
664 | ret = GS_OK; | |
665 | break; | |
666 | ||
392e3d51 RS |
667 | case UNARY_PLUS_EXPR: |
668 | { | |
669 | tree arg = TREE_OPERAND (*expr_p, 0); | |
670 | tree type = TREE_TYPE (*expr_p); | |
671 | *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg) | |
672 | : arg; | |
673 | ret = GS_OK; | |
674 | } | |
675 | break; | |
676 | ||
7c34ced1 | 677 | default: |
32e8bb8e | 678 | ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p); |
7c34ced1 RH |
679 | break; |
680 | } | |
681 | ||
682 | /* Restore saved state. */ | |
683 | if (STATEMENT_CODE_P (code)) | |
684 | current_stmt_tree ()->stmts_are_full_exprs_p | |
685 | = saved_stmts_are_full_exprs_p; | |
686 | ||
687 | return ret; | |
688 | } | |
5a508662 | 689 | |
d8472c75 | 690 | static inline bool |
58f9752a | 691 | is_invisiref_parm (const_tree t) |
d8472c75 | 692 | { |
cc77ae10 | 693 | return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL) |
d8472c75 JM |
694 | && DECL_BY_REFERENCE (t)); |
695 | } | |
696 | ||
10827cd8 JJ |
697 | /* Return true if the uid in both int tree maps are equal. */ |
698 | ||
699 | int | |
700 | cxx_int_tree_map_eq (const void *va, const void *vb) | |
701 | { | |
702 | const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va; | |
703 | const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb; | |
704 | return (a->uid == b->uid); | |
705 | } | |
706 | ||
707 | /* Hash a UID in a cxx_int_tree_map. */ | |
708 | ||
709 | unsigned int | |
710 | cxx_int_tree_map_hash (const void *item) | |
711 | { | |
712 | return ((const struct cxx_int_tree_map *)item)->uid; | |
713 | } | |
714 | ||
ac3cbee5 RG |
715 | struct cp_genericize_data |
716 | { | |
717 | struct pointer_set_t *p_set; | |
718 | VEC (tree, heap) *bind_expr_stack; | |
719 | }; | |
720 | ||
d8472c75 JM |
721 | /* Perform any pre-gimplification lowering of C++ front end trees to |
722 | GENERIC. */ | |
5a508662 RH |
723 | |
724 | static tree | |
d8472c75 | 725 | cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) |
5a508662 RH |
726 | { |
727 | tree stmt = *stmt_p; | |
ac3cbee5 RG |
728 | struct cp_genericize_data *wtd = (struct cp_genericize_data *) data; |
729 | struct pointer_set_t *p_set = wtd->p_set; | |
5a508662 | 730 | |
5b009a96 JM |
731 | if (is_invisiref_parm (stmt) |
732 | /* Don't dereference parms in a thunk, pass the references through. */ | |
733 | && !(DECL_THUNK_P (current_function_decl) | |
3db45ab5 | 734 | && TREE_CODE (stmt) == PARM_DECL)) |
d8472c75 | 735 | { |
cc77ae10 | 736 | *stmt_p = convert_from_reference (stmt); |
d8472c75 JM |
737 | *walk_subtrees = 0; |
738 | return NULL; | |
739 | } | |
740 | ||
10827cd8 JJ |
741 | /* Map block scope extern declarations to visible declarations with the |
742 | same name and type in outer scopes if any. */ | |
743 | if (cp_function_chain->extern_decl_map | |
744 | && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL) | |
745 | && DECL_EXTERNAL (stmt)) | |
746 | { | |
747 | struct cxx_int_tree_map *h, in; | |
748 | in.uid = DECL_UID (stmt); | |
749 | h = (struct cxx_int_tree_map *) | |
750 | htab_find_with_hash (cp_function_chain->extern_decl_map, | |
751 | &in, in.uid); | |
752 | if (h) | |
753 | { | |
754 | *stmt_p = h->to; | |
755 | *walk_subtrees = 0; | |
756 | return NULL; | |
757 | } | |
758 | } | |
759 | ||
d8472c75 | 760 | /* Other than invisiref parms, don't walk the same tree twice. */ |
af76441f | 761 | if (pointer_set_contains (p_set, stmt)) |
d8472c75 JM |
762 | { |
763 | *walk_subtrees = 0; | |
764 | return NULL_TREE; | |
765 | } | |
766 | ||
767 | if (TREE_CODE (stmt) == ADDR_EXPR | |
768 | && is_invisiref_parm (TREE_OPERAND (stmt, 0))) | |
769 | { | |
770 | *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0)); | |
771 | *walk_subtrees = 0; | |
772 | } | |
cc77ae10 JM |
773 | else if (TREE_CODE (stmt) == RETURN_EXPR |
774 | && TREE_OPERAND (stmt, 0) | |
775 | && is_invisiref_parm (TREE_OPERAND (stmt, 0))) | |
776 | /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */ | |
777 | *walk_subtrees = 0; | |
e02a048f JJ |
778 | else if (TREE_CODE (stmt) == OMP_CLAUSE) |
779 | switch (OMP_CLAUSE_CODE (stmt)) | |
780 | { | |
a68ab351 JJ |
781 | case OMP_CLAUSE_LASTPRIVATE: |
782 | /* Don't dereference an invisiref in OpenMP clauses. */ | |
783 | if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) | |
784 | { | |
785 | *walk_subtrees = 0; | |
786 | if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt)) | |
787 | cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt), | |
ac3cbee5 | 788 | cp_genericize_r, data, NULL); |
a68ab351 JJ |
789 | } |
790 | break; | |
e02a048f JJ |
791 | case OMP_CLAUSE_PRIVATE: |
792 | case OMP_CLAUSE_SHARED: | |
793 | case OMP_CLAUSE_FIRSTPRIVATE: | |
e02a048f JJ |
794 | case OMP_CLAUSE_COPYIN: |
795 | case OMP_CLAUSE_COPYPRIVATE: | |
796 | /* Don't dereference an invisiref in OpenMP clauses. */ | |
797 | if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) | |
798 | *walk_subtrees = 0; | |
799 | break; | |
800 | case OMP_CLAUSE_REDUCTION: | |
801 | gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt))); | |
802 | break; | |
803 | default: | |
804 | break; | |
805 | } | |
6615c446 | 806 | else if (IS_TYPE_OR_DECL_P (stmt)) |
5a508662 | 807 | *walk_subtrees = 0; |
d8472c75 JM |
808 | |
809 | /* Due to the way voidify_wrapper_expr is written, we don't get a chance | |
810 | to lower this construct before scanning it, so we need to lower these | |
811 | before doing anything else. */ | |
5a508662 | 812 | else if (TREE_CODE (stmt) == CLEANUP_STMT) |
af76441f AP |
813 | *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR |
814 | : TRY_FINALLY_EXPR, | |
815 | void_type_node, | |
816 | CLEANUP_BODY (stmt), | |
817 | CLEANUP_EXPR (stmt)); | |
818 | ||
f74d9c8f JJ |
819 | else if (TREE_CODE (stmt) == IF_STMT) |
820 | { | |
821 | genericize_if_stmt (stmt_p); | |
822 | /* *stmt_p has changed, tail recurse to handle it again. */ | |
823 | return cp_genericize_r (stmt_p, walk_subtrees, data); | |
824 | } | |
825 | ||
bbdf5682 JJ |
826 | /* COND_EXPR might have incompatible types in branches if one or both |
827 | arms are bitfields. Fix it up now. */ | |
828 | else if (TREE_CODE (stmt) == COND_EXPR) | |
829 | { | |
830 | tree type_left | |
831 | = (TREE_OPERAND (stmt, 1) | |
832 | ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1)) | |
833 | : NULL_TREE); | |
834 | tree type_right | |
835 | = (TREE_OPERAND (stmt, 2) | |
836 | ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2)) | |
837 | : NULL_TREE); | |
d767aebf JJ |
838 | if (type_left |
839 | && !useless_type_conversion_p (TREE_TYPE (stmt), | |
840 | TREE_TYPE (TREE_OPERAND (stmt, 1)))) | |
bbdf5682 JJ |
841 | { |
842 | TREE_OPERAND (stmt, 1) | |
843 | = fold_convert (type_left, TREE_OPERAND (stmt, 1)); | |
844 | gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt), | |
845 | type_left)); | |
846 | } | |
d767aebf JJ |
847 | if (type_right |
848 | && !useless_type_conversion_p (TREE_TYPE (stmt), | |
849 | TREE_TYPE (TREE_OPERAND (stmt, 2)))) | |
bbdf5682 JJ |
850 | { |
851 | TREE_OPERAND (stmt, 2) | |
852 | = fold_convert (type_right, TREE_OPERAND (stmt, 2)); | |
853 | gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt), | |
854 | type_right)); | |
855 | } | |
856 | } | |
857 | ||
ac3cbee5 RG |
858 | else if (TREE_CODE (stmt) == BIND_EXPR) |
859 | { | |
860 | VEC_safe_push (tree, heap, wtd->bind_expr_stack, stmt); | |
861 | cp_walk_tree (&BIND_EXPR_BODY (stmt), | |
862 | cp_genericize_r, data, NULL); | |
863 | VEC_pop (tree, wtd->bind_expr_stack); | |
ac3cbee5 RG |
864 | } |
865 | ||
866 | else if (TREE_CODE (stmt) == USING_STMT) | |
867 | { | |
868 | tree block = NULL_TREE; | |
869 | ||
870 | /* Get the innermost inclosing GIMPLE_BIND that has a non NULL | |
871 | BLOCK, and append an IMPORTED_DECL to its | |
872 | BLOCK_VARS chained list. */ | |
873 | if (wtd->bind_expr_stack) | |
874 | { | |
875 | int i; | |
876 | for (i = VEC_length (tree, wtd->bind_expr_stack) - 1; i >= 0; i--) | |
877 | if ((block = BIND_EXPR_BLOCK (VEC_index (tree, | |
878 | wtd->bind_expr_stack, i)))) | |
879 | break; | |
880 | } | |
881 | if (block) | |
882 | { | |
883 | tree using_directive; | |
884 | gcc_assert (TREE_OPERAND (stmt, 0)); | |
885 | ||
886 | using_directive = make_node (IMPORTED_DECL); | |
887 | TREE_TYPE (using_directive) = void_type_node; | |
888 | ||
889 | IMPORTED_DECL_ASSOCIATED_DECL (using_directive) | |
890 | = TREE_OPERAND (stmt, 0); | |
891 | TREE_CHAIN (using_directive) = BLOCK_VARS (block); | |
892 | BLOCK_VARS (block) = using_directive; | |
893 | } | |
894 | /* The USING_STMT won't appear in GENERIC. */ | |
895 | *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node); | |
896 | *walk_subtrees = 0; | |
897 | } | |
898 | ||
899 | else if (TREE_CODE (stmt) == DECL_EXPR | |
900 | && TREE_CODE (DECL_EXPR_DECL (stmt)) == USING_DECL) | |
901 | { | |
902 | /* Using decls inside DECL_EXPRs are just dropped on the floor. */ | |
903 | *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node); | |
904 | *walk_subtrees = 0; | |
905 | } | |
906 | ||
af76441f | 907 | pointer_set_insert (p_set, *stmt_p); |
c8094d83 | 908 | |
5a508662 RH |
909 | return NULL; |
910 | } | |
911 | ||
912 | void | |
913 | cp_genericize (tree fndecl) | |
914 | { | |
d8472c75 | 915 | tree t; |
ac3cbee5 | 916 | struct cp_genericize_data wtd; |
d8472c75 JM |
917 | |
918 | /* Fix up the types of parms passed by invisible reference. */ | |
919 | for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t)) | |
dfb5c523 MM |
920 | if (TREE_ADDRESSABLE (TREE_TYPE (t))) |
921 | { | |
922 | /* If a function's arguments are copied to create a thunk, | |
923 | then DECL_BY_REFERENCE will be set -- but the type of the | |
924 | argument will be a pointer type, so we will never get | |
925 | here. */ | |
926 | gcc_assert (!DECL_BY_REFERENCE (t)); | |
927 | gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); | |
928 | TREE_TYPE (t) = DECL_ARG_TYPE (t); | |
929 | DECL_BY_REFERENCE (t) = 1; | |
930 | TREE_ADDRESSABLE (t) = 0; | |
931 | relayout_decl (t); | |
932 | } | |
d8472c75 | 933 | |
cc77ae10 JM |
934 | /* Do the same for the return value. */ |
935 | if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) | |
936 | { | |
937 | t = DECL_RESULT (fndecl); | |
938 | TREE_TYPE (t) = build_reference_type (TREE_TYPE (t)); | |
939 | DECL_BY_REFERENCE (t) = 1; | |
940 | TREE_ADDRESSABLE (t) = 0; | |
941 | relayout_decl (t); | |
942 | } | |
943 | ||
d8472c75 JM |
944 | /* If we're a clone, the body is already GIMPLE. */ |
945 | if (DECL_CLONED_FUNCTION_P (fndecl)) | |
946 | return; | |
947 | ||
948 | /* We do want to see every occurrence of the parms, so we can't just use | |
949 | walk_tree's hash functionality. */ | |
ac3cbee5 RG |
950 | wtd.p_set = pointer_set_create (); |
951 | wtd.bind_expr_stack = NULL; | |
952 | cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, &wtd, NULL); | |
953 | pointer_set_destroy (wtd.p_set); | |
954 | VEC_free (tree, heap, wtd.bind_expr_stack); | |
5a508662 RH |
955 | |
956 | /* Do everything else. */ | |
957 | c_genericize (fndecl); | |
1799e5d5 RH |
958 | |
959 | gcc_assert (bc_label[bc_break] == NULL); | |
960 | gcc_assert (bc_label[bc_continue] == NULL); | |
961 | } | |
962 | \f | |
963 | /* Build code to apply FN to each member of ARG1 and ARG2. FN may be | |
964 | NULL if there is in fact nothing to do. ARG2 may be null if FN | |
965 | actually only takes one argument. */ | |
966 | ||
967 | static tree | |
968 | cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2) | |
969 | { | |
c2898ec9 | 970 | tree defparm, parm, t; |
94a0dd7b SL |
971 | int i = 0; |
972 | int nargs; | |
973 | tree *argarray; | |
fae2b46b | 974 | |
1799e5d5 RH |
975 | if (fn == NULL) |
976 | return NULL; | |
977 | ||
94a0dd7b SL |
978 | nargs = list_length (DECL_ARGUMENTS (fn)); |
979 | argarray = (tree *) alloca (nargs * sizeof (tree)); | |
980 | ||
fae2b46b JJ |
981 | defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn))); |
982 | if (arg2) | |
983 | defparm = TREE_CHAIN (defparm); | |
984 | ||
1799e5d5 RH |
985 | if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE) |
986 | { | |
987 | tree inner_type = TREE_TYPE (arg1); | |
988 | tree start1, end1, p1; | |
989 | tree start2 = NULL, p2 = NULL; | |
c2898ec9 | 990 | tree ret = NULL, lab; |
1799e5d5 RH |
991 | |
992 | start1 = arg1; | |
993 | start2 = arg2; | |
994 | do | |
995 | { | |
996 | inner_type = TREE_TYPE (inner_type); | |
997 | start1 = build4 (ARRAY_REF, inner_type, start1, | |
998 | size_zero_node, NULL, NULL); | |
999 | if (arg2) | |
1000 | start2 = build4 (ARRAY_REF, inner_type, start2, | |
1001 | size_zero_node, NULL, NULL); | |
1002 | } | |
1003 | while (TREE_CODE (inner_type) == ARRAY_TYPE); | |
db3927fb | 1004 | start1 = build_fold_addr_expr_loc (input_location, start1); |
1799e5d5 | 1005 | if (arg2) |
db3927fb | 1006 | start2 = build_fold_addr_expr_loc (input_location, start2); |
1799e5d5 RH |
1007 | |
1008 | end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1)); | |
5be014d5 | 1009 | end1 = build2 (POINTER_PLUS_EXPR, TREE_TYPE (start1), start1, end1); |
1799e5d5 RH |
1010 | |
1011 | p1 = create_tmp_var (TREE_TYPE (start1), NULL); | |
726a989a | 1012 | t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, start1); |
1799e5d5 RH |
1013 | append_to_statement_list (t, &ret); |
1014 | ||
1015 | if (arg2) | |
1016 | { | |
1017 | p2 = create_tmp_var (TREE_TYPE (start2), NULL); | |
726a989a | 1018 | t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, start2); |
1799e5d5 RH |
1019 | append_to_statement_list (t, &ret); |
1020 | } | |
1021 | ||
c2255bc4 | 1022 | lab = create_artificial_label (input_location); |
1799e5d5 RH |
1023 | t = build1 (LABEL_EXPR, void_type_node, lab); |
1024 | append_to_statement_list (t, &ret); | |
1025 | ||
94a0dd7b | 1026 | argarray[i++] = p1; |
1799e5d5 | 1027 | if (arg2) |
94a0dd7b | 1028 | argarray[i++] = p2; |
fae2b46b | 1029 | /* Handle default arguments. */ |
d2ee546f JJ |
1030 | for (parm = defparm; parm && parm != void_list_node; |
1031 | parm = TREE_CHAIN (parm), i++) | |
94a0dd7b SL |
1032 | argarray[i] = convert_default_arg (TREE_VALUE (parm), |
1033 | TREE_PURPOSE (parm), fn, i); | |
1034 | t = build_call_a (fn, i, argarray); | |
c2898ec9 JJ |
1035 | t = fold_convert (void_type_node, t); |
1036 | t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); | |
1799e5d5 RH |
1037 | append_to_statement_list (t, &ret); |
1038 | ||
5be014d5 AP |
1039 | t = TYPE_SIZE_UNIT (inner_type); |
1040 | t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p1), p1, t); | |
726a989a | 1041 | t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, t); |
1799e5d5 RH |
1042 | append_to_statement_list (t, &ret); |
1043 | ||
1044 | if (arg2) | |
1045 | { | |
5be014d5 AP |
1046 | t = TYPE_SIZE_UNIT (inner_type); |
1047 | t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p2), p2, t); | |
726a989a | 1048 | t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, t); |
1799e5d5 RH |
1049 | append_to_statement_list (t, &ret); |
1050 | } | |
1051 | ||
1052 | t = build2 (NE_EXPR, boolean_type_node, p1, end1); | |
1053 | t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL); | |
1054 | append_to_statement_list (t, &ret); | |
1055 | ||
1056 | return ret; | |
1057 | } | |
1058 | else | |
1059 | { | |
db3927fb | 1060 | argarray[i++] = build_fold_addr_expr_loc (input_location, arg1); |
1799e5d5 | 1061 | if (arg2) |
db3927fb | 1062 | argarray[i++] = build_fold_addr_expr_loc (input_location, arg2); |
fae2b46b | 1063 | /* Handle default arguments. */ |
d2ee546f | 1064 | for (parm = defparm; parm && parm != void_list_node; |
94a0dd7b SL |
1065 | parm = TREE_CHAIN (parm), i++) |
1066 | argarray[i] = convert_default_arg (TREE_VALUE (parm), | |
1067 | TREE_PURPOSE (parm), | |
1068 | fn, i); | |
c2898ec9 JJ |
1069 | t = build_call_a (fn, i, argarray); |
1070 | t = fold_convert (void_type_node, t); | |
1071 | return fold_build_cleanup_point_expr (TREE_TYPE (t), t); | |
1799e5d5 RH |
1072 | } |
1073 | } | |
1074 | ||
1075 | /* Return code to initialize DECL with its default constructor, or | |
1076 | NULL if there's nothing to do. */ | |
1077 | ||
1078 | tree | |
a68ab351 JJ |
1079 | cxx_omp_clause_default_ctor (tree clause, tree decl, |
1080 | tree outer ATTRIBUTE_UNUSED) | |
1799e5d5 RH |
1081 | { |
1082 | tree info = CP_OMP_CLAUSE_INFO (clause); | |
1083 | tree ret = NULL; | |
1084 | ||
1085 | if (info) | |
1086 | ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL); | |
1087 | ||
1088 | return ret; | |
1089 | } | |
1090 | ||
1091 | /* Return code to initialize DST with a copy constructor from SRC. */ | |
1092 | ||
1093 | tree | |
1094 | cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src) | |
1095 | { | |
1096 | tree info = CP_OMP_CLAUSE_INFO (clause); | |
1097 | tree ret = NULL; | |
1098 | ||
1099 | if (info) | |
1100 | ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src); | |
1101 | if (ret == NULL) | |
726a989a | 1102 | ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src); |
1799e5d5 RH |
1103 | |
1104 | return ret; | |
1105 | } | |
1106 | ||
1107 | /* Similarly, except use an assignment operator instead. */ | |
1108 | ||
1109 | tree | |
1110 | cxx_omp_clause_assign_op (tree clause, tree dst, tree src) | |
1111 | { | |
1112 | tree info = CP_OMP_CLAUSE_INFO (clause); | |
1113 | tree ret = NULL; | |
1114 | ||
1115 | if (info) | |
1116 | ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src); | |
1117 | if (ret == NULL) | |
726a989a | 1118 | ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src); |
1799e5d5 RH |
1119 | |
1120 | return ret; | |
1121 | } | |
1122 | ||
1123 | /* Return code to destroy DECL. */ | |
1124 | ||
1125 | tree | |
1126 | cxx_omp_clause_dtor (tree clause, tree decl) | |
1127 | { | |
1128 | tree info = CP_OMP_CLAUSE_INFO (clause); | |
1129 | tree ret = NULL; | |
1130 | ||
1131 | if (info) | |
1132 | ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL); | |
1133 | ||
1134 | return ret; | |
5a508662 | 1135 | } |
077b0dfb JJ |
1136 | |
1137 | /* True if OpenMP should privatize what this DECL points to rather | |
1138 | than the DECL itself. */ | |
1139 | ||
1140 | bool | |
58f9752a | 1141 | cxx_omp_privatize_by_reference (const_tree decl) |
077b0dfb | 1142 | { |
e02a048f | 1143 | return is_invisiref_parm (decl); |
077b0dfb | 1144 | } |
a68ab351 JJ |
1145 | |
1146 | /* True if OpenMP sharing attribute of DECL is predetermined. */ | |
1147 | ||
1148 | enum omp_clause_default_kind | |
1149 | cxx_omp_predetermined_sharing (tree decl) | |
1150 | { | |
1151 | tree type; | |
1152 | ||
1153 | /* Static data members are predetermined as shared. */ | |
1154 | if (TREE_STATIC (decl)) | |
1155 | { | |
1156 | tree ctx = CP_DECL_CONTEXT (decl); | |
1157 | if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx)) | |
1158 | return OMP_CLAUSE_DEFAULT_SHARED; | |
1159 | } | |
1160 | ||
1161 | type = TREE_TYPE (decl); | |
1162 | if (TREE_CODE (type) == REFERENCE_TYPE) | |
1163 | { | |
1164 | if (!is_invisiref_parm (decl)) | |
1165 | return OMP_CLAUSE_DEFAULT_UNSPECIFIED; | |
1166 | type = TREE_TYPE (type); | |
1167 | ||
1168 | if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl)) | |
1169 | { | |
1170 | /* NVR doesn't preserve const qualification of the | |
1171 | variable's type. */ | |
1172 | tree outer = outer_curly_brace_block (current_function_decl); | |
1173 | tree var; | |
1174 | ||
1175 | if (outer) | |
1176 | for (var = BLOCK_VARS (outer); var; var = TREE_CHAIN (var)) | |
1177 | if (DECL_NAME (decl) == DECL_NAME (var) | |
1178 | && (TYPE_MAIN_VARIANT (type) | |
1179 | == TYPE_MAIN_VARIANT (TREE_TYPE (var)))) | |
1180 | { | |
1181 | if (TYPE_READONLY (TREE_TYPE (var))) | |
1182 | type = TREE_TYPE (var); | |
1183 | break; | |
1184 | } | |
1185 | } | |
1186 | } | |
1187 | ||
1188 | if (type == error_mark_node) | |
1189 | return OMP_CLAUSE_DEFAULT_UNSPECIFIED; | |
1190 | ||
1191 | /* Variables with const-qualified type having no mutable member | |
1192 | are predetermined shared. */ | |
1193 | if (TYPE_READONLY (type) && !cp_has_mutable_p (type)) | |
1194 | return OMP_CLAUSE_DEFAULT_SHARED; | |
1195 | ||
1196 | return OMP_CLAUSE_DEFAULT_UNSPECIFIED; | |
1197 | } | |
1198 | ||
1199 | /* Finalize an implicitly determined clause. */ | |
1200 | ||
1201 | void | |
1202 | cxx_omp_finish_clause (tree c) | |
1203 | { | |
1204 | tree decl, inner_type; | |
1205 | bool make_shared = false; | |
1206 | ||
1207 | if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE) | |
1208 | return; | |
1209 | ||
1210 | decl = OMP_CLAUSE_DECL (c); | |
1211 | decl = require_complete_type (decl); | |
1212 | inner_type = TREE_TYPE (decl); | |
1213 | if (decl == error_mark_node) | |
1214 | make_shared = true; | |
1215 | else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE) | |
1216 | { | |
1217 | if (is_invisiref_parm (decl)) | |
1218 | inner_type = TREE_TYPE (inner_type); | |
1219 | else | |
1220 | { | |
1221 | error ("%qE implicitly determined as %<firstprivate%> has reference type", | |
1222 | decl); | |
1223 | make_shared = true; | |
1224 | } | |
1225 | } | |
1226 | ||
1227 | /* We're interested in the base element, not arrays. */ | |
1228 | while (TREE_CODE (inner_type) == ARRAY_TYPE) | |
1229 | inner_type = TREE_TYPE (inner_type); | |
1230 | ||
1231 | /* Check for special function availability by building a call to one. | |
1232 | Save the results, because later we won't be in the right context | |
1233 | for making these queries. */ | |
1234 | if (!make_shared | |
1235 | && CLASS_TYPE_P (inner_type) | |
1236 | && cxx_omp_create_clause_info (c, inner_type, false, true, false)) | |
1237 | make_shared = true; | |
1238 | ||
1239 | if (make_shared) | |
1240 | OMP_CLAUSE_CODE (c) = OMP_CLAUSE_SHARED; | |
1241 | } |