]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/cp/cp-gimplify.c
* c-cppbuiltin.c (c_cpp_builtins): Change _OPENMP value to
[thirdparty/gcc.git] / gcc / cp / cp-gimplify.c
CommitLineData
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
7This file is part of GCC.
8
9GCC is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
aa139c3f 11Software Foundation; either version 3, or (at your option) any later
4ee9c684 12version.
13
14GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17for more details.
18
19You should have received a copy of the GNU General Public License
aa139c3f 20along 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
38enum 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. */
42static 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
49static tree
50begin_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
65static tree
66finish_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
89static tree
90build_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
111static void
112genericize_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
129static void
130genericize_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
144static void
145genericize_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
157static void
158gimplify_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
188static tree
189gimplify_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
263static void
264gimplify_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
277static void
278gimplify_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
287static void
288gimplify_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
297static void
298gimplify_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
323static enum gimplify_status
324cp_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
350static void
351gimplify_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
385static void
386cp_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
444static void
445gimplify_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
467int
468cp_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 613static inline bool
9f627b1a 614is_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
622int
623cxx_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
632unsigned int
633cxx_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
641static tree
dddcebdc 642cp_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
740void
741cp_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
793static tree
794cxx_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
904tree
fd6481cf 905cxx_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
919tree
920cxx_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
935tree
936cxx_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
951tree
952cxx_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
966bool
9f627b1a 967cxx_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
974enum omp_clause_default_kind
975cxx_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
1027void
1028cxx_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}