]>
Commit | Line | Data |
---|---|---|
88bce636 | 1 | /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c. |
4ee9c684 | 2 | |
97767aad | 3 | Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 |
aa139c3f | 4 | Free Software Foundation, Inc. |
4ee9c684 | 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 | |
aa139c3f | 11 | Software Foundation; either version 3, or (at your option) any later |
4ee9c684 | 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 | |
aa139c3f | 20 | along with GCC; see the file COPYING3. If not see |
21 | <http://www.gnu.org/licenses/>. */ | |
4ee9c684 | 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" | |
75a70cf9 | 31 | #include "tree-iterator.h" |
32 | #include "gimple.h" | |
dddcebdc | 33 | #include "hashtab.h" |
cee17238 | 34 | #include "pointer-set.h" |
7219fab5 | 35 | #include "flags.h" |
4ee9c684 | 36 | |
e7911019 | 37 | /* Local declarations. */ |
38 | ||
39 | enum bc_t { bc_break = 0, bc_continue = 1 }; | |
40 | ||
8487df40 | 41 | /* Stack of labels which are targets for "break" or "continue", |
42 | linked through TREE_CHAIN. */ | |
43 | static tree bc_label[2]; | |
e7911019 | 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 | { | |
e60a6f7b | 53 | tree label = create_artificial_label (input_location); |
8487df40 | 54 | TREE_CHAIN (label) = bc_label[bc]; |
55 | bc_label[bc] = label; | |
e7911019 | 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 | ||
75a70cf9 | 66 | static gimple_seq |
67 | finish_bc_block (enum bc_t bc, tree label, gimple_seq body) | |
e7911019 | 68 | { |
8487df40 | 69 | gcc_assert (label == bc_label[bc]); |
e7911019 | 70 | |
71 | if (TREE_USED (label)) | |
72 | { | |
75a70cf9 | 73 | gimple_seq_add_stmt (&body, gimple_build_label (label)); |
e7911019 | 74 | } |
75 | ||
8487df40 | 76 | bc_label[bc] = TREE_CHAIN (label); |
e7911019 | 77 | TREE_CHAIN (label) = NULL_TREE; |
78 | return body; | |
79 | } | |
80 | ||
75a70cf9 | 81 | /* Get the LABEL_EXPR to represent a break or continue statement |
82 | in the current block scope. BC indicates which. */ | |
e7911019 | 83 | |
84 | static tree | |
75a70cf9 | 85 | get_bc_label (enum bc_t bc) |
e7911019 | 86 | { |
8487df40 | 87 | tree label = bc_label[bc]; |
e7911019 | 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; | |
75a70cf9 | 101 | return label; |
e7911019 | 102 | } |
103 | ||
4ee9c684 | 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 | ||
831d52a2 | 112 | *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup); |
4ee9c684 | 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 | ||
4ee9c684 | 123 | /* FIXME should the caught type go in TREE_TYPE? */ |
831d52a2 | 124 | *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body); |
4ee9c684 | 125 | } |
126 | ||
75a70cf9 | 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 | ||
4ee9c684 | 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); | |
d01f58f9 | 153 | tree failure = build_call_n (call_unexpected_node, 1, build_exc_ptr ()); |
4ee9c684 | 154 | |
75a70cf9 | 155 | *stmt_p = build_gimple_eh_filter_tree (body, allowed, failure); |
4ee9c684 | 156 | } |
157 | ||
dddab69e | 158 | /* Genericize an IF_STMT by turning it into a COND_EXPR. */ |
159 | ||
160 | static void | |
97767aad | 161 | genericize_if_stmt (tree *stmt_p) |
dddab69e | 162 | { |
551fa2c7 | 163 | tree stmt, cond, then_, else_; |
75a70cf9 | 164 | location_t locus = EXPR_LOCATION (*stmt_p); |
dddab69e | 165 | |
166 | stmt = *stmt_p; | |
551fa2c7 | 167 | cond = IF_COND (stmt); |
dddab69e | 168 | then_ = THEN_CLAUSE (stmt); |
169 | else_ = ELSE_CLAUSE (stmt); | |
170 | ||
171 | if (!then_) | |
e60a6f7b | 172 | then_ = build_empty_stmt (locus); |
dddab69e | 173 | if (!else_) |
e60a6f7b | 174 | else_ = build_empty_stmt (locus); |
dddab69e | 175 | |
551fa2c7 | 176 | if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_)) |
177 | stmt = then_; | |
178 | else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_)) | |
179 | stmt = else_; | |
180 | else | |
181 | stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_); | |
75a70cf9 | 182 | if (CAN_HAVE_LOCATION_P (stmt) && !EXPR_HAS_LOCATION (stmt)) |
183 | SET_EXPR_LOCATION (stmt, locus); | |
dddab69e | 184 | *stmt_p = stmt; |
185 | } | |
186 | ||
e7911019 | 187 | /* Build a generic representation of one of the C loop forms. COND is the |
188 | loop condition or NULL_TREE. BODY is the (possibly compound) statement | |
189 | controlled by the loop. INCR is the increment expression of a for-loop, | |
190 | or NULL_TREE. COND_IS_FIRST indicates whether the condition is | |
191 | evaluated before the loop body as in while and for loops, or after the | |
192 | loop body as in do-while loops. */ | |
193 | ||
75a70cf9 | 194 | static gimple_seq |
e7911019 | 195 | gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first) |
196 | { | |
75a70cf9 | 197 | gimple top, entry, stmt; |
198 | gimple_seq stmt_list, body_seq, incr_seq, exit_seq; | |
199 | tree cont_block, break_block; | |
e7911019 | 200 | location_t stmt_locus; |
201 | ||
202 | stmt_locus = input_location; | |
75a70cf9 | 203 | stmt_list = NULL; |
204 | body_seq = NULL; | |
205 | incr_seq = NULL; | |
206 | exit_seq = NULL; | |
207 | entry = NULL; | |
e7911019 | 208 | |
209 | break_block = begin_bc_block (bc_break); | |
210 | cont_block = begin_bc_block (bc_continue); | |
211 | ||
212 | /* If condition is zero don't generate a loop construct. */ | |
213 | if (cond && integer_zerop (cond)) | |
214 | { | |
75a70cf9 | 215 | top = NULL; |
e7911019 | 216 | if (cond_is_first) |
217 | { | |
75a70cf9 | 218 | stmt = gimple_build_goto (get_bc_label (bc_break)); |
219 | gimple_set_location (stmt, stmt_locus); | |
220 | gimple_seq_add_stmt (&stmt_list, stmt); | |
e7911019 | 221 | } |
222 | } | |
223 | else | |
224 | { | |
225 | /* If we use a LOOP_EXPR here, we have to feed the whole thing | |
226 | back through the main gimplifier to lower it. Given that we | |
227 | have to gimplify the loop body NOW so that we can resolve | |
228 | break/continue stmts, seems easier to just expand to gotos. */ | |
e60a6f7b | 229 | top = gimple_build_label (create_artificial_label (stmt_locus)); |
e7911019 | 230 | |
231 | /* If we have an exit condition, then we build an IF with gotos either | |
232 | out of the loop, or to the top of it. If there's no exit condition, | |
233 | then we just build a jump back to the top. */ | |
e7911019 | 234 | if (cond && !integer_nonzerop (cond)) |
235 | { | |
75a70cf9 | 236 | if (cond != error_mark_node) |
237 | { | |
238 | gimplify_expr (&cond, &exit_seq, NULL, is_gimple_val, fb_rvalue); | |
239 | stmt = gimple_build_cond (NE_EXPR, cond, | |
240 | build_int_cst (TREE_TYPE (cond), 0), | |
241 | gimple_label_label (top), | |
242 | get_bc_label (bc_break)); | |
243 | gimple_seq_add_stmt (&exit_seq, stmt); | |
244 | } | |
e7911019 | 245 | |
246 | if (cond_is_first) | |
247 | { | |
248 | if (incr) | |
249 | { | |
e60a6f7b | 250 | entry = gimple_build_label |
251 | (create_artificial_label (stmt_locus)); | |
75a70cf9 | 252 | stmt = gimple_build_goto (gimple_label_label (entry)); |
e7911019 | 253 | } |
254 | else | |
75a70cf9 | 255 | stmt = gimple_build_goto (get_bc_label (bc_continue)); |
256 | gimple_set_location (stmt, stmt_locus); | |
257 | gimple_seq_add_stmt (&stmt_list, stmt); | |
e7911019 | 258 | } |
259 | } | |
75a70cf9 | 260 | else |
261 | { | |
262 | stmt = gimple_build_goto (gimple_label_label (top)); | |
263 | gimple_seq_add_stmt (&exit_seq, stmt); | |
264 | } | |
e7911019 | 265 | } |
266 | ||
75a70cf9 | 267 | gimplify_stmt (&body, &body_seq); |
268 | gimplify_stmt (&incr, &incr_seq); | |
e7911019 | 269 | |
75a70cf9 | 270 | body_seq = finish_bc_block (bc_continue, cont_block, body_seq); |
e7911019 | 271 | |
75a70cf9 | 272 | gimple_seq_add_stmt (&stmt_list, top); |
273 | gimple_seq_add_seq (&stmt_list, body_seq); | |
274 | gimple_seq_add_seq (&stmt_list, incr_seq); | |
275 | gimple_seq_add_stmt (&stmt_list, entry); | |
276 | gimple_seq_add_seq (&stmt_list, exit_seq); | |
e7911019 | 277 | |
75a70cf9 | 278 | annotate_all_with_location (stmt_list, stmt_locus); |
e7911019 | 279 | |
280 | return finish_bc_block (bc_break, break_block, stmt_list); | |
281 | } | |
282 | ||
283 | /* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the | |
284 | prequeue and hand off to gimplify_cp_loop. */ | |
285 | ||
286 | static void | |
75a70cf9 | 287 | gimplify_for_stmt (tree *stmt_p, gimple_seq *pre_p) |
e7911019 | 288 | { |
289 | tree stmt = *stmt_p; | |
290 | ||
291 | if (FOR_INIT_STMT (stmt)) | |
292 | gimplify_and_add (FOR_INIT_STMT (stmt), pre_p); | |
293 | ||
75a70cf9 | 294 | gimple_seq_add_seq (pre_p, |
295 | gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt), | |
296 | FOR_EXPR (stmt), 1)); | |
297 | *stmt_p = NULL_TREE; | |
e7911019 | 298 | } |
299 | ||
300 | /* Gimplify a WHILE_STMT node. */ | |
301 | ||
302 | static void | |
75a70cf9 | 303 | gimplify_while_stmt (tree *stmt_p, gimple_seq *pre_p) |
e7911019 | 304 | { |
305 | tree stmt = *stmt_p; | |
75a70cf9 | 306 | gimple_seq_add_seq (pre_p, |
307 | gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt), | |
308 | NULL_TREE, 1)); | |
309 | *stmt_p = NULL_TREE; | |
e7911019 | 310 | } |
311 | ||
312 | /* Gimplify a DO_STMT node. */ | |
313 | ||
314 | static void | |
75a70cf9 | 315 | gimplify_do_stmt (tree *stmt_p, gimple_seq *pre_p) |
e7911019 | 316 | { |
317 | tree stmt = *stmt_p; | |
75a70cf9 | 318 | gimple_seq_add_seq (pre_p, |
319 | gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt), | |
320 | NULL_TREE, 0)); | |
321 | *stmt_p = NULL_TREE; | |
e7911019 | 322 | } |
323 | ||
324 | /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */ | |
325 | ||
326 | static void | |
75a70cf9 | 327 | gimplify_switch_stmt (tree *stmt_p, gimple_seq *pre_p) |
e7911019 | 328 | { |
329 | tree stmt = *stmt_p; | |
75a70cf9 | 330 | tree break_block, body, t; |
e7911019 | 331 | location_t stmt_locus = input_location; |
75a70cf9 | 332 | gimple_seq seq = NULL; |
e7911019 | 333 | |
334 | break_block = begin_bc_block (bc_break); | |
335 | ||
336 | body = SWITCH_STMT_BODY (stmt); | |
337 | if (!body) | |
e60a6f7b | 338 | body = build_empty_stmt (stmt_locus); |
e7911019 | 339 | |
75a70cf9 | 340 | t = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt), |
341 | SWITCH_STMT_COND (stmt), body, NULL_TREE); | |
342 | SET_EXPR_LOCATION (t, stmt_locus); | |
343 | gimplify_and_add (t, &seq); | |
e7911019 | 344 | |
75a70cf9 | 345 | seq = finish_bc_block (bc_break, break_block, seq); |
346 | gimple_seq_add_seq (pre_p, seq); | |
347 | *stmt_p = NULL_TREE; | |
e7911019 | 348 | } |
349 | ||
8487df40 | 350 | /* Hook into the middle of gimplifying an OMP_FOR node. This is required |
351 | in order to properly gimplify CONTINUE statements. Here we merely | |
352 | manage the continue stack; the rest of the job is performed by the | |
074ab442 | 353 | regular gimplifier. */ |
8487df40 | 354 | |
355 | static enum gimplify_status | |
75a70cf9 | 356 | cp_gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) |
8487df40 | 357 | { |
358 | tree for_stmt = *expr_p; | |
359 | tree cont_block; | |
75a70cf9 | 360 | gimple stmt; |
361 | gimple_seq seq = NULL; | |
8487df40 | 362 | |
363 | /* Protect ourselves from recursion. */ | |
364 | if (OMP_FOR_GIMPLIFYING_P (for_stmt)) | |
365 | return GS_UNHANDLED; | |
366 | OMP_FOR_GIMPLIFYING_P (for_stmt) = 1; | |
367 | ||
368 | /* Note that while technically the continue label is enabled too soon | |
369 | here, we should have already diagnosed invalid continues nested within | |
370 | statement expressions within the INIT, COND, or INCR expressions. */ | |
371 | cont_block = begin_bc_block (bc_continue); | |
372 | ||
75a70cf9 | 373 | gimplify_and_add (for_stmt, &seq); |
374 | stmt = gimple_seq_last_stmt (seq); | |
375 | if (gimple_code (stmt) == GIMPLE_OMP_FOR) | |
376 | gimple_omp_set_body (stmt, finish_bc_block (bc_continue, cont_block, | |
377 | gimple_omp_body (stmt))); | |
378 | else | |
379 | seq = finish_bc_block (bc_continue, cont_block, seq); | |
380 | gimple_seq_add_seq (pre_p, seq); | |
8487df40 | 381 | |
8487df40 | 382 | OMP_FOR_GIMPLIFYING_P (for_stmt) = 0; |
383 | ||
384 | return GS_ALL_DONE; | |
385 | } | |
386 | ||
7219fab5 | 387 | /* Gimplify an EXPR_STMT node. */ |
388 | ||
389 | static void | |
390 | gimplify_expr_stmt (tree *stmt_p) | |
391 | { | |
392 | tree stmt = EXPR_STMT_EXPR (*stmt_p); | |
393 | ||
394 | if (stmt == error_mark_node) | |
395 | stmt = NULL; | |
396 | ||
397 | /* Gimplification of a statement expression will nullify the | |
398 | statement if all its side effects are moved to *PRE_P and *POST_P. | |
399 | ||
400 | In this case we will not want to emit the gimplified statement. | |
401 | However, we may still want to emit a warning, so we do that before | |
402 | gimplification. */ | |
43667bd3 | 403 | if (stmt && warn_unused_value) |
7219fab5 | 404 | { |
405 | if (!TREE_SIDE_EFFECTS (stmt)) | |
406 | { | |
407 | if (!IS_EMPTY_STMT (stmt) | |
408 | && !VOID_TYPE_P (TREE_TYPE (stmt)) | |
409 | && !TREE_NO_WARNING (stmt)) | |
43667bd3 | 410 | warning (OPT_Wunused_value, "statement with no effect"); |
7219fab5 | 411 | } |
43667bd3 | 412 | else |
7219fab5 | 413 | warn_if_unused_value (stmt, input_location); |
414 | } | |
415 | ||
416 | if (stmt == NULL_TREE) | |
417 | stmt = alloc_stmt_list (); | |
418 | ||
419 | *stmt_p = stmt; | |
420 | } | |
421 | ||
4ee9c684 | 422 | /* Gimplify initialization from an AGGR_INIT_EXPR. */ |
423 | ||
424 | static void | |
75a70cf9 | 425 | cp_gimplify_init_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) |
4ee9c684 | 426 | { |
427 | tree from = TREE_OPERAND (*expr_p, 1); | |
428 | tree to = TREE_OPERAND (*expr_p, 0); | |
930e8175 | 429 | tree t; |
430 | tree slot = NULL_TREE; | |
4ee9c684 | 431 | |
4ee9c684 | 432 | /* What about code that pulls out the temp and uses it elsewhere? I |
433 | think that such code never uses the TARGET_EXPR as an initializer. If | |
434 | I'm wrong, we'll abort because the temp won't have any RTL. In that | |
435 | case, I guess we'll need to replace references somehow. */ | |
436 | if (TREE_CODE (from) == TARGET_EXPR) | |
930e8175 | 437 | { |
438 | slot = TARGET_EXPR_SLOT (from); | |
439 | from = TARGET_EXPR_INITIAL (from); | |
440 | } | |
4ee9c684 | 441 | |
c3d09d4d | 442 | /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them |
443 | inside the TARGET_EXPR. */ | |
930e8175 | 444 | for (t = from; t; ) |
445 | { | |
446 | tree sub = TREE_CODE (t) == COMPOUND_EXPR ? TREE_OPERAND (t, 0) : t; | |
4ee9c684 | 447 | |
930e8175 | 448 | /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and |
449 | replace the slot operand with our target. | |
4ee9c684 | 450 | |
930e8175 | 451 | Should we add a target parm to gimplify_expr instead? No, as in this |
452 | case we want to replace the INIT_EXPR. */ | |
453 | if (TREE_CODE (sub) == AGGR_INIT_EXPR) | |
454 | { | |
455 | gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue); | |
456 | AGGR_INIT_EXPR_SLOT (sub) = to; | |
457 | *expr_p = from; | |
458 | ||
459 | /* The initialization is now a side-effect, so the container can | |
460 | become void. */ | |
461 | if (from != sub) | |
462 | TREE_TYPE (from) = void_type_node; | |
463 | } | |
930e8175 | 464 | |
465 | if (t == sub) | |
466 | break; | |
467 | else | |
468 | t = TREE_OPERAND (t, 1); | |
4ee9c684 | 469 | } |
930e8175 | 470 | |
4ee9c684 | 471 | } |
472 | ||
473 | /* Gimplify a MUST_NOT_THROW_EXPR. */ | |
474 | ||
75a70cf9 | 475 | static enum gimplify_status |
476 | gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p) | |
4ee9c684 | 477 | { |
478 | tree stmt = *expr_p; | |
2363ef00 | 479 | tree temp = voidify_wrapper_expr (stmt, NULL); |
4ee9c684 | 480 | tree body = TREE_OPERAND (stmt, 0); |
481 | ||
75a70cf9 | 482 | stmt = build_gimple_eh_filter_tree (body, NULL_TREE, |
483 | build_call_n (terminate_node, 0)); | |
4ee9c684 | 484 | |
75a70cf9 | 485 | gimplify_and_add (stmt, pre_p); |
4ee9c684 | 486 | if (temp) |
487 | { | |
4ee9c684 | 488 | *expr_p = temp; |
75a70cf9 | 489 | return GS_OK; |
4ee9c684 | 490 | } |
75a70cf9 | 491 | |
492 | *expr_p = NULL; | |
493 | return GS_ALL_DONE; | |
4ee9c684 | 494 | } |
8495c0ca | 495 | |
496 | /* Do C++-specific gimplification. Args are as for gimplify_expr. */ | |
497 | ||
498 | int | |
75a70cf9 | 499 | cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) |
8495c0ca | 500 | { |
501 | int saved_stmts_are_full_exprs_p = 0; | |
502 | enum tree_code code = TREE_CODE (*expr_p); | |
503 | enum gimplify_status ret; | |
5d8a39b7 | 504 | tree block = NULL; |
505 | VEC(gimple, heap) *bind_expr_stack = NULL; | |
8495c0ca | 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 | ||
526 | case THROW_EXPR: | |
a17c2a3a | 527 | /* FIXME communicate throw type to back end, probably by moving |
8495c0ca | 528 | THROW_EXPR into ../tree.def. */ |
529 | *expr_p = TREE_OPERAND (*expr_p, 0); | |
530 | ret = GS_OK; | |
531 | break; | |
532 | ||
533 | case MUST_NOT_THROW_EXPR: | |
75a70cf9 | 534 | ret = gimplify_must_not_throw_expr (expr_p, pre_p); |
8495c0ca | 535 | break; |
536 | ||
75a70cf9 | 537 | /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the |
cf6b103e | 538 | LHS of an assignment might also be involved in the RHS, as in bug |
539 | 25979. */ | |
8495c0ca | 540 | case INIT_EXPR: |
8495c0ca | 541 | cp_gimplify_init_expr (expr_p, pre_p, post_p); |
542 | ret = GS_OK; | |
543 | break; | |
544 | ||
545 | case EMPTY_CLASS_EXPR: | |
ff8c638e | 546 | /* We create an empty CONSTRUCTOR with RECORD_TYPE. */ |
547 | *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL); | |
8495c0ca | 548 | ret = GS_OK; |
549 | break; | |
550 | ||
551 | case BASELINK: | |
552 | *expr_p = BASELINK_FUNCTIONS (*expr_p); | |
553 | ret = GS_OK; | |
554 | break; | |
555 | ||
556 | case TRY_BLOCK: | |
557 | genericize_try_block (expr_p); | |
558 | ret = GS_OK; | |
559 | break; | |
560 | ||
561 | case HANDLER: | |
562 | genericize_catch_block (expr_p); | |
563 | ret = GS_OK; | |
564 | break; | |
565 | ||
566 | case EH_SPEC_BLOCK: | |
567 | genericize_eh_spec_block (expr_p); | |
568 | ret = GS_OK; | |
569 | break; | |
570 | ||
571 | case USING_STMT: | |
5d8a39b7 | 572 | /* Get the innermost inclosing GIMPLE_BIND that has a non NULL |
573 | BLOCK, and append an IMPORTED_DECL to its | |
574 | BLOCK_VARS chained list. */ | |
575 | ||
576 | bind_expr_stack = gimple_bind_expr_stack (); | |
577 | if (bind_expr_stack) | |
578 | { | |
579 | int i; | |
580 | for (i = VEC_length (gimple, bind_expr_stack) - 1; i >= 0; i--) | |
581 | if ((block = gimple_bind_block (VEC_index (gimple, | |
582 | bind_expr_stack, | |
583 | i)))) | |
584 | break; | |
585 | } | |
586 | if (block) | |
587 | { | |
588 | tree using_directive; | |
169f8686 | 589 | gcc_assert (TREE_OPERAND (*expr_p, 0)); |
5d8a39b7 | 590 | |
591 | using_directive = make_node (IMPORTED_DECL); | |
592 | TREE_TYPE (using_directive) = void_type_node; | |
593 | ||
594 | IMPORTED_DECL_ASSOCIATED_DECL (using_directive) | |
595 | = TREE_OPERAND (*expr_p, 0); | |
5d8a39b7 | 596 | TREE_CHAIN (using_directive) = BLOCK_VARS (block); |
597 | BLOCK_VARS (block) = using_directive; | |
598 | } | |
599 | /* The USING_STMT won't appear in GIMPLE. */ | |
75a70cf9 | 600 | *expr_p = NULL; |
8495c0ca | 601 | ret = GS_ALL_DONE; |
602 | break; | |
603 | ||
e7911019 | 604 | case FOR_STMT: |
605 | gimplify_for_stmt (expr_p, pre_p); | |
75a70cf9 | 606 | ret = GS_OK; |
e7911019 | 607 | break; |
608 | ||
609 | case WHILE_STMT: | |
75a70cf9 | 610 | gimplify_while_stmt (expr_p, pre_p); |
611 | ret = GS_OK; | |
e7911019 | 612 | break; |
613 | ||
614 | case DO_STMT: | |
75a70cf9 | 615 | gimplify_do_stmt (expr_p, pre_p); |
616 | ret = GS_OK; | |
e7911019 | 617 | break; |
618 | ||
619 | case SWITCH_STMT: | |
75a70cf9 | 620 | gimplify_switch_stmt (expr_p, pre_p); |
621 | ret = GS_OK; | |
e7911019 | 622 | break; |
623 | ||
8487df40 | 624 | case OMP_FOR: |
75a70cf9 | 625 | ret = cp_gimplify_omp_for (expr_p, pre_p); |
8487df40 | 626 | break; |
627 | ||
e7911019 | 628 | case CONTINUE_STMT: |
1add270f | 629 | gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_CONTINUE, NOT_TAKEN)); |
75a70cf9 | 630 | gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_continue))); |
631 | *expr_p = NULL_TREE; | |
e7911019 | 632 | ret = GS_ALL_DONE; |
633 | break; | |
634 | ||
635 | case BREAK_STMT: | |
75a70cf9 | 636 | gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_break))); |
637 | *expr_p = NULL_TREE; | |
e7911019 | 638 | ret = GS_ALL_DONE; |
639 | break; | |
640 | ||
7219fab5 | 641 | case EXPR_STMT: |
642 | gimplify_expr_stmt (expr_p); | |
643 | ret = GS_OK; | |
644 | break; | |
645 | ||
97d541d5 | 646 | case UNARY_PLUS_EXPR: |
647 | { | |
648 | tree arg = TREE_OPERAND (*expr_p, 0); | |
649 | tree type = TREE_TYPE (*expr_p); | |
650 | *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg) | |
651 | : arg; | |
652 | ret = GS_OK; | |
653 | } | |
654 | break; | |
655 | ||
8495c0ca | 656 | default: |
8458f4ca | 657 | ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p); |
8495c0ca | 658 | break; |
659 | } | |
660 | ||
661 | /* Restore saved state. */ | |
662 | if (STATEMENT_CODE_P (code)) | |
663 | current_stmt_tree ()->stmts_are_full_exprs_p | |
664 | = saved_stmts_are_full_exprs_p; | |
665 | ||
666 | return ret; | |
667 | } | |
dddab69e | 668 | |
dddcebdc | 669 | static inline bool |
9f627b1a | 670 | is_invisiref_parm (const_tree t) |
dddcebdc | 671 | { |
806e4c12 | 672 | return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL) |
dddcebdc | 673 | && DECL_BY_REFERENCE (t)); |
674 | } | |
675 | ||
7db5a284 | 676 | /* Return true if the uid in both int tree maps are equal. */ |
677 | ||
678 | int | |
679 | cxx_int_tree_map_eq (const void *va, const void *vb) | |
680 | { | |
681 | const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va; | |
682 | const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb; | |
683 | return (a->uid == b->uid); | |
684 | } | |
685 | ||
686 | /* Hash a UID in a cxx_int_tree_map. */ | |
687 | ||
688 | unsigned int | |
689 | cxx_int_tree_map_hash (const void *item) | |
690 | { | |
691 | return ((const struct cxx_int_tree_map *)item)->uid; | |
692 | } | |
693 | ||
dddcebdc | 694 | /* Perform any pre-gimplification lowering of C++ front end trees to |
695 | GENERIC. */ | |
dddab69e | 696 | |
697 | static tree | |
dddcebdc | 698 | cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) |
dddab69e | 699 | { |
700 | tree stmt = *stmt_p; | |
cee17238 | 701 | struct pointer_set_t *p_set = (struct pointer_set_t*) data; |
dddab69e | 702 | |
698b706e | 703 | if (is_invisiref_parm (stmt) |
704 | /* Don't dereference parms in a thunk, pass the references through. */ | |
705 | && !(DECL_THUNK_P (current_function_decl) | |
074ab442 | 706 | && TREE_CODE (stmt) == PARM_DECL)) |
dddcebdc | 707 | { |
806e4c12 | 708 | *stmt_p = convert_from_reference (stmt); |
dddcebdc | 709 | *walk_subtrees = 0; |
710 | return NULL; | |
711 | } | |
712 | ||
7db5a284 | 713 | /* Map block scope extern declarations to visible declarations with the |
714 | same name and type in outer scopes if any. */ | |
715 | if (cp_function_chain->extern_decl_map | |
716 | && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL) | |
717 | && DECL_EXTERNAL (stmt)) | |
718 | { | |
719 | struct cxx_int_tree_map *h, in; | |
720 | in.uid = DECL_UID (stmt); | |
721 | h = (struct cxx_int_tree_map *) | |
722 | htab_find_with_hash (cp_function_chain->extern_decl_map, | |
723 | &in, in.uid); | |
724 | if (h) | |
725 | { | |
726 | *stmt_p = h->to; | |
727 | *walk_subtrees = 0; | |
728 | return NULL; | |
729 | } | |
730 | } | |
731 | ||
dddcebdc | 732 | /* Other than invisiref parms, don't walk the same tree twice. */ |
675cc66a | 733 | if (pointer_set_contains (p_set, stmt)) |
dddcebdc | 734 | { |
735 | *walk_subtrees = 0; | |
736 | return NULL_TREE; | |
737 | } | |
738 | ||
739 | if (TREE_CODE (stmt) == ADDR_EXPR | |
740 | && is_invisiref_parm (TREE_OPERAND (stmt, 0))) | |
741 | { | |
742 | *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0)); | |
743 | *walk_subtrees = 0; | |
744 | } | |
806e4c12 | 745 | else if (TREE_CODE (stmt) == RETURN_EXPR |
746 | && TREE_OPERAND (stmt, 0) | |
747 | && is_invisiref_parm (TREE_OPERAND (stmt, 0))) | |
748 | /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */ | |
749 | *walk_subtrees = 0; | |
6bfa729b | 750 | else if (TREE_CODE (stmt) == OMP_CLAUSE) |
751 | switch (OMP_CLAUSE_CODE (stmt)) | |
752 | { | |
fd6481cf | 753 | case OMP_CLAUSE_LASTPRIVATE: |
754 | /* Don't dereference an invisiref in OpenMP clauses. */ | |
755 | if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) | |
756 | { | |
757 | *walk_subtrees = 0; | |
758 | if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt)) | |
759 | cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt), | |
760 | cp_genericize_r, p_set, NULL); | |
761 | } | |
762 | break; | |
6bfa729b | 763 | case OMP_CLAUSE_PRIVATE: |
764 | case OMP_CLAUSE_SHARED: | |
765 | case OMP_CLAUSE_FIRSTPRIVATE: | |
6bfa729b | 766 | case OMP_CLAUSE_COPYIN: |
767 | case OMP_CLAUSE_COPYPRIVATE: | |
768 | /* Don't dereference an invisiref in OpenMP clauses. */ | |
769 | if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) | |
770 | *walk_subtrees = 0; | |
771 | break; | |
772 | case OMP_CLAUSE_REDUCTION: | |
773 | gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt))); | |
774 | break; | |
775 | default: | |
776 | break; | |
777 | } | |
ce45a448 | 778 | else if (IS_TYPE_OR_DECL_P (stmt)) |
dddab69e | 779 | *walk_subtrees = 0; |
dddcebdc | 780 | |
781 | /* Due to the way voidify_wrapper_expr is written, we don't get a chance | |
782 | to lower this construct before scanning it, so we need to lower these | |
783 | before doing anything else. */ | |
dddab69e | 784 | else if (TREE_CODE (stmt) == CLEANUP_STMT) |
675cc66a | 785 | *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR |
786 | : TRY_FINALLY_EXPR, | |
787 | void_type_node, | |
788 | CLEANUP_BODY (stmt), | |
789 | CLEANUP_EXPR (stmt)); | |
790 | ||
97767aad | 791 | else if (TREE_CODE (stmt) == IF_STMT) |
792 | { | |
793 | genericize_if_stmt (stmt_p); | |
794 | /* *stmt_p has changed, tail recurse to handle it again. */ | |
795 | return cp_genericize_r (stmt_p, walk_subtrees, data); | |
796 | } | |
797 | ||
a0a1efe3 | 798 | /* COND_EXPR might have incompatible types in branches if one or both |
799 | arms are bitfields. Fix it up now. */ | |
800 | else if (TREE_CODE (stmt) == COND_EXPR) | |
801 | { | |
802 | tree type_left | |
803 | = (TREE_OPERAND (stmt, 1) | |
804 | ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1)) | |
805 | : NULL_TREE); | |
806 | tree type_right | |
807 | = (TREE_OPERAND (stmt, 2) | |
808 | ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2)) | |
809 | : NULL_TREE); | |
c9d034f5 | 810 | if (type_left |
811 | && !useless_type_conversion_p (TREE_TYPE (stmt), | |
812 | TREE_TYPE (TREE_OPERAND (stmt, 1)))) | |
a0a1efe3 | 813 | { |
814 | TREE_OPERAND (stmt, 1) | |
815 | = fold_convert (type_left, TREE_OPERAND (stmt, 1)); | |
816 | gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt), | |
817 | type_left)); | |
818 | } | |
c9d034f5 | 819 | if (type_right |
820 | && !useless_type_conversion_p (TREE_TYPE (stmt), | |
821 | TREE_TYPE (TREE_OPERAND (stmt, 2)))) | |
a0a1efe3 | 822 | { |
823 | TREE_OPERAND (stmt, 2) | |
824 | = fold_convert (type_right, TREE_OPERAND (stmt, 2)); | |
825 | gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt), | |
826 | type_right)); | |
827 | } | |
828 | } | |
829 | ||
675cc66a | 830 | pointer_set_insert (p_set, *stmt_p); |
9031d10b | 831 | |
dddab69e | 832 | return NULL; |
833 | } | |
834 | ||
835 | void | |
836 | cp_genericize (tree fndecl) | |
837 | { | |
dddcebdc | 838 | tree t; |
cee17238 | 839 | struct pointer_set_t *p_set; |
dddcebdc | 840 | |
841 | /* Fix up the types of parms passed by invisible reference. */ | |
842 | for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t)) | |
1fe46df1 | 843 | if (TREE_ADDRESSABLE (TREE_TYPE (t))) |
844 | { | |
845 | /* If a function's arguments are copied to create a thunk, | |
846 | then DECL_BY_REFERENCE will be set -- but the type of the | |
847 | argument will be a pointer type, so we will never get | |
848 | here. */ | |
849 | gcc_assert (!DECL_BY_REFERENCE (t)); | |
850 | gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); | |
851 | TREE_TYPE (t) = DECL_ARG_TYPE (t); | |
852 | DECL_BY_REFERENCE (t) = 1; | |
853 | TREE_ADDRESSABLE (t) = 0; | |
854 | relayout_decl (t); | |
855 | } | |
dddcebdc | 856 | |
806e4c12 | 857 | /* Do the same for the return value. */ |
858 | if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) | |
859 | { | |
860 | t = DECL_RESULT (fndecl); | |
861 | TREE_TYPE (t) = build_reference_type (TREE_TYPE (t)); | |
862 | DECL_BY_REFERENCE (t) = 1; | |
863 | TREE_ADDRESSABLE (t) = 0; | |
864 | relayout_decl (t); | |
865 | } | |
866 | ||
dddcebdc | 867 | /* If we're a clone, the body is already GIMPLE. */ |
868 | if (DECL_CLONED_FUNCTION_P (fndecl)) | |
869 | return; | |
870 | ||
871 | /* We do want to see every occurrence of the parms, so we can't just use | |
872 | walk_tree's hash functionality. */ | |
cee17238 | 873 | p_set = pointer_set_create (); |
20a8f962 | 874 | cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL); |
cee17238 | 875 | pointer_set_destroy (p_set); |
dddab69e | 876 | |
877 | /* Do everything else. */ | |
878 | c_genericize (fndecl); | |
8487df40 | 879 | |
880 | gcc_assert (bc_label[bc_break] == NULL); | |
881 | gcc_assert (bc_label[bc_continue] == NULL); | |
882 | } | |
883 | \f | |
884 | /* Build code to apply FN to each member of ARG1 and ARG2. FN may be | |
885 | NULL if there is in fact nothing to do. ARG2 may be null if FN | |
886 | actually only takes one argument. */ | |
887 | ||
888 | static tree | |
889 | cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2) | |
890 | { | |
c1be427d | 891 | tree defparm, parm, t; |
d01f58f9 | 892 | int i = 0; |
893 | int nargs; | |
894 | tree *argarray; | |
2f2c591f | 895 | |
8487df40 | 896 | if (fn == NULL) |
897 | return NULL; | |
898 | ||
d01f58f9 | 899 | nargs = list_length (DECL_ARGUMENTS (fn)); |
900 | argarray = (tree *) alloca (nargs * sizeof (tree)); | |
901 | ||
2f2c591f | 902 | defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn))); |
903 | if (arg2) | |
904 | defparm = TREE_CHAIN (defparm); | |
905 | ||
8487df40 | 906 | if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE) |
907 | { | |
908 | tree inner_type = TREE_TYPE (arg1); | |
909 | tree start1, end1, p1; | |
910 | tree start2 = NULL, p2 = NULL; | |
c1be427d | 911 | tree ret = NULL, lab; |
8487df40 | 912 | |
913 | start1 = arg1; | |
914 | start2 = arg2; | |
915 | do | |
916 | { | |
917 | inner_type = TREE_TYPE (inner_type); | |
918 | start1 = build4 (ARRAY_REF, inner_type, start1, | |
919 | size_zero_node, NULL, NULL); | |
920 | if (arg2) | |
921 | start2 = build4 (ARRAY_REF, inner_type, start2, | |
922 | size_zero_node, NULL, NULL); | |
923 | } | |
924 | while (TREE_CODE (inner_type) == ARRAY_TYPE); | |
925 | start1 = build_fold_addr_expr (start1); | |
926 | if (arg2) | |
927 | start2 = build_fold_addr_expr (start2); | |
928 | ||
929 | end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1)); | |
0de36bdb | 930 | end1 = build2 (POINTER_PLUS_EXPR, TREE_TYPE (start1), start1, end1); |
8487df40 | 931 | |
932 | p1 = create_tmp_var (TREE_TYPE (start1), NULL); | |
75a70cf9 | 933 | t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, start1); |
8487df40 | 934 | append_to_statement_list (t, &ret); |
935 | ||
936 | if (arg2) | |
937 | { | |
938 | p2 = create_tmp_var (TREE_TYPE (start2), NULL); | |
75a70cf9 | 939 | t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, start2); |
8487df40 | 940 | append_to_statement_list (t, &ret); |
941 | } | |
942 | ||
e60a6f7b | 943 | lab = create_artificial_label (input_location); |
8487df40 | 944 | t = build1 (LABEL_EXPR, void_type_node, lab); |
945 | append_to_statement_list (t, &ret); | |
946 | ||
d01f58f9 | 947 | argarray[i++] = p1; |
8487df40 | 948 | if (arg2) |
d01f58f9 | 949 | argarray[i++] = p2; |
2f2c591f | 950 | /* Handle default arguments. */ |
93bb78b6 | 951 | for (parm = defparm; parm && parm != void_list_node; |
952 | parm = TREE_CHAIN (parm), i++) | |
d01f58f9 | 953 | argarray[i] = convert_default_arg (TREE_VALUE (parm), |
954 | TREE_PURPOSE (parm), fn, i); | |
955 | t = build_call_a (fn, i, argarray); | |
c1be427d | 956 | t = fold_convert (void_type_node, t); |
957 | t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); | |
8487df40 | 958 | append_to_statement_list (t, &ret); |
959 | ||
0de36bdb | 960 | t = TYPE_SIZE_UNIT (inner_type); |
961 | t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p1), p1, t); | |
75a70cf9 | 962 | t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, t); |
8487df40 | 963 | append_to_statement_list (t, &ret); |
964 | ||
965 | if (arg2) | |
966 | { | |
0de36bdb | 967 | t = TYPE_SIZE_UNIT (inner_type); |
968 | t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p2), p2, t); | |
75a70cf9 | 969 | t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, t); |
8487df40 | 970 | append_to_statement_list (t, &ret); |
971 | } | |
972 | ||
973 | t = build2 (NE_EXPR, boolean_type_node, p1, end1); | |
974 | t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL); | |
975 | append_to_statement_list (t, &ret); | |
976 | ||
977 | return ret; | |
978 | } | |
979 | else | |
980 | { | |
d01f58f9 | 981 | argarray[i++] = build_fold_addr_expr (arg1); |
8487df40 | 982 | if (arg2) |
d01f58f9 | 983 | argarray[i++] = build_fold_addr_expr (arg2); |
2f2c591f | 984 | /* Handle default arguments. */ |
93bb78b6 | 985 | for (parm = defparm; parm && parm != void_list_node; |
d01f58f9 | 986 | parm = TREE_CHAIN (parm), i++) |
987 | argarray[i] = convert_default_arg (TREE_VALUE (parm), | |
988 | TREE_PURPOSE (parm), | |
989 | fn, i); | |
c1be427d | 990 | t = build_call_a (fn, i, argarray); |
991 | t = fold_convert (void_type_node, t); | |
992 | return fold_build_cleanup_point_expr (TREE_TYPE (t), t); | |
8487df40 | 993 | } |
994 | } | |
995 | ||
996 | /* Return code to initialize DECL with its default constructor, or | |
997 | NULL if there's nothing to do. */ | |
998 | ||
999 | tree | |
fd6481cf | 1000 | cxx_omp_clause_default_ctor (tree clause, tree decl, |
1001 | tree outer ATTRIBUTE_UNUSED) | |
8487df40 | 1002 | { |
1003 | tree info = CP_OMP_CLAUSE_INFO (clause); | |
1004 | tree ret = NULL; | |
1005 | ||
1006 | if (info) | |
1007 | ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL); | |
1008 | ||
1009 | return ret; | |
1010 | } | |
1011 | ||
1012 | /* Return code to initialize DST with a copy constructor from SRC. */ | |
1013 | ||
1014 | tree | |
1015 | cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src) | |
1016 | { | |
1017 | tree info = CP_OMP_CLAUSE_INFO (clause); | |
1018 | tree ret = NULL; | |
1019 | ||
1020 | if (info) | |
1021 | ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src); | |
1022 | if (ret == NULL) | |
75a70cf9 | 1023 | ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src); |
8487df40 | 1024 | |
1025 | return ret; | |
1026 | } | |
1027 | ||
1028 | /* Similarly, except use an assignment operator instead. */ | |
1029 | ||
1030 | tree | |
1031 | cxx_omp_clause_assign_op (tree clause, tree dst, tree src) | |
1032 | { | |
1033 | tree info = CP_OMP_CLAUSE_INFO (clause); | |
1034 | tree ret = NULL; | |
1035 | ||
1036 | if (info) | |
1037 | ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src); | |
1038 | if (ret == NULL) | |
75a70cf9 | 1039 | ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src); |
8487df40 | 1040 | |
1041 | return ret; | |
1042 | } | |
1043 | ||
1044 | /* Return code to destroy DECL. */ | |
1045 | ||
1046 | tree | |
1047 | cxx_omp_clause_dtor (tree clause, tree decl) | |
1048 | { | |
1049 | tree info = CP_OMP_CLAUSE_INFO (clause); | |
1050 | tree ret = NULL; | |
1051 | ||
1052 | if (info) | |
1053 | ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL); | |
1054 | ||
1055 | return ret; | |
dddab69e | 1056 | } |
df2c34fc | 1057 | |
1058 | /* True if OpenMP should privatize what this DECL points to rather | |
1059 | than the DECL itself. */ | |
1060 | ||
1061 | bool | |
9f627b1a | 1062 | cxx_omp_privatize_by_reference (const_tree decl) |
df2c34fc | 1063 | { |
6bfa729b | 1064 | return is_invisiref_parm (decl); |
df2c34fc | 1065 | } |
fd6481cf | 1066 | |
1067 | /* True if OpenMP sharing attribute of DECL is predetermined. */ | |
1068 | ||
1069 | enum omp_clause_default_kind | |
1070 | cxx_omp_predetermined_sharing (tree decl) | |
1071 | { | |
1072 | tree type; | |
1073 | ||
1074 | /* Static data members are predetermined as shared. */ | |
1075 | if (TREE_STATIC (decl)) | |
1076 | { | |
1077 | tree ctx = CP_DECL_CONTEXT (decl); | |
1078 | if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx)) | |
1079 | return OMP_CLAUSE_DEFAULT_SHARED; | |
1080 | } | |
1081 | ||
1082 | type = TREE_TYPE (decl); | |
1083 | if (TREE_CODE (type) == REFERENCE_TYPE) | |
1084 | { | |
1085 | if (!is_invisiref_parm (decl)) | |
1086 | return OMP_CLAUSE_DEFAULT_UNSPECIFIED; | |
1087 | type = TREE_TYPE (type); | |
1088 | ||
1089 | if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl)) | |
1090 | { | |
1091 | /* NVR doesn't preserve const qualification of the | |
1092 | variable's type. */ | |
1093 | tree outer = outer_curly_brace_block (current_function_decl); | |
1094 | tree var; | |
1095 | ||
1096 | if (outer) | |
1097 | for (var = BLOCK_VARS (outer); var; var = TREE_CHAIN (var)) | |
1098 | if (DECL_NAME (decl) == DECL_NAME (var) | |
1099 | && (TYPE_MAIN_VARIANT (type) | |
1100 | == TYPE_MAIN_VARIANT (TREE_TYPE (var)))) | |
1101 | { | |
1102 | if (TYPE_READONLY (TREE_TYPE (var))) | |
1103 | type = TREE_TYPE (var); | |
1104 | break; | |
1105 | } | |
1106 | } | |
1107 | } | |
1108 | ||
1109 | if (type == error_mark_node) | |
1110 | return OMP_CLAUSE_DEFAULT_UNSPECIFIED; | |
1111 | ||
1112 | /* Variables with const-qualified type having no mutable member | |
1113 | are predetermined shared. */ | |
1114 | if (TYPE_READONLY (type) && !cp_has_mutable_p (type)) | |
1115 | return OMP_CLAUSE_DEFAULT_SHARED; | |
1116 | ||
1117 | return OMP_CLAUSE_DEFAULT_UNSPECIFIED; | |
1118 | } | |
1119 | ||
1120 | /* Finalize an implicitly determined clause. */ | |
1121 | ||
1122 | void | |
1123 | cxx_omp_finish_clause (tree c) | |
1124 | { | |
1125 | tree decl, inner_type; | |
1126 | bool make_shared = false; | |
1127 | ||
1128 | if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE) | |
1129 | return; | |
1130 | ||
1131 | decl = OMP_CLAUSE_DECL (c); | |
1132 | decl = require_complete_type (decl); | |
1133 | inner_type = TREE_TYPE (decl); | |
1134 | if (decl == error_mark_node) | |
1135 | make_shared = true; | |
1136 | else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE) | |
1137 | { | |
1138 | if (is_invisiref_parm (decl)) | |
1139 | inner_type = TREE_TYPE (inner_type); | |
1140 | else | |
1141 | { | |
1142 | error ("%qE implicitly determined as %<firstprivate%> has reference type", | |
1143 | decl); | |
1144 | make_shared = true; | |
1145 | } | |
1146 | } | |
1147 | ||
1148 | /* We're interested in the base element, not arrays. */ | |
1149 | while (TREE_CODE (inner_type) == ARRAY_TYPE) | |
1150 | inner_type = TREE_TYPE (inner_type); | |
1151 | ||
1152 | /* Check for special function availability by building a call to one. | |
1153 | Save the results, because later we won't be in the right context | |
1154 | for making these queries. */ | |
1155 | if (!make_shared | |
1156 | && CLASS_TYPE_P (inner_type) | |
1157 | && cxx_omp_create_clause_info (c, inner_type, false, true, false)) | |
1158 | make_shared = true; | |
1159 | ||
1160 | if (make_shared) | |
1161 | OMP_CLAUSE_CODE (c) = OMP_CLAUSE_SHARED; | |
1162 | } |