OSDN Git Service

PR c++/30852
[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_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 (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   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 = fold_convert (TREE_TYPE (start1), end1);
806       end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1);
807
808       p1 = create_tmp_var (TREE_TYPE (start1), NULL);
809       t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p1, start1);
810       append_to_statement_list (t, &ret);
811
812       if (arg2)
813         {
814           p2 = create_tmp_var (TREE_TYPE (start2), NULL);
815           t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p2, start2);
816           append_to_statement_list (t, &ret);
817         }
818
819       lab = create_artificial_label ();
820       t = build1 (LABEL_EXPR, void_type_node, lab);
821       append_to_statement_list (t, &ret);
822
823       argarray[i++] = p1;
824       if (arg2)
825         argarray[i++] = p2;
826       /* Handle default arguments.  */
827       for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm), i++)
828         argarray[i] = convert_default_arg (TREE_VALUE (parm),
829                                            TREE_PURPOSE (parm), fn, i);
830       t = build_call_a (fn, i, argarray);
831       append_to_statement_list (t, &ret);
832
833       t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type));
834       t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t);
835       t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p1, t);
836       append_to_statement_list (t, &ret);
837
838       if (arg2)
839         {
840           t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type));
841           t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t);
842           t = build2 (GIMPLE_MODIFY_STMT, void_type_node, p2, t);
843           append_to_statement_list (t, &ret);
844         }
845
846       t = build2 (NE_EXPR, boolean_type_node, p1, end1);
847       t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
848       append_to_statement_list (t, &ret);
849
850       return ret;
851     }
852   else
853     {
854       argarray[i++] = build_fold_addr_expr (arg1);
855       if (arg2)
856         argarray[i++] = build_fold_addr_expr (arg2);
857       /* Handle default arguments.  */
858       for (parm = defparm; parm != void_list_node;
859            parm = TREE_CHAIN (parm), i++)
860         argarray[i] = convert_default_arg (TREE_VALUE (parm),
861                                            TREE_PURPOSE (parm),
862                                            fn, i);
863       return build_call_a (fn, i, argarray);
864     }
865 }
866
867 /* Return code to initialize DECL with its default constructor, or
868    NULL if there's nothing to do.  */
869
870 tree
871 cxx_omp_clause_default_ctor (tree clause, tree decl)
872 {
873   tree info = CP_OMP_CLAUSE_INFO (clause);
874   tree ret = NULL;
875
876   if (info)
877     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
878
879   return ret;
880 }
881
882 /* Return code to initialize DST with a copy constructor from SRC.  */
883
884 tree
885 cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
886 {
887   tree info = CP_OMP_CLAUSE_INFO (clause);
888   tree ret = NULL;
889
890   if (info)
891     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
892   if (ret == NULL)
893     ret = build2 (GIMPLE_MODIFY_STMT, void_type_node, dst, src);
894
895   return ret;
896 }
897
898 /* Similarly, except use an assignment operator instead.  */
899
900 tree
901 cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
902 {
903   tree info = CP_OMP_CLAUSE_INFO (clause);
904   tree ret = NULL;
905
906   if (info)
907     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
908   if (ret == NULL)
909     ret = build2 (GIMPLE_MODIFY_STMT, void_type_node, dst, src);
910
911   return ret;
912 }
913
914 /* Return code to destroy DECL.  */
915
916 tree
917 cxx_omp_clause_dtor (tree clause, tree decl)
918 {
919   tree info = CP_OMP_CLAUSE_INFO (clause);
920   tree ret = NULL;
921
922   if (info)
923     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
924
925   return ret;
926 }
927
928 /* True if OpenMP should privatize what this DECL points to rather
929    than the DECL itself.  */
930
931 bool
932 cxx_omp_privatize_by_reference (tree decl)
933 {
934   return is_invisiref_parm (decl);
935 }