* config/darwin.c (darwin_assemble_visibility): Treat
[official-gcc.git] / gcc / cp / cp-gimplify.c
blobdd2ef067c8fe9e6d88304bd2a111fd970248b6c0
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 /* Forward declarations. */
39 static tree cp_genericize_r (tree *, int *, void *);
40 static void cp_genericize_tree (tree*);
42 /* Local declarations. */
44 enum bc_t { bc_break = 0, bc_continue = 1 };
46 /* Stack of labels which are targets for "break" or "continue",
47 linked through TREE_CHAIN. */
48 static tree bc_label[2];
50 /* Begin a scope which can be exited by a break or continue statement. BC
51 indicates which.
53 Just creates a label with location LOCATION and pushes it into the current
54 context. */
56 static tree
57 begin_bc_block (enum bc_t bc, location_t location)
59 tree label = create_artificial_label (location);
60 DECL_CHAIN (label) = bc_label[bc];
61 bc_label[bc] = label;
62 return label;
65 /* Finish a scope which can be exited by a break or continue statement.
66 LABEL was returned from the most recent call to begin_bc_block. BLOCK is
67 an expression for the contents of the scope.
69 If we saw a break (or continue) in the scope, append a LABEL_EXPR to
70 BLOCK. Otherwise, just forget the label. */
72 static void
73 finish_bc_block (tree *block, enum bc_t bc, tree label)
75 gcc_assert (label == bc_label[bc]);
77 if (TREE_USED (label))
78 append_to_statement_list (build1 (LABEL_EXPR, void_type_node, label),
79 block);
81 bc_label[bc] = DECL_CHAIN (label);
82 DECL_CHAIN (label) = NULL_TREE;
85 /* Get the LABEL_EXPR to represent a break or continue statement
86 in the current block scope. BC indicates which. */
88 static tree
89 get_bc_label (enum bc_t bc)
91 tree label = bc_label[bc];
93 /* Mark the label used for finish_bc_block. */
94 TREE_USED (label) = 1;
95 return label;
98 /* Genericize a TRY_BLOCK. */
100 static void
101 genericize_try_block (tree *stmt_p)
103 tree body = TRY_STMTS (*stmt_p);
104 tree cleanup = TRY_HANDLERS (*stmt_p);
106 *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
109 /* Genericize a HANDLER by converting to a CATCH_EXPR. */
111 static void
112 genericize_catch_block (tree *stmt_p)
114 tree type = HANDLER_TYPE (*stmt_p);
115 tree body = HANDLER_BODY (*stmt_p);
117 /* FIXME should the caught type go in TREE_TYPE? */
118 *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
121 /* A terser interface for building a representation of an exception
122 specification. */
124 static tree
125 build_gimple_eh_filter_tree (tree body, tree allowed, tree failure)
127 tree t;
129 /* FIXME should the allowed types go in TREE_TYPE? */
130 t = build2 (EH_FILTER_EXPR, void_type_node, allowed, NULL_TREE);
131 append_to_statement_list (failure, &EH_FILTER_FAILURE (t));
133 t = build2 (TRY_CATCH_EXPR, void_type_node, NULL_TREE, t);
134 append_to_statement_list (body, &TREE_OPERAND (t, 0));
136 return t;
139 /* Genericize an EH_SPEC_BLOCK by converting it to a
140 TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
142 static void
143 genericize_eh_spec_block (tree *stmt_p)
145 tree body = EH_SPEC_STMTS (*stmt_p);
146 tree allowed = EH_SPEC_RAISES (*stmt_p);
147 tree failure = build_call_n (call_unexpected_node, 1, build_exc_ptr ());
149 *stmt_p = build_gimple_eh_filter_tree (body, allowed, failure);
150 TREE_NO_WARNING (*stmt_p) = true;
151 TREE_NO_WARNING (TREE_OPERAND (*stmt_p, 1)) = true;
154 /* Genericize an IF_STMT by turning it into a COND_EXPR. */
156 static void
157 genericize_if_stmt (tree *stmt_p)
159 tree stmt, cond, then_, else_;
160 location_t locus = EXPR_LOCATION (*stmt_p);
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 (locus);
169 if (!else_)
170 else_ = build_empty_stmt (locus);
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 if (CAN_HAVE_LOCATION_P (stmt) && !EXPR_HAS_LOCATION (stmt))
179 SET_EXPR_LOCATION (stmt, locus);
180 *stmt_p = stmt;
183 /* Build a generic representation of one of the C loop forms. COND is the
184 loop condition or NULL_TREE. BODY is the (possibly compound) statement
185 controlled by the loop. INCR is the increment expression of a for-loop,
186 or NULL_TREE. COND_IS_FIRST indicates whether the condition is
187 evaluated before the loop body as in while and for loops, or after the
188 loop body as in do-while loops. */
190 static void
191 genericize_cp_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
192 tree incr, bool cond_is_first, int *walk_subtrees,
193 void *data)
195 tree blab, clab;
196 tree entry = NULL, exit = NULL, t;
197 tree stmt_list = NULL;
199 blab = begin_bc_block (bc_break, start_locus);
200 clab = begin_bc_block (bc_continue, start_locus);
202 if (incr && EXPR_P (incr))
203 SET_EXPR_LOCATION (incr, start_locus);
205 cp_walk_tree (&cond, cp_genericize_r, data, NULL);
206 cp_walk_tree (&body, cp_genericize_r, data, NULL);
207 cp_walk_tree (&incr, cp_genericize_r, data, NULL);
208 *walk_subtrees = 0;
210 /* If condition is zero don't generate a loop construct. */
211 if (cond && integer_zerop (cond))
213 if (cond_is_first)
215 t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
216 get_bc_label (bc_break));
217 append_to_statement_list (t, &stmt_list);
220 else
222 /* Expand to gotos, just like c_finish_loop. TODO: Use LOOP_EXPR. */
223 tree top = build1 (LABEL_EXPR, void_type_node,
224 create_artificial_label (start_locus));
226 /* If we have an exit condition, then we build an IF with gotos either
227 out of the loop, or to the top of it. If there's no exit condition,
228 then we just build a jump back to the top. */
229 exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
231 if (cond && !integer_nonzerop (cond))
233 /* Canonicalize the loop condition to the end. This means
234 generating a branch to the loop condition. Reuse the
235 continue label, if possible. */
236 if (cond_is_first)
238 if (incr)
240 entry = build1 (LABEL_EXPR, void_type_node,
241 create_artificial_label (start_locus));
242 t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
243 LABEL_EXPR_LABEL (entry));
245 else
246 t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
247 get_bc_label (bc_continue));
248 append_to_statement_list (t, &stmt_list);
251 t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
252 exit = fold_build3_loc (start_locus,
253 COND_EXPR, void_type_node, cond, exit, t);
256 append_to_statement_list (top, &stmt_list);
259 append_to_statement_list (body, &stmt_list);
260 finish_bc_block (&stmt_list, bc_continue, clab);
261 append_to_statement_list (incr, &stmt_list);
262 append_to_statement_list (entry, &stmt_list);
263 append_to_statement_list (exit, &stmt_list);
264 finish_bc_block (&stmt_list, bc_break, blab);
266 if (stmt_list == NULL_TREE)
267 stmt_list = build1 (NOP_EXPR, void_type_node, integer_zero_node);
269 *stmt_p = stmt_list;
272 /* Genericize a FOR_STMT node *STMT_P. */
274 static void
275 genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data)
277 tree stmt = *stmt_p;
278 tree expr = NULL;
279 tree loop;
280 tree init = FOR_INIT_STMT (stmt);
282 if (init)
284 cp_walk_tree (&init, cp_genericize_r, data, NULL);
285 append_to_statement_list (init, &expr);
288 genericize_cp_loop (&loop, EXPR_LOCATION (stmt), FOR_COND (stmt),
289 FOR_BODY (stmt), FOR_EXPR (stmt), 1, walk_subtrees, data);
290 append_to_statement_list (loop, &expr);
291 *stmt_p = expr;
294 /* Genericize a WHILE_STMT node *STMT_P. */
296 static void
297 genericize_while_stmt (tree *stmt_p, int *walk_subtrees, void *data)
299 tree stmt = *stmt_p;
300 genericize_cp_loop (stmt_p, EXPR_LOCATION (stmt), WHILE_COND (stmt),
301 WHILE_BODY (stmt), NULL_TREE, 1, walk_subtrees, data);
304 /* Genericize a DO_STMT node *STMT_P. */
306 static void
307 genericize_do_stmt (tree *stmt_p, int *walk_subtrees, void *data)
309 tree stmt = *stmt_p;
310 genericize_cp_loop (stmt_p, EXPR_LOCATION (stmt), DO_COND (stmt),
311 DO_BODY (stmt), NULL_TREE, 0, walk_subtrees, data);
314 /* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR. */
316 static void
317 genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data)
319 tree stmt = *stmt_p;
320 tree break_block, body, cond, type;
321 location_t stmt_locus = EXPR_LOCATION (stmt);
323 break_block = begin_bc_block (bc_break, stmt_locus);
325 body = SWITCH_STMT_BODY (stmt);
326 if (!body)
327 body = build_empty_stmt (stmt_locus);
328 cond = SWITCH_STMT_COND (stmt);
329 type = SWITCH_STMT_TYPE (stmt);
331 cp_walk_tree (&body, cp_genericize_r, data, NULL);
332 cp_walk_tree (&cond, cp_genericize_r, data, NULL);
333 cp_walk_tree (&type, cp_genericize_r, data, NULL);
334 *walk_subtrees = 0;
336 *stmt_p = build3_loc (stmt_locus, SWITCH_EXPR, type, cond, body, NULL_TREE);
337 finish_bc_block (stmt_p, bc_break, break_block);
340 /* Genericize a CONTINUE_STMT node *STMT_P. */
342 static void
343 genericize_continue_stmt (tree *stmt_p)
345 tree stmt_list = NULL;
346 tree pred = build_predict_expr (PRED_CONTINUE, NOT_TAKEN);
347 tree label = get_bc_label (bc_continue);
348 location_t location = EXPR_LOCATION (*stmt_p);
349 tree jump = build1_loc (location, GOTO_EXPR, void_type_node, label);
350 append_to_statement_list (pred, &stmt_list);
351 append_to_statement_list (jump, &stmt_list);
352 *stmt_p = stmt_list;
355 /* Genericize a BREAK_STMT node *STMT_P. */
357 static void
358 genericize_break_stmt (tree *stmt_p)
360 tree label = get_bc_label (bc_break);
361 location_t location = EXPR_LOCATION (*stmt_p);
362 *stmt_p = build1_loc (location, GOTO_EXPR, void_type_node, label);
365 /* Genericize a OMP_FOR node *STMT_P. */
367 static void
368 genericize_omp_for_stmt (tree *stmt_p, int *walk_subtrees, void *data)
370 tree stmt = *stmt_p;
371 location_t locus = EXPR_LOCATION (stmt);
372 tree clab = begin_bc_block (bc_continue, locus);
374 cp_walk_tree (&OMP_FOR_BODY (stmt), cp_genericize_r, data, NULL);
375 cp_walk_tree (&OMP_FOR_CLAUSES (stmt), cp_genericize_r, data, NULL);
376 cp_walk_tree (&OMP_FOR_INIT (stmt), cp_genericize_r, data, NULL);
377 cp_walk_tree (&OMP_FOR_COND (stmt), cp_genericize_r, data, NULL);
378 cp_walk_tree (&OMP_FOR_INCR (stmt), cp_genericize_r, data, NULL);
379 cp_walk_tree (&OMP_FOR_PRE_BODY (stmt), cp_genericize_r, data, NULL);
380 *walk_subtrees = 0;
382 finish_bc_block (&OMP_FOR_BODY (stmt), bc_continue, clab);
385 /* Hook into the middle of gimplifying an OMP_FOR node. */
387 static enum gimplify_status
388 cp_gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
390 tree for_stmt = *expr_p;
391 gimple_seq seq = NULL;
393 /* Protect ourselves from recursion. */
394 if (OMP_FOR_GIMPLIFYING_P (for_stmt))
395 return GS_UNHANDLED;
396 OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
398 gimplify_and_add (for_stmt, &seq);
399 gimple_seq_add_seq (pre_p, seq);
401 OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
403 return GS_ALL_DONE;
406 /* Gimplify an EXPR_STMT node. */
408 static void
409 gimplify_expr_stmt (tree *stmt_p)
411 tree stmt = EXPR_STMT_EXPR (*stmt_p);
413 if (stmt == error_mark_node)
414 stmt = NULL;
416 /* Gimplification of a statement expression will nullify the
417 statement if all its side effects are moved to *PRE_P and *POST_P.
419 In this case we will not want to emit the gimplified statement.
420 However, we may still want to emit a warning, so we do that before
421 gimplification. */
422 if (stmt && warn_unused_value)
424 if (!TREE_SIDE_EFFECTS (stmt))
426 if (!IS_EMPTY_STMT (stmt)
427 && !VOID_TYPE_P (TREE_TYPE (stmt))
428 && !TREE_NO_WARNING (stmt))
429 warning (OPT_Wunused_value, "statement with no effect");
431 else
432 warn_if_unused_value (stmt, input_location);
435 if (stmt == NULL_TREE)
436 stmt = alloc_stmt_list ();
438 *stmt_p = stmt;
441 /* Gimplify initialization from an AGGR_INIT_EXPR. */
443 static void
444 cp_gimplify_init_expr (tree *expr_p)
446 tree from = TREE_OPERAND (*expr_p, 1);
447 tree to = TREE_OPERAND (*expr_p, 0);
448 tree t;
450 /* What about code that pulls out the temp and uses it elsewhere? I
451 think that such code never uses the TARGET_EXPR as an initializer. If
452 I'm wrong, we'll abort because the temp won't have any RTL. In that
453 case, I guess we'll need to replace references somehow. */
454 if (TREE_CODE (from) == TARGET_EXPR)
455 from = TARGET_EXPR_INITIAL (from);
457 /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
458 inside the TARGET_EXPR. */
459 for (t = from; t; )
461 tree sub = TREE_CODE (t) == COMPOUND_EXPR ? TREE_OPERAND (t, 0) : t;
463 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
464 replace the slot operand with our target.
466 Should we add a target parm to gimplify_expr instead? No, as in this
467 case we want to replace the INIT_EXPR. */
468 if (TREE_CODE (sub) == AGGR_INIT_EXPR
469 || TREE_CODE (sub) == VEC_INIT_EXPR)
471 if (TREE_CODE (sub) == AGGR_INIT_EXPR)
472 AGGR_INIT_EXPR_SLOT (sub) = to;
473 else
474 VEC_INIT_EXPR_SLOT (sub) = to;
475 *expr_p = from;
477 /* The initialization is now a side-effect, so the container can
478 become void. */
479 if (from != sub)
480 TREE_TYPE (from) = void_type_node;
483 if (t == sub)
484 break;
485 else
486 t = TREE_OPERAND (t, 1);
491 /* Gimplify a MUST_NOT_THROW_EXPR. */
493 static enum gimplify_status
494 gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p)
496 tree stmt = *expr_p;
497 tree temp = voidify_wrapper_expr (stmt, NULL);
498 tree body = TREE_OPERAND (stmt, 0);
499 gimple_seq try_ = NULL;
500 gimple_seq catch_ = NULL;
501 gimple mnt;
503 gimplify_and_add (body, &try_);
504 mnt = gimple_build_eh_must_not_throw (terminate_node);
505 gimple_seq_add_stmt_without_update (&catch_, mnt);
506 mnt = gimple_build_try (try_, catch_, GIMPLE_TRY_CATCH);
508 gimple_seq_add_stmt_without_update (pre_p, mnt);
509 if (temp)
511 *expr_p = temp;
512 return GS_OK;
515 *expr_p = NULL;
516 return GS_ALL_DONE;
519 /* Do C++-specific gimplification. Args are as for gimplify_expr. */
522 cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
524 int saved_stmts_are_full_exprs_p = 0;
525 enum tree_code code = TREE_CODE (*expr_p);
526 enum gimplify_status ret;
528 if (STATEMENT_CODE_P (code))
530 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
531 current_stmt_tree ()->stmts_are_full_exprs_p
532 = STMT_IS_FULL_EXPR_P (*expr_p);
535 switch (code)
537 case PTRMEM_CST:
538 *expr_p = cplus_expand_constant (*expr_p);
539 ret = GS_OK;
540 break;
542 case AGGR_INIT_EXPR:
543 simplify_aggr_init_expr (expr_p);
544 ret = GS_OK;
545 break;
547 case VEC_INIT_EXPR:
549 location_t loc = input_location;
550 tree init = VEC_INIT_EXPR_INIT (*expr_p);
551 int from_array = (init && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE);
552 gcc_assert (EXPR_HAS_LOCATION (*expr_p));
553 input_location = EXPR_LOCATION (*expr_p);
554 *expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE,
555 init, VEC_INIT_EXPR_VALUE_INIT (*expr_p),
556 from_array,
557 tf_warning_or_error);
558 cp_genericize_tree (expr_p);
559 ret = GS_OK;
560 input_location = loc;
562 break;
564 case THROW_EXPR:
565 /* FIXME communicate throw type to back end, probably by moving
566 THROW_EXPR into ../tree.def. */
567 *expr_p = TREE_OPERAND (*expr_p, 0);
568 ret = GS_OK;
569 break;
571 case MUST_NOT_THROW_EXPR:
572 ret = gimplify_must_not_throw_expr (expr_p, pre_p);
573 break;
575 /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
576 LHS of an assignment might also be involved in the RHS, as in bug
577 25979. */
578 case INIT_EXPR:
579 cp_gimplify_init_expr (expr_p);
580 if (TREE_CODE (*expr_p) != INIT_EXPR)
581 return GS_OK;
582 /* Otherwise fall through. */
583 case MODIFY_EXPR:
585 /* If the back end isn't clever enough to know that the lhs and rhs
586 types are the same, add an explicit conversion. */
587 tree op0 = TREE_OPERAND (*expr_p, 0);
588 tree op1 = TREE_OPERAND (*expr_p, 1);
590 if (!error_operand_p (op0)
591 && !error_operand_p (op1)
592 && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0))
593 || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1)))
594 && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
595 TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
596 TREE_TYPE (op0), op1);
598 else if ((is_gimple_lvalue (op1) || INDIRECT_REF_P (op1)
599 || (TREE_CODE (op1) == CONSTRUCTOR
600 && CONSTRUCTOR_NELTS (op1) == 0
601 && !TREE_CLOBBER_P (op1))
602 || (TREE_CODE (op1) == CALL_EXPR
603 && !CALL_EXPR_RETURN_SLOT_OPT (op1)))
604 && is_really_empty_class (TREE_TYPE (op0)))
606 /* Remove any copies of empty classes. We check that the RHS
607 has a simple form so that TARGET_EXPRs and non-empty
608 CONSTRUCTORs get reduced properly, and we leave the return
609 slot optimization alone because it isn't a copy (FIXME so it
610 shouldn't be represented as one).
612 Also drop volatile variables on the RHS to avoid infinite
613 recursion from gimplify_expr trying to load the value. */
614 if (!TREE_SIDE_EFFECTS (op1)
615 || (DECL_P (op1) && TREE_THIS_VOLATILE (op1)))
616 *expr_p = op0;
617 else if (TREE_CODE (op1) == MEM_REF
618 && TREE_THIS_VOLATILE (op1))
620 /* Similarly for volatile MEM_REFs on the RHS. */
621 if (!TREE_SIDE_EFFECTS (TREE_OPERAND (op1, 0)))
622 *expr_p = op0;
623 else
624 *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
625 TREE_OPERAND (op1, 0), op0);
627 else
628 *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
629 op0, op1);
632 ret = GS_OK;
633 break;
635 case EMPTY_CLASS_EXPR:
636 /* We create an empty CONSTRUCTOR with RECORD_TYPE. */
637 *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
638 ret = GS_OK;
639 break;
641 case BASELINK:
642 *expr_p = BASELINK_FUNCTIONS (*expr_p);
643 ret = GS_OK;
644 break;
646 case TRY_BLOCK:
647 genericize_try_block (expr_p);
648 ret = GS_OK;
649 break;
651 case HANDLER:
652 genericize_catch_block (expr_p);
653 ret = GS_OK;
654 break;
656 case EH_SPEC_BLOCK:
657 genericize_eh_spec_block (expr_p);
658 ret = GS_OK;
659 break;
661 case USING_STMT:
662 gcc_unreachable ();
664 case FOR_STMT:
665 case WHILE_STMT:
666 case DO_STMT:
667 case SWITCH_STMT:
668 case CONTINUE_STMT:
669 case BREAK_STMT:
670 gcc_unreachable ();
672 case OMP_FOR:
673 ret = cp_gimplify_omp_for (expr_p, pre_p);
674 break;
676 case EXPR_STMT:
677 gimplify_expr_stmt (expr_p);
678 ret = GS_OK;
679 break;
681 case UNARY_PLUS_EXPR:
683 tree arg = TREE_OPERAND (*expr_p, 0);
684 tree type = TREE_TYPE (*expr_p);
685 *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
686 : arg;
687 ret = GS_OK;
689 break;
691 default:
692 ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p);
693 break;
696 /* Restore saved state. */
697 if (STATEMENT_CODE_P (code))
698 current_stmt_tree ()->stmts_are_full_exprs_p
699 = saved_stmts_are_full_exprs_p;
701 return ret;
704 static inline bool
705 is_invisiref_parm (const_tree t)
707 return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
708 && DECL_BY_REFERENCE (t));
711 /* Return true if the uid in both int tree maps are equal. */
714 cxx_int_tree_map_eq (const void *va, const void *vb)
716 const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
717 const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
718 return (a->uid == b->uid);
721 /* Hash a UID in a cxx_int_tree_map. */
723 unsigned int
724 cxx_int_tree_map_hash (const void *item)
726 return ((const struct cxx_int_tree_map *)item)->uid;
729 /* A stable comparison routine for use with splay trees and DECLs. */
731 static int
732 splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
734 tree a = (tree) xa;
735 tree b = (tree) xb;
737 return DECL_UID (a) - DECL_UID (b);
740 /* OpenMP context during genericization. */
742 struct cp_genericize_omp_taskreg
744 bool is_parallel;
745 bool default_shared;
746 struct cp_genericize_omp_taskreg *outer;
747 splay_tree variables;
750 /* Return true if genericization should try to determine if
751 DECL is firstprivate or shared within task regions. */
753 static bool
754 omp_var_to_track (tree decl)
756 tree type = TREE_TYPE (decl);
757 if (is_invisiref_parm (decl))
758 type = TREE_TYPE (type);
759 while (TREE_CODE (type) == ARRAY_TYPE)
760 type = TREE_TYPE (type);
761 if (type == error_mark_node || !CLASS_TYPE_P (type))
762 return false;
763 if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
764 return false;
765 if (cxx_omp_predetermined_sharing (decl) != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
766 return false;
767 return true;
770 /* Note DECL use in OpenMP region OMP_CTX during genericization. */
772 static void
773 omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl)
775 splay_tree_node n = splay_tree_lookup (omp_ctx->variables,
776 (splay_tree_key) decl);
777 if (n == NULL)
779 int flags = OMP_CLAUSE_DEFAULT_SHARED;
780 if (omp_ctx->outer)
781 omp_cxx_notice_variable (omp_ctx->outer, decl);
782 if (!omp_ctx->default_shared)
784 struct cp_genericize_omp_taskreg *octx;
786 for (octx = omp_ctx->outer; octx; octx = octx->outer)
788 n = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
789 if (n && n->value != OMP_CLAUSE_DEFAULT_SHARED)
791 flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
792 break;
794 if (octx->is_parallel)
795 break;
797 if (octx == NULL
798 && (TREE_CODE (decl) == PARM_DECL
799 || (!(TREE_STATIC (decl) || DECL_EXTERNAL (decl))
800 && DECL_CONTEXT (decl) == current_function_decl)))
801 flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
802 if (flags == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
804 /* DECL is implicitly determined firstprivate in
805 the current task construct. Ensure copy ctor and
806 dtor are instantiated, because during gimplification
807 it will be already too late. */
808 tree type = TREE_TYPE (decl);
809 if (is_invisiref_parm (decl))
810 type = TREE_TYPE (type);
811 while (TREE_CODE (type) == ARRAY_TYPE)
812 type = TREE_TYPE (type);
813 get_copy_ctor (type, tf_none);
814 get_dtor (type, tf_none);
817 splay_tree_insert (omp_ctx->variables, (splay_tree_key) decl, flags);
821 /* Genericization context. */
823 struct cp_genericize_data
825 struct pointer_set_t *p_set;
826 VEC (tree, heap) *bind_expr_stack;
827 struct cp_genericize_omp_taskreg *omp_ctx;
830 /* Perform any pre-gimplification lowering of C++ front end trees to
831 GENERIC. */
833 static tree
834 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
836 tree stmt = *stmt_p;
837 struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
838 struct pointer_set_t *p_set = wtd->p_set;
840 /* If in an OpenMP context, note var uses. */
841 if (__builtin_expect (wtd->omp_ctx != NULL, 0)
842 && (TREE_CODE (stmt) == VAR_DECL
843 || TREE_CODE (stmt) == PARM_DECL
844 || TREE_CODE (stmt) == RESULT_DECL)
845 && omp_var_to_track (stmt))
846 omp_cxx_notice_variable (wtd->omp_ctx, stmt);
848 if (is_invisiref_parm (stmt)
849 /* Don't dereference parms in a thunk, pass the references through. */
850 && !(DECL_THUNK_P (current_function_decl)
851 && TREE_CODE (stmt) == PARM_DECL))
853 *stmt_p = convert_from_reference (stmt);
854 *walk_subtrees = 0;
855 return NULL;
858 /* Map block scope extern declarations to visible declarations with the
859 same name and type in outer scopes if any. */
860 if (cp_function_chain->extern_decl_map
861 && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
862 && DECL_EXTERNAL (stmt))
864 struct cxx_int_tree_map *h, in;
865 in.uid = DECL_UID (stmt);
866 h = (struct cxx_int_tree_map *)
867 htab_find_with_hash (cp_function_chain->extern_decl_map,
868 &in, in.uid);
869 if (h)
871 *stmt_p = h->to;
872 *walk_subtrees = 0;
873 return NULL;
877 /* Other than invisiref parms, don't walk the same tree twice. */
878 if (pointer_set_contains (p_set, stmt))
880 *walk_subtrees = 0;
881 return NULL_TREE;
884 if (TREE_CODE (stmt) == ADDR_EXPR
885 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
887 /* If in an OpenMP context, note var uses. */
888 if (__builtin_expect (wtd->omp_ctx != NULL, 0)
889 && omp_var_to_track (TREE_OPERAND (stmt, 0)))
890 omp_cxx_notice_variable (wtd->omp_ctx, TREE_OPERAND (stmt, 0));
891 *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
892 *walk_subtrees = 0;
894 else if (TREE_CODE (stmt) == RETURN_EXPR
895 && TREE_OPERAND (stmt, 0)
896 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
897 /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */
898 *walk_subtrees = 0;
899 else if (TREE_CODE (stmt) == OMP_CLAUSE)
900 switch (OMP_CLAUSE_CODE (stmt))
902 case OMP_CLAUSE_LASTPRIVATE:
903 /* Don't dereference an invisiref in OpenMP clauses. */
904 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
906 *walk_subtrees = 0;
907 if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt))
908 cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt),
909 cp_genericize_r, data, NULL);
911 break;
912 case OMP_CLAUSE_PRIVATE:
913 /* Don't dereference an invisiref in OpenMP clauses. */
914 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
915 *walk_subtrees = 0;
916 else if (wtd->omp_ctx != NULL)
918 /* Private clause doesn't cause any references to the
919 var in outer contexts, avoid calling
920 omp_cxx_notice_variable for it. */
921 struct cp_genericize_omp_taskreg *old = wtd->omp_ctx;
922 wtd->omp_ctx = NULL;
923 cp_walk_tree (&OMP_CLAUSE_DECL (stmt), cp_genericize_r,
924 data, NULL);
925 wtd->omp_ctx = old;
926 *walk_subtrees = 0;
928 break;
929 case OMP_CLAUSE_SHARED:
930 case OMP_CLAUSE_FIRSTPRIVATE:
931 case OMP_CLAUSE_COPYIN:
932 case OMP_CLAUSE_COPYPRIVATE:
933 /* Don't dereference an invisiref in OpenMP clauses. */
934 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
935 *walk_subtrees = 0;
936 break;
937 case OMP_CLAUSE_REDUCTION:
938 gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
939 break;
940 default:
941 break;
943 else if (IS_TYPE_OR_DECL_P (stmt))
944 *walk_subtrees = 0;
946 /* Due to the way voidify_wrapper_expr is written, we don't get a chance
947 to lower this construct before scanning it, so we need to lower these
948 before doing anything else. */
949 else if (TREE_CODE (stmt) == CLEANUP_STMT)
950 *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
951 : TRY_FINALLY_EXPR,
952 void_type_node,
953 CLEANUP_BODY (stmt),
954 CLEANUP_EXPR (stmt));
956 else if (TREE_CODE (stmt) == IF_STMT)
958 genericize_if_stmt (stmt_p);
959 /* *stmt_p has changed, tail recurse to handle it again. */
960 return cp_genericize_r (stmt_p, walk_subtrees, data);
963 /* COND_EXPR might have incompatible types in branches if one or both
964 arms are bitfields. Fix it up now. */
965 else if (TREE_CODE (stmt) == COND_EXPR)
967 tree type_left
968 = (TREE_OPERAND (stmt, 1)
969 ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1))
970 : NULL_TREE);
971 tree type_right
972 = (TREE_OPERAND (stmt, 2)
973 ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2))
974 : NULL_TREE);
975 if (type_left
976 && !useless_type_conversion_p (TREE_TYPE (stmt),
977 TREE_TYPE (TREE_OPERAND (stmt, 1))))
979 TREE_OPERAND (stmt, 1)
980 = fold_convert (type_left, TREE_OPERAND (stmt, 1));
981 gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
982 type_left));
984 if (type_right
985 && !useless_type_conversion_p (TREE_TYPE (stmt),
986 TREE_TYPE (TREE_OPERAND (stmt, 2))))
988 TREE_OPERAND (stmt, 2)
989 = fold_convert (type_right, TREE_OPERAND (stmt, 2));
990 gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
991 type_right));
995 else if (TREE_CODE (stmt) == BIND_EXPR)
997 if (__builtin_expect (wtd->omp_ctx != NULL, 0))
999 tree decl;
1000 for (decl = BIND_EXPR_VARS (stmt); decl; decl = DECL_CHAIN (decl))
1001 if (TREE_CODE (decl) == VAR_DECL
1002 && !DECL_EXTERNAL (decl)
1003 && omp_var_to_track (decl))
1005 splay_tree_node n
1006 = splay_tree_lookup (wtd->omp_ctx->variables,
1007 (splay_tree_key) decl);
1008 if (n == NULL)
1009 splay_tree_insert (wtd->omp_ctx->variables,
1010 (splay_tree_key) decl,
1011 TREE_STATIC (decl)
1012 ? OMP_CLAUSE_DEFAULT_SHARED
1013 : OMP_CLAUSE_DEFAULT_PRIVATE);
1016 VEC_safe_push (tree, heap, wtd->bind_expr_stack, stmt);
1017 cp_walk_tree (&BIND_EXPR_BODY (stmt),
1018 cp_genericize_r, data, NULL);
1019 VEC_pop (tree, wtd->bind_expr_stack);
1022 else if (TREE_CODE (stmt) == USING_STMT)
1024 tree block = NULL_TREE;
1026 /* Get the innermost inclosing GIMPLE_BIND that has a non NULL
1027 BLOCK, and append an IMPORTED_DECL to its
1028 BLOCK_VARS chained list. */
1029 if (wtd->bind_expr_stack)
1031 int i;
1032 for (i = VEC_length (tree, wtd->bind_expr_stack) - 1; i >= 0; i--)
1033 if ((block = BIND_EXPR_BLOCK (VEC_index (tree,
1034 wtd->bind_expr_stack, i))))
1035 break;
1037 if (block)
1039 tree using_directive;
1040 gcc_assert (TREE_OPERAND (stmt, 0));
1042 using_directive = make_node (IMPORTED_DECL);
1043 TREE_TYPE (using_directive) = void_type_node;
1045 IMPORTED_DECL_ASSOCIATED_DECL (using_directive)
1046 = TREE_OPERAND (stmt, 0);
1047 DECL_CHAIN (using_directive) = BLOCK_VARS (block);
1048 BLOCK_VARS (block) = using_directive;
1050 /* The USING_STMT won't appear in GENERIC. */
1051 *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
1052 *walk_subtrees = 0;
1055 else if (TREE_CODE (stmt) == DECL_EXPR
1056 && TREE_CODE (DECL_EXPR_DECL (stmt)) == USING_DECL)
1058 /* Using decls inside DECL_EXPRs are just dropped on the floor. */
1059 *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
1060 *walk_subtrees = 0;
1062 else if (TREE_CODE (stmt) == OMP_PARALLEL || TREE_CODE (stmt) == OMP_TASK)
1064 struct cp_genericize_omp_taskreg omp_ctx;
1065 tree c, decl;
1066 splay_tree_node n;
1068 *walk_subtrees = 0;
1069 cp_walk_tree (&OMP_CLAUSES (stmt), cp_genericize_r, data, NULL);
1070 omp_ctx.is_parallel = TREE_CODE (stmt) == OMP_PARALLEL;
1071 omp_ctx.default_shared = omp_ctx.is_parallel;
1072 omp_ctx.outer = wtd->omp_ctx;
1073 omp_ctx.variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
1074 wtd->omp_ctx = &omp_ctx;
1075 for (c = OMP_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
1076 switch (OMP_CLAUSE_CODE (c))
1078 case OMP_CLAUSE_SHARED:
1079 case OMP_CLAUSE_PRIVATE:
1080 case OMP_CLAUSE_FIRSTPRIVATE:
1081 case OMP_CLAUSE_LASTPRIVATE:
1082 decl = OMP_CLAUSE_DECL (c);
1083 if (decl == error_mark_node || !omp_var_to_track (decl))
1084 break;
1085 n = splay_tree_lookup (omp_ctx.variables, (splay_tree_key) decl);
1086 if (n != NULL)
1087 break;
1088 splay_tree_insert (omp_ctx.variables, (splay_tree_key) decl,
1089 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1090 ? OMP_CLAUSE_DEFAULT_SHARED
1091 : OMP_CLAUSE_DEFAULT_PRIVATE);
1092 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE
1093 && omp_ctx.outer)
1094 omp_cxx_notice_variable (omp_ctx.outer, decl);
1095 break;
1096 case OMP_CLAUSE_DEFAULT:
1097 if (OMP_CLAUSE_DEFAULT_KIND (c) == OMP_CLAUSE_DEFAULT_SHARED)
1098 omp_ctx.default_shared = true;
1099 default:
1100 break;
1102 cp_walk_tree (&OMP_BODY (stmt), cp_genericize_r, data, NULL);
1103 wtd->omp_ctx = omp_ctx.outer;
1104 splay_tree_delete (omp_ctx.variables);
1106 else if (TREE_CODE (stmt) == CONVERT_EXPR)
1107 gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt));
1108 else if (TREE_CODE (stmt) == FOR_STMT)
1109 genericize_for_stmt (stmt_p, walk_subtrees, data);
1110 else if (TREE_CODE (stmt) == WHILE_STMT)
1111 genericize_while_stmt (stmt_p, walk_subtrees, data);
1112 else if (TREE_CODE (stmt) == DO_STMT)
1113 genericize_do_stmt (stmt_p, walk_subtrees, data);
1114 else if (TREE_CODE (stmt) == SWITCH_STMT)
1115 genericize_switch_stmt (stmt_p, walk_subtrees, data);
1116 else if (TREE_CODE (stmt) == CONTINUE_STMT)
1117 genericize_continue_stmt (stmt_p);
1118 else if (TREE_CODE (stmt) == BREAK_STMT)
1119 genericize_break_stmt (stmt_p);
1120 else if (TREE_CODE (stmt) == OMP_FOR)
1121 genericize_omp_for_stmt (stmt_p, walk_subtrees, data);
1123 pointer_set_insert (p_set, *stmt_p);
1125 return NULL;
1128 /* Lower C++ front end trees to GENERIC in T_P. */
1130 static void
1131 cp_genericize_tree (tree* t_p)
1133 struct cp_genericize_data wtd;
1135 wtd.p_set = pointer_set_create ();
1136 wtd.bind_expr_stack = NULL;
1137 wtd.omp_ctx = NULL;
1138 cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
1139 pointer_set_destroy (wtd.p_set);
1140 VEC_free (tree, heap, wtd.bind_expr_stack);
1143 void
1144 cp_genericize (tree fndecl)
1146 tree t;
1148 /* Fix up the types of parms passed by invisible reference. */
1149 for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t))
1150 if (TREE_ADDRESSABLE (TREE_TYPE (t)))
1152 /* If a function's arguments are copied to create a thunk,
1153 then DECL_BY_REFERENCE will be set -- but the type of the
1154 argument will be a pointer type, so we will never get
1155 here. */
1156 gcc_assert (!DECL_BY_REFERENCE (t));
1157 gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
1158 TREE_TYPE (t) = DECL_ARG_TYPE (t);
1159 DECL_BY_REFERENCE (t) = 1;
1160 TREE_ADDRESSABLE (t) = 0;
1161 relayout_decl (t);
1164 /* Do the same for the return value. */
1165 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
1167 t = DECL_RESULT (fndecl);
1168 TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
1169 DECL_BY_REFERENCE (t) = 1;
1170 TREE_ADDRESSABLE (t) = 0;
1171 relayout_decl (t);
1172 if (DECL_NAME (t))
1174 /* Adjust DECL_VALUE_EXPR of the original var. */
1175 tree outer = outer_curly_brace_block (current_function_decl);
1176 tree var;
1178 if (outer)
1179 for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
1180 if (DECL_NAME (t) == DECL_NAME (var)
1181 && DECL_HAS_VALUE_EXPR_P (var)
1182 && DECL_VALUE_EXPR (var) == t)
1184 tree val = convert_from_reference (t);
1185 SET_DECL_VALUE_EXPR (var, val);
1186 break;
1191 /* If we're a clone, the body is already GIMPLE. */
1192 if (DECL_CLONED_FUNCTION_P (fndecl))
1193 return;
1195 /* We do want to see every occurrence of the parms, so we can't just use
1196 walk_tree's hash functionality. */
1197 cp_genericize_tree (&DECL_SAVED_TREE (fndecl));
1199 /* Do everything else. */
1200 c_genericize (fndecl);
1202 gcc_assert (bc_label[bc_break] == NULL);
1203 gcc_assert (bc_label[bc_continue] == NULL);
1206 /* Build code to apply FN to each member of ARG1 and ARG2. FN may be
1207 NULL if there is in fact nothing to do. ARG2 may be null if FN
1208 actually only takes one argument. */
1210 static tree
1211 cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
1213 tree defparm, parm, t;
1214 int i = 0;
1215 int nargs;
1216 tree *argarray;
1218 if (fn == NULL)
1219 return NULL;
1221 nargs = list_length (DECL_ARGUMENTS (fn));
1222 argarray = XALLOCAVEC (tree, nargs);
1224 defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
1225 if (arg2)
1226 defparm = TREE_CHAIN (defparm);
1228 if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
1230 tree inner_type = TREE_TYPE (arg1);
1231 tree start1, end1, p1;
1232 tree start2 = NULL, p2 = NULL;
1233 tree ret = NULL, lab;
1235 start1 = arg1;
1236 start2 = arg2;
1239 inner_type = TREE_TYPE (inner_type);
1240 start1 = build4 (ARRAY_REF, inner_type, start1,
1241 size_zero_node, NULL, NULL);
1242 if (arg2)
1243 start2 = build4 (ARRAY_REF, inner_type, start2,
1244 size_zero_node, NULL, NULL);
1246 while (TREE_CODE (inner_type) == ARRAY_TYPE);
1247 start1 = build_fold_addr_expr_loc (input_location, start1);
1248 if (arg2)
1249 start2 = build_fold_addr_expr_loc (input_location, start2);
1251 end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
1252 end1 = fold_build_pointer_plus (start1, end1);
1254 p1 = create_tmp_var (TREE_TYPE (start1), NULL);
1255 t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, start1);
1256 append_to_statement_list (t, &ret);
1258 if (arg2)
1260 p2 = create_tmp_var (TREE_TYPE (start2), NULL);
1261 t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, start2);
1262 append_to_statement_list (t, &ret);
1265 lab = create_artificial_label (input_location);
1266 t = build1 (LABEL_EXPR, void_type_node, lab);
1267 append_to_statement_list (t, &ret);
1269 argarray[i++] = p1;
1270 if (arg2)
1271 argarray[i++] = p2;
1272 /* Handle default arguments. */
1273 for (parm = defparm; parm && parm != void_list_node;
1274 parm = TREE_CHAIN (parm), i++)
1275 argarray[i] = convert_default_arg (TREE_VALUE (parm),
1276 TREE_PURPOSE (parm), fn, i,
1277 tf_warning_or_error);
1278 t = build_call_a (fn, i, argarray);
1279 t = fold_convert (void_type_node, t);
1280 t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
1281 append_to_statement_list (t, &ret);
1283 t = fold_build_pointer_plus (p1, TYPE_SIZE_UNIT (inner_type));
1284 t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, t);
1285 append_to_statement_list (t, &ret);
1287 if (arg2)
1289 t = fold_build_pointer_plus (p2, TYPE_SIZE_UNIT (inner_type));
1290 t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, t);
1291 append_to_statement_list (t, &ret);
1294 t = build2 (NE_EXPR, boolean_type_node, p1, end1);
1295 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
1296 append_to_statement_list (t, &ret);
1298 return ret;
1300 else
1302 argarray[i++] = build_fold_addr_expr_loc (input_location, arg1);
1303 if (arg2)
1304 argarray[i++] = build_fold_addr_expr_loc (input_location, arg2);
1305 /* Handle default arguments. */
1306 for (parm = defparm; parm && parm != void_list_node;
1307 parm = TREE_CHAIN (parm), i++)
1308 argarray[i] = convert_default_arg (TREE_VALUE (parm),
1309 TREE_PURPOSE (parm),
1310 fn, i, tf_warning_or_error);
1311 t = build_call_a (fn, i, argarray);
1312 t = fold_convert (void_type_node, t);
1313 return fold_build_cleanup_point_expr (TREE_TYPE (t), t);
1317 /* Return code to initialize DECL with its default constructor, or
1318 NULL if there's nothing to do. */
1320 tree
1321 cxx_omp_clause_default_ctor (tree clause, tree decl, tree /*outer*/)
1323 tree info = CP_OMP_CLAUSE_INFO (clause);
1324 tree ret = NULL;
1326 if (info)
1327 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
1329 return ret;
1332 /* Return code to initialize DST with a copy constructor from SRC. */
1334 tree
1335 cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
1337 tree info = CP_OMP_CLAUSE_INFO (clause);
1338 tree ret = NULL;
1340 if (info)
1341 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
1342 if (ret == NULL)
1343 ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
1345 return ret;
1348 /* Similarly, except use an assignment operator instead. */
1350 tree
1351 cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
1353 tree info = CP_OMP_CLAUSE_INFO (clause);
1354 tree ret = NULL;
1356 if (info)
1357 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
1358 if (ret == NULL)
1359 ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
1361 return ret;
1364 /* Return code to destroy DECL. */
1366 tree
1367 cxx_omp_clause_dtor (tree clause, tree decl)
1369 tree info = CP_OMP_CLAUSE_INFO (clause);
1370 tree ret = NULL;
1372 if (info)
1373 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
1375 return ret;
1378 /* True if OpenMP should privatize what this DECL points to rather
1379 than the DECL itself. */
1381 bool
1382 cxx_omp_privatize_by_reference (const_tree decl)
1384 return is_invisiref_parm (decl);
1387 /* Return true if DECL is const qualified var having no mutable member. */
1388 bool
1389 cxx_omp_const_qual_no_mutable (tree decl)
1391 tree type = TREE_TYPE (decl);
1392 if (TREE_CODE (type) == REFERENCE_TYPE)
1394 if (!is_invisiref_parm (decl))
1395 return false;
1396 type = TREE_TYPE (type);
1398 if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl))
1400 /* NVR doesn't preserve const qualification of the
1401 variable's type. */
1402 tree outer = outer_curly_brace_block (current_function_decl);
1403 tree var;
1405 if (outer)
1406 for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
1407 if (DECL_NAME (decl) == DECL_NAME (var)
1408 && (TYPE_MAIN_VARIANT (type)
1409 == TYPE_MAIN_VARIANT (TREE_TYPE (var))))
1411 if (TYPE_READONLY (TREE_TYPE (var)))
1412 type = TREE_TYPE (var);
1413 break;
1418 if (type == error_mark_node)
1419 return false;
1421 /* Variables with const-qualified type having no mutable member
1422 are predetermined shared. */
1423 if (TYPE_READONLY (type) && !cp_has_mutable_p (type))
1424 return true;
1426 return false;
1429 /* True if OpenMP sharing attribute of DECL is predetermined. */
1431 enum omp_clause_default_kind
1432 cxx_omp_predetermined_sharing (tree decl)
1434 /* Static data members are predetermined shared. */
1435 if (TREE_STATIC (decl))
1437 tree ctx = CP_DECL_CONTEXT (decl);
1438 if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
1439 return OMP_CLAUSE_DEFAULT_SHARED;
1442 /* Const qualified vars having no mutable member are predetermined
1443 shared. */
1444 if (cxx_omp_const_qual_no_mutable (decl))
1445 return OMP_CLAUSE_DEFAULT_SHARED;
1447 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
1450 /* Finalize an implicitly determined clause. */
1452 void
1453 cxx_omp_finish_clause (tree c)
1455 tree decl, inner_type;
1456 bool make_shared = false;
1458 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
1459 return;
1461 decl = OMP_CLAUSE_DECL (c);
1462 decl = require_complete_type (decl);
1463 inner_type = TREE_TYPE (decl);
1464 if (decl == error_mark_node)
1465 make_shared = true;
1466 else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
1468 if (is_invisiref_parm (decl))
1469 inner_type = TREE_TYPE (inner_type);
1470 else
1472 error ("%qE implicitly determined as %<firstprivate%> has reference type",
1473 decl);
1474 make_shared = true;
1478 /* We're interested in the base element, not arrays. */
1479 while (TREE_CODE (inner_type) == ARRAY_TYPE)
1480 inner_type = TREE_TYPE (inner_type);
1482 /* Check for special function availability by building a call to one.
1483 Save the results, because later we won't be in the right context
1484 for making these queries. */
1485 if (!make_shared
1486 && CLASS_TYPE_P (inner_type)
1487 && cxx_omp_create_clause_info (c, inner_type, false, true, false))
1488 make_shared = true;
1490 if (make_shared)
1491 OMP_CLAUSE_CODE (c) = OMP_CLAUSE_SHARED;