OSDN Git Service

PR c++/28048
[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 /* Return true if the uid in both int tree maps are equal.  */
605
606 int
607 cxx_int_tree_map_eq (const void *va, const void *vb)
608 {
609   const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
610   const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
611   return (a->uid == b->uid);
612 }
613
614 /* Hash a UID in a cxx_int_tree_map.  */
615
616 unsigned int
617 cxx_int_tree_map_hash (const void *item)
618 {
619   return ((const struct cxx_int_tree_map *)item)->uid;
620 }
621
622 /* Perform any pre-gimplification lowering of C++ front end trees to
623    GENERIC.  */
624
625 static tree
626 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
627 {
628   tree stmt = *stmt_p;
629   struct pointer_set_t *p_set = (struct pointer_set_t*) data;
630
631   if (is_invisiref_parm (stmt)
632       /* Don't dereference parms in a thunk, pass the references through. */
633       && !(DECL_THUNK_P (current_function_decl)
634            && TREE_CODE (stmt) == PARM_DECL))
635     {
636       *stmt_p = convert_from_reference (stmt);
637       *walk_subtrees = 0;
638       return NULL;
639     }
640
641   /* Map block scope extern declarations to visible declarations with the
642      same name and type in outer scopes if any.  */
643   if (cp_function_chain->extern_decl_map
644       && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
645       && DECL_EXTERNAL (stmt))
646     {
647       struct cxx_int_tree_map *h, in;
648       in.uid = DECL_UID (stmt);
649       h = (struct cxx_int_tree_map *)
650           htab_find_with_hash (cp_function_chain->extern_decl_map,
651                                &in, in.uid);
652       if (h)
653         {
654           *stmt_p = h->to;
655           *walk_subtrees = 0;
656           return NULL;
657         }
658     }
659
660   /* Other than invisiref parms, don't walk the same tree twice.  */
661   if (pointer_set_contains (p_set, stmt))
662     {
663       *walk_subtrees = 0;
664       return NULL_TREE;
665     }
666
667   if (TREE_CODE (stmt) == ADDR_EXPR
668       && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
669     {
670       *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
671       *walk_subtrees = 0;
672     }
673   else if (TREE_CODE (stmt) == RETURN_EXPR
674            && TREE_OPERAND (stmt, 0)
675            && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
676     /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
677     *walk_subtrees = 0;
678   else if (IS_TYPE_OR_DECL_P (stmt))
679     *walk_subtrees = 0;
680
681   /* Due to the way voidify_wrapper_expr is written, we don't get a chance
682      to lower this construct before scanning it, so we need to lower these
683      before doing anything else.  */
684   else if (TREE_CODE (stmt) == CLEANUP_STMT)
685     *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
686                                              : TRY_FINALLY_EXPR,
687                       void_type_node,
688                       CLEANUP_BODY (stmt),
689                       CLEANUP_EXPR (stmt));
690
691   pointer_set_insert (p_set, *stmt_p);
692
693   return NULL;
694 }
695
696 void
697 cp_genericize (tree fndecl)
698 {
699   tree t;
700   struct pointer_set_t *p_set;
701
702   /* Fix up the types of parms passed by invisible reference.  */
703   for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
704     if (TREE_ADDRESSABLE (TREE_TYPE (t)))
705       {
706         /* If a function's arguments are copied to create a thunk,
707            then DECL_BY_REFERENCE will be set -- but the type of the
708            argument will be a pointer type, so we will never get
709            here.  */
710         gcc_assert (!DECL_BY_REFERENCE (t));
711         gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
712         TREE_TYPE (t) = DECL_ARG_TYPE (t);
713         DECL_BY_REFERENCE (t) = 1;
714         TREE_ADDRESSABLE (t) = 0;
715         relayout_decl (t);
716       }
717
718   /* Do the same for the return value.  */
719   if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
720     {
721       t = DECL_RESULT (fndecl);
722       TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
723       DECL_BY_REFERENCE (t) = 1;
724       TREE_ADDRESSABLE (t) = 0;
725       relayout_decl (t);
726     }
727
728   /* If we're a clone, the body is already GIMPLE.  */
729   if (DECL_CLONED_FUNCTION_P (fndecl))
730     return;
731
732   /* We do want to see every occurrence of the parms, so we can't just use
733      walk_tree's hash functionality.  */
734   p_set = pointer_set_create ();
735   walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
736   pointer_set_destroy (p_set);
737
738   /* Do everything else.  */
739   c_genericize (fndecl);
740
741   gcc_assert (bc_label[bc_break] == NULL);
742   gcc_assert (bc_label[bc_continue] == NULL);
743 }
744 \f
745 /* Build code to apply FN to each member of ARG1 and ARG2.  FN may be
746    NULL if there is in fact nothing to do.  ARG2 may be null if FN
747    actually only takes one argument.  */
748
749 static tree
750 cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
751 {
752   tree defparm, parm;
753   int i;
754
755   if (fn == NULL)
756     return NULL;
757
758   defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
759   if (arg2)
760     defparm = TREE_CHAIN (defparm);
761
762   if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
763     {
764       tree inner_type = TREE_TYPE (arg1);
765       tree start1, end1, p1;
766       tree start2 = NULL, p2 = NULL;
767       tree ret = NULL, lab, t;
768
769       start1 = arg1;
770       start2 = arg2;
771       do
772         {
773           inner_type = TREE_TYPE (inner_type);
774           start1 = build4 (ARRAY_REF, inner_type, start1,
775                            size_zero_node, NULL, NULL);
776           if (arg2)
777             start2 = build4 (ARRAY_REF, inner_type, start2,
778                              size_zero_node, NULL, NULL);
779         }
780       while (TREE_CODE (inner_type) == ARRAY_TYPE);
781       start1 = build_fold_addr_expr (start1);
782       if (arg2)
783         start2 = build_fold_addr_expr (start2);
784
785       end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
786       end1 = fold_convert (TREE_TYPE (start1), end1);
787       end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1);
788
789       p1 = create_tmp_var (TREE_TYPE (start1), NULL);
790       t = build2 (MODIFY_EXPR, void_type_node, p1, start1);
791       append_to_statement_list (t, &ret);
792
793       if (arg2)
794         {
795           p2 = create_tmp_var (TREE_TYPE (start2), NULL);
796           t = build2 (MODIFY_EXPR, void_type_node, p2, start2);
797           append_to_statement_list (t, &ret);
798         }
799
800       lab = create_artificial_label ();
801       t = build1 (LABEL_EXPR, void_type_node, lab);
802       append_to_statement_list (t, &ret);
803
804       t = tree_cons (NULL, p1, NULL);
805       if (arg2)
806         t = tree_cons (NULL, p2, t);
807       /* Handle default arguments.  */
808       i = 1 + (arg2 != NULL);
809       for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
810         t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
811                                                   TREE_PURPOSE (parm),
812                                                   fn, i++), t);
813       t = build_call (fn, nreverse (t));
814       append_to_statement_list (t, &ret);
815
816       t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type));
817       t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t);
818       t = build2 (MODIFY_EXPR, void_type_node, p1, t);
819       append_to_statement_list (t, &ret);
820
821       if (arg2)
822         {
823           t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type));
824           t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t);
825           t = build2 (MODIFY_EXPR, void_type_node, p2, t);
826           append_to_statement_list (t, &ret);
827         }
828
829       t = build2 (NE_EXPR, boolean_type_node, p1, end1);
830       t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
831       append_to_statement_list (t, &ret);
832
833       return ret;
834     }
835   else
836     {
837       tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL);
838       if (arg2)
839         t = tree_cons (NULL, build_fold_addr_expr (arg2), t);
840       /* Handle default arguments.  */
841       i = 1 + (arg2 != NULL);
842       for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
843         t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
844                                                   TREE_PURPOSE (parm),
845                                                   fn, i++), t);
846       return build_call (fn, nreverse (t));
847     }
848 }
849
850 /* Return code to initialize DECL with its default constructor, or
851    NULL if there's nothing to do.  */
852
853 tree
854 cxx_omp_clause_default_ctor (tree clause, tree decl)
855 {
856   tree info = CP_OMP_CLAUSE_INFO (clause);
857   tree ret = NULL;
858
859   if (info)
860     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
861
862   return ret;
863 }
864
865 /* Return code to initialize DST with a copy constructor from SRC.  */
866
867 tree
868 cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
869 {
870   tree info = CP_OMP_CLAUSE_INFO (clause);
871   tree ret = NULL;
872
873   if (info)
874     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
875   if (ret == NULL)
876     ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
877
878   return ret;
879 }
880
881 /* Similarly, except use an assignment operator instead.  */
882
883 tree
884 cxx_omp_clause_assign_op (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, 2), dst, src);
891   if (ret == NULL)
892     ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
893
894   return ret;
895 }
896
897 /* Return code to destroy DECL.  */
898
899 tree
900 cxx_omp_clause_dtor (tree clause, tree decl)
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, 1), decl, NULL);
907
908   return ret;
909 }
910
911 /* True if OpenMP should privatize what this DECL points to rather
912    than the DECL itself.  */
913
914 bool
915 cxx_omp_privatize_by_reference (tree decl)
916 {
917   return TREE_CODE (decl) == RESULT_DECL && DECL_BY_REFERENCE (decl);
918 }