cp/
[official-gcc.git] / gcc / cp / cp-gimplify.c
blobf9d800ea388bf88c4cacf54222fc5000060a51e6
1 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
3 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
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-gimple.h"
32 #include "hashtab.h"
33 #include "pointer-set.h"
34 #include "flags.h"
36 /* Local declarations. */
38 enum bc_t { bc_break = 0, bc_continue = 1 };
40 /* Stack of labels which are targets for "break" or "continue",
41 linked through TREE_CHAIN. */
42 static tree bc_label[2];
44 /* Begin a scope which can be exited by a break or continue statement. BC
45 indicates which.
47 Just creates a label and pushes it into the current context. */
49 static tree
50 begin_bc_block (enum bc_t bc)
52 tree label = create_artificial_label ();
53 TREE_CHAIN (label) = bc_label[bc];
54 bc_label[bc] = label;
55 return label;
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.
62 If we saw a break (or continue) in the scope, append a LABEL_EXPR to
63 body. Otherwise, just forget the label. */
65 static tree
66 finish_bc_block (enum bc_t bc, tree label, tree body)
68 gcc_assert (label == bc_label[bc]);
70 if (TREE_USED (label))
72 tree t, sl = NULL;
74 t = build1 (LABEL_EXPR, void_type_node, label);
76 append_to_statement_list (body, &sl);
77 append_to_statement_list (t, &sl);
78 body = sl;
81 bc_label[bc] = TREE_CHAIN (label);
82 TREE_CHAIN (label) = NULL_TREE;
83 return body;
86 /* Build a GOTO_EXPR to represent a break or continue statement. BC
87 indicates which. */
89 static tree
90 build_bc_goto (enum bc_t bc)
92 tree label = bc_label[bc];
94 if (label == NULL_TREE)
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");
101 return NULL_TREE;
104 /* Mark the label used for finish_bc_block. */
105 TREE_USED (label) = 1;
106 return build1 (GOTO_EXPR, void_type_node, label);
109 /* Genericize a TRY_BLOCK. */
111 static void
112 genericize_try_block (tree *stmt_p)
114 tree body = TRY_STMTS (*stmt_p);
115 tree cleanup = TRY_HANDLERS (*stmt_p);
117 gimplify_stmt (&body);
119 if (CLEANUP_P (*stmt_p))
120 /* A cleanup is an expression, so it doesn't need to be genericized. */;
121 else
122 gimplify_stmt (&cleanup);
124 *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
127 /* Genericize a HANDLER by converting to a CATCH_EXPR. */
129 static void
130 genericize_catch_block (tree *stmt_p)
132 tree type = HANDLER_TYPE (*stmt_p);
133 tree body = HANDLER_BODY (*stmt_p);
135 gimplify_stmt (&body);
137 /* FIXME should the caught type go in TREE_TYPE? */
138 *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
141 /* Genericize an EH_SPEC_BLOCK by converting it to a
142 TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
144 static void
145 genericize_eh_spec_block (tree *stmt_p)
147 tree body = EH_SPEC_STMTS (*stmt_p);
148 tree allowed = EH_SPEC_RAISES (*stmt_p);
149 tree failure = build_call_n (call_unexpected_node, 1, build_exc_ptr ());
150 gimplify_stmt (&body);
152 *stmt_p = gimple_build_eh_filter (body, allowed, failure);
155 /* Genericize an IF_STMT by turning it into a COND_EXPR. */
157 static void
158 gimplify_if_stmt (tree *stmt_p)
160 tree stmt, cond, then_, else_;
162 stmt = *stmt_p;
163 cond = IF_COND (stmt);
164 then_ = THEN_CLAUSE (stmt);
165 else_ = ELSE_CLAUSE (stmt);
167 if (!then_)
168 then_ = build_empty_stmt ();
169 if (!else_)
170 else_ = build_empty_stmt ();
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_);
178 *stmt_p = stmt;
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. */
188 static tree
189 gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
191 tree top, entry, exit, cont_block, break_block, stmt_list, t;
192 location_t stmt_locus;
194 stmt_locus = input_location;
195 stmt_list = NULL_TREE;
196 entry = NULL_TREE;
198 break_block = begin_bc_block (bc_break);
199 cont_block = begin_bc_block (bc_continue);
201 /* If condition is zero don't generate a loop construct. */
202 if (cond && integer_zerop (cond))
204 top = NULL_TREE;
205 exit = NULL_TREE;
206 if (cond_is_first)
208 t = build_bc_goto (bc_break);
209 append_to_statement_list (t, &stmt_list);
212 else
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);
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))
226 t = build_bc_goto (bc_break);
227 exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
228 gimplify_stmt (&exit);
230 if (cond_is_first)
232 if (incr)
234 entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
235 t = build_and_jump (&LABEL_EXPR_LABEL (entry));
237 else
238 t = build_bc_goto (bc_continue);
239 append_to_statement_list (t, &stmt_list);
244 gimplify_stmt (&body);
245 gimplify_stmt (&incr);
247 body = finish_bc_block (bc_continue, cont_block, body);
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);
255 annotate_all_with_locus (&stmt_list, stmt_locus);
257 return finish_bc_block (bc_break, break_block, stmt_list);
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. */
263 static void
264 gimplify_for_stmt (tree *stmt_p, tree *pre_p)
266 tree stmt = *stmt_p;
268 if (FOR_INIT_STMT (stmt))
269 gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
271 *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
272 FOR_EXPR (stmt), 1);
275 /* Gimplify a WHILE_STMT node. */
277 static void
278 gimplify_while_stmt (tree *stmt_p)
280 tree stmt = *stmt_p;
281 *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
282 NULL_TREE, 1);
285 /* Gimplify a DO_STMT node. */
287 static void
288 gimplify_do_stmt (tree *stmt_p)
290 tree stmt = *stmt_p;
291 *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
292 NULL_TREE, 0);
295 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */
297 static void
298 gimplify_switch_stmt (tree *stmt_p)
300 tree stmt = *stmt_p;
301 tree break_block, body;
302 location_t stmt_locus = input_location;
304 break_block = begin_bc_block (bc_break);
306 body = SWITCH_STMT_BODY (stmt);
307 if (!body)
308 body = build_empty_stmt ();
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);
315 *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p);
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
321 regular gimplifier. */
323 static enum gimplify_status
324 cp_gimplify_omp_for (tree *expr_p)
326 tree for_stmt = *expr_p;
327 tree cont_block;
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;
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);
339 gimplify_stmt (expr_p);
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;
345 return GS_ALL_DONE;
348 /* Gimplify an EXPR_STMT node. */
350 static void
351 gimplify_expr_stmt (tree *stmt_p)
353 tree stmt = EXPR_STMT_EXPR (*stmt_p);
355 if (stmt == error_mark_node)
356 stmt = NULL;
358 /* Gimplification of a statement expression will nullify the
359 statement if all its side effects are moved to *PRE_P and *POST_P.
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. */
364 if (stmt && warn_unused_value)
366 if (!TREE_SIDE_EFFECTS (stmt))
368 if (!IS_EMPTY_STMT (stmt)
369 && !VOID_TYPE_P (TREE_TYPE (stmt))
370 && !TREE_NO_WARNING (stmt))
371 warning (OPT_Wunused_value, "statement with no effect");
373 else
374 warn_if_unused_value (stmt, input_location);
377 if (stmt == NULL_TREE)
378 stmt = alloc_stmt_list ();
380 *stmt_p = stmt;
383 /* Gimplify initialization from an AGGR_INIT_EXPR. */
385 static void
386 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
388 tree from = TREE_OPERAND (*expr_p, 1);
389 tree to = TREE_OPERAND (*expr_p, 0);
390 tree sub;
392 /* What about code that pulls out the temp and uses it elsewhere? I
393 think that such code never uses the TARGET_EXPR as an initializer. If
394 I'm wrong, we'll abort because the temp won't have any RTL. In that
395 case, I guess we'll need to replace references somehow. */
396 if (TREE_CODE (from) == TARGET_EXPR)
397 from = TARGET_EXPR_INITIAL (from);
399 /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
400 inside the TARGET_EXPR. */
401 sub = expr_last (from);
403 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
404 replace the slot operand with our target.
406 Should we add a target parm to gimplify_expr instead? No, as in this
407 case we want to replace the INIT_EXPR. */
408 if (TREE_CODE (sub) == AGGR_INIT_EXPR)
410 gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
411 AGGR_INIT_EXPR_SLOT (sub) = to;
412 *expr_p = from;
414 /* The initialization is now a side-effect, so the container can
415 become void. */
416 if (from != sub)
417 TREE_TYPE (from) = void_type_node;
421 /* Gimplify a MUST_NOT_THROW_EXPR. */
423 static void
424 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
426 tree stmt = *expr_p;
427 tree temp = voidify_wrapper_expr (stmt, NULL);
428 tree body = TREE_OPERAND (stmt, 0);
430 gimplify_stmt (&body);
432 stmt = gimple_build_eh_filter (body, NULL_TREE,
433 build_call_n (terminate_node, 0));
435 if (temp)
437 append_to_statement_list (stmt, pre_p);
438 *expr_p = temp;
440 else
441 *expr_p = stmt;
444 /* Do C++-specific gimplification. Args are as for gimplify_expr. */
447 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
449 int saved_stmts_are_full_exprs_p = 0;
450 enum tree_code code = TREE_CODE (*expr_p);
451 enum gimplify_status ret;
453 if (STATEMENT_CODE_P (code))
455 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
456 current_stmt_tree ()->stmts_are_full_exprs_p
457 = STMT_IS_FULL_EXPR_P (*expr_p);
460 switch (code)
462 case PTRMEM_CST:
463 *expr_p = cplus_expand_constant (*expr_p);
464 ret = GS_OK;
465 break;
467 case AGGR_INIT_EXPR:
468 simplify_aggr_init_expr (expr_p);
469 ret = GS_OK;
470 break;
472 case THROW_EXPR:
473 /* FIXME communicate throw type to back end, probably by moving
474 THROW_EXPR into ../tree.def. */
475 *expr_p = TREE_OPERAND (*expr_p, 0);
476 ret = GS_OK;
477 break;
479 case MUST_NOT_THROW_EXPR:
480 gimplify_must_not_throw_expr (expr_p, pre_p);
481 ret = GS_OK;
482 break;
484 /* We used to do this for GIMPLE_MODIFY_STMT as well, but that's unsafe; the
485 LHS of an assignment might also be involved in the RHS, as in bug
486 25979. */
487 case INIT_EXPR:
488 cp_gimplify_init_expr (expr_p, pre_p, post_p);
489 ret = GS_OK;
490 break;
492 case EMPTY_CLASS_EXPR:
493 /* We create an empty CONSTRUCTOR with RECORD_TYPE. */
494 *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
495 ret = GS_OK;
496 break;
498 case BASELINK:
499 *expr_p = BASELINK_FUNCTIONS (*expr_p);
500 ret = GS_OK;
501 break;
503 case TRY_BLOCK:
504 genericize_try_block (expr_p);
505 ret = GS_OK;
506 break;
508 case HANDLER:
509 genericize_catch_block (expr_p);
510 ret = GS_OK;
511 break;
513 case EH_SPEC_BLOCK:
514 genericize_eh_spec_block (expr_p);
515 ret = GS_OK;
516 break;
518 case USING_STMT:
519 /* Just ignore for now. Eventually we will want to pass this on to
520 the debugger. */
521 *expr_p = build_empty_stmt ();
522 ret = GS_ALL_DONE;
523 break;
525 case IF_STMT:
526 gimplify_if_stmt (expr_p);
527 ret = GS_OK;
528 break;
530 case FOR_STMT:
531 gimplify_for_stmt (expr_p, pre_p);
532 ret = GS_ALL_DONE;
533 break;
535 case WHILE_STMT:
536 gimplify_while_stmt (expr_p);
537 ret = GS_ALL_DONE;
538 break;
540 case DO_STMT:
541 gimplify_do_stmt (expr_p);
542 ret = GS_ALL_DONE;
543 break;
545 case SWITCH_STMT:
546 gimplify_switch_stmt (expr_p);
547 ret = GS_ALL_DONE;
548 break;
550 case OMP_FOR:
551 ret = cp_gimplify_omp_for (expr_p);
552 break;
554 case CONTINUE_STMT:
555 *expr_p = build_bc_goto (bc_continue);
556 ret = GS_ALL_DONE;
557 break;
559 case BREAK_STMT:
560 *expr_p = build_bc_goto (bc_break);
561 ret = GS_ALL_DONE;
562 break;
564 case EXPR_STMT:
565 gimplify_expr_stmt (expr_p);
566 ret = GS_OK;
567 break;
569 case UNARY_PLUS_EXPR:
571 tree arg = TREE_OPERAND (*expr_p, 0);
572 tree type = TREE_TYPE (*expr_p);
573 *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
574 : arg;
575 ret = GS_OK;
577 break;
579 default:
580 ret = c_gimplify_expr (expr_p, pre_p, post_p);
581 break;
584 /* Restore saved state. */
585 if (STATEMENT_CODE_P (code))
586 current_stmt_tree ()->stmts_are_full_exprs_p
587 = saved_stmts_are_full_exprs_p;
589 return ret;
592 static inline bool
593 is_invisiref_parm (const_tree t)
595 return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
596 && DECL_BY_REFERENCE (t));
599 /* Return true if the uid in both int tree maps are equal. */
602 cxx_int_tree_map_eq (const void *va, const void *vb)
604 const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
605 const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
606 return (a->uid == b->uid);
609 /* Hash a UID in a cxx_int_tree_map. */
611 unsigned int
612 cxx_int_tree_map_hash (const void *item)
614 return ((const struct cxx_int_tree_map *)item)->uid;
617 /* Perform any pre-gimplification lowering of C++ front end trees to
618 GENERIC. */
620 static tree
621 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
623 tree stmt = *stmt_p;
624 struct pointer_set_t *p_set = (struct pointer_set_t*) data;
626 if (is_invisiref_parm (stmt)
627 /* Don't dereference parms in a thunk, pass the references through. */
628 && !(DECL_THUNK_P (current_function_decl)
629 && TREE_CODE (stmt) == PARM_DECL))
631 *stmt_p = convert_from_reference (stmt);
632 *walk_subtrees = 0;
633 return NULL;
636 /* Map block scope extern declarations to visible declarations with the
637 same name and type in outer scopes if any. */
638 if (cp_function_chain->extern_decl_map
639 && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
640 && DECL_EXTERNAL (stmt))
642 struct cxx_int_tree_map *h, in;
643 in.uid = DECL_UID (stmt);
644 h = (struct cxx_int_tree_map *)
645 htab_find_with_hash (cp_function_chain->extern_decl_map,
646 &in, in.uid);
647 if (h)
649 *stmt_p = h->to;
650 *walk_subtrees = 0;
651 return NULL;
655 /* Other than invisiref parms, don't walk the same tree twice. */
656 if (pointer_set_contains (p_set, stmt))
658 *walk_subtrees = 0;
659 return NULL_TREE;
662 if (TREE_CODE (stmt) == ADDR_EXPR
663 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
665 *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
666 *walk_subtrees = 0;
668 else if (TREE_CODE (stmt) == RETURN_EXPR
669 && TREE_OPERAND (stmt, 0)
670 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
671 /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */
672 *walk_subtrees = 0;
673 else if (TREE_CODE (stmt) == OMP_CLAUSE)
674 switch (OMP_CLAUSE_CODE (stmt))
676 case OMP_CLAUSE_PRIVATE:
677 case OMP_CLAUSE_SHARED:
678 case OMP_CLAUSE_FIRSTPRIVATE:
679 case OMP_CLAUSE_LASTPRIVATE:
680 case OMP_CLAUSE_COPYIN:
681 case OMP_CLAUSE_COPYPRIVATE:
682 /* Don't dereference an invisiref in OpenMP clauses. */
683 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
684 *walk_subtrees = 0;
685 break;
686 case OMP_CLAUSE_REDUCTION:
687 gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
688 break;
689 default:
690 break;
692 else if (IS_TYPE_OR_DECL_P (stmt))
693 *walk_subtrees = 0;
695 /* Due to the way voidify_wrapper_expr is written, we don't get a chance
696 to lower this construct before scanning it, so we need to lower these
697 before doing anything else. */
698 else if (TREE_CODE (stmt) == CLEANUP_STMT)
699 *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
700 : TRY_FINALLY_EXPR,
701 void_type_node,
702 CLEANUP_BODY (stmt),
703 CLEANUP_EXPR (stmt));
705 pointer_set_insert (p_set, *stmt_p);
707 return NULL;
710 void
711 cp_genericize (tree fndecl)
713 tree t;
714 struct pointer_set_t *p_set;
716 /* Fix up the types of parms passed by invisible reference. */
717 for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
718 if (TREE_ADDRESSABLE (TREE_TYPE (t)))
720 /* If a function's arguments are copied to create a thunk,
721 then DECL_BY_REFERENCE will be set -- but the type of the
722 argument will be a pointer type, so we will never get
723 here. */
724 gcc_assert (!DECL_BY_REFERENCE (t));
725 gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
726 TREE_TYPE (t) = DECL_ARG_TYPE (t);
727 DECL_BY_REFERENCE (t) = 1;
728 TREE_ADDRESSABLE (t) = 0;
729 relayout_decl (t);
732 /* Do the same for the return value. */
733 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
735 t = DECL_RESULT (fndecl);
736 TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
737 DECL_BY_REFERENCE (t) = 1;
738 TREE_ADDRESSABLE (t) = 0;
739 relayout_decl (t);
742 /* If we're a clone, the body is already GIMPLE. */
743 if (DECL_CLONED_FUNCTION_P (fndecl))
744 return;
746 /* We do want to see every occurrence of the parms, so we can't just use
747 walk_tree's hash functionality. */
748 p_set = pointer_set_create ();
749 cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
750 pointer_set_destroy (p_set);
752 /* Do everything else. */
753 c_genericize (fndecl);
755 gcc_assert (bc_label[bc_break] == NULL);
756 gcc_assert (bc_label[bc_continue] == NULL);
759 /* Build code to apply FN to each member of ARG1 and ARG2. FN may be
760 NULL if there is in fact nothing to do. ARG2 may be null if FN
761 actually only takes one argument. */
763 static tree
764 cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
766 tree defparm, parm;
767 int i = 0;
768 int nargs;
769 tree *argarray;
771 if (fn == NULL)
772 return NULL;
774 nargs = list_length (DECL_ARGUMENTS (fn));
775 argarray = (tree *) alloca (nargs * sizeof (tree));
777 defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
778 if (arg2)
779 defparm = TREE_CHAIN (defparm);
781 if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
783 tree inner_type = TREE_TYPE (arg1);
784 tree start1, end1, p1;
785 tree start2 = NULL, p2 = NULL;
786 tree ret = NULL, lab, t;
788 start1 = arg1;
789 start2 = arg2;
792 inner_type = TREE_TYPE (inner_type);
793 start1 = build4 (ARRAY_REF, inner_type, start1,
794 size_zero_node, NULL, NULL);
795 if (arg2)
796 start2 = build4 (ARRAY_REF, inner_type, start2,
797 size_zero_node, NULL, NULL);
799 while (TREE_CODE (inner_type) == ARRAY_TYPE);
800 start1 = build_fold_addr_expr (start1);
801 if (arg2)
802 start2 = build_fold_addr_expr (start2);
804 end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
805 end1 = build2 (POINTER_PLUS_EXPR, TREE_TYPE (start1), start1, end1);
807 p1 = create_tmp_var (TREE_TYPE (start1), NULL);
808 t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p1, start1);
809 append_to_statement_list (t, &ret);
811 if (arg2)
813 p2 = create_tmp_var (TREE_TYPE (start2), NULL);
814 t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p2, start2);
815 append_to_statement_list (t, &ret);
818 lab = create_artificial_label ();
819 t = build1 (LABEL_EXPR, void_type_node, lab);
820 append_to_statement_list (t, &ret);
822 argarray[i++] = p1;
823 if (arg2)
824 argarray[i++] = p2;
825 /* Handle default arguments. */
826 for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm), i++)
827 argarray[i] = convert_default_arg (TREE_VALUE (parm),
828 TREE_PURPOSE (parm), fn, i);
829 t = build_call_a (fn, i, argarray);
830 append_to_statement_list (t, &ret);
832 t = TYPE_SIZE_UNIT (inner_type);
833 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p1), p1, t);
834 t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p1, t);
835 append_to_statement_list (t, &ret);
837 if (arg2)
839 t = TYPE_SIZE_UNIT (inner_type);
840 t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p2), p2, t);
841 t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p2, t);
842 append_to_statement_list (t, &ret);
845 t = build2 (NE_EXPR, boolean_type_node, p1, end1);
846 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
847 append_to_statement_list (t, &ret);
849 return ret;
851 else
853 argarray[i++] = build_fold_addr_expr (arg1);
854 if (arg2)
855 argarray[i++] = build_fold_addr_expr (arg2);
856 /* Handle default arguments. */
857 for (parm = defparm; parm != void_list_node;
858 parm = TREE_CHAIN (parm), i++)
859 argarray[i] = convert_default_arg (TREE_VALUE (parm),
860 TREE_PURPOSE (parm),
861 fn, i);
862 return build_call_a (fn, i, argarray);
866 /* Return code to initialize DECL with its default constructor, or
867 NULL if there's nothing to do. */
869 tree
870 cxx_omp_clause_default_ctor (tree clause, tree decl)
872 tree info = CP_OMP_CLAUSE_INFO (clause);
873 tree ret = NULL;
875 if (info)
876 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
878 return ret;
881 /* Return code to initialize DST with a copy constructor from SRC. */
883 tree
884 cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
886 tree info = CP_OMP_CLAUSE_INFO (clause);
887 tree ret = NULL;
889 if (info)
890 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
891 if (ret == NULL)
892 ret = build2 (GIMPLE_MODIFY_STMT, void_type_node, dst, src);
894 return ret;
897 /* Similarly, except use an assignment operator instead. */
899 tree
900 cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
902 tree info = CP_OMP_CLAUSE_INFO (clause);
903 tree ret = NULL;
905 if (info)
906 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
907 if (ret == NULL)
908 ret = build2 (GIMPLE_MODIFY_STMT, void_type_node, dst, src);
910 return ret;
913 /* Return code to destroy DECL. */
915 tree
916 cxx_omp_clause_dtor (tree clause, tree decl)
918 tree info = CP_OMP_CLAUSE_INFO (clause);
919 tree ret = NULL;
921 if (info)
922 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
924 return ret;
927 /* True if OpenMP should privatize what this DECL points to rather
928 than the DECL itself. */
930 bool
931 cxx_omp_privatize_by_reference (const_tree decl)
933 return is_invisiref_parm (decl);