2011-08-19 Andrew Stubbs <ams@codesourcery.com>
[official-gcc.git] / gcc / cp / cp-gimplify.c
blob6aeae75b06336d60c56c194691c28494deafbdf0
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, 2009, 2010, 2011
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-family/c-common.h"
30 #include "tree-iterator.h"
31 #include "gimple.h"
32 #include "hashtab.h"
33 #include "pointer-set.h"
34 #include "flags.h"
35 #include "splay-tree.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 (input_location);
54 DECL_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] = DECL_CHAIN (label);
77 DECL_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);
156 TREE_NO_WARNING (*stmt_p) = true;
157 TREE_NO_WARNING (TREE_OPERAND (*stmt_p, 1)) = true;
160 /* Genericize an IF_STMT by turning it into a COND_EXPR. */
162 static void
163 genericize_if_stmt (tree *stmt_p)
165 tree stmt, cond, then_, else_;
166 location_t locus = EXPR_LOCATION (*stmt_p);
168 stmt = *stmt_p;
169 cond = IF_COND (stmt);
170 then_ = THEN_CLAUSE (stmt);
171 else_ = ELSE_CLAUSE (stmt);
173 if (!then_)
174 then_ = build_empty_stmt (locus);
175 if (!else_)
176 else_ = build_empty_stmt (locus);
178 if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
179 stmt = then_;
180 else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
181 stmt = else_;
182 else
183 stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
184 if (CAN_HAVE_LOCATION_P (stmt) && !EXPR_HAS_LOCATION (stmt))
185 SET_EXPR_LOCATION (stmt, locus);
186 *stmt_p = stmt;
189 /* Build a generic representation of one of the C loop forms. COND is the
190 loop condition or NULL_TREE. BODY is the (possibly compound) statement
191 controlled by the loop. INCR is the increment expression of a for-loop,
192 or NULL_TREE. COND_IS_FIRST indicates whether the condition is
193 evaluated before the loop body as in while and for loops, or after the
194 loop body as in do-while loops. */
196 static gimple_seq
197 gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
199 gimple top, entry, stmt;
200 gimple_seq stmt_list, body_seq, incr_seq, exit_seq;
201 tree cont_block, break_block;
202 location_t stmt_locus;
204 stmt_locus = input_location;
205 stmt_list = NULL;
206 body_seq = NULL;
207 incr_seq = NULL;
208 exit_seq = NULL;
209 entry = NULL;
211 break_block = begin_bc_block (bc_break);
212 cont_block = begin_bc_block (bc_continue);
214 /* If condition is zero don't generate a loop construct. */
215 if (cond && integer_zerop (cond))
217 top = NULL;
218 if (cond_is_first)
220 stmt = gimple_build_goto (get_bc_label (bc_break));
221 gimple_set_location (stmt, stmt_locus);
222 gimple_seq_add_stmt (&stmt_list, stmt);
225 else
227 /* If we use a LOOP_EXPR here, we have to feed the whole thing
228 back through the main gimplifier to lower it. Given that we
229 have to gimplify the loop body NOW so that we can resolve
230 break/continue stmts, seems easier to just expand to gotos. */
231 top = gimple_build_label (create_artificial_label (stmt_locus));
233 /* If we have an exit condition, then we build an IF with gotos either
234 out of the loop, or to the top of it. If there's no exit condition,
235 then we just build a jump back to the top. */
236 if (cond && !integer_nonzerop (cond))
238 if (cond != error_mark_node)
240 gimplify_expr (&cond, &exit_seq, NULL, is_gimple_val, fb_rvalue);
241 stmt = gimple_build_cond (NE_EXPR, cond,
242 build_int_cst (TREE_TYPE (cond), 0),
243 gimple_label_label (top),
244 get_bc_label (bc_break));
245 gimple_seq_add_stmt (&exit_seq, stmt);
248 if (cond_is_first)
250 if (incr)
252 entry = gimple_build_label
253 (create_artificial_label (stmt_locus));
254 stmt = gimple_build_goto (gimple_label_label (entry));
256 else
257 stmt = gimple_build_goto (get_bc_label (bc_continue));
258 gimple_set_location (stmt, stmt_locus);
259 gimple_seq_add_stmt (&stmt_list, stmt);
262 else
264 stmt = gimple_build_goto (gimple_label_label (top));
265 gimple_seq_add_stmt (&exit_seq, stmt);
269 gimplify_stmt (&body, &body_seq);
270 gimplify_stmt (&incr, &incr_seq);
272 body_seq = finish_bc_block (bc_continue, cont_block, body_seq);
274 gimple_seq_add_stmt (&stmt_list, top);
275 gimple_seq_add_seq (&stmt_list, body_seq);
276 gimple_seq_add_seq (&stmt_list, incr_seq);
277 gimple_seq_add_stmt (&stmt_list, entry);
278 gimple_seq_add_seq (&stmt_list, exit_seq);
280 annotate_all_with_location (stmt_list, stmt_locus);
282 return finish_bc_block (bc_break, break_block, stmt_list);
285 /* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the
286 prequeue and hand off to gimplify_cp_loop. */
288 static void
289 gimplify_for_stmt (tree *stmt_p, gimple_seq *pre_p)
291 tree stmt = *stmt_p;
293 if (FOR_INIT_STMT (stmt))
294 gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
296 gimple_seq_add_seq (pre_p,
297 gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
298 FOR_EXPR (stmt), 1));
299 *stmt_p = NULL_TREE;
302 /* Gimplify a WHILE_STMT node. */
304 static void
305 gimplify_while_stmt (tree *stmt_p, gimple_seq *pre_p)
307 tree stmt = *stmt_p;
308 gimple_seq_add_seq (pre_p,
309 gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
310 NULL_TREE, 1));
311 *stmt_p = NULL_TREE;
314 /* Gimplify a DO_STMT node. */
316 static void
317 gimplify_do_stmt (tree *stmt_p, gimple_seq *pre_p)
319 tree stmt = *stmt_p;
320 gimple_seq_add_seq (pre_p,
321 gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
322 NULL_TREE, 0));
323 *stmt_p = NULL_TREE;
326 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */
328 static void
329 gimplify_switch_stmt (tree *stmt_p, gimple_seq *pre_p)
331 tree stmt = *stmt_p;
332 tree break_block, body, t;
333 location_t stmt_locus = input_location;
334 gimple_seq seq = NULL;
336 break_block = begin_bc_block (bc_break);
338 body = SWITCH_STMT_BODY (stmt);
339 if (!body)
340 body = build_empty_stmt (stmt_locus);
342 t = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
343 SWITCH_STMT_COND (stmt), body, NULL_TREE);
344 SET_EXPR_LOCATION (t, stmt_locus);
345 gimplify_and_add (t, &seq);
347 seq = finish_bc_block (bc_break, break_block, seq);
348 gimple_seq_add_seq (pre_p, seq);
349 *stmt_p = NULL_TREE;
352 /* Hook into the middle of gimplifying an OMP_FOR node. This is required
353 in order to properly gimplify CONTINUE statements. Here we merely
354 manage the continue stack; the rest of the job is performed by the
355 regular gimplifier. */
357 static enum gimplify_status
358 cp_gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
360 tree for_stmt = *expr_p;
361 tree cont_block;
362 gimple stmt;
363 gimple_seq seq = NULL;
365 /* Protect ourselves from recursion. */
366 if (OMP_FOR_GIMPLIFYING_P (for_stmt))
367 return GS_UNHANDLED;
368 OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
370 /* Note that while technically the continue label is enabled too soon
371 here, we should have already diagnosed invalid continues nested within
372 statement expressions within the INIT, COND, or INCR expressions. */
373 cont_block = begin_bc_block (bc_continue);
375 gimplify_and_add (for_stmt, &seq);
376 stmt = gimple_seq_last_stmt (seq);
377 if (gimple_code (stmt) == GIMPLE_OMP_FOR)
378 gimple_omp_set_body (stmt, finish_bc_block (bc_continue, cont_block,
379 gimple_omp_body (stmt)));
380 else
381 seq = finish_bc_block (bc_continue, cont_block, seq);
382 gimple_seq_add_seq (pre_p, seq);
384 OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
386 return GS_ALL_DONE;
389 /* Gimplify an EXPR_STMT node. */
391 static void
392 gimplify_expr_stmt (tree *stmt_p)
394 tree stmt = EXPR_STMT_EXPR (*stmt_p);
396 if (stmt == error_mark_node)
397 stmt = NULL;
399 /* Gimplification of a statement expression will nullify the
400 statement if all its side effects are moved to *PRE_P and *POST_P.
402 In this case we will not want to emit the gimplified statement.
403 However, we may still want to emit a warning, so we do that before
404 gimplification. */
405 if (stmt && warn_unused_value)
407 if (!TREE_SIDE_EFFECTS (stmt))
409 if (!IS_EMPTY_STMT (stmt)
410 && !VOID_TYPE_P (TREE_TYPE (stmt))
411 && !TREE_NO_WARNING (stmt))
412 warning (OPT_Wunused_value, "statement with no effect");
414 else
415 warn_if_unused_value (stmt, input_location);
418 if (stmt == NULL_TREE)
419 stmt = alloc_stmt_list ();
421 *stmt_p = stmt;
424 /* Gimplify initialization from an AGGR_INIT_EXPR. */
426 static void
427 cp_gimplify_init_expr (tree *expr_p)
429 tree from = TREE_OPERAND (*expr_p, 1);
430 tree to = TREE_OPERAND (*expr_p, 0);
431 tree t;
433 /* What about code that pulls out the temp and uses it elsewhere? I
434 think that such code never uses the TARGET_EXPR as an initializer. If
435 I'm wrong, we'll abort because the temp won't have any RTL. In that
436 case, I guess we'll need to replace references somehow. */
437 if (TREE_CODE (from) == TARGET_EXPR)
438 from = TARGET_EXPR_INITIAL (from);
440 /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
441 inside the TARGET_EXPR. */
442 for (t = from; t; )
444 tree sub = TREE_CODE (t) == COMPOUND_EXPR ? TREE_OPERAND (t, 0) : t;
446 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
447 replace the slot operand with our target.
449 Should we add a target parm to gimplify_expr instead? No, as in this
450 case we want to replace the INIT_EXPR. */
451 if (TREE_CODE (sub) == AGGR_INIT_EXPR
452 || TREE_CODE (sub) == VEC_INIT_EXPR)
454 if (TREE_CODE (sub) == AGGR_INIT_EXPR)
455 AGGR_INIT_EXPR_SLOT (sub) = to;
456 else
457 VEC_INIT_EXPR_SLOT (sub) = to;
458 *expr_p = from;
460 /* The initialization is now a side-effect, so the container can
461 become void. */
462 if (from != sub)
463 TREE_TYPE (from) = void_type_node;
466 if (t == sub)
467 break;
468 else
469 t = TREE_OPERAND (t, 1);
474 /* Gimplify a MUST_NOT_THROW_EXPR. */
476 static enum gimplify_status
477 gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p)
479 tree stmt = *expr_p;
480 tree temp = voidify_wrapper_expr (stmt, NULL);
481 tree body = TREE_OPERAND (stmt, 0);
482 gimple_seq try_ = NULL;
483 gimple_seq catch_ = NULL;
484 gimple mnt;
486 gimplify_and_add (body, &try_);
487 mnt = gimple_build_eh_must_not_throw (terminate_node);
488 gimplify_seq_add_stmt (&catch_, mnt);
489 mnt = gimple_build_try (try_, catch_, GIMPLE_TRY_CATCH);
491 gimplify_seq_add_stmt (pre_p, mnt);
492 if (temp)
494 *expr_p = temp;
495 return GS_OK;
498 *expr_p = NULL;
499 return GS_ALL_DONE;
502 /* Do C++-specific gimplification. Args are as for gimplify_expr. */
505 cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
507 int saved_stmts_are_full_exprs_p = 0;
508 enum tree_code code = TREE_CODE (*expr_p);
509 enum gimplify_status ret;
511 if (STATEMENT_CODE_P (code))
513 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
514 current_stmt_tree ()->stmts_are_full_exprs_p
515 = STMT_IS_FULL_EXPR_P (*expr_p);
518 switch (code)
520 case PTRMEM_CST:
521 *expr_p = cplus_expand_constant (*expr_p);
522 ret = GS_OK;
523 break;
525 case AGGR_INIT_EXPR:
526 simplify_aggr_init_expr (expr_p);
527 ret = GS_OK;
528 break;
530 case VEC_INIT_EXPR:
532 location_t loc = input_location;
533 tree init = VEC_INIT_EXPR_INIT (*expr_p);
534 int from_array = (init && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE);
535 gcc_assert (EXPR_HAS_LOCATION (*expr_p));
536 input_location = EXPR_LOCATION (*expr_p);
537 *expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE,
538 init, VEC_INIT_EXPR_VALUE_INIT (*expr_p),
539 from_array,
540 tf_warning_or_error);
541 ret = GS_OK;
542 input_location = loc;
544 break;
546 case THROW_EXPR:
547 /* FIXME communicate throw type to back end, probably by moving
548 THROW_EXPR into ../tree.def. */
549 *expr_p = TREE_OPERAND (*expr_p, 0);
550 ret = GS_OK;
551 break;
553 case MUST_NOT_THROW_EXPR:
554 ret = gimplify_must_not_throw_expr (expr_p, pre_p);
555 break;
557 /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
558 LHS of an assignment might also be involved in the RHS, as in bug
559 25979. */
560 case INIT_EXPR:
561 cp_gimplify_init_expr (expr_p);
562 if (TREE_CODE (*expr_p) != INIT_EXPR)
563 return GS_OK;
564 /* Otherwise fall through. */
565 case MODIFY_EXPR:
567 /* If the back end isn't clever enough to know that the lhs and rhs
568 types are the same, add an explicit conversion. */
569 tree op0 = TREE_OPERAND (*expr_p, 0);
570 tree op1 = TREE_OPERAND (*expr_p, 1);
572 if (!error_operand_p (op0)
573 && !error_operand_p (op1)
574 && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0))
575 || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1)))
576 && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
577 TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
578 TREE_TYPE (op0), op1);
580 else if ((is_gimple_lvalue (op1) || INDIRECT_REF_P (op1)
581 || (TREE_CODE (op1) == CONSTRUCTOR
582 && CONSTRUCTOR_NELTS (op1) == 0)
583 || (TREE_CODE (op1) == CALL_EXPR
584 && !CALL_EXPR_RETURN_SLOT_OPT (op1)))
585 && is_really_empty_class (TREE_TYPE (op0)))
587 /* Remove any copies of empty classes. We check that the RHS
588 has a simple form so that TARGET_EXPRs and non-empty
589 CONSTRUCTORs get reduced properly, and we leave the return
590 slot optimization alone because it isn't a copy (FIXME so it
591 shouldn't be represented as one).
593 Also drop volatile variables on the RHS to avoid infinite
594 recursion from gimplify_expr trying to load the value. */
595 if (!TREE_SIDE_EFFECTS (op1)
596 || (DECL_P (op1) && TREE_THIS_VOLATILE (op1)))
597 *expr_p = op0;
598 else if (TREE_CODE (op1) == MEM_REF
599 && TREE_THIS_VOLATILE (op1))
601 /* Similarly for volatile MEM_REFs on the RHS. */
602 if (!TREE_SIDE_EFFECTS (TREE_OPERAND (op1, 0)))
603 *expr_p = op0;
604 else
605 *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
606 TREE_OPERAND (op1, 0), op0);
608 else
609 *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
610 op0, op1);
613 ret = GS_OK;
614 break;
616 case EMPTY_CLASS_EXPR:
617 /* We create an empty CONSTRUCTOR with RECORD_TYPE. */
618 *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
619 ret = GS_OK;
620 break;
622 case BASELINK:
623 *expr_p = BASELINK_FUNCTIONS (*expr_p);
624 ret = GS_OK;
625 break;
627 case TRY_BLOCK:
628 genericize_try_block (expr_p);
629 ret = GS_OK;
630 break;
632 case HANDLER:
633 genericize_catch_block (expr_p);
634 ret = GS_OK;
635 break;
637 case EH_SPEC_BLOCK:
638 genericize_eh_spec_block (expr_p);
639 ret = GS_OK;
640 break;
642 case USING_STMT:
643 gcc_unreachable ();
645 case FOR_STMT:
646 gimplify_for_stmt (expr_p, pre_p);
647 ret = GS_OK;
648 break;
650 case WHILE_STMT:
651 gimplify_while_stmt (expr_p, pre_p);
652 ret = GS_OK;
653 break;
655 case DO_STMT:
656 gimplify_do_stmt (expr_p, pre_p);
657 ret = GS_OK;
658 break;
660 case SWITCH_STMT:
661 gimplify_switch_stmt (expr_p, pre_p);
662 ret = GS_OK;
663 break;
665 case OMP_FOR:
666 ret = cp_gimplify_omp_for (expr_p, pre_p);
667 break;
669 case CONTINUE_STMT:
670 gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_CONTINUE, NOT_TAKEN));
671 gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_continue)));
672 *expr_p = NULL_TREE;
673 ret = GS_ALL_DONE;
674 break;
676 case BREAK_STMT:
677 gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_break)));
678 *expr_p = NULL_TREE;
679 ret = GS_ALL_DONE;
680 break;
682 case EXPR_STMT:
683 gimplify_expr_stmt (expr_p);
684 ret = GS_OK;
685 break;
687 case UNARY_PLUS_EXPR:
689 tree arg = TREE_OPERAND (*expr_p, 0);
690 tree type = TREE_TYPE (*expr_p);
691 *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
692 : arg;
693 ret = GS_OK;
695 break;
697 default:
698 ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p);
699 break;
702 /* Restore saved state. */
703 if (STATEMENT_CODE_P (code))
704 current_stmt_tree ()->stmts_are_full_exprs_p
705 = saved_stmts_are_full_exprs_p;
707 return ret;
710 static inline bool
711 is_invisiref_parm (const_tree t)
713 return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
714 && DECL_BY_REFERENCE (t));
717 /* Return true if the uid in both int tree maps are equal. */
720 cxx_int_tree_map_eq (const void *va, const void *vb)
722 const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
723 const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
724 return (a->uid == b->uid);
727 /* Hash a UID in a cxx_int_tree_map. */
729 unsigned int
730 cxx_int_tree_map_hash (const void *item)
732 return ((const struct cxx_int_tree_map *)item)->uid;
735 /* A stable comparison routine for use with splay trees and DECLs. */
737 static int
738 splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
740 tree a = (tree) xa;
741 tree b = (tree) xb;
743 return DECL_UID (a) - DECL_UID (b);
746 /* OpenMP context during genericization. */
748 struct cp_genericize_omp_taskreg
750 bool is_parallel;
751 bool default_shared;
752 struct cp_genericize_omp_taskreg *outer;
753 splay_tree variables;
756 /* Return true if genericization should try to determine if
757 DECL is firstprivate or shared within task regions. */
759 static bool
760 omp_var_to_track (tree decl)
762 tree type = TREE_TYPE (decl);
763 if (is_invisiref_parm (decl))
764 type = TREE_TYPE (type);
765 while (TREE_CODE (type) == ARRAY_TYPE)
766 type = TREE_TYPE (type);
767 if (type == error_mark_node || !CLASS_TYPE_P (type))
768 return false;
769 if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
770 return false;
771 if (cxx_omp_predetermined_sharing (decl) != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
772 return false;
773 return true;
776 /* Note DECL use in OpenMP region OMP_CTX during genericization. */
778 static void
779 omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl)
781 splay_tree_node n = splay_tree_lookup (omp_ctx->variables,
782 (splay_tree_key) decl);
783 if (n == NULL)
785 int flags = OMP_CLAUSE_DEFAULT_SHARED;
786 if (omp_ctx->outer)
787 omp_cxx_notice_variable (omp_ctx->outer, decl);
788 if (!omp_ctx->default_shared)
790 struct cp_genericize_omp_taskreg *octx;
792 for (octx = omp_ctx->outer; octx; octx = octx->outer)
794 n = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
795 if (n && n->value != OMP_CLAUSE_DEFAULT_SHARED)
797 flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
798 break;
800 if (octx->is_parallel)
801 break;
803 if (octx == NULL
804 && (TREE_CODE (decl) == PARM_DECL
805 || (!(TREE_STATIC (decl) || DECL_EXTERNAL (decl))
806 && DECL_CONTEXT (decl) == current_function_decl)))
807 flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
808 if (flags == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
810 /* DECL is implicitly determined firstprivate in
811 the current task construct. Ensure copy ctor and
812 dtor are instantiated, because during gimplification
813 it will be already too late. */
814 tree type = TREE_TYPE (decl);
815 if (is_invisiref_parm (decl))
816 type = TREE_TYPE (type);
817 while (TREE_CODE (type) == ARRAY_TYPE)
818 type = TREE_TYPE (type);
819 get_copy_ctor (type, tf_none);
820 get_dtor (type, tf_none);
823 splay_tree_insert (omp_ctx->variables, (splay_tree_key) decl, flags);
827 /* Genericization context. */
829 struct cp_genericize_data
831 struct pointer_set_t *p_set;
832 VEC (tree, heap) *bind_expr_stack;
833 struct cp_genericize_omp_taskreg *omp_ctx;
836 /* Perform any pre-gimplification lowering of C++ front end trees to
837 GENERIC. */
839 static tree
840 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
842 tree stmt = *stmt_p;
843 struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
844 struct pointer_set_t *p_set = wtd->p_set;
846 /* If in an OpenMP context, note var uses. */
847 if (__builtin_expect (wtd->omp_ctx != NULL, 0)
848 && (TREE_CODE (stmt) == VAR_DECL
849 || TREE_CODE (stmt) == PARM_DECL
850 || TREE_CODE (stmt) == RESULT_DECL)
851 && omp_var_to_track (stmt))
852 omp_cxx_notice_variable (wtd->omp_ctx, stmt);
854 if (is_invisiref_parm (stmt)
855 /* Don't dereference parms in a thunk, pass the references through. */
856 && !(DECL_THUNK_P (current_function_decl)
857 && TREE_CODE (stmt) == PARM_DECL))
859 *stmt_p = convert_from_reference (stmt);
860 *walk_subtrees = 0;
861 return NULL;
864 /* Map block scope extern declarations to visible declarations with the
865 same name and type in outer scopes if any. */
866 if (cp_function_chain->extern_decl_map
867 && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
868 && DECL_EXTERNAL (stmt))
870 struct cxx_int_tree_map *h, in;
871 in.uid = DECL_UID (stmt);
872 h = (struct cxx_int_tree_map *)
873 htab_find_with_hash (cp_function_chain->extern_decl_map,
874 &in, in.uid);
875 if (h)
877 *stmt_p = h->to;
878 *walk_subtrees = 0;
879 return NULL;
883 /* Other than invisiref parms, don't walk the same tree twice. */
884 if (pointer_set_contains (p_set, stmt))
886 *walk_subtrees = 0;
887 return NULL_TREE;
890 if (TREE_CODE (stmt) == ADDR_EXPR
891 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
893 /* If in an OpenMP context, note var uses. */
894 if (__builtin_expect (wtd->omp_ctx != NULL, 0)
895 && omp_var_to_track (TREE_OPERAND (stmt, 0)))
896 omp_cxx_notice_variable (wtd->omp_ctx, TREE_OPERAND (stmt, 0));
897 *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
898 *walk_subtrees = 0;
900 else if (TREE_CODE (stmt) == RETURN_EXPR
901 && TREE_OPERAND (stmt, 0)
902 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
903 /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */
904 *walk_subtrees = 0;
905 else if (TREE_CODE (stmt) == OMP_CLAUSE)
906 switch (OMP_CLAUSE_CODE (stmt))
908 case OMP_CLAUSE_LASTPRIVATE:
909 /* Don't dereference an invisiref in OpenMP clauses. */
910 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
912 *walk_subtrees = 0;
913 if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt))
914 cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt),
915 cp_genericize_r, data, NULL);
917 break;
918 case OMP_CLAUSE_PRIVATE:
919 /* Don't dereference an invisiref in OpenMP clauses. */
920 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
921 *walk_subtrees = 0;
922 else if (wtd->omp_ctx != NULL)
924 /* Private clause doesn't cause any references to the
925 var in outer contexts, avoid calling
926 omp_cxx_notice_variable for it. */
927 struct cp_genericize_omp_taskreg *old = wtd->omp_ctx;
928 wtd->omp_ctx = NULL;
929 cp_walk_tree (&OMP_CLAUSE_DECL (stmt), cp_genericize_r,
930 data, NULL);
931 wtd->omp_ctx = old;
932 *walk_subtrees = 0;
934 break;
935 case OMP_CLAUSE_SHARED:
936 case OMP_CLAUSE_FIRSTPRIVATE:
937 case OMP_CLAUSE_COPYIN:
938 case OMP_CLAUSE_COPYPRIVATE:
939 /* Don't dereference an invisiref in OpenMP clauses. */
940 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
941 *walk_subtrees = 0;
942 break;
943 case OMP_CLAUSE_REDUCTION:
944 gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
945 break;
946 default:
947 break;
949 else if (IS_TYPE_OR_DECL_P (stmt))
950 *walk_subtrees = 0;
952 /* Due to the way voidify_wrapper_expr is written, we don't get a chance
953 to lower this construct before scanning it, so we need to lower these
954 before doing anything else. */
955 else if (TREE_CODE (stmt) == CLEANUP_STMT)
956 *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
957 : TRY_FINALLY_EXPR,
958 void_type_node,
959 CLEANUP_BODY (stmt),
960 CLEANUP_EXPR (stmt));
962 else if (TREE_CODE (stmt) == IF_STMT)
964 genericize_if_stmt (stmt_p);
965 /* *stmt_p has changed, tail recurse to handle it again. */
966 return cp_genericize_r (stmt_p, walk_subtrees, data);
969 /* COND_EXPR might have incompatible types in branches if one or both
970 arms are bitfields. Fix it up now. */
971 else if (TREE_CODE (stmt) == COND_EXPR)
973 tree type_left
974 = (TREE_OPERAND (stmt, 1)
975 ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1))
976 : NULL_TREE);
977 tree type_right
978 = (TREE_OPERAND (stmt, 2)
979 ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2))
980 : NULL_TREE);
981 if (type_left
982 && !useless_type_conversion_p (TREE_TYPE (stmt),
983 TREE_TYPE (TREE_OPERAND (stmt, 1))))
985 TREE_OPERAND (stmt, 1)
986 = fold_convert (type_left, TREE_OPERAND (stmt, 1));
987 gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
988 type_left));
990 if (type_right
991 && !useless_type_conversion_p (TREE_TYPE (stmt),
992 TREE_TYPE (TREE_OPERAND (stmt, 2))))
994 TREE_OPERAND (stmt, 2)
995 = fold_convert (type_right, TREE_OPERAND (stmt, 2));
996 gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
997 type_right));
1001 else if (TREE_CODE (stmt) == BIND_EXPR)
1003 if (__builtin_expect (wtd->omp_ctx != NULL, 0))
1005 tree decl;
1006 for (decl = BIND_EXPR_VARS (stmt); decl; decl = DECL_CHAIN (decl))
1007 if (TREE_CODE (decl) == VAR_DECL
1008 && !DECL_EXTERNAL (decl)
1009 && omp_var_to_track (decl))
1011 splay_tree_node n
1012 = splay_tree_lookup (wtd->omp_ctx->variables,
1013 (splay_tree_key) decl);
1014 if (n == NULL)
1015 splay_tree_insert (wtd->omp_ctx->variables,
1016 (splay_tree_key) decl,
1017 TREE_STATIC (decl)
1018 ? OMP_CLAUSE_DEFAULT_SHARED
1019 : OMP_CLAUSE_DEFAULT_PRIVATE);
1022 VEC_safe_push (tree, heap, wtd->bind_expr_stack, stmt);
1023 cp_walk_tree (&BIND_EXPR_BODY (stmt),
1024 cp_genericize_r, data, NULL);
1025 VEC_pop (tree, wtd->bind_expr_stack);
1028 else if (TREE_CODE (stmt) == USING_STMT)
1030 tree block = NULL_TREE;
1032 /* Get the innermost inclosing GIMPLE_BIND that has a non NULL
1033 BLOCK, and append an IMPORTED_DECL to its
1034 BLOCK_VARS chained list. */
1035 if (wtd->bind_expr_stack)
1037 int i;
1038 for (i = VEC_length (tree, wtd->bind_expr_stack) - 1; i >= 0; i--)
1039 if ((block = BIND_EXPR_BLOCK (VEC_index (tree,
1040 wtd->bind_expr_stack, i))))
1041 break;
1043 if (block)
1045 tree using_directive;
1046 gcc_assert (TREE_OPERAND (stmt, 0));
1048 using_directive = make_node (IMPORTED_DECL);
1049 TREE_TYPE (using_directive) = void_type_node;
1051 IMPORTED_DECL_ASSOCIATED_DECL (using_directive)
1052 = TREE_OPERAND (stmt, 0);
1053 DECL_CHAIN (using_directive) = BLOCK_VARS (block);
1054 BLOCK_VARS (block) = using_directive;
1056 /* The USING_STMT won't appear in GENERIC. */
1057 *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
1058 *walk_subtrees = 0;
1061 else if (TREE_CODE (stmt) == DECL_EXPR
1062 && TREE_CODE (DECL_EXPR_DECL (stmt)) == USING_DECL)
1064 /* Using decls inside DECL_EXPRs are just dropped on the floor. */
1065 *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
1066 *walk_subtrees = 0;
1068 else if (TREE_CODE (stmt) == OMP_PARALLEL || TREE_CODE (stmt) == OMP_TASK)
1070 struct cp_genericize_omp_taskreg omp_ctx;
1071 tree c, decl;
1072 splay_tree_node n;
1074 *walk_subtrees = 0;
1075 cp_walk_tree (&OMP_CLAUSES (stmt), cp_genericize_r, data, NULL);
1076 omp_ctx.is_parallel = TREE_CODE (stmt) == OMP_PARALLEL;
1077 omp_ctx.default_shared = omp_ctx.is_parallel;
1078 omp_ctx.outer = wtd->omp_ctx;
1079 omp_ctx.variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
1080 wtd->omp_ctx = &omp_ctx;
1081 for (c = OMP_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
1082 switch (OMP_CLAUSE_CODE (c))
1084 case OMP_CLAUSE_SHARED:
1085 case OMP_CLAUSE_PRIVATE:
1086 case OMP_CLAUSE_FIRSTPRIVATE:
1087 case OMP_CLAUSE_LASTPRIVATE:
1088 decl = OMP_CLAUSE_DECL (c);
1089 if (decl == error_mark_node || !omp_var_to_track (decl))
1090 break;
1091 n = splay_tree_lookup (omp_ctx.variables, (splay_tree_key) decl);
1092 if (n != NULL)
1093 break;
1094 splay_tree_insert (omp_ctx.variables, (splay_tree_key) decl,
1095 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1096 ? OMP_CLAUSE_DEFAULT_SHARED
1097 : OMP_CLAUSE_DEFAULT_PRIVATE);
1098 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE
1099 && omp_ctx.outer)
1100 omp_cxx_notice_variable (omp_ctx.outer, decl);
1101 break;
1102 case OMP_CLAUSE_DEFAULT:
1103 if (OMP_CLAUSE_DEFAULT_KIND (c) == OMP_CLAUSE_DEFAULT_SHARED)
1104 omp_ctx.default_shared = true;
1105 default:
1106 break;
1108 cp_walk_tree (&OMP_BODY (stmt), cp_genericize_r, data, NULL);
1109 wtd->omp_ctx = omp_ctx.outer;
1110 splay_tree_delete (omp_ctx.variables);
1113 pointer_set_insert (p_set, *stmt_p);
1115 return NULL;
1118 void
1119 cp_genericize (tree fndecl)
1121 tree t;
1122 struct cp_genericize_data wtd;
1124 /* Fix up the types of parms passed by invisible reference. */
1125 for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t))
1126 if (TREE_ADDRESSABLE (TREE_TYPE (t)))
1128 /* If a function's arguments are copied to create a thunk,
1129 then DECL_BY_REFERENCE will be set -- but the type of the
1130 argument will be a pointer type, so we will never get
1131 here. */
1132 gcc_assert (!DECL_BY_REFERENCE (t));
1133 gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
1134 TREE_TYPE (t) = DECL_ARG_TYPE (t);
1135 DECL_BY_REFERENCE (t) = 1;
1136 TREE_ADDRESSABLE (t) = 0;
1137 relayout_decl (t);
1140 /* Do the same for the return value. */
1141 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
1143 t = DECL_RESULT (fndecl);
1144 TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
1145 DECL_BY_REFERENCE (t) = 1;
1146 TREE_ADDRESSABLE (t) = 0;
1147 relayout_decl (t);
1148 if (DECL_NAME (t))
1150 /* Adjust DECL_VALUE_EXPR of the original var. */
1151 tree outer = outer_curly_brace_block (current_function_decl);
1152 tree var;
1154 if (outer)
1155 for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
1156 if (DECL_NAME (t) == DECL_NAME (var)
1157 && DECL_HAS_VALUE_EXPR_P (var)
1158 && DECL_VALUE_EXPR (var) == t)
1160 tree val = convert_from_reference (t);
1161 SET_DECL_VALUE_EXPR (var, val);
1162 break;
1167 /* If we're a clone, the body is already GIMPLE. */
1168 if (DECL_CLONED_FUNCTION_P (fndecl))
1169 return;
1171 /* We do want to see every occurrence of the parms, so we can't just use
1172 walk_tree's hash functionality. */
1173 wtd.p_set = pointer_set_create ();
1174 wtd.bind_expr_stack = NULL;
1175 wtd.omp_ctx = NULL;
1176 cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, &wtd, NULL);
1177 pointer_set_destroy (wtd.p_set);
1178 VEC_free (tree, heap, wtd.bind_expr_stack);
1180 /* Do everything else. */
1181 c_genericize (fndecl);
1183 gcc_assert (bc_label[bc_break] == NULL);
1184 gcc_assert (bc_label[bc_continue] == NULL);
1187 /* Build code to apply FN to each member of ARG1 and ARG2. FN may be
1188 NULL if there is in fact nothing to do. ARG2 may be null if FN
1189 actually only takes one argument. */
1191 static tree
1192 cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
1194 tree defparm, parm, t;
1195 int i = 0;
1196 int nargs;
1197 tree *argarray;
1199 if (fn == NULL)
1200 return NULL;
1202 nargs = list_length (DECL_ARGUMENTS (fn));
1203 argarray = XALLOCAVEC (tree, nargs);
1205 defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
1206 if (arg2)
1207 defparm = TREE_CHAIN (defparm);
1209 if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
1211 tree inner_type = TREE_TYPE (arg1);
1212 tree start1, end1, p1;
1213 tree start2 = NULL, p2 = NULL;
1214 tree ret = NULL, lab;
1216 start1 = arg1;
1217 start2 = arg2;
1220 inner_type = TREE_TYPE (inner_type);
1221 start1 = build4 (ARRAY_REF, inner_type, start1,
1222 size_zero_node, NULL, NULL);
1223 if (arg2)
1224 start2 = build4 (ARRAY_REF, inner_type, start2,
1225 size_zero_node, NULL, NULL);
1227 while (TREE_CODE (inner_type) == ARRAY_TYPE);
1228 start1 = build_fold_addr_expr_loc (input_location, start1);
1229 if (arg2)
1230 start2 = build_fold_addr_expr_loc (input_location, start2);
1232 end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
1233 end1 = fold_build_pointer_plus (start1, end1);
1235 p1 = create_tmp_var (TREE_TYPE (start1), NULL);
1236 t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, start1);
1237 append_to_statement_list (t, &ret);
1239 if (arg2)
1241 p2 = create_tmp_var (TREE_TYPE (start2), NULL);
1242 t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, start2);
1243 append_to_statement_list (t, &ret);
1246 lab = create_artificial_label (input_location);
1247 t = build1 (LABEL_EXPR, void_type_node, lab);
1248 append_to_statement_list (t, &ret);
1250 argarray[i++] = p1;
1251 if (arg2)
1252 argarray[i++] = p2;
1253 /* Handle default arguments. */
1254 for (parm = defparm; parm && parm != void_list_node;
1255 parm = TREE_CHAIN (parm), i++)
1256 argarray[i] = convert_default_arg (TREE_VALUE (parm),
1257 TREE_PURPOSE (parm), fn, i);
1258 t = build_call_a (fn, i, argarray);
1259 t = fold_convert (void_type_node, t);
1260 t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
1261 append_to_statement_list (t, &ret);
1263 t = fold_build_pointer_plus (p1, TYPE_SIZE_UNIT (inner_type));
1264 t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, t);
1265 append_to_statement_list (t, &ret);
1267 if (arg2)
1269 t = fold_build_pointer_plus (p2, TYPE_SIZE_UNIT (inner_type));
1270 t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, t);
1271 append_to_statement_list (t, &ret);
1274 t = build2 (NE_EXPR, boolean_type_node, p1, end1);
1275 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
1276 append_to_statement_list (t, &ret);
1278 return ret;
1280 else
1282 argarray[i++] = build_fold_addr_expr_loc (input_location, arg1);
1283 if (arg2)
1284 argarray[i++] = build_fold_addr_expr_loc (input_location, arg2);
1285 /* Handle default arguments. */
1286 for (parm = defparm; parm && parm != void_list_node;
1287 parm = TREE_CHAIN (parm), i++)
1288 argarray[i] = convert_default_arg (TREE_VALUE (parm),
1289 TREE_PURPOSE (parm),
1290 fn, i);
1291 t = build_call_a (fn, i, argarray);
1292 t = fold_convert (void_type_node, t);
1293 return fold_build_cleanup_point_expr (TREE_TYPE (t), t);
1297 /* Return code to initialize DECL with its default constructor, or
1298 NULL if there's nothing to do. */
1300 tree
1301 cxx_omp_clause_default_ctor (tree clause, tree decl,
1302 tree outer ATTRIBUTE_UNUSED)
1304 tree info = CP_OMP_CLAUSE_INFO (clause);
1305 tree ret = NULL;
1307 if (info)
1308 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
1310 return ret;
1313 /* Return code to initialize DST with a copy constructor from SRC. */
1315 tree
1316 cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
1318 tree info = CP_OMP_CLAUSE_INFO (clause);
1319 tree ret = NULL;
1321 if (info)
1322 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
1323 if (ret == NULL)
1324 ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
1326 return ret;
1329 /* Similarly, except use an assignment operator instead. */
1331 tree
1332 cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
1334 tree info = CP_OMP_CLAUSE_INFO (clause);
1335 tree ret = NULL;
1337 if (info)
1338 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
1339 if (ret == NULL)
1340 ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
1342 return ret;
1345 /* Return code to destroy DECL. */
1347 tree
1348 cxx_omp_clause_dtor (tree clause, tree decl)
1350 tree info = CP_OMP_CLAUSE_INFO (clause);
1351 tree ret = NULL;
1353 if (info)
1354 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
1356 return ret;
1359 /* True if OpenMP should privatize what this DECL points to rather
1360 than the DECL itself. */
1362 bool
1363 cxx_omp_privatize_by_reference (const_tree decl)
1365 return is_invisiref_parm (decl);
1368 /* Return true if DECL is const qualified var having no mutable member. */
1369 bool
1370 cxx_omp_const_qual_no_mutable (tree decl)
1372 tree type = TREE_TYPE (decl);
1373 if (TREE_CODE (type) == REFERENCE_TYPE)
1375 if (!is_invisiref_parm (decl))
1376 return false;
1377 type = TREE_TYPE (type);
1379 if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl))
1381 /* NVR doesn't preserve const qualification of the
1382 variable's type. */
1383 tree outer = outer_curly_brace_block (current_function_decl);
1384 tree var;
1386 if (outer)
1387 for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
1388 if (DECL_NAME (decl) == DECL_NAME (var)
1389 && (TYPE_MAIN_VARIANT (type)
1390 == TYPE_MAIN_VARIANT (TREE_TYPE (var))))
1392 if (TYPE_READONLY (TREE_TYPE (var)))
1393 type = TREE_TYPE (var);
1394 break;
1399 if (type == error_mark_node)
1400 return false;
1402 /* Variables with const-qualified type having no mutable member
1403 are predetermined shared. */
1404 if (TYPE_READONLY (type) && !cp_has_mutable_p (type))
1405 return true;
1407 return false;
1410 /* True if OpenMP sharing attribute of DECL is predetermined. */
1412 enum omp_clause_default_kind
1413 cxx_omp_predetermined_sharing (tree decl)
1415 /* Static data members are predetermined shared. */
1416 if (TREE_STATIC (decl))
1418 tree ctx = CP_DECL_CONTEXT (decl);
1419 if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
1420 return OMP_CLAUSE_DEFAULT_SHARED;
1423 /* Const qualified vars having no mutable member are predetermined
1424 shared. */
1425 if (cxx_omp_const_qual_no_mutable (decl))
1426 return OMP_CLAUSE_DEFAULT_SHARED;
1428 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
1431 /* Finalize an implicitly determined clause. */
1433 void
1434 cxx_omp_finish_clause (tree c)
1436 tree decl, inner_type;
1437 bool make_shared = false;
1439 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
1440 return;
1442 decl = OMP_CLAUSE_DECL (c);
1443 decl = require_complete_type (decl);
1444 inner_type = TREE_TYPE (decl);
1445 if (decl == error_mark_node)
1446 make_shared = true;
1447 else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
1449 if (is_invisiref_parm (decl))
1450 inner_type = TREE_TYPE (inner_type);
1451 else
1453 error ("%qE implicitly determined as %<firstprivate%> has reference type",
1454 decl);
1455 make_shared = true;
1459 /* We're interested in the base element, not arrays. */
1460 while (TREE_CODE (inner_type) == ARRAY_TYPE)
1461 inner_type = TREE_TYPE (inner_type);
1463 /* Check for special function availability by building a call to one.
1464 Save the results, because later we won't be in the right context
1465 for making these queries. */
1466 if (!make_shared
1467 && CLASS_TYPE_P (inner_type)
1468 && cxx_omp_create_clause_info (c, inner_type, false, true, false))
1469 make_shared = true;
1471 if (make_shared)
1472 OMP_CLAUSE_CODE (c) = OMP_CLAUSE_SHARED;