Merge from trunk @ 138209
[official-gcc.git] / gcc / cp / cp-gimplify.c
blob8dda74d3cbe22bd0e40c787a46b08f08c214715f
1 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
3 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
4 Free Software Foundation, Inc.
5 Contributed by Jason Merrill <jason@redhat.com>
7 This file is part of GCC.
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
11 Software Foundation; either version 3, or (at your option) any later
12 version.
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.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
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"
31 #include "tree-iterator.h"
32 #include "gimple.h"
33 #include "hashtab.h"
34 #include "pointer-set.h"
35 #include "flags.h"
37 /* Local declarations. */
39 enum bc_t { bc_break = 0, bc_continue = 1 };
41 /* Stack of labels which are targets for "break" or "continue",
42 linked through TREE_CHAIN. */
43 static tree bc_label[2];
45 /* Begin a scope which can be exited by a break or continue statement. BC
46 indicates which.
48 Just creates a label and pushes it into the current context. */
50 static tree
51 begin_bc_block (enum bc_t bc)
53 tree label = create_artificial_label ();
54 TREE_CHAIN (label) = bc_label[bc];
55 bc_label[bc] = label;
56 return label;
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.
63 If we saw a break (or continue) in the scope, append a LABEL_EXPR to
64 body. Otherwise, just forget the label. */
66 static gimple_seq
67 finish_bc_block (enum bc_t bc, tree label, gimple_seq body)
69 gcc_assert (label == bc_label[bc]);
71 if (TREE_USED (label))
73 gimple_seq_add_stmt (&body, gimple_build_label (label));
76 bc_label[bc] = TREE_CHAIN (label);
77 TREE_CHAIN (label) = NULL_TREE;
78 return body;
81 /* Get the LABEL_EXPR to represent a break or continue statement
82 in the current block scope. BC indicates which. */
84 static tree
85 get_bc_label (enum bc_t bc)
87 tree label = bc_label[bc];
89 if (label == NULL_TREE)
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");
96 return NULL_TREE;
99 /* Mark the label used for finish_bc_block. */
100 TREE_USED (label) = 1;
101 return label;
104 /* Genericize a TRY_BLOCK. */
106 static void
107 genericize_try_block (tree *stmt_p)
109 tree body = TRY_STMTS (*stmt_p);
110 tree cleanup = TRY_HANDLERS (*stmt_p);
112 *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
115 /* Genericize a HANDLER by converting to a CATCH_EXPR. */
117 static void
118 genericize_catch_block (tree *stmt_p)
120 tree type = HANDLER_TYPE (*stmt_p);
121 tree body = HANDLER_BODY (*stmt_p);
123 /* FIXME should the caught type go in TREE_TYPE? */
124 *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
127 /* A terser interface for building a representation of an exception
128 specification. */
130 static tree
131 build_gimple_eh_filter_tree (tree body, tree allowed, tree failure)
133 tree t;
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));
139 t = build2 (TRY_CATCH_EXPR, void_type_node, NULL_TREE, t);
140 append_to_statement_list (body, &TREE_OPERAND (t, 0));
142 return t;
145 /* Genericize an EH_SPEC_BLOCK by converting it to a
146 TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
148 static void
149 genericize_eh_spec_block (tree *stmt_p)
151 tree body = EH_SPEC_STMTS (*stmt_p);
152 tree allowed = EH_SPEC_RAISES (*stmt_p);
153 tree failure = build_call_n (call_unexpected_node, 1, build_exc_ptr ());
155 *stmt_p = build_gimple_eh_filter_tree (body, allowed, failure);
158 /* Genericize an IF_STMT by turning it into a COND_EXPR. */
160 static void
161 gimplify_if_stmt (tree *stmt_p)
163 tree stmt, cond, then_, else_;
164 location_t locus = EXPR_LOCATION (*stmt_p);
166 stmt = *stmt_p;
167 cond = IF_COND (stmt);
168 then_ = THEN_CLAUSE (stmt);
169 else_ = ELSE_CLAUSE (stmt);
171 if (!then_)
172 then_ = build_empty_stmt ();
173 if (!else_)
174 else_ = build_empty_stmt ();
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_);
182 if (CAN_HAVE_LOCATION_P (stmt) && !EXPR_HAS_LOCATION (stmt))
183 SET_EXPR_LOCATION (stmt, locus);
184 *stmt_p = stmt;
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. */
194 static gimple_seq
195 gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
197 gimple top, entry, stmt;
198 gimple_seq stmt_list, body_seq, incr_seq, exit_seq;
199 tree cont_block, break_block;
200 location_t stmt_locus;
202 stmt_locus = input_location;
203 stmt_list = NULL;
204 body_seq = NULL;
205 incr_seq = NULL;
206 exit_seq = NULL;
207 entry = NULL;
209 break_block = begin_bc_block (bc_break);
210 cont_block = begin_bc_block (bc_continue);
212 /* If condition is zero don't generate a loop construct. */
213 if (cond && integer_zerop (cond))
215 top = NULL;
216 if (cond_is_first)
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);
223 else
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. */
229 top = gimple_build_label (create_artificial_label ());
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. */
234 if (cond && !integer_nonzerop (cond))
236 if (cond != error_mark_node)
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);
246 if (cond_is_first)
248 if (incr)
250 entry = gimple_build_label (create_artificial_label ());
251 stmt = gimple_build_goto (gimple_label_label (entry));
253 else
254 stmt = gimple_build_goto (get_bc_label (bc_continue));
255 gimple_set_location (stmt, stmt_locus);
256 gimple_seq_add_stmt (&stmt_list, stmt);
259 else
261 stmt = gimple_build_goto (gimple_label_label (top));
262 gimple_seq_add_stmt (&exit_seq, stmt);
266 gimplify_stmt (&body, &body_seq);
267 gimplify_stmt (&incr, &incr_seq);
269 body_seq = finish_bc_block (bc_continue, cont_block, body_seq);
271 gimple_seq_add_stmt (&stmt_list, top);
272 gimple_seq_add_seq (&stmt_list, body_seq);
273 gimple_seq_add_seq (&stmt_list, incr_seq);
274 gimple_seq_add_stmt (&stmt_list, entry);
275 gimple_seq_add_seq (&stmt_list, exit_seq);
277 annotate_all_with_location (stmt_list, stmt_locus);
279 return finish_bc_block (bc_break, break_block, stmt_list);
282 /* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the
283 prequeue and hand off to gimplify_cp_loop. */
285 static void
286 gimplify_for_stmt (tree *stmt_p, gimple_seq *pre_p)
288 tree stmt = *stmt_p;
290 if (FOR_INIT_STMT (stmt))
291 gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
293 gimple_seq_add_seq (pre_p,
294 gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
295 FOR_EXPR (stmt), 1));
296 *stmt_p = NULL_TREE;
299 /* Gimplify a WHILE_STMT node. */
301 static void
302 gimplify_while_stmt (tree *stmt_p, gimple_seq *pre_p)
304 tree stmt = *stmt_p;
305 gimple_seq_add_seq (pre_p,
306 gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
307 NULL_TREE, 1));
308 *stmt_p = NULL_TREE;
311 /* Gimplify a DO_STMT node. */
313 static void
314 gimplify_do_stmt (tree *stmt_p, gimple_seq *pre_p)
316 tree stmt = *stmt_p;
317 gimple_seq_add_seq (pre_p,
318 gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
319 NULL_TREE, 0));
320 *stmt_p = NULL_TREE;
323 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */
325 static void
326 gimplify_switch_stmt (tree *stmt_p, gimple_seq *pre_p)
328 tree stmt = *stmt_p;
329 tree break_block, body, t;
330 location_t stmt_locus = input_location;
331 gimple_seq seq = NULL;
333 break_block = begin_bc_block (bc_break);
335 body = SWITCH_STMT_BODY (stmt);
336 if (!body)
337 body = build_empty_stmt ();
339 t = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
340 SWITCH_STMT_COND (stmt), body, NULL_TREE);
341 SET_EXPR_LOCATION (t, stmt_locus);
342 gimplify_and_add (t, &seq);
344 seq = finish_bc_block (bc_break, break_block, seq);
345 gimple_seq_add_seq (pre_p, seq);
346 *stmt_p = NULL_TREE;
349 /* Hook into the middle of gimplifying an OMP_FOR node. This is required
350 in order to properly gimplify CONTINUE statements. Here we merely
351 manage the continue stack; the rest of the job is performed by the
352 regular gimplifier. */
354 static enum gimplify_status
355 cp_gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
357 tree for_stmt = *expr_p;
358 tree cont_block;
359 gimple stmt;
360 gimple_seq seq = NULL;
362 /* Protect ourselves from recursion. */
363 if (OMP_FOR_GIMPLIFYING_P (for_stmt))
364 return GS_UNHANDLED;
365 OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
367 /* Note that while technically the continue label is enabled too soon
368 here, we should have already diagnosed invalid continues nested within
369 statement expressions within the INIT, COND, or INCR expressions. */
370 cont_block = begin_bc_block (bc_continue);
372 gimplify_and_add (for_stmt, &seq);
373 stmt = gimple_seq_last_stmt (seq);
374 if (gimple_code (stmt) == GIMPLE_OMP_FOR)
375 gimple_omp_set_body (stmt, finish_bc_block (bc_continue, cont_block,
376 gimple_omp_body (stmt)));
377 else
378 seq = finish_bc_block (bc_continue, cont_block, seq);
379 gimple_seq_add_seq (pre_p, seq);
381 OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
383 return GS_ALL_DONE;
386 /* Gimplify an EXPR_STMT node. */
388 static void
389 gimplify_expr_stmt (tree *stmt_p)
391 tree stmt = EXPR_STMT_EXPR (*stmt_p);
393 if (stmt == error_mark_node)
394 stmt = NULL;
396 /* Gimplification of a statement expression will nullify the
397 statement if all its side effects are moved to *PRE_P and *POST_P.
399 In this case we will not want to emit the gimplified statement.
400 However, we may still want to emit a warning, so we do that before
401 gimplification. */
402 if (stmt && warn_unused_value)
404 if (!TREE_SIDE_EFFECTS (stmt))
406 if (!IS_EMPTY_STMT (stmt)
407 && !VOID_TYPE_P (TREE_TYPE (stmt))
408 && !TREE_NO_WARNING (stmt))
409 warning (OPT_Wunused_value, "statement with no effect");
411 else
412 warn_if_unused_value (stmt, input_location);
415 if (stmt == NULL_TREE)
416 stmt = alloc_stmt_list ();
418 *stmt_p = stmt;
421 /* Gimplify initialization from an AGGR_INIT_EXPR. */
423 static void
424 cp_gimplify_init_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
426 tree from = TREE_OPERAND (*expr_p, 1);
427 tree to = TREE_OPERAND (*expr_p, 0);
428 tree t;
429 tree slot = NULL_TREE;
431 /* What about code that pulls out the temp and uses it elsewhere? I
432 think that such code never uses the TARGET_EXPR as an initializer. If
433 I'm wrong, we'll abort because the temp won't have any RTL. In that
434 case, I guess we'll need to replace references somehow. */
435 if (TREE_CODE (from) == TARGET_EXPR)
437 slot = TARGET_EXPR_SLOT (from);
438 from = TARGET_EXPR_INITIAL (from);
441 /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
442 inside the TARGET_EXPR. */
443 for (t = from; t; )
445 tree sub = TREE_CODE (t) == COMPOUND_EXPR ? TREE_OPERAND (t, 0) : t;
447 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
448 replace the slot operand with our target.
450 Should we add a target parm to gimplify_expr instead? No, as in this
451 case we want to replace the INIT_EXPR. */
452 if (TREE_CODE (sub) == AGGR_INIT_EXPR)
454 gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
455 AGGR_INIT_EXPR_SLOT (sub) = to;
456 *expr_p = from;
458 /* The initialization is now a side-effect, so the container can
459 become void. */
460 if (from != sub)
461 TREE_TYPE (from) = void_type_node;
463 else if (TREE_CODE (sub) == INIT_EXPR
464 && TREE_OPERAND (sub, 0) == slot)
466 /* An INIT_EXPR under TARGET_EXPR created by build_value_init,
467 will be followed by an AGGR_INIT_EXPR. */
468 gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
469 TREE_OPERAND (sub, 0) = to;
472 if (t == sub)
473 break;
474 else
475 t = TREE_OPERAND (t, 1);
480 /* Gimplify a MUST_NOT_THROW_EXPR. */
482 static enum gimplify_status
483 gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p)
485 tree stmt = *expr_p;
486 tree temp = voidify_wrapper_expr (stmt, NULL);
487 tree body = TREE_OPERAND (stmt, 0);
489 stmt = build_gimple_eh_filter_tree (body, NULL_TREE,
490 build_call_n (terminate_node, 0));
492 gimplify_and_add (stmt, pre_p);
493 if (temp)
495 *expr_p = temp;
496 return GS_OK;
499 *expr_p = NULL;
500 return GS_ALL_DONE;
503 /* Do C++-specific gimplification. Args are as for gimplify_expr. */
506 cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
508 int saved_stmts_are_full_exprs_p = 0;
509 enum tree_code code = TREE_CODE (*expr_p);
510 enum gimplify_status ret;
512 if (STATEMENT_CODE_P (code))
514 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
515 current_stmt_tree ()->stmts_are_full_exprs_p
516 = STMT_IS_FULL_EXPR_P (*expr_p);
519 switch (code)
521 case PTRMEM_CST:
522 *expr_p = cplus_expand_constant (*expr_p);
523 ret = GS_OK;
524 break;
526 case AGGR_INIT_EXPR:
527 simplify_aggr_init_expr (expr_p);
528 ret = GS_OK;
529 break;
531 case THROW_EXPR:
532 /* FIXME communicate throw type to back end, probably by moving
533 THROW_EXPR into ../tree.def. */
534 *expr_p = TREE_OPERAND (*expr_p, 0);
535 ret = GS_OK;
536 break;
538 case MUST_NOT_THROW_EXPR:
539 ret = gimplify_must_not_throw_expr (expr_p, pre_p);
540 break;
542 /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
543 LHS of an assignment might also be involved in the RHS, as in bug
544 25979. */
545 case INIT_EXPR:
546 cp_gimplify_init_expr (expr_p, pre_p, post_p);
547 ret = GS_OK;
548 break;
550 case EMPTY_CLASS_EXPR:
551 /* We create an empty CONSTRUCTOR with RECORD_TYPE. */
552 *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
553 ret = GS_OK;
554 break;
556 case BASELINK:
557 *expr_p = BASELINK_FUNCTIONS (*expr_p);
558 ret = GS_OK;
559 break;
561 case TRY_BLOCK:
562 genericize_try_block (expr_p);
563 ret = GS_OK;
564 break;
566 case HANDLER:
567 genericize_catch_block (expr_p);
568 ret = GS_OK;
569 break;
571 case EH_SPEC_BLOCK:
572 genericize_eh_spec_block (expr_p);
573 ret = GS_OK;
574 break;
576 case USING_STMT:
577 /* Just ignore for now. Eventually we will want to pass this on to
578 the debugger. */
579 *expr_p = NULL;
580 ret = GS_ALL_DONE;
581 break;
583 case IF_STMT:
584 gimplify_if_stmt (expr_p);
585 ret = GS_OK;
586 break;
588 case FOR_STMT:
589 gimplify_for_stmt (expr_p, pre_p);
590 ret = GS_OK;
591 break;
593 case WHILE_STMT:
594 gimplify_while_stmt (expr_p, pre_p);
595 ret = GS_OK;
596 break;
598 case DO_STMT:
599 gimplify_do_stmt (expr_p, pre_p);
600 ret = GS_OK;
601 break;
603 case SWITCH_STMT:
604 gimplify_switch_stmt (expr_p, pre_p);
605 ret = GS_OK;
606 break;
608 case OMP_FOR:
609 ret = cp_gimplify_omp_for (expr_p, pre_p);
610 break;
612 case CONTINUE_STMT:
613 gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_continue)));
614 *expr_p = NULL_TREE;
615 ret = GS_ALL_DONE;
616 break;
618 case BREAK_STMT:
619 gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_break)));
620 *expr_p = NULL_TREE;
621 ret = GS_ALL_DONE;
622 break;
624 case EXPR_STMT:
625 gimplify_expr_stmt (expr_p);
626 ret = GS_OK;
627 break;
629 case UNARY_PLUS_EXPR:
631 tree arg = TREE_OPERAND (*expr_p, 0);
632 tree type = TREE_TYPE (*expr_p);
633 *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
634 : arg;
635 ret = GS_OK;
637 break;
639 default:
640 ret = c_gimplify_expr (expr_p, pre_p, post_p);
641 break;
644 /* Restore saved state. */
645 if (STATEMENT_CODE_P (code))
646 current_stmt_tree ()->stmts_are_full_exprs_p
647 = saved_stmts_are_full_exprs_p;
649 return ret;
652 static inline bool
653 is_invisiref_parm (const_tree t)
655 return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
656 && DECL_BY_REFERENCE (t));
659 /* Return true if the uid in both int tree maps are equal. */
662 cxx_int_tree_map_eq (const void *va, const void *vb)
664 const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
665 const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
666 return (a->uid == b->uid);
669 /* Hash a UID in a cxx_int_tree_map. */
671 unsigned int
672 cxx_int_tree_map_hash (const void *item)
674 return ((const struct cxx_int_tree_map *)item)->uid;
677 /* Perform any pre-gimplification lowering of C++ front end trees to
678 GENERIC. */
680 static tree
681 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
683 tree stmt = *stmt_p;
684 struct pointer_set_t *p_set = (struct pointer_set_t*) data;
686 if (is_invisiref_parm (stmt)
687 /* Don't dereference parms in a thunk, pass the references through. */
688 && !(DECL_THUNK_P (current_function_decl)
689 && TREE_CODE (stmt) == PARM_DECL))
691 *stmt_p = convert_from_reference (stmt);
692 *walk_subtrees = 0;
693 return NULL;
696 /* Map block scope extern declarations to visible declarations with the
697 same name and type in outer scopes if any. */
698 if (cp_function_chain->extern_decl_map
699 && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
700 && DECL_EXTERNAL (stmt))
702 struct cxx_int_tree_map *h, in;
703 in.uid = DECL_UID (stmt);
704 h = (struct cxx_int_tree_map *)
705 htab_find_with_hash (cp_function_chain->extern_decl_map,
706 &in, in.uid);
707 if (h)
709 *stmt_p = h->to;
710 *walk_subtrees = 0;
711 return NULL;
715 /* Other than invisiref parms, don't walk the same tree twice. */
716 if (pointer_set_contains (p_set, stmt))
718 *walk_subtrees = 0;
719 return NULL_TREE;
722 if (TREE_CODE (stmt) == ADDR_EXPR
723 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
725 *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
726 *walk_subtrees = 0;
728 else if (TREE_CODE (stmt) == RETURN_EXPR
729 && TREE_OPERAND (stmt, 0)
730 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
731 /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */
732 *walk_subtrees = 0;
733 else if (TREE_CODE (stmt) == OMP_CLAUSE)
734 switch (OMP_CLAUSE_CODE (stmt))
736 case OMP_CLAUSE_LASTPRIVATE:
737 /* Don't dereference an invisiref in OpenMP clauses. */
738 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
740 *walk_subtrees = 0;
741 if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt))
742 cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt),
743 cp_genericize_r, p_set, NULL);
745 break;
746 case OMP_CLAUSE_PRIVATE:
747 case OMP_CLAUSE_SHARED:
748 case OMP_CLAUSE_FIRSTPRIVATE:
749 case OMP_CLAUSE_COPYIN:
750 case OMP_CLAUSE_COPYPRIVATE:
751 /* Don't dereference an invisiref in OpenMP clauses. */
752 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
753 *walk_subtrees = 0;
754 break;
755 case OMP_CLAUSE_REDUCTION:
756 gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
757 break;
758 default:
759 break;
761 else if (IS_TYPE_OR_DECL_P (stmt))
762 *walk_subtrees = 0;
764 /* Due to the way voidify_wrapper_expr is written, we don't get a chance
765 to lower this construct before scanning it, so we need to lower these
766 before doing anything else. */
767 else if (TREE_CODE (stmt) == CLEANUP_STMT)
768 *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
769 : TRY_FINALLY_EXPR,
770 void_type_node,
771 CLEANUP_BODY (stmt),
772 CLEANUP_EXPR (stmt));
774 pointer_set_insert (p_set, *stmt_p);
776 return NULL;
779 void
780 cp_genericize (tree fndecl)
782 tree t;
783 struct pointer_set_t *p_set;
785 /* Fix up the types of parms passed by invisible reference. */
786 for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
787 if (TREE_ADDRESSABLE (TREE_TYPE (t)))
789 /* If a function's arguments are copied to create a thunk,
790 then DECL_BY_REFERENCE will be set -- but the type of the
791 argument will be a pointer type, so we will never get
792 here. */
793 gcc_assert (!DECL_BY_REFERENCE (t));
794 gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
795 TREE_TYPE (t) = DECL_ARG_TYPE (t);
796 DECL_BY_REFERENCE (t) = 1;
797 TREE_ADDRESSABLE (t) = 0;
798 relayout_decl (t);
801 /* Do the same for the return value. */
802 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
804 t = DECL_RESULT (fndecl);
805 TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
806 DECL_BY_REFERENCE (t) = 1;
807 TREE_ADDRESSABLE (t) = 0;
808 relayout_decl (t);
811 /* If we're a clone, the body is already GIMPLE. */
812 if (DECL_CLONED_FUNCTION_P (fndecl))
813 return;
815 /* We do want to see every occurrence of the parms, so we can't just use
816 walk_tree's hash functionality. */
817 p_set = pointer_set_create ();
818 cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
819 pointer_set_destroy (p_set);
821 /* Do everything else. */
822 c_genericize (fndecl);
824 gcc_assert (bc_label[bc_break] == NULL);
825 gcc_assert (bc_label[bc_continue] == NULL);
828 /* Build code to apply FN to each member of ARG1 and ARG2. FN may be
829 NULL if there is in fact nothing to do. ARG2 may be null if FN
830 actually only takes one argument. */
832 static tree
833 cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
835 tree defparm, parm, t;
836 int i = 0;
837 int nargs;
838 tree *argarray;
840 if (fn == NULL)
841 return NULL;
843 nargs = list_length (DECL_ARGUMENTS (fn));
844 argarray = (tree *) alloca (nargs * sizeof (tree));
846 defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
847 if (arg2)
848 defparm = TREE_CHAIN (defparm);
850 if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
852 tree inner_type = TREE_TYPE (arg1);
853 tree start1, end1, p1;
854 tree start2 = NULL, p2 = NULL;
855 tree ret = NULL, lab;
857 start1 = arg1;
858 start2 = arg2;
861 inner_type = TREE_TYPE (inner_type);
862 start1 = build4 (ARRAY_REF, inner_type, start1,
863 size_zero_node, NULL, NULL);
864 if (arg2)
865 start2 = build4 (ARRAY_REF, inner_type, start2,
866 size_zero_node, NULL, NULL);
868 while (TREE_CODE (inner_type) == ARRAY_TYPE);
869 start1 = build_fold_addr_expr (start1);
870 if (arg2)
871 start2 = build_fold_addr_expr (start2);
873 end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
874 end1 = build2 (POINTER_PLUS_EXPR, TREE_TYPE (start1), start1, end1);
876 p1 = create_tmp_var (TREE_TYPE (start1), NULL);
877 t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, start1);
878 append_to_statement_list (t, &ret);
880 if (arg2)
882 p2 = create_tmp_var (TREE_TYPE (start2), NULL);
883 t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, start2);
884 append_to_statement_list (t, &ret);
887 lab = create_artificial_label ();
888 t = build1 (LABEL_EXPR, void_type_node, lab);
889 append_to_statement_list (t, &ret);
891 argarray[i++] = p1;
892 if (arg2)
893 argarray[i++] = p2;
894 /* Handle default arguments. */
895 for (parm = defparm; parm && parm != void_list_node;
896 parm = TREE_CHAIN (parm), i++)
897 argarray[i] = convert_default_arg (TREE_VALUE (parm),
898 TREE_PURPOSE (parm), fn, i);
899 t = build_call_a (fn, i, argarray);
900 t = fold_convert (void_type_node, t);
901 t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
902 append_to_statement_list (t, &ret);
904 t = TYPE_SIZE_UNIT (inner_type);
905 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p1), p1, t);
906 t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, t);
907 append_to_statement_list (t, &ret);
909 if (arg2)
911 t = TYPE_SIZE_UNIT (inner_type);
912 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p2), p2, t);
913 t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, t);
914 append_to_statement_list (t, &ret);
917 t = build2 (NE_EXPR, boolean_type_node, p1, end1);
918 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
919 append_to_statement_list (t, &ret);
921 return ret;
923 else
925 argarray[i++] = build_fold_addr_expr (arg1);
926 if (arg2)
927 argarray[i++] = build_fold_addr_expr (arg2);
928 /* Handle default arguments. */
929 for (parm = defparm; parm && parm != void_list_node;
930 parm = TREE_CHAIN (parm), i++)
931 argarray[i] = convert_default_arg (TREE_VALUE (parm),
932 TREE_PURPOSE (parm),
933 fn, i);
934 t = build_call_a (fn, i, argarray);
935 t = fold_convert (void_type_node, t);
936 return fold_build_cleanup_point_expr (TREE_TYPE (t), t);
940 /* Return code to initialize DECL with its default constructor, or
941 NULL if there's nothing to do. */
943 tree
944 cxx_omp_clause_default_ctor (tree clause, tree decl,
945 tree outer ATTRIBUTE_UNUSED)
947 tree info = CP_OMP_CLAUSE_INFO (clause);
948 tree ret = NULL;
950 if (info)
951 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
953 return ret;
956 /* Return code to initialize DST with a copy constructor from SRC. */
958 tree
959 cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
961 tree info = CP_OMP_CLAUSE_INFO (clause);
962 tree ret = NULL;
964 if (info)
965 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
966 if (ret == NULL)
967 ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
969 return ret;
972 /* Similarly, except use an assignment operator instead. */
974 tree
975 cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
977 tree info = CP_OMP_CLAUSE_INFO (clause);
978 tree ret = NULL;
980 if (info)
981 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
982 if (ret == NULL)
983 ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
985 return ret;
988 /* Return code to destroy DECL. */
990 tree
991 cxx_omp_clause_dtor (tree clause, tree decl)
993 tree info = CP_OMP_CLAUSE_INFO (clause);
994 tree ret = NULL;
996 if (info)
997 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
999 return ret;
1002 /* True if OpenMP should privatize what this DECL points to rather
1003 than the DECL itself. */
1005 bool
1006 cxx_omp_privatize_by_reference (const_tree decl)
1008 return is_invisiref_parm (decl);
1011 /* True if OpenMP sharing attribute of DECL is predetermined. */
1013 enum omp_clause_default_kind
1014 cxx_omp_predetermined_sharing (tree decl)
1016 tree type;
1018 /* Static data members are predetermined as shared. */
1019 if (TREE_STATIC (decl))
1021 tree ctx = CP_DECL_CONTEXT (decl);
1022 if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
1023 return OMP_CLAUSE_DEFAULT_SHARED;
1026 type = TREE_TYPE (decl);
1027 if (TREE_CODE (type) == REFERENCE_TYPE)
1029 if (!is_invisiref_parm (decl))
1030 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
1031 type = TREE_TYPE (type);
1033 if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl))
1035 /* NVR doesn't preserve const qualification of the
1036 variable's type. */
1037 tree outer = outer_curly_brace_block (current_function_decl);
1038 tree var;
1040 if (outer)
1041 for (var = BLOCK_VARS (outer); var; var = TREE_CHAIN (var))
1042 if (DECL_NAME (decl) == DECL_NAME (var)
1043 && (TYPE_MAIN_VARIANT (type)
1044 == TYPE_MAIN_VARIANT (TREE_TYPE (var))))
1046 if (TYPE_READONLY (TREE_TYPE (var)))
1047 type = TREE_TYPE (var);
1048 break;
1053 if (type == error_mark_node)
1054 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
1056 /* Variables with const-qualified type having no mutable member
1057 are predetermined shared. */
1058 if (TYPE_READONLY (type) && !cp_has_mutable_p (type))
1059 return OMP_CLAUSE_DEFAULT_SHARED;
1061 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
1064 /* Finalize an implicitly determined clause. */
1066 void
1067 cxx_omp_finish_clause (tree c)
1069 tree decl, inner_type;
1070 bool make_shared = false;
1072 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
1073 return;
1075 decl = OMP_CLAUSE_DECL (c);
1076 decl = require_complete_type (decl);
1077 inner_type = TREE_TYPE (decl);
1078 if (decl == error_mark_node)
1079 make_shared = true;
1080 else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
1082 if (is_invisiref_parm (decl))
1083 inner_type = TREE_TYPE (inner_type);
1084 else
1086 error ("%qE implicitly determined as %<firstprivate%> has reference type",
1087 decl);
1088 make_shared = true;
1092 /* We're interested in the base element, not arrays. */
1093 while (TREE_CODE (inner_type) == ARRAY_TYPE)
1094 inner_type = TREE_TYPE (inner_type);
1096 /* Check for special function availability by building a call to one.
1097 Save the results, because later we won't be in the right context
1098 for making these queries. */
1099 if (!make_shared
1100 && CLASS_TYPE_P (inner_type)
1101 && cxx_omp_create_clause_info (c, inner_type, false, true, false))
1102 make_shared = true;
1104 if (make_shared)
1105 OMP_CLAUSE_CODE (c) = OMP_CLAUSE_SHARED;