1*404b540aSrobert /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
2*404b540aSrobert
3*404b540aSrobert Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
4*404b540aSrobert Contributed by Jason Merrill <jason@redhat.com>
5*404b540aSrobert
6*404b540aSrobert This file is part of GCC.
7*404b540aSrobert
8*404b540aSrobert GCC is free software; you can redistribute it and/or modify it under
9*404b540aSrobert the terms of the GNU General Public License as published by the Free
10*404b540aSrobert Software Foundation; either version 2, or (at your option) any later
11*404b540aSrobert version.
12*404b540aSrobert
13*404b540aSrobert GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*404b540aSrobert WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*404b540aSrobert FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16*404b540aSrobert for more details.
17*404b540aSrobert
18*404b540aSrobert You should have received a copy of the GNU General Public License
19*404b540aSrobert along with GCC; see the file COPYING. If not, write to the Free
20*404b540aSrobert Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21*404b540aSrobert 02110-1301, USA. */
22*404b540aSrobert
23*404b540aSrobert #include "config.h"
24*404b540aSrobert #include "system.h"
25*404b540aSrobert #include "coretypes.h"
26*404b540aSrobert #include "tm.h"
27*404b540aSrobert #include "tree.h"
28*404b540aSrobert #include "cp-tree.h"
29*404b540aSrobert #include "c-common.h"
30*404b540aSrobert #include "toplev.h"
31*404b540aSrobert #include "tree-gimple.h"
32*404b540aSrobert #include "hashtab.h"
33*404b540aSrobert #include "pointer-set.h"
34*404b540aSrobert #include "flags.h"
35*404b540aSrobert
36*404b540aSrobert /* Local declarations. */
37*404b540aSrobert
38*404b540aSrobert enum bc_t { bc_break = 0, bc_continue = 1 };
39*404b540aSrobert
40*404b540aSrobert /* Stack of labels which are targets for "break" or "continue",
41*404b540aSrobert linked through TREE_CHAIN. */
42*404b540aSrobert static tree bc_label[2];
43*404b540aSrobert
44*404b540aSrobert /* Begin a scope which can be exited by a break or continue statement. BC
45*404b540aSrobert indicates which.
46*404b540aSrobert
47*404b540aSrobert Just creates a label and pushes it into the current context. */
48*404b540aSrobert
49*404b540aSrobert static tree
begin_bc_block(enum bc_t bc)50*404b540aSrobert begin_bc_block (enum bc_t bc)
51*404b540aSrobert {
52*404b540aSrobert tree label = create_artificial_label ();
53*404b540aSrobert TREE_CHAIN (label) = bc_label[bc];
54*404b540aSrobert bc_label[bc] = label;
55*404b540aSrobert return label;
56*404b540aSrobert }
57*404b540aSrobert
58*404b540aSrobert /* Finish a scope which can be exited by a break or continue statement.
59*404b540aSrobert LABEL was returned from the most recent call to begin_bc_block. BODY is
60*404b540aSrobert an expression for the contents of the scope.
61*404b540aSrobert
62*404b540aSrobert If we saw a break (or continue) in the scope, append a LABEL_EXPR to
63*404b540aSrobert body. Otherwise, just forget the label. */
64*404b540aSrobert
65*404b540aSrobert static tree
finish_bc_block(enum bc_t bc,tree label,tree body)66*404b540aSrobert finish_bc_block (enum bc_t bc, tree label, tree body)
67*404b540aSrobert {
68*404b540aSrobert gcc_assert (label == bc_label[bc]);
69*404b540aSrobert
70*404b540aSrobert if (TREE_USED (label))
71*404b540aSrobert {
72*404b540aSrobert tree t, sl = NULL;
73*404b540aSrobert
74*404b540aSrobert t = build1 (LABEL_EXPR, void_type_node, label);
75*404b540aSrobert
76*404b540aSrobert append_to_statement_list (body, &sl);
77*404b540aSrobert append_to_statement_list (t, &sl);
78*404b540aSrobert body = sl;
79*404b540aSrobert }
80*404b540aSrobert
81*404b540aSrobert bc_label[bc] = TREE_CHAIN (label);
82*404b540aSrobert TREE_CHAIN (label) = NULL_TREE;
83*404b540aSrobert return body;
84*404b540aSrobert }
85*404b540aSrobert
86*404b540aSrobert /* Build a GOTO_EXPR to represent a break or continue statement. BC
87*404b540aSrobert indicates which. */
88*404b540aSrobert
89*404b540aSrobert static tree
build_bc_goto(enum bc_t bc)90*404b540aSrobert build_bc_goto (enum bc_t bc)
91*404b540aSrobert {
92*404b540aSrobert tree label = bc_label[bc];
93*404b540aSrobert
94*404b540aSrobert if (label == NULL_TREE)
95*404b540aSrobert {
96*404b540aSrobert if (bc == bc_break)
97*404b540aSrobert error ("break statement not within loop or switch");
98*404b540aSrobert else
99*404b540aSrobert error ("continue statement not within loop or switch");
100*404b540aSrobert
101*404b540aSrobert return NULL_TREE;
102*404b540aSrobert }
103*404b540aSrobert
104*404b540aSrobert /* Mark the label used for finish_bc_block. */
105*404b540aSrobert TREE_USED (label) = 1;
106*404b540aSrobert return build1 (GOTO_EXPR, void_type_node, label);
107*404b540aSrobert }
108*404b540aSrobert
109*404b540aSrobert /* Genericize a TRY_BLOCK. */
110*404b540aSrobert
111*404b540aSrobert static void
genericize_try_block(tree * stmt_p)112*404b540aSrobert genericize_try_block (tree *stmt_p)
113*404b540aSrobert {
114*404b540aSrobert tree body = TRY_STMTS (*stmt_p);
115*404b540aSrobert tree cleanup = TRY_HANDLERS (*stmt_p);
116*404b540aSrobert
117*404b540aSrobert gimplify_stmt (&body);
118*404b540aSrobert
119*404b540aSrobert if (CLEANUP_P (*stmt_p))
120*404b540aSrobert /* A cleanup is an expression, so it doesn't need to be genericized. */;
121*404b540aSrobert else
122*404b540aSrobert gimplify_stmt (&cleanup);
123*404b540aSrobert
124*404b540aSrobert *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
125*404b540aSrobert }
126*404b540aSrobert
127*404b540aSrobert /* Genericize a HANDLER by converting to a CATCH_EXPR. */
128*404b540aSrobert
129*404b540aSrobert static void
genericize_catch_block(tree * stmt_p)130*404b540aSrobert genericize_catch_block (tree *stmt_p)
131*404b540aSrobert {
132*404b540aSrobert tree type = HANDLER_TYPE (*stmt_p);
133*404b540aSrobert tree body = HANDLER_BODY (*stmt_p);
134*404b540aSrobert
135*404b540aSrobert gimplify_stmt (&body);
136*404b540aSrobert
137*404b540aSrobert /* FIXME should the caught type go in TREE_TYPE? */
138*404b540aSrobert *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
139*404b540aSrobert }
140*404b540aSrobert
141*404b540aSrobert /* Genericize an EH_SPEC_BLOCK by converting it to a
142*404b540aSrobert TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
143*404b540aSrobert
144*404b540aSrobert static void
genericize_eh_spec_block(tree * stmt_p)145*404b540aSrobert genericize_eh_spec_block (tree *stmt_p)
146*404b540aSrobert {
147*404b540aSrobert tree body = EH_SPEC_STMTS (*stmt_p);
148*404b540aSrobert tree allowed = EH_SPEC_RAISES (*stmt_p);
149*404b540aSrobert tree failure = build_call (call_unexpected_node,
150*404b540aSrobert tree_cons (NULL_TREE, build_exc_ptr (),
151*404b540aSrobert NULL_TREE));
152*404b540aSrobert gimplify_stmt (&body);
153*404b540aSrobert
154*404b540aSrobert *stmt_p = gimple_build_eh_filter (body, allowed, failure);
155*404b540aSrobert }
156*404b540aSrobert
157*404b540aSrobert /* Genericize an IF_STMT by turning it into a COND_EXPR. */
158*404b540aSrobert
159*404b540aSrobert static void
gimplify_if_stmt(tree * stmt_p)160*404b540aSrobert gimplify_if_stmt (tree *stmt_p)
161*404b540aSrobert {
162*404b540aSrobert tree stmt, cond, then_, else_;
163*404b540aSrobert
164*404b540aSrobert stmt = *stmt_p;
165*404b540aSrobert cond = IF_COND (stmt);
166*404b540aSrobert then_ = THEN_CLAUSE (stmt);
167*404b540aSrobert else_ = ELSE_CLAUSE (stmt);
168*404b540aSrobert
169*404b540aSrobert if (!then_)
170*404b540aSrobert then_ = build_empty_stmt ();
171*404b540aSrobert if (!else_)
172*404b540aSrobert else_ = build_empty_stmt ();
173*404b540aSrobert
174*404b540aSrobert if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
175*404b540aSrobert stmt = then_;
176*404b540aSrobert else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
177*404b540aSrobert stmt = else_;
178*404b540aSrobert else
179*404b540aSrobert stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
180*404b540aSrobert *stmt_p = stmt;
181*404b540aSrobert }
182*404b540aSrobert
183*404b540aSrobert /* Build a generic representation of one of the C loop forms. COND is the
184*404b540aSrobert loop condition or NULL_TREE. BODY is the (possibly compound) statement
185*404b540aSrobert controlled by the loop. INCR is the increment expression of a for-loop,
186*404b540aSrobert or NULL_TREE. COND_IS_FIRST indicates whether the condition is
187*404b540aSrobert evaluated before the loop body as in while and for loops, or after the
188*404b540aSrobert loop body as in do-while loops. */
189*404b540aSrobert
190*404b540aSrobert static tree
gimplify_cp_loop(tree cond,tree body,tree incr,bool cond_is_first)191*404b540aSrobert gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
192*404b540aSrobert {
193*404b540aSrobert tree top, entry, exit, cont_block, break_block, stmt_list, t;
194*404b540aSrobert location_t stmt_locus;
195*404b540aSrobert
196*404b540aSrobert stmt_locus = input_location;
197*404b540aSrobert stmt_list = NULL_TREE;
198*404b540aSrobert entry = NULL_TREE;
199*404b540aSrobert
200*404b540aSrobert break_block = begin_bc_block (bc_break);
201*404b540aSrobert cont_block = begin_bc_block (bc_continue);
202*404b540aSrobert
203*404b540aSrobert /* If condition is zero don't generate a loop construct. */
204*404b540aSrobert if (cond && integer_zerop (cond))
205*404b540aSrobert {
206*404b540aSrobert top = NULL_TREE;
207*404b540aSrobert exit = NULL_TREE;
208*404b540aSrobert if (cond_is_first)
209*404b540aSrobert {
210*404b540aSrobert t = build_bc_goto (bc_break);
211*404b540aSrobert append_to_statement_list (t, &stmt_list);
212*404b540aSrobert }
213*404b540aSrobert }
214*404b540aSrobert else
215*404b540aSrobert {
216*404b540aSrobert /* If we use a LOOP_EXPR here, we have to feed the whole thing
217*404b540aSrobert back through the main gimplifier to lower it. Given that we
218*404b540aSrobert have to gimplify the loop body NOW so that we can resolve
219*404b540aSrobert break/continue stmts, seems easier to just expand to gotos. */
220*404b540aSrobert top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
221*404b540aSrobert
222*404b540aSrobert /* If we have an exit condition, then we build an IF with gotos either
223*404b540aSrobert out of the loop, or to the top of it. If there's no exit condition,
224*404b540aSrobert then we just build a jump back to the top. */
225*404b540aSrobert exit = build_and_jump (&LABEL_EXPR_LABEL (top));
226*404b540aSrobert if (cond && !integer_nonzerop (cond))
227*404b540aSrobert {
228*404b540aSrobert t = build_bc_goto (bc_break);
229*404b540aSrobert exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
230*404b540aSrobert gimplify_stmt (&exit);
231*404b540aSrobert
232*404b540aSrobert if (cond_is_first)
233*404b540aSrobert {
234*404b540aSrobert if (incr)
235*404b540aSrobert {
236*404b540aSrobert entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
237*404b540aSrobert t = build_and_jump (&LABEL_EXPR_LABEL (entry));
238*404b540aSrobert }
239*404b540aSrobert else
240*404b540aSrobert t = build_bc_goto (bc_continue);
241*404b540aSrobert append_to_statement_list (t, &stmt_list);
242*404b540aSrobert }
243*404b540aSrobert }
244*404b540aSrobert }
245*404b540aSrobert
246*404b540aSrobert gimplify_stmt (&body);
247*404b540aSrobert gimplify_stmt (&incr);
248*404b540aSrobert
249*404b540aSrobert body = finish_bc_block (bc_continue, cont_block, body);
250*404b540aSrobert
251*404b540aSrobert append_to_statement_list (top, &stmt_list);
252*404b540aSrobert append_to_statement_list (body, &stmt_list);
253*404b540aSrobert append_to_statement_list (incr, &stmt_list);
254*404b540aSrobert append_to_statement_list (entry, &stmt_list);
255*404b540aSrobert append_to_statement_list (exit, &stmt_list);
256*404b540aSrobert
257*404b540aSrobert annotate_all_with_locus (&stmt_list, stmt_locus);
258*404b540aSrobert
259*404b540aSrobert return finish_bc_block (bc_break, break_block, stmt_list);
260*404b540aSrobert }
261*404b540aSrobert
262*404b540aSrobert /* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the
263*404b540aSrobert prequeue and hand off to gimplify_cp_loop. */
264*404b540aSrobert
265*404b540aSrobert static void
gimplify_for_stmt(tree * stmt_p,tree * pre_p)266*404b540aSrobert gimplify_for_stmt (tree *stmt_p, tree *pre_p)
267*404b540aSrobert {
268*404b540aSrobert tree stmt = *stmt_p;
269*404b540aSrobert
270*404b540aSrobert if (FOR_INIT_STMT (stmt))
271*404b540aSrobert gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
272*404b540aSrobert
273*404b540aSrobert *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
274*404b540aSrobert FOR_EXPR (stmt), 1);
275*404b540aSrobert }
276*404b540aSrobert
277*404b540aSrobert /* Gimplify a WHILE_STMT node. */
278*404b540aSrobert
279*404b540aSrobert static void
gimplify_while_stmt(tree * stmt_p)280*404b540aSrobert gimplify_while_stmt (tree *stmt_p)
281*404b540aSrobert {
282*404b540aSrobert tree stmt = *stmt_p;
283*404b540aSrobert *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
284*404b540aSrobert NULL_TREE, 1);
285*404b540aSrobert }
286*404b540aSrobert
287*404b540aSrobert /* Gimplify a DO_STMT node. */
288*404b540aSrobert
289*404b540aSrobert static void
gimplify_do_stmt(tree * stmt_p)290*404b540aSrobert gimplify_do_stmt (tree *stmt_p)
291*404b540aSrobert {
292*404b540aSrobert tree stmt = *stmt_p;
293*404b540aSrobert *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
294*404b540aSrobert NULL_TREE, 0);
295*404b540aSrobert }
296*404b540aSrobert
297*404b540aSrobert /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */
298*404b540aSrobert
299*404b540aSrobert static void
gimplify_switch_stmt(tree * stmt_p)300*404b540aSrobert gimplify_switch_stmt (tree *stmt_p)
301*404b540aSrobert {
302*404b540aSrobert tree stmt = *stmt_p;
303*404b540aSrobert tree break_block, body;
304*404b540aSrobert location_t stmt_locus = input_location;
305*404b540aSrobert
306*404b540aSrobert break_block = begin_bc_block (bc_break);
307*404b540aSrobert
308*404b540aSrobert body = SWITCH_STMT_BODY (stmt);
309*404b540aSrobert if (!body)
310*404b540aSrobert body = build_empty_stmt ();
311*404b540aSrobert
312*404b540aSrobert *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
313*404b540aSrobert SWITCH_STMT_COND (stmt), body, NULL_TREE);
314*404b540aSrobert SET_EXPR_LOCATION (*stmt_p, stmt_locus);
315*404b540aSrobert gimplify_stmt (stmt_p);
316*404b540aSrobert
317*404b540aSrobert *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p);
318*404b540aSrobert }
319*404b540aSrobert
320*404b540aSrobert /* Hook into the middle of gimplifying an OMP_FOR node. This is required
321*404b540aSrobert in order to properly gimplify CONTINUE statements. Here we merely
322*404b540aSrobert manage the continue stack; the rest of the job is performed by the
323*404b540aSrobert regular gimplifier. */
324*404b540aSrobert
325*404b540aSrobert static enum gimplify_status
cp_gimplify_omp_for(tree * expr_p)326*404b540aSrobert cp_gimplify_omp_for (tree *expr_p)
327*404b540aSrobert {
328*404b540aSrobert tree for_stmt = *expr_p;
329*404b540aSrobert tree cont_block;
330*404b540aSrobert
331*404b540aSrobert /* Protect ourselves from recursion. */
332*404b540aSrobert if (OMP_FOR_GIMPLIFYING_P (for_stmt))
333*404b540aSrobert return GS_UNHANDLED;
334*404b540aSrobert OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
335*404b540aSrobert
336*404b540aSrobert /* Note that while technically the continue label is enabled too soon
337*404b540aSrobert here, we should have already diagnosed invalid continues nested within
338*404b540aSrobert statement expressions within the INIT, COND, or INCR expressions. */
339*404b540aSrobert cont_block = begin_bc_block (bc_continue);
340*404b540aSrobert
341*404b540aSrobert gimplify_stmt (expr_p);
342*404b540aSrobert
343*404b540aSrobert OMP_FOR_BODY (for_stmt)
344*404b540aSrobert = finish_bc_block (bc_continue, cont_block, OMP_FOR_BODY (for_stmt));
345*404b540aSrobert OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
346*404b540aSrobert
347*404b540aSrobert return GS_ALL_DONE;
348*404b540aSrobert }
349*404b540aSrobert
350*404b540aSrobert /* Gimplify an EXPR_STMT node. */
351*404b540aSrobert
352*404b540aSrobert static void
gimplify_expr_stmt(tree * stmt_p)353*404b540aSrobert gimplify_expr_stmt (tree *stmt_p)
354*404b540aSrobert {
355*404b540aSrobert tree stmt = EXPR_STMT_EXPR (*stmt_p);
356*404b540aSrobert
357*404b540aSrobert if (stmt == error_mark_node)
358*404b540aSrobert stmt = NULL;
359*404b540aSrobert
360*404b540aSrobert /* Gimplification of a statement expression will nullify the
361*404b540aSrobert statement if all its side effects are moved to *PRE_P and *POST_P.
362*404b540aSrobert
363*404b540aSrobert In this case we will not want to emit the gimplified statement.
364*404b540aSrobert However, we may still want to emit a warning, so we do that before
365*404b540aSrobert gimplification. */
366*404b540aSrobert if (stmt && (extra_warnings || warn_unused_value))
367*404b540aSrobert {
368*404b540aSrobert if (!TREE_SIDE_EFFECTS (stmt))
369*404b540aSrobert {
370*404b540aSrobert if (!IS_EMPTY_STMT (stmt)
371*404b540aSrobert && !VOID_TYPE_P (TREE_TYPE (stmt))
372*404b540aSrobert && !TREE_NO_WARNING (stmt))
373*404b540aSrobert warning (OPT_Wextra, "statement with no effect");
374*404b540aSrobert }
375*404b540aSrobert else if (warn_unused_value)
376*404b540aSrobert warn_if_unused_value (stmt, input_location);
377*404b540aSrobert }
378*404b540aSrobert
379*404b540aSrobert if (stmt == NULL_TREE)
380*404b540aSrobert stmt = alloc_stmt_list ();
381*404b540aSrobert
382*404b540aSrobert *stmt_p = stmt;
383*404b540aSrobert }
384*404b540aSrobert
385*404b540aSrobert /* Gimplify initialization from an AGGR_INIT_EXPR. */
386*404b540aSrobert
387*404b540aSrobert static void
cp_gimplify_init_expr(tree * expr_p,tree * pre_p,tree * post_p)388*404b540aSrobert cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
389*404b540aSrobert {
390*404b540aSrobert tree from = TREE_OPERAND (*expr_p, 1);
391*404b540aSrobert tree to = TREE_OPERAND (*expr_p, 0);
392*404b540aSrobert tree sub;
393*404b540aSrobert
394*404b540aSrobert /* What about code that pulls out the temp and uses it elsewhere? I
395*404b540aSrobert think that such code never uses the TARGET_EXPR as an initializer. If
396*404b540aSrobert I'm wrong, we'll abort because the temp won't have any RTL. In that
397*404b540aSrobert case, I guess we'll need to replace references somehow. */
398*404b540aSrobert if (TREE_CODE (from) == TARGET_EXPR)
399*404b540aSrobert from = TARGET_EXPR_INITIAL (from);
400*404b540aSrobert
401*404b540aSrobert /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
402*404b540aSrobert inside the TARGET_EXPR. */
403*404b540aSrobert sub = expr_last (from);
404*404b540aSrobert
405*404b540aSrobert /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
406*404b540aSrobert replace the slot operand with our target.
407*404b540aSrobert
408*404b540aSrobert Should we add a target parm to gimplify_expr instead? No, as in this
409*404b540aSrobert case we want to replace the INIT_EXPR. */
410*404b540aSrobert if (TREE_CODE (sub) == AGGR_INIT_EXPR)
411*404b540aSrobert {
412*404b540aSrobert gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
413*404b540aSrobert TREE_OPERAND (sub, 2) = to;
414*404b540aSrobert *expr_p = from;
415*404b540aSrobert
416*404b540aSrobert /* The initialization is now a side-effect, so the container can
417*404b540aSrobert become void. */
418*404b540aSrobert if (from != sub)
419*404b540aSrobert TREE_TYPE (from) = void_type_node;
420*404b540aSrobert }
421*404b540aSrobert }
422*404b540aSrobert
423*404b540aSrobert /* Gimplify a MUST_NOT_THROW_EXPR. */
424*404b540aSrobert
425*404b540aSrobert static void
gimplify_must_not_throw_expr(tree * expr_p,tree * pre_p)426*404b540aSrobert gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
427*404b540aSrobert {
428*404b540aSrobert tree stmt = *expr_p;
429*404b540aSrobert tree temp = voidify_wrapper_expr (stmt, NULL);
430*404b540aSrobert tree body = TREE_OPERAND (stmt, 0);
431*404b540aSrobert
432*404b540aSrobert gimplify_stmt (&body);
433*404b540aSrobert
434*404b540aSrobert stmt = gimple_build_eh_filter (body, NULL_TREE,
435*404b540aSrobert build_call (terminate_node, NULL_TREE));
436*404b540aSrobert
437*404b540aSrobert if (temp)
438*404b540aSrobert {
439*404b540aSrobert append_to_statement_list (stmt, pre_p);
440*404b540aSrobert *expr_p = temp;
441*404b540aSrobert }
442*404b540aSrobert else
443*404b540aSrobert *expr_p = stmt;
444*404b540aSrobert }
445*404b540aSrobert
446*404b540aSrobert /* Do C++-specific gimplification. Args are as for gimplify_expr. */
447*404b540aSrobert
448*404b540aSrobert int
cp_gimplify_expr(tree * expr_p,tree * pre_p,tree * post_p)449*404b540aSrobert cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
450*404b540aSrobert {
451*404b540aSrobert int saved_stmts_are_full_exprs_p = 0;
452*404b540aSrobert enum tree_code code = TREE_CODE (*expr_p);
453*404b540aSrobert enum gimplify_status ret;
454*404b540aSrobert
455*404b540aSrobert if (STATEMENT_CODE_P (code))
456*404b540aSrobert {
457*404b540aSrobert saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
458*404b540aSrobert current_stmt_tree ()->stmts_are_full_exprs_p
459*404b540aSrobert = STMT_IS_FULL_EXPR_P (*expr_p);
460*404b540aSrobert }
461*404b540aSrobert
462*404b540aSrobert switch (code)
463*404b540aSrobert {
464*404b540aSrobert case PTRMEM_CST:
465*404b540aSrobert *expr_p = cplus_expand_constant (*expr_p);
466*404b540aSrobert ret = GS_OK;
467*404b540aSrobert break;
468*404b540aSrobert
469*404b540aSrobert case AGGR_INIT_EXPR:
470*404b540aSrobert simplify_aggr_init_expr (expr_p);
471*404b540aSrobert ret = GS_OK;
472*404b540aSrobert break;
473*404b540aSrobert
474*404b540aSrobert case THROW_EXPR:
475*404b540aSrobert /* FIXME communicate throw type to backend, probably by moving
476*404b540aSrobert THROW_EXPR into ../tree.def. */
477*404b540aSrobert *expr_p = TREE_OPERAND (*expr_p, 0);
478*404b540aSrobert ret = GS_OK;
479*404b540aSrobert break;
480*404b540aSrobert
481*404b540aSrobert case MUST_NOT_THROW_EXPR:
482*404b540aSrobert gimplify_must_not_throw_expr (expr_p, pre_p);
483*404b540aSrobert ret = GS_OK;
484*404b540aSrobert break;
485*404b540aSrobert
486*404b540aSrobert /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
487*404b540aSrobert LHS of an assignment might also be involved in the RHS, as in bug
488*404b540aSrobert 25979. */
489*404b540aSrobert case INIT_EXPR:
490*404b540aSrobert cp_gimplify_init_expr (expr_p, pre_p, post_p);
491*404b540aSrobert ret = GS_OK;
492*404b540aSrobert break;
493*404b540aSrobert
494*404b540aSrobert case EMPTY_CLASS_EXPR:
495*404b540aSrobert /* We create an empty CONSTRUCTOR with RECORD_TYPE. */
496*404b540aSrobert *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
497*404b540aSrobert ret = GS_OK;
498*404b540aSrobert break;
499*404b540aSrobert
500*404b540aSrobert case BASELINK:
501*404b540aSrobert *expr_p = BASELINK_FUNCTIONS (*expr_p);
502*404b540aSrobert ret = GS_OK;
503*404b540aSrobert break;
504*404b540aSrobert
505*404b540aSrobert case TRY_BLOCK:
506*404b540aSrobert genericize_try_block (expr_p);
507*404b540aSrobert ret = GS_OK;
508*404b540aSrobert break;
509*404b540aSrobert
510*404b540aSrobert case HANDLER:
511*404b540aSrobert genericize_catch_block (expr_p);
512*404b540aSrobert ret = GS_OK;
513*404b540aSrobert break;
514*404b540aSrobert
515*404b540aSrobert case EH_SPEC_BLOCK:
516*404b540aSrobert genericize_eh_spec_block (expr_p);
517*404b540aSrobert ret = GS_OK;
518*404b540aSrobert break;
519*404b540aSrobert
520*404b540aSrobert case USING_STMT:
521*404b540aSrobert /* Just ignore for now. Eventually we will want to pass this on to
522*404b540aSrobert the debugger. */
523*404b540aSrobert *expr_p = build_empty_stmt ();
524*404b540aSrobert ret = GS_ALL_DONE;
525*404b540aSrobert break;
526*404b540aSrobert
527*404b540aSrobert case IF_STMT:
528*404b540aSrobert gimplify_if_stmt (expr_p);
529*404b540aSrobert ret = GS_OK;
530*404b540aSrobert break;
531*404b540aSrobert
532*404b540aSrobert case FOR_STMT:
533*404b540aSrobert gimplify_for_stmt (expr_p, pre_p);
534*404b540aSrobert ret = GS_ALL_DONE;
535*404b540aSrobert break;
536*404b540aSrobert
537*404b540aSrobert case WHILE_STMT:
538*404b540aSrobert gimplify_while_stmt (expr_p);
539*404b540aSrobert ret = GS_ALL_DONE;
540*404b540aSrobert break;
541*404b540aSrobert
542*404b540aSrobert case DO_STMT:
543*404b540aSrobert gimplify_do_stmt (expr_p);
544*404b540aSrobert ret = GS_ALL_DONE;
545*404b540aSrobert break;
546*404b540aSrobert
547*404b540aSrobert case SWITCH_STMT:
548*404b540aSrobert gimplify_switch_stmt (expr_p);
549*404b540aSrobert ret = GS_ALL_DONE;
550*404b540aSrobert break;
551*404b540aSrobert
552*404b540aSrobert case OMP_FOR:
553*404b540aSrobert ret = cp_gimplify_omp_for (expr_p);
554*404b540aSrobert break;
555*404b540aSrobert
556*404b540aSrobert case CONTINUE_STMT:
557*404b540aSrobert *expr_p = build_bc_goto (bc_continue);
558*404b540aSrobert ret = GS_ALL_DONE;
559*404b540aSrobert break;
560*404b540aSrobert
561*404b540aSrobert case BREAK_STMT:
562*404b540aSrobert *expr_p = build_bc_goto (bc_break);
563*404b540aSrobert ret = GS_ALL_DONE;
564*404b540aSrobert break;
565*404b540aSrobert
566*404b540aSrobert case EXPR_STMT:
567*404b540aSrobert gimplify_expr_stmt (expr_p);
568*404b540aSrobert ret = GS_OK;
569*404b540aSrobert break;
570*404b540aSrobert
571*404b540aSrobert case UNARY_PLUS_EXPR:
572*404b540aSrobert {
573*404b540aSrobert tree arg = TREE_OPERAND (*expr_p, 0);
574*404b540aSrobert tree type = TREE_TYPE (*expr_p);
575*404b540aSrobert *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
576*404b540aSrobert : arg;
577*404b540aSrobert ret = GS_OK;
578*404b540aSrobert }
579*404b540aSrobert break;
580*404b540aSrobert
581*404b540aSrobert default:
582*404b540aSrobert ret = c_gimplify_expr (expr_p, pre_p, post_p);
583*404b540aSrobert break;
584*404b540aSrobert }
585*404b540aSrobert
586*404b540aSrobert /* Restore saved state. */
587*404b540aSrobert if (STATEMENT_CODE_P (code))
588*404b540aSrobert current_stmt_tree ()->stmts_are_full_exprs_p
589*404b540aSrobert = saved_stmts_are_full_exprs_p;
590*404b540aSrobert
591*404b540aSrobert return ret;
592*404b540aSrobert }
593*404b540aSrobert
594*404b540aSrobert static inline bool
is_invisiref_parm(tree t)595*404b540aSrobert is_invisiref_parm (tree t)
596*404b540aSrobert {
597*404b540aSrobert return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
598*404b540aSrobert && DECL_BY_REFERENCE (t));
599*404b540aSrobert }
600*404b540aSrobert
601*404b540aSrobert /* Return true if the uid in both int tree maps are equal. */
602*404b540aSrobert
603*404b540aSrobert int
cxx_int_tree_map_eq(const void * va,const void * vb)604*404b540aSrobert cxx_int_tree_map_eq (const void *va, const void *vb)
605*404b540aSrobert {
606*404b540aSrobert const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
607*404b540aSrobert const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
608*404b540aSrobert return (a->uid == b->uid);
609*404b540aSrobert }
610*404b540aSrobert
611*404b540aSrobert /* Hash a UID in a cxx_int_tree_map. */
612*404b540aSrobert
613*404b540aSrobert unsigned int
cxx_int_tree_map_hash(const void * item)614*404b540aSrobert cxx_int_tree_map_hash (const void *item)
615*404b540aSrobert {
616*404b540aSrobert return ((const struct cxx_int_tree_map *)item)->uid;
617*404b540aSrobert }
618*404b540aSrobert
619*404b540aSrobert /* Perform any pre-gimplification lowering of C++ front end trees to
620*404b540aSrobert GENERIC. */
621*404b540aSrobert
622*404b540aSrobert static tree
cp_genericize_r(tree * stmt_p,int * walk_subtrees,void * data)623*404b540aSrobert cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
624*404b540aSrobert {
625*404b540aSrobert tree stmt = *stmt_p;
626*404b540aSrobert struct pointer_set_t *p_set = (struct pointer_set_t*) data;
627*404b540aSrobert
628*404b540aSrobert if (is_invisiref_parm (stmt)
629*404b540aSrobert /* Don't dereference parms in a thunk, pass the references through. */
630*404b540aSrobert && !(DECL_THUNK_P (current_function_decl)
631*404b540aSrobert && TREE_CODE (stmt) == PARM_DECL))
632*404b540aSrobert {
633*404b540aSrobert *stmt_p = convert_from_reference (stmt);
634*404b540aSrobert *walk_subtrees = 0;
635*404b540aSrobert return NULL;
636*404b540aSrobert }
637*404b540aSrobert
638*404b540aSrobert /* Map block scope extern declarations to visible declarations with the
639*404b540aSrobert same name and type in outer scopes if any. */
640*404b540aSrobert if (cp_function_chain->extern_decl_map
641*404b540aSrobert && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
642*404b540aSrobert && DECL_EXTERNAL (stmt))
643*404b540aSrobert {
644*404b540aSrobert struct cxx_int_tree_map *h, in;
645*404b540aSrobert in.uid = DECL_UID (stmt);
646*404b540aSrobert h = (struct cxx_int_tree_map *)
647*404b540aSrobert htab_find_with_hash (cp_function_chain->extern_decl_map,
648*404b540aSrobert &in, in.uid);
649*404b540aSrobert if (h)
650*404b540aSrobert {
651*404b540aSrobert *stmt_p = h->to;
652*404b540aSrobert *walk_subtrees = 0;
653*404b540aSrobert return NULL;
654*404b540aSrobert }
655*404b540aSrobert }
656*404b540aSrobert
657*404b540aSrobert /* Other than invisiref parms, don't walk the same tree twice. */
658*404b540aSrobert if (pointer_set_contains (p_set, stmt))
659*404b540aSrobert {
660*404b540aSrobert *walk_subtrees = 0;
661*404b540aSrobert return NULL_TREE;
662*404b540aSrobert }
663*404b540aSrobert
664*404b540aSrobert if (TREE_CODE (stmt) == ADDR_EXPR
665*404b540aSrobert && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
666*404b540aSrobert {
667*404b540aSrobert *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
668*404b540aSrobert *walk_subtrees = 0;
669*404b540aSrobert }
670*404b540aSrobert else if (TREE_CODE (stmt) == RETURN_EXPR
671*404b540aSrobert && TREE_OPERAND (stmt, 0)
672*404b540aSrobert && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
673*404b540aSrobert /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */
674*404b540aSrobert *walk_subtrees = 0;
675*404b540aSrobert else if (TREE_CODE (stmt) == OMP_CLAUSE)
676*404b540aSrobert switch (OMP_CLAUSE_CODE (stmt))
677*404b540aSrobert {
678*404b540aSrobert case OMP_CLAUSE_PRIVATE:
679*404b540aSrobert case OMP_CLAUSE_SHARED:
680*404b540aSrobert case OMP_CLAUSE_FIRSTPRIVATE:
681*404b540aSrobert case OMP_CLAUSE_LASTPRIVATE:
682*404b540aSrobert case OMP_CLAUSE_COPYIN:
683*404b540aSrobert case OMP_CLAUSE_COPYPRIVATE:
684*404b540aSrobert /* Don't dereference an invisiref in OpenMP clauses. */
685*404b540aSrobert if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
686*404b540aSrobert *walk_subtrees = 0;
687*404b540aSrobert break;
688*404b540aSrobert case OMP_CLAUSE_REDUCTION:
689*404b540aSrobert gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
690*404b540aSrobert break;
691*404b540aSrobert default:
692*404b540aSrobert break;
693*404b540aSrobert }
694*404b540aSrobert else if (IS_TYPE_OR_DECL_P (stmt))
695*404b540aSrobert *walk_subtrees = 0;
696*404b540aSrobert
697*404b540aSrobert /* Due to the way voidify_wrapper_expr is written, we don't get a chance
698*404b540aSrobert to lower this construct before scanning it, so we need to lower these
699*404b540aSrobert before doing anything else. */
700*404b540aSrobert else if (TREE_CODE (stmt) == CLEANUP_STMT)
701*404b540aSrobert *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
702*404b540aSrobert : TRY_FINALLY_EXPR,
703*404b540aSrobert void_type_node,
704*404b540aSrobert CLEANUP_BODY (stmt),
705*404b540aSrobert CLEANUP_EXPR (stmt));
706*404b540aSrobert
707*404b540aSrobert pointer_set_insert (p_set, *stmt_p);
708*404b540aSrobert
709*404b540aSrobert return NULL;
710*404b540aSrobert }
711*404b540aSrobert
712*404b540aSrobert void
cp_genericize(tree fndecl)713*404b540aSrobert cp_genericize (tree fndecl)
714*404b540aSrobert {
715*404b540aSrobert tree t;
716*404b540aSrobert struct pointer_set_t *p_set;
717*404b540aSrobert
718*404b540aSrobert /* Fix up the types of parms passed by invisible reference. */
719*404b540aSrobert for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
720*404b540aSrobert if (TREE_ADDRESSABLE (TREE_TYPE (t)))
721*404b540aSrobert {
722*404b540aSrobert /* If a function's arguments are copied to create a thunk,
723*404b540aSrobert then DECL_BY_REFERENCE will be set -- but the type of the
724*404b540aSrobert argument will be a pointer type, so we will never get
725*404b540aSrobert here. */
726*404b540aSrobert gcc_assert (!DECL_BY_REFERENCE (t));
727*404b540aSrobert gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
728*404b540aSrobert TREE_TYPE (t) = DECL_ARG_TYPE (t);
729*404b540aSrobert DECL_BY_REFERENCE (t) = 1;
730*404b540aSrobert TREE_ADDRESSABLE (t) = 0;
731*404b540aSrobert relayout_decl (t);
732*404b540aSrobert }
733*404b540aSrobert
734*404b540aSrobert /* Do the same for the return value. */
735*404b540aSrobert if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
736*404b540aSrobert {
737*404b540aSrobert t = DECL_RESULT (fndecl);
738*404b540aSrobert TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
739*404b540aSrobert DECL_BY_REFERENCE (t) = 1;
740*404b540aSrobert TREE_ADDRESSABLE (t) = 0;
741*404b540aSrobert relayout_decl (t);
742*404b540aSrobert }
743*404b540aSrobert
744*404b540aSrobert /* If we're a clone, the body is already GIMPLE. */
745*404b540aSrobert if (DECL_CLONED_FUNCTION_P (fndecl))
746*404b540aSrobert return;
747*404b540aSrobert
748*404b540aSrobert /* We do want to see every occurrence of the parms, so we can't just use
749*404b540aSrobert walk_tree's hash functionality. */
750*404b540aSrobert p_set = pointer_set_create ();
751*404b540aSrobert walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
752*404b540aSrobert pointer_set_destroy (p_set);
753*404b540aSrobert
754*404b540aSrobert /* Do everything else. */
755*404b540aSrobert c_genericize (fndecl);
756*404b540aSrobert
757*404b540aSrobert gcc_assert (bc_label[bc_break] == NULL);
758*404b540aSrobert gcc_assert (bc_label[bc_continue] == NULL);
759*404b540aSrobert }
760*404b540aSrobert
761*404b540aSrobert /* Build code to apply FN to each member of ARG1 and ARG2. FN may be
762*404b540aSrobert NULL if there is in fact nothing to do. ARG2 may be null if FN
763*404b540aSrobert actually only takes one argument. */
764*404b540aSrobert
765*404b540aSrobert static tree
cxx_omp_clause_apply_fn(tree fn,tree arg1,tree arg2)766*404b540aSrobert cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
767*404b540aSrobert {
768*404b540aSrobert tree defparm, parm;
769*404b540aSrobert int i;
770*404b540aSrobert
771*404b540aSrobert if (fn == NULL)
772*404b540aSrobert return NULL;
773*404b540aSrobert
774*404b540aSrobert defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
775*404b540aSrobert if (arg2)
776*404b540aSrobert defparm = TREE_CHAIN (defparm);
777*404b540aSrobert
778*404b540aSrobert if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
779*404b540aSrobert {
780*404b540aSrobert tree inner_type = TREE_TYPE (arg1);
781*404b540aSrobert tree start1, end1, p1;
782*404b540aSrobert tree start2 = NULL, p2 = NULL;
783*404b540aSrobert tree ret = NULL, lab, t;
784*404b540aSrobert
785*404b540aSrobert start1 = arg1;
786*404b540aSrobert start2 = arg2;
787*404b540aSrobert do
788*404b540aSrobert {
789*404b540aSrobert inner_type = TREE_TYPE (inner_type);
790*404b540aSrobert start1 = build4 (ARRAY_REF, inner_type, start1,
791*404b540aSrobert size_zero_node, NULL, NULL);
792*404b540aSrobert if (arg2)
793*404b540aSrobert start2 = build4 (ARRAY_REF, inner_type, start2,
794*404b540aSrobert size_zero_node, NULL, NULL);
795*404b540aSrobert }
796*404b540aSrobert while (TREE_CODE (inner_type) == ARRAY_TYPE);
797*404b540aSrobert start1 = build_fold_addr_expr (start1);
798*404b540aSrobert if (arg2)
799*404b540aSrobert start2 = build_fold_addr_expr (start2);
800*404b540aSrobert
801*404b540aSrobert end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
802*404b540aSrobert end1 = fold_convert (TREE_TYPE (start1), end1);
803*404b540aSrobert end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1);
804*404b540aSrobert
805*404b540aSrobert p1 = create_tmp_var (TREE_TYPE (start1), NULL);
806*404b540aSrobert t = build2 (MODIFY_EXPR, void_type_node, p1, start1);
807*404b540aSrobert append_to_statement_list (t, &ret);
808*404b540aSrobert
809*404b540aSrobert if (arg2)
810*404b540aSrobert {
811*404b540aSrobert p2 = create_tmp_var (TREE_TYPE (start2), NULL);
812*404b540aSrobert t = build2 (MODIFY_EXPR, void_type_node, p2, start2);
813*404b540aSrobert append_to_statement_list (t, &ret);
814*404b540aSrobert }
815*404b540aSrobert
816*404b540aSrobert lab = create_artificial_label ();
817*404b540aSrobert t = build1 (LABEL_EXPR, void_type_node, lab);
818*404b540aSrobert append_to_statement_list (t, &ret);
819*404b540aSrobert
820*404b540aSrobert t = tree_cons (NULL, p1, NULL);
821*404b540aSrobert if (arg2)
822*404b540aSrobert t = tree_cons (NULL, p2, t);
823*404b540aSrobert /* Handle default arguments. */
824*404b540aSrobert i = 1 + (arg2 != NULL);
825*404b540aSrobert for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
826*404b540aSrobert t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
827*404b540aSrobert TREE_PURPOSE (parm),
828*404b540aSrobert fn, i++), t);
829*404b540aSrobert t = build_call (fn, nreverse (t));
830*404b540aSrobert append_to_statement_list (t, &ret);
831*404b540aSrobert
832*404b540aSrobert t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type));
833*404b540aSrobert t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t);
834*404b540aSrobert t = build2 (MODIFY_EXPR, void_type_node, p1, t);
835*404b540aSrobert append_to_statement_list (t, &ret);
836*404b540aSrobert
837*404b540aSrobert if (arg2)
838*404b540aSrobert {
839*404b540aSrobert t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type));
840*404b540aSrobert t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t);
841*404b540aSrobert t = build2 (MODIFY_EXPR, void_type_node, p2, t);
842*404b540aSrobert append_to_statement_list (t, &ret);
843*404b540aSrobert }
844*404b540aSrobert
845*404b540aSrobert t = build2 (NE_EXPR, boolean_type_node, p1, end1);
846*404b540aSrobert t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
847*404b540aSrobert append_to_statement_list (t, &ret);
848*404b540aSrobert
849*404b540aSrobert return ret;
850*404b540aSrobert }
851*404b540aSrobert else
852*404b540aSrobert {
853*404b540aSrobert tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL);
854*404b540aSrobert if (arg2)
855*404b540aSrobert t = tree_cons (NULL, build_fold_addr_expr (arg2), t);
856*404b540aSrobert /* Handle default arguments. */
857*404b540aSrobert i = 1 + (arg2 != NULL);
858*404b540aSrobert for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
859*404b540aSrobert t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
860*404b540aSrobert TREE_PURPOSE (parm),
861*404b540aSrobert fn, i++), t);
862*404b540aSrobert return build_call (fn, nreverse (t));
863*404b540aSrobert }
864*404b540aSrobert }
865*404b540aSrobert
866*404b540aSrobert /* Return code to initialize DECL with its default constructor, or
867*404b540aSrobert NULL if there's nothing to do. */
868*404b540aSrobert
869*404b540aSrobert tree
cxx_omp_clause_default_ctor(tree clause,tree decl)870*404b540aSrobert cxx_omp_clause_default_ctor (tree clause, tree decl)
871*404b540aSrobert {
872*404b540aSrobert tree info = CP_OMP_CLAUSE_INFO (clause);
873*404b540aSrobert tree ret = NULL;
874*404b540aSrobert
875*404b540aSrobert if (info)
876*404b540aSrobert ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
877*404b540aSrobert
878*404b540aSrobert return ret;
879*404b540aSrobert }
880*404b540aSrobert
881*404b540aSrobert /* Return code to initialize DST with a copy constructor from SRC. */
882*404b540aSrobert
883*404b540aSrobert tree
cxx_omp_clause_copy_ctor(tree clause,tree dst,tree src)884*404b540aSrobert cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
885*404b540aSrobert {
886*404b540aSrobert tree info = CP_OMP_CLAUSE_INFO (clause);
887*404b540aSrobert tree ret = NULL;
888*404b540aSrobert
889*404b540aSrobert if (info)
890*404b540aSrobert ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
891*404b540aSrobert if (ret == NULL)
892*404b540aSrobert ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
893*404b540aSrobert
894*404b540aSrobert return ret;
895*404b540aSrobert }
896*404b540aSrobert
897*404b540aSrobert /* Similarly, except use an assignment operator instead. */
898*404b540aSrobert
899*404b540aSrobert tree
cxx_omp_clause_assign_op(tree clause,tree dst,tree src)900*404b540aSrobert cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
901*404b540aSrobert {
902*404b540aSrobert tree info = CP_OMP_CLAUSE_INFO (clause);
903*404b540aSrobert tree ret = NULL;
904*404b540aSrobert
905*404b540aSrobert if (info)
906*404b540aSrobert ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
907*404b540aSrobert if (ret == NULL)
908*404b540aSrobert ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
909*404b540aSrobert
910*404b540aSrobert return ret;
911*404b540aSrobert }
912*404b540aSrobert
913*404b540aSrobert /* Return code to destroy DECL. */
914*404b540aSrobert
915*404b540aSrobert tree
cxx_omp_clause_dtor(tree clause,tree decl)916*404b540aSrobert cxx_omp_clause_dtor (tree clause, tree decl)
917*404b540aSrobert {
918*404b540aSrobert tree info = CP_OMP_CLAUSE_INFO (clause);
919*404b540aSrobert tree ret = NULL;
920*404b540aSrobert
921*404b540aSrobert if (info)
922*404b540aSrobert ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
923*404b540aSrobert
924*404b540aSrobert return ret;
925*404b540aSrobert }
926*404b540aSrobert
927*404b540aSrobert /* True if OpenMP should privatize what this DECL points to rather
928*404b540aSrobert than the DECL itself. */
929*404b540aSrobert
930*404b540aSrobert bool
cxx_omp_privatize_by_reference(tree decl)931*404b540aSrobert cxx_omp_privatize_by_reference (tree decl)
932*404b540aSrobert {
933*404b540aSrobert return is_invisiref_parm (decl);
934*404b540aSrobert }
935