]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/gcc/cp/cp-gimplify.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / 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   /* What about code that pulls out the temp and uses it elsewhere?  I
395      think that such code never uses the TARGET_EXPR as an initializer.  If
396      I'm wrong, we'll abort because the temp won't have any RTL.  In that
397      case, I guess we'll need to replace references somehow.  */
398   if (TREE_CODE (from) == TARGET_EXPR)
399     from = TARGET_EXPR_INITIAL (from);
400
401   /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
402      inside the TARGET_EXPR.  */
403   sub = expr_last (from);
404
405   /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
406      replace the slot operand with our target.
407
408      Should we add a target parm to gimplify_expr instead?  No, as in this
409      case we want to replace the INIT_EXPR.  */
410   if (TREE_CODE (sub) == AGGR_INIT_EXPR)
411     {
412       gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
413       TREE_OPERAND (sub, 2) = to;
414       *expr_p = from;
415
416       /* The initialization is now a side-effect, so the container can
417          become void.  */
418       if (from != sub)
419         TREE_TYPE (from) = void_type_node;
420     }
421 }
422
423 /* Gimplify a MUST_NOT_THROW_EXPR.  */
424
425 static void
426 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
427 {
428   tree stmt = *expr_p;
429   tree temp = voidify_wrapper_expr (stmt, NULL);
430   tree body = TREE_OPERAND (stmt, 0);
431
432   gimplify_stmt (&body);
433
434   stmt = gimple_build_eh_filter (body, NULL_TREE,
435                                  build_call (terminate_node, NULL_TREE));
436
437   if (temp)
438     {
439       append_to_statement_list (stmt, pre_p);
440       *expr_p = temp;
441     }
442   else
443     *expr_p = stmt;
444 }
445
446 /* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
447
448 int
449 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
450 {
451   int saved_stmts_are_full_exprs_p = 0;
452   enum tree_code code = TREE_CODE (*expr_p);
453   enum gimplify_status ret;
454
455   if (STATEMENT_CODE_P (code))
456     {
457       saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
458       current_stmt_tree ()->stmts_are_full_exprs_p
459         = STMT_IS_FULL_EXPR_P (*expr_p);
460     }
461
462   switch (code)
463     {
464     case PTRMEM_CST:
465       *expr_p = cplus_expand_constant (*expr_p);
466       ret = GS_OK;
467       break;
468
469     case AGGR_INIT_EXPR:
470       simplify_aggr_init_expr (expr_p);
471       ret = GS_OK;
472       break;
473
474     case THROW_EXPR:
475       /* FIXME communicate throw type to backend, probably by moving
476          THROW_EXPR into ../tree.def.  */
477       *expr_p = TREE_OPERAND (*expr_p, 0);
478       ret = GS_OK;
479       break;
480
481     case MUST_NOT_THROW_EXPR:
482       gimplify_must_not_throw_expr (expr_p, pre_p);
483       ret = GS_OK;
484       break;
485
486       /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
487          LHS of an assignment might also be involved in the RHS, as in bug
488          25979.  */
489     case INIT_EXPR:
490       cp_gimplify_init_expr (expr_p, pre_p, post_p);
491       ret = GS_OK;
492       break;
493
494     case EMPTY_CLASS_EXPR:
495       /* We create an empty CONSTRUCTOR with RECORD_TYPE.  */
496       *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
497       ret = GS_OK;
498       break;
499
500     case BASELINK:
501       *expr_p = BASELINK_FUNCTIONS (*expr_p);
502       ret = GS_OK;
503       break;
504
505     case TRY_BLOCK:
506       genericize_try_block (expr_p);
507       ret = GS_OK;
508       break;
509
510     case HANDLER:
511       genericize_catch_block (expr_p);
512       ret = GS_OK;
513       break;
514
515     case EH_SPEC_BLOCK:
516       genericize_eh_spec_block (expr_p);
517       ret = GS_OK;
518       break;
519
520     case USING_STMT:
521       /* Just ignore for now.  Eventually we will want to pass this on to
522          the debugger.  */
523       *expr_p = build_empty_stmt ();
524       ret = GS_ALL_DONE;
525       break;
526
527     case IF_STMT:
528       gimplify_if_stmt (expr_p);
529       ret = GS_OK;
530       break;
531
532     case FOR_STMT:
533       gimplify_for_stmt (expr_p, pre_p);
534       ret = GS_ALL_DONE;
535       break;
536
537     case WHILE_STMT:
538       gimplify_while_stmt (expr_p);
539       ret = GS_ALL_DONE;
540       break;
541
542     case DO_STMT:
543       gimplify_do_stmt (expr_p);
544       ret = GS_ALL_DONE;
545       break;
546
547     case SWITCH_STMT:
548       gimplify_switch_stmt (expr_p);
549       ret = GS_ALL_DONE;
550       break;
551
552     case OMP_FOR:
553       ret = cp_gimplify_omp_for (expr_p);
554       break;
555
556     case CONTINUE_STMT:
557       *expr_p = build_bc_goto (bc_continue);
558       ret = GS_ALL_DONE;
559       break;
560
561     case BREAK_STMT:
562       *expr_p = build_bc_goto (bc_break);
563       ret = GS_ALL_DONE;
564       break;
565
566     case EXPR_STMT:
567       gimplify_expr_stmt (expr_p);
568       ret = GS_OK;
569       break;
570
571     case UNARY_PLUS_EXPR:
572       {
573         tree arg = TREE_OPERAND (*expr_p, 0);
574         tree type = TREE_TYPE (*expr_p);
575         *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
576                                             : arg;
577         ret = GS_OK;
578       }
579       break;
580
581     default:
582       ret = c_gimplify_expr (expr_p, pre_p, post_p);
583       break;
584     }
585
586   /* Restore saved state.  */
587   if (STATEMENT_CODE_P (code))
588     current_stmt_tree ()->stmts_are_full_exprs_p
589       = saved_stmts_are_full_exprs_p;
590
591   return ret;
592 }
593
594 static inline bool
595 is_invisiref_parm (tree t)
596 {
597   return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
598           && DECL_BY_REFERENCE (t));
599 }
600
601 /* Return true if the uid in both int tree maps are equal.  */
602
603 int
604 cxx_int_tree_map_eq (const void *va, const void *vb)
605 {
606   const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
607   const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
608   return (a->uid == b->uid);
609 }
610
611 /* Hash a UID in a cxx_int_tree_map.  */
612
613 unsigned int
614 cxx_int_tree_map_hash (const void *item)
615 {
616   return ((const struct cxx_int_tree_map *)item)->uid;
617 }
618
619 /* Perform any pre-gimplification lowering of C++ front end trees to
620    GENERIC.  */
621
622 static tree
623 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
624 {
625   tree stmt = *stmt_p;
626   struct pointer_set_t *p_set = (struct pointer_set_t*) data;
627
628   if (is_invisiref_parm (stmt)
629       /* Don't dereference parms in a thunk, pass the references through. */
630       && !(DECL_THUNK_P (current_function_decl)
631            && TREE_CODE (stmt) == PARM_DECL))
632     {
633       *stmt_p = convert_from_reference (stmt);
634       *walk_subtrees = 0;
635       return NULL;
636     }
637
638   /* Map block scope extern declarations to visible declarations with the
639      same name and type in outer scopes if any.  */
640   if (cp_function_chain->extern_decl_map
641       && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
642       && DECL_EXTERNAL (stmt))
643     {
644       struct cxx_int_tree_map *h, in;
645       in.uid = DECL_UID (stmt);
646       h = (struct cxx_int_tree_map *)
647           htab_find_with_hash (cp_function_chain->extern_decl_map,
648                                &in, in.uid);
649       if (h)
650         {
651           *stmt_p = h->to;
652           *walk_subtrees = 0;
653           return NULL;
654         }
655     }
656
657   /* Other than invisiref parms, don't walk the same tree twice.  */
658   if (pointer_set_contains (p_set, stmt))
659     {
660       *walk_subtrees = 0;
661       return NULL_TREE;
662     }
663
664   if (TREE_CODE (stmt) == ADDR_EXPR
665       && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
666     {
667       *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
668       *walk_subtrees = 0;
669     }
670   else if (TREE_CODE (stmt) == RETURN_EXPR
671            && TREE_OPERAND (stmt, 0)
672            && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
673     /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
674     *walk_subtrees = 0;
675   else if (TREE_CODE (stmt) == OMP_CLAUSE)
676     switch (OMP_CLAUSE_CODE (stmt))
677       {
678       case OMP_CLAUSE_PRIVATE:
679       case OMP_CLAUSE_SHARED:
680       case OMP_CLAUSE_FIRSTPRIVATE:
681       case OMP_CLAUSE_LASTPRIVATE:
682       case OMP_CLAUSE_COPYIN:
683       case OMP_CLAUSE_COPYPRIVATE:
684         /* Don't dereference an invisiref in OpenMP clauses.  */
685         if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
686           *walk_subtrees = 0;
687         break;
688       case OMP_CLAUSE_REDUCTION:
689         gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
690         break;
691       default:
692         break;
693       }
694   else if (IS_TYPE_OR_DECL_P (stmt))
695     *walk_subtrees = 0;
696
697   /* Due to the way voidify_wrapper_expr is written, we don't get a chance
698      to lower this construct before scanning it, so we need to lower these
699      before doing anything else.  */
700   else if (TREE_CODE (stmt) == CLEANUP_STMT)
701     *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
702                                              : TRY_FINALLY_EXPR,
703                       void_type_node,
704                       CLEANUP_BODY (stmt),
705                       CLEANUP_EXPR (stmt));
706
707   pointer_set_insert (p_set, *stmt_p);
708
709   return NULL;
710 }
711
712 void
713 cp_genericize (tree fndecl)
714 {
715   tree t;
716   struct pointer_set_t *p_set;
717
718   /* Fix up the types of parms passed by invisible reference.  */
719   for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
720     if (TREE_ADDRESSABLE (TREE_TYPE (t)))
721       {
722         /* If a function's arguments are copied to create a thunk,
723            then DECL_BY_REFERENCE will be set -- but the type of the
724            argument will be a pointer type, so we will never get
725            here.  */
726         gcc_assert (!DECL_BY_REFERENCE (t));
727         gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
728         TREE_TYPE (t) = DECL_ARG_TYPE (t);
729         DECL_BY_REFERENCE (t) = 1;
730         TREE_ADDRESSABLE (t) = 0;
731         relayout_decl (t);
732       }
733
734   /* Do the same for the return value.  */
735   if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
736     {
737       t = DECL_RESULT (fndecl);
738       TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
739       DECL_BY_REFERENCE (t) = 1;
740       TREE_ADDRESSABLE (t) = 0;
741       relayout_decl (t);
742     }
743
744   /* If we're a clone, the body is already GIMPLE.  */
745   if (DECL_CLONED_FUNCTION_P (fndecl))
746     return;
747
748   /* We do want to see every occurrence of the parms, so we can't just use
749      walk_tree's hash functionality.  */
750   p_set = pointer_set_create ();
751   walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
752   pointer_set_destroy (p_set);
753
754   /* Do everything else.  */
755   c_genericize (fndecl);
756
757   gcc_assert (bc_label[bc_break] == NULL);
758   gcc_assert (bc_label[bc_continue] == NULL);
759 }
760 \f
761 /* Build code to apply FN to each member of ARG1 and ARG2.  FN may be
762    NULL if there is in fact nothing to do.  ARG2 may be null if FN
763    actually only takes one argument.  */
764
765 static tree
766 cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
767 {
768   tree defparm, parm;
769   int i;
770
771   if (fn == NULL)
772     return NULL;
773
774   defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
775   if (arg2)
776     defparm = TREE_CHAIN (defparm);
777
778   if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
779     {
780       tree inner_type = TREE_TYPE (arg1);
781       tree start1, end1, p1;
782       tree start2 = NULL, p2 = NULL;
783       tree ret = NULL, lab, t;
784
785       start1 = arg1;
786       start2 = arg2;
787       do
788         {
789           inner_type = TREE_TYPE (inner_type);
790           start1 = build4 (ARRAY_REF, inner_type, start1,
791                            size_zero_node, NULL, NULL);
792           if (arg2)
793             start2 = build4 (ARRAY_REF, inner_type, start2,
794                              size_zero_node, NULL, NULL);
795         }
796       while (TREE_CODE (inner_type) == ARRAY_TYPE);
797       start1 = build_fold_addr_expr (start1);
798       if (arg2)
799         start2 = build_fold_addr_expr (start2);
800
801       end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
802       end1 = fold_convert (TREE_TYPE (start1), end1);
803       end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1);
804
805       p1 = create_tmp_var (TREE_TYPE (start1), NULL);
806       t = build2 (MODIFY_EXPR, void_type_node, p1, start1);
807       append_to_statement_list (t, &ret);
808
809       if (arg2)
810         {
811           p2 = create_tmp_var (TREE_TYPE (start2), NULL);
812           t = build2 (MODIFY_EXPR, void_type_node, p2, start2);
813           append_to_statement_list (t, &ret);
814         }
815
816       lab = create_artificial_label ();
817       t = build1 (LABEL_EXPR, void_type_node, lab);
818       append_to_statement_list (t, &ret);
819
820       t = tree_cons (NULL, p1, NULL);
821       if (arg2)
822         t = tree_cons (NULL, p2, t);
823       /* Handle default arguments.  */
824       i = 1 + (arg2 != NULL);
825       for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
826         t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
827                                                   TREE_PURPOSE (parm),
828                                                   fn, i++), t);
829       t = build_call (fn, nreverse (t));
830       append_to_statement_list (t, &ret);
831
832       t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type));
833       t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t);
834       t = build2 (MODIFY_EXPR, void_type_node, p1, t);
835       append_to_statement_list (t, &ret);
836
837       if (arg2)
838         {
839           t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type));
840           t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t);
841           t = build2 (MODIFY_EXPR, void_type_node, p2, t);
842           append_to_statement_list (t, &ret);
843         }
844
845       t = build2 (NE_EXPR, boolean_type_node, p1, end1);
846       t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
847       append_to_statement_list (t, &ret);
848
849       return ret;
850     }
851   else
852     {
853       tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL);
854       if (arg2)
855         t = tree_cons (NULL, build_fold_addr_expr (arg2), t);
856       /* Handle default arguments.  */
857       i = 1 + (arg2 != NULL);
858       for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
859         t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
860                                                   TREE_PURPOSE (parm),
861                                                   fn, i++), t);
862       return build_call (fn, nreverse (t));
863     }
864 }
865
866 /* Return code to initialize DECL with its default constructor, or
867    NULL if there's nothing to do.  */
868
869 tree
870 cxx_omp_clause_default_ctor (tree clause, tree decl)
871 {
872   tree info = CP_OMP_CLAUSE_INFO (clause);
873   tree ret = NULL;
874
875   if (info)
876     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
877
878   return ret;
879 }
880
881 /* Return code to initialize DST with a copy constructor from SRC.  */
882
883 tree
884 cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
885 {
886   tree info = CP_OMP_CLAUSE_INFO (clause);
887   tree ret = NULL;
888
889   if (info)
890     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
891   if (ret == NULL)
892     ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
893
894   return ret;
895 }
896
897 /* Similarly, except use an assignment operator instead.  */
898
899 tree
900 cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
901 {
902   tree info = CP_OMP_CLAUSE_INFO (clause);
903   tree ret = NULL;
904
905   if (info)
906     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
907   if (ret == NULL)
908     ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
909
910   return ret;
911 }
912
913 /* Return code to destroy DECL.  */
914
915 tree
916 cxx_omp_clause_dtor (tree clause, tree decl)
917 {
918   tree info = CP_OMP_CLAUSE_INFO (clause);
919   tree ret = NULL;
920
921   if (info)
922     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
923
924   return ret;
925 }
926
927 /* True if OpenMP should privatize what this DECL points to rather
928    than the DECL itself.  */
929
930 bool
931 cxx_omp_privatize_by_reference (tree decl)
932 {
933   return is_invisiref_parm (decl);
934 }