xref: /openbsd/gnu/gcc/gcc/cp/cp-gimplify.c (revision 404b540a)
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