138fd1498Szrj /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
238fd1498Szrj
338fd1498Szrj Copyright (C) 2002-2018 Free Software Foundation, Inc.
438fd1498Szrj Contributed by Jason Merrill <jason@redhat.com>
538fd1498Szrj
638fd1498Szrj This file is part of GCC.
738fd1498Szrj
838fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
938fd1498Szrj the terms of the GNU General Public License as published by the Free
1038fd1498Szrj Software Foundation; either version 3, or (at your option) any later
1138fd1498Szrj version.
1238fd1498Szrj
1338fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1438fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1538fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1638fd1498Szrj for more details.
1738fd1498Szrj
1838fd1498Szrj You should have received a copy of the GNU General Public License
1938fd1498Szrj along with GCC; see the file COPYING3. If not see
2038fd1498Szrj <http://www.gnu.org/licenses/>. */
2138fd1498Szrj
2238fd1498Szrj #include "config.h"
2338fd1498Szrj #include "system.h"
2438fd1498Szrj #include "coretypes.h"
2538fd1498Szrj #include "target.h"
2638fd1498Szrj #include "basic-block.h"
2738fd1498Szrj #include "cp-tree.h"
2838fd1498Szrj #include "gimple.h"
2938fd1498Szrj #include "predict.h"
3038fd1498Szrj #include "stor-layout.h"
3138fd1498Szrj #include "tree-iterator.h"
3238fd1498Szrj #include "gimplify.h"
3338fd1498Szrj #include "c-family/c-ubsan.h"
3438fd1498Szrj #include "stringpool.h"
3538fd1498Szrj #include "attribs.h"
3638fd1498Szrj #include "asan.h"
3738fd1498Szrj
3838fd1498Szrj /* Forward declarations. */
3938fd1498Szrj
4038fd1498Szrj static tree cp_genericize_r (tree *, int *, void *);
4138fd1498Szrj static tree cp_fold_r (tree *, int *, void *);
4238fd1498Szrj static void cp_genericize_tree (tree*, bool);
4338fd1498Szrj static tree cp_fold (tree);
4438fd1498Szrj
4538fd1498Szrj /* Local declarations. */
4638fd1498Szrj
4738fd1498Szrj enum bc_t { bc_break = 0, bc_continue = 1 };
4838fd1498Szrj
4938fd1498Szrj /* Stack of labels which are targets for "break" or "continue",
5038fd1498Szrj linked through TREE_CHAIN. */
5138fd1498Szrj static tree bc_label[2];
5238fd1498Szrj
5338fd1498Szrj /* Begin a scope which can be exited by a break or continue statement. BC
5438fd1498Szrj indicates which.
5538fd1498Szrj
5638fd1498Szrj Just creates a label with location LOCATION and pushes it into the current
5738fd1498Szrj context. */
5838fd1498Szrj
5938fd1498Szrj static tree
begin_bc_block(enum bc_t bc,location_t location)6038fd1498Szrj begin_bc_block (enum bc_t bc, location_t location)
6138fd1498Szrj {
6238fd1498Szrj tree label = create_artificial_label (location);
6338fd1498Szrj DECL_CHAIN (label) = bc_label[bc];
6438fd1498Szrj bc_label[bc] = label;
6538fd1498Szrj if (bc == bc_break)
6638fd1498Szrj LABEL_DECL_BREAK (label) = true;
6738fd1498Szrj else
6838fd1498Szrj LABEL_DECL_CONTINUE (label) = true;
6938fd1498Szrj return label;
7038fd1498Szrj }
7138fd1498Szrj
7238fd1498Szrj /* Finish a scope which can be exited by a break or continue statement.
7338fd1498Szrj LABEL was returned from the most recent call to begin_bc_block. BLOCK is
7438fd1498Szrj an expression for the contents of the scope.
7538fd1498Szrj
7638fd1498Szrj If we saw a break (or continue) in the scope, append a LABEL_EXPR to
7738fd1498Szrj BLOCK. Otherwise, just forget the label. */
7838fd1498Szrj
7938fd1498Szrj static void
finish_bc_block(tree * block,enum bc_t bc,tree label)8038fd1498Szrj finish_bc_block (tree *block, enum bc_t bc, tree label)
8138fd1498Szrj {
8238fd1498Szrj gcc_assert (label == bc_label[bc]);
8338fd1498Szrj
8438fd1498Szrj if (TREE_USED (label))
8538fd1498Szrj append_to_statement_list (build1 (LABEL_EXPR, void_type_node, label),
8638fd1498Szrj block);
8738fd1498Szrj
8838fd1498Szrj bc_label[bc] = DECL_CHAIN (label);
8938fd1498Szrj DECL_CHAIN (label) = NULL_TREE;
9038fd1498Szrj }
9138fd1498Szrj
9238fd1498Szrj /* Get the LABEL_EXPR to represent a break or continue statement
9338fd1498Szrj in the current block scope. BC indicates which. */
9438fd1498Szrj
9538fd1498Szrj static tree
get_bc_label(enum bc_t bc)9638fd1498Szrj get_bc_label (enum bc_t bc)
9738fd1498Szrj {
9838fd1498Szrj tree label = bc_label[bc];
9938fd1498Szrj
10038fd1498Szrj /* Mark the label used for finish_bc_block. */
10138fd1498Szrj TREE_USED (label) = 1;
10238fd1498Szrj return label;
10338fd1498Szrj }
10438fd1498Szrj
10538fd1498Szrj /* Genericize a TRY_BLOCK. */
10638fd1498Szrj
10738fd1498Szrj static void
genericize_try_block(tree * stmt_p)10838fd1498Szrj genericize_try_block (tree *stmt_p)
10938fd1498Szrj {
11038fd1498Szrj tree body = TRY_STMTS (*stmt_p);
11138fd1498Szrj tree cleanup = TRY_HANDLERS (*stmt_p);
11238fd1498Szrj
11338fd1498Szrj *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
11438fd1498Szrj }
11538fd1498Szrj
11638fd1498Szrj /* Genericize a HANDLER by converting to a CATCH_EXPR. */
11738fd1498Szrj
11838fd1498Szrj static void
genericize_catch_block(tree * stmt_p)11938fd1498Szrj genericize_catch_block (tree *stmt_p)
12038fd1498Szrj {
12138fd1498Szrj tree type = HANDLER_TYPE (*stmt_p);
12238fd1498Szrj tree body = HANDLER_BODY (*stmt_p);
12338fd1498Szrj
12438fd1498Szrj /* FIXME should the caught type go in TREE_TYPE? */
12538fd1498Szrj *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
12638fd1498Szrj }
12738fd1498Szrj
12838fd1498Szrj /* A terser interface for building a representation of an exception
12938fd1498Szrj specification. */
13038fd1498Szrj
13138fd1498Szrj static tree
build_gimple_eh_filter_tree(tree body,tree allowed,tree failure)13238fd1498Szrj build_gimple_eh_filter_tree (tree body, tree allowed, tree failure)
13338fd1498Szrj {
13438fd1498Szrj tree t;
13538fd1498Szrj
13638fd1498Szrj /* FIXME should the allowed types go in TREE_TYPE? */
13738fd1498Szrj t = build2 (EH_FILTER_EXPR, void_type_node, allowed, NULL_TREE);
13838fd1498Szrj append_to_statement_list (failure, &EH_FILTER_FAILURE (t));
13938fd1498Szrj
14038fd1498Szrj t = build2 (TRY_CATCH_EXPR, void_type_node, NULL_TREE, t);
14138fd1498Szrj append_to_statement_list (body, &TREE_OPERAND (t, 0));
14238fd1498Szrj
14338fd1498Szrj return t;
14438fd1498Szrj }
14538fd1498Szrj
14638fd1498Szrj /* Genericize an EH_SPEC_BLOCK by converting it to a
14738fd1498Szrj TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
14838fd1498Szrj
14938fd1498Szrj static void
genericize_eh_spec_block(tree * stmt_p)15038fd1498Szrj genericize_eh_spec_block (tree *stmt_p)
15138fd1498Szrj {
15238fd1498Szrj tree body = EH_SPEC_STMTS (*stmt_p);
15338fd1498Szrj tree allowed = EH_SPEC_RAISES (*stmt_p);
15438fd1498Szrj tree failure = build_call_n (call_unexpected_fn, 1, build_exc_ptr ());
15538fd1498Szrj
15638fd1498Szrj *stmt_p = build_gimple_eh_filter_tree (body, allowed, failure);
15738fd1498Szrj TREE_NO_WARNING (*stmt_p) = true;
15838fd1498Szrj TREE_NO_WARNING (TREE_OPERAND (*stmt_p, 1)) = true;
15938fd1498Szrj }
16038fd1498Szrj
16138fd1498Szrj /* Genericize an IF_STMT by turning it into a COND_EXPR. */
16238fd1498Szrj
16338fd1498Szrj static void
genericize_if_stmt(tree * stmt_p)16438fd1498Szrj genericize_if_stmt (tree *stmt_p)
16538fd1498Szrj {
16638fd1498Szrj tree stmt, cond, then_, else_;
16738fd1498Szrj location_t locus = EXPR_LOCATION (*stmt_p);
16838fd1498Szrj
16938fd1498Szrj stmt = *stmt_p;
17038fd1498Szrj cond = IF_COND (stmt);
17138fd1498Szrj then_ = THEN_CLAUSE (stmt);
17238fd1498Szrj else_ = ELSE_CLAUSE (stmt);
17338fd1498Szrj
17438fd1498Szrj if (!then_)
17538fd1498Szrj then_ = build_empty_stmt (locus);
17638fd1498Szrj if (!else_)
17738fd1498Szrj else_ = build_empty_stmt (locus);
17838fd1498Szrj
17938fd1498Szrj if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
18038fd1498Szrj stmt = then_;
18138fd1498Szrj else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
18238fd1498Szrj stmt = else_;
18338fd1498Szrj else
18438fd1498Szrj stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
18538fd1498Szrj if (!EXPR_HAS_LOCATION (stmt))
18638fd1498Szrj protected_set_expr_location (stmt, locus);
18738fd1498Szrj *stmt_p = stmt;
18838fd1498Szrj }
18938fd1498Szrj
19038fd1498Szrj /* Build a generic representation of one of the C loop forms. COND is the
19138fd1498Szrj loop condition or NULL_TREE. BODY is the (possibly compound) statement
19238fd1498Szrj controlled by the loop. INCR is the increment expression of a for-loop,
19338fd1498Szrj or NULL_TREE. COND_IS_FIRST indicates whether the condition is
19438fd1498Szrj evaluated before the loop body as in while and for loops, or after the
19538fd1498Szrj loop body as in do-while loops. */
19638fd1498Szrj
19738fd1498Szrj static void
genericize_cp_loop(tree * stmt_p,location_t start_locus,tree cond,tree body,tree incr,bool cond_is_first,int * walk_subtrees,void * data)19838fd1498Szrj genericize_cp_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
19938fd1498Szrj tree incr, bool cond_is_first, int *walk_subtrees,
20038fd1498Szrj void *data)
20138fd1498Szrj {
20238fd1498Szrj tree blab, clab;
20338fd1498Szrj tree exit = NULL;
20438fd1498Szrj tree stmt_list = NULL;
20538fd1498Szrj
20638fd1498Szrj blab = begin_bc_block (bc_break, start_locus);
20738fd1498Szrj clab = begin_bc_block (bc_continue, start_locus);
20838fd1498Szrj
20938fd1498Szrj protected_set_expr_location (incr, start_locus);
21038fd1498Szrj
21138fd1498Szrj cp_walk_tree (&cond, cp_genericize_r, data, NULL);
21238fd1498Szrj cp_walk_tree (&body, cp_genericize_r, data, NULL);
21338fd1498Szrj cp_walk_tree (&incr, cp_genericize_r, data, NULL);
21438fd1498Szrj *walk_subtrees = 0;
21538fd1498Szrj
21638fd1498Szrj if (cond && TREE_CODE (cond) != INTEGER_CST)
21738fd1498Szrj {
21838fd1498Szrj /* If COND is constant, don't bother building an exit. If it's false,
21938fd1498Szrj we won't build a loop. If it's true, any exits are in the body. */
22038fd1498Szrj location_t cloc = EXPR_LOC_OR_LOC (cond, start_locus);
22138fd1498Szrj exit = build1_loc (cloc, GOTO_EXPR, void_type_node,
22238fd1498Szrj get_bc_label (bc_break));
22338fd1498Szrj exit = fold_build3_loc (cloc, COND_EXPR, void_type_node, cond,
22438fd1498Szrj build_empty_stmt (cloc), exit);
22538fd1498Szrj }
22638fd1498Szrj
22738fd1498Szrj if (exit && cond_is_first)
22838fd1498Szrj append_to_statement_list (exit, &stmt_list);
22938fd1498Szrj append_to_statement_list (body, &stmt_list);
23038fd1498Szrj finish_bc_block (&stmt_list, bc_continue, clab);
23138fd1498Szrj append_to_statement_list (incr, &stmt_list);
23238fd1498Szrj if (exit && !cond_is_first)
23338fd1498Szrj append_to_statement_list (exit, &stmt_list);
23438fd1498Szrj
23538fd1498Szrj if (!stmt_list)
23638fd1498Szrj stmt_list = build_empty_stmt (start_locus);
23738fd1498Szrj
23838fd1498Szrj tree loop;
23938fd1498Szrj if (cond && integer_zerop (cond))
24038fd1498Szrj {
24138fd1498Szrj if (cond_is_first)
24238fd1498Szrj loop = fold_build3_loc (start_locus, COND_EXPR,
24338fd1498Szrj void_type_node, cond, stmt_list,
24438fd1498Szrj build_empty_stmt (start_locus));
24538fd1498Szrj else
24638fd1498Szrj loop = stmt_list;
24738fd1498Szrj }
24838fd1498Szrj else
24938fd1498Szrj {
25038fd1498Szrj location_t loc = start_locus;
25138fd1498Szrj if (!cond || integer_nonzerop (cond))
25238fd1498Szrj loc = EXPR_LOCATION (expr_first (body));
25338fd1498Szrj if (loc == UNKNOWN_LOCATION)
25438fd1498Szrj loc = start_locus;
25538fd1498Szrj loop = build1_loc (loc, LOOP_EXPR, void_type_node, stmt_list);
25638fd1498Szrj }
25738fd1498Szrj
25838fd1498Szrj stmt_list = NULL;
25938fd1498Szrj append_to_statement_list (loop, &stmt_list);
26038fd1498Szrj finish_bc_block (&stmt_list, bc_break, blab);
26138fd1498Szrj if (!stmt_list)
26238fd1498Szrj stmt_list = build_empty_stmt (start_locus);
26338fd1498Szrj
26438fd1498Szrj *stmt_p = stmt_list;
26538fd1498Szrj }
26638fd1498Szrj
26738fd1498Szrj /* Genericize a FOR_STMT node *STMT_P. */
26838fd1498Szrj
26938fd1498Szrj static void
genericize_for_stmt(tree * stmt_p,int * walk_subtrees,void * data)27038fd1498Szrj genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data)
27138fd1498Szrj {
27238fd1498Szrj tree stmt = *stmt_p;
27338fd1498Szrj tree expr = NULL;
27438fd1498Szrj tree loop;
27538fd1498Szrj tree init = FOR_INIT_STMT (stmt);
27638fd1498Szrj
27738fd1498Szrj if (init)
27838fd1498Szrj {
27938fd1498Szrj cp_walk_tree (&init, cp_genericize_r, data, NULL);
28038fd1498Szrj append_to_statement_list (init, &expr);
28138fd1498Szrj }
28238fd1498Szrj
28338fd1498Szrj genericize_cp_loop (&loop, EXPR_LOCATION (stmt), FOR_COND (stmt),
28438fd1498Szrj FOR_BODY (stmt), FOR_EXPR (stmt), 1, walk_subtrees, data);
28538fd1498Szrj append_to_statement_list (loop, &expr);
28638fd1498Szrj if (expr == NULL_TREE)
28738fd1498Szrj expr = loop;
28838fd1498Szrj *stmt_p = expr;
28938fd1498Szrj }
29038fd1498Szrj
29138fd1498Szrj /* Genericize a WHILE_STMT node *STMT_P. */
29238fd1498Szrj
29338fd1498Szrj static void
genericize_while_stmt(tree * stmt_p,int * walk_subtrees,void * data)29438fd1498Szrj genericize_while_stmt (tree *stmt_p, int *walk_subtrees, void *data)
29538fd1498Szrj {
29638fd1498Szrj tree stmt = *stmt_p;
29738fd1498Szrj genericize_cp_loop (stmt_p, EXPR_LOCATION (stmt), WHILE_COND (stmt),
29838fd1498Szrj WHILE_BODY (stmt), NULL_TREE, 1, walk_subtrees, data);
29938fd1498Szrj }
30038fd1498Szrj
30138fd1498Szrj /* Genericize a DO_STMT node *STMT_P. */
30238fd1498Szrj
30338fd1498Szrj static void
genericize_do_stmt(tree * stmt_p,int * walk_subtrees,void * data)30438fd1498Szrj genericize_do_stmt (tree *stmt_p, int *walk_subtrees, void *data)
30538fd1498Szrj {
30638fd1498Szrj tree stmt = *stmt_p;
30738fd1498Szrj genericize_cp_loop (stmt_p, EXPR_LOCATION (stmt), DO_COND (stmt),
30838fd1498Szrj DO_BODY (stmt), NULL_TREE, 0, walk_subtrees, data);
30938fd1498Szrj }
31038fd1498Szrj
31138fd1498Szrj /* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR. */
31238fd1498Szrj
31338fd1498Szrj static void
genericize_switch_stmt(tree * stmt_p,int * walk_subtrees,void * data)31438fd1498Szrj genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data)
31538fd1498Szrj {
31638fd1498Szrj tree stmt = *stmt_p;
31738fd1498Szrj tree break_block, body, cond, type;
31838fd1498Szrj location_t stmt_locus = EXPR_LOCATION (stmt);
31938fd1498Szrj
32038fd1498Szrj break_block = begin_bc_block (bc_break, stmt_locus);
32138fd1498Szrj
32238fd1498Szrj body = SWITCH_STMT_BODY (stmt);
32338fd1498Szrj if (!body)
32438fd1498Szrj body = build_empty_stmt (stmt_locus);
32538fd1498Szrj cond = SWITCH_STMT_COND (stmt);
32638fd1498Szrj type = SWITCH_STMT_TYPE (stmt);
32738fd1498Szrj
32838fd1498Szrj cp_walk_tree (&body, cp_genericize_r, data, NULL);
32938fd1498Szrj cp_walk_tree (&cond, cp_genericize_r, data, NULL);
33038fd1498Szrj cp_walk_tree (&type, cp_genericize_r, data, NULL);
33138fd1498Szrj *walk_subtrees = 0;
33238fd1498Szrj
33338fd1498Szrj if (TREE_USED (break_block))
33438fd1498Szrj SWITCH_BREAK_LABEL_P (break_block) = 1;
33538fd1498Szrj finish_bc_block (&body, bc_break, break_block);
33638fd1498Szrj *stmt_p = build2_loc (stmt_locus, SWITCH_EXPR, type, cond, body);
33738fd1498Szrj SWITCH_ALL_CASES_P (*stmt_p) = SWITCH_STMT_ALL_CASES_P (stmt);
33838fd1498Szrj gcc_checking_assert (!SWITCH_STMT_NO_BREAK_P (stmt)
33938fd1498Szrj || !TREE_USED (break_block));
34038fd1498Szrj }
34138fd1498Szrj
34238fd1498Szrj /* Genericize a CONTINUE_STMT node *STMT_P. */
34338fd1498Szrj
34438fd1498Szrj static void
genericize_continue_stmt(tree * stmt_p)34538fd1498Szrj genericize_continue_stmt (tree *stmt_p)
34638fd1498Szrj {
34738fd1498Szrj tree stmt_list = NULL;
34838fd1498Szrj tree pred = build_predict_expr (PRED_CONTINUE, NOT_TAKEN);
34938fd1498Szrj tree label = get_bc_label (bc_continue);
35038fd1498Szrj location_t location = EXPR_LOCATION (*stmt_p);
35138fd1498Szrj tree jump = build1_loc (location, GOTO_EXPR, void_type_node, label);
35238fd1498Szrj append_to_statement_list_force (pred, &stmt_list);
35338fd1498Szrj append_to_statement_list (jump, &stmt_list);
35438fd1498Szrj *stmt_p = stmt_list;
35538fd1498Szrj }
35638fd1498Szrj
35738fd1498Szrj /* Genericize a BREAK_STMT node *STMT_P. */
35838fd1498Szrj
35938fd1498Szrj static void
genericize_break_stmt(tree * stmt_p)36038fd1498Szrj genericize_break_stmt (tree *stmt_p)
36138fd1498Szrj {
36238fd1498Szrj tree label = get_bc_label (bc_break);
36338fd1498Szrj location_t location = EXPR_LOCATION (*stmt_p);
36438fd1498Szrj *stmt_p = build1_loc (location, GOTO_EXPR, void_type_node, label);
36538fd1498Szrj }
36638fd1498Szrj
36738fd1498Szrj /* Genericize a OMP_FOR node *STMT_P. */
36838fd1498Szrj
36938fd1498Szrj static void
genericize_omp_for_stmt(tree * stmt_p,int * walk_subtrees,void * data)37038fd1498Szrj genericize_omp_for_stmt (tree *stmt_p, int *walk_subtrees, void *data)
37138fd1498Szrj {
37238fd1498Szrj tree stmt = *stmt_p;
37338fd1498Szrj location_t locus = EXPR_LOCATION (stmt);
37438fd1498Szrj tree clab = begin_bc_block (bc_continue, locus);
37538fd1498Szrj
37638fd1498Szrj cp_walk_tree (&OMP_FOR_BODY (stmt), cp_genericize_r, data, NULL);
37738fd1498Szrj if (TREE_CODE (stmt) != OMP_TASKLOOP)
37838fd1498Szrj cp_walk_tree (&OMP_FOR_CLAUSES (stmt), cp_genericize_r, data, NULL);
37938fd1498Szrj cp_walk_tree (&OMP_FOR_INIT (stmt), cp_genericize_r, data, NULL);
38038fd1498Szrj cp_walk_tree (&OMP_FOR_COND (stmt), cp_genericize_r, data, NULL);
38138fd1498Szrj cp_walk_tree (&OMP_FOR_INCR (stmt), cp_genericize_r, data, NULL);
38238fd1498Szrj cp_walk_tree (&OMP_FOR_PRE_BODY (stmt), cp_genericize_r, data, NULL);
38338fd1498Szrj *walk_subtrees = 0;
38438fd1498Szrj
38538fd1498Szrj finish_bc_block (&OMP_FOR_BODY (stmt), bc_continue, clab);
38638fd1498Szrj }
38738fd1498Szrj
38838fd1498Szrj /* Hook into the middle of gimplifying an OMP_FOR node. */
38938fd1498Szrj
39038fd1498Szrj static enum gimplify_status
cp_gimplify_omp_for(tree * expr_p,gimple_seq * pre_p)39138fd1498Szrj cp_gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
39238fd1498Szrj {
39338fd1498Szrj tree for_stmt = *expr_p;
39438fd1498Szrj gimple_seq seq = NULL;
39538fd1498Szrj
39638fd1498Szrj /* Protect ourselves from recursion. */
39738fd1498Szrj if (OMP_FOR_GIMPLIFYING_P (for_stmt))
39838fd1498Szrj return GS_UNHANDLED;
39938fd1498Szrj OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
40038fd1498Szrj
40138fd1498Szrj gimplify_and_add (for_stmt, &seq);
40238fd1498Szrj gimple_seq_add_seq (pre_p, seq);
40338fd1498Szrj
40438fd1498Szrj OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
40538fd1498Szrj
40638fd1498Szrj return GS_ALL_DONE;
40738fd1498Szrj }
40838fd1498Szrj
40938fd1498Szrj /* Gimplify an EXPR_STMT node. */
41038fd1498Szrj
41138fd1498Szrj static void
gimplify_expr_stmt(tree * stmt_p)41238fd1498Szrj gimplify_expr_stmt (tree *stmt_p)
41338fd1498Szrj {
41438fd1498Szrj tree stmt = EXPR_STMT_EXPR (*stmt_p);
41538fd1498Szrj
41638fd1498Szrj if (stmt == error_mark_node)
41738fd1498Szrj stmt = NULL;
41838fd1498Szrj
41938fd1498Szrj /* Gimplification of a statement expression will nullify the
42038fd1498Szrj statement if all its side effects are moved to *PRE_P and *POST_P.
42138fd1498Szrj
42238fd1498Szrj In this case we will not want to emit the gimplified statement.
42338fd1498Szrj However, we may still want to emit a warning, so we do that before
42438fd1498Szrj gimplification. */
42538fd1498Szrj if (stmt && warn_unused_value)
42638fd1498Szrj {
42738fd1498Szrj if (!TREE_SIDE_EFFECTS (stmt))
42838fd1498Szrj {
42938fd1498Szrj if (!IS_EMPTY_STMT (stmt)
43038fd1498Szrj && !VOID_TYPE_P (TREE_TYPE (stmt))
43138fd1498Szrj && !TREE_NO_WARNING (stmt))
43238fd1498Szrj warning (OPT_Wunused_value, "statement with no effect");
43338fd1498Szrj }
43438fd1498Szrj else
43538fd1498Szrj warn_if_unused_value (stmt, input_location);
43638fd1498Szrj }
43738fd1498Szrj
43838fd1498Szrj if (stmt == NULL_TREE)
43938fd1498Szrj stmt = alloc_stmt_list ();
44038fd1498Szrj
44138fd1498Szrj *stmt_p = stmt;
44238fd1498Szrj }
44338fd1498Szrj
44438fd1498Szrj /* Gimplify initialization from an AGGR_INIT_EXPR. */
44538fd1498Szrj
44638fd1498Szrj static void
cp_gimplify_init_expr(tree * expr_p)44738fd1498Szrj cp_gimplify_init_expr (tree *expr_p)
44838fd1498Szrj {
44938fd1498Szrj tree from = TREE_OPERAND (*expr_p, 1);
45038fd1498Szrj tree to = TREE_OPERAND (*expr_p, 0);
45138fd1498Szrj tree t;
45238fd1498Szrj
45338fd1498Szrj /* What about code that pulls out the temp and uses it elsewhere? I
45438fd1498Szrj think that such code never uses the TARGET_EXPR as an initializer. If
45538fd1498Szrj I'm wrong, we'll abort because the temp won't have any RTL. In that
45638fd1498Szrj case, I guess we'll need to replace references somehow. */
45738fd1498Szrj if (TREE_CODE (from) == TARGET_EXPR)
45838fd1498Szrj from = TARGET_EXPR_INITIAL (from);
45938fd1498Szrj
46038fd1498Szrj /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
46138fd1498Szrj inside the TARGET_EXPR. */
46238fd1498Szrj for (t = from; t; )
46338fd1498Szrj {
46438fd1498Szrj tree sub = TREE_CODE (t) == COMPOUND_EXPR ? TREE_OPERAND (t, 0) : t;
46538fd1498Szrj
46638fd1498Szrj /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
46738fd1498Szrj replace the slot operand with our target.
46838fd1498Szrj
46938fd1498Szrj Should we add a target parm to gimplify_expr instead? No, as in this
47038fd1498Szrj case we want to replace the INIT_EXPR. */
47138fd1498Szrj if (TREE_CODE (sub) == AGGR_INIT_EXPR
47238fd1498Szrj || TREE_CODE (sub) == VEC_INIT_EXPR)
47338fd1498Szrj {
47438fd1498Szrj if (TREE_CODE (sub) == AGGR_INIT_EXPR)
47538fd1498Szrj AGGR_INIT_EXPR_SLOT (sub) = to;
47638fd1498Szrj else
47738fd1498Szrj VEC_INIT_EXPR_SLOT (sub) = to;
47838fd1498Szrj *expr_p = from;
47938fd1498Szrj
48038fd1498Szrj /* The initialization is now a side-effect, so the container can
48138fd1498Szrj become void. */
48238fd1498Szrj if (from != sub)
48338fd1498Szrj TREE_TYPE (from) = void_type_node;
48438fd1498Szrj }
48538fd1498Szrj
48638fd1498Szrj /* Handle aggregate NSDMI. */
48738fd1498Szrj replace_placeholders (sub, to);
48838fd1498Szrj
48938fd1498Szrj if (t == sub)
49038fd1498Szrj break;
49138fd1498Szrj else
49238fd1498Szrj t = TREE_OPERAND (t, 1);
49338fd1498Szrj }
49438fd1498Szrj
49538fd1498Szrj }
49638fd1498Szrj
49738fd1498Szrj /* Gimplify a MUST_NOT_THROW_EXPR. */
49838fd1498Szrj
49938fd1498Szrj static enum gimplify_status
gimplify_must_not_throw_expr(tree * expr_p,gimple_seq * pre_p)50038fd1498Szrj gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p)
50138fd1498Szrj {
50238fd1498Szrj tree stmt = *expr_p;
50338fd1498Szrj tree temp = voidify_wrapper_expr (stmt, NULL);
50438fd1498Szrj tree body = TREE_OPERAND (stmt, 0);
50538fd1498Szrj gimple_seq try_ = NULL;
50638fd1498Szrj gimple_seq catch_ = NULL;
50738fd1498Szrj gimple *mnt;
50838fd1498Szrj
50938fd1498Szrj gimplify_and_add (body, &try_);
51038fd1498Szrj mnt = gimple_build_eh_must_not_throw (terminate_fn);
51138fd1498Szrj gimple_seq_add_stmt_without_update (&catch_, mnt);
51238fd1498Szrj mnt = gimple_build_try (try_, catch_, GIMPLE_TRY_CATCH);
51338fd1498Szrj
51438fd1498Szrj gimple_seq_add_stmt_without_update (pre_p, mnt);
51538fd1498Szrj if (temp)
51638fd1498Szrj {
51738fd1498Szrj *expr_p = temp;
51838fd1498Szrj return GS_OK;
51938fd1498Szrj }
52038fd1498Szrj
52138fd1498Szrj *expr_p = NULL;
52238fd1498Szrj return GS_ALL_DONE;
52338fd1498Szrj }
52438fd1498Szrj
52538fd1498Szrj /* Return TRUE if an operand (OP) of a given TYPE being copied is
52638fd1498Szrj really just an empty class copy.
52738fd1498Szrj
52838fd1498Szrj Check that the operand has a simple form so that TARGET_EXPRs and
52938fd1498Szrj non-empty CONSTRUCTORs get reduced properly, and we leave the
53038fd1498Szrj return slot optimization alone because it isn't a copy. */
53138fd1498Szrj
53238fd1498Szrj static bool
simple_empty_class_p(tree type,tree op)53338fd1498Szrj simple_empty_class_p (tree type, tree op)
53438fd1498Szrj {
53538fd1498Szrj return
53638fd1498Szrj ((TREE_CODE (op) == COMPOUND_EXPR
53738fd1498Szrj && simple_empty_class_p (type, TREE_OPERAND (op, 1)))
53838fd1498Szrj || TREE_CODE (op) == EMPTY_CLASS_EXPR
53938fd1498Szrj || is_gimple_lvalue (op)
54038fd1498Szrj || INDIRECT_REF_P (op)
54138fd1498Szrj || (TREE_CODE (op) == CONSTRUCTOR
54238fd1498Szrj && CONSTRUCTOR_NELTS (op) == 0
54338fd1498Szrj && !TREE_CLOBBER_P (op))
54438fd1498Szrj || (TREE_CODE (op) == CALL_EXPR
54538fd1498Szrj && !CALL_EXPR_RETURN_SLOT_OPT (op)))
54638fd1498Szrj && is_really_empty_class (type);
54738fd1498Szrj }
54838fd1498Szrj
54938fd1498Szrj /* Returns true if evaluating E as an lvalue has side-effects;
55038fd1498Szrj specifically, a volatile lvalue has TREE_SIDE_EFFECTS, but it doesn't really
55138fd1498Szrj have side-effects until there is a read or write through it. */
55238fd1498Szrj
55338fd1498Szrj static bool
lvalue_has_side_effects(tree e)55438fd1498Szrj lvalue_has_side_effects (tree e)
55538fd1498Szrj {
55638fd1498Szrj if (!TREE_SIDE_EFFECTS (e))
55738fd1498Szrj return false;
55838fd1498Szrj while (handled_component_p (e))
55938fd1498Szrj {
56038fd1498Szrj if (TREE_CODE (e) == ARRAY_REF
56138fd1498Szrj && TREE_SIDE_EFFECTS (TREE_OPERAND (e, 1)))
56238fd1498Szrj return true;
56338fd1498Szrj e = TREE_OPERAND (e, 0);
56438fd1498Szrj }
56538fd1498Szrj if (DECL_P (e))
56638fd1498Szrj /* Just naming a variable has no side-effects. */
56738fd1498Szrj return false;
56838fd1498Szrj else if (INDIRECT_REF_P (e))
56938fd1498Szrj /* Similarly, indirection has no side-effects. */
57038fd1498Szrj return TREE_SIDE_EFFECTS (TREE_OPERAND (e, 0));
57138fd1498Szrj else
57238fd1498Szrj /* For anything else, trust TREE_SIDE_EFFECTS. */
57338fd1498Szrj return TREE_SIDE_EFFECTS (e);
57438fd1498Szrj }
57538fd1498Szrj
57638fd1498Szrj /* Do C++-specific gimplification. Args are as for gimplify_expr. */
57738fd1498Szrj
57838fd1498Szrj int
cp_gimplify_expr(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p)57938fd1498Szrj cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
58038fd1498Szrj {
58138fd1498Szrj int saved_stmts_are_full_exprs_p = 0;
58238fd1498Szrj location_t loc = EXPR_LOC_OR_LOC (*expr_p, input_location);
58338fd1498Szrj enum tree_code code = TREE_CODE (*expr_p);
58438fd1498Szrj enum gimplify_status ret;
58538fd1498Szrj
58638fd1498Szrj if (STATEMENT_CODE_P (code))
58738fd1498Szrj {
58838fd1498Szrj saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
58938fd1498Szrj current_stmt_tree ()->stmts_are_full_exprs_p
59038fd1498Szrj = STMT_IS_FULL_EXPR_P (*expr_p);
59138fd1498Szrj }
59238fd1498Szrj
59338fd1498Szrj switch (code)
59438fd1498Szrj {
59538fd1498Szrj case AGGR_INIT_EXPR:
59638fd1498Szrj simplify_aggr_init_expr (expr_p);
59738fd1498Szrj ret = GS_OK;
59838fd1498Szrj break;
59938fd1498Szrj
60038fd1498Szrj case VEC_INIT_EXPR:
60138fd1498Szrj {
60238fd1498Szrj location_t loc = input_location;
60338fd1498Szrj tree init = VEC_INIT_EXPR_INIT (*expr_p);
60438fd1498Szrj int from_array = (init && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE);
60538fd1498Szrj gcc_assert (EXPR_HAS_LOCATION (*expr_p));
60638fd1498Szrj input_location = EXPR_LOCATION (*expr_p);
60738fd1498Szrj *expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE,
60838fd1498Szrj init, VEC_INIT_EXPR_VALUE_INIT (*expr_p),
60938fd1498Szrj from_array,
61038fd1498Szrj tf_warning_or_error);
61138fd1498Szrj hash_set<tree> pset;
61238fd1498Szrj cp_walk_tree (expr_p, cp_fold_r, &pset, NULL);
61338fd1498Szrj cp_genericize_tree (expr_p, false);
61438fd1498Szrj ret = GS_OK;
61538fd1498Szrj input_location = loc;
61638fd1498Szrj }
61738fd1498Szrj break;
61838fd1498Szrj
61938fd1498Szrj case THROW_EXPR:
62038fd1498Szrj /* FIXME communicate throw type to back end, probably by moving
62138fd1498Szrj THROW_EXPR into ../tree.def. */
62238fd1498Szrj *expr_p = TREE_OPERAND (*expr_p, 0);
62338fd1498Szrj ret = GS_OK;
62438fd1498Szrj break;
62538fd1498Szrj
62638fd1498Szrj case MUST_NOT_THROW_EXPR:
62738fd1498Szrj ret = gimplify_must_not_throw_expr (expr_p, pre_p);
62838fd1498Szrj break;
62938fd1498Szrj
63038fd1498Szrj /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
63138fd1498Szrj LHS of an assignment might also be involved in the RHS, as in bug
63238fd1498Szrj 25979. */
63338fd1498Szrj case INIT_EXPR:
63438fd1498Szrj cp_gimplify_init_expr (expr_p);
63538fd1498Szrj if (TREE_CODE (*expr_p) != INIT_EXPR)
63638fd1498Szrj return GS_OK;
63738fd1498Szrj /* Fall through. */
63838fd1498Szrj case MODIFY_EXPR:
63938fd1498Szrj modify_expr_case:
64038fd1498Szrj {
64138fd1498Szrj /* If the back end isn't clever enough to know that the lhs and rhs
64238fd1498Szrj types are the same, add an explicit conversion. */
64338fd1498Szrj tree op0 = TREE_OPERAND (*expr_p, 0);
64438fd1498Szrj tree op1 = TREE_OPERAND (*expr_p, 1);
64538fd1498Szrj
64638fd1498Szrj if (!error_operand_p (op0)
64738fd1498Szrj && !error_operand_p (op1)
64838fd1498Szrj && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0))
64938fd1498Szrj || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1)))
65038fd1498Szrj && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
65138fd1498Szrj TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
65238fd1498Szrj TREE_TYPE (op0), op1);
65338fd1498Szrj
65438fd1498Szrj else if (simple_empty_class_p (TREE_TYPE (op0), op1))
65538fd1498Szrj {
65638fd1498Szrj /* Remove any copies of empty classes. Also drop volatile
65738fd1498Szrj variables on the RHS to avoid infinite recursion from
65838fd1498Szrj gimplify_expr trying to load the value. */
65938fd1498Szrj if (TREE_SIDE_EFFECTS (op1))
66038fd1498Szrj {
66138fd1498Szrj if (TREE_THIS_VOLATILE (op1)
66238fd1498Szrj && (REFERENCE_CLASS_P (op1) || DECL_P (op1)))
66338fd1498Szrj op1 = build_fold_addr_expr (op1);
66438fd1498Szrj
66538fd1498Szrj gimplify_and_add (op1, pre_p);
66638fd1498Szrj }
66738fd1498Szrj gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
66838fd1498Szrj is_gimple_lvalue, fb_lvalue);
66938fd1498Szrj *expr_p = TREE_OPERAND (*expr_p, 0);
67038fd1498Szrj }
67138fd1498Szrj /* P0145 says that the RHS is sequenced before the LHS.
67238fd1498Szrj gimplify_modify_expr gimplifies the RHS before the LHS, but that
67338fd1498Szrj isn't quite strong enough in two cases:
67438fd1498Szrj
67538fd1498Szrj 1) gimplify.c wants to leave a CALL_EXPR on the RHS, which would
67638fd1498Szrj mean it's evaluated after the LHS.
67738fd1498Szrj
67838fd1498Szrj 2) the value calculation of the RHS is also sequenced before the
67938fd1498Szrj LHS, so for scalar assignment we need to preevaluate if the
68038fd1498Szrj RHS could be affected by LHS side-effects even if it has no
68138fd1498Szrj side-effects of its own. We don't need this for classes because
68238fd1498Szrj class assignment takes its RHS by reference. */
68338fd1498Szrj else if (flag_strong_eval_order > 1
68438fd1498Szrj && TREE_CODE (*expr_p) == MODIFY_EXPR
68538fd1498Szrj && lvalue_has_side_effects (op0)
68638fd1498Szrj && (TREE_CODE (op1) == CALL_EXPR
68738fd1498Szrj || (SCALAR_TYPE_P (TREE_TYPE (op1))
68838fd1498Szrj && !TREE_CONSTANT (op1))))
68938fd1498Szrj TREE_OPERAND (*expr_p, 1) = get_formal_tmp_var (op1, pre_p);
69038fd1498Szrj }
69138fd1498Szrj ret = GS_OK;
69238fd1498Szrj break;
69338fd1498Szrj
69438fd1498Szrj case EMPTY_CLASS_EXPR:
69538fd1498Szrj /* We create an empty CONSTRUCTOR with RECORD_TYPE. */
69638fd1498Szrj *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
69738fd1498Szrj ret = GS_OK;
69838fd1498Szrj break;
69938fd1498Szrj
70038fd1498Szrj case BASELINK:
70138fd1498Szrj *expr_p = BASELINK_FUNCTIONS (*expr_p);
70238fd1498Szrj ret = GS_OK;
70338fd1498Szrj break;
70438fd1498Szrj
70538fd1498Szrj case TRY_BLOCK:
70638fd1498Szrj genericize_try_block (expr_p);
70738fd1498Szrj ret = GS_OK;
70838fd1498Szrj break;
70938fd1498Szrj
71038fd1498Szrj case HANDLER:
71138fd1498Szrj genericize_catch_block (expr_p);
71238fd1498Szrj ret = GS_OK;
71338fd1498Szrj break;
71438fd1498Szrj
71538fd1498Szrj case EH_SPEC_BLOCK:
71638fd1498Szrj genericize_eh_spec_block (expr_p);
71738fd1498Szrj ret = GS_OK;
71838fd1498Szrj break;
71938fd1498Szrj
72038fd1498Szrj case USING_STMT:
72138fd1498Szrj gcc_unreachable ();
72238fd1498Szrj
72338fd1498Szrj case FOR_STMT:
72438fd1498Szrj case WHILE_STMT:
72538fd1498Szrj case DO_STMT:
72638fd1498Szrj case SWITCH_STMT:
72738fd1498Szrj case CONTINUE_STMT:
72838fd1498Szrj case BREAK_STMT:
72938fd1498Szrj gcc_unreachable ();
73038fd1498Szrj
73138fd1498Szrj case OMP_FOR:
73238fd1498Szrj case OMP_SIMD:
73338fd1498Szrj case OMP_DISTRIBUTE:
73438fd1498Szrj case OMP_TASKLOOP:
73538fd1498Szrj ret = cp_gimplify_omp_for (expr_p, pre_p);
73638fd1498Szrj break;
73738fd1498Szrj
73838fd1498Szrj case EXPR_STMT:
73938fd1498Szrj gimplify_expr_stmt (expr_p);
74038fd1498Szrj ret = GS_OK;
74138fd1498Szrj break;
74238fd1498Szrj
74338fd1498Szrj case UNARY_PLUS_EXPR:
74438fd1498Szrj {
74538fd1498Szrj tree arg = TREE_OPERAND (*expr_p, 0);
74638fd1498Szrj tree type = TREE_TYPE (*expr_p);
74738fd1498Szrj *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
74838fd1498Szrj : arg;
74938fd1498Szrj ret = GS_OK;
75038fd1498Szrj }
75138fd1498Szrj break;
75238fd1498Szrj
75338fd1498Szrj case CALL_EXPR:
75438fd1498Szrj ret = GS_OK;
75538fd1498Szrj if (!CALL_EXPR_FN (*expr_p))
75638fd1498Szrj /* Internal function call. */;
75738fd1498Szrj else if (CALL_EXPR_REVERSE_ARGS (*expr_p))
75838fd1498Szrj {
75938fd1498Szrj /* This is a call to a (compound) assignment operator that used
76038fd1498Szrj the operator syntax; gimplify the RHS first. */
76138fd1498Szrj gcc_assert (call_expr_nargs (*expr_p) == 2);
76238fd1498Szrj gcc_assert (!CALL_EXPR_ORDERED_ARGS (*expr_p));
76338fd1498Szrj enum gimplify_status t
76438fd1498Szrj = gimplify_arg (&CALL_EXPR_ARG (*expr_p, 1), pre_p, loc);
76538fd1498Szrj if (t == GS_ERROR)
76638fd1498Szrj ret = GS_ERROR;
76738fd1498Szrj }
76838fd1498Szrj else if (CALL_EXPR_ORDERED_ARGS (*expr_p))
76938fd1498Szrj {
77038fd1498Szrj /* Leave the last argument for gimplify_call_expr, to avoid problems
77138fd1498Szrj with __builtin_va_arg_pack(). */
77238fd1498Szrj int nargs = call_expr_nargs (*expr_p) - 1;
77338fd1498Szrj for (int i = 0; i < nargs; ++i)
77438fd1498Szrj {
77538fd1498Szrj enum gimplify_status t
77638fd1498Szrj = gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p, loc);
77738fd1498Szrj if (t == GS_ERROR)
77838fd1498Szrj ret = GS_ERROR;
77938fd1498Szrj }
78038fd1498Szrj }
78138fd1498Szrj else if (flag_strong_eval_order
78238fd1498Szrj && !CALL_EXPR_OPERATOR_SYNTAX (*expr_p))
78338fd1498Szrj {
78438fd1498Szrj /* If flag_strong_eval_order, evaluate the object argument first. */
78538fd1498Szrj tree fntype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
78638fd1498Szrj if (POINTER_TYPE_P (fntype))
78738fd1498Szrj fntype = TREE_TYPE (fntype);
78838fd1498Szrj if (TREE_CODE (fntype) == METHOD_TYPE)
78938fd1498Szrj {
79038fd1498Szrj enum gimplify_status t
79138fd1498Szrj = gimplify_arg (&CALL_EXPR_ARG (*expr_p, 0), pre_p, loc);
79238fd1498Szrj if (t == GS_ERROR)
79338fd1498Szrj ret = GS_ERROR;
79438fd1498Szrj }
79538fd1498Szrj }
79638fd1498Szrj break;
79738fd1498Szrj
79838fd1498Szrj case RETURN_EXPR:
79938fd1498Szrj if (TREE_OPERAND (*expr_p, 0)
80038fd1498Szrj && (TREE_CODE (TREE_OPERAND (*expr_p, 0)) == INIT_EXPR
80138fd1498Szrj || TREE_CODE (TREE_OPERAND (*expr_p, 0)) == MODIFY_EXPR))
80238fd1498Szrj {
80338fd1498Szrj expr_p = &TREE_OPERAND (*expr_p, 0);
80438fd1498Szrj code = TREE_CODE (*expr_p);
80538fd1498Szrj /* Avoid going through the INIT_EXPR case, which can
80638fd1498Szrj degrade INIT_EXPRs into AGGR_INIT_EXPRs. */
80738fd1498Szrj goto modify_expr_case;
80838fd1498Szrj }
80938fd1498Szrj /* Fall through. */
81038fd1498Szrj
81138fd1498Szrj default:
81238fd1498Szrj ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p);
81338fd1498Szrj break;
81438fd1498Szrj }
81538fd1498Szrj
81638fd1498Szrj /* Restore saved state. */
81738fd1498Szrj if (STATEMENT_CODE_P (code))
81838fd1498Szrj current_stmt_tree ()->stmts_are_full_exprs_p
81938fd1498Szrj = saved_stmts_are_full_exprs_p;
82038fd1498Szrj
82138fd1498Szrj return ret;
82238fd1498Szrj }
82338fd1498Szrj
82438fd1498Szrj static inline bool
is_invisiref_parm(const_tree t)82538fd1498Szrj is_invisiref_parm (const_tree t)
82638fd1498Szrj {
82738fd1498Szrj return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
82838fd1498Szrj && DECL_BY_REFERENCE (t));
82938fd1498Szrj }
83038fd1498Szrj
83138fd1498Szrj /* Return true if the uid in both int tree maps are equal. */
83238fd1498Szrj
83338fd1498Szrj bool
equal(cxx_int_tree_map * a,cxx_int_tree_map * b)83438fd1498Szrj cxx_int_tree_map_hasher::equal (cxx_int_tree_map *a, cxx_int_tree_map *b)
83538fd1498Szrj {
83638fd1498Szrj return (a->uid == b->uid);
83738fd1498Szrj }
83838fd1498Szrj
83938fd1498Szrj /* Hash a UID in a cxx_int_tree_map. */
84038fd1498Szrj
84138fd1498Szrj unsigned int
hash(cxx_int_tree_map * item)84238fd1498Szrj cxx_int_tree_map_hasher::hash (cxx_int_tree_map *item)
84338fd1498Szrj {
84438fd1498Szrj return item->uid;
84538fd1498Szrj }
84638fd1498Szrj
84738fd1498Szrj /* A stable comparison routine for use with splay trees and DECLs. */
84838fd1498Szrj
84938fd1498Szrj static int
splay_tree_compare_decl_uid(splay_tree_key xa,splay_tree_key xb)85038fd1498Szrj splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
85138fd1498Szrj {
85238fd1498Szrj tree a = (tree) xa;
85338fd1498Szrj tree b = (tree) xb;
85438fd1498Szrj
85538fd1498Szrj return DECL_UID (a) - DECL_UID (b);
85638fd1498Szrj }
85738fd1498Szrj
85838fd1498Szrj /* OpenMP context during genericization. */
85938fd1498Szrj
86038fd1498Szrj struct cp_genericize_omp_taskreg
86138fd1498Szrj {
86238fd1498Szrj bool is_parallel;
86338fd1498Szrj bool default_shared;
86438fd1498Szrj struct cp_genericize_omp_taskreg *outer;
86538fd1498Szrj splay_tree variables;
86638fd1498Szrj };
86738fd1498Szrj
86838fd1498Szrj /* Return true if genericization should try to determine if
86938fd1498Szrj DECL is firstprivate or shared within task regions. */
87038fd1498Szrj
87138fd1498Szrj static bool
omp_var_to_track(tree decl)87238fd1498Szrj omp_var_to_track (tree decl)
87338fd1498Szrj {
87438fd1498Szrj tree type = TREE_TYPE (decl);
87538fd1498Szrj if (is_invisiref_parm (decl))
87638fd1498Szrj type = TREE_TYPE (type);
87738fd1498Szrj else if (TREE_CODE (type) == REFERENCE_TYPE)
87838fd1498Szrj type = TREE_TYPE (type);
87938fd1498Szrj while (TREE_CODE (type) == ARRAY_TYPE)
88038fd1498Szrj type = TREE_TYPE (type);
88138fd1498Szrj if (type == error_mark_node || !CLASS_TYPE_P (type))
88238fd1498Szrj return false;
88338fd1498Szrj if (VAR_P (decl) && CP_DECL_THREAD_LOCAL_P (decl))
88438fd1498Szrj return false;
88538fd1498Szrj if (cxx_omp_predetermined_sharing (decl) != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
88638fd1498Szrj return false;
88738fd1498Szrj return true;
88838fd1498Szrj }
88938fd1498Szrj
89038fd1498Szrj /* Note DECL use in OpenMP region OMP_CTX during genericization. */
89138fd1498Szrj
89238fd1498Szrj static void
omp_cxx_notice_variable(struct cp_genericize_omp_taskreg * omp_ctx,tree decl)89338fd1498Szrj omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl)
89438fd1498Szrj {
89538fd1498Szrj splay_tree_node n = splay_tree_lookup (omp_ctx->variables,
89638fd1498Szrj (splay_tree_key) decl);
89738fd1498Szrj if (n == NULL)
89838fd1498Szrj {
89938fd1498Szrj int flags = OMP_CLAUSE_DEFAULT_SHARED;
90038fd1498Szrj if (omp_ctx->outer)
90138fd1498Szrj omp_cxx_notice_variable (omp_ctx->outer, decl);
90238fd1498Szrj if (!omp_ctx->default_shared)
90338fd1498Szrj {
90438fd1498Szrj struct cp_genericize_omp_taskreg *octx;
90538fd1498Szrj
90638fd1498Szrj for (octx = omp_ctx->outer; octx; octx = octx->outer)
90738fd1498Szrj {
90838fd1498Szrj n = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
90938fd1498Szrj if (n && n->value != OMP_CLAUSE_DEFAULT_SHARED)
91038fd1498Szrj {
91138fd1498Szrj flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
91238fd1498Szrj break;
91338fd1498Szrj }
91438fd1498Szrj if (octx->is_parallel)
91538fd1498Szrj break;
91638fd1498Szrj }
91738fd1498Szrj if (octx == NULL
91838fd1498Szrj && (TREE_CODE (decl) == PARM_DECL
91938fd1498Szrj || (!(TREE_STATIC (decl) || DECL_EXTERNAL (decl))
92038fd1498Szrj && DECL_CONTEXT (decl) == current_function_decl)))
92138fd1498Szrj flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
92238fd1498Szrj if (flags == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
92338fd1498Szrj {
92438fd1498Szrj /* DECL is implicitly determined firstprivate in
92538fd1498Szrj the current task construct. Ensure copy ctor and
92638fd1498Szrj dtor are instantiated, because during gimplification
92738fd1498Szrj it will be already too late. */
92838fd1498Szrj tree type = TREE_TYPE (decl);
92938fd1498Szrj if (is_invisiref_parm (decl))
93038fd1498Szrj type = TREE_TYPE (type);
93138fd1498Szrj else if (TREE_CODE (type) == REFERENCE_TYPE)
93238fd1498Szrj type = TREE_TYPE (type);
93338fd1498Szrj while (TREE_CODE (type) == ARRAY_TYPE)
93438fd1498Szrj type = TREE_TYPE (type);
93538fd1498Szrj get_copy_ctor (type, tf_none);
93638fd1498Szrj get_dtor (type, tf_none);
93738fd1498Szrj }
93838fd1498Szrj }
93938fd1498Szrj splay_tree_insert (omp_ctx->variables, (splay_tree_key) decl, flags);
94038fd1498Szrj }
94138fd1498Szrj }
94238fd1498Szrj
94338fd1498Szrj /* Genericization context. */
94438fd1498Szrj
94538fd1498Szrj struct cp_genericize_data
94638fd1498Szrj {
94738fd1498Szrj hash_set<tree> *p_set;
94838fd1498Szrj vec<tree> bind_expr_stack;
94938fd1498Szrj struct cp_genericize_omp_taskreg *omp_ctx;
95038fd1498Szrj tree try_block;
95138fd1498Szrj bool no_sanitize_p;
95238fd1498Szrj bool handle_invisiref_parm_p;
95338fd1498Szrj };
95438fd1498Szrj
95538fd1498Szrj /* Perform any pre-gimplification folding of C++ front end trees to
95638fd1498Szrj GENERIC.
95738fd1498Szrj Note: The folding of none-omp cases is something to move into
95838fd1498Szrj the middle-end. As for now we have most foldings only on GENERIC
95938fd1498Szrj in fold-const, we need to perform this before transformation to
96038fd1498Szrj GIMPLE-form. */
96138fd1498Szrj
96238fd1498Szrj static tree
cp_fold_r(tree * stmt_p,int * walk_subtrees,void * data)96338fd1498Szrj cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data)
96438fd1498Szrj {
96538fd1498Szrj tree stmt;
96638fd1498Szrj enum tree_code code;
96738fd1498Szrj
96838fd1498Szrj *stmt_p = stmt = cp_fold (*stmt_p);
96938fd1498Szrj
97038fd1498Szrj if (((hash_set<tree> *) data)->add (stmt))
97138fd1498Szrj {
97238fd1498Szrj /* Don't walk subtrees of stmts we've already walked once, otherwise
97338fd1498Szrj we can have exponential complexity with e.g. lots of nested
97438fd1498Szrj SAVE_EXPRs or TARGET_EXPRs. cp_fold uses a cache and will return
97538fd1498Szrj always the same tree, which the first time cp_fold_r has been
97638fd1498Szrj called on it had the subtrees walked. */
97738fd1498Szrj *walk_subtrees = 0;
97838fd1498Szrj return NULL;
97938fd1498Szrj }
98038fd1498Szrj
98138fd1498Szrj code = TREE_CODE (stmt);
98238fd1498Szrj if (code == OMP_FOR || code == OMP_SIMD || code == OMP_DISTRIBUTE
98338fd1498Szrj || code == OMP_TASKLOOP || code == OACC_LOOP)
98438fd1498Szrj {
98538fd1498Szrj tree x;
98638fd1498Szrj int i, n;
98738fd1498Szrj
98838fd1498Szrj cp_walk_tree (&OMP_FOR_BODY (stmt), cp_fold_r, data, NULL);
98938fd1498Szrj cp_walk_tree (&OMP_FOR_CLAUSES (stmt), cp_fold_r, data, NULL);
99038fd1498Szrj cp_walk_tree (&OMP_FOR_INIT (stmt), cp_fold_r, data, NULL);
99138fd1498Szrj x = OMP_FOR_COND (stmt);
99238fd1498Szrj if (x && TREE_CODE_CLASS (TREE_CODE (x)) == tcc_comparison)
99338fd1498Szrj {
99438fd1498Szrj cp_walk_tree (&TREE_OPERAND (x, 0), cp_fold_r, data, NULL);
99538fd1498Szrj cp_walk_tree (&TREE_OPERAND (x, 1), cp_fold_r, data, NULL);
99638fd1498Szrj }
99738fd1498Szrj else if (x && TREE_CODE (x) == TREE_VEC)
99838fd1498Szrj {
99938fd1498Szrj n = TREE_VEC_LENGTH (x);
100038fd1498Szrj for (i = 0; i < n; i++)
100138fd1498Szrj {
100238fd1498Szrj tree o = TREE_VEC_ELT (x, i);
100338fd1498Szrj if (o && TREE_CODE_CLASS (TREE_CODE (o)) == tcc_comparison)
100438fd1498Szrj cp_walk_tree (&TREE_OPERAND (o, 1), cp_fold_r, data, NULL);
100538fd1498Szrj }
100638fd1498Szrj }
100738fd1498Szrj x = OMP_FOR_INCR (stmt);
100838fd1498Szrj if (x && TREE_CODE (x) == TREE_VEC)
100938fd1498Szrj {
101038fd1498Szrj n = TREE_VEC_LENGTH (x);
101138fd1498Szrj for (i = 0; i < n; i++)
101238fd1498Szrj {
101338fd1498Szrj tree o = TREE_VEC_ELT (x, i);
101438fd1498Szrj if (o && TREE_CODE (o) == MODIFY_EXPR)
101538fd1498Szrj o = TREE_OPERAND (o, 1);
101638fd1498Szrj if (o && (TREE_CODE (o) == PLUS_EXPR || TREE_CODE (o) == MINUS_EXPR
101738fd1498Szrj || TREE_CODE (o) == POINTER_PLUS_EXPR))
101838fd1498Szrj {
101938fd1498Szrj cp_walk_tree (&TREE_OPERAND (o, 0), cp_fold_r, data, NULL);
102038fd1498Szrj cp_walk_tree (&TREE_OPERAND (o, 1), cp_fold_r, data, NULL);
102138fd1498Szrj }
102238fd1498Szrj }
102338fd1498Szrj }
102438fd1498Szrj cp_walk_tree (&OMP_FOR_PRE_BODY (stmt), cp_fold_r, data, NULL);
102538fd1498Szrj *walk_subtrees = 0;
102638fd1498Szrj }
102738fd1498Szrj
102838fd1498Szrj return NULL;
102938fd1498Szrj }
103038fd1498Szrj
103138fd1498Szrj /* Fold ALL the trees! FIXME we should be able to remove this, but
103238fd1498Szrj apparently that still causes optimization regressions. */
103338fd1498Szrj
103438fd1498Szrj void
cp_fold_function(tree fndecl)103538fd1498Szrj cp_fold_function (tree fndecl)
103638fd1498Szrj {
103738fd1498Szrj hash_set<tree> pset;
103838fd1498Szrj cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_fold_r, &pset, NULL);
103938fd1498Szrj }
104038fd1498Szrj
104138fd1498Szrj /* Perform any pre-gimplification lowering of C++ front end trees to
104238fd1498Szrj GENERIC. */
104338fd1498Szrj
104438fd1498Szrj static tree
cp_genericize_r(tree * stmt_p,int * walk_subtrees,void * data)104538fd1498Szrj cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
104638fd1498Szrj {
104738fd1498Szrj tree stmt = *stmt_p;
104838fd1498Szrj struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
104938fd1498Szrj hash_set<tree> *p_set = wtd->p_set;
105038fd1498Szrj
105138fd1498Szrj /* If in an OpenMP context, note var uses. */
105238fd1498Szrj if (__builtin_expect (wtd->omp_ctx != NULL, 0)
105338fd1498Szrj && (VAR_P (stmt)
105438fd1498Szrj || TREE_CODE (stmt) == PARM_DECL
105538fd1498Szrj || TREE_CODE (stmt) == RESULT_DECL)
105638fd1498Szrj && omp_var_to_track (stmt))
105738fd1498Szrj omp_cxx_notice_variable (wtd->omp_ctx, stmt);
105838fd1498Szrj
105938fd1498Szrj /* Don't dereference parms in a thunk, pass the references through. */
106038fd1498Szrj if ((TREE_CODE (stmt) == CALL_EXPR && CALL_FROM_THUNK_P (stmt))
106138fd1498Szrj || (TREE_CODE (stmt) == AGGR_INIT_EXPR && AGGR_INIT_FROM_THUNK_P (stmt)))
106238fd1498Szrj {
106338fd1498Szrj *walk_subtrees = 0;
106438fd1498Szrj return NULL;
106538fd1498Szrj }
106638fd1498Szrj
106738fd1498Szrj /* Dereference invisible reference parms. */
106838fd1498Szrj if (wtd->handle_invisiref_parm_p && is_invisiref_parm (stmt))
106938fd1498Szrj {
107038fd1498Szrj *stmt_p = convert_from_reference (stmt);
107138fd1498Szrj p_set->add (*stmt_p);
107238fd1498Szrj *walk_subtrees = 0;
107338fd1498Szrj return NULL;
107438fd1498Szrj }
107538fd1498Szrj
107638fd1498Szrj /* Map block scope extern declarations to visible declarations with the
107738fd1498Szrj same name and type in outer scopes if any. */
107838fd1498Szrj if (cp_function_chain->extern_decl_map
107938fd1498Szrj && VAR_OR_FUNCTION_DECL_P (stmt)
108038fd1498Szrj && DECL_EXTERNAL (stmt))
108138fd1498Szrj {
108238fd1498Szrj struct cxx_int_tree_map *h, in;
108338fd1498Szrj in.uid = DECL_UID (stmt);
108438fd1498Szrj h = cp_function_chain->extern_decl_map->find_with_hash (&in, in.uid);
108538fd1498Szrj if (h)
108638fd1498Szrj {
108738fd1498Szrj *stmt_p = h->to;
1088*58e805e6Szrj TREE_USED (h->to) |= TREE_USED (stmt);
108938fd1498Szrj *walk_subtrees = 0;
109038fd1498Szrj return NULL;
109138fd1498Szrj }
109238fd1498Szrj }
109338fd1498Szrj
109438fd1498Szrj if (TREE_CODE (stmt) == INTEGER_CST
109538fd1498Szrj && TREE_CODE (TREE_TYPE (stmt)) == REFERENCE_TYPE
109638fd1498Szrj && (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
109738fd1498Szrj && !wtd->no_sanitize_p)
109838fd1498Szrj {
109938fd1498Szrj ubsan_maybe_instrument_reference (stmt_p);
110038fd1498Szrj if (*stmt_p != stmt)
110138fd1498Szrj {
110238fd1498Szrj *walk_subtrees = 0;
110338fd1498Szrj return NULL_TREE;
110438fd1498Szrj }
110538fd1498Szrj }
110638fd1498Szrj
110738fd1498Szrj /* Other than invisiref parms, don't walk the same tree twice. */
110838fd1498Szrj if (p_set->contains (stmt))
110938fd1498Szrj {
111038fd1498Szrj *walk_subtrees = 0;
111138fd1498Szrj return NULL_TREE;
111238fd1498Szrj }
111338fd1498Szrj
111438fd1498Szrj switch (TREE_CODE (stmt))
111538fd1498Szrj {
111638fd1498Szrj case ADDR_EXPR:
111738fd1498Szrj if (is_invisiref_parm (TREE_OPERAND (stmt, 0)))
111838fd1498Szrj {
111938fd1498Szrj /* If in an OpenMP context, note var uses. */
112038fd1498Szrj if (__builtin_expect (wtd->omp_ctx != NULL, 0)
112138fd1498Szrj && omp_var_to_track (TREE_OPERAND (stmt, 0)))
112238fd1498Szrj omp_cxx_notice_variable (wtd->omp_ctx, TREE_OPERAND (stmt, 0));
112338fd1498Szrj *stmt_p = fold_convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
112438fd1498Szrj *walk_subtrees = 0;
112538fd1498Szrj }
112638fd1498Szrj break;
112738fd1498Szrj
112838fd1498Szrj case RETURN_EXPR:
112938fd1498Szrj if (TREE_OPERAND (stmt, 0) && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
113038fd1498Szrj /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */
113138fd1498Szrj *walk_subtrees = 0;
113238fd1498Szrj break;
113338fd1498Szrj
113438fd1498Szrj case OMP_CLAUSE:
113538fd1498Szrj switch (OMP_CLAUSE_CODE (stmt))
113638fd1498Szrj {
113738fd1498Szrj case OMP_CLAUSE_LASTPRIVATE:
113838fd1498Szrj /* Don't dereference an invisiref in OpenMP clauses. */
113938fd1498Szrj if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
114038fd1498Szrj {
114138fd1498Szrj *walk_subtrees = 0;
114238fd1498Szrj if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt))
114338fd1498Szrj cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt),
114438fd1498Szrj cp_genericize_r, data, NULL);
114538fd1498Szrj }
114638fd1498Szrj break;
114738fd1498Szrj case OMP_CLAUSE_PRIVATE:
114838fd1498Szrj /* Don't dereference an invisiref in OpenMP clauses. */
114938fd1498Szrj if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
115038fd1498Szrj *walk_subtrees = 0;
115138fd1498Szrj else if (wtd->omp_ctx != NULL)
115238fd1498Szrj {
115338fd1498Szrj /* Private clause doesn't cause any references to the
115438fd1498Szrj var in outer contexts, avoid calling
115538fd1498Szrj omp_cxx_notice_variable for it. */
115638fd1498Szrj struct cp_genericize_omp_taskreg *old = wtd->omp_ctx;
115738fd1498Szrj wtd->omp_ctx = NULL;
115838fd1498Szrj cp_walk_tree (&OMP_CLAUSE_DECL (stmt), cp_genericize_r,
115938fd1498Szrj data, NULL);
116038fd1498Szrj wtd->omp_ctx = old;
116138fd1498Szrj *walk_subtrees = 0;
116238fd1498Szrj }
116338fd1498Szrj break;
116438fd1498Szrj case OMP_CLAUSE_SHARED:
116538fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
116638fd1498Szrj case OMP_CLAUSE_COPYIN:
116738fd1498Szrj case OMP_CLAUSE_COPYPRIVATE:
116838fd1498Szrj /* Don't dereference an invisiref in OpenMP clauses. */
116938fd1498Szrj if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
117038fd1498Szrj *walk_subtrees = 0;
117138fd1498Szrj break;
117238fd1498Szrj case OMP_CLAUSE_REDUCTION:
117338fd1498Szrj /* Don't dereference an invisiref in reduction clause's
117438fd1498Szrj OMP_CLAUSE_DECL either. OMP_CLAUSE_REDUCTION_{INIT,MERGE}
117538fd1498Szrj still needs to be genericized. */
117638fd1498Szrj if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
117738fd1498Szrj {
117838fd1498Szrj *walk_subtrees = 0;
117938fd1498Szrj if (OMP_CLAUSE_REDUCTION_INIT (stmt))
118038fd1498Szrj cp_walk_tree (&OMP_CLAUSE_REDUCTION_INIT (stmt),
118138fd1498Szrj cp_genericize_r, data, NULL);
118238fd1498Szrj if (OMP_CLAUSE_REDUCTION_MERGE (stmt))
118338fd1498Szrj cp_walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (stmt),
118438fd1498Szrj cp_genericize_r, data, NULL);
118538fd1498Szrj }
118638fd1498Szrj break;
118738fd1498Szrj default:
118838fd1498Szrj break;
118938fd1498Szrj }
119038fd1498Szrj break;
119138fd1498Szrj
119238fd1498Szrj /* Due to the way voidify_wrapper_expr is written, we don't get a chance
119338fd1498Szrj to lower this construct before scanning it, so we need to lower these
119438fd1498Szrj before doing anything else. */
119538fd1498Szrj case CLEANUP_STMT:
119638fd1498Szrj *stmt_p = build2_loc (EXPR_LOCATION (stmt),
119738fd1498Szrj CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
119838fd1498Szrj : TRY_FINALLY_EXPR,
119938fd1498Szrj void_type_node,
120038fd1498Szrj CLEANUP_BODY (stmt),
120138fd1498Szrj CLEANUP_EXPR (stmt));
120238fd1498Szrj break;
120338fd1498Szrj
120438fd1498Szrj case IF_STMT:
120538fd1498Szrj genericize_if_stmt (stmt_p);
120638fd1498Szrj /* *stmt_p has changed, tail recurse to handle it again. */
120738fd1498Szrj return cp_genericize_r (stmt_p, walk_subtrees, data);
120838fd1498Szrj
120938fd1498Szrj /* COND_EXPR might have incompatible types in branches if one or both
121038fd1498Szrj arms are bitfields. Fix it up now. */
121138fd1498Szrj case COND_EXPR:
121238fd1498Szrj {
121338fd1498Szrj tree type_left
121438fd1498Szrj = (TREE_OPERAND (stmt, 1)
121538fd1498Szrj ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1))
121638fd1498Szrj : NULL_TREE);
121738fd1498Szrj tree type_right
121838fd1498Szrj = (TREE_OPERAND (stmt, 2)
121938fd1498Szrj ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2))
122038fd1498Szrj : NULL_TREE);
122138fd1498Szrj if (type_left
122238fd1498Szrj && !useless_type_conversion_p (TREE_TYPE (stmt),
122338fd1498Szrj TREE_TYPE (TREE_OPERAND (stmt, 1))))
122438fd1498Szrj {
122538fd1498Szrj TREE_OPERAND (stmt, 1)
122638fd1498Szrj = fold_convert (type_left, TREE_OPERAND (stmt, 1));
122738fd1498Szrj gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
122838fd1498Szrj type_left));
122938fd1498Szrj }
123038fd1498Szrj if (type_right
123138fd1498Szrj && !useless_type_conversion_p (TREE_TYPE (stmt),
123238fd1498Szrj TREE_TYPE (TREE_OPERAND (stmt, 2))))
123338fd1498Szrj {
123438fd1498Szrj TREE_OPERAND (stmt, 2)
123538fd1498Szrj = fold_convert (type_right, TREE_OPERAND (stmt, 2));
123638fd1498Szrj gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
123738fd1498Szrj type_right));
123838fd1498Szrj }
123938fd1498Szrj }
124038fd1498Szrj break;
124138fd1498Szrj
124238fd1498Szrj case BIND_EXPR:
124338fd1498Szrj if (__builtin_expect (wtd->omp_ctx != NULL, 0))
124438fd1498Szrj {
124538fd1498Szrj tree decl;
124638fd1498Szrj for (decl = BIND_EXPR_VARS (stmt); decl; decl = DECL_CHAIN (decl))
124738fd1498Szrj if (VAR_P (decl)
124838fd1498Szrj && !DECL_EXTERNAL (decl)
124938fd1498Szrj && omp_var_to_track (decl))
125038fd1498Szrj {
125138fd1498Szrj splay_tree_node n
125238fd1498Szrj = splay_tree_lookup (wtd->omp_ctx->variables,
125338fd1498Szrj (splay_tree_key) decl);
125438fd1498Szrj if (n == NULL)
125538fd1498Szrj splay_tree_insert (wtd->omp_ctx->variables,
125638fd1498Szrj (splay_tree_key) decl,
125738fd1498Szrj TREE_STATIC (decl)
125838fd1498Szrj ? OMP_CLAUSE_DEFAULT_SHARED
125938fd1498Szrj : OMP_CLAUSE_DEFAULT_PRIVATE);
126038fd1498Szrj }
126138fd1498Szrj }
126238fd1498Szrj if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT | SANITIZE_VPTR))
126338fd1498Szrj {
126438fd1498Szrj /* The point here is to not sanitize static initializers. */
126538fd1498Szrj bool no_sanitize_p = wtd->no_sanitize_p;
126638fd1498Szrj wtd->no_sanitize_p = true;
126738fd1498Szrj for (tree decl = BIND_EXPR_VARS (stmt);
126838fd1498Szrj decl;
126938fd1498Szrj decl = DECL_CHAIN (decl))
127038fd1498Szrj if (VAR_P (decl)
127138fd1498Szrj && TREE_STATIC (decl)
127238fd1498Szrj && DECL_INITIAL (decl))
127338fd1498Szrj cp_walk_tree (&DECL_INITIAL (decl), cp_genericize_r, data, NULL);
127438fd1498Szrj wtd->no_sanitize_p = no_sanitize_p;
127538fd1498Szrj }
127638fd1498Szrj wtd->bind_expr_stack.safe_push (stmt);
127738fd1498Szrj cp_walk_tree (&BIND_EXPR_BODY (stmt),
127838fd1498Szrj cp_genericize_r, data, NULL);
127938fd1498Szrj wtd->bind_expr_stack.pop ();
128038fd1498Szrj break;
128138fd1498Szrj
128238fd1498Szrj case USING_STMT:
128338fd1498Szrj {
128438fd1498Szrj tree block = NULL_TREE;
128538fd1498Szrj
128638fd1498Szrj /* Get the innermost inclosing GIMPLE_BIND that has a non NULL
128738fd1498Szrj BLOCK, and append an IMPORTED_DECL to its
128838fd1498Szrj BLOCK_VARS chained list. */
128938fd1498Szrj if (wtd->bind_expr_stack.exists ())
129038fd1498Szrj {
129138fd1498Szrj int i;
129238fd1498Szrj for (i = wtd->bind_expr_stack.length () - 1; i >= 0; i--)
129338fd1498Szrj if ((block = BIND_EXPR_BLOCK (wtd->bind_expr_stack[i])))
129438fd1498Szrj break;
129538fd1498Szrj }
129638fd1498Szrj if (block)
129738fd1498Szrj {
129838fd1498Szrj tree decl = TREE_OPERAND (stmt, 0);
129938fd1498Szrj gcc_assert (decl);
130038fd1498Szrj
130138fd1498Szrj if (undeduced_auto_decl (decl))
130238fd1498Szrj /* Omit from the GENERIC, the back-end can't handle it. */;
130338fd1498Szrj else
130438fd1498Szrj {
130538fd1498Szrj tree using_directive = make_node (IMPORTED_DECL);
130638fd1498Szrj TREE_TYPE (using_directive) = void_type_node;
130738fd1498Szrj
130838fd1498Szrj IMPORTED_DECL_ASSOCIATED_DECL (using_directive) = decl;
130938fd1498Szrj DECL_CHAIN (using_directive) = BLOCK_VARS (block);
131038fd1498Szrj BLOCK_VARS (block) = using_directive;
131138fd1498Szrj }
131238fd1498Szrj }
131338fd1498Szrj /* The USING_STMT won't appear in GENERIC. */
131438fd1498Szrj *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
131538fd1498Szrj *walk_subtrees = 0;
131638fd1498Szrj }
131738fd1498Szrj break;
131838fd1498Szrj
131938fd1498Szrj case DECL_EXPR:
132038fd1498Szrj if (TREE_CODE (DECL_EXPR_DECL (stmt)) == USING_DECL)
132138fd1498Szrj {
132238fd1498Szrj /* Using decls inside DECL_EXPRs are just dropped on the floor. */
132338fd1498Szrj *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
132438fd1498Szrj *walk_subtrees = 0;
132538fd1498Szrj }
132638fd1498Szrj else
132738fd1498Szrj {
132838fd1498Szrj tree d = DECL_EXPR_DECL (stmt);
132938fd1498Szrj if (VAR_P (d))
133038fd1498Szrj gcc_assert (CP_DECL_THREAD_LOCAL_P (d) == DECL_THREAD_LOCAL_P (d));
133138fd1498Szrj }
133238fd1498Szrj break;
133338fd1498Szrj
133438fd1498Szrj case OMP_PARALLEL:
133538fd1498Szrj case OMP_TASK:
133638fd1498Szrj case OMP_TASKLOOP:
133738fd1498Szrj {
133838fd1498Szrj struct cp_genericize_omp_taskreg omp_ctx;
133938fd1498Szrj tree c, decl;
134038fd1498Szrj splay_tree_node n;
134138fd1498Szrj
134238fd1498Szrj *walk_subtrees = 0;
134338fd1498Szrj cp_walk_tree (&OMP_CLAUSES (stmt), cp_genericize_r, data, NULL);
134438fd1498Szrj omp_ctx.is_parallel = TREE_CODE (stmt) == OMP_PARALLEL;
134538fd1498Szrj omp_ctx.default_shared = omp_ctx.is_parallel;
134638fd1498Szrj omp_ctx.outer = wtd->omp_ctx;
134738fd1498Szrj omp_ctx.variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
134838fd1498Szrj wtd->omp_ctx = &omp_ctx;
134938fd1498Szrj for (c = OMP_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
135038fd1498Szrj switch (OMP_CLAUSE_CODE (c))
135138fd1498Szrj {
135238fd1498Szrj case OMP_CLAUSE_SHARED:
135338fd1498Szrj case OMP_CLAUSE_PRIVATE:
135438fd1498Szrj case OMP_CLAUSE_FIRSTPRIVATE:
135538fd1498Szrj case OMP_CLAUSE_LASTPRIVATE:
135638fd1498Szrj decl = OMP_CLAUSE_DECL (c);
135738fd1498Szrj if (decl == error_mark_node || !omp_var_to_track (decl))
135838fd1498Szrj break;
135938fd1498Szrj n = splay_tree_lookup (omp_ctx.variables, (splay_tree_key) decl);
136038fd1498Szrj if (n != NULL)
136138fd1498Szrj break;
136238fd1498Szrj splay_tree_insert (omp_ctx.variables, (splay_tree_key) decl,
136338fd1498Szrj OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
136438fd1498Szrj ? OMP_CLAUSE_DEFAULT_SHARED
136538fd1498Szrj : OMP_CLAUSE_DEFAULT_PRIVATE);
136638fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE && omp_ctx.outer)
136738fd1498Szrj omp_cxx_notice_variable (omp_ctx.outer, decl);
136838fd1498Szrj break;
136938fd1498Szrj case OMP_CLAUSE_DEFAULT:
137038fd1498Szrj if (OMP_CLAUSE_DEFAULT_KIND (c) == OMP_CLAUSE_DEFAULT_SHARED)
137138fd1498Szrj omp_ctx.default_shared = true;
137238fd1498Szrj default:
137338fd1498Szrj break;
137438fd1498Szrj }
137538fd1498Szrj if (TREE_CODE (stmt) == OMP_TASKLOOP)
137638fd1498Szrj genericize_omp_for_stmt (stmt_p, walk_subtrees, data);
137738fd1498Szrj else
137838fd1498Szrj cp_walk_tree (&OMP_BODY (stmt), cp_genericize_r, data, NULL);
137938fd1498Szrj wtd->omp_ctx = omp_ctx.outer;
138038fd1498Szrj splay_tree_delete (omp_ctx.variables);
138138fd1498Szrj }
138238fd1498Szrj break;
138338fd1498Szrj
138438fd1498Szrj case TRY_BLOCK:
138538fd1498Szrj {
138638fd1498Szrj *walk_subtrees = 0;
138738fd1498Szrj tree try_block = wtd->try_block;
138838fd1498Szrj wtd->try_block = stmt;
138938fd1498Szrj cp_walk_tree (&TRY_STMTS (stmt), cp_genericize_r, data, NULL);
139038fd1498Szrj wtd->try_block = try_block;
139138fd1498Szrj cp_walk_tree (&TRY_HANDLERS (stmt), cp_genericize_r, data, NULL);
139238fd1498Szrj }
139338fd1498Szrj break;
139438fd1498Szrj
139538fd1498Szrj case MUST_NOT_THROW_EXPR:
139638fd1498Szrj /* MUST_NOT_THROW_COND might be something else with TM. */
139738fd1498Szrj if (MUST_NOT_THROW_COND (stmt) == NULL_TREE)
139838fd1498Szrj {
139938fd1498Szrj *walk_subtrees = 0;
140038fd1498Szrj tree try_block = wtd->try_block;
140138fd1498Szrj wtd->try_block = stmt;
140238fd1498Szrj cp_walk_tree (&TREE_OPERAND (stmt, 0), cp_genericize_r, data, NULL);
140338fd1498Szrj wtd->try_block = try_block;
140438fd1498Szrj }
140538fd1498Szrj break;
140638fd1498Szrj
140738fd1498Szrj case THROW_EXPR:
140838fd1498Szrj {
140938fd1498Szrj location_t loc = location_of (stmt);
141038fd1498Szrj if (TREE_NO_WARNING (stmt))
141138fd1498Szrj /* Never mind. */;
141238fd1498Szrj else if (wtd->try_block)
141338fd1498Szrj {
141438fd1498Szrj if (TREE_CODE (wtd->try_block) == MUST_NOT_THROW_EXPR
141538fd1498Szrj && warning_at (loc, OPT_Wterminate,
141638fd1498Szrj "throw will always call terminate()")
141738fd1498Szrj && cxx_dialect >= cxx11
141838fd1498Szrj && DECL_DESTRUCTOR_P (current_function_decl))
141938fd1498Szrj inform (loc, "in C++11 destructors default to noexcept");
142038fd1498Szrj }
142138fd1498Szrj else
142238fd1498Szrj {
142338fd1498Szrj if (warn_cxx11_compat && cxx_dialect < cxx11
142438fd1498Szrj && DECL_DESTRUCTOR_P (current_function_decl)
142538fd1498Szrj && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl))
142638fd1498Szrj == NULL_TREE)
142738fd1498Szrj && (get_defaulted_eh_spec (current_function_decl)
142838fd1498Szrj == empty_except_spec))
142938fd1498Szrj warning_at (loc, OPT_Wc__11_compat,
143038fd1498Szrj "in C++11 this throw will terminate because "
143138fd1498Szrj "destructors default to noexcept");
143238fd1498Szrj }
143338fd1498Szrj }
143438fd1498Szrj break;
143538fd1498Szrj
143638fd1498Szrj case CONVERT_EXPR:
143738fd1498Szrj gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt));
143838fd1498Szrj break;
143938fd1498Szrj
144038fd1498Szrj case FOR_STMT:
144138fd1498Szrj genericize_for_stmt (stmt_p, walk_subtrees, data);
144238fd1498Szrj break;
144338fd1498Szrj
144438fd1498Szrj case WHILE_STMT:
144538fd1498Szrj genericize_while_stmt (stmt_p, walk_subtrees, data);
144638fd1498Szrj break;
144738fd1498Szrj
144838fd1498Szrj case DO_STMT:
144938fd1498Szrj genericize_do_stmt (stmt_p, walk_subtrees, data);
145038fd1498Szrj break;
145138fd1498Szrj
145238fd1498Szrj case SWITCH_STMT:
145338fd1498Szrj genericize_switch_stmt (stmt_p, walk_subtrees, data);
145438fd1498Szrj break;
145538fd1498Szrj
145638fd1498Szrj case CONTINUE_STMT:
145738fd1498Szrj genericize_continue_stmt (stmt_p);
145838fd1498Szrj break;
145938fd1498Szrj
146038fd1498Szrj case BREAK_STMT:
146138fd1498Szrj genericize_break_stmt (stmt_p);
146238fd1498Szrj break;
146338fd1498Szrj
146438fd1498Szrj case OMP_FOR:
146538fd1498Szrj case OMP_SIMD:
146638fd1498Szrj case OMP_DISTRIBUTE:
1467*58e805e6Szrj case OACC_LOOP:
146838fd1498Szrj genericize_omp_for_stmt (stmt_p, walk_subtrees, data);
146938fd1498Szrj break;
147038fd1498Szrj
147138fd1498Szrj case PTRMEM_CST:
147238fd1498Szrj /* By the time we get here we're handing off to the back end, so we don't
147338fd1498Szrj need or want to preserve PTRMEM_CST anymore. */
147438fd1498Szrj *stmt_p = cplus_expand_constant (stmt);
147538fd1498Szrj *walk_subtrees = 0;
147638fd1498Szrj break;
147738fd1498Szrj
147838fd1498Szrj case MEM_REF:
147938fd1498Szrj /* For MEM_REF, make sure not to sanitize the second operand even
148038fd1498Szrj if it has reference type. It is just an offset with a type
148138fd1498Szrj holding other information. There is no other processing we
148238fd1498Szrj need to do for INTEGER_CSTs, so just ignore the second argument
148338fd1498Szrj unconditionally. */
148438fd1498Szrj cp_walk_tree (&TREE_OPERAND (stmt, 0), cp_genericize_r, data, NULL);
148538fd1498Szrj *walk_subtrees = 0;
148638fd1498Szrj break;
148738fd1498Szrj
148838fd1498Szrj case NOP_EXPR:
148938fd1498Szrj if (!wtd->no_sanitize_p
149038fd1498Szrj && sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT)
149138fd1498Szrj && TREE_CODE (TREE_TYPE (stmt)) == REFERENCE_TYPE)
149238fd1498Szrj ubsan_maybe_instrument_reference (stmt_p);
149338fd1498Szrj break;
149438fd1498Szrj
149538fd1498Szrj case CALL_EXPR:
149638fd1498Szrj if (!wtd->no_sanitize_p
149738fd1498Szrj && sanitize_flags_p ((SANITIZE_NULL
149838fd1498Szrj | SANITIZE_ALIGNMENT | SANITIZE_VPTR)))
149938fd1498Szrj {
150038fd1498Szrj tree fn = CALL_EXPR_FN (stmt);
150138fd1498Szrj if (fn != NULL_TREE
150238fd1498Szrj && !error_operand_p (fn)
150338fd1498Szrj && POINTER_TYPE_P (TREE_TYPE (fn))
150438fd1498Szrj && TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) == METHOD_TYPE)
150538fd1498Szrj {
150638fd1498Szrj bool is_ctor
150738fd1498Szrj = TREE_CODE (fn) == ADDR_EXPR
150838fd1498Szrj && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
150938fd1498Szrj && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0));
151038fd1498Szrj if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT))
151138fd1498Szrj ubsan_maybe_instrument_member_call (stmt, is_ctor);
151238fd1498Szrj if (sanitize_flags_p (SANITIZE_VPTR) && !is_ctor)
151338fd1498Szrj cp_ubsan_maybe_instrument_member_call (stmt);
151438fd1498Szrj }
151538fd1498Szrj else if (fn == NULL_TREE
151638fd1498Szrj && CALL_EXPR_IFN (stmt) == IFN_UBSAN_NULL
151738fd1498Szrj && TREE_CODE (CALL_EXPR_ARG (stmt, 0)) == INTEGER_CST
151838fd1498Szrj && (TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (stmt, 0)))
151938fd1498Szrj == REFERENCE_TYPE))
152038fd1498Szrj *walk_subtrees = 0;
152138fd1498Szrj }
152238fd1498Szrj /* Fall through. */
152338fd1498Szrj case AGGR_INIT_EXPR:
152438fd1498Szrj /* For calls to a multi-versioned function, overload resolution
152538fd1498Szrj returns the function with the highest target priority, that is,
152638fd1498Szrj the version that will checked for dispatching first. If this
152738fd1498Szrj version is inlinable, a direct call to this version can be made
152838fd1498Szrj otherwise the call should go through the dispatcher. */
152938fd1498Szrj {
153038fd1498Szrj tree fn = cp_get_callee_fndecl_nofold (stmt);
153138fd1498Szrj if (fn && DECL_FUNCTION_VERSIONED (fn)
153238fd1498Szrj && (current_function_decl == NULL
153338fd1498Szrj || !targetm.target_option.can_inline_p (current_function_decl,
153438fd1498Szrj fn)))
153538fd1498Szrj if (tree dis = get_function_version_dispatcher (fn))
153638fd1498Szrj {
153738fd1498Szrj mark_versions_used (dis);
153838fd1498Szrj dis = build_address (dis);
153938fd1498Szrj if (TREE_CODE (stmt) == CALL_EXPR)
154038fd1498Szrj CALL_EXPR_FN (stmt) = dis;
154138fd1498Szrj else
154238fd1498Szrj AGGR_INIT_EXPR_FN (stmt) = dis;
154338fd1498Szrj }
154438fd1498Szrj }
154538fd1498Szrj break;
154638fd1498Szrj
154738fd1498Szrj case TARGET_EXPR:
154838fd1498Szrj if (TARGET_EXPR_INITIAL (stmt)
154938fd1498Szrj && TREE_CODE (TARGET_EXPR_INITIAL (stmt)) == CONSTRUCTOR
155038fd1498Szrj && CONSTRUCTOR_PLACEHOLDER_BOUNDARY (TARGET_EXPR_INITIAL (stmt)))
155138fd1498Szrj TARGET_EXPR_NO_ELIDE (stmt) = 1;
155238fd1498Szrj break;
155338fd1498Szrj
155438fd1498Szrj default:
155538fd1498Szrj if (IS_TYPE_OR_DECL_P (stmt))
155638fd1498Szrj *walk_subtrees = 0;
155738fd1498Szrj break;
155838fd1498Szrj }
155938fd1498Szrj
156038fd1498Szrj p_set->add (*stmt_p);
156138fd1498Szrj
156238fd1498Szrj return NULL;
156338fd1498Szrj }
156438fd1498Szrj
156538fd1498Szrj /* Lower C++ front end trees to GENERIC in T_P. */
156638fd1498Szrj
156738fd1498Szrj static void
cp_genericize_tree(tree * t_p,bool handle_invisiref_parm_p)156838fd1498Szrj cp_genericize_tree (tree* t_p, bool handle_invisiref_parm_p)
156938fd1498Szrj {
157038fd1498Szrj struct cp_genericize_data wtd;
157138fd1498Szrj
157238fd1498Szrj wtd.p_set = new hash_set<tree>;
157338fd1498Szrj wtd.bind_expr_stack.create (0);
157438fd1498Szrj wtd.omp_ctx = NULL;
157538fd1498Szrj wtd.try_block = NULL_TREE;
157638fd1498Szrj wtd.no_sanitize_p = false;
157738fd1498Szrj wtd.handle_invisiref_parm_p = handle_invisiref_parm_p;
157838fd1498Szrj cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
157938fd1498Szrj delete wtd.p_set;
158038fd1498Szrj wtd.bind_expr_stack.release ();
158138fd1498Szrj if (sanitize_flags_p (SANITIZE_VPTR))
158238fd1498Szrj cp_ubsan_instrument_member_accesses (t_p);
158338fd1498Szrj }
158438fd1498Szrj
158538fd1498Szrj /* If a function that should end with a return in non-void
158638fd1498Szrj function doesn't obviously end with return, add ubsan
158738fd1498Szrj instrumentation code to verify it at runtime. If -fsanitize=return
158838fd1498Szrj is not enabled, instrument __builtin_unreachable. */
158938fd1498Szrj
159038fd1498Szrj static void
cp_maybe_instrument_return(tree fndecl)159138fd1498Szrj cp_maybe_instrument_return (tree fndecl)
159238fd1498Szrj {
159338fd1498Szrj if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
159438fd1498Szrj || DECL_CONSTRUCTOR_P (fndecl)
159538fd1498Szrj || DECL_DESTRUCTOR_P (fndecl)
159638fd1498Szrj || !targetm.warn_func_return (fndecl))
159738fd1498Szrj return;
159838fd1498Szrj
159938fd1498Szrj if (!sanitize_flags_p (SANITIZE_RETURN, fndecl)
160038fd1498Szrj /* Don't add __builtin_unreachable () if not optimizing, it will not
160138fd1498Szrj improve any optimizations in that case, just break UB code.
160238fd1498Szrj Don't add it if -fsanitize=unreachable -fno-sanitize=return either,
160338fd1498Szrj UBSan covers this with ubsan_instrument_return above where sufficient
160438fd1498Szrj information is provided, while the __builtin_unreachable () below
160538fd1498Szrj if return sanitization is disabled will just result in hard to
160638fd1498Szrj understand runtime error without location. */
160738fd1498Szrj && (!optimize
160838fd1498Szrj || sanitize_flags_p (SANITIZE_UNREACHABLE, fndecl)))
160938fd1498Szrj return;
161038fd1498Szrj
161138fd1498Szrj tree t = DECL_SAVED_TREE (fndecl);
161238fd1498Szrj while (t)
161338fd1498Szrj {
161438fd1498Szrj switch (TREE_CODE (t))
161538fd1498Szrj {
161638fd1498Szrj case BIND_EXPR:
161738fd1498Szrj t = BIND_EXPR_BODY (t);
161838fd1498Szrj continue;
161938fd1498Szrj case TRY_FINALLY_EXPR:
162038fd1498Szrj case CLEANUP_POINT_EXPR:
162138fd1498Szrj t = TREE_OPERAND (t, 0);
162238fd1498Szrj continue;
162338fd1498Szrj case STATEMENT_LIST:
162438fd1498Szrj {
162538fd1498Szrj tree_stmt_iterator i = tsi_last (t);
1626*58e805e6Szrj while (!tsi_end_p (i))
1627*58e805e6Szrj {
1628*58e805e6Szrj tree p = tsi_stmt (i);
1629*58e805e6Szrj if (TREE_CODE (p) != DEBUG_BEGIN_STMT)
1630*58e805e6Szrj break;
1631*58e805e6Szrj tsi_prev (&i);
1632*58e805e6Szrj }
163338fd1498Szrj if (!tsi_end_p (i))
163438fd1498Szrj {
163538fd1498Szrj t = tsi_stmt (i);
163638fd1498Szrj continue;
163738fd1498Szrj }
163838fd1498Szrj }
163938fd1498Szrj break;
164038fd1498Szrj case RETURN_EXPR:
164138fd1498Szrj return;
164238fd1498Szrj default:
164338fd1498Szrj break;
164438fd1498Szrj }
164538fd1498Szrj break;
164638fd1498Szrj }
164738fd1498Szrj if (t == NULL_TREE)
164838fd1498Szrj return;
164938fd1498Szrj tree *p = &DECL_SAVED_TREE (fndecl);
165038fd1498Szrj if (TREE_CODE (*p) == BIND_EXPR)
165138fd1498Szrj p = &BIND_EXPR_BODY (*p);
165238fd1498Szrj
165338fd1498Szrj location_t loc = DECL_SOURCE_LOCATION (fndecl);
165438fd1498Szrj if (sanitize_flags_p (SANITIZE_RETURN, fndecl))
165538fd1498Szrj t = ubsan_instrument_return (loc);
165638fd1498Szrj else
165738fd1498Szrj {
165838fd1498Szrj tree fndecl = builtin_decl_explicit (BUILT_IN_UNREACHABLE);
165938fd1498Szrj t = build_call_expr_loc (BUILTINS_LOCATION, fndecl, 0);
166038fd1498Szrj }
166138fd1498Szrj
166238fd1498Szrj append_to_statement_list (t, p);
166338fd1498Szrj }
166438fd1498Szrj
166538fd1498Szrj void
cp_genericize(tree fndecl)166638fd1498Szrj cp_genericize (tree fndecl)
166738fd1498Szrj {
166838fd1498Szrj tree t;
166938fd1498Szrj
167038fd1498Szrj /* Fix up the types of parms passed by invisible reference. */
167138fd1498Szrj for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t))
167238fd1498Szrj if (TREE_ADDRESSABLE (TREE_TYPE (t)))
167338fd1498Szrj {
167438fd1498Szrj /* If a function's arguments are copied to create a thunk,
167538fd1498Szrj then DECL_BY_REFERENCE will be set -- but the type of the
167638fd1498Szrj argument will be a pointer type, so we will never get
167738fd1498Szrj here. */
167838fd1498Szrj gcc_assert (!DECL_BY_REFERENCE (t));
167938fd1498Szrj gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
168038fd1498Szrj TREE_TYPE (t) = DECL_ARG_TYPE (t);
168138fd1498Szrj DECL_BY_REFERENCE (t) = 1;
168238fd1498Szrj TREE_ADDRESSABLE (t) = 0;
168338fd1498Szrj relayout_decl (t);
168438fd1498Szrj }
168538fd1498Szrj
168638fd1498Szrj /* Do the same for the return value. */
168738fd1498Szrj if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
168838fd1498Szrj {
168938fd1498Szrj t = DECL_RESULT (fndecl);
169038fd1498Szrj TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
169138fd1498Szrj DECL_BY_REFERENCE (t) = 1;
169238fd1498Szrj TREE_ADDRESSABLE (t) = 0;
169338fd1498Szrj relayout_decl (t);
169438fd1498Szrj if (DECL_NAME (t))
169538fd1498Szrj {
169638fd1498Szrj /* Adjust DECL_VALUE_EXPR of the original var. */
169738fd1498Szrj tree outer = outer_curly_brace_block (current_function_decl);
169838fd1498Szrj tree var;
169938fd1498Szrj
170038fd1498Szrj if (outer)
170138fd1498Szrj for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
170238fd1498Szrj if (VAR_P (var)
170338fd1498Szrj && DECL_NAME (t) == DECL_NAME (var)
170438fd1498Szrj && DECL_HAS_VALUE_EXPR_P (var)
170538fd1498Szrj && DECL_VALUE_EXPR (var) == t)
170638fd1498Szrj {
170738fd1498Szrj tree val = convert_from_reference (t);
170838fd1498Szrj SET_DECL_VALUE_EXPR (var, val);
170938fd1498Szrj break;
171038fd1498Szrj }
171138fd1498Szrj }
171238fd1498Szrj }
171338fd1498Szrj
171438fd1498Szrj /* If we're a clone, the body is already GIMPLE. */
171538fd1498Szrj if (DECL_CLONED_FUNCTION_P (fndecl))
171638fd1498Szrj return;
171738fd1498Szrj
171838fd1498Szrj /* Allow cp_genericize calls to be nested. */
171938fd1498Szrj tree save_bc_label[2];
172038fd1498Szrj save_bc_label[bc_break] = bc_label[bc_break];
172138fd1498Szrj save_bc_label[bc_continue] = bc_label[bc_continue];
172238fd1498Szrj bc_label[bc_break] = NULL_TREE;
172338fd1498Szrj bc_label[bc_continue] = NULL_TREE;
172438fd1498Szrj
172538fd1498Szrj /* We do want to see every occurrence of the parms, so we can't just use
172638fd1498Szrj walk_tree's hash functionality. */
172738fd1498Szrj cp_genericize_tree (&DECL_SAVED_TREE (fndecl), true);
172838fd1498Szrj
172938fd1498Szrj cp_maybe_instrument_return (fndecl);
173038fd1498Szrj
173138fd1498Szrj /* Do everything else. */
173238fd1498Szrj c_genericize (fndecl);
173338fd1498Szrj
173438fd1498Szrj gcc_assert (bc_label[bc_break] == NULL);
173538fd1498Szrj gcc_assert (bc_label[bc_continue] == NULL);
173638fd1498Szrj bc_label[bc_break] = save_bc_label[bc_break];
173738fd1498Szrj bc_label[bc_continue] = save_bc_label[bc_continue];
173838fd1498Szrj }
173938fd1498Szrj
174038fd1498Szrj /* Build code to apply FN to each member of ARG1 and ARG2. FN may be
174138fd1498Szrj NULL if there is in fact nothing to do. ARG2 may be null if FN
174238fd1498Szrj actually only takes one argument. */
174338fd1498Szrj
174438fd1498Szrj static tree
cxx_omp_clause_apply_fn(tree fn,tree arg1,tree arg2)174538fd1498Szrj cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
174638fd1498Szrj {
174738fd1498Szrj tree defparm, parm, t;
174838fd1498Szrj int i = 0;
174938fd1498Szrj int nargs;
175038fd1498Szrj tree *argarray;
175138fd1498Szrj
175238fd1498Szrj if (fn == NULL)
175338fd1498Szrj return NULL;
175438fd1498Szrj
175538fd1498Szrj nargs = list_length (DECL_ARGUMENTS (fn));
175638fd1498Szrj argarray = XALLOCAVEC (tree, nargs);
175738fd1498Szrj
175838fd1498Szrj defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
175938fd1498Szrj if (arg2)
176038fd1498Szrj defparm = TREE_CHAIN (defparm);
176138fd1498Szrj
176238fd1498Szrj bool is_method = TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE;
176338fd1498Szrj if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
176438fd1498Szrj {
176538fd1498Szrj tree inner_type = TREE_TYPE (arg1);
176638fd1498Szrj tree start1, end1, p1;
176738fd1498Szrj tree start2 = NULL, p2 = NULL;
176838fd1498Szrj tree ret = NULL, lab;
176938fd1498Szrj
177038fd1498Szrj start1 = arg1;
177138fd1498Szrj start2 = arg2;
177238fd1498Szrj do
177338fd1498Szrj {
177438fd1498Szrj inner_type = TREE_TYPE (inner_type);
177538fd1498Szrj start1 = build4 (ARRAY_REF, inner_type, start1,
177638fd1498Szrj size_zero_node, NULL, NULL);
177738fd1498Szrj if (arg2)
177838fd1498Szrj start2 = build4 (ARRAY_REF, inner_type, start2,
177938fd1498Szrj size_zero_node, NULL, NULL);
178038fd1498Szrj }
178138fd1498Szrj while (TREE_CODE (inner_type) == ARRAY_TYPE);
178238fd1498Szrj start1 = build_fold_addr_expr_loc (input_location, start1);
178338fd1498Szrj if (arg2)
178438fd1498Szrj start2 = build_fold_addr_expr_loc (input_location, start2);
178538fd1498Szrj
178638fd1498Szrj end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
178738fd1498Szrj end1 = fold_build_pointer_plus (start1, end1);
178838fd1498Szrj
178938fd1498Szrj p1 = create_tmp_var (TREE_TYPE (start1));
179038fd1498Szrj t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, start1);
179138fd1498Szrj append_to_statement_list (t, &ret);
179238fd1498Szrj
179338fd1498Szrj if (arg2)
179438fd1498Szrj {
179538fd1498Szrj p2 = create_tmp_var (TREE_TYPE (start2));
179638fd1498Szrj t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, start2);
179738fd1498Szrj append_to_statement_list (t, &ret);
179838fd1498Szrj }
179938fd1498Szrj
180038fd1498Szrj lab = create_artificial_label (input_location);
180138fd1498Szrj t = build1 (LABEL_EXPR, void_type_node, lab);
180238fd1498Szrj append_to_statement_list (t, &ret);
180338fd1498Szrj
180438fd1498Szrj argarray[i++] = p1;
180538fd1498Szrj if (arg2)
180638fd1498Szrj argarray[i++] = p2;
180738fd1498Szrj /* Handle default arguments. */
180838fd1498Szrj for (parm = defparm; parm && parm != void_list_node;
180938fd1498Szrj parm = TREE_CHAIN (parm), i++)
181038fd1498Szrj argarray[i] = convert_default_arg (TREE_VALUE (parm),
181138fd1498Szrj TREE_PURPOSE (parm), fn,
181238fd1498Szrj i - is_method, tf_warning_or_error);
181338fd1498Szrj t = build_call_a (fn, i, argarray);
181438fd1498Szrj t = fold_convert (void_type_node, t);
181538fd1498Szrj t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
181638fd1498Szrj append_to_statement_list (t, &ret);
181738fd1498Szrj
181838fd1498Szrj t = fold_build_pointer_plus (p1, TYPE_SIZE_UNIT (inner_type));
181938fd1498Szrj t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, t);
182038fd1498Szrj append_to_statement_list (t, &ret);
182138fd1498Szrj
182238fd1498Szrj if (arg2)
182338fd1498Szrj {
182438fd1498Szrj t = fold_build_pointer_plus (p2, TYPE_SIZE_UNIT (inner_type));
182538fd1498Szrj t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, t);
182638fd1498Szrj append_to_statement_list (t, &ret);
182738fd1498Szrj }
182838fd1498Szrj
182938fd1498Szrj t = build2 (NE_EXPR, boolean_type_node, p1, end1);
183038fd1498Szrj t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
183138fd1498Szrj append_to_statement_list (t, &ret);
183238fd1498Szrj
183338fd1498Szrj return ret;
183438fd1498Szrj }
183538fd1498Szrj else
183638fd1498Szrj {
183738fd1498Szrj argarray[i++] = build_fold_addr_expr_loc (input_location, arg1);
183838fd1498Szrj if (arg2)
183938fd1498Szrj argarray[i++] = build_fold_addr_expr_loc (input_location, arg2);
184038fd1498Szrj /* Handle default arguments. */
184138fd1498Szrj for (parm = defparm; parm && parm != void_list_node;
184238fd1498Szrj parm = TREE_CHAIN (parm), i++)
184338fd1498Szrj argarray[i] = convert_default_arg (TREE_VALUE (parm),
184438fd1498Szrj TREE_PURPOSE (parm), fn,
184538fd1498Szrj i - is_method, tf_warning_or_error);
184638fd1498Szrj t = build_call_a (fn, i, argarray);
184738fd1498Szrj t = fold_convert (void_type_node, t);
184838fd1498Szrj return fold_build_cleanup_point_expr (TREE_TYPE (t), t);
184938fd1498Szrj }
185038fd1498Szrj }
185138fd1498Szrj
185238fd1498Szrj /* Return code to initialize DECL with its default constructor, or
185338fd1498Szrj NULL if there's nothing to do. */
185438fd1498Szrj
185538fd1498Szrj tree
cxx_omp_clause_default_ctor(tree clause,tree decl,tree)185638fd1498Szrj cxx_omp_clause_default_ctor (tree clause, tree decl, tree /*outer*/)
185738fd1498Szrj {
185838fd1498Szrj tree info = CP_OMP_CLAUSE_INFO (clause);
185938fd1498Szrj tree ret = NULL;
186038fd1498Szrj
186138fd1498Szrj if (info)
186238fd1498Szrj ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
186338fd1498Szrj
186438fd1498Szrj return ret;
186538fd1498Szrj }
186638fd1498Szrj
186738fd1498Szrj /* Return code to initialize DST with a copy constructor from SRC. */
186838fd1498Szrj
186938fd1498Szrj tree
cxx_omp_clause_copy_ctor(tree clause,tree dst,tree src)187038fd1498Szrj cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
187138fd1498Szrj {
187238fd1498Szrj tree info = CP_OMP_CLAUSE_INFO (clause);
187338fd1498Szrj tree ret = NULL;
187438fd1498Szrj
187538fd1498Szrj if (info)
187638fd1498Szrj ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
187738fd1498Szrj if (ret == NULL)
187838fd1498Szrj ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
187938fd1498Szrj
188038fd1498Szrj return ret;
188138fd1498Szrj }
188238fd1498Szrj
188338fd1498Szrj /* Similarly, except use an assignment operator instead. */
188438fd1498Szrj
188538fd1498Szrj tree
cxx_omp_clause_assign_op(tree clause,tree dst,tree src)188638fd1498Szrj cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
188738fd1498Szrj {
188838fd1498Szrj tree info = CP_OMP_CLAUSE_INFO (clause);
188938fd1498Szrj tree ret = NULL;
189038fd1498Szrj
189138fd1498Szrj if (info)
189238fd1498Szrj ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
189338fd1498Szrj if (ret == NULL)
189438fd1498Szrj ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
189538fd1498Szrj
189638fd1498Szrj return ret;
189738fd1498Szrj }
189838fd1498Szrj
189938fd1498Szrj /* Return code to destroy DECL. */
190038fd1498Szrj
190138fd1498Szrj tree
cxx_omp_clause_dtor(tree clause,tree decl)190238fd1498Szrj cxx_omp_clause_dtor (tree clause, tree decl)
190338fd1498Szrj {
190438fd1498Szrj tree info = CP_OMP_CLAUSE_INFO (clause);
190538fd1498Szrj tree ret = NULL;
190638fd1498Szrj
190738fd1498Szrj if (info)
190838fd1498Szrj ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
190938fd1498Szrj
191038fd1498Szrj return ret;
191138fd1498Szrj }
191238fd1498Szrj
191338fd1498Szrj /* True if OpenMP should privatize what this DECL points to rather
191438fd1498Szrj than the DECL itself. */
191538fd1498Szrj
191638fd1498Szrj bool
cxx_omp_privatize_by_reference(const_tree decl)191738fd1498Szrj cxx_omp_privatize_by_reference (const_tree decl)
191838fd1498Szrj {
191938fd1498Szrj return (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE
192038fd1498Szrj || is_invisiref_parm (decl));
192138fd1498Szrj }
192238fd1498Szrj
192338fd1498Szrj /* Return true if DECL is const qualified var having no mutable member. */
192438fd1498Szrj bool
cxx_omp_const_qual_no_mutable(tree decl)192538fd1498Szrj cxx_omp_const_qual_no_mutable (tree decl)
192638fd1498Szrj {
192738fd1498Szrj tree type = TREE_TYPE (decl);
192838fd1498Szrj if (TREE_CODE (type) == REFERENCE_TYPE)
192938fd1498Szrj {
193038fd1498Szrj if (!is_invisiref_parm (decl))
193138fd1498Szrj return false;
193238fd1498Szrj type = TREE_TYPE (type);
193338fd1498Szrj
193438fd1498Szrj if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl))
193538fd1498Szrj {
193638fd1498Szrj /* NVR doesn't preserve const qualification of the
193738fd1498Szrj variable's type. */
193838fd1498Szrj tree outer = outer_curly_brace_block (current_function_decl);
193938fd1498Szrj tree var;
194038fd1498Szrj
194138fd1498Szrj if (outer)
194238fd1498Szrj for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
194338fd1498Szrj if (VAR_P (var)
194438fd1498Szrj && DECL_NAME (decl) == DECL_NAME (var)
194538fd1498Szrj && (TYPE_MAIN_VARIANT (type)
194638fd1498Szrj == TYPE_MAIN_VARIANT (TREE_TYPE (var))))
194738fd1498Szrj {
194838fd1498Szrj if (TYPE_READONLY (TREE_TYPE (var)))
194938fd1498Szrj type = TREE_TYPE (var);
195038fd1498Szrj break;
195138fd1498Szrj }
195238fd1498Szrj }
195338fd1498Szrj }
195438fd1498Szrj
195538fd1498Szrj if (type == error_mark_node)
195638fd1498Szrj return false;
195738fd1498Szrj
195838fd1498Szrj /* Variables with const-qualified type having no mutable member
195938fd1498Szrj are predetermined shared. */
196038fd1498Szrj if (TYPE_READONLY (type) && !cp_has_mutable_p (type))
196138fd1498Szrj return true;
196238fd1498Szrj
196338fd1498Szrj return false;
196438fd1498Szrj }
196538fd1498Szrj
196638fd1498Szrj /* True if OpenMP sharing attribute of DECL is predetermined. */
196738fd1498Szrj
196838fd1498Szrj enum omp_clause_default_kind
cxx_omp_predetermined_sharing_1(tree decl)1969*58e805e6Szrj cxx_omp_predetermined_sharing_1 (tree decl)
197038fd1498Szrj {
197138fd1498Szrj /* Static data members are predetermined shared. */
197238fd1498Szrj if (TREE_STATIC (decl))
197338fd1498Szrj {
197438fd1498Szrj tree ctx = CP_DECL_CONTEXT (decl);
197538fd1498Szrj if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
197638fd1498Szrj return OMP_CLAUSE_DEFAULT_SHARED;
197738fd1498Szrj }
197838fd1498Szrj
197938fd1498Szrj /* Const qualified vars having no mutable member are predetermined
198038fd1498Szrj shared. */
198138fd1498Szrj if (cxx_omp_const_qual_no_mutable (decl))
198238fd1498Szrj return OMP_CLAUSE_DEFAULT_SHARED;
198338fd1498Szrj
198438fd1498Szrj return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
198538fd1498Szrj }
198638fd1498Szrj
1987*58e805e6Szrj /* Likewise, but also include the artificial vars. We don't want to
1988*58e805e6Szrj disallow the artificial vars being mentioned in explicit clauses,
1989*58e805e6Szrj as we use artificial vars e.g. for loop constructs with random
1990*58e805e6Szrj access iterators other than pointers, but during gimplification
1991*58e805e6Szrj we want to treat them as predetermined. */
1992*58e805e6Szrj
1993*58e805e6Szrj enum omp_clause_default_kind
cxx_omp_predetermined_sharing(tree decl)1994*58e805e6Szrj cxx_omp_predetermined_sharing (tree decl)
1995*58e805e6Szrj {
1996*58e805e6Szrj enum omp_clause_default_kind ret = cxx_omp_predetermined_sharing_1 (decl);
1997*58e805e6Szrj if (ret != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
1998*58e805e6Szrj return ret;
1999*58e805e6Szrj
2000*58e805e6Szrj /* Predetermine artificial variables holding integral values, those
2001*58e805e6Szrj are usually result of gimplify_one_sizepos or SAVE_EXPR
2002*58e805e6Szrj gimplification. */
2003*58e805e6Szrj if (VAR_P (decl)
2004*58e805e6Szrj && DECL_ARTIFICIAL (decl)
2005*58e805e6Szrj && INTEGRAL_TYPE_P (TREE_TYPE (decl))
2006*58e805e6Szrj && !(DECL_LANG_SPECIFIC (decl)
2007*58e805e6Szrj && DECL_OMP_PRIVATIZED_MEMBER (decl)))
2008*58e805e6Szrj return OMP_CLAUSE_DEFAULT_SHARED;
2009*58e805e6Szrj
2010*58e805e6Szrj return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
2011*58e805e6Szrj }
2012*58e805e6Szrj
201338fd1498Szrj /* Finalize an implicitly determined clause. */
201438fd1498Szrj
201538fd1498Szrj void
cxx_omp_finish_clause(tree c,gimple_seq *)201638fd1498Szrj cxx_omp_finish_clause (tree c, gimple_seq *)
201738fd1498Szrj {
201838fd1498Szrj tree decl, inner_type;
201938fd1498Szrj bool make_shared = false;
202038fd1498Szrj
202138fd1498Szrj if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
202238fd1498Szrj return;
202338fd1498Szrj
202438fd1498Szrj decl = OMP_CLAUSE_DECL (c);
202538fd1498Szrj decl = require_complete_type (decl);
202638fd1498Szrj inner_type = TREE_TYPE (decl);
202738fd1498Szrj if (decl == error_mark_node)
202838fd1498Szrj make_shared = true;
202938fd1498Szrj else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
203038fd1498Szrj inner_type = TREE_TYPE (inner_type);
203138fd1498Szrj
203238fd1498Szrj /* We're interested in the base element, not arrays. */
203338fd1498Szrj while (TREE_CODE (inner_type) == ARRAY_TYPE)
203438fd1498Szrj inner_type = TREE_TYPE (inner_type);
203538fd1498Szrj
203638fd1498Szrj /* Check for special function availability by building a call to one.
203738fd1498Szrj Save the results, because later we won't be in the right context
203838fd1498Szrj for making these queries. */
203938fd1498Szrj if (!make_shared
204038fd1498Szrj && CLASS_TYPE_P (inner_type)
204138fd1498Szrj && cxx_omp_create_clause_info (c, inner_type, false, true, false, true))
204238fd1498Szrj make_shared = true;
204338fd1498Szrj
204438fd1498Szrj if (make_shared)
204538fd1498Szrj {
204638fd1498Szrj OMP_CLAUSE_CODE (c) = OMP_CLAUSE_SHARED;
204738fd1498Szrj OMP_CLAUSE_SHARED_FIRSTPRIVATE (c) = 0;
204838fd1498Szrj OMP_CLAUSE_SHARED_READONLY (c) = 0;
204938fd1498Szrj }
205038fd1498Szrj }
205138fd1498Szrj
205238fd1498Szrj /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
205338fd1498Szrj disregarded in OpenMP construct, because it is going to be
205438fd1498Szrj remapped during OpenMP lowering. SHARED is true if DECL
205538fd1498Szrj is going to be shared, false if it is going to be privatized. */
205638fd1498Szrj
205738fd1498Szrj bool
cxx_omp_disregard_value_expr(tree decl,bool shared)205838fd1498Szrj cxx_omp_disregard_value_expr (tree decl, bool shared)
205938fd1498Szrj {
206038fd1498Szrj return !shared
206138fd1498Szrj && VAR_P (decl)
206238fd1498Szrj && DECL_HAS_VALUE_EXPR_P (decl)
206338fd1498Szrj && DECL_ARTIFICIAL (decl)
206438fd1498Szrj && DECL_LANG_SPECIFIC (decl)
206538fd1498Szrj && DECL_OMP_PRIVATIZED_MEMBER (decl);
206638fd1498Szrj }
206738fd1498Szrj
206838fd1498Szrj /* Fold expression X which is used as an rvalue if RVAL is true. */
206938fd1498Szrj
207038fd1498Szrj static tree
cp_fold_maybe_rvalue(tree x,bool rval)207138fd1498Szrj cp_fold_maybe_rvalue (tree x, bool rval)
207238fd1498Szrj {
207338fd1498Szrj while (true)
207438fd1498Szrj {
207538fd1498Szrj x = cp_fold (x);
207638fd1498Szrj if (rval && DECL_P (x)
207738fd1498Szrj && TREE_CODE (TREE_TYPE (x)) != REFERENCE_TYPE)
207838fd1498Szrj {
207938fd1498Szrj tree v = decl_constant_value (x);
208038fd1498Szrj if (v != x && v != error_mark_node)
208138fd1498Szrj {
208238fd1498Szrj x = v;
208338fd1498Szrj continue;
208438fd1498Szrj }
208538fd1498Szrj }
208638fd1498Szrj break;
208738fd1498Szrj }
208838fd1498Szrj return x;
208938fd1498Szrj }
209038fd1498Szrj
209138fd1498Szrj /* Fold expression X which is used as an rvalue. */
209238fd1498Szrj
209338fd1498Szrj static tree
cp_fold_rvalue(tree x)209438fd1498Szrj cp_fold_rvalue (tree x)
209538fd1498Szrj {
209638fd1498Szrj return cp_fold_maybe_rvalue (x, true);
209738fd1498Szrj }
209838fd1498Szrj
209938fd1498Szrj /* Perform folding on expression X. */
210038fd1498Szrj
210138fd1498Szrj tree
cp_fully_fold(tree x)210238fd1498Szrj cp_fully_fold (tree x)
210338fd1498Szrj {
210438fd1498Szrj if (processing_template_decl)
210538fd1498Szrj return x;
210638fd1498Szrj /* FIXME cp_fold ought to be a superset of maybe_constant_value so we don't
210738fd1498Szrj have to call both. */
210838fd1498Szrj if (cxx_dialect >= cxx11)
210938fd1498Szrj {
211038fd1498Szrj x = maybe_constant_value (x);
211138fd1498Szrj /* Sometimes we are given a CONSTRUCTOR but the call above wraps it into
211238fd1498Szrj a TARGET_EXPR; undo that here. */
211338fd1498Szrj if (TREE_CODE (x) == TARGET_EXPR)
211438fd1498Szrj x = TARGET_EXPR_INITIAL (x);
211538fd1498Szrj else if (TREE_CODE (x) == VIEW_CONVERT_EXPR
211638fd1498Szrj && TREE_CODE (TREE_OPERAND (x, 0)) == CONSTRUCTOR
211738fd1498Szrj && TREE_TYPE (TREE_OPERAND (x, 0)) == TREE_TYPE (x))
211838fd1498Szrj x = TREE_OPERAND (x, 0);
211938fd1498Szrj }
212038fd1498Szrj return cp_fold_rvalue (x);
212138fd1498Szrj }
212238fd1498Szrj
212338fd1498Szrj /* c-common interface to cp_fold. If IN_INIT, this is in a static initializer
212438fd1498Szrj and certain changes are made to the folding done. Or should be (FIXME). We
212538fd1498Szrj never touch maybe_const, as it is only used for the C front-end
212638fd1498Szrj C_MAYBE_CONST_EXPR. */
212738fd1498Szrj
212838fd1498Szrj tree
c_fully_fold(tree x,bool,bool *,bool lval)212938fd1498Szrj c_fully_fold (tree x, bool /*in_init*/, bool */*maybe_const*/, bool lval)
213038fd1498Szrj {
213138fd1498Szrj return cp_fold_maybe_rvalue (x, !lval);
213238fd1498Szrj }
213338fd1498Szrj
213438fd1498Szrj static GTY((deletable)) hash_map<tree, tree> *fold_cache;
213538fd1498Szrj
213638fd1498Szrj /* Dispose of the whole FOLD_CACHE. */
213738fd1498Szrj
213838fd1498Szrj void
clear_fold_cache(void)213938fd1498Szrj clear_fold_cache (void)
214038fd1498Szrj {
214138fd1498Szrj if (fold_cache != NULL)
214238fd1498Szrj fold_cache->empty ();
214338fd1498Szrj }
214438fd1498Szrj
214538fd1498Szrj /* This function tries to fold an expression X.
214638fd1498Szrj To avoid combinatorial explosion, folding results are kept in fold_cache.
214738fd1498Szrj If X is invalid, we don't fold at all.
214838fd1498Szrj For performance reasons we don't cache expressions representing a
214938fd1498Szrj declaration or constant.
215038fd1498Szrj Function returns X or its folded variant. */
215138fd1498Szrj
215238fd1498Szrj static tree
cp_fold(tree x)215338fd1498Szrj cp_fold (tree x)
215438fd1498Szrj {
215538fd1498Szrj tree op0, op1, op2, op3;
215638fd1498Szrj tree org_x = x, r = NULL_TREE;
215738fd1498Szrj enum tree_code code;
215838fd1498Szrj location_t loc;
215938fd1498Szrj bool rval_ops = true;
216038fd1498Szrj
216138fd1498Szrj if (!x || x == error_mark_node)
216238fd1498Szrj return x;
216338fd1498Szrj
216438fd1498Szrj if (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node))
216538fd1498Szrj return x;
216638fd1498Szrj
216738fd1498Szrj /* Don't bother to cache DECLs or constants. */
216838fd1498Szrj if (DECL_P (x) || CONSTANT_CLASS_P (x))
216938fd1498Szrj return x;
217038fd1498Szrj
217138fd1498Szrj if (fold_cache == NULL)
217238fd1498Szrj fold_cache = hash_map<tree, tree>::create_ggc (101);
217338fd1498Szrj
217438fd1498Szrj if (tree *cached = fold_cache->get (x))
217538fd1498Szrj return *cached;
217638fd1498Szrj
217738fd1498Szrj code = TREE_CODE (x);
217838fd1498Szrj switch (code)
217938fd1498Szrj {
218038fd1498Szrj case CLEANUP_POINT_EXPR:
218138fd1498Szrj /* Strip CLEANUP_POINT_EXPR if the expression doesn't have side
218238fd1498Szrj effects. */
218338fd1498Szrj r = cp_fold_rvalue (TREE_OPERAND (x, 0));
218438fd1498Szrj if (!TREE_SIDE_EFFECTS (r))
218538fd1498Szrj x = r;
218638fd1498Szrj break;
218738fd1498Szrj
218838fd1498Szrj case SIZEOF_EXPR:
218938fd1498Szrj x = fold_sizeof_expr (x);
219038fd1498Szrj break;
219138fd1498Szrj
219238fd1498Szrj case VIEW_CONVERT_EXPR:
219338fd1498Szrj rval_ops = false;
219438fd1498Szrj /* FALLTHRU */
219538fd1498Szrj case CONVERT_EXPR:
219638fd1498Szrj case NOP_EXPR:
219738fd1498Szrj case NON_LVALUE_EXPR:
219838fd1498Szrj
219938fd1498Szrj if (VOID_TYPE_P (TREE_TYPE (x)))
220038fd1498Szrj {
220138fd1498Szrj /* This is just to make sure we don't end up with casts to
220238fd1498Szrj void from error_mark_node. If we just return x, then
220338fd1498Szrj cp_fold_r might fold the operand into error_mark_node and
220438fd1498Szrj leave the conversion in the IR. STRIP_USELESS_TYPE_CONVERSION
220538fd1498Szrj during gimplification doesn't like such casts.
220638fd1498Szrj Don't create a new tree if op0 != TREE_OPERAND (x, 0), the
220738fd1498Szrj folding of the operand should be in the caches and if in cp_fold_r
220838fd1498Szrj it will modify it in place. */
220938fd1498Szrj op0 = cp_fold (TREE_OPERAND (x, 0));
221038fd1498Szrj if (op0 == error_mark_node)
221138fd1498Szrj x = error_mark_node;
221238fd1498Szrj break;
221338fd1498Szrj }
221438fd1498Szrj
221538fd1498Szrj loc = EXPR_LOCATION (x);
221638fd1498Szrj op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops);
221738fd1498Szrj
221838fd1498Szrj if (code == CONVERT_EXPR
221938fd1498Szrj && SCALAR_TYPE_P (TREE_TYPE (x))
222038fd1498Szrj && op0 != void_node)
222138fd1498Szrj /* During parsing we used convert_to_*_nofold; re-convert now using the
222238fd1498Szrj folding variants, since fold() doesn't do those transformations. */
222338fd1498Szrj x = fold (convert (TREE_TYPE (x), op0));
222438fd1498Szrj else if (op0 != TREE_OPERAND (x, 0))
222538fd1498Szrj {
222638fd1498Szrj if (op0 == error_mark_node)
222738fd1498Szrj x = error_mark_node;
222838fd1498Szrj else
222938fd1498Szrj x = fold_build1_loc (loc, code, TREE_TYPE (x), op0);
223038fd1498Szrj }
223138fd1498Szrj else
223238fd1498Szrj x = fold (x);
223338fd1498Szrj
223438fd1498Szrj /* Conversion of an out-of-range value has implementation-defined
223538fd1498Szrj behavior; the language considers it different from arithmetic
223638fd1498Szrj overflow, which is undefined. */
223738fd1498Szrj if (TREE_CODE (op0) == INTEGER_CST
223838fd1498Szrj && TREE_OVERFLOW_P (x) && !TREE_OVERFLOW_P (op0))
223938fd1498Szrj TREE_OVERFLOW (x) = false;
224038fd1498Szrj
224138fd1498Szrj break;
224238fd1498Szrj
224338fd1498Szrj case INDIRECT_REF:
224438fd1498Szrj /* We don't need the decltype(auto) obfuscation anymore. */
224538fd1498Szrj if (REF_PARENTHESIZED_P (x))
224638fd1498Szrj {
224738fd1498Szrj tree p = maybe_undo_parenthesized_ref (x);
224838fd1498Szrj return cp_fold (p);
224938fd1498Szrj }
225038fd1498Szrj goto unary;
225138fd1498Szrj
225238fd1498Szrj case ADDR_EXPR:
225338fd1498Szrj loc = EXPR_LOCATION (x);
225438fd1498Szrj op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), false);
225538fd1498Szrj
225638fd1498Szrj /* Cope with user tricks that amount to offsetof. */
225738fd1498Szrj if (op0 != error_mark_node
225838fd1498Szrj && TREE_CODE (TREE_TYPE (op0)) != FUNCTION_TYPE
225938fd1498Szrj && TREE_CODE (TREE_TYPE (op0)) != METHOD_TYPE)
226038fd1498Szrj {
226138fd1498Szrj tree val = get_base_address (op0);
226238fd1498Szrj if (val
226338fd1498Szrj && INDIRECT_REF_P (val)
226438fd1498Szrj && COMPLETE_TYPE_P (TREE_TYPE (val))
226538fd1498Szrj && TREE_CONSTANT (TREE_OPERAND (val, 0)))
226638fd1498Szrj {
226738fd1498Szrj val = TREE_OPERAND (val, 0);
226838fd1498Szrj STRIP_NOPS (val);
2269*58e805e6Szrj val = maybe_constant_value (val);
227038fd1498Szrj if (TREE_CODE (val) == INTEGER_CST)
2271*58e805e6Szrj return fold_offsetof (op0, TREE_TYPE (x));
227238fd1498Szrj }
227338fd1498Szrj }
227438fd1498Szrj goto finish_unary;
227538fd1498Szrj
227638fd1498Szrj case REALPART_EXPR:
227738fd1498Szrj case IMAGPART_EXPR:
227838fd1498Szrj rval_ops = false;
227938fd1498Szrj /* FALLTHRU */
228038fd1498Szrj case CONJ_EXPR:
228138fd1498Szrj case FIX_TRUNC_EXPR:
228238fd1498Szrj case FLOAT_EXPR:
228338fd1498Szrj case NEGATE_EXPR:
228438fd1498Szrj case ABS_EXPR:
228538fd1498Szrj case BIT_NOT_EXPR:
228638fd1498Szrj case TRUTH_NOT_EXPR:
228738fd1498Szrj case FIXED_CONVERT_EXPR:
228838fd1498Szrj unary:
228938fd1498Szrj
229038fd1498Szrj loc = EXPR_LOCATION (x);
229138fd1498Szrj op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops);
229238fd1498Szrj
229338fd1498Szrj finish_unary:
229438fd1498Szrj if (op0 != TREE_OPERAND (x, 0))
229538fd1498Szrj {
229638fd1498Szrj if (op0 == error_mark_node)
229738fd1498Szrj x = error_mark_node;
229838fd1498Szrj else
229938fd1498Szrj {
230038fd1498Szrj x = fold_build1_loc (loc, code, TREE_TYPE (x), op0);
230138fd1498Szrj if (code == INDIRECT_REF
230238fd1498Szrj && (INDIRECT_REF_P (x) || TREE_CODE (x) == MEM_REF))
230338fd1498Szrj {
230438fd1498Szrj TREE_READONLY (x) = TREE_READONLY (org_x);
230538fd1498Szrj TREE_SIDE_EFFECTS (x) = TREE_SIDE_EFFECTS (org_x);
230638fd1498Szrj TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x);
230738fd1498Szrj }
230838fd1498Szrj }
230938fd1498Szrj }
231038fd1498Szrj else
231138fd1498Szrj x = fold (x);
231238fd1498Szrj
231338fd1498Szrj gcc_assert (TREE_CODE (x) != COND_EXPR
231438fd1498Szrj || !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))));
231538fd1498Szrj break;
231638fd1498Szrj
231738fd1498Szrj case UNARY_PLUS_EXPR:
231838fd1498Szrj op0 = cp_fold_rvalue (TREE_OPERAND (x, 0));
231938fd1498Szrj if (op0 == error_mark_node)
232038fd1498Szrj x = error_mark_node;
232138fd1498Szrj else
232238fd1498Szrj x = fold_convert (TREE_TYPE (x), op0);
232338fd1498Szrj break;
232438fd1498Szrj
232538fd1498Szrj case POSTDECREMENT_EXPR:
232638fd1498Szrj case POSTINCREMENT_EXPR:
232738fd1498Szrj case INIT_EXPR:
232838fd1498Szrj case PREDECREMENT_EXPR:
232938fd1498Szrj case PREINCREMENT_EXPR:
233038fd1498Szrj case COMPOUND_EXPR:
233138fd1498Szrj case MODIFY_EXPR:
233238fd1498Szrj rval_ops = false;
233338fd1498Szrj /* FALLTHRU */
233438fd1498Szrj case POINTER_PLUS_EXPR:
233538fd1498Szrj case PLUS_EXPR:
233638fd1498Szrj case POINTER_DIFF_EXPR:
233738fd1498Szrj case MINUS_EXPR:
233838fd1498Szrj case MULT_EXPR:
233938fd1498Szrj case TRUNC_DIV_EXPR:
234038fd1498Szrj case CEIL_DIV_EXPR:
234138fd1498Szrj case FLOOR_DIV_EXPR:
234238fd1498Szrj case ROUND_DIV_EXPR:
234338fd1498Szrj case TRUNC_MOD_EXPR:
234438fd1498Szrj case CEIL_MOD_EXPR:
234538fd1498Szrj case ROUND_MOD_EXPR:
234638fd1498Szrj case RDIV_EXPR:
234738fd1498Szrj case EXACT_DIV_EXPR:
234838fd1498Szrj case MIN_EXPR:
234938fd1498Szrj case MAX_EXPR:
235038fd1498Szrj case LSHIFT_EXPR:
235138fd1498Szrj case RSHIFT_EXPR:
235238fd1498Szrj case LROTATE_EXPR:
235338fd1498Szrj case RROTATE_EXPR:
235438fd1498Szrj case BIT_AND_EXPR:
235538fd1498Szrj case BIT_IOR_EXPR:
235638fd1498Szrj case BIT_XOR_EXPR:
235738fd1498Szrj case TRUTH_AND_EXPR:
235838fd1498Szrj case TRUTH_ANDIF_EXPR:
235938fd1498Szrj case TRUTH_OR_EXPR:
236038fd1498Szrj case TRUTH_ORIF_EXPR:
236138fd1498Szrj case TRUTH_XOR_EXPR:
236238fd1498Szrj case LT_EXPR: case LE_EXPR:
236338fd1498Szrj case GT_EXPR: case GE_EXPR:
236438fd1498Szrj case EQ_EXPR: case NE_EXPR:
236538fd1498Szrj case UNORDERED_EXPR: case ORDERED_EXPR:
236638fd1498Szrj case UNLT_EXPR: case UNLE_EXPR:
236738fd1498Szrj case UNGT_EXPR: case UNGE_EXPR:
236838fd1498Szrj case UNEQ_EXPR: case LTGT_EXPR:
236938fd1498Szrj case RANGE_EXPR: case COMPLEX_EXPR:
237038fd1498Szrj
237138fd1498Szrj loc = EXPR_LOCATION (x);
237238fd1498Szrj op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops);
237338fd1498Szrj op1 = cp_fold_rvalue (TREE_OPERAND (x, 1));
237438fd1498Szrj
237538fd1498Szrj if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1))
237638fd1498Szrj {
237738fd1498Szrj if (op0 == error_mark_node || op1 == error_mark_node)
237838fd1498Szrj x = error_mark_node;
237938fd1498Szrj else
238038fd1498Szrj x = fold_build2_loc (loc, code, TREE_TYPE (x), op0, op1);
238138fd1498Szrj }
238238fd1498Szrj else
238338fd1498Szrj x = fold (x);
238438fd1498Szrj
238538fd1498Szrj if (TREE_NO_WARNING (org_x)
238638fd1498Szrj && warn_nonnull_compare
238738fd1498Szrj && COMPARISON_CLASS_P (org_x))
238838fd1498Szrj {
238938fd1498Szrj if (x == error_mark_node || TREE_CODE (x) == INTEGER_CST)
239038fd1498Szrj ;
239138fd1498Szrj else if (COMPARISON_CLASS_P (x))
239238fd1498Szrj TREE_NO_WARNING (x) = 1;
239338fd1498Szrj /* Otherwise give up on optimizing these, let GIMPLE folders
239438fd1498Szrj optimize those later on. */
239538fd1498Szrj else if (op0 != TREE_OPERAND (org_x, 0)
239638fd1498Szrj || op1 != TREE_OPERAND (org_x, 1))
239738fd1498Szrj {
239838fd1498Szrj x = build2_loc (loc, code, TREE_TYPE (org_x), op0, op1);
239938fd1498Szrj TREE_NO_WARNING (x) = 1;
240038fd1498Szrj }
240138fd1498Szrj else
240238fd1498Szrj x = org_x;
240338fd1498Szrj }
240438fd1498Szrj break;
240538fd1498Szrj
240638fd1498Szrj case VEC_COND_EXPR:
240738fd1498Szrj case COND_EXPR:
240838fd1498Szrj loc = EXPR_LOCATION (x);
240938fd1498Szrj op0 = cp_fold_rvalue (TREE_OPERAND (x, 0));
241038fd1498Szrj op1 = cp_fold (TREE_OPERAND (x, 1));
241138fd1498Szrj op2 = cp_fold (TREE_OPERAND (x, 2));
241238fd1498Szrj
241338fd1498Szrj if (TREE_CODE (TREE_TYPE (x)) == BOOLEAN_TYPE)
241438fd1498Szrj {
241538fd1498Szrj warning_sentinel s (warn_int_in_bool_context);
241638fd1498Szrj if (!VOID_TYPE_P (TREE_TYPE (op1)))
241738fd1498Szrj op1 = cp_truthvalue_conversion (op1);
241838fd1498Szrj if (!VOID_TYPE_P (TREE_TYPE (op2)))
241938fd1498Szrj op2 = cp_truthvalue_conversion (op2);
242038fd1498Szrj }
242138fd1498Szrj else if (VOID_TYPE_P (TREE_TYPE (x)))
242238fd1498Szrj {
242338fd1498Szrj if (TREE_CODE (op0) == INTEGER_CST)
242438fd1498Szrj {
242538fd1498Szrj /* If the condition is constant, fold can fold away
242638fd1498Szrj the COND_EXPR. If some statement-level uses of COND_EXPR
242738fd1498Szrj have one of the branches NULL, avoid folding crash. */
242838fd1498Szrj if (!op1)
242938fd1498Szrj op1 = build_empty_stmt (loc);
243038fd1498Szrj if (!op2)
243138fd1498Szrj op2 = build_empty_stmt (loc);
243238fd1498Szrj }
243338fd1498Szrj else
243438fd1498Szrj {
243538fd1498Szrj /* Otherwise, don't bother folding a void condition, since
243638fd1498Szrj it can't produce a constant value. */
243738fd1498Szrj if (op0 != TREE_OPERAND (x, 0)
243838fd1498Szrj || op1 != TREE_OPERAND (x, 1)
243938fd1498Szrj || op2 != TREE_OPERAND (x, 2))
244038fd1498Szrj x = build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2);
244138fd1498Szrj break;
244238fd1498Szrj }
244338fd1498Szrj }
244438fd1498Szrj
244538fd1498Szrj if (op0 != TREE_OPERAND (x, 0)
244638fd1498Szrj || op1 != TREE_OPERAND (x, 1)
244738fd1498Szrj || op2 != TREE_OPERAND (x, 2))
244838fd1498Szrj {
244938fd1498Szrj if (op0 == error_mark_node
245038fd1498Szrj || op1 == error_mark_node
245138fd1498Szrj || op2 == error_mark_node)
245238fd1498Szrj x = error_mark_node;
245338fd1498Szrj else
245438fd1498Szrj x = fold_build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2);
245538fd1498Szrj }
245638fd1498Szrj else
245738fd1498Szrj x = fold (x);
245838fd1498Szrj
245938fd1498Szrj /* A COND_EXPR might have incompatible types in branches if one or both
246038fd1498Szrj arms are bitfields. If folding exposed such a branch, fix it up. */
246138fd1498Szrj if (TREE_CODE (x) != code
246238fd1498Szrj && x != error_mark_node
246338fd1498Szrj && !useless_type_conversion_p (TREE_TYPE (org_x), TREE_TYPE (x)))
246438fd1498Szrj x = fold_convert (TREE_TYPE (org_x), x);
246538fd1498Szrj
246638fd1498Szrj break;
246738fd1498Szrj
246838fd1498Szrj case CALL_EXPR:
246938fd1498Szrj {
247038fd1498Szrj int i, m, sv = optimize, nw = sv, changed = 0;
247138fd1498Szrj tree callee = get_callee_fndecl (x);
247238fd1498Szrj
247338fd1498Szrj /* Some built-in function calls will be evaluated at compile-time in
247438fd1498Szrj fold (). Set optimize to 1 when folding __builtin_constant_p inside
247538fd1498Szrj a constexpr function so that fold_builtin_1 doesn't fold it to 0. */
247638fd1498Szrj if (callee && DECL_BUILT_IN (callee) && !optimize
247738fd1498Szrj && DECL_IS_BUILTIN_CONSTANT_P (callee)
247838fd1498Szrj && current_function_decl
247938fd1498Szrj && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
248038fd1498Szrj nw = 1;
248138fd1498Szrj
248238fd1498Szrj x = copy_node (x);
248338fd1498Szrj
248438fd1498Szrj m = call_expr_nargs (x);
248538fd1498Szrj for (i = 0; i < m; i++)
248638fd1498Szrj {
248738fd1498Szrj r = cp_fold (CALL_EXPR_ARG (x, i));
248838fd1498Szrj if (r != CALL_EXPR_ARG (x, i))
248938fd1498Szrj {
249038fd1498Szrj if (r == error_mark_node)
249138fd1498Szrj {
249238fd1498Szrj x = error_mark_node;
249338fd1498Szrj break;
249438fd1498Szrj }
249538fd1498Szrj changed = 1;
249638fd1498Szrj }
249738fd1498Szrj CALL_EXPR_ARG (x, i) = r;
249838fd1498Szrj }
249938fd1498Szrj if (x == error_mark_node)
250038fd1498Szrj break;
250138fd1498Szrj
250238fd1498Szrj optimize = nw;
250338fd1498Szrj r = fold (x);
250438fd1498Szrj optimize = sv;
250538fd1498Szrj
250638fd1498Szrj if (TREE_CODE (r) != CALL_EXPR)
250738fd1498Szrj {
250838fd1498Szrj x = cp_fold (r);
250938fd1498Szrj break;
251038fd1498Szrj }
251138fd1498Szrj
251238fd1498Szrj optimize = nw;
251338fd1498Szrj
251438fd1498Szrj /* Invoke maybe_constant_value for functions declared
251538fd1498Szrj constexpr and not called with AGGR_INIT_EXPRs.
251638fd1498Szrj TODO:
251738fd1498Szrj Do constexpr expansion of expressions where the call itself is not
251838fd1498Szrj constant, but the call followed by an INDIRECT_REF is. */
251938fd1498Szrj if (callee && DECL_DECLARED_CONSTEXPR_P (callee)
252038fd1498Szrj && !flag_no_inline)
252138fd1498Szrj r = maybe_constant_value (x);
252238fd1498Szrj optimize = sv;
252338fd1498Szrj
252438fd1498Szrj if (TREE_CODE (r) != CALL_EXPR)
252538fd1498Szrj {
252638fd1498Szrj if (DECL_CONSTRUCTOR_P (callee))
252738fd1498Szrj {
252838fd1498Szrj loc = EXPR_LOCATION (x);
252938fd1498Szrj tree s = build_fold_indirect_ref_loc (loc,
253038fd1498Szrj CALL_EXPR_ARG (x, 0));
253138fd1498Szrj r = build2_loc (loc, INIT_EXPR, TREE_TYPE (s), s, r);
253238fd1498Szrj }
253338fd1498Szrj x = r;
253438fd1498Szrj break;
253538fd1498Szrj }
253638fd1498Szrj
253738fd1498Szrj if (!changed)
253838fd1498Szrj x = org_x;
253938fd1498Szrj break;
254038fd1498Szrj }
254138fd1498Szrj
254238fd1498Szrj case CONSTRUCTOR:
254338fd1498Szrj {
254438fd1498Szrj unsigned i;
254538fd1498Szrj constructor_elt *p;
254638fd1498Szrj vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (x);
254738fd1498Szrj vec<constructor_elt, va_gc> *nelts = NULL;
254838fd1498Szrj FOR_EACH_VEC_SAFE_ELT (elts, i, p)
254938fd1498Szrj {
255038fd1498Szrj tree op = cp_fold (p->value);
255138fd1498Szrj if (op != p->value)
255238fd1498Szrj {
255338fd1498Szrj if (op == error_mark_node)
255438fd1498Szrj {
255538fd1498Szrj x = error_mark_node;
255638fd1498Szrj vec_free (nelts);
255738fd1498Szrj break;
255838fd1498Szrj }
255938fd1498Szrj if (nelts == NULL)
256038fd1498Szrj nelts = elts->copy ();
256138fd1498Szrj (*nelts)[i].value = op;
256238fd1498Szrj }
256338fd1498Szrj }
256438fd1498Szrj if (nelts)
256538fd1498Szrj {
256638fd1498Szrj x = build_constructor (TREE_TYPE (x), nelts);
256738fd1498Szrj CONSTRUCTOR_PLACEHOLDER_BOUNDARY (x)
256838fd1498Szrj = CONSTRUCTOR_PLACEHOLDER_BOUNDARY (org_x);
256938fd1498Szrj }
257038fd1498Szrj if (VECTOR_TYPE_P (TREE_TYPE (x)))
257138fd1498Szrj x = fold (x);
257238fd1498Szrj break;
257338fd1498Szrj }
257438fd1498Szrj case TREE_VEC:
257538fd1498Szrj {
257638fd1498Szrj bool changed = false;
257738fd1498Szrj vec<tree, va_gc> *vec = make_tree_vector ();
257838fd1498Szrj int i, n = TREE_VEC_LENGTH (x);
257938fd1498Szrj vec_safe_reserve (vec, n);
258038fd1498Szrj
258138fd1498Szrj for (i = 0; i < n; i++)
258238fd1498Szrj {
258338fd1498Szrj tree op = cp_fold (TREE_VEC_ELT (x, i));
258438fd1498Szrj vec->quick_push (op);
258538fd1498Szrj if (op != TREE_VEC_ELT (x, i))
258638fd1498Szrj changed = true;
258738fd1498Szrj }
258838fd1498Szrj
258938fd1498Szrj if (changed)
259038fd1498Szrj {
259138fd1498Szrj r = copy_node (x);
259238fd1498Szrj for (i = 0; i < n; i++)
259338fd1498Szrj TREE_VEC_ELT (r, i) = (*vec)[i];
259438fd1498Szrj x = r;
259538fd1498Szrj }
259638fd1498Szrj
259738fd1498Szrj release_tree_vector (vec);
259838fd1498Szrj }
259938fd1498Szrj
260038fd1498Szrj break;
260138fd1498Szrj
260238fd1498Szrj case ARRAY_REF:
260338fd1498Szrj case ARRAY_RANGE_REF:
260438fd1498Szrj
260538fd1498Szrj loc = EXPR_LOCATION (x);
260638fd1498Szrj op0 = cp_fold (TREE_OPERAND (x, 0));
260738fd1498Szrj op1 = cp_fold (TREE_OPERAND (x, 1));
260838fd1498Szrj op2 = cp_fold (TREE_OPERAND (x, 2));
260938fd1498Szrj op3 = cp_fold (TREE_OPERAND (x, 3));
261038fd1498Szrj
261138fd1498Szrj if (op0 != TREE_OPERAND (x, 0)
261238fd1498Szrj || op1 != TREE_OPERAND (x, 1)
261338fd1498Szrj || op2 != TREE_OPERAND (x, 2)
261438fd1498Szrj || op3 != TREE_OPERAND (x, 3))
261538fd1498Szrj {
261638fd1498Szrj if (op0 == error_mark_node
261738fd1498Szrj || op1 == error_mark_node
261838fd1498Szrj || op2 == error_mark_node
261938fd1498Szrj || op3 == error_mark_node)
262038fd1498Szrj x = error_mark_node;
262138fd1498Szrj else
262238fd1498Szrj {
262338fd1498Szrj x = build4_loc (loc, code, TREE_TYPE (x), op0, op1, op2, op3);
262438fd1498Szrj TREE_READONLY (x) = TREE_READONLY (org_x);
262538fd1498Szrj TREE_SIDE_EFFECTS (x) = TREE_SIDE_EFFECTS (org_x);
262638fd1498Szrj TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x);
262738fd1498Szrj }
262838fd1498Szrj }
262938fd1498Szrj
263038fd1498Szrj x = fold (x);
263138fd1498Szrj break;
263238fd1498Szrj
263338fd1498Szrj case SAVE_EXPR:
263438fd1498Szrj /* A SAVE_EXPR might contain e.g. (0 * i) + (0 * j), which, after
263538fd1498Szrj folding, evaluates to an invariant. In that case no need to wrap
263638fd1498Szrj this folded tree with a SAVE_EXPR. */
263738fd1498Szrj r = cp_fold (TREE_OPERAND (x, 0));
263838fd1498Szrj if (tree_invariant_p (r))
263938fd1498Szrj x = r;
264038fd1498Szrj break;
264138fd1498Szrj
264238fd1498Szrj default:
264338fd1498Szrj return org_x;
264438fd1498Szrj }
264538fd1498Szrj
264638fd1498Szrj fold_cache->put (org_x, x);
264738fd1498Szrj /* Prevent that we try to fold an already folded result again. */
264838fd1498Szrj if (x != org_x)
264938fd1498Szrj fold_cache->put (x, x);
265038fd1498Szrj
265138fd1498Szrj return x;
265238fd1498Szrj }
265338fd1498Szrj
265438fd1498Szrj #include "gt-cp-cp-gimplify.h"
2655