xref: /dflybsd-src/contrib/gcc-8.0/gcc/cp/cp-gimplify.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
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