OSDN Git Service

* c-common.c (vector_types_convertible_p,
[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, 2007
4    Free Software Foundation, Inc.
5    Contributed by Jason Merrill <jason@redhat.com>
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3.  If not see
21 <http://www.gnu.org/licenses/>.  */
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_n (call_unexpected_node, 1, build_exc_ptr ());
150   gimplify_stmt (&body);
151
152   *stmt_p = gimple_build_eh_filter (body, allowed, failure);
153 }
154
155 /* Genericize an IF_STMT by turning it into a COND_EXPR.  */
156
157 static void
158 gimplify_if_stmt (tree *stmt_p)
159 {
160   tree stmt, cond, then_, else_;
161
162   stmt = *stmt_p;
163   cond = IF_COND (stmt);
164   then_ = THEN_CLAUSE (stmt);
165   else_ = ELSE_CLAUSE (stmt);
166
167   if (!then_)
168     then_ = build_empty_stmt ();
169   if (!else_)
170     else_ = build_empty_stmt ();
171
172   if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
173     stmt = then_;
174   else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
175     stmt = else_;
176   else
177     stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
178   *stmt_p = stmt;
179 }
180
181 /* Build a generic representation of one of the C loop forms.  COND is the
182    loop condition or NULL_TREE.  BODY is the (possibly compound) statement
183    controlled by the loop.  INCR is the increment expression of a for-loop,
184    or NULL_TREE.  COND_IS_FIRST indicates whether the condition is
185    evaluated before the loop body as in while and for loops, or after the
186    loop body as in do-while loops.  */
187
188 static tree
189 gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
190 {
191   tree top, entry, exit, cont_block, break_block, stmt_list, t;
192   location_t stmt_locus;
193
194   stmt_locus = input_location;
195   stmt_list = NULL_TREE;
196   entry = NULL_TREE;
197
198   break_block = begin_bc_block (bc_break);
199   cont_block = begin_bc_block (bc_continue);
200
201   /* If condition is zero don't generate a loop construct.  */
202   if (cond && integer_zerop (cond))
203     {
204       top = NULL_TREE;
205       exit = NULL_TREE;
206       if (cond_is_first)
207         {
208           t = build_bc_goto (bc_break);
209           append_to_statement_list (t, &stmt_list);
210         }
211     }
212   else
213     {
214       /* If we use a LOOP_EXPR here, we have to feed the whole thing
215          back through the main gimplifier to lower it.  Given that we
216          have to gimplify the loop body NOW so that we can resolve
217          break/continue stmts, seems easier to just expand to gotos.  */
218       top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
219
220       /* If we have an exit condition, then we build an IF with gotos either
221          out of the loop, or to the top of it.  If there's no exit condition,
222          then we just build a jump back to the top.  */
223       exit = build_and_jump (&LABEL_EXPR_LABEL (top));
224       if (cond && !integer_nonzerop (cond))
225         {
226           t = build_bc_goto (bc_break);
227           exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
228           gimplify_stmt (&exit);
229
230           if (cond_is_first)
231             {
232               if (incr)
233                 {
234                   entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
235                   t = build_and_jump (&LABEL_EXPR_LABEL (entry));
236                 }
237               else
238                 t = build_bc_goto (bc_continue);
239               append_to_statement_list (t, &stmt_list);
240             }
241         }
242     }
243
244   gimplify_stmt (&body);
245   gimplify_stmt (&incr);
246
247   body = finish_bc_block (bc_continue, cont_block, body);
248
249   append_to_statement_list (top, &stmt_list);
250   append_to_statement_list (body, &stmt_list);
251   append_to_statement_list (incr, &stmt_list);
252   append_to_statement_list (entry, &stmt_list);
253   append_to_statement_list (exit, &stmt_list);
254
255   annotate_all_with_locus (&stmt_list, stmt_locus);
256
257   return finish_bc_block (bc_break, break_block, stmt_list);
258 }
259
260 /* Gimplify a FOR_STMT node.  Move the stuff in the for-init-stmt into the
261    prequeue and hand off to gimplify_cp_loop.  */
262
263 static void
264 gimplify_for_stmt (tree *stmt_p, tree *pre_p)
265 {
266   tree stmt = *stmt_p;
267
268   if (FOR_INIT_STMT (stmt))
269     gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
270
271   *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
272                               FOR_EXPR (stmt), 1);
273 }
274
275 /* Gimplify a WHILE_STMT node.  */
276
277 static void
278 gimplify_while_stmt (tree *stmt_p)
279 {
280   tree stmt = *stmt_p;
281   *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
282                               NULL_TREE, 1);
283 }
284
285 /* Gimplify a DO_STMT node.  */
286
287 static void
288 gimplify_do_stmt (tree *stmt_p)
289 {
290   tree stmt = *stmt_p;
291   *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
292                               NULL_TREE, 0);
293 }
294
295 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
296
297 static void
298 gimplify_switch_stmt (tree *stmt_p)
299 {
300   tree stmt = *stmt_p;
301   tree break_block, body;
302   location_t stmt_locus = input_location;
303
304   break_block = begin_bc_block (bc_break);
305
306   body = SWITCH_STMT_BODY (stmt);
307   if (!body)
308     body = build_empty_stmt ();
309
310   *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
311                     SWITCH_STMT_COND (stmt), body, NULL_TREE);
312   SET_EXPR_LOCATION (*stmt_p, stmt_locus);
313   gimplify_stmt (stmt_p);
314
315   *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p);
316 }
317
318 /* Hook into the middle of gimplifying an OMP_FOR node.  This is required
319    in order to properly gimplify CONTINUE statements.  Here we merely
320    manage the continue stack; the rest of the job is performed by the
321    regular gimplifier.  */
322
323 static enum gimplify_status
324 cp_gimplify_omp_for (tree *expr_p)
325 {
326   tree for_stmt = *expr_p;
327   tree cont_block;
328
329   /* Protect ourselves from recursion.  */
330   if (OMP_FOR_GIMPLIFYING_P (for_stmt))
331     return GS_UNHANDLED;
332   OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
333
334   /* Note that while technically the continue label is enabled too soon
335      here, we should have already diagnosed invalid continues nested within
336      statement expressions within the INIT, COND, or INCR expressions.  */
337   cont_block = begin_bc_block (bc_continue);
338
339   gimplify_stmt (expr_p);
340
341   OMP_FOR_BODY (for_stmt)
342     = finish_bc_block (bc_continue, cont_block, OMP_FOR_BODY (for_stmt));
343   OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
344
345   return GS_ALL_DONE;
346 }
347
348 /*  Gimplify an EXPR_STMT node.  */
349
350 static void
351 gimplify_expr_stmt (tree *stmt_p)
352 {
353   tree stmt = EXPR_STMT_EXPR (*stmt_p);
354
355   if (stmt == error_mark_node)
356     stmt = NULL;
357
358   /* Gimplification of a statement expression will nullify the
359      statement if all its side effects are moved to *PRE_P and *POST_P.
360
361      In this case we will not want to emit the gimplified statement.
362      However, we may still want to emit a warning, so we do that before
363      gimplification.  */
364   if (stmt && warn_unused_value)
365     {
366       if (!TREE_SIDE_EFFECTS (stmt))
367         {
368           if (!IS_EMPTY_STMT (stmt)
369               && !VOID_TYPE_P (TREE_TYPE (stmt))
370               && !TREE_NO_WARNING (stmt))
371             warning (OPT_Wunused_value, "statement with no effect");
372         }
373       else
374         warn_if_unused_value (stmt, input_location);
375     }
376
377   if (stmt == NULL_TREE)
378     stmt = alloc_stmt_list ();
379
380   *stmt_p = stmt;
381 }
382
383 /* Gimplify initialization from an AGGR_INIT_EXPR.  */
384
385 static void
386 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
387 {
388   tree from = TREE_OPERAND (*expr_p, 1);
389   tree to = TREE_OPERAND (*expr_p, 0);
390   tree sub;
391
392   /* What about code that pulls out the temp and uses it elsewhere?  I
393      think that such code never uses the TARGET_EXPR as an initializer.  If
394      I'm wrong, we'll abort because the temp won't have any RTL.  In that
395      case, I guess we'll need to replace references somehow.  */
396   if (TREE_CODE (from) == TARGET_EXPR)
397     from = TARGET_EXPR_INITIAL (from);
398
399   /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
400      inside the TARGET_EXPR.  */
401   sub = expr_last (from);
402
403   /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
404      replace the slot operand with our target.
405
406      Should we add a target parm to gimplify_expr instead?  No, as in this
407      case we want to replace the INIT_EXPR.  */
408   if (TREE_CODE (sub) == AGGR_INIT_EXPR)
409     {
410       gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
411       AGGR_INIT_EXPR_SLOT (sub) = to;
412       *expr_p = from;
413
414       /* The initialization is now a side-effect, so the container can
415          become void.  */
416       if (from != sub)
417         TREE_TYPE (from) = void_type_node;
418     }
419 }
420
421 /* Gimplify a MUST_NOT_THROW_EXPR.  */
422
423 static void
424 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
425 {
426   tree stmt = *expr_p;
427   tree temp = voidify_wrapper_expr (stmt, NULL);
428   tree body = TREE_OPERAND (stmt, 0);
429
430   gimplify_stmt (&body);
431
432   stmt = gimple_build_eh_filter (body, NULL_TREE,
433                                  build_call_n (terminate_node, 0));
434
435   if (temp)
436     {
437       append_to_statement_list (stmt, pre_p);
438       *expr_p = temp;
439     }
440   else
441     *expr_p = stmt;
442 }
443
444 /* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
445
446 int
447 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
448 {
449   int saved_stmts_are_full_exprs_p = 0;
450   enum tree_code code = TREE_CODE (*expr_p);
451   enum gimplify_status ret;
452
453   if (STATEMENT_CODE_P (code))
454     {
455       saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
456       current_stmt_tree ()->stmts_are_full_exprs_p
457         = STMT_IS_FULL_EXPR_P (*expr_p);
458     }
459
460   switch (code)
461     {
462     case PTRMEM_CST:
463       *expr_p = cplus_expand_constant (*expr_p);
464       ret = GS_OK;
465       break;
466
467     case AGGR_INIT_EXPR:
468       simplify_aggr_init_expr (expr_p);
469       ret = GS_OK;
470       break;
471
472     case THROW_EXPR:
473       /* FIXME communicate throw type to back end, probably by moving
474          THROW_EXPR into ../tree.def.  */
475       *expr_p = TREE_OPERAND (*expr_p, 0);
476       ret = GS_OK;
477       break;
478
479     case MUST_NOT_THROW_EXPR:
480       gimplify_must_not_throw_expr (expr_p, pre_p);
481       ret = GS_OK;
482       break;
483
484       /* We used to do this for GIMPLE_MODIFY_STMT as well, but that's unsafe; the
485          LHS of an assignment might also be involved in the RHS, as in bug
486          25979.  */
487     case INIT_EXPR:
488       cp_gimplify_init_expr (expr_p, pre_p, post_p);
489       ret = GS_OK;
490       break;
491
492     case EMPTY_CLASS_EXPR:
493       /* We create an empty CONSTRUCTOR with RECORD_TYPE.  */
494       *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
495       ret = GS_OK;
496       break;
497
498     case BASELINK:
499       *expr_p = BASELINK_FUNCTIONS (*expr_p);
500       ret = GS_OK;
501       break;
502
503     case TRY_BLOCK:
504       genericize_try_block (expr_p);
505       ret = GS_OK;
506       break;
507
508     case HANDLER:
509       genericize_catch_block (expr_p);
510       ret = GS_OK;
511       break;
512
513     case EH_SPEC_BLOCK:
514       genericize_eh_spec_block (expr_p);
515       ret = GS_OK;
516       break;
517
518     case USING_STMT:
519       /* Just ignore for now.  Eventually we will want to pass this on to
520          the debugger.  */
521       *expr_p = build_empty_stmt ();
522       ret = GS_ALL_DONE;
523       break;
524
525     case IF_STMT:
526       gimplify_if_stmt (expr_p);
527       ret = GS_OK;
528       break;
529
530     case FOR_STMT:
531       gimplify_for_stmt (expr_p, pre_p);
532       ret = GS_ALL_DONE;
533       break;
534
535     case WHILE_STMT:
536       gimplify_while_stmt (expr_p);
537       ret = GS_ALL_DONE;
538       break;
539
540     case DO_STMT:
541       gimplify_do_stmt (expr_p);
542       ret = GS_ALL_DONE;
543       break;
544
545     case SWITCH_STMT:
546       gimplify_switch_stmt (expr_p);
547       ret = GS_ALL_DONE;
548       break;
549
550     case OMP_FOR:
551       ret = cp_gimplify_omp_for (expr_p);
552       break;
553
554     case CONTINUE_STMT:
555       *expr_p = build_bc_goto (bc_continue);
556       ret = GS_ALL_DONE;
557       break;
558
559     case BREAK_STMT:
560       *expr_p = build_bc_goto (bc_break);
561       ret = GS_ALL_DONE;
562       break;
563
564     case EXPR_STMT:
565       gimplify_expr_stmt (expr_p);
566       ret = GS_OK;
567       break;
568
569     case UNARY_PLUS_EXPR:
570       {
571         tree arg = TREE_OPERAND (*expr_p, 0);
572         tree type = TREE_TYPE (*expr_p);
573         *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
574                                             : arg;
575         ret = GS_OK;
576       }
577       break;
578
579     default:
580       ret = c_gimplify_expr (expr_p, pre_p, post_p);
581       break;
582     }
583
584   /* Restore saved state.  */
585   if (STATEMENT_CODE_P (code))
586     current_stmt_tree ()->stmts_are_full_exprs_p
587       = saved_stmts_are_full_exprs_p;
588
589   return ret;
590 }
591
592 static inline bool
593 is_invisiref_parm (const_tree t)
594 {
595   return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
596           && DECL_BY_REFERENCE (t));
597 }
598
599 /* Return true if the uid in both int tree maps are equal.  */
600
601 int
602 cxx_int_tree_map_eq (const void *va, const void *vb)
603 {
604   const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
605   const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
606   return (a->uid == b->uid);
607 }
608
609 /* Hash a UID in a cxx_int_tree_map.  */
610
611 unsigned int
612 cxx_int_tree_map_hash (const void *item)
613 {
614   return ((const struct cxx_int_tree_map *)item)->uid;
615 }
616
617 /* Perform any pre-gimplification lowering of C++ front end trees to
618    GENERIC.  */
619
620 static tree
621 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
622 {
623   tree stmt = *stmt_p;
624   struct pointer_set_t *p_set = (struct pointer_set_t*) data;
625
626   if (is_invisiref_parm (stmt)
627       /* Don't dereference parms in a thunk, pass the references through. */
628       && !(DECL_THUNK_P (current_function_decl)
629            && TREE_CODE (stmt) == PARM_DECL))
630     {
631       *stmt_p = convert_from_reference (stmt);
632       *walk_subtrees = 0;
633       return NULL;
634     }
635
636   /* Map block scope extern declarations to visible declarations with the
637      same name and type in outer scopes if any.  */
638   if (cp_function_chain->extern_decl_map
639       && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
640       && DECL_EXTERNAL (stmt))
641     {
642       struct cxx_int_tree_map *h, in;
643       in.uid = DECL_UID (stmt);
644       h = (struct cxx_int_tree_map *)
645           htab_find_with_hash (cp_function_chain->extern_decl_map,
646                                &in, in.uid);
647       if (h)
648         {
649           *stmt_p = h->to;
650           *walk_subtrees = 0;
651           return NULL;
652         }
653     }
654
655   /* Other than invisiref parms, don't walk the same tree twice.  */
656   if (pointer_set_contains (p_set, stmt))
657     {
658       *walk_subtrees = 0;
659       return NULL_TREE;
660     }
661
662   if (TREE_CODE (stmt) == ADDR_EXPR
663       && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
664     {
665       *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
666       *walk_subtrees = 0;
667     }
668   else if (TREE_CODE (stmt) == RETURN_EXPR
669            && TREE_OPERAND (stmt, 0)
670            && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
671     /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
672     *walk_subtrees = 0;
673   else if (TREE_CODE (stmt) == OMP_CLAUSE)
674     switch (OMP_CLAUSE_CODE (stmt))
675       {
676       case OMP_CLAUSE_PRIVATE:
677       case OMP_CLAUSE_SHARED:
678       case OMP_CLAUSE_FIRSTPRIVATE:
679       case OMP_CLAUSE_LASTPRIVATE:
680       case OMP_CLAUSE_COPYIN:
681       case OMP_CLAUSE_COPYPRIVATE:
682         /* Don't dereference an invisiref in OpenMP clauses.  */
683         if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
684           *walk_subtrees = 0;
685         break;
686       case OMP_CLAUSE_REDUCTION:
687         gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
688         break;
689       default:
690         break;
691       }
692   else if (IS_TYPE_OR_DECL_P (stmt))
693     *walk_subtrees = 0;
694
695   /* Due to the way voidify_wrapper_expr is written, we don't get a chance
696      to lower this construct before scanning it, so we need to lower these
697      before doing anything else.  */
698   else if (TREE_CODE (stmt) == CLEANUP_STMT)
699     *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
700                                              : TRY_FINALLY_EXPR,
701                       void_type_node,
702                       CLEANUP_BODY (stmt),
703                       CLEANUP_EXPR (stmt));
704
705   pointer_set_insert (p_set, *stmt_p);
706
707   return NULL;
708 }
709
710 void
711 cp_genericize (tree fndecl)
712 {
713   tree t;
714   struct pointer_set_t *p_set;
715
716   /* Fix up the types of parms passed by invisible reference.  */
717   for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
718     if (TREE_ADDRESSABLE (TREE_TYPE (t)))
719       {
720         /* If a function's arguments are copied to create a thunk,
721            then DECL_BY_REFERENCE will be set -- but the type of the
722            argument will be a pointer type, so we will never get
723            here.  */
724         gcc_assert (!DECL_BY_REFERENCE (t));
725         gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
726         TREE_TYPE (t) = DECL_ARG_TYPE (t);
727         DECL_BY_REFERENCE (t) = 1;
728         TREE_ADDRESSABLE (t) = 0;
729         relayout_decl (t);
730       }
731
732   /* Do the same for the return value.  */
733   if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
734     {
735       t = DECL_RESULT (fndecl);
736       TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
737       DECL_BY_REFERENCE (t) = 1;
738       TREE_ADDRESSABLE (t) = 0;
739       relayout_decl (t);
740     }
741
742   /* If we're a clone, the body is already GIMPLE.  */
743   if (DECL_CLONED_FUNCTION_P (fndecl))
744     return;
745
746   /* We do want to see every occurrence of the parms, so we can't just use
747      walk_tree's hash functionality.  */
748   p_set = pointer_set_create ();
749   cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
750   pointer_set_destroy (p_set);
751
752   /* Do everything else.  */
753   c_genericize (fndecl);
754
755   gcc_assert (bc_label[bc_break] == NULL);
756   gcc_assert (bc_label[bc_continue] == NULL);
757 }
758 \f
759 /* Build code to apply FN to each member of ARG1 and ARG2.  FN may be
760    NULL if there is in fact nothing to do.  ARG2 may be null if FN
761    actually only takes one argument.  */
762
763 static tree
764 cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
765 {
766   tree defparm, parm;
767   int i = 0;
768   int nargs;
769   tree *argarray;
770
771   if (fn == NULL)
772     return NULL;
773
774   nargs = list_length (DECL_ARGUMENTS (fn));
775   argarray = (tree *) alloca (nargs * sizeof (tree));
776
777   defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
778   if (arg2)
779     defparm = TREE_CHAIN (defparm);
780
781   if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
782     {
783       tree inner_type = TREE_TYPE (arg1);
784       tree start1, end1, p1;
785       tree start2 = NULL, p2 = NULL;
786       tree ret = NULL, lab, t;
787
788       start1 = arg1;
789       start2 = arg2;
790       do
791         {
792           inner_type = TREE_TYPE (inner_type);
793           start1 = build4 (ARRAY_REF, inner_type, start1,
794                            size_zero_node, NULL, NULL);
795           if (arg2)
796             start2 = build4 (ARRAY_REF, inner_type, start2,
797                              size_zero_node, NULL, NULL);
798         }
799       while (TREE_CODE (inner_type) == ARRAY_TYPE);
800       start1 = build_fold_addr_expr (start1);
801       if (arg2)
802         start2 = build_fold_addr_expr (start2);
803
804       end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
805       end1 = build2 (POINTER_PLUS_EXPR, TREE_TYPE (start1), start1, end1);
806
807       p1 = create_tmp_var (TREE_TYPE (start1), NULL);
808       t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p1, start1);
809       append_to_statement_list (t, &ret);
810
811       if (arg2)
812         {
813           p2 = create_tmp_var (TREE_TYPE (start2), NULL);
814           t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p2, start2);
815           append_to_statement_list (t, &ret);
816         }
817
818       lab = create_artificial_label ();
819       t = build1 (LABEL_EXPR, void_type_node, lab);
820       append_to_statement_list (t, &ret);
821
822       argarray[i++] = p1;
823       if (arg2)
824         argarray[i++] = p2;
825       /* Handle default arguments.  */
826       for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm), i++)
827         argarray[i] = convert_default_arg (TREE_VALUE (parm),
828                                            TREE_PURPOSE (parm), fn, i);
829       t = build_call_a (fn, i, argarray);
830       append_to_statement_list (t, &ret);
831
832       t = TYPE_SIZE_UNIT (inner_type);
833       t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p1), p1, t);
834       t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p1, t);
835       append_to_statement_list (t, &ret);
836
837       if (arg2)
838         {
839           t = TYPE_SIZE_UNIT (inner_type);
840           t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p2), p2, t);
841           t = build2 (GIMPLE_MODIFY_STMT, 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       argarray[i++] = build_fold_addr_expr (arg1);
854       if (arg2)
855         argarray[i++] = build_fold_addr_expr (arg2);
856       /* Handle default arguments.  */
857       for (parm = defparm; parm != void_list_node;
858            parm = TREE_CHAIN (parm), i++)
859         argarray[i] = convert_default_arg (TREE_VALUE (parm),
860                                            TREE_PURPOSE (parm),
861                                            fn, i);
862       return build_call_a (fn, i, argarray);
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 (GIMPLE_MODIFY_STMT, 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 (GIMPLE_MODIFY_STMT, 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 (const_tree decl)
932 {
933   return is_invisiref_parm (decl);
934 }