OSDN Git Service

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