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