1*e4b17023SJohn Marino /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
2*e4b17023SJohn Marino
3*e4b17023SJohn Marino Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
4*e4b17023SJohn Marino Free Software Foundation, Inc.
5*e4b17023SJohn Marino Contributed by Jason Merrill <jason@redhat.com>
6*e4b17023SJohn Marino
7*e4b17023SJohn Marino This file is part of GCC.
8*e4b17023SJohn Marino
9*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
10*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
11*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
12*e4b17023SJohn Marino version.
13*e4b17023SJohn Marino
14*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
16*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17*e4b17023SJohn Marino for more details.
18*e4b17023SJohn Marino
19*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
20*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
21*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
22*e4b17023SJohn Marino
23*e4b17023SJohn Marino #include "config.h"
24*e4b17023SJohn Marino #include "system.h"
25*e4b17023SJohn Marino #include "coretypes.h"
26*e4b17023SJohn Marino #include "tm.h"
27*e4b17023SJohn Marino #include "tree.h"
28*e4b17023SJohn Marino #include "cp-tree.h"
29*e4b17023SJohn Marino #include "c-family/c-common.h"
30*e4b17023SJohn Marino #include "tree-iterator.h"
31*e4b17023SJohn Marino #include "gimple.h"
32*e4b17023SJohn Marino #include "hashtab.h"
33*e4b17023SJohn Marino #include "pointer-set.h"
34*e4b17023SJohn Marino #include "flags.h"
35*e4b17023SJohn Marino #include "splay-tree.h"
36*e4b17023SJohn Marino
37*e4b17023SJohn Marino /* Local declarations. */
38*e4b17023SJohn Marino
39*e4b17023SJohn Marino enum bc_t { bc_break = 0, bc_continue = 1 };
40*e4b17023SJohn Marino
41*e4b17023SJohn Marino /* Stack of labels which are targets for "break" or "continue",
42*e4b17023SJohn Marino linked through TREE_CHAIN. */
43*e4b17023SJohn Marino static tree bc_label[2];
44*e4b17023SJohn Marino
45*e4b17023SJohn Marino /* Begin a scope which can be exited by a break or continue statement. BC
46*e4b17023SJohn Marino indicates which.
47*e4b17023SJohn Marino
48*e4b17023SJohn Marino Just creates a label and pushes it into the current context. */
49*e4b17023SJohn Marino
50*e4b17023SJohn Marino static tree
begin_bc_block(enum bc_t bc)51*e4b17023SJohn Marino begin_bc_block (enum bc_t bc)
52*e4b17023SJohn Marino {
53*e4b17023SJohn Marino tree label = create_artificial_label (input_location);
54*e4b17023SJohn Marino DECL_CHAIN (label) = bc_label[bc];
55*e4b17023SJohn Marino bc_label[bc] = label;
56*e4b17023SJohn Marino return label;
57*e4b17023SJohn Marino }
58*e4b17023SJohn Marino
59*e4b17023SJohn Marino /* Finish a scope which can be exited by a break or continue statement.
60*e4b17023SJohn Marino LABEL was returned from the most recent call to begin_bc_block. BODY is
61*e4b17023SJohn Marino an expression for the contents of the scope.
62*e4b17023SJohn Marino
63*e4b17023SJohn Marino If we saw a break (or continue) in the scope, append a LABEL_EXPR to
64*e4b17023SJohn Marino body. Otherwise, just forget the label. */
65*e4b17023SJohn Marino
66*e4b17023SJohn Marino static gimple_seq
finish_bc_block(enum bc_t bc,tree label,gimple_seq body)67*e4b17023SJohn Marino finish_bc_block (enum bc_t bc, tree label, gimple_seq body)
68*e4b17023SJohn Marino {
69*e4b17023SJohn Marino gcc_assert (label == bc_label[bc]);
70*e4b17023SJohn Marino
71*e4b17023SJohn Marino if (TREE_USED (label))
72*e4b17023SJohn Marino {
73*e4b17023SJohn Marino gimple_seq_add_stmt (&body, gimple_build_label (label));
74*e4b17023SJohn Marino }
75*e4b17023SJohn Marino
76*e4b17023SJohn Marino bc_label[bc] = DECL_CHAIN (label);
77*e4b17023SJohn Marino DECL_CHAIN (label) = NULL_TREE;
78*e4b17023SJohn Marino return body;
79*e4b17023SJohn Marino }
80*e4b17023SJohn Marino
81*e4b17023SJohn Marino /* Get the LABEL_EXPR to represent a break or continue statement
82*e4b17023SJohn Marino in the current block scope. BC indicates which. */
83*e4b17023SJohn Marino
84*e4b17023SJohn Marino static tree
get_bc_label(enum bc_t bc)85*e4b17023SJohn Marino get_bc_label (enum bc_t bc)
86*e4b17023SJohn Marino {
87*e4b17023SJohn Marino tree label = bc_label[bc];
88*e4b17023SJohn Marino
89*e4b17023SJohn Marino /* Mark the label used for finish_bc_block. */
90*e4b17023SJohn Marino TREE_USED (label) = 1;
91*e4b17023SJohn Marino return label;
92*e4b17023SJohn Marino }
93*e4b17023SJohn Marino
94*e4b17023SJohn Marino /* Genericize a TRY_BLOCK. */
95*e4b17023SJohn Marino
96*e4b17023SJohn Marino static void
genericize_try_block(tree * stmt_p)97*e4b17023SJohn Marino genericize_try_block (tree *stmt_p)
98*e4b17023SJohn Marino {
99*e4b17023SJohn Marino tree body = TRY_STMTS (*stmt_p);
100*e4b17023SJohn Marino tree cleanup = TRY_HANDLERS (*stmt_p);
101*e4b17023SJohn Marino
102*e4b17023SJohn Marino *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
103*e4b17023SJohn Marino }
104*e4b17023SJohn Marino
105*e4b17023SJohn Marino /* Genericize a HANDLER by converting to a CATCH_EXPR. */
106*e4b17023SJohn Marino
107*e4b17023SJohn Marino static void
genericize_catch_block(tree * stmt_p)108*e4b17023SJohn Marino genericize_catch_block (tree *stmt_p)
109*e4b17023SJohn Marino {
110*e4b17023SJohn Marino tree type = HANDLER_TYPE (*stmt_p);
111*e4b17023SJohn Marino tree body = HANDLER_BODY (*stmt_p);
112*e4b17023SJohn Marino
113*e4b17023SJohn Marino /* FIXME should the caught type go in TREE_TYPE? */
114*e4b17023SJohn Marino *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
115*e4b17023SJohn Marino }
116*e4b17023SJohn Marino
117*e4b17023SJohn Marino /* A terser interface for building a representation of an exception
118*e4b17023SJohn Marino specification. */
119*e4b17023SJohn Marino
120*e4b17023SJohn Marino static tree
build_gimple_eh_filter_tree(tree body,tree allowed,tree failure)121*e4b17023SJohn Marino build_gimple_eh_filter_tree (tree body, tree allowed, tree failure)
122*e4b17023SJohn Marino {
123*e4b17023SJohn Marino tree t;
124*e4b17023SJohn Marino
125*e4b17023SJohn Marino /* FIXME should the allowed types go in TREE_TYPE? */
126*e4b17023SJohn Marino t = build2 (EH_FILTER_EXPR, void_type_node, allowed, NULL_TREE);
127*e4b17023SJohn Marino append_to_statement_list (failure, &EH_FILTER_FAILURE (t));
128*e4b17023SJohn Marino
129*e4b17023SJohn Marino t = build2 (TRY_CATCH_EXPR, void_type_node, NULL_TREE, t);
130*e4b17023SJohn Marino append_to_statement_list (body, &TREE_OPERAND (t, 0));
131*e4b17023SJohn Marino
132*e4b17023SJohn Marino return t;
133*e4b17023SJohn Marino }
134*e4b17023SJohn Marino
135*e4b17023SJohn Marino /* Genericize an EH_SPEC_BLOCK by converting it to a
136*e4b17023SJohn Marino TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
137*e4b17023SJohn Marino
138*e4b17023SJohn Marino static void
genericize_eh_spec_block(tree * stmt_p)139*e4b17023SJohn Marino genericize_eh_spec_block (tree *stmt_p)
140*e4b17023SJohn Marino {
141*e4b17023SJohn Marino tree body = EH_SPEC_STMTS (*stmt_p);
142*e4b17023SJohn Marino tree allowed = EH_SPEC_RAISES (*stmt_p);
143*e4b17023SJohn Marino tree failure = build_call_n (call_unexpected_node, 1, build_exc_ptr ());
144*e4b17023SJohn Marino
145*e4b17023SJohn Marino *stmt_p = build_gimple_eh_filter_tree (body, allowed, failure);
146*e4b17023SJohn Marino TREE_NO_WARNING (*stmt_p) = true;
147*e4b17023SJohn Marino TREE_NO_WARNING (TREE_OPERAND (*stmt_p, 1)) = true;
148*e4b17023SJohn Marino }
149*e4b17023SJohn Marino
150*e4b17023SJohn Marino /* Genericize an IF_STMT by turning it into a COND_EXPR. */
151*e4b17023SJohn Marino
152*e4b17023SJohn Marino static void
genericize_if_stmt(tree * stmt_p)153*e4b17023SJohn Marino genericize_if_stmt (tree *stmt_p)
154*e4b17023SJohn Marino {
155*e4b17023SJohn Marino tree stmt, cond, then_, else_;
156*e4b17023SJohn Marino location_t locus = EXPR_LOCATION (*stmt_p);
157*e4b17023SJohn Marino
158*e4b17023SJohn Marino stmt = *stmt_p;
159*e4b17023SJohn Marino cond = IF_COND (stmt);
160*e4b17023SJohn Marino then_ = THEN_CLAUSE (stmt);
161*e4b17023SJohn Marino else_ = ELSE_CLAUSE (stmt);
162*e4b17023SJohn Marino
163*e4b17023SJohn Marino if (!then_)
164*e4b17023SJohn Marino then_ = build_empty_stmt (locus);
165*e4b17023SJohn Marino if (!else_)
166*e4b17023SJohn Marino else_ = build_empty_stmt (locus);
167*e4b17023SJohn Marino
168*e4b17023SJohn Marino if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
169*e4b17023SJohn Marino stmt = then_;
170*e4b17023SJohn Marino else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
171*e4b17023SJohn Marino stmt = else_;
172*e4b17023SJohn Marino else
173*e4b17023SJohn Marino stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
174*e4b17023SJohn Marino if (CAN_HAVE_LOCATION_P (stmt) && !EXPR_HAS_LOCATION (stmt))
175*e4b17023SJohn Marino SET_EXPR_LOCATION (stmt, locus);
176*e4b17023SJohn Marino *stmt_p = stmt;
177*e4b17023SJohn Marino }
178*e4b17023SJohn Marino
179*e4b17023SJohn Marino /* Build a generic representation of one of the C loop forms. COND is the
180*e4b17023SJohn Marino loop condition or NULL_TREE. BODY is the (possibly compound) statement
181*e4b17023SJohn Marino controlled by the loop. INCR is the increment expression of a for-loop,
182*e4b17023SJohn Marino or NULL_TREE. COND_IS_FIRST indicates whether the condition is
183*e4b17023SJohn Marino evaluated before the loop body as in while and for loops, or after the
184*e4b17023SJohn Marino loop body as in do-while loops. */
185*e4b17023SJohn Marino
186*e4b17023SJohn Marino static gimple_seq
gimplify_cp_loop(tree cond,tree body,tree incr,bool cond_is_first)187*e4b17023SJohn Marino gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
188*e4b17023SJohn Marino {
189*e4b17023SJohn Marino gimple top, entry, stmt;
190*e4b17023SJohn Marino gimple_seq stmt_list, body_seq, incr_seq, exit_seq;
191*e4b17023SJohn Marino tree cont_block, break_block;
192*e4b17023SJohn Marino location_t stmt_locus;
193*e4b17023SJohn Marino
194*e4b17023SJohn Marino stmt_locus = input_location;
195*e4b17023SJohn Marino stmt_list = NULL;
196*e4b17023SJohn Marino body_seq = NULL;
197*e4b17023SJohn Marino incr_seq = NULL;
198*e4b17023SJohn Marino exit_seq = NULL;
199*e4b17023SJohn Marino entry = NULL;
200*e4b17023SJohn Marino
201*e4b17023SJohn Marino break_block = begin_bc_block (bc_break);
202*e4b17023SJohn Marino cont_block = begin_bc_block (bc_continue);
203*e4b17023SJohn Marino
204*e4b17023SJohn Marino /* If condition is zero don't generate a loop construct. */
205*e4b17023SJohn Marino if (cond && integer_zerop (cond))
206*e4b17023SJohn Marino {
207*e4b17023SJohn Marino top = NULL;
208*e4b17023SJohn Marino if (cond_is_first)
209*e4b17023SJohn Marino {
210*e4b17023SJohn Marino stmt = gimple_build_goto (get_bc_label (bc_break));
211*e4b17023SJohn Marino gimple_set_location (stmt, stmt_locus);
212*e4b17023SJohn Marino gimple_seq_add_stmt (&stmt_list, stmt);
213*e4b17023SJohn Marino }
214*e4b17023SJohn Marino }
215*e4b17023SJohn Marino else
216*e4b17023SJohn Marino {
217*e4b17023SJohn Marino /* If we use a LOOP_EXPR here, we have to feed the whole thing
218*e4b17023SJohn Marino back through the main gimplifier to lower it. Given that we
219*e4b17023SJohn Marino have to gimplify the loop body NOW so that we can resolve
220*e4b17023SJohn Marino break/continue stmts, seems easier to just expand to gotos. */
221*e4b17023SJohn Marino top = gimple_build_label (create_artificial_label (stmt_locus));
222*e4b17023SJohn Marino
223*e4b17023SJohn Marino /* If we have an exit condition, then we build an IF with gotos either
224*e4b17023SJohn Marino out of the loop, or to the top of it. If there's no exit condition,
225*e4b17023SJohn Marino then we just build a jump back to the top. */
226*e4b17023SJohn Marino if (cond && !integer_nonzerop (cond))
227*e4b17023SJohn Marino {
228*e4b17023SJohn Marino if (cond != error_mark_node)
229*e4b17023SJohn Marino {
230*e4b17023SJohn Marino gimplify_expr (&cond, &exit_seq, NULL, is_gimple_val, fb_rvalue);
231*e4b17023SJohn Marino stmt = gimple_build_cond (NE_EXPR, cond,
232*e4b17023SJohn Marino build_int_cst (TREE_TYPE (cond), 0),
233*e4b17023SJohn Marino gimple_label_label (top),
234*e4b17023SJohn Marino get_bc_label (bc_break));
235*e4b17023SJohn Marino gimple_seq_add_stmt (&exit_seq, stmt);
236*e4b17023SJohn Marino }
237*e4b17023SJohn Marino
238*e4b17023SJohn Marino if (cond_is_first)
239*e4b17023SJohn Marino {
240*e4b17023SJohn Marino if (incr)
241*e4b17023SJohn Marino {
242*e4b17023SJohn Marino entry = gimple_build_label
243*e4b17023SJohn Marino (create_artificial_label (stmt_locus));
244*e4b17023SJohn Marino stmt = gimple_build_goto (gimple_label_label (entry));
245*e4b17023SJohn Marino }
246*e4b17023SJohn Marino else
247*e4b17023SJohn Marino stmt = gimple_build_goto (get_bc_label (bc_continue));
248*e4b17023SJohn Marino gimple_set_location (stmt, stmt_locus);
249*e4b17023SJohn Marino gimple_seq_add_stmt (&stmt_list, stmt);
250*e4b17023SJohn Marino }
251*e4b17023SJohn Marino }
252*e4b17023SJohn Marino else
253*e4b17023SJohn Marino {
254*e4b17023SJohn Marino stmt = gimple_build_goto (gimple_label_label (top));
255*e4b17023SJohn Marino gimple_seq_add_stmt (&exit_seq, stmt);
256*e4b17023SJohn Marino }
257*e4b17023SJohn Marino }
258*e4b17023SJohn Marino
259*e4b17023SJohn Marino gimplify_stmt (&body, &body_seq);
260*e4b17023SJohn Marino gimplify_stmt (&incr, &incr_seq);
261*e4b17023SJohn Marino
262*e4b17023SJohn Marino body_seq = finish_bc_block (bc_continue, cont_block, body_seq);
263*e4b17023SJohn Marino
264*e4b17023SJohn Marino gimple_seq_add_stmt (&stmt_list, top);
265*e4b17023SJohn Marino gimple_seq_add_seq (&stmt_list, body_seq);
266*e4b17023SJohn Marino gimple_seq_add_seq (&stmt_list, incr_seq);
267*e4b17023SJohn Marino gimple_seq_add_stmt (&stmt_list, entry);
268*e4b17023SJohn Marino gimple_seq_add_seq (&stmt_list, exit_seq);
269*e4b17023SJohn Marino
270*e4b17023SJohn Marino annotate_all_with_location (stmt_list, stmt_locus);
271*e4b17023SJohn Marino
272*e4b17023SJohn Marino return finish_bc_block (bc_break, break_block, stmt_list);
273*e4b17023SJohn Marino }
274*e4b17023SJohn Marino
275*e4b17023SJohn Marino /* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the
276*e4b17023SJohn Marino prequeue and hand off to gimplify_cp_loop. */
277*e4b17023SJohn Marino
278*e4b17023SJohn Marino static void
gimplify_for_stmt(tree * stmt_p,gimple_seq * pre_p)279*e4b17023SJohn Marino gimplify_for_stmt (tree *stmt_p, gimple_seq *pre_p)
280*e4b17023SJohn Marino {
281*e4b17023SJohn Marino tree stmt = *stmt_p;
282*e4b17023SJohn Marino
283*e4b17023SJohn Marino if (FOR_INIT_STMT (stmt))
284*e4b17023SJohn Marino gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
285*e4b17023SJohn Marino
286*e4b17023SJohn Marino gimple_seq_add_seq (pre_p,
287*e4b17023SJohn Marino gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
288*e4b17023SJohn Marino FOR_EXPR (stmt), 1));
289*e4b17023SJohn Marino *stmt_p = NULL_TREE;
290*e4b17023SJohn Marino }
291*e4b17023SJohn Marino
292*e4b17023SJohn Marino /* Gimplify a WHILE_STMT node. */
293*e4b17023SJohn Marino
294*e4b17023SJohn Marino static void
gimplify_while_stmt(tree * stmt_p,gimple_seq * pre_p)295*e4b17023SJohn Marino gimplify_while_stmt (tree *stmt_p, gimple_seq *pre_p)
296*e4b17023SJohn Marino {
297*e4b17023SJohn Marino tree stmt = *stmt_p;
298*e4b17023SJohn Marino gimple_seq_add_seq (pre_p,
299*e4b17023SJohn Marino gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
300*e4b17023SJohn Marino NULL_TREE, 1));
301*e4b17023SJohn Marino *stmt_p = NULL_TREE;
302*e4b17023SJohn Marino }
303*e4b17023SJohn Marino
304*e4b17023SJohn Marino /* Gimplify a DO_STMT node. */
305*e4b17023SJohn Marino
306*e4b17023SJohn Marino static void
gimplify_do_stmt(tree * stmt_p,gimple_seq * pre_p)307*e4b17023SJohn Marino gimplify_do_stmt (tree *stmt_p, gimple_seq *pre_p)
308*e4b17023SJohn Marino {
309*e4b17023SJohn Marino tree stmt = *stmt_p;
310*e4b17023SJohn Marino gimple_seq_add_seq (pre_p,
311*e4b17023SJohn Marino gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
312*e4b17023SJohn Marino NULL_TREE, 0));
313*e4b17023SJohn Marino *stmt_p = NULL_TREE;
314*e4b17023SJohn Marino }
315*e4b17023SJohn Marino
316*e4b17023SJohn Marino /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */
317*e4b17023SJohn Marino
318*e4b17023SJohn Marino static void
gimplify_switch_stmt(tree * stmt_p,gimple_seq * pre_p)319*e4b17023SJohn Marino gimplify_switch_stmt (tree *stmt_p, gimple_seq *pre_p)
320*e4b17023SJohn Marino {
321*e4b17023SJohn Marino tree stmt = *stmt_p;
322*e4b17023SJohn Marino tree break_block, body, t;
323*e4b17023SJohn Marino location_t stmt_locus = input_location;
324*e4b17023SJohn Marino gimple_seq seq = NULL;
325*e4b17023SJohn Marino
326*e4b17023SJohn Marino break_block = begin_bc_block (bc_break);
327*e4b17023SJohn Marino
328*e4b17023SJohn Marino body = SWITCH_STMT_BODY (stmt);
329*e4b17023SJohn Marino if (!body)
330*e4b17023SJohn Marino body = build_empty_stmt (stmt_locus);
331*e4b17023SJohn Marino
332*e4b17023SJohn Marino t = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
333*e4b17023SJohn Marino SWITCH_STMT_COND (stmt), body, NULL_TREE);
334*e4b17023SJohn Marino SET_EXPR_LOCATION (t, stmt_locus);
335*e4b17023SJohn Marino gimplify_and_add (t, &seq);
336*e4b17023SJohn Marino
337*e4b17023SJohn Marino seq = finish_bc_block (bc_break, break_block, seq);
338*e4b17023SJohn Marino gimple_seq_add_seq (pre_p, seq);
339*e4b17023SJohn Marino *stmt_p = NULL_TREE;
340*e4b17023SJohn Marino }
341*e4b17023SJohn Marino
342*e4b17023SJohn Marino /* Hook into the middle of gimplifying an OMP_FOR node. This is required
343*e4b17023SJohn Marino in order to properly gimplify CONTINUE statements. Here we merely
344*e4b17023SJohn Marino manage the continue stack; the rest of the job is performed by the
345*e4b17023SJohn Marino regular gimplifier. */
346*e4b17023SJohn Marino
347*e4b17023SJohn Marino static enum gimplify_status
cp_gimplify_omp_for(tree * expr_p,gimple_seq * pre_p)348*e4b17023SJohn Marino cp_gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
349*e4b17023SJohn Marino {
350*e4b17023SJohn Marino tree for_stmt = *expr_p;
351*e4b17023SJohn Marino tree cont_block;
352*e4b17023SJohn Marino gimple stmt;
353*e4b17023SJohn Marino gimple_seq seq = NULL;
354*e4b17023SJohn Marino
355*e4b17023SJohn Marino /* Protect ourselves from recursion. */
356*e4b17023SJohn Marino if (OMP_FOR_GIMPLIFYING_P (for_stmt))
357*e4b17023SJohn Marino return GS_UNHANDLED;
358*e4b17023SJohn Marino OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
359*e4b17023SJohn Marino
360*e4b17023SJohn Marino /* Note that while technically the continue label is enabled too soon
361*e4b17023SJohn Marino here, we should have already diagnosed invalid continues nested within
362*e4b17023SJohn Marino statement expressions within the INIT, COND, or INCR expressions. */
363*e4b17023SJohn Marino cont_block = begin_bc_block (bc_continue);
364*e4b17023SJohn Marino
365*e4b17023SJohn Marino gimplify_and_add (for_stmt, &seq);
366*e4b17023SJohn Marino stmt = gimple_seq_last_stmt (seq);
367*e4b17023SJohn Marino if (gimple_code (stmt) == GIMPLE_OMP_FOR)
368*e4b17023SJohn Marino gimple_omp_set_body (stmt, finish_bc_block (bc_continue, cont_block,
369*e4b17023SJohn Marino gimple_omp_body (stmt)));
370*e4b17023SJohn Marino else
371*e4b17023SJohn Marino seq = finish_bc_block (bc_continue, cont_block, seq);
372*e4b17023SJohn Marino gimple_seq_add_seq (pre_p, seq);
373*e4b17023SJohn Marino
374*e4b17023SJohn Marino OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
375*e4b17023SJohn Marino
376*e4b17023SJohn Marino return GS_ALL_DONE;
377*e4b17023SJohn Marino }
378*e4b17023SJohn Marino
379*e4b17023SJohn Marino /* Gimplify an EXPR_STMT node. */
380*e4b17023SJohn Marino
381*e4b17023SJohn Marino static void
gimplify_expr_stmt(tree * stmt_p)382*e4b17023SJohn Marino gimplify_expr_stmt (tree *stmt_p)
383*e4b17023SJohn Marino {
384*e4b17023SJohn Marino tree stmt = EXPR_STMT_EXPR (*stmt_p);
385*e4b17023SJohn Marino
386*e4b17023SJohn Marino if (stmt == error_mark_node)
387*e4b17023SJohn Marino stmt = NULL;
388*e4b17023SJohn Marino
389*e4b17023SJohn Marino /* Gimplification of a statement expression will nullify the
390*e4b17023SJohn Marino statement if all its side effects are moved to *PRE_P and *POST_P.
391*e4b17023SJohn Marino
392*e4b17023SJohn Marino In this case we will not want to emit the gimplified statement.
393*e4b17023SJohn Marino However, we may still want to emit a warning, so we do that before
394*e4b17023SJohn Marino gimplification. */
395*e4b17023SJohn Marino if (stmt && warn_unused_value)
396*e4b17023SJohn Marino {
397*e4b17023SJohn Marino if (!TREE_SIDE_EFFECTS (stmt))
398*e4b17023SJohn Marino {
399*e4b17023SJohn Marino if (!IS_EMPTY_STMT (stmt)
400*e4b17023SJohn Marino && !VOID_TYPE_P (TREE_TYPE (stmt))
401*e4b17023SJohn Marino && !TREE_NO_WARNING (stmt))
402*e4b17023SJohn Marino warning (OPT_Wunused_value, "statement with no effect");
403*e4b17023SJohn Marino }
404*e4b17023SJohn Marino else
405*e4b17023SJohn Marino warn_if_unused_value (stmt, input_location);
406*e4b17023SJohn Marino }
407*e4b17023SJohn Marino
408*e4b17023SJohn Marino if (stmt == NULL_TREE)
409*e4b17023SJohn Marino stmt = alloc_stmt_list ();
410*e4b17023SJohn Marino
411*e4b17023SJohn Marino *stmt_p = stmt;
412*e4b17023SJohn Marino }
413*e4b17023SJohn Marino
414*e4b17023SJohn Marino /* Gimplify initialization from an AGGR_INIT_EXPR. */
415*e4b17023SJohn Marino
416*e4b17023SJohn Marino static void
cp_gimplify_init_expr(tree * expr_p)417*e4b17023SJohn Marino cp_gimplify_init_expr (tree *expr_p)
418*e4b17023SJohn Marino {
419*e4b17023SJohn Marino tree from = TREE_OPERAND (*expr_p, 1);
420*e4b17023SJohn Marino tree to = TREE_OPERAND (*expr_p, 0);
421*e4b17023SJohn Marino tree t;
422*e4b17023SJohn Marino
423*e4b17023SJohn Marino /* What about code that pulls out the temp and uses it elsewhere? I
424*e4b17023SJohn Marino think that such code never uses the TARGET_EXPR as an initializer. If
425*e4b17023SJohn Marino I'm wrong, we'll abort because the temp won't have any RTL. In that
426*e4b17023SJohn Marino case, I guess we'll need to replace references somehow. */
427*e4b17023SJohn Marino if (TREE_CODE (from) == TARGET_EXPR)
428*e4b17023SJohn Marino from = TARGET_EXPR_INITIAL (from);
429*e4b17023SJohn Marino
430*e4b17023SJohn Marino /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
431*e4b17023SJohn Marino inside the TARGET_EXPR. */
432*e4b17023SJohn Marino for (t = from; t; )
433*e4b17023SJohn Marino {
434*e4b17023SJohn Marino tree sub = TREE_CODE (t) == COMPOUND_EXPR ? TREE_OPERAND (t, 0) : t;
435*e4b17023SJohn Marino
436*e4b17023SJohn Marino /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
437*e4b17023SJohn Marino replace the slot operand with our target.
438*e4b17023SJohn Marino
439*e4b17023SJohn Marino Should we add a target parm to gimplify_expr instead? No, as in this
440*e4b17023SJohn Marino case we want to replace the INIT_EXPR. */
441*e4b17023SJohn Marino if (TREE_CODE (sub) == AGGR_INIT_EXPR
442*e4b17023SJohn Marino || TREE_CODE (sub) == VEC_INIT_EXPR)
443*e4b17023SJohn Marino {
444*e4b17023SJohn Marino if (TREE_CODE (sub) == AGGR_INIT_EXPR)
445*e4b17023SJohn Marino AGGR_INIT_EXPR_SLOT (sub) = to;
446*e4b17023SJohn Marino else
447*e4b17023SJohn Marino VEC_INIT_EXPR_SLOT (sub) = to;
448*e4b17023SJohn Marino *expr_p = from;
449*e4b17023SJohn Marino
450*e4b17023SJohn Marino /* The initialization is now a side-effect, so the container can
451*e4b17023SJohn Marino become void. */
452*e4b17023SJohn Marino if (from != sub)
453*e4b17023SJohn Marino TREE_TYPE (from) = void_type_node;
454*e4b17023SJohn Marino }
455*e4b17023SJohn Marino
456*e4b17023SJohn Marino if (t == sub)
457*e4b17023SJohn Marino break;
458*e4b17023SJohn Marino else
459*e4b17023SJohn Marino t = TREE_OPERAND (t, 1);
460*e4b17023SJohn Marino }
461*e4b17023SJohn Marino
462*e4b17023SJohn Marino }
463*e4b17023SJohn Marino
464*e4b17023SJohn Marino /* Gimplify a MUST_NOT_THROW_EXPR. */
465*e4b17023SJohn Marino
466*e4b17023SJohn Marino static enum gimplify_status
gimplify_must_not_throw_expr(tree * expr_p,gimple_seq * pre_p)467*e4b17023SJohn Marino gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p)
468*e4b17023SJohn Marino {
469*e4b17023SJohn Marino tree stmt = *expr_p;
470*e4b17023SJohn Marino tree temp = voidify_wrapper_expr (stmt, NULL);
471*e4b17023SJohn Marino tree body = TREE_OPERAND (stmt, 0);
472*e4b17023SJohn Marino gimple_seq try_ = NULL;
473*e4b17023SJohn Marino gimple_seq catch_ = NULL;
474*e4b17023SJohn Marino gimple mnt;
475*e4b17023SJohn Marino
476*e4b17023SJohn Marino gimplify_and_add (body, &try_);
477*e4b17023SJohn Marino mnt = gimple_build_eh_must_not_throw (terminate_node);
478*e4b17023SJohn Marino gimple_seq_add_stmt_without_update (&catch_, mnt);
479*e4b17023SJohn Marino mnt = gimple_build_try (try_, catch_, GIMPLE_TRY_CATCH);
480*e4b17023SJohn Marino
481*e4b17023SJohn Marino gimple_seq_add_stmt_without_update (pre_p, mnt);
482*e4b17023SJohn Marino if (temp)
483*e4b17023SJohn Marino {
484*e4b17023SJohn Marino *expr_p = temp;
485*e4b17023SJohn Marino return GS_OK;
486*e4b17023SJohn Marino }
487*e4b17023SJohn Marino
488*e4b17023SJohn Marino *expr_p = NULL;
489*e4b17023SJohn Marino return GS_ALL_DONE;
490*e4b17023SJohn Marino }
491*e4b17023SJohn Marino
492*e4b17023SJohn Marino /* Do C++-specific gimplification. Args are as for gimplify_expr. */
493*e4b17023SJohn Marino
494*e4b17023SJohn Marino int
cp_gimplify_expr(tree * expr_p,gimple_seq * pre_p,gimple_seq * post_p)495*e4b17023SJohn Marino cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
496*e4b17023SJohn Marino {
497*e4b17023SJohn Marino int saved_stmts_are_full_exprs_p = 0;
498*e4b17023SJohn Marino enum tree_code code = TREE_CODE (*expr_p);
499*e4b17023SJohn Marino enum gimplify_status ret;
500*e4b17023SJohn Marino
501*e4b17023SJohn Marino if (STATEMENT_CODE_P (code))
502*e4b17023SJohn Marino {
503*e4b17023SJohn Marino saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
504*e4b17023SJohn Marino current_stmt_tree ()->stmts_are_full_exprs_p
505*e4b17023SJohn Marino = STMT_IS_FULL_EXPR_P (*expr_p);
506*e4b17023SJohn Marino }
507*e4b17023SJohn Marino
508*e4b17023SJohn Marino switch (code)
509*e4b17023SJohn Marino {
510*e4b17023SJohn Marino case PTRMEM_CST:
511*e4b17023SJohn Marino *expr_p = cplus_expand_constant (*expr_p);
512*e4b17023SJohn Marino ret = GS_OK;
513*e4b17023SJohn Marino break;
514*e4b17023SJohn Marino
515*e4b17023SJohn Marino case AGGR_INIT_EXPR:
516*e4b17023SJohn Marino simplify_aggr_init_expr (expr_p);
517*e4b17023SJohn Marino ret = GS_OK;
518*e4b17023SJohn Marino break;
519*e4b17023SJohn Marino
520*e4b17023SJohn Marino case VEC_INIT_EXPR:
521*e4b17023SJohn Marino {
522*e4b17023SJohn Marino location_t loc = input_location;
523*e4b17023SJohn Marino tree init = VEC_INIT_EXPR_INIT (*expr_p);
524*e4b17023SJohn Marino int from_array = (init && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE);
525*e4b17023SJohn Marino gcc_assert (EXPR_HAS_LOCATION (*expr_p));
526*e4b17023SJohn Marino input_location = EXPR_LOCATION (*expr_p);
527*e4b17023SJohn Marino *expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE,
528*e4b17023SJohn Marino init, VEC_INIT_EXPR_VALUE_INIT (*expr_p),
529*e4b17023SJohn Marino from_array,
530*e4b17023SJohn Marino tf_warning_or_error);
531*e4b17023SJohn Marino ret = GS_OK;
532*e4b17023SJohn Marino input_location = loc;
533*e4b17023SJohn Marino }
534*e4b17023SJohn Marino break;
535*e4b17023SJohn Marino
536*e4b17023SJohn Marino case THROW_EXPR:
537*e4b17023SJohn Marino /* FIXME communicate throw type to back end, probably by moving
538*e4b17023SJohn Marino THROW_EXPR into ../tree.def. */
539*e4b17023SJohn Marino *expr_p = TREE_OPERAND (*expr_p, 0);
540*e4b17023SJohn Marino ret = GS_OK;
541*e4b17023SJohn Marino break;
542*e4b17023SJohn Marino
543*e4b17023SJohn Marino case MUST_NOT_THROW_EXPR:
544*e4b17023SJohn Marino ret = gimplify_must_not_throw_expr (expr_p, pre_p);
545*e4b17023SJohn Marino break;
546*e4b17023SJohn Marino
547*e4b17023SJohn Marino /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
548*e4b17023SJohn Marino LHS of an assignment might also be involved in the RHS, as in bug
549*e4b17023SJohn Marino 25979. */
550*e4b17023SJohn Marino case INIT_EXPR:
551*e4b17023SJohn Marino cp_gimplify_init_expr (expr_p);
552*e4b17023SJohn Marino if (TREE_CODE (*expr_p) != INIT_EXPR)
553*e4b17023SJohn Marino return GS_OK;
554*e4b17023SJohn Marino /* Otherwise fall through. */
555*e4b17023SJohn Marino case MODIFY_EXPR:
556*e4b17023SJohn Marino {
557*e4b17023SJohn Marino /* If the back end isn't clever enough to know that the lhs and rhs
558*e4b17023SJohn Marino types are the same, add an explicit conversion. */
559*e4b17023SJohn Marino tree op0 = TREE_OPERAND (*expr_p, 0);
560*e4b17023SJohn Marino tree op1 = TREE_OPERAND (*expr_p, 1);
561*e4b17023SJohn Marino
562*e4b17023SJohn Marino if (!error_operand_p (op0)
563*e4b17023SJohn Marino && !error_operand_p (op1)
564*e4b17023SJohn Marino && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0))
565*e4b17023SJohn Marino || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1)))
566*e4b17023SJohn Marino && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
567*e4b17023SJohn Marino TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
568*e4b17023SJohn Marino TREE_TYPE (op0), op1);
569*e4b17023SJohn Marino
570*e4b17023SJohn Marino else if ((is_gimple_lvalue (op1) || INDIRECT_REF_P (op1)
571*e4b17023SJohn Marino || (TREE_CODE (op1) == CONSTRUCTOR
572*e4b17023SJohn Marino && CONSTRUCTOR_NELTS (op1) == 0
573*e4b17023SJohn Marino && !TREE_CLOBBER_P (op1))
574*e4b17023SJohn Marino || (TREE_CODE (op1) == CALL_EXPR
575*e4b17023SJohn Marino && !CALL_EXPR_RETURN_SLOT_OPT (op1)))
576*e4b17023SJohn Marino && is_really_empty_class (TREE_TYPE (op0)))
577*e4b17023SJohn Marino {
578*e4b17023SJohn Marino /* Remove any copies of empty classes. We check that the RHS
579*e4b17023SJohn Marino has a simple form so that TARGET_EXPRs and non-empty
580*e4b17023SJohn Marino CONSTRUCTORs get reduced properly, and we leave the return
581*e4b17023SJohn Marino slot optimization alone because it isn't a copy (FIXME so it
582*e4b17023SJohn Marino shouldn't be represented as one).
583*e4b17023SJohn Marino
584*e4b17023SJohn Marino Also drop volatile variables on the RHS to avoid infinite
585*e4b17023SJohn Marino recursion from gimplify_expr trying to load the value. */
586*e4b17023SJohn Marino if (!TREE_SIDE_EFFECTS (op1)
587*e4b17023SJohn Marino || (DECL_P (op1) && TREE_THIS_VOLATILE (op1)))
588*e4b17023SJohn Marino *expr_p = op0;
589*e4b17023SJohn Marino else if (TREE_CODE (op1) == MEM_REF
590*e4b17023SJohn Marino && TREE_THIS_VOLATILE (op1))
591*e4b17023SJohn Marino {
592*e4b17023SJohn Marino /* Similarly for volatile MEM_REFs on the RHS. */
593*e4b17023SJohn Marino if (!TREE_SIDE_EFFECTS (TREE_OPERAND (op1, 0)))
594*e4b17023SJohn Marino *expr_p = op0;
595*e4b17023SJohn Marino else
596*e4b17023SJohn Marino *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
597*e4b17023SJohn Marino TREE_OPERAND (op1, 0), op0);
598*e4b17023SJohn Marino }
599*e4b17023SJohn Marino else
600*e4b17023SJohn Marino *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
601*e4b17023SJohn Marino op0, op1);
602*e4b17023SJohn Marino }
603*e4b17023SJohn Marino }
604*e4b17023SJohn Marino ret = GS_OK;
605*e4b17023SJohn Marino break;
606*e4b17023SJohn Marino
607*e4b17023SJohn Marino case EMPTY_CLASS_EXPR:
608*e4b17023SJohn Marino /* We create an empty CONSTRUCTOR with RECORD_TYPE. */
609*e4b17023SJohn Marino *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
610*e4b17023SJohn Marino ret = GS_OK;
611*e4b17023SJohn Marino break;
612*e4b17023SJohn Marino
613*e4b17023SJohn Marino case BASELINK:
614*e4b17023SJohn Marino *expr_p = BASELINK_FUNCTIONS (*expr_p);
615*e4b17023SJohn Marino ret = GS_OK;
616*e4b17023SJohn Marino break;
617*e4b17023SJohn Marino
618*e4b17023SJohn Marino case TRY_BLOCK:
619*e4b17023SJohn Marino genericize_try_block (expr_p);
620*e4b17023SJohn Marino ret = GS_OK;
621*e4b17023SJohn Marino break;
622*e4b17023SJohn Marino
623*e4b17023SJohn Marino case HANDLER:
624*e4b17023SJohn Marino genericize_catch_block (expr_p);
625*e4b17023SJohn Marino ret = GS_OK;
626*e4b17023SJohn Marino break;
627*e4b17023SJohn Marino
628*e4b17023SJohn Marino case EH_SPEC_BLOCK:
629*e4b17023SJohn Marino genericize_eh_spec_block (expr_p);
630*e4b17023SJohn Marino ret = GS_OK;
631*e4b17023SJohn Marino break;
632*e4b17023SJohn Marino
633*e4b17023SJohn Marino case USING_STMT:
634*e4b17023SJohn Marino gcc_unreachable ();
635*e4b17023SJohn Marino
636*e4b17023SJohn Marino case FOR_STMT:
637*e4b17023SJohn Marino gimplify_for_stmt (expr_p, pre_p);
638*e4b17023SJohn Marino ret = GS_OK;
639*e4b17023SJohn Marino break;
640*e4b17023SJohn Marino
641*e4b17023SJohn Marino case WHILE_STMT:
642*e4b17023SJohn Marino gimplify_while_stmt (expr_p, pre_p);
643*e4b17023SJohn Marino ret = GS_OK;
644*e4b17023SJohn Marino break;
645*e4b17023SJohn Marino
646*e4b17023SJohn Marino case DO_STMT:
647*e4b17023SJohn Marino gimplify_do_stmt (expr_p, pre_p);
648*e4b17023SJohn Marino ret = GS_OK;
649*e4b17023SJohn Marino break;
650*e4b17023SJohn Marino
651*e4b17023SJohn Marino case SWITCH_STMT:
652*e4b17023SJohn Marino gimplify_switch_stmt (expr_p, pre_p);
653*e4b17023SJohn Marino ret = GS_OK;
654*e4b17023SJohn Marino break;
655*e4b17023SJohn Marino
656*e4b17023SJohn Marino case OMP_FOR:
657*e4b17023SJohn Marino ret = cp_gimplify_omp_for (expr_p, pre_p);
658*e4b17023SJohn Marino break;
659*e4b17023SJohn Marino
660*e4b17023SJohn Marino case CONTINUE_STMT:
661*e4b17023SJohn Marino gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_CONTINUE, NOT_TAKEN));
662*e4b17023SJohn Marino gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_continue)));
663*e4b17023SJohn Marino *expr_p = NULL_TREE;
664*e4b17023SJohn Marino ret = GS_ALL_DONE;
665*e4b17023SJohn Marino break;
666*e4b17023SJohn Marino
667*e4b17023SJohn Marino case BREAK_STMT:
668*e4b17023SJohn Marino gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_break)));
669*e4b17023SJohn Marino *expr_p = NULL_TREE;
670*e4b17023SJohn Marino ret = GS_ALL_DONE;
671*e4b17023SJohn Marino break;
672*e4b17023SJohn Marino
673*e4b17023SJohn Marino case EXPR_STMT:
674*e4b17023SJohn Marino gimplify_expr_stmt (expr_p);
675*e4b17023SJohn Marino ret = GS_OK;
676*e4b17023SJohn Marino break;
677*e4b17023SJohn Marino
678*e4b17023SJohn Marino case UNARY_PLUS_EXPR:
679*e4b17023SJohn Marino {
680*e4b17023SJohn Marino tree arg = TREE_OPERAND (*expr_p, 0);
681*e4b17023SJohn Marino tree type = TREE_TYPE (*expr_p);
682*e4b17023SJohn Marino *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
683*e4b17023SJohn Marino : arg;
684*e4b17023SJohn Marino ret = GS_OK;
685*e4b17023SJohn Marino }
686*e4b17023SJohn Marino break;
687*e4b17023SJohn Marino
688*e4b17023SJohn Marino default:
689*e4b17023SJohn Marino ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p);
690*e4b17023SJohn Marino break;
691*e4b17023SJohn Marino }
692*e4b17023SJohn Marino
693*e4b17023SJohn Marino /* Restore saved state. */
694*e4b17023SJohn Marino if (STATEMENT_CODE_P (code))
695*e4b17023SJohn Marino current_stmt_tree ()->stmts_are_full_exprs_p
696*e4b17023SJohn Marino = saved_stmts_are_full_exprs_p;
697*e4b17023SJohn Marino
698*e4b17023SJohn Marino return ret;
699*e4b17023SJohn Marino }
700*e4b17023SJohn Marino
701*e4b17023SJohn Marino static inline bool
is_invisiref_parm(const_tree t)702*e4b17023SJohn Marino is_invisiref_parm (const_tree t)
703*e4b17023SJohn Marino {
704*e4b17023SJohn Marino return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
705*e4b17023SJohn Marino && DECL_BY_REFERENCE (t));
706*e4b17023SJohn Marino }
707*e4b17023SJohn Marino
708*e4b17023SJohn Marino /* Return true if the uid in both int tree maps are equal. */
709*e4b17023SJohn Marino
710*e4b17023SJohn Marino int
cxx_int_tree_map_eq(const void * va,const void * vb)711*e4b17023SJohn Marino cxx_int_tree_map_eq (const void *va, const void *vb)
712*e4b17023SJohn Marino {
713*e4b17023SJohn Marino const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
714*e4b17023SJohn Marino const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
715*e4b17023SJohn Marino return (a->uid == b->uid);
716*e4b17023SJohn Marino }
717*e4b17023SJohn Marino
718*e4b17023SJohn Marino /* Hash a UID in a cxx_int_tree_map. */
719*e4b17023SJohn Marino
720*e4b17023SJohn Marino unsigned int
cxx_int_tree_map_hash(const void * item)721*e4b17023SJohn Marino cxx_int_tree_map_hash (const void *item)
722*e4b17023SJohn Marino {
723*e4b17023SJohn Marino return ((const struct cxx_int_tree_map *)item)->uid;
724*e4b17023SJohn Marino }
725*e4b17023SJohn Marino
726*e4b17023SJohn Marino /* A stable comparison routine for use with splay trees and DECLs. */
727*e4b17023SJohn Marino
728*e4b17023SJohn Marino static int
splay_tree_compare_decl_uid(splay_tree_key xa,splay_tree_key xb)729*e4b17023SJohn Marino splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
730*e4b17023SJohn Marino {
731*e4b17023SJohn Marino tree a = (tree) xa;
732*e4b17023SJohn Marino tree b = (tree) xb;
733*e4b17023SJohn Marino
734*e4b17023SJohn Marino return DECL_UID (a) - DECL_UID (b);
735*e4b17023SJohn Marino }
736*e4b17023SJohn Marino
737*e4b17023SJohn Marino /* OpenMP context during genericization. */
738*e4b17023SJohn Marino
739*e4b17023SJohn Marino struct cp_genericize_omp_taskreg
740*e4b17023SJohn Marino {
741*e4b17023SJohn Marino bool is_parallel;
742*e4b17023SJohn Marino bool default_shared;
743*e4b17023SJohn Marino struct cp_genericize_omp_taskreg *outer;
744*e4b17023SJohn Marino splay_tree variables;
745*e4b17023SJohn Marino };
746*e4b17023SJohn Marino
747*e4b17023SJohn Marino /* Return true if genericization should try to determine if
748*e4b17023SJohn Marino DECL is firstprivate or shared within task regions. */
749*e4b17023SJohn Marino
750*e4b17023SJohn Marino static bool
omp_var_to_track(tree decl)751*e4b17023SJohn Marino omp_var_to_track (tree decl)
752*e4b17023SJohn Marino {
753*e4b17023SJohn Marino tree type = TREE_TYPE (decl);
754*e4b17023SJohn Marino if (is_invisiref_parm (decl))
755*e4b17023SJohn Marino type = TREE_TYPE (type);
756*e4b17023SJohn Marino while (TREE_CODE (type) == ARRAY_TYPE)
757*e4b17023SJohn Marino type = TREE_TYPE (type);
758*e4b17023SJohn Marino if (type == error_mark_node || !CLASS_TYPE_P (type))
759*e4b17023SJohn Marino return false;
760*e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
761*e4b17023SJohn Marino return false;
762*e4b17023SJohn Marino if (cxx_omp_predetermined_sharing (decl) != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
763*e4b17023SJohn Marino return false;
764*e4b17023SJohn Marino return true;
765*e4b17023SJohn Marino }
766*e4b17023SJohn Marino
767*e4b17023SJohn Marino /* Note DECL use in OpenMP region OMP_CTX during genericization. */
768*e4b17023SJohn Marino
769*e4b17023SJohn Marino static void
omp_cxx_notice_variable(struct cp_genericize_omp_taskreg * omp_ctx,tree decl)770*e4b17023SJohn Marino omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl)
771*e4b17023SJohn Marino {
772*e4b17023SJohn Marino splay_tree_node n = splay_tree_lookup (omp_ctx->variables,
773*e4b17023SJohn Marino (splay_tree_key) decl);
774*e4b17023SJohn Marino if (n == NULL)
775*e4b17023SJohn Marino {
776*e4b17023SJohn Marino int flags = OMP_CLAUSE_DEFAULT_SHARED;
777*e4b17023SJohn Marino if (omp_ctx->outer)
778*e4b17023SJohn Marino omp_cxx_notice_variable (omp_ctx->outer, decl);
779*e4b17023SJohn Marino if (!omp_ctx->default_shared)
780*e4b17023SJohn Marino {
781*e4b17023SJohn Marino struct cp_genericize_omp_taskreg *octx;
782*e4b17023SJohn Marino
783*e4b17023SJohn Marino for (octx = omp_ctx->outer; octx; octx = octx->outer)
784*e4b17023SJohn Marino {
785*e4b17023SJohn Marino n = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
786*e4b17023SJohn Marino if (n && n->value != OMP_CLAUSE_DEFAULT_SHARED)
787*e4b17023SJohn Marino {
788*e4b17023SJohn Marino flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
789*e4b17023SJohn Marino break;
790*e4b17023SJohn Marino }
791*e4b17023SJohn Marino if (octx->is_parallel)
792*e4b17023SJohn Marino break;
793*e4b17023SJohn Marino }
794*e4b17023SJohn Marino if (octx == NULL
795*e4b17023SJohn Marino && (TREE_CODE (decl) == PARM_DECL
796*e4b17023SJohn Marino || (!(TREE_STATIC (decl) || DECL_EXTERNAL (decl))
797*e4b17023SJohn Marino && DECL_CONTEXT (decl) == current_function_decl)))
798*e4b17023SJohn Marino flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
799*e4b17023SJohn Marino if (flags == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
800*e4b17023SJohn Marino {
801*e4b17023SJohn Marino /* DECL is implicitly determined firstprivate in
802*e4b17023SJohn Marino the current task construct. Ensure copy ctor and
803*e4b17023SJohn Marino dtor are instantiated, because during gimplification
804*e4b17023SJohn Marino it will be already too late. */
805*e4b17023SJohn Marino tree type = TREE_TYPE (decl);
806*e4b17023SJohn Marino if (is_invisiref_parm (decl))
807*e4b17023SJohn Marino type = TREE_TYPE (type);
808*e4b17023SJohn Marino while (TREE_CODE (type) == ARRAY_TYPE)
809*e4b17023SJohn Marino type = TREE_TYPE (type);
810*e4b17023SJohn Marino get_copy_ctor (type, tf_none);
811*e4b17023SJohn Marino get_dtor (type, tf_none);
812*e4b17023SJohn Marino }
813*e4b17023SJohn Marino }
814*e4b17023SJohn Marino splay_tree_insert (omp_ctx->variables, (splay_tree_key) decl, flags);
815*e4b17023SJohn Marino }
816*e4b17023SJohn Marino }
817*e4b17023SJohn Marino
818*e4b17023SJohn Marino /* Genericization context. */
819*e4b17023SJohn Marino
820*e4b17023SJohn Marino struct cp_genericize_data
821*e4b17023SJohn Marino {
822*e4b17023SJohn Marino struct pointer_set_t *p_set;
823*e4b17023SJohn Marino VEC (tree, heap) *bind_expr_stack;
824*e4b17023SJohn Marino struct cp_genericize_omp_taskreg *omp_ctx;
825*e4b17023SJohn Marino };
826*e4b17023SJohn Marino
827*e4b17023SJohn Marino /* Perform any pre-gimplification lowering of C++ front end trees to
828*e4b17023SJohn Marino GENERIC. */
829*e4b17023SJohn Marino
830*e4b17023SJohn Marino static tree
cp_genericize_r(tree * stmt_p,int * walk_subtrees,void * data)831*e4b17023SJohn Marino cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
832*e4b17023SJohn Marino {
833*e4b17023SJohn Marino tree stmt = *stmt_p;
834*e4b17023SJohn Marino struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
835*e4b17023SJohn Marino struct pointer_set_t *p_set = wtd->p_set;
836*e4b17023SJohn Marino
837*e4b17023SJohn Marino /* If in an OpenMP context, note var uses. */
838*e4b17023SJohn Marino if (__builtin_expect (wtd->omp_ctx != NULL, 0)
839*e4b17023SJohn Marino && (TREE_CODE (stmt) == VAR_DECL
840*e4b17023SJohn Marino || TREE_CODE (stmt) == PARM_DECL
841*e4b17023SJohn Marino || TREE_CODE (stmt) == RESULT_DECL)
842*e4b17023SJohn Marino && omp_var_to_track (stmt))
843*e4b17023SJohn Marino omp_cxx_notice_variable (wtd->omp_ctx, stmt);
844*e4b17023SJohn Marino
845*e4b17023SJohn Marino if (is_invisiref_parm (stmt)
846*e4b17023SJohn Marino /* Don't dereference parms in a thunk, pass the references through. */
847*e4b17023SJohn Marino && !(DECL_THUNK_P (current_function_decl)
848*e4b17023SJohn Marino && TREE_CODE (stmt) == PARM_DECL))
849*e4b17023SJohn Marino {
850*e4b17023SJohn Marino *stmt_p = convert_from_reference (stmt);
851*e4b17023SJohn Marino *walk_subtrees = 0;
852*e4b17023SJohn Marino return NULL;
853*e4b17023SJohn Marino }
854*e4b17023SJohn Marino
855*e4b17023SJohn Marino /* Map block scope extern declarations to visible declarations with the
856*e4b17023SJohn Marino same name and type in outer scopes if any. */
857*e4b17023SJohn Marino if (cp_function_chain->extern_decl_map
858*e4b17023SJohn Marino && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
859*e4b17023SJohn Marino && DECL_EXTERNAL (stmt))
860*e4b17023SJohn Marino {
861*e4b17023SJohn Marino struct cxx_int_tree_map *h, in;
862*e4b17023SJohn Marino in.uid = DECL_UID (stmt);
863*e4b17023SJohn Marino h = (struct cxx_int_tree_map *)
864*e4b17023SJohn Marino htab_find_with_hash (cp_function_chain->extern_decl_map,
865*e4b17023SJohn Marino &in, in.uid);
866*e4b17023SJohn Marino if (h)
867*e4b17023SJohn Marino {
868*e4b17023SJohn Marino *stmt_p = h->to;
869*e4b17023SJohn Marino *walk_subtrees = 0;
870*e4b17023SJohn Marino return NULL;
871*e4b17023SJohn Marino }
872*e4b17023SJohn Marino }
873*e4b17023SJohn Marino
874*e4b17023SJohn Marino /* Other than invisiref parms, don't walk the same tree twice. */
875*e4b17023SJohn Marino if (pointer_set_contains (p_set, stmt))
876*e4b17023SJohn Marino {
877*e4b17023SJohn Marino *walk_subtrees = 0;
878*e4b17023SJohn Marino return NULL_TREE;
879*e4b17023SJohn Marino }
880*e4b17023SJohn Marino
881*e4b17023SJohn Marino if (TREE_CODE (stmt) == ADDR_EXPR
882*e4b17023SJohn Marino && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
883*e4b17023SJohn Marino {
884*e4b17023SJohn Marino /* If in an OpenMP context, note var uses. */
885*e4b17023SJohn Marino if (__builtin_expect (wtd->omp_ctx != NULL, 0)
886*e4b17023SJohn Marino && omp_var_to_track (TREE_OPERAND (stmt, 0)))
887*e4b17023SJohn Marino omp_cxx_notice_variable (wtd->omp_ctx, TREE_OPERAND (stmt, 0));
888*e4b17023SJohn Marino *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
889*e4b17023SJohn Marino *walk_subtrees = 0;
890*e4b17023SJohn Marino }
891*e4b17023SJohn Marino else if (TREE_CODE (stmt) == RETURN_EXPR
892*e4b17023SJohn Marino && TREE_OPERAND (stmt, 0)
893*e4b17023SJohn Marino && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
894*e4b17023SJohn Marino /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */
895*e4b17023SJohn Marino *walk_subtrees = 0;
896*e4b17023SJohn Marino else if (TREE_CODE (stmt) == OMP_CLAUSE)
897*e4b17023SJohn Marino switch (OMP_CLAUSE_CODE (stmt))
898*e4b17023SJohn Marino {
899*e4b17023SJohn Marino case OMP_CLAUSE_LASTPRIVATE:
900*e4b17023SJohn Marino /* Don't dereference an invisiref in OpenMP clauses. */
901*e4b17023SJohn Marino if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
902*e4b17023SJohn Marino {
903*e4b17023SJohn Marino *walk_subtrees = 0;
904*e4b17023SJohn Marino if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt))
905*e4b17023SJohn Marino cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt),
906*e4b17023SJohn Marino cp_genericize_r, data, NULL);
907*e4b17023SJohn Marino }
908*e4b17023SJohn Marino break;
909*e4b17023SJohn Marino case OMP_CLAUSE_PRIVATE:
910*e4b17023SJohn Marino /* Don't dereference an invisiref in OpenMP clauses. */
911*e4b17023SJohn Marino if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
912*e4b17023SJohn Marino *walk_subtrees = 0;
913*e4b17023SJohn Marino else if (wtd->omp_ctx != NULL)
914*e4b17023SJohn Marino {
915*e4b17023SJohn Marino /* Private clause doesn't cause any references to the
916*e4b17023SJohn Marino var in outer contexts, avoid calling
917*e4b17023SJohn Marino omp_cxx_notice_variable for it. */
918*e4b17023SJohn Marino struct cp_genericize_omp_taskreg *old = wtd->omp_ctx;
919*e4b17023SJohn Marino wtd->omp_ctx = NULL;
920*e4b17023SJohn Marino cp_walk_tree (&OMP_CLAUSE_DECL (stmt), cp_genericize_r,
921*e4b17023SJohn Marino data, NULL);
922*e4b17023SJohn Marino wtd->omp_ctx = old;
923*e4b17023SJohn Marino *walk_subtrees = 0;
924*e4b17023SJohn Marino }
925*e4b17023SJohn Marino break;
926*e4b17023SJohn Marino case OMP_CLAUSE_SHARED:
927*e4b17023SJohn Marino case OMP_CLAUSE_FIRSTPRIVATE:
928*e4b17023SJohn Marino case OMP_CLAUSE_COPYIN:
929*e4b17023SJohn Marino case OMP_CLAUSE_COPYPRIVATE:
930*e4b17023SJohn Marino /* Don't dereference an invisiref in OpenMP clauses. */
931*e4b17023SJohn Marino if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
932*e4b17023SJohn Marino *walk_subtrees = 0;
933*e4b17023SJohn Marino break;
934*e4b17023SJohn Marino case OMP_CLAUSE_REDUCTION:
935*e4b17023SJohn Marino gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
936*e4b17023SJohn Marino break;
937*e4b17023SJohn Marino default:
938*e4b17023SJohn Marino break;
939*e4b17023SJohn Marino }
940*e4b17023SJohn Marino else if (IS_TYPE_OR_DECL_P (stmt))
941*e4b17023SJohn Marino *walk_subtrees = 0;
942*e4b17023SJohn Marino
943*e4b17023SJohn Marino /* Due to the way voidify_wrapper_expr is written, we don't get a chance
944*e4b17023SJohn Marino to lower this construct before scanning it, so we need to lower these
945*e4b17023SJohn Marino before doing anything else. */
946*e4b17023SJohn Marino else if (TREE_CODE (stmt) == CLEANUP_STMT)
947*e4b17023SJohn Marino *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
948*e4b17023SJohn Marino : TRY_FINALLY_EXPR,
949*e4b17023SJohn Marino void_type_node,
950*e4b17023SJohn Marino CLEANUP_BODY (stmt),
951*e4b17023SJohn Marino CLEANUP_EXPR (stmt));
952*e4b17023SJohn Marino
953*e4b17023SJohn Marino else if (TREE_CODE (stmt) == IF_STMT)
954*e4b17023SJohn Marino {
955*e4b17023SJohn Marino genericize_if_stmt (stmt_p);
956*e4b17023SJohn Marino /* *stmt_p has changed, tail recurse to handle it again. */
957*e4b17023SJohn Marino return cp_genericize_r (stmt_p, walk_subtrees, data);
958*e4b17023SJohn Marino }
959*e4b17023SJohn Marino
960*e4b17023SJohn Marino /* COND_EXPR might have incompatible types in branches if one or both
961*e4b17023SJohn Marino arms are bitfields. Fix it up now. */
962*e4b17023SJohn Marino else if (TREE_CODE (stmt) == COND_EXPR)
963*e4b17023SJohn Marino {
964*e4b17023SJohn Marino tree type_left
965*e4b17023SJohn Marino = (TREE_OPERAND (stmt, 1)
966*e4b17023SJohn Marino ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1))
967*e4b17023SJohn Marino : NULL_TREE);
968*e4b17023SJohn Marino tree type_right
969*e4b17023SJohn Marino = (TREE_OPERAND (stmt, 2)
970*e4b17023SJohn Marino ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2))
971*e4b17023SJohn Marino : NULL_TREE);
972*e4b17023SJohn Marino if (type_left
973*e4b17023SJohn Marino && !useless_type_conversion_p (TREE_TYPE (stmt),
974*e4b17023SJohn Marino TREE_TYPE (TREE_OPERAND (stmt, 1))))
975*e4b17023SJohn Marino {
976*e4b17023SJohn Marino TREE_OPERAND (stmt, 1)
977*e4b17023SJohn Marino = fold_convert (type_left, TREE_OPERAND (stmt, 1));
978*e4b17023SJohn Marino gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
979*e4b17023SJohn Marino type_left));
980*e4b17023SJohn Marino }
981*e4b17023SJohn Marino if (type_right
982*e4b17023SJohn Marino && !useless_type_conversion_p (TREE_TYPE (stmt),
983*e4b17023SJohn Marino TREE_TYPE (TREE_OPERAND (stmt, 2))))
984*e4b17023SJohn Marino {
985*e4b17023SJohn Marino TREE_OPERAND (stmt, 2)
986*e4b17023SJohn Marino = fold_convert (type_right, TREE_OPERAND (stmt, 2));
987*e4b17023SJohn Marino gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
988*e4b17023SJohn Marino type_right));
989*e4b17023SJohn Marino }
990*e4b17023SJohn Marino }
991*e4b17023SJohn Marino
992*e4b17023SJohn Marino else if (TREE_CODE (stmt) == BIND_EXPR)
993*e4b17023SJohn Marino {
994*e4b17023SJohn Marino if (__builtin_expect (wtd->omp_ctx != NULL, 0))
995*e4b17023SJohn Marino {
996*e4b17023SJohn Marino tree decl;
997*e4b17023SJohn Marino for (decl = BIND_EXPR_VARS (stmt); decl; decl = DECL_CHAIN (decl))
998*e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL
999*e4b17023SJohn Marino && !DECL_EXTERNAL (decl)
1000*e4b17023SJohn Marino && omp_var_to_track (decl))
1001*e4b17023SJohn Marino {
1002*e4b17023SJohn Marino splay_tree_node n
1003*e4b17023SJohn Marino = splay_tree_lookup (wtd->omp_ctx->variables,
1004*e4b17023SJohn Marino (splay_tree_key) decl);
1005*e4b17023SJohn Marino if (n == NULL)
1006*e4b17023SJohn Marino splay_tree_insert (wtd->omp_ctx->variables,
1007*e4b17023SJohn Marino (splay_tree_key) decl,
1008*e4b17023SJohn Marino TREE_STATIC (decl)
1009*e4b17023SJohn Marino ? OMP_CLAUSE_DEFAULT_SHARED
1010*e4b17023SJohn Marino : OMP_CLAUSE_DEFAULT_PRIVATE);
1011*e4b17023SJohn Marino }
1012*e4b17023SJohn Marino }
1013*e4b17023SJohn Marino VEC_safe_push (tree, heap, wtd->bind_expr_stack, stmt);
1014*e4b17023SJohn Marino cp_walk_tree (&BIND_EXPR_BODY (stmt),
1015*e4b17023SJohn Marino cp_genericize_r, data, NULL);
1016*e4b17023SJohn Marino VEC_pop (tree, wtd->bind_expr_stack);
1017*e4b17023SJohn Marino }
1018*e4b17023SJohn Marino
1019*e4b17023SJohn Marino else if (TREE_CODE (stmt) == USING_STMT)
1020*e4b17023SJohn Marino {
1021*e4b17023SJohn Marino tree block = NULL_TREE;
1022*e4b17023SJohn Marino
1023*e4b17023SJohn Marino /* Get the innermost inclosing GIMPLE_BIND that has a non NULL
1024*e4b17023SJohn Marino BLOCK, and append an IMPORTED_DECL to its
1025*e4b17023SJohn Marino BLOCK_VARS chained list. */
1026*e4b17023SJohn Marino if (wtd->bind_expr_stack)
1027*e4b17023SJohn Marino {
1028*e4b17023SJohn Marino int i;
1029*e4b17023SJohn Marino for (i = VEC_length (tree, wtd->bind_expr_stack) - 1; i >= 0; i--)
1030*e4b17023SJohn Marino if ((block = BIND_EXPR_BLOCK (VEC_index (tree,
1031*e4b17023SJohn Marino wtd->bind_expr_stack, i))))
1032*e4b17023SJohn Marino break;
1033*e4b17023SJohn Marino }
1034*e4b17023SJohn Marino if (block)
1035*e4b17023SJohn Marino {
1036*e4b17023SJohn Marino tree using_directive;
1037*e4b17023SJohn Marino gcc_assert (TREE_OPERAND (stmt, 0));
1038*e4b17023SJohn Marino
1039*e4b17023SJohn Marino using_directive = make_node (IMPORTED_DECL);
1040*e4b17023SJohn Marino TREE_TYPE (using_directive) = void_type_node;
1041*e4b17023SJohn Marino
1042*e4b17023SJohn Marino IMPORTED_DECL_ASSOCIATED_DECL (using_directive)
1043*e4b17023SJohn Marino = TREE_OPERAND (stmt, 0);
1044*e4b17023SJohn Marino DECL_CHAIN (using_directive) = BLOCK_VARS (block);
1045*e4b17023SJohn Marino BLOCK_VARS (block) = using_directive;
1046*e4b17023SJohn Marino }
1047*e4b17023SJohn Marino /* The USING_STMT won't appear in GENERIC. */
1048*e4b17023SJohn Marino *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
1049*e4b17023SJohn Marino *walk_subtrees = 0;
1050*e4b17023SJohn Marino }
1051*e4b17023SJohn Marino
1052*e4b17023SJohn Marino else if (TREE_CODE (stmt) == DECL_EXPR
1053*e4b17023SJohn Marino && TREE_CODE (DECL_EXPR_DECL (stmt)) == USING_DECL)
1054*e4b17023SJohn Marino {
1055*e4b17023SJohn Marino /* Using decls inside DECL_EXPRs are just dropped on the floor. */
1056*e4b17023SJohn Marino *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
1057*e4b17023SJohn Marino *walk_subtrees = 0;
1058*e4b17023SJohn Marino }
1059*e4b17023SJohn Marino else if (TREE_CODE (stmt) == OMP_PARALLEL || TREE_CODE (stmt) == OMP_TASK)
1060*e4b17023SJohn Marino {
1061*e4b17023SJohn Marino struct cp_genericize_omp_taskreg omp_ctx;
1062*e4b17023SJohn Marino tree c, decl;
1063*e4b17023SJohn Marino splay_tree_node n;
1064*e4b17023SJohn Marino
1065*e4b17023SJohn Marino *walk_subtrees = 0;
1066*e4b17023SJohn Marino cp_walk_tree (&OMP_CLAUSES (stmt), cp_genericize_r, data, NULL);
1067*e4b17023SJohn Marino omp_ctx.is_parallel = TREE_CODE (stmt) == OMP_PARALLEL;
1068*e4b17023SJohn Marino omp_ctx.default_shared = omp_ctx.is_parallel;
1069*e4b17023SJohn Marino omp_ctx.outer = wtd->omp_ctx;
1070*e4b17023SJohn Marino omp_ctx.variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
1071*e4b17023SJohn Marino wtd->omp_ctx = &omp_ctx;
1072*e4b17023SJohn Marino for (c = OMP_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
1073*e4b17023SJohn Marino switch (OMP_CLAUSE_CODE (c))
1074*e4b17023SJohn Marino {
1075*e4b17023SJohn Marino case OMP_CLAUSE_SHARED:
1076*e4b17023SJohn Marino case OMP_CLAUSE_PRIVATE:
1077*e4b17023SJohn Marino case OMP_CLAUSE_FIRSTPRIVATE:
1078*e4b17023SJohn Marino case OMP_CLAUSE_LASTPRIVATE:
1079*e4b17023SJohn Marino decl = OMP_CLAUSE_DECL (c);
1080*e4b17023SJohn Marino if (decl == error_mark_node || !omp_var_to_track (decl))
1081*e4b17023SJohn Marino break;
1082*e4b17023SJohn Marino n = splay_tree_lookup (omp_ctx.variables, (splay_tree_key) decl);
1083*e4b17023SJohn Marino if (n != NULL)
1084*e4b17023SJohn Marino break;
1085*e4b17023SJohn Marino splay_tree_insert (omp_ctx.variables, (splay_tree_key) decl,
1086*e4b17023SJohn Marino OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1087*e4b17023SJohn Marino ? OMP_CLAUSE_DEFAULT_SHARED
1088*e4b17023SJohn Marino : OMP_CLAUSE_DEFAULT_PRIVATE);
1089*e4b17023SJohn Marino if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE
1090*e4b17023SJohn Marino && omp_ctx.outer)
1091*e4b17023SJohn Marino omp_cxx_notice_variable (omp_ctx.outer, decl);
1092*e4b17023SJohn Marino break;
1093*e4b17023SJohn Marino case OMP_CLAUSE_DEFAULT:
1094*e4b17023SJohn Marino if (OMP_CLAUSE_DEFAULT_KIND (c) == OMP_CLAUSE_DEFAULT_SHARED)
1095*e4b17023SJohn Marino omp_ctx.default_shared = true;
1096*e4b17023SJohn Marino default:
1097*e4b17023SJohn Marino break;
1098*e4b17023SJohn Marino }
1099*e4b17023SJohn Marino cp_walk_tree (&OMP_BODY (stmt), cp_genericize_r, data, NULL);
1100*e4b17023SJohn Marino wtd->omp_ctx = omp_ctx.outer;
1101*e4b17023SJohn Marino splay_tree_delete (omp_ctx.variables);
1102*e4b17023SJohn Marino }
1103*e4b17023SJohn Marino else if (TREE_CODE (stmt) == CONVERT_EXPR)
1104*e4b17023SJohn Marino gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt));
1105*e4b17023SJohn Marino
1106*e4b17023SJohn Marino pointer_set_insert (p_set, *stmt_p);
1107*e4b17023SJohn Marino
1108*e4b17023SJohn Marino return NULL;
1109*e4b17023SJohn Marino }
1110*e4b17023SJohn Marino
1111*e4b17023SJohn Marino void
cp_genericize(tree fndecl)1112*e4b17023SJohn Marino cp_genericize (tree fndecl)
1113*e4b17023SJohn Marino {
1114*e4b17023SJohn Marino tree t;
1115*e4b17023SJohn Marino struct cp_genericize_data wtd;
1116*e4b17023SJohn Marino
1117*e4b17023SJohn Marino /* Fix up the types of parms passed by invisible reference. */
1118*e4b17023SJohn Marino for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t))
1119*e4b17023SJohn Marino if (TREE_ADDRESSABLE (TREE_TYPE (t)))
1120*e4b17023SJohn Marino {
1121*e4b17023SJohn Marino /* If a function's arguments are copied to create a thunk,
1122*e4b17023SJohn Marino then DECL_BY_REFERENCE will be set -- but the type of the
1123*e4b17023SJohn Marino argument will be a pointer type, so we will never get
1124*e4b17023SJohn Marino here. */
1125*e4b17023SJohn Marino gcc_assert (!DECL_BY_REFERENCE (t));
1126*e4b17023SJohn Marino gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
1127*e4b17023SJohn Marino TREE_TYPE (t) = DECL_ARG_TYPE (t);
1128*e4b17023SJohn Marino DECL_BY_REFERENCE (t) = 1;
1129*e4b17023SJohn Marino TREE_ADDRESSABLE (t) = 0;
1130*e4b17023SJohn Marino relayout_decl (t);
1131*e4b17023SJohn Marino }
1132*e4b17023SJohn Marino
1133*e4b17023SJohn Marino /* Do the same for the return value. */
1134*e4b17023SJohn Marino if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
1135*e4b17023SJohn Marino {
1136*e4b17023SJohn Marino t = DECL_RESULT (fndecl);
1137*e4b17023SJohn Marino TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
1138*e4b17023SJohn Marino DECL_BY_REFERENCE (t) = 1;
1139*e4b17023SJohn Marino TREE_ADDRESSABLE (t) = 0;
1140*e4b17023SJohn Marino relayout_decl (t);
1141*e4b17023SJohn Marino if (DECL_NAME (t))
1142*e4b17023SJohn Marino {
1143*e4b17023SJohn Marino /* Adjust DECL_VALUE_EXPR of the original var. */
1144*e4b17023SJohn Marino tree outer = outer_curly_brace_block (current_function_decl);
1145*e4b17023SJohn Marino tree var;
1146*e4b17023SJohn Marino
1147*e4b17023SJohn Marino if (outer)
1148*e4b17023SJohn Marino for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
1149*e4b17023SJohn Marino if (DECL_NAME (t) == DECL_NAME (var)
1150*e4b17023SJohn Marino && DECL_HAS_VALUE_EXPR_P (var)
1151*e4b17023SJohn Marino && DECL_VALUE_EXPR (var) == t)
1152*e4b17023SJohn Marino {
1153*e4b17023SJohn Marino tree val = convert_from_reference (t);
1154*e4b17023SJohn Marino SET_DECL_VALUE_EXPR (var, val);
1155*e4b17023SJohn Marino break;
1156*e4b17023SJohn Marino }
1157*e4b17023SJohn Marino }
1158*e4b17023SJohn Marino }
1159*e4b17023SJohn Marino
1160*e4b17023SJohn Marino /* If we're a clone, the body is already GIMPLE. */
1161*e4b17023SJohn Marino if (DECL_CLONED_FUNCTION_P (fndecl))
1162*e4b17023SJohn Marino return;
1163*e4b17023SJohn Marino
1164*e4b17023SJohn Marino /* We do want to see every occurrence of the parms, so we can't just use
1165*e4b17023SJohn Marino walk_tree's hash functionality. */
1166*e4b17023SJohn Marino wtd.p_set = pointer_set_create ();
1167*e4b17023SJohn Marino wtd.bind_expr_stack = NULL;
1168*e4b17023SJohn Marino wtd.omp_ctx = NULL;
1169*e4b17023SJohn Marino cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, &wtd, NULL);
1170*e4b17023SJohn Marino pointer_set_destroy (wtd.p_set);
1171*e4b17023SJohn Marino VEC_free (tree, heap, wtd.bind_expr_stack);
1172*e4b17023SJohn Marino
1173*e4b17023SJohn Marino /* Do everything else. */
1174*e4b17023SJohn Marino c_genericize (fndecl);
1175*e4b17023SJohn Marino
1176*e4b17023SJohn Marino gcc_assert (bc_label[bc_break] == NULL);
1177*e4b17023SJohn Marino gcc_assert (bc_label[bc_continue] == NULL);
1178*e4b17023SJohn Marino }
1179*e4b17023SJohn Marino
1180*e4b17023SJohn Marino /* Build code to apply FN to each member of ARG1 and ARG2. FN may be
1181*e4b17023SJohn Marino NULL if there is in fact nothing to do. ARG2 may be null if FN
1182*e4b17023SJohn Marino actually only takes one argument. */
1183*e4b17023SJohn Marino
1184*e4b17023SJohn Marino static tree
cxx_omp_clause_apply_fn(tree fn,tree arg1,tree arg2)1185*e4b17023SJohn Marino cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
1186*e4b17023SJohn Marino {
1187*e4b17023SJohn Marino tree defparm, parm, t;
1188*e4b17023SJohn Marino int i = 0;
1189*e4b17023SJohn Marino int nargs;
1190*e4b17023SJohn Marino tree *argarray;
1191*e4b17023SJohn Marino
1192*e4b17023SJohn Marino if (fn == NULL)
1193*e4b17023SJohn Marino return NULL;
1194*e4b17023SJohn Marino
1195*e4b17023SJohn Marino nargs = list_length (DECL_ARGUMENTS (fn));
1196*e4b17023SJohn Marino argarray = XALLOCAVEC (tree, nargs);
1197*e4b17023SJohn Marino
1198*e4b17023SJohn Marino defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
1199*e4b17023SJohn Marino if (arg2)
1200*e4b17023SJohn Marino defparm = TREE_CHAIN (defparm);
1201*e4b17023SJohn Marino
1202*e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
1203*e4b17023SJohn Marino {
1204*e4b17023SJohn Marino tree inner_type = TREE_TYPE (arg1);
1205*e4b17023SJohn Marino tree start1, end1, p1;
1206*e4b17023SJohn Marino tree start2 = NULL, p2 = NULL;
1207*e4b17023SJohn Marino tree ret = NULL, lab;
1208*e4b17023SJohn Marino
1209*e4b17023SJohn Marino start1 = arg1;
1210*e4b17023SJohn Marino start2 = arg2;
1211*e4b17023SJohn Marino do
1212*e4b17023SJohn Marino {
1213*e4b17023SJohn Marino inner_type = TREE_TYPE (inner_type);
1214*e4b17023SJohn Marino start1 = build4 (ARRAY_REF, inner_type, start1,
1215*e4b17023SJohn Marino size_zero_node, NULL, NULL);
1216*e4b17023SJohn Marino if (arg2)
1217*e4b17023SJohn Marino start2 = build4 (ARRAY_REF, inner_type, start2,
1218*e4b17023SJohn Marino size_zero_node, NULL, NULL);
1219*e4b17023SJohn Marino }
1220*e4b17023SJohn Marino while (TREE_CODE (inner_type) == ARRAY_TYPE);
1221*e4b17023SJohn Marino start1 = build_fold_addr_expr_loc (input_location, start1);
1222*e4b17023SJohn Marino if (arg2)
1223*e4b17023SJohn Marino start2 = build_fold_addr_expr_loc (input_location, start2);
1224*e4b17023SJohn Marino
1225*e4b17023SJohn Marino end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
1226*e4b17023SJohn Marino end1 = fold_build_pointer_plus (start1, end1);
1227*e4b17023SJohn Marino
1228*e4b17023SJohn Marino p1 = create_tmp_var (TREE_TYPE (start1), NULL);
1229*e4b17023SJohn Marino t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, start1);
1230*e4b17023SJohn Marino append_to_statement_list (t, &ret);
1231*e4b17023SJohn Marino
1232*e4b17023SJohn Marino if (arg2)
1233*e4b17023SJohn Marino {
1234*e4b17023SJohn Marino p2 = create_tmp_var (TREE_TYPE (start2), NULL);
1235*e4b17023SJohn Marino t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, start2);
1236*e4b17023SJohn Marino append_to_statement_list (t, &ret);
1237*e4b17023SJohn Marino }
1238*e4b17023SJohn Marino
1239*e4b17023SJohn Marino lab = create_artificial_label (input_location);
1240*e4b17023SJohn Marino t = build1 (LABEL_EXPR, void_type_node, lab);
1241*e4b17023SJohn Marino append_to_statement_list (t, &ret);
1242*e4b17023SJohn Marino
1243*e4b17023SJohn Marino argarray[i++] = p1;
1244*e4b17023SJohn Marino if (arg2)
1245*e4b17023SJohn Marino argarray[i++] = p2;
1246*e4b17023SJohn Marino /* Handle default arguments. */
1247*e4b17023SJohn Marino for (parm = defparm; parm && parm != void_list_node;
1248*e4b17023SJohn Marino parm = TREE_CHAIN (parm), i++)
1249*e4b17023SJohn Marino argarray[i] = convert_default_arg (TREE_VALUE (parm),
1250*e4b17023SJohn Marino TREE_PURPOSE (parm), fn, i);
1251*e4b17023SJohn Marino t = build_call_a (fn, i, argarray);
1252*e4b17023SJohn Marino t = fold_convert (void_type_node, t);
1253*e4b17023SJohn Marino t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
1254*e4b17023SJohn Marino append_to_statement_list (t, &ret);
1255*e4b17023SJohn Marino
1256*e4b17023SJohn Marino t = fold_build_pointer_plus (p1, TYPE_SIZE_UNIT (inner_type));
1257*e4b17023SJohn Marino t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, t);
1258*e4b17023SJohn Marino append_to_statement_list (t, &ret);
1259*e4b17023SJohn Marino
1260*e4b17023SJohn Marino if (arg2)
1261*e4b17023SJohn Marino {
1262*e4b17023SJohn Marino t = fold_build_pointer_plus (p2, TYPE_SIZE_UNIT (inner_type));
1263*e4b17023SJohn Marino t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, t);
1264*e4b17023SJohn Marino append_to_statement_list (t, &ret);
1265*e4b17023SJohn Marino }
1266*e4b17023SJohn Marino
1267*e4b17023SJohn Marino t = build2 (NE_EXPR, boolean_type_node, p1, end1);
1268*e4b17023SJohn Marino t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
1269*e4b17023SJohn Marino append_to_statement_list (t, &ret);
1270*e4b17023SJohn Marino
1271*e4b17023SJohn Marino return ret;
1272*e4b17023SJohn Marino }
1273*e4b17023SJohn Marino else
1274*e4b17023SJohn Marino {
1275*e4b17023SJohn Marino argarray[i++] = build_fold_addr_expr_loc (input_location, arg1);
1276*e4b17023SJohn Marino if (arg2)
1277*e4b17023SJohn Marino argarray[i++] = build_fold_addr_expr_loc (input_location, arg2);
1278*e4b17023SJohn Marino /* Handle default arguments. */
1279*e4b17023SJohn Marino for (parm = defparm; parm && parm != void_list_node;
1280*e4b17023SJohn Marino parm = TREE_CHAIN (parm), i++)
1281*e4b17023SJohn Marino argarray[i] = convert_default_arg (TREE_VALUE (parm),
1282*e4b17023SJohn Marino TREE_PURPOSE (parm),
1283*e4b17023SJohn Marino fn, i);
1284*e4b17023SJohn Marino t = build_call_a (fn, i, argarray);
1285*e4b17023SJohn Marino t = fold_convert (void_type_node, t);
1286*e4b17023SJohn Marino return fold_build_cleanup_point_expr (TREE_TYPE (t), t);
1287*e4b17023SJohn Marino }
1288*e4b17023SJohn Marino }
1289*e4b17023SJohn Marino
1290*e4b17023SJohn Marino /* Return code to initialize DECL with its default constructor, or
1291*e4b17023SJohn Marino NULL if there's nothing to do. */
1292*e4b17023SJohn Marino
1293*e4b17023SJohn Marino tree
cxx_omp_clause_default_ctor(tree clause,tree decl,tree outer ATTRIBUTE_UNUSED)1294*e4b17023SJohn Marino cxx_omp_clause_default_ctor (tree clause, tree decl,
1295*e4b17023SJohn Marino tree outer ATTRIBUTE_UNUSED)
1296*e4b17023SJohn Marino {
1297*e4b17023SJohn Marino tree info = CP_OMP_CLAUSE_INFO (clause);
1298*e4b17023SJohn Marino tree ret = NULL;
1299*e4b17023SJohn Marino
1300*e4b17023SJohn Marino if (info)
1301*e4b17023SJohn Marino ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
1302*e4b17023SJohn Marino
1303*e4b17023SJohn Marino return ret;
1304*e4b17023SJohn Marino }
1305*e4b17023SJohn Marino
1306*e4b17023SJohn Marino /* Return code to initialize DST with a copy constructor from SRC. */
1307*e4b17023SJohn Marino
1308*e4b17023SJohn Marino tree
cxx_omp_clause_copy_ctor(tree clause,tree dst,tree src)1309*e4b17023SJohn Marino cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
1310*e4b17023SJohn Marino {
1311*e4b17023SJohn Marino tree info = CP_OMP_CLAUSE_INFO (clause);
1312*e4b17023SJohn Marino tree ret = NULL;
1313*e4b17023SJohn Marino
1314*e4b17023SJohn Marino if (info)
1315*e4b17023SJohn Marino ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
1316*e4b17023SJohn Marino if (ret == NULL)
1317*e4b17023SJohn Marino ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
1318*e4b17023SJohn Marino
1319*e4b17023SJohn Marino return ret;
1320*e4b17023SJohn Marino }
1321*e4b17023SJohn Marino
1322*e4b17023SJohn Marino /* Similarly, except use an assignment operator instead. */
1323*e4b17023SJohn Marino
1324*e4b17023SJohn Marino tree
cxx_omp_clause_assign_op(tree clause,tree dst,tree src)1325*e4b17023SJohn Marino cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
1326*e4b17023SJohn Marino {
1327*e4b17023SJohn Marino tree info = CP_OMP_CLAUSE_INFO (clause);
1328*e4b17023SJohn Marino tree ret = NULL;
1329*e4b17023SJohn Marino
1330*e4b17023SJohn Marino if (info)
1331*e4b17023SJohn Marino ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
1332*e4b17023SJohn Marino if (ret == NULL)
1333*e4b17023SJohn Marino ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
1334*e4b17023SJohn Marino
1335*e4b17023SJohn Marino return ret;
1336*e4b17023SJohn Marino }
1337*e4b17023SJohn Marino
1338*e4b17023SJohn Marino /* Return code to destroy DECL. */
1339*e4b17023SJohn Marino
1340*e4b17023SJohn Marino tree
cxx_omp_clause_dtor(tree clause,tree decl)1341*e4b17023SJohn Marino cxx_omp_clause_dtor (tree clause, tree decl)
1342*e4b17023SJohn Marino {
1343*e4b17023SJohn Marino tree info = CP_OMP_CLAUSE_INFO (clause);
1344*e4b17023SJohn Marino tree ret = NULL;
1345*e4b17023SJohn Marino
1346*e4b17023SJohn Marino if (info)
1347*e4b17023SJohn Marino ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
1348*e4b17023SJohn Marino
1349*e4b17023SJohn Marino return ret;
1350*e4b17023SJohn Marino }
1351*e4b17023SJohn Marino
1352*e4b17023SJohn Marino /* True if OpenMP should privatize what this DECL points to rather
1353*e4b17023SJohn Marino than the DECL itself. */
1354*e4b17023SJohn Marino
1355*e4b17023SJohn Marino bool
cxx_omp_privatize_by_reference(const_tree decl)1356*e4b17023SJohn Marino cxx_omp_privatize_by_reference (const_tree decl)
1357*e4b17023SJohn Marino {
1358*e4b17023SJohn Marino return is_invisiref_parm (decl);
1359*e4b17023SJohn Marino }
1360*e4b17023SJohn Marino
1361*e4b17023SJohn Marino /* Return true if DECL is const qualified var having no mutable member. */
1362*e4b17023SJohn Marino bool
cxx_omp_const_qual_no_mutable(tree decl)1363*e4b17023SJohn Marino cxx_omp_const_qual_no_mutable (tree decl)
1364*e4b17023SJohn Marino {
1365*e4b17023SJohn Marino tree type = TREE_TYPE (decl);
1366*e4b17023SJohn Marino if (TREE_CODE (type) == REFERENCE_TYPE)
1367*e4b17023SJohn Marino {
1368*e4b17023SJohn Marino if (!is_invisiref_parm (decl))
1369*e4b17023SJohn Marino return false;
1370*e4b17023SJohn Marino type = TREE_TYPE (type);
1371*e4b17023SJohn Marino
1372*e4b17023SJohn Marino if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl))
1373*e4b17023SJohn Marino {
1374*e4b17023SJohn Marino /* NVR doesn't preserve const qualification of the
1375*e4b17023SJohn Marino variable's type. */
1376*e4b17023SJohn Marino tree outer = outer_curly_brace_block (current_function_decl);
1377*e4b17023SJohn Marino tree var;
1378*e4b17023SJohn Marino
1379*e4b17023SJohn Marino if (outer)
1380*e4b17023SJohn Marino for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
1381*e4b17023SJohn Marino if (DECL_NAME (decl) == DECL_NAME (var)
1382*e4b17023SJohn Marino && (TYPE_MAIN_VARIANT (type)
1383*e4b17023SJohn Marino == TYPE_MAIN_VARIANT (TREE_TYPE (var))))
1384*e4b17023SJohn Marino {
1385*e4b17023SJohn Marino if (TYPE_READONLY (TREE_TYPE (var)))
1386*e4b17023SJohn Marino type = TREE_TYPE (var);
1387*e4b17023SJohn Marino break;
1388*e4b17023SJohn Marino }
1389*e4b17023SJohn Marino }
1390*e4b17023SJohn Marino }
1391*e4b17023SJohn Marino
1392*e4b17023SJohn Marino if (type == error_mark_node)
1393*e4b17023SJohn Marino return false;
1394*e4b17023SJohn Marino
1395*e4b17023SJohn Marino /* Variables with const-qualified type having no mutable member
1396*e4b17023SJohn Marino are predetermined shared. */
1397*e4b17023SJohn Marino if (TYPE_READONLY (type) && !cp_has_mutable_p (type))
1398*e4b17023SJohn Marino return true;
1399*e4b17023SJohn Marino
1400*e4b17023SJohn Marino return false;
1401*e4b17023SJohn Marino }
1402*e4b17023SJohn Marino
1403*e4b17023SJohn Marino /* True if OpenMP sharing attribute of DECL is predetermined. */
1404*e4b17023SJohn Marino
1405*e4b17023SJohn Marino enum omp_clause_default_kind
cxx_omp_predetermined_sharing(tree decl)1406*e4b17023SJohn Marino cxx_omp_predetermined_sharing (tree decl)
1407*e4b17023SJohn Marino {
1408*e4b17023SJohn Marino /* Static data members are predetermined shared. */
1409*e4b17023SJohn Marino if (TREE_STATIC (decl))
1410*e4b17023SJohn Marino {
1411*e4b17023SJohn Marino tree ctx = CP_DECL_CONTEXT (decl);
1412*e4b17023SJohn Marino if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
1413*e4b17023SJohn Marino return OMP_CLAUSE_DEFAULT_SHARED;
1414*e4b17023SJohn Marino }
1415*e4b17023SJohn Marino
1416*e4b17023SJohn Marino /* Const qualified vars having no mutable member are predetermined
1417*e4b17023SJohn Marino shared. */
1418*e4b17023SJohn Marino if (cxx_omp_const_qual_no_mutable (decl))
1419*e4b17023SJohn Marino return OMP_CLAUSE_DEFAULT_SHARED;
1420*e4b17023SJohn Marino
1421*e4b17023SJohn Marino return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
1422*e4b17023SJohn Marino }
1423*e4b17023SJohn Marino
1424*e4b17023SJohn Marino /* Finalize an implicitly determined clause. */
1425*e4b17023SJohn Marino
1426*e4b17023SJohn Marino void
cxx_omp_finish_clause(tree c)1427*e4b17023SJohn Marino cxx_omp_finish_clause (tree c)
1428*e4b17023SJohn Marino {
1429*e4b17023SJohn Marino tree decl, inner_type;
1430*e4b17023SJohn Marino bool make_shared = false;
1431*e4b17023SJohn Marino
1432*e4b17023SJohn Marino if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
1433*e4b17023SJohn Marino return;
1434*e4b17023SJohn Marino
1435*e4b17023SJohn Marino decl = OMP_CLAUSE_DECL (c);
1436*e4b17023SJohn Marino decl = require_complete_type (decl);
1437*e4b17023SJohn Marino inner_type = TREE_TYPE (decl);
1438*e4b17023SJohn Marino if (decl == error_mark_node)
1439*e4b17023SJohn Marino make_shared = true;
1440*e4b17023SJohn Marino else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
1441*e4b17023SJohn Marino {
1442*e4b17023SJohn Marino if (is_invisiref_parm (decl))
1443*e4b17023SJohn Marino inner_type = TREE_TYPE (inner_type);
1444*e4b17023SJohn Marino else
1445*e4b17023SJohn Marino {
1446*e4b17023SJohn Marino error ("%qE implicitly determined as %<firstprivate%> has reference type",
1447*e4b17023SJohn Marino decl);
1448*e4b17023SJohn Marino make_shared = true;
1449*e4b17023SJohn Marino }
1450*e4b17023SJohn Marino }
1451*e4b17023SJohn Marino
1452*e4b17023SJohn Marino /* We're interested in the base element, not arrays. */
1453*e4b17023SJohn Marino while (TREE_CODE (inner_type) == ARRAY_TYPE)
1454*e4b17023SJohn Marino inner_type = TREE_TYPE (inner_type);
1455*e4b17023SJohn Marino
1456*e4b17023SJohn Marino /* Check for special function availability by building a call to one.
1457*e4b17023SJohn Marino Save the results, because later we won't be in the right context
1458*e4b17023SJohn Marino for making these queries. */
1459*e4b17023SJohn Marino if (!make_shared
1460*e4b17023SJohn Marino && CLASS_TYPE_P (inner_type)
1461*e4b17023SJohn Marino && cxx_omp_create_clause_info (c, inner_type, false, true, false))
1462*e4b17023SJohn Marino make_shared = true;
1463*e4b17023SJohn Marino
1464*e4b17023SJohn Marino if (make_shared)
1465*e4b17023SJohn Marino OMP_CLAUSE_CODE (c) = OMP_CLAUSE_SHARED;
1466*e4b17023SJohn Marino }
1467