1 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
3 Copyright (C) 2002-2015 Free Software Foundation, Inc.
4 Contributed by Jason Merrill <jason@redhat.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
29 #include "double-int.h"
36 #include "stor-layout.h"
38 #include "c-family/c-common.h"
39 #include "tree-iterator.h"
41 #include "hard-reg-set.h"
44 #include "basic-block.h"
45 #include "tree-ssa-alias.h"
46 #include "internal-fn.h"
47 #include "gimple-expr.h"
52 #include "splay-tree.h"
54 #include "c-family/c-ubsan.h"
57 #include "gimple-expr.h"
59 /* Forward declarations. */
61 static tree
cp_genericize_r (tree
*, int *, void *);
62 static void cp_genericize_tree (tree
*);
64 /* Local declarations. */
66 enum bc_t
{ bc_break
= 0, bc_continue
= 1 };
68 /* Stack of labels which are targets for "break" or "continue",
69 linked through TREE_CHAIN. */
70 static tree bc_label
[2];
72 /* Begin a scope which can be exited by a break or continue statement. BC
75 Just creates a label with location LOCATION and pushes it into the current
79 begin_bc_block (enum bc_t bc
, location_t location
)
81 tree label
= create_artificial_label (location
);
82 DECL_CHAIN (label
) = bc_label
[bc
];
85 LABEL_DECL_BREAK (label
) = true;
87 LABEL_DECL_CONTINUE (label
) = true;
91 /* Finish a scope which can be exited by a break or continue statement.
92 LABEL was returned from the most recent call to begin_bc_block. BLOCK is
93 an expression for the contents of the scope.
95 If we saw a break (or continue) in the scope, append a LABEL_EXPR to
96 BLOCK. Otherwise, just forget the label. */
99 finish_bc_block (tree
*block
, enum bc_t bc
, tree label
)
101 gcc_assert (label
== bc_label
[bc
]);
103 if (TREE_USED (label
))
104 append_to_statement_list (build1 (LABEL_EXPR
, void_type_node
, label
),
107 bc_label
[bc
] = DECL_CHAIN (label
);
108 DECL_CHAIN (label
) = NULL_TREE
;
111 /* Get the LABEL_EXPR to represent a break or continue statement
112 in the current block scope. BC indicates which. */
115 get_bc_label (enum bc_t bc
)
117 tree label
= bc_label
[bc
];
119 /* Mark the label used for finish_bc_block. */
120 TREE_USED (label
) = 1;
124 /* Genericize a TRY_BLOCK. */
127 genericize_try_block (tree
*stmt_p
)
129 tree body
= TRY_STMTS (*stmt_p
);
130 tree cleanup
= TRY_HANDLERS (*stmt_p
);
132 *stmt_p
= build2 (TRY_CATCH_EXPR
, void_type_node
, body
, cleanup
);
135 /* Genericize a HANDLER by converting to a CATCH_EXPR. */
138 genericize_catch_block (tree
*stmt_p
)
140 tree type
= HANDLER_TYPE (*stmt_p
);
141 tree body
= HANDLER_BODY (*stmt_p
);
143 /* FIXME should the caught type go in TREE_TYPE? */
144 *stmt_p
= build2 (CATCH_EXPR
, void_type_node
, type
, body
);
147 /* A terser interface for building a representation of an exception
151 build_gimple_eh_filter_tree (tree body
, tree allowed
, tree failure
)
155 /* FIXME should the allowed types go in TREE_TYPE? */
156 t
= build2 (EH_FILTER_EXPR
, void_type_node
, allowed
, NULL_TREE
);
157 append_to_statement_list (failure
, &EH_FILTER_FAILURE (t
));
159 t
= build2 (TRY_CATCH_EXPR
, void_type_node
, NULL_TREE
, t
);
160 append_to_statement_list (body
, &TREE_OPERAND (t
, 0));
165 /* Genericize an EH_SPEC_BLOCK by converting it to a
166 TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
169 genericize_eh_spec_block (tree
*stmt_p
)
171 tree body
= EH_SPEC_STMTS (*stmt_p
);
172 tree allowed
= EH_SPEC_RAISES (*stmt_p
);
173 tree failure
= build_call_n (call_unexpected_node
, 1, build_exc_ptr ());
175 *stmt_p
= build_gimple_eh_filter_tree (body
, allowed
, failure
);
176 TREE_NO_WARNING (*stmt_p
) = true;
177 TREE_NO_WARNING (TREE_OPERAND (*stmt_p
, 1)) = true;
180 /* Genericize an IF_STMT by turning it into a COND_EXPR. */
183 genericize_if_stmt (tree
*stmt_p
)
185 tree stmt
, cond
, then_
, else_
;
186 location_t locus
= EXPR_LOCATION (*stmt_p
);
189 cond
= IF_COND (stmt
);
190 then_
= THEN_CLAUSE (stmt
);
191 else_
= ELSE_CLAUSE (stmt
);
194 then_
= build_empty_stmt (locus
);
196 else_
= build_empty_stmt (locus
);
198 if (integer_nonzerop (cond
) && !TREE_SIDE_EFFECTS (else_
))
200 else if (integer_zerop (cond
) && !TREE_SIDE_EFFECTS (then_
))
203 stmt
= build3 (COND_EXPR
, void_type_node
, cond
, then_
, else_
);
204 if (CAN_HAVE_LOCATION_P (stmt
) && !EXPR_HAS_LOCATION (stmt
))
205 SET_EXPR_LOCATION (stmt
, locus
);
209 /* Build a generic representation of one of the C loop forms. COND is the
210 loop condition or NULL_TREE. BODY is the (possibly compound) statement
211 controlled by the loop. INCR is the increment expression of a for-loop,
212 or NULL_TREE. COND_IS_FIRST indicates whether the condition is
213 evaluated before the loop body as in while and for loops, or after the
214 loop body as in do-while loops. */
217 genericize_cp_loop (tree
*stmt_p
, location_t start_locus
, tree cond
, tree body
,
218 tree incr
, bool cond_is_first
, int *walk_subtrees
,
223 tree stmt_list
= NULL
;
225 blab
= begin_bc_block (bc_break
, start_locus
);
226 clab
= begin_bc_block (bc_continue
, start_locus
);
228 if (incr
&& EXPR_P (incr
))
229 SET_EXPR_LOCATION (incr
, start_locus
);
231 cp_walk_tree (&cond
, cp_genericize_r
, data
, NULL
);
232 cp_walk_tree (&body
, cp_genericize_r
, data
, NULL
);
233 cp_walk_tree (&incr
, cp_genericize_r
, data
, NULL
);
236 if (cond
&& TREE_CODE (cond
) != INTEGER_CST
)
238 /* If COND is constant, don't bother building an exit. If it's false,
239 we won't build a loop. If it's true, any exits are in the body. */
240 location_t cloc
= EXPR_LOC_OR_LOC (cond
, start_locus
);
241 exit
= build1_loc (cloc
, GOTO_EXPR
, void_type_node
,
242 get_bc_label (bc_break
));
243 exit
= fold_build3_loc (cloc
, COND_EXPR
, void_type_node
, cond
,
244 build_empty_stmt (cloc
), exit
);
247 if (exit
&& cond_is_first
)
248 append_to_statement_list (exit
, &stmt_list
);
249 append_to_statement_list (body
, &stmt_list
);
250 finish_bc_block (&stmt_list
, bc_continue
, clab
);
251 append_to_statement_list (incr
, &stmt_list
);
252 if (exit
&& !cond_is_first
)
253 append_to_statement_list (exit
, &stmt_list
);
256 stmt_list
= build_empty_stmt (start_locus
);
259 if (cond
&& integer_zerop (cond
))
262 loop
= fold_build3_loc (start_locus
, COND_EXPR
,
263 void_type_node
, cond
, stmt_list
,
264 build_empty_stmt (start_locus
));
269 loop
= build1_loc (start_locus
, LOOP_EXPR
, void_type_node
, stmt_list
);
272 append_to_statement_list (loop
, &stmt_list
);
273 finish_bc_block (&stmt_list
, bc_break
, blab
);
275 stmt_list
= build_empty_stmt (start_locus
);
280 /* Genericize a FOR_STMT node *STMT_P. */
283 genericize_for_stmt (tree
*stmt_p
, int *walk_subtrees
, void *data
)
288 tree init
= FOR_INIT_STMT (stmt
);
292 cp_walk_tree (&init
, cp_genericize_r
, data
, NULL
);
293 append_to_statement_list (init
, &expr
);
296 genericize_cp_loop (&loop
, EXPR_LOCATION (stmt
), FOR_COND (stmt
),
297 FOR_BODY (stmt
), FOR_EXPR (stmt
), 1, walk_subtrees
, data
);
298 append_to_statement_list (loop
, &expr
);
299 if (expr
== NULL_TREE
)
304 /* Genericize a WHILE_STMT node *STMT_P. */
307 genericize_while_stmt (tree
*stmt_p
, int *walk_subtrees
, void *data
)
310 genericize_cp_loop (stmt_p
, EXPR_LOCATION (stmt
), WHILE_COND (stmt
),
311 WHILE_BODY (stmt
), NULL_TREE
, 1, walk_subtrees
, data
);
314 /* Genericize a DO_STMT node *STMT_P. */
317 genericize_do_stmt (tree
*stmt_p
, int *walk_subtrees
, void *data
)
320 genericize_cp_loop (stmt_p
, EXPR_LOCATION (stmt
), DO_COND (stmt
),
321 DO_BODY (stmt
), NULL_TREE
, 0, walk_subtrees
, data
);
324 /* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR. */
327 genericize_switch_stmt (tree
*stmt_p
, int *walk_subtrees
, void *data
)
330 tree break_block
, body
, cond
, type
;
331 location_t stmt_locus
= EXPR_LOCATION (stmt
);
333 break_block
= begin_bc_block (bc_break
, stmt_locus
);
335 body
= SWITCH_STMT_BODY (stmt
);
337 body
= build_empty_stmt (stmt_locus
);
338 cond
= SWITCH_STMT_COND (stmt
);
339 type
= SWITCH_STMT_TYPE (stmt
);
341 cp_walk_tree (&body
, cp_genericize_r
, data
, NULL
);
342 cp_walk_tree (&cond
, cp_genericize_r
, data
, NULL
);
343 cp_walk_tree (&type
, cp_genericize_r
, data
, NULL
);
346 *stmt_p
= build3_loc (stmt_locus
, SWITCH_EXPR
, type
, cond
, body
, NULL_TREE
);
347 finish_bc_block (stmt_p
, bc_break
, break_block
);
350 /* Genericize a CONTINUE_STMT node *STMT_P. */
353 genericize_continue_stmt (tree
*stmt_p
)
355 tree stmt_list
= NULL
;
356 tree pred
= build_predict_expr (PRED_CONTINUE
, NOT_TAKEN
);
357 tree label
= get_bc_label (bc_continue
);
358 location_t location
= EXPR_LOCATION (*stmt_p
);
359 tree jump
= build1_loc (location
, GOTO_EXPR
, void_type_node
, label
);
360 append_to_statement_list (pred
, &stmt_list
);
361 append_to_statement_list (jump
, &stmt_list
);
365 /* Genericize a BREAK_STMT node *STMT_P. */
368 genericize_break_stmt (tree
*stmt_p
)
370 tree label
= get_bc_label (bc_break
);
371 location_t location
= EXPR_LOCATION (*stmt_p
);
372 *stmt_p
= build1_loc (location
, GOTO_EXPR
, void_type_node
, label
);
375 /* Genericize a OMP_FOR node *STMT_P. */
378 genericize_omp_for_stmt (tree
*stmt_p
, int *walk_subtrees
, void *data
)
381 location_t locus
= EXPR_LOCATION (stmt
);
382 tree clab
= begin_bc_block (bc_continue
, locus
);
384 cp_walk_tree (&OMP_FOR_BODY (stmt
), cp_genericize_r
, data
, NULL
);
385 cp_walk_tree (&OMP_FOR_CLAUSES (stmt
), cp_genericize_r
, data
, NULL
);
386 cp_walk_tree (&OMP_FOR_INIT (stmt
), cp_genericize_r
, data
, NULL
);
387 cp_walk_tree (&OMP_FOR_COND (stmt
), cp_genericize_r
, data
, NULL
);
388 cp_walk_tree (&OMP_FOR_INCR (stmt
), cp_genericize_r
, data
, NULL
);
389 cp_walk_tree (&OMP_FOR_PRE_BODY (stmt
), cp_genericize_r
, data
, NULL
);
392 finish_bc_block (&OMP_FOR_BODY (stmt
), bc_continue
, clab
);
395 /* Hook into the middle of gimplifying an OMP_FOR node. */
397 static enum gimplify_status
398 cp_gimplify_omp_for (tree
*expr_p
, gimple_seq
*pre_p
)
400 tree for_stmt
= *expr_p
;
401 gimple_seq seq
= NULL
;
403 /* Protect ourselves from recursion. */
404 if (OMP_FOR_GIMPLIFYING_P (for_stmt
))
406 OMP_FOR_GIMPLIFYING_P (for_stmt
) = 1;
408 gimplify_and_add (for_stmt
, &seq
);
409 gimple_seq_add_seq (pre_p
, seq
);
411 OMP_FOR_GIMPLIFYING_P (for_stmt
) = 0;
416 /* Gimplify an EXPR_STMT node. */
419 gimplify_expr_stmt (tree
*stmt_p
)
421 tree stmt
= EXPR_STMT_EXPR (*stmt_p
);
423 if (stmt
== error_mark_node
)
426 /* Gimplification of a statement expression will nullify the
427 statement if all its side effects are moved to *PRE_P and *POST_P.
429 In this case we will not want to emit the gimplified statement.
430 However, we may still want to emit a warning, so we do that before
432 if (stmt
&& warn_unused_value
)
434 if (!TREE_SIDE_EFFECTS (stmt
))
436 if (!IS_EMPTY_STMT (stmt
)
437 && !VOID_TYPE_P (TREE_TYPE (stmt
))
438 && !TREE_NO_WARNING (stmt
))
439 warning (OPT_Wunused_value
, "statement with no effect");
442 warn_if_unused_value (stmt
, input_location
);
445 if (stmt
== NULL_TREE
)
446 stmt
= alloc_stmt_list ();
451 /* Gimplify initialization from an AGGR_INIT_EXPR. */
454 cp_gimplify_init_expr (tree
*expr_p
)
456 tree from
= TREE_OPERAND (*expr_p
, 1);
457 tree to
= TREE_OPERAND (*expr_p
, 0);
460 /* What about code that pulls out the temp and uses it elsewhere? I
461 think that such code never uses the TARGET_EXPR as an initializer. If
462 I'm wrong, we'll abort because the temp won't have any RTL. In that
463 case, I guess we'll need to replace references somehow. */
464 if (TREE_CODE (from
) == TARGET_EXPR
)
465 from
= TARGET_EXPR_INITIAL (from
);
467 /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
468 inside the TARGET_EXPR. */
471 tree sub
= TREE_CODE (t
) == COMPOUND_EXPR
? TREE_OPERAND (t
, 0) : t
;
473 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
474 replace the slot operand with our target.
476 Should we add a target parm to gimplify_expr instead? No, as in this
477 case we want to replace the INIT_EXPR. */
478 if (TREE_CODE (sub
) == AGGR_INIT_EXPR
479 || TREE_CODE (sub
) == VEC_INIT_EXPR
)
481 if (TREE_CODE (sub
) == AGGR_INIT_EXPR
)
482 AGGR_INIT_EXPR_SLOT (sub
) = to
;
484 VEC_INIT_EXPR_SLOT (sub
) = to
;
487 /* The initialization is now a side-effect, so the container can
490 TREE_TYPE (from
) = void_type_node
;
493 if (cxx_dialect
>= cxx14
&& TREE_CODE (sub
) == CONSTRUCTOR
)
494 /* Handle aggregate NSDMI. */
495 replace_placeholders (sub
, to
);
500 t
= TREE_OPERAND (t
, 1);
505 /* Gimplify a MUST_NOT_THROW_EXPR. */
507 static enum gimplify_status
508 gimplify_must_not_throw_expr (tree
*expr_p
, gimple_seq
*pre_p
)
511 tree temp
= voidify_wrapper_expr (stmt
, NULL
);
512 tree body
= TREE_OPERAND (stmt
, 0);
513 gimple_seq try_
= NULL
;
514 gimple_seq catch_
= NULL
;
517 gimplify_and_add (body
, &try_
);
518 mnt
= gimple_build_eh_must_not_throw (terminate_node
);
519 gimple_seq_add_stmt_without_update (&catch_
, mnt
);
520 mnt
= gimple_build_try (try_
, catch_
, GIMPLE_TRY_CATCH
);
522 gimple_seq_add_stmt_without_update (pre_p
, mnt
);
533 /* Return TRUE if an operand (OP) of a given TYPE being copied is
534 really just an empty class copy.
536 Check that the operand has a simple form so that TARGET_EXPRs and
537 non-empty CONSTRUCTORs get reduced properly, and we leave the
538 return slot optimization alone because it isn't a copy. */
541 simple_empty_class_p (tree type
, tree op
)
544 ((TREE_CODE (op
) == COMPOUND_EXPR
545 && simple_empty_class_p (type
, TREE_OPERAND (op
, 1)))
546 || is_gimple_lvalue (op
)
547 || INDIRECT_REF_P (op
)
548 || (TREE_CODE (op
) == CONSTRUCTOR
549 && CONSTRUCTOR_NELTS (op
) == 0
550 && !TREE_CLOBBER_P (op
))
551 || (TREE_CODE (op
) == CALL_EXPR
552 && !CALL_EXPR_RETURN_SLOT_OPT (op
)))
553 && is_really_empty_class (type
);
556 /* Do C++-specific gimplification. Args are as for gimplify_expr. */
559 cp_gimplify_expr (tree
*expr_p
, gimple_seq
*pre_p
, gimple_seq
*post_p
)
561 int saved_stmts_are_full_exprs_p
= 0;
562 enum tree_code code
= TREE_CODE (*expr_p
);
563 enum gimplify_status ret
;
565 if (STATEMENT_CODE_P (code
))
567 saved_stmts_are_full_exprs_p
= stmts_are_full_exprs_p ();
568 current_stmt_tree ()->stmts_are_full_exprs_p
569 = STMT_IS_FULL_EXPR_P (*expr_p
);
575 *expr_p
= cplus_expand_constant (*expr_p
);
580 simplify_aggr_init_expr (expr_p
);
586 location_t loc
= input_location
;
587 tree init
= VEC_INIT_EXPR_INIT (*expr_p
);
588 int from_array
= (init
&& TREE_CODE (TREE_TYPE (init
)) == ARRAY_TYPE
);
589 gcc_assert (EXPR_HAS_LOCATION (*expr_p
));
590 input_location
= EXPR_LOCATION (*expr_p
);
591 *expr_p
= build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p
), NULL_TREE
,
592 init
, VEC_INIT_EXPR_VALUE_INIT (*expr_p
),
594 tf_warning_or_error
);
595 cp_genericize_tree (expr_p
);
597 input_location
= loc
;
602 /* FIXME communicate throw type to back end, probably by moving
603 THROW_EXPR into ../tree.def. */
604 *expr_p
= TREE_OPERAND (*expr_p
, 0);
608 case MUST_NOT_THROW_EXPR
:
609 ret
= gimplify_must_not_throw_expr (expr_p
, pre_p
);
612 /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
613 LHS of an assignment might also be involved in the RHS, as in bug
616 if (fn_contains_cilk_spawn_p (cfun
)
617 && cilk_detect_spawn_and_unwrap (expr_p
)
619 return (enum gimplify_status
) gimplify_cilk_spawn (expr_p
);
620 cp_gimplify_init_expr (expr_p
);
621 if (TREE_CODE (*expr_p
) != INIT_EXPR
)
623 /* Otherwise fall through. */
627 if (fn_contains_cilk_spawn_p (cfun
)
628 && cilk_detect_spawn_and_unwrap (expr_p
)
630 return (enum gimplify_status
) gimplify_cilk_spawn (expr_p
);
632 /* If the back end isn't clever enough to know that the lhs and rhs
633 types are the same, add an explicit conversion. */
634 tree op0
= TREE_OPERAND (*expr_p
, 0);
635 tree op1
= TREE_OPERAND (*expr_p
, 1);
637 if (!error_operand_p (op0
)
638 && !error_operand_p (op1
)
639 && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0
))
640 || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1
)))
641 && !useless_type_conversion_p (TREE_TYPE (op1
), TREE_TYPE (op0
)))
642 TREE_OPERAND (*expr_p
, 1) = build1 (VIEW_CONVERT_EXPR
,
643 TREE_TYPE (op0
), op1
);
645 else if (simple_empty_class_p (TREE_TYPE (op0
), op1
))
647 /* Remove any copies of empty classes. Also drop volatile
648 variables on the RHS to avoid infinite recursion from
649 gimplify_expr trying to load the value. */
650 gimplify_expr (&TREE_OPERAND (*expr_p
, 0), pre_p
, post_p
,
651 is_gimple_lvalue
, fb_lvalue
);
652 if (TREE_SIDE_EFFECTS (op1
))
654 if (TREE_THIS_VOLATILE (op1
)
655 && (REFERENCE_CLASS_P (op1
) || DECL_P (op1
)))
656 op1
= build_fold_addr_expr (op1
);
658 gimplify_and_add (op1
, pre_p
);
660 *expr_p
= TREE_OPERAND (*expr_p
, 0);
666 case EMPTY_CLASS_EXPR
:
667 /* We create an empty CONSTRUCTOR with RECORD_TYPE. */
668 *expr_p
= build_constructor (TREE_TYPE (*expr_p
), NULL
);
673 *expr_p
= BASELINK_FUNCTIONS (*expr_p
);
678 genericize_try_block (expr_p
);
683 genericize_catch_block (expr_p
);
688 genericize_eh_spec_block (expr_p
);
706 ret
= cp_gimplify_omp_for (expr_p
, pre_p
);
710 gimplify_expr_stmt (expr_p
);
714 case UNARY_PLUS_EXPR
:
716 tree arg
= TREE_OPERAND (*expr_p
, 0);
717 tree type
= TREE_TYPE (*expr_p
);
718 *expr_p
= (TREE_TYPE (arg
) != type
) ? fold_convert (type
, arg
)
724 case CILK_SPAWN_STMT
:
726 (fn_contains_cilk_spawn_p (cfun
)
727 && cilk_detect_spawn_and_unwrap (expr_p
));
729 /* If errors are seen, then just process it as a CALL_EXPR. */
731 return (enum gimplify_status
) gimplify_cilk_spawn (expr_p
);
734 if (fn_contains_cilk_spawn_p (cfun
)
735 && cilk_detect_spawn_and_unwrap (expr_p
)
737 return (enum gimplify_status
) gimplify_cilk_spawn (expr_p
);
739 /* DR 1030 says that we need to evaluate the elements of an
740 initializer-list in forward order even when it's used as arguments to
741 a constructor. So if the target wants to evaluate them in reverse
742 order and there's more than one argument other than 'this', gimplify
745 if (PUSH_ARGS_REVERSED
&& CALL_EXPR_LIST_INIT_P (*expr_p
)
746 && call_expr_nargs (*expr_p
) > 2)
748 int nargs
= call_expr_nargs (*expr_p
);
749 location_t loc
= EXPR_LOC_OR_LOC (*expr_p
, input_location
);
750 for (int i
= 1; i
< nargs
; ++i
)
752 enum gimplify_status t
753 = gimplify_arg (&CALL_EXPR_ARG (*expr_p
, i
), pre_p
, loc
);
761 if (TREE_OPERAND (*expr_p
, 0)
762 && (TREE_CODE (TREE_OPERAND (*expr_p
, 0)) == INIT_EXPR
763 || TREE_CODE (TREE_OPERAND (*expr_p
, 0)) == MODIFY_EXPR
))
765 expr_p
= &TREE_OPERAND (*expr_p
, 0);
766 code
= TREE_CODE (*expr_p
);
767 /* Avoid going through the INIT_EXPR case, which can
768 degrade INIT_EXPRs into AGGR_INIT_EXPRs. */
769 goto modify_expr_case
;
774 ret
= (enum gimplify_status
) c_gimplify_expr (expr_p
, pre_p
, post_p
);
778 /* Restore saved state. */
779 if (STATEMENT_CODE_P (code
))
780 current_stmt_tree ()->stmts_are_full_exprs_p
781 = saved_stmts_are_full_exprs_p
;
787 is_invisiref_parm (const_tree t
)
789 return ((TREE_CODE (t
) == PARM_DECL
|| TREE_CODE (t
) == RESULT_DECL
)
790 && DECL_BY_REFERENCE (t
));
793 /* Return true if the uid in both int tree maps are equal. */
796 cxx_int_tree_map_hasher::equal (cxx_int_tree_map
*a
, cxx_int_tree_map
*b
)
798 return (a
->uid
== b
->uid
);
801 /* Hash a UID in a cxx_int_tree_map. */
804 cxx_int_tree_map_hasher::hash (cxx_int_tree_map
*item
)
809 /* A stable comparison routine for use with splay trees and DECLs. */
812 splay_tree_compare_decl_uid (splay_tree_key xa
, splay_tree_key xb
)
817 return DECL_UID (a
) - DECL_UID (b
);
820 /* OpenMP context during genericization. */
822 struct cp_genericize_omp_taskreg
826 struct cp_genericize_omp_taskreg
*outer
;
827 splay_tree variables
;
830 /* Return true if genericization should try to determine if
831 DECL is firstprivate or shared within task regions. */
834 omp_var_to_track (tree decl
)
836 tree type
= TREE_TYPE (decl
);
837 if (is_invisiref_parm (decl
))
838 type
= TREE_TYPE (type
);
839 while (TREE_CODE (type
) == ARRAY_TYPE
)
840 type
= TREE_TYPE (type
);
841 if (type
== error_mark_node
|| !CLASS_TYPE_P (type
))
843 if (VAR_P (decl
) && DECL_THREAD_LOCAL_P (decl
))
845 if (cxx_omp_predetermined_sharing (decl
) != OMP_CLAUSE_DEFAULT_UNSPECIFIED
)
850 /* Note DECL use in OpenMP region OMP_CTX during genericization. */
853 omp_cxx_notice_variable (struct cp_genericize_omp_taskreg
*omp_ctx
, tree decl
)
855 splay_tree_node n
= splay_tree_lookup (omp_ctx
->variables
,
856 (splay_tree_key
) decl
);
859 int flags
= OMP_CLAUSE_DEFAULT_SHARED
;
861 omp_cxx_notice_variable (omp_ctx
->outer
, decl
);
862 if (!omp_ctx
->default_shared
)
864 struct cp_genericize_omp_taskreg
*octx
;
866 for (octx
= omp_ctx
->outer
; octx
; octx
= octx
->outer
)
868 n
= splay_tree_lookup (octx
->variables
, (splay_tree_key
) decl
);
869 if (n
&& n
->value
!= OMP_CLAUSE_DEFAULT_SHARED
)
871 flags
= OMP_CLAUSE_DEFAULT_FIRSTPRIVATE
;
874 if (octx
->is_parallel
)
878 && (TREE_CODE (decl
) == PARM_DECL
879 || (!(TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
880 && DECL_CONTEXT (decl
) == current_function_decl
)))
881 flags
= OMP_CLAUSE_DEFAULT_FIRSTPRIVATE
;
882 if (flags
== OMP_CLAUSE_DEFAULT_FIRSTPRIVATE
)
884 /* DECL is implicitly determined firstprivate in
885 the current task construct. Ensure copy ctor and
886 dtor are instantiated, because during gimplification
887 it will be already too late. */
888 tree type
= TREE_TYPE (decl
);
889 if (is_invisiref_parm (decl
))
890 type
= TREE_TYPE (type
);
891 while (TREE_CODE (type
) == ARRAY_TYPE
)
892 type
= TREE_TYPE (type
);
893 get_copy_ctor (type
, tf_none
);
894 get_dtor (type
, tf_none
);
897 splay_tree_insert (omp_ctx
->variables
, (splay_tree_key
) decl
, flags
);
901 /* Genericization context. */
903 struct cp_genericize_data
905 hash_set
<tree
> *p_set
;
906 vec
<tree
> bind_expr_stack
;
907 struct cp_genericize_omp_taskreg
*omp_ctx
;
911 /* Perform any pre-gimplification lowering of C++ front end trees to
915 cp_genericize_r (tree
*stmt_p
, int *walk_subtrees
, void *data
)
918 struct cp_genericize_data
*wtd
= (struct cp_genericize_data
*) data
;
919 hash_set
<tree
> *p_set
= wtd
->p_set
;
921 /* If in an OpenMP context, note var uses. */
922 if (__builtin_expect (wtd
->omp_ctx
!= NULL
, 0)
924 || TREE_CODE (stmt
) == PARM_DECL
925 || TREE_CODE (stmt
) == RESULT_DECL
)
926 && omp_var_to_track (stmt
))
927 omp_cxx_notice_variable (wtd
->omp_ctx
, stmt
);
929 if (is_invisiref_parm (stmt
)
930 /* Don't dereference parms in a thunk, pass the references through. */
931 && !(DECL_THUNK_P (current_function_decl
)
932 && TREE_CODE (stmt
) == PARM_DECL
))
934 *stmt_p
= convert_from_reference (stmt
);
939 /* Map block scope extern declarations to visible declarations with the
940 same name and type in outer scopes if any. */
941 if (cp_function_chain
->extern_decl_map
942 && VAR_OR_FUNCTION_DECL_P (stmt
)
943 && DECL_EXTERNAL (stmt
))
945 struct cxx_int_tree_map
*h
, in
;
946 in
.uid
= DECL_UID (stmt
);
947 h
= cp_function_chain
->extern_decl_map
->find_with_hash (&in
, in
.uid
);
956 /* Other than invisiref parms, don't walk the same tree twice. */
957 if (p_set
->contains (stmt
))
963 if (TREE_CODE (stmt
) == ADDR_EXPR
964 && is_invisiref_parm (TREE_OPERAND (stmt
, 0)))
966 /* If in an OpenMP context, note var uses. */
967 if (__builtin_expect (wtd
->omp_ctx
!= NULL
, 0)
968 && omp_var_to_track (TREE_OPERAND (stmt
, 0)))
969 omp_cxx_notice_variable (wtd
->omp_ctx
, TREE_OPERAND (stmt
, 0));
970 *stmt_p
= convert (TREE_TYPE (stmt
), TREE_OPERAND (stmt
, 0));
973 else if (TREE_CODE (stmt
) == RETURN_EXPR
974 && TREE_OPERAND (stmt
, 0)
975 && is_invisiref_parm (TREE_OPERAND (stmt
, 0)))
976 /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */
978 else if (TREE_CODE (stmt
) == OMP_CLAUSE
)
979 switch (OMP_CLAUSE_CODE (stmt
))
981 case OMP_CLAUSE_LASTPRIVATE
:
982 /* Don't dereference an invisiref in OpenMP clauses. */
983 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt
)))
986 if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt
))
987 cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt
),
988 cp_genericize_r
, data
, NULL
);
991 case OMP_CLAUSE_PRIVATE
:
992 /* Don't dereference an invisiref in OpenMP clauses. */
993 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt
)))
995 else if (wtd
->omp_ctx
!= NULL
)
997 /* Private clause doesn't cause any references to the
998 var in outer contexts, avoid calling
999 omp_cxx_notice_variable for it. */
1000 struct cp_genericize_omp_taskreg
*old
= wtd
->omp_ctx
;
1001 wtd
->omp_ctx
= NULL
;
1002 cp_walk_tree (&OMP_CLAUSE_DECL (stmt
), cp_genericize_r
,
1008 case OMP_CLAUSE_SHARED
:
1009 case OMP_CLAUSE_FIRSTPRIVATE
:
1010 case OMP_CLAUSE_COPYIN
:
1011 case OMP_CLAUSE_COPYPRIVATE
:
1012 /* Don't dereference an invisiref in OpenMP clauses. */
1013 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt
)))
1016 case OMP_CLAUSE_REDUCTION
:
1017 /* Don't dereference an invisiref in reduction clause's
1018 OMP_CLAUSE_DECL either. OMP_CLAUSE_REDUCTION_{INIT,MERGE}
1019 still needs to be genericized. */
1020 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt
)))
1023 if (OMP_CLAUSE_REDUCTION_INIT (stmt
))
1024 cp_walk_tree (&OMP_CLAUSE_REDUCTION_INIT (stmt
),
1025 cp_genericize_r
, data
, NULL
);
1026 if (OMP_CLAUSE_REDUCTION_MERGE (stmt
))
1027 cp_walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (stmt
),
1028 cp_genericize_r
, data
, NULL
);
1034 else if (IS_TYPE_OR_DECL_P (stmt
))
1037 /* Due to the way voidify_wrapper_expr is written, we don't get a chance
1038 to lower this construct before scanning it, so we need to lower these
1039 before doing anything else. */
1040 else if (TREE_CODE (stmt
) == CLEANUP_STMT
)
1041 *stmt_p
= build2_loc (EXPR_LOCATION (stmt
),
1042 CLEANUP_EH_ONLY (stmt
) ? TRY_CATCH_EXPR
1045 CLEANUP_BODY (stmt
),
1046 CLEANUP_EXPR (stmt
));
1048 else if (TREE_CODE (stmt
) == IF_STMT
)
1050 genericize_if_stmt (stmt_p
);
1051 /* *stmt_p has changed, tail recurse to handle it again. */
1052 return cp_genericize_r (stmt_p
, walk_subtrees
, data
);
1055 /* COND_EXPR might have incompatible types in branches if one or both
1056 arms are bitfields. Fix it up now. */
1057 else if (TREE_CODE (stmt
) == COND_EXPR
)
1060 = (TREE_OPERAND (stmt
, 1)
1061 ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt
, 1))
1064 = (TREE_OPERAND (stmt
, 2)
1065 ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt
, 2))
1068 && !useless_type_conversion_p (TREE_TYPE (stmt
),
1069 TREE_TYPE (TREE_OPERAND (stmt
, 1))))
1071 TREE_OPERAND (stmt
, 1)
1072 = fold_convert (type_left
, TREE_OPERAND (stmt
, 1));
1073 gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt
),
1077 && !useless_type_conversion_p (TREE_TYPE (stmt
),
1078 TREE_TYPE (TREE_OPERAND (stmt
, 2))))
1080 TREE_OPERAND (stmt
, 2)
1081 = fold_convert (type_right
, TREE_OPERAND (stmt
, 2));
1082 gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt
),
1087 else if (TREE_CODE (stmt
) == BIND_EXPR
)
1089 if (__builtin_expect (wtd
->omp_ctx
!= NULL
, 0))
1092 for (decl
= BIND_EXPR_VARS (stmt
); decl
; decl
= DECL_CHAIN (decl
))
1094 && !DECL_EXTERNAL (decl
)
1095 && omp_var_to_track (decl
))
1098 = splay_tree_lookup (wtd
->omp_ctx
->variables
,
1099 (splay_tree_key
) decl
);
1101 splay_tree_insert (wtd
->omp_ctx
->variables
,
1102 (splay_tree_key
) decl
,
1104 ? OMP_CLAUSE_DEFAULT_SHARED
1105 : OMP_CLAUSE_DEFAULT_PRIVATE
);
1108 wtd
->bind_expr_stack
.safe_push (stmt
);
1109 cp_walk_tree (&BIND_EXPR_BODY (stmt
),
1110 cp_genericize_r
, data
, NULL
);
1111 wtd
->bind_expr_stack
.pop ();
1114 else if (TREE_CODE (stmt
) == USING_STMT
)
1116 tree block
= NULL_TREE
;
1118 /* Get the innermost inclosing GIMPLE_BIND that has a non NULL
1119 BLOCK, and append an IMPORTED_DECL to its
1120 BLOCK_VARS chained list. */
1121 if (wtd
->bind_expr_stack
.exists ())
1124 for (i
= wtd
->bind_expr_stack
.length () - 1; i
>= 0; i
--)
1125 if ((block
= BIND_EXPR_BLOCK (wtd
->bind_expr_stack
[i
])))
1130 tree using_directive
;
1131 gcc_assert (TREE_OPERAND (stmt
, 0));
1133 using_directive
= make_node (IMPORTED_DECL
);
1134 TREE_TYPE (using_directive
) = void_type_node
;
1136 IMPORTED_DECL_ASSOCIATED_DECL (using_directive
)
1137 = TREE_OPERAND (stmt
, 0);
1138 DECL_CHAIN (using_directive
) = BLOCK_VARS (block
);
1139 BLOCK_VARS (block
) = using_directive
;
1141 /* The USING_STMT won't appear in GENERIC. */
1142 *stmt_p
= build1 (NOP_EXPR
, void_type_node
, integer_zero_node
);
1146 else if (TREE_CODE (stmt
) == DECL_EXPR
1147 && TREE_CODE (DECL_EXPR_DECL (stmt
)) == USING_DECL
)
1149 /* Using decls inside DECL_EXPRs are just dropped on the floor. */
1150 *stmt_p
= build1 (NOP_EXPR
, void_type_node
, integer_zero_node
);
1153 else if (TREE_CODE (stmt
) == OMP_PARALLEL
|| TREE_CODE (stmt
) == OMP_TASK
)
1155 struct cp_genericize_omp_taskreg omp_ctx
;
1160 cp_walk_tree (&OMP_CLAUSES (stmt
), cp_genericize_r
, data
, NULL
);
1161 omp_ctx
.is_parallel
= TREE_CODE (stmt
) == OMP_PARALLEL
;
1162 omp_ctx
.default_shared
= omp_ctx
.is_parallel
;
1163 omp_ctx
.outer
= wtd
->omp_ctx
;
1164 omp_ctx
.variables
= splay_tree_new (splay_tree_compare_decl_uid
, 0, 0);
1165 wtd
->omp_ctx
= &omp_ctx
;
1166 for (c
= OMP_CLAUSES (stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
1167 switch (OMP_CLAUSE_CODE (c
))
1169 case OMP_CLAUSE_SHARED
:
1170 case OMP_CLAUSE_PRIVATE
:
1171 case OMP_CLAUSE_FIRSTPRIVATE
:
1172 case OMP_CLAUSE_LASTPRIVATE
:
1173 decl
= OMP_CLAUSE_DECL (c
);
1174 if (decl
== error_mark_node
|| !omp_var_to_track (decl
))
1176 n
= splay_tree_lookup (omp_ctx
.variables
, (splay_tree_key
) decl
);
1179 splay_tree_insert (omp_ctx
.variables
, (splay_tree_key
) decl
,
1180 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
1181 ? OMP_CLAUSE_DEFAULT_SHARED
1182 : OMP_CLAUSE_DEFAULT_PRIVATE
);
1183 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_PRIVATE
1185 omp_cxx_notice_variable (omp_ctx
.outer
, decl
);
1187 case OMP_CLAUSE_DEFAULT
:
1188 if (OMP_CLAUSE_DEFAULT_KIND (c
) == OMP_CLAUSE_DEFAULT_SHARED
)
1189 omp_ctx
.default_shared
= true;
1193 cp_walk_tree (&OMP_BODY (stmt
), cp_genericize_r
, data
, NULL
);
1194 wtd
->omp_ctx
= omp_ctx
.outer
;
1195 splay_tree_delete (omp_ctx
.variables
);
1197 else if (TREE_CODE (stmt
) == TRY_BLOCK
)
1200 tree try_block
= wtd
->try_block
;
1201 wtd
->try_block
= stmt
;
1202 cp_walk_tree (&TRY_STMTS (stmt
), cp_genericize_r
, data
, NULL
);
1203 wtd
->try_block
= try_block
;
1204 cp_walk_tree (&TRY_HANDLERS (stmt
), cp_genericize_r
, data
, NULL
);
1206 else if (TREE_CODE (stmt
) == MUST_NOT_THROW_EXPR
)
1208 /* MUST_NOT_THROW_COND might be something else with TM. */
1209 if (MUST_NOT_THROW_COND (stmt
) == NULL_TREE
)
1212 tree try_block
= wtd
->try_block
;
1213 wtd
->try_block
= stmt
;
1214 cp_walk_tree (&TREE_OPERAND (stmt
, 0), cp_genericize_r
, data
, NULL
);
1215 wtd
->try_block
= try_block
;
1218 else if (TREE_CODE (stmt
) == THROW_EXPR
)
1220 location_t loc
= location_of (stmt
);
1221 if (TREE_NO_WARNING (stmt
))
1223 else if (wtd
->try_block
)
1225 if (TREE_CODE (wtd
->try_block
) == MUST_NOT_THROW_EXPR
1226 && warning_at (loc
, OPT_Wterminate
,
1227 "throw will always call terminate()")
1228 && cxx_dialect
>= cxx11
1229 && DECL_DESTRUCTOR_P (current_function_decl
))
1230 inform (loc
, "in C++11 destructors default to noexcept");
1234 if (warn_cxx11_compat
&& cxx_dialect
< cxx11
1235 && DECL_DESTRUCTOR_P (current_function_decl
)
1236 && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl
))
1238 && (get_defaulted_eh_spec (current_function_decl
)
1239 == empty_except_spec
))
1240 warning_at (loc
, OPT_Wc__11_compat
,
1241 "in C++11 this throw will terminate because "
1242 "destructors default to noexcept");
1245 else if (TREE_CODE (stmt
) == CONVERT_EXPR
)
1246 gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt
));
1247 else if (TREE_CODE (stmt
) == FOR_STMT
)
1248 genericize_for_stmt (stmt_p
, walk_subtrees
, data
);
1249 else if (TREE_CODE (stmt
) == WHILE_STMT
)
1250 genericize_while_stmt (stmt_p
, walk_subtrees
, data
);
1251 else if (TREE_CODE (stmt
) == DO_STMT
)
1252 genericize_do_stmt (stmt_p
, walk_subtrees
, data
);
1253 else if (TREE_CODE (stmt
) == SWITCH_STMT
)
1254 genericize_switch_stmt (stmt_p
, walk_subtrees
, data
);
1255 else if (TREE_CODE (stmt
) == CONTINUE_STMT
)
1256 genericize_continue_stmt (stmt_p
);
1257 else if (TREE_CODE (stmt
) == BREAK_STMT
)
1258 genericize_break_stmt (stmt_p
);
1259 else if (TREE_CODE (stmt
) == OMP_FOR
1260 || TREE_CODE (stmt
) == OMP_SIMD
1261 || TREE_CODE (stmt
) == OMP_DISTRIBUTE
)
1262 genericize_omp_for_stmt (stmt_p
, walk_subtrees
, data
);
1263 else if (TREE_CODE (stmt
) == SIZEOF_EXPR
)
1265 if (SIZEOF_EXPR_TYPE_P (stmt
))
1267 = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (stmt
, 0)),
1268 SIZEOF_EXPR
, false);
1269 else if (TYPE_P (TREE_OPERAND (stmt
, 0)))
1270 *stmt_p
= cxx_sizeof_or_alignof_type (TREE_OPERAND (stmt
, 0),
1271 SIZEOF_EXPR
, false);
1273 *stmt_p
= cxx_sizeof_or_alignof_expr (TREE_OPERAND (stmt
, 0),
1274 SIZEOF_EXPR
, false);
1275 if (*stmt_p
== error_mark_node
)
1276 *stmt_p
= size_one_node
;
1279 else if (flag_sanitize
1280 & (SANITIZE_NULL
| SANITIZE_ALIGNMENT
| SANITIZE_VPTR
))
1282 if ((flag_sanitize
& (SANITIZE_NULL
| SANITIZE_ALIGNMENT
))
1283 && TREE_CODE (stmt
) == NOP_EXPR
1284 && TREE_CODE (TREE_TYPE (stmt
)) == REFERENCE_TYPE
)
1285 ubsan_maybe_instrument_reference (stmt
);
1286 else if (TREE_CODE (stmt
) == CALL_EXPR
)
1288 tree fn
= CALL_EXPR_FN (stmt
);
1290 && !error_operand_p (fn
)
1291 && POINTER_TYPE_P (TREE_TYPE (fn
))
1292 && TREE_CODE (TREE_TYPE (TREE_TYPE (fn
))) == METHOD_TYPE
)
1295 = TREE_CODE (fn
) == ADDR_EXPR
1296 && TREE_CODE (TREE_OPERAND (fn
, 0)) == FUNCTION_DECL
1297 && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn
, 0));
1298 if (flag_sanitize
& (SANITIZE_NULL
| SANITIZE_ALIGNMENT
))
1299 ubsan_maybe_instrument_member_call (stmt
, is_ctor
);
1300 if ((flag_sanitize
& SANITIZE_VPTR
) && !is_ctor
)
1301 cp_ubsan_maybe_instrument_member_call (stmt
);
1306 p_set
->add (*stmt_p
);
1311 /* Lower C++ front end trees to GENERIC in T_P. */
1314 cp_genericize_tree (tree
* t_p
)
1316 struct cp_genericize_data wtd
;
1318 wtd
.p_set
= new hash_set
<tree
>;
1319 wtd
.bind_expr_stack
.create (0);
1321 wtd
.try_block
= NULL_TREE
;
1322 cp_walk_tree (t_p
, cp_genericize_r
, &wtd
, NULL
);
1324 wtd
.bind_expr_stack
.release ();
1325 if (flag_sanitize
& SANITIZE_VPTR
)
1326 cp_ubsan_instrument_member_accesses (t_p
);
1329 /* If a function that should end with a return in non-void
1330 function doesn't obviously end with return, add ubsan
1331 instrumentation code to verify it at runtime. */
1334 cp_ubsan_maybe_instrument_return (tree fndecl
)
1336 if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl
)))
1337 || DECL_CONSTRUCTOR_P (fndecl
)
1338 || DECL_DESTRUCTOR_P (fndecl
)
1339 || !targetm
.warn_func_return (fndecl
))
1342 tree t
= DECL_SAVED_TREE (fndecl
);
1345 switch (TREE_CODE (t
))
1348 t
= BIND_EXPR_BODY (t
);
1350 case TRY_FINALLY_EXPR
:
1351 t
= TREE_OPERAND (t
, 0);
1353 case STATEMENT_LIST
:
1355 tree_stmt_iterator i
= tsi_last (t
);
1372 t
= DECL_SAVED_TREE (fndecl
);
1373 if (TREE_CODE (t
) == BIND_EXPR
1374 && TREE_CODE (BIND_EXPR_BODY (t
)) == STATEMENT_LIST
)
1376 tree_stmt_iterator i
= tsi_last (BIND_EXPR_BODY (t
));
1377 t
= ubsan_instrument_return (DECL_SOURCE_LOCATION (fndecl
));
1378 tsi_link_after (&i
, t
, TSI_NEW_STMT
);
1383 cp_genericize (tree fndecl
)
1387 /* Fix up the types of parms passed by invisible reference. */
1388 for (t
= DECL_ARGUMENTS (fndecl
); t
; t
= DECL_CHAIN (t
))
1389 if (TREE_ADDRESSABLE (TREE_TYPE (t
)))
1391 /* If a function's arguments are copied to create a thunk,
1392 then DECL_BY_REFERENCE will be set -- but the type of the
1393 argument will be a pointer type, so we will never get
1395 gcc_assert (!DECL_BY_REFERENCE (t
));
1396 gcc_assert (DECL_ARG_TYPE (t
) != TREE_TYPE (t
));
1397 TREE_TYPE (t
) = DECL_ARG_TYPE (t
);
1398 DECL_BY_REFERENCE (t
) = 1;
1399 TREE_ADDRESSABLE (t
) = 0;
1403 /* Do the same for the return value. */
1404 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl
))))
1406 t
= DECL_RESULT (fndecl
);
1407 TREE_TYPE (t
) = build_reference_type (TREE_TYPE (t
));
1408 DECL_BY_REFERENCE (t
) = 1;
1409 TREE_ADDRESSABLE (t
) = 0;
1413 /* Adjust DECL_VALUE_EXPR of the original var. */
1414 tree outer
= outer_curly_brace_block (current_function_decl
);
1418 for (var
= BLOCK_VARS (outer
); var
; var
= DECL_CHAIN (var
))
1419 if (DECL_NAME (t
) == DECL_NAME (var
)
1420 && DECL_HAS_VALUE_EXPR_P (var
)
1421 && DECL_VALUE_EXPR (var
) == t
)
1423 tree val
= convert_from_reference (t
);
1424 SET_DECL_VALUE_EXPR (var
, val
);
1430 /* If we're a clone, the body is already GIMPLE. */
1431 if (DECL_CLONED_FUNCTION_P (fndecl
))
1434 /* Expand all the array notations here. */
1436 && contains_array_notation_expr (DECL_SAVED_TREE (fndecl
)))
1437 DECL_SAVED_TREE (fndecl
) =
1438 expand_array_notation_exprs (DECL_SAVED_TREE (fndecl
));
1440 /* We do want to see every occurrence of the parms, so we can't just use
1441 walk_tree's hash functionality. */
1442 cp_genericize_tree (&DECL_SAVED_TREE (fndecl
));
1444 if (flag_sanitize
& SANITIZE_RETURN
1445 && do_ubsan_in_current_function ())
1446 cp_ubsan_maybe_instrument_return (fndecl
);
1448 /* Do everything else. */
1449 c_genericize (fndecl
);
1451 gcc_assert (bc_label
[bc_break
] == NULL
);
1452 gcc_assert (bc_label
[bc_continue
] == NULL
);
1455 /* Build code to apply FN to each member of ARG1 and ARG2. FN may be
1456 NULL if there is in fact nothing to do. ARG2 may be null if FN
1457 actually only takes one argument. */
1460 cxx_omp_clause_apply_fn (tree fn
, tree arg1
, tree arg2
)
1462 tree defparm
, parm
, t
;
1470 nargs
= list_length (DECL_ARGUMENTS (fn
));
1471 argarray
= XALLOCAVEC (tree
, nargs
);
1473 defparm
= TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn
)));
1475 defparm
= TREE_CHAIN (defparm
);
1477 if (TREE_CODE (TREE_TYPE (arg1
)) == ARRAY_TYPE
)
1479 tree inner_type
= TREE_TYPE (arg1
);
1480 tree start1
, end1
, p1
;
1481 tree start2
= NULL
, p2
= NULL
;
1482 tree ret
= NULL
, lab
;
1488 inner_type
= TREE_TYPE (inner_type
);
1489 start1
= build4 (ARRAY_REF
, inner_type
, start1
,
1490 size_zero_node
, NULL
, NULL
);
1492 start2
= build4 (ARRAY_REF
, inner_type
, start2
,
1493 size_zero_node
, NULL
, NULL
);
1495 while (TREE_CODE (inner_type
) == ARRAY_TYPE
);
1496 start1
= build_fold_addr_expr_loc (input_location
, start1
);
1498 start2
= build_fold_addr_expr_loc (input_location
, start2
);
1500 end1
= TYPE_SIZE_UNIT (TREE_TYPE (arg1
));
1501 end1
= fold_build_pointer_plus (start1
, end1
);
1503 p1
= create_tmp_var (TREE_TYPE (start1
));
1504 t
= build2 (MODIFY_EXPR
, TREE_TYPE (p1
), p1
, start1
);
1505 append_to_statement_list (t
, &ret
);
1509 p2
= create_tmp_var (TREE_TYPE (start2
));
1510 t
= build2 (MODIFY_EXPR
, TREE_TYPE (p2
), p2
, start2
);
1511 append_to_statement_list (t
, &ret
);
1514 lab
= create_artificial_label (input_location
);
1515 t
= build1 (LABEL_EXPR
, void_type_node
, lab
);
1516 append_to_statement_list (t
, &ret
);
1521 /* Handle default arguments. */
1522 for (parm
= defparm
; parm
&& parm
!= void_list_node
;
1523 parm
= TREE_CHAIN (parm
), i
++)
1524 argarray
[i
] = convert_default_arg (TREE_VALUE (parm
),
1525 TREE_PURPOSE (parm
), fn
, i
,
1526 tf_warning_or_error
);
1527 t
= build_call_a (fn
, i
, argarray
);
1528 t
= fold_convert (void_type_node
, t
);
1529 t
= fold_build_cleanup_point_expr (TREE_TYPE (t
), t
);
1530 append_to_statement_list (t
, &ret
);
1532 t
= fold_build_pointer_plus (p1
, TYPE_SIZE_UNIT (inner_type
));
1533 t
= build2 (MODIFY_EXPR
, TREE_TYPE (p1
), p1
, t
);
1534 append_to_statement_list (t
, &ret
);
1538 t
= fold_build_pointer_plus (p2
, TYPE_SIZE_UNIT (inner_type
));
1539 t
= build2 (MODIFY_EXPR
, TREE_TYPE (p2
), p2
, t
);
1540 append_to_statement_list (t
, &ret
);
1543 t
= build2 (NE_EXPR
, boolean_type_node
, p1
, end1
);
1544 t
= build3 (COND_EXPR
, void_type_node
, t
, build_and_jump (&lab
), NULL
);
1545 append_to_statement_list (t
, &ret
);
1551 argarray
[i
++] = build_fold_addr_expr_loc (input_location
, arg1
);
1553 argarray
[i
++] = build_fold_addr_expr_loc (input_location
, arg2
);
1554 /* Handle default arguments. */
1555 for (parm
= defparm
; parm
&& parm
!= void_list_node
;
1556 parm
= TREE_CHAIN (parm
), i
++)
1557 argarray
[i
] = convert_default_arg (TREE_VALUE (parm
),
1558 TREE_PURPOSE (parm
),
1559 fn
, i
, tf_warning_or_error
);
1560 t
= build_call_a (fn
, i
, argarray
);
1561 t
= fold_convert (void_type_node
, t
);
1562 return fold_build_cleanup_point_expr (TREE_TYPE (t
), t
);
1566 /* Return code to initialize DECL with its default constructor, or
1567 NULL if there's nothing to do. */
1570 cxx_omp_clause_default_ctor (tree clause
, tree decl
, tree
/*outer*/)
1572 tree info
= CP_OMP_CLAUSE_INFO (clause
);
1576 ret
= cxx_omp_clause_apply_fn (TREE_VEC_ELT (info
, 0), decl
, NULL
);
1581 /* Return code to initialize DST with a copy constructor from SRC. */
1584 cxx_omp_clause_copy_ctor (tree clause
, tree dst
, tree src
)
1586 tree info
= CP_OMP_CLAUSE_INFO (clause
);
1590 ret
= cxx_omp_clause_apply_fn (TREE_VEC_ELT (info
, 0), dst
, src
);
1592 ret
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
1597 /* Similarly, except use an assignment operator instead. */
1600 cxx_omp_clause_assign_op (tree clause
, tree dst
, tree src
)
1602 tree info
= CP_OMP_CLAUSE_INFO (clause
);
1606 ret
= cxx_omp_clause_apply_fn (TREE_VEC_ELT (info
, 2), dst
, src
);
1608 ret
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
1613 /* Return code to destroy DECL. */
1616 cxx_omp_clause_dtor (tree clause
, tree decl
)
1618 tree info
= CP_OMP_CLAUSE_INFO (clause
);
1622 ret
= cxx_omp_clause_apply_fn (TREE_VEC_ELT (info
, 1), decl
, NULL
);
1627 /* True if OpenMP should privatize what this DECL points to rather
1628 than the DECL itself. */
1631 cxx_omp_privatize_by_reference (const_tree decl
)
1633 return (TREE_CODE (TREE_TYPE (decl
)) == REFERENCE_TYPE
1634 || is_invisiref_parm (decl
));
1637 /* Return true if DECL is const qualified var having no mutable member. */
1639 cxx_omp_const_qual_no_mutable (tree decl
)
1641 tree type
= TREE_TYPE (decl
);
1642 if (TREE_CODE (type
) == REFERENCE_TYPE
)
1644 if (!is_invisiref_parm (decl
))
1646 type
= TREE_TYPE (type
);
1648 if (TREE_CODE (decl
) == RESULT_DECL
&& DECL_NAME (decl
))
1650 /* NVR doesn't preserve const qualification of the
1652 tree outer
= outer_curly_brace_block (current_function_decl
);
1656 for (var
= BLOCK_VARS (outer
); var
; var
= DECL_CHAIN (var
))
1657 if (DECL_NAME (decl
) == DECL_NAME (var
)
1658 && (TYPE_MAIN_VARIANT (type
)
1659 == TYPE_MAIN_VARIANT (TREE_TYPE (var
))))
1661 if (TYPE_READONLY (TREE_TYPE (var
)))
1662 type
= TREE_TYPE (var
);
1668 if (type
== error_mark_node
)
1671 /* Variables with const-qualified type having no mutable member
1672 are predetermined shared. */
1673 if (TYPE_READONLY (type
) && !cp_has_mutable_p (type
))
1679 /* True if OpenMP sharing attribute of DECL is predetermined. */
1681 enum omp_clause_default_kind
1682 cxx_omp_predetermined_sharing (tree decl
)
1684 /* Static data members are predetermined shared. */
1685 if (TREE_STATIC (decl
))
1687 tree ctx
= CP_DECL_CONTEXT (decl
);
1688 if (TYPE_P (ctx
) && MAYBE_CLASS_TYPE_P (ctx
))
1689 return OMP_CLAUSE_DEFAULT_SHARED
;
1692 /* Const qualified vars having no mutable member are predetermined
1694 if (cxx_omp_const_qual_no_mutable (decl
))
1695 return OMP_CLAUSE_DEFAULT_SHARED
;
1697 return OMP_CLAUSE_DEFAULT_UNSPECIFIED
;
1700 /* Finalize an implicitly determined clause. */
1703 cxx_omp_finish_clause (tree c
, gimple_seq
*)
1705 tree decl
, inner_type
;
1706 bool make_shared
= false;
1708 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_FIRSTPRIVATE
)
1711 decl
= OMP_CLAUSE_DECL (c
);
1712 decl
= require_complete_type (decl
);
1713 inner_type
= TREE_TYPE (decl
);
1714 if (decl
== error_mark_node
)
1716 else if (TREE_CODE (TREE_TYPE (decl
)) == REFERENCE_TYPE
)
1718 if (is_invisiref_parm (decl
))
1719 inner_type
= TREE_TYPE (inner_type
);
1722 error ("%qE implicitly determined as %<firstprivate%> has reference type",
1728 /* We're interested in the base element, not arrays. */
1729 while (TREE_CODE (inner_type
) == ARRAY_TYPE
)
1730 inner_type
= TREE_TYPE (inner_type
);
1732 /* Check for special function availability by building a call to one.
1733 Save the results, because later we won't be in the right context
1734 for making these queries. */
1736 && CLASS_TYPE_P (inner_type
)
1737 && cxx_omp_create_clause_info (c
, inner_type
, false, true, false, true))
1741 OMP_CLAUSE_CODE (c
) = OMP_CLAUSE_SHARED
;