]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - contrib/gcc/cp/cp-gimplify.c
Copy stable/9 to releng/9.3 as part of the 9.3-RELEASE cycle.
[FreeBSD/releng/9.3.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 /* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
192 gimplify_cp_loop (tree cond, tree body, tree incr, tree attrs,
193                   bool cond_is_first, tree inner_foreach)
194 /* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
195 {
196   tree top, entry, exit, cont_block, break_block, stmt_list, t;
197   location_t stmt_locus;
198
199   stmt_locus = input_location;
200   stmt_list = NULL_TREE;
201   entry = NULL_TREE;
202
203   break_block = begin_bc_block (bc_break);
204   cont_block = begin_bc_block (bc_continue);
205
206   /* If condition is zero don't generate a loop construct.  */
207   if (cond && integer_zerop (cond))
208     {
209       top = NULL_TREE;
210       exit = NULL_TREE;
211       if (cond_is_first)
212         {
213           t = build_bc_goto (bc_break);
214           append_to_statement_list (t, &stmt_list);
215         }
216     }
217   else
218     {
219       /* If we use a LOOP_EXPR here, we have to feed the whole thing
220          back through the main gimplifier to lower it.  Given that we
221          have to gimplify the loop body NOW so that we can resolve
222          break/continue stmts, seems easier to just expand to gotos.  */
223       top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
224
225       /* If we have an exit condition, then we build an IF with gotos either
226          out of the loop, or to the top of it.  If there's no exit condition,
227          then we just build a jump back to the top.  */
228       exit = build_and_jump (&LABEL_EXPR_LABEL (top));
229 /* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
230
231       /* Add the attributes to the 'top' label.  */
232       decl_attributes (&LABEL_EXPR_LABEL (top), attrs, 0);
233
234 /* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
235       if (cond && !integer_nonzerop (cond))
236         {
237           t = build_bc_goto (bc_break);
238           exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
239           gimplify_stmt (&exit);
240
241           if (cond_is_first)
242             {
243               if (incr)
244                 {
245                   entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
246                   t = build_and_jump (&LABEL_EXPR_LABEL (entry));
247                 }
248               else
249                 t = build_bc_goto (bc_continue);
250               append_to_statement_list (t, &stmt_list);
251             }
252         }
253     }
254
255   gimplify_stmt (&body);
256   gimplify_stmt (&incr);
257
258   body = finish_bc_block (bc_continue, cont_block, body);
259
260   append_to_statement_list (top, &stmt_list);
261   append_to_statement_list (body, &stmt_list);
262   append_to_statement_list (incr, &stmt_list);
263   append_to_statement_list (entry, &stmt_list);
264   append_to_statement_list (exit, &stmt_list);
265
266   annotate_all_with_locus (&stmt_list, stmt_locus);
267
268   return finish_bc_block (bc_break, break_block, stmt_list);
269 }
270
271 /* Gimplify a FOR_STMT node.  Move the stuff in the for-init-stmt into the
272    prequeue and hand off to gimplify_cp_loop.  */
273
274 static void
275 gimplify_for_stmt (tree *stmt_p, tree *pre_p)
276 {
277   tree stmt = *stmt_p;
278
279   if (FOR_INIT_STMT (stmt))
280     gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
281
282 /* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
283   *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
284                               FOR_EXPR (stmt), FOR_ATTRIBUTES (stmt), 1,
285                               NULL_TREE);
286 /* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
287 }
288
289 /* Gimplify a WHILE_STMT node.  */
290
291 static void
292 gimplify_while_stmt (tree *stmt_p)
293 {
294   tree stmt = *stmt_p;
295 /* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
296   *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
297                               NULL_TREE, WHILE_ATTRIBUTES (stmt), 1,
298                               NULL_TREE);
299 /* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
300 }
301
302 /* Gimplify a DO_STMT node.  */
303
304 static void
305 gimplify_do_stmt (tree *stmt_p)
306 {
307   tree stmt = *stmt_p;
308 /* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
309   *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
310                               NULL_TREE, DO_ATTRIBUTES (stmt), 0,
311                               DO_FOREACH (stmt));
312 /* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
313 }
314
315 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
316
317 static void
318 gimplify_switch_stmt (tree *stmt_p)
319 {
320   tree stmt = *stmt_p;
321   tree break_block, body;
322   location_t stmt_locus = input_location;
323
324   break_block = begin_bc_block (bc_break);
325
326   body = SWITCH_STMT_BODY (stmt);
327   if (!body)
328     body = build_empty_stmt ();
329
330   *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
331                     SWITCH_STMT_COND (stmt), body, NULL_TREE);
332   SET_EXPR_LOCATION (*stmt_p, stmt_locus);
333   gimplify_stmt (stmt_p);
334
335   *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p);
336 }
337
338 /* Hook into the middle of gimplifying an OMP_FOR node.  This is required
339    in order to properly gimplify CONTINUE statements.  Here we merely
340    manage the continue stack; the rest of the job is performed by the
341    regular gimplifier.  */
342
343 static enum gimplify_status
344 cp_gimplify_omp_for (tree *expr_p)
345 {
346   tree for_stmt = *expr_p;
347   tree cont_block;
348
349   /* Protect ourselves from recursion.  */
350   if (OMP_FOR_GIMPLIFYING_P (for_stmt))
351     return GS_UNHANDLED;
352   OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
353
354   /* Note that while technically the continue label is enabled too soon
355      here, we should have already diagnosed invalid continues nested within
356      statement expressions within the INIT, COND, or INCR expressions.  */
357   cont_block = begin_bc_block (bc_continue);
358
359   gimplify_stmt (expr_p);
360
361   OMP_FOR_BODY (for_stmt)
362     = finish_bc_block (bc_continue, cont_block, OMP_FOR_BODY (for_stmt));
363   OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
364
365   return GS_ALL_DONE;
366 }
367
368 /*  Gimplify an EXPR_STMT node.  */
369
370 static void
371 gimplify_expr_stmt (tree *stmt_p)
372 {
373   tree stmt = EXPR_STMT_EXPR (*stmt_p);
374
375   if (stmt == error_mark_node)
376     stmt = NULL;
377
378   /* Gimplification of a statement expression will nullify the
379      statement if all its side effects are moved to *PRE_P and *POST_P.
380
381      In this case we will not want to emit the gimplified statement.
382      However, we may still want to emit a warning, so we do that before
383      gimplification.  */
384   if (stmt && (extra_warnings || warn_unused_value))
385     {
386       if (!TREE_SIDE_EFFECTS (stmt))
387         {
388           if (!IS_EMPTY_STMT (stmt)
389               && !VOID_TYPE_P (TREE_TYPE (stmt))
390               && !TREE_NO_WARNING (stmt))
391             warning (OPT_Wextra, "statement with no effect");
392         }
393       else if (warn_unused_value)
394         warn_if_unused_value (stmt, input_location);
395     }
396
397   if (stmt == NULL_TREE)
398     stmt = alloc_stmt_list ();
399
400   *stmt_p = stmt;
401 }
402
403 /* Gimplify initialization from an AGGR_INIT_EXPR.  */
404
405 static void
406 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
407 {
408   tree from = TREE_OPERAND (*expr_p, 1);
409   tree to = TREE_OPERAND (*expr_p, 0);
410   tree sub;
411
412   /* What about code that pulls out the temp and uses it elsewhere?  I
413      think that such code never uses the TARGET_EXPR as an initializer.  If
414      I'm wrong, we'll abort because the temp won't have any RTL.  In that
415      case, I guess we'll need to replace references somehow.  */
416   if (TREE_CODE (from) == TARGET_EXPR)
417     from = TARGET_EXPR_INITIAL (from);
418
419   /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
420      inside the TARGET_EXPR.  */
421   sub = expr_last (from);
422
423   /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
424      replace the slot operand with our target.
425
426      Should we add a target parm to gimplify_expr instead?  No, as in this
427      case we want to replace the INIT_EXPR.  */
428   if (TREE_CODE (sub) == AGGR_INIT_EXPR)
429     {
430       gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
431       TREE_OPERAND (sub, 2) = to;
432       *expr_p = from;
433
434       /* The initialization is now a side-effect, so the container can
435          become void.  */
436       if (from != sub)
437         TREE_TYPE (from) = void_type_node;
438     }
439 }
440
441 /* Gimplify a MUST_NOT_THROW_EXPR.  */
442
443 static void
444 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
445 {
446   tree stmt = *expr_p;
447   tree temp = voidify_wrapper_expr (stmt, NULL);
448   tree body = TREE_OPERAND (stmt, 0);
449
450   gimplify_stmt (&body);
451
452   stmt = gimple_build_eh_filter (body, NULL_TREE,
453                                  build_call (terminate_node, NULL_TREE));
454
455   if (temp)
456     {
457       append_to_statement_list (stmt, pre_p);
458       *expr_p = temp;
459     }
460   else
461     *expr_p = stmt;
462 }
463
464 /* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
465
466 int
467 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
468 {
469   int saved_stmts_are_full_exprs_p = 0;
470   enum tree_code code = TREE_CODE (*expr_p);
471   enum gimplify_status ret;
472
473   if (STATEMENT_CODE_P (code))
474     {
475       saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
476       current_stmt_tree ()->stmts_are_full_exprs_p
477         = STMT_IS_FULL_EXPR_P (*expr_p);
478     }
479
480   switch (code)
481     {
482     case PTRMEM_CST:
483       *expr_p = cplus_expand_constant (*expr_p);
484       ret = GS_OK;
485       break;
486
487     case AGGR_INIT_EXPR:
488       simplify_aggr_init_expr (expr_p);
489       ret = GS_OK;
490       break;
491
492     case THROW_EXPR:
493       /* FIXME communicate throw type to backend, probably by moving
494          THROW_EXPR into ../tree.def.  */
495       *expr_p = TREE_OPERAND (*expr_p, 0);
496       ret = GS_OK;
497       break;
498
499     case MUST_NOT_THROW_EXPR:
500       gimplify_must_not_throw_expr (expr_p, pre_p);
501       ret = GS_OK;
502       break;
503
504       /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
505          LHS of an assignment might also be involved in the RHS, as in bug
506          25979.  */
507     case INIT_EXPR:
508       cp_gimplify_init_expr (expr_p, pre_p, post_p);
509       ret = GS_OK;
510       break;
511
512     case EMPTY_CLASS_EXPR:
513       /* We create an empty CONSTRUCTOR with RECORD_TYPE.  */
514       *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
515       ret = GS_OK;
516       break;
517
518     case BASELINK:
519       *expr_p = BASELINK_FUNCTIONS (*expr_p);
520       ret = GS_OK;
521       break;
522
523     case TRY_BLOCK:
524       genericize_try_block (expr_p);
525       ret = GS_OK;
526       break;
527
528     case HANDLER:
529       genericize_catch_block (expr_p);
530       ret = GS_OK;
531       break;
532
533     case EH_SPEC_BLOCK:
534       genericize_eh_spec_block (expr_p);
535       ret = GS_OK;
536       break;
537
538     case USING_STMT:
539       /* Just ignore for now.  Eventually we will want to pass this on to
540          the debugger.  */
541       *expr_p = build_empty_stmt ();
542       ret = GS_ALL_DONE;
543       break;
544
545     case IF_STMT:
546       gimplify_if_stmt (expr_p);
547       ret = GS_OK;
548       break;
549
550     case FOR_STMT:
551       gimplify_for_stmt (expr_p, pre_p);
552       ret = GS_ALL_DONE;
553       break;
554
555     case WHILE_STMT:
556       gimplify_while_stmt (expr_p);
557       ret = GS_ALL_DONE;
558       break;
559
560     case DO_STMT:
561       gimplify_do_stmt (expr_p);
562       ret = GS_ALL_DONE;
563       break;
564
565     case SWITCH_STMT:
566       gimplify_switch_stmt (expr_p);
567       ret = GS_ALL_DONE;
568       break;
569
570     case OMP_FOR:
571       ret = cp_gimplify_omp_for (expr_p);
572       break;
573
574     case CONTINUE_STMT:
575       *expr_p = build_bc_goto (bc_continue);
576       ret = GS_ALL_DONE;
577       break;
578
579     case BREAK_STMT:
580       *expr_p = build_bc_goto (bc_break);
581       ret = GS_ALL_DONE;
582       break;
583
584     case EXPR_STMT:
585       gimplify_expr_stmt (expr_p);
586       ret = GS_OK;
587       break;
588
589     case UNARY_PLUS_EXPR:
590       {
591         tree arg = TREE_OPERAND (*expr_p, 0);
592         tree type = TREE_TYPE (*expr_p);
593         *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
594                                             : arg;
595         ret = GS_OK;
596       }
597       break;
598
599     default:
600       ret = c_gimplify_expr (expr_p, pre_p, post_p);
601       break;
602     }
603
604   /* Restore saved state.  */
605   if (STATEMENT_CODE_P (code))
606     current_stmt_tree ()->stmts_are_full_exprs_p
607       = saved_stmts_are_full_exprs_p;
608
609   return ret;
610 }
611
612 static inline bool
613 is_invisiref_parm (tree t)
614 {
615   return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
616           && DECL_BY_REFERENCE (t));
617 }
618
619 /* Return true if the uid in both int tree maps are equal.  */
620
621 int
622 cxx_int_tree_map_eq (const void *va, const void *vb)
623 {
624   const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
625   const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
626   return (a->uid == b->uid);
627 }
628
629 /* Hash a UID in a cxx_int_tree_map.  */
630
631 unsigned int
632 cxx_int_tree_map_hash (const void *item)
633 {
634   return ((const struct cxx_int_tree_map *)item)->uid;
635 }
636
637 /* Perform any pre-gimplification lowering of C++ front end trees to
638    GENERIC.  */
639
640 static tree
641 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
642 {
643   tree stmt = *stmt_p;
644   struct pointer_set_t *p_set = (struct pointer_set_t*) data;
645
646   if (is_invisiref_parm (stmt)
647       /* Don't dereference parms in a thunk, pass the references through. */
648       && !(DECL_THUNK_P (current_function_decl)
649            && TREE_CODE (stmt) == PARM_DECL))
650     {
651       *stmt_p = convert_from_reference (stmt);
652       *walk_subtrees = 0;
653       return NULL;
654     }
655
656   /* Map block scope extern declarations to visible declarations with the
657      same name and type in outer scopes if any.  */
658   if (cp_function_chain->extern_decl_map
659       && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
660       && DECL_EXTERNAL (stmt))
661     {
662       struct cxx_int_tree_map *h, in;
663       in.uid = DECL_UID (stmt);
664       h = (struct cxx_int_tree_map *)
665           htab_find_with_hash (cp_function_chain->extern_decl_map,
666                                &in, in.uid);
667       if (h)
668         {
669           *stmt_p = h->to;
670           *walk_subtrees = 0;
671           return NULL;
672         }
673     }
674
675   /* Other than invisiref parms, don't walk the same tree twice.  */
676   if (pointer_set_contains (p_set, stmt))
677     {
678       *walk_subtrees = 0;
679       return NULL_TREE;
680     }
681
682   if (TREE_CODE (stmt) == ADDR_EXPR
683       && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
684     {
685       *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
686       *walk_subtrees = 0;
687     }
688   else if (TREE_CODE (stmt) == RETURN_EXPR
689            && TREE_OPERAND (stmt, 0)
690            && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
691     /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
692     *walk_subtrees = 0;
693   else if (TREE_CODE (stmt) == OMP_CLAUSE)
694     switch (OMP_CLAUSE_CODE (stmt))
695       {
696       case OMP_CLAUSE_PRIVATE:
697       case OMP_CLAUSE_SHARED:
698       case OMP_CLAUSE_FIRSTPRIVATE:
699       case OMP_CLAUSE_LASTPRIVATE:
700       case OMP_CLAUSE_COPYIN:
701       case OMP_CLAUSE_COPYPRIVATE:
702         /* Don't dereference an invisiref in OpenMP clauses.  */
703         if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
704           *walk_subtrees = 0;
705         break;
706       case OMP_CLAUSE_REDUCTION:
707         gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
708         break;
709       default:
710         break;
711       }
712   else if (IS_TYPE_OR_DECL_P (stmt))
713     *walk_subtrees = 0;
714
715   /* Due to the way voidify_wrapper_expr is written, we don't get a chance
716      to lower this construct before scanning it, so we need to lower these
717      before doing anything else.  */
718   else if (TREE_CODE (stmt) == CLEANUP_STMT)
719     *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
720                                              : TRY_FINALLY_EXPR,
721                       void_type_node,
722                       CLEANUP_BODY (stmt),
723                       CLEANUP_EXPR (stmt));
724
725   pointer_set_insert (p_set, *stmt_p);
726
727   return NULL;
728 }
729
730 void
731 cp_genericize (tree fndecl)
732 {
733   tree t;
734   struct pointer_set_t *p_set;
735
736   /* Fix up the types of parms passed by invisible reference.  */
737   for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
738     if (TREE_ADDRESSABLE (TREE_TYPE (t)))
739       {
740         /* If a function's arguments are copied to create a thunk,
741            then DECL_BY_REFERENCE will be set -- but the type of the
742            argument will be a pointer type, so we will never get
743            here.  */
744         gcc_assert (!DECL_BY_REFERENCE (t));
745         gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
746         TREE_TYPE (t) = DECL_ARG_TYPE (t);
747         DECL_BY_REFERENCE (t) = 1;
748         TREE_ADDRESSABLE (t) = 0;
749         relayout_decl (t);
750       }
751
752   /* Do the same for the return value.  */
753   if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
754     {
755       t = DECL_RESULT (fndecl);
756       TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
757       DECL_BY_REFERENCE (t) = 1;
758       TREE_ADDRESSABLE (t) = 0;
759       relayout_decl (t);
760     }
761
762   /* If we're a clone, the body is already GIMPLE.  */
763   if (DECL_CLONED_FUNCTION_P (fndecl))
764     return;
765
766   /* We do want to see every occurrence of the parms, so we can't just use
767      walk_tree's hash functionality.  */
768   p_set = pointer_set_create ();
769   walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
770   pointer_set_destroy (p_set);
771
772   /* Do everything else.  */
773   c_genericize (fndecl);
774
775   gcc_assert (bc_label[bc_break] == NULL);
776   gcc_assert (bc_label[bc_continue] == NULL);
777 }
778 \f
779 /* Build code to apply FN to each member of ARG1 and ARG2.  FN may be
780    NULL if there is in fact nothing to do.  ARG2 may be null if FN
781    actually only takes one argument.  */
782
783 static tree
784 cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
785 {
786   tree defparm, parm;
787   int i;
788
789   if (fn == NULL)
790     return NULL;
791
792   defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
793   if (arg2)
794     defparm = TREE_CHAIN (defparm);
795
796   if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
797     {
798       tree inner_type = TREE_TYPE (arg1);
799       tree start1, end1, p1;
800       tree start2 = NULL, p2 = NULL;
801       tree ret = NULL, lab, t;
802
803       start1 = arg1;
804       start2 = arg2;
805       do
806         {
807           inner_type = TREE_TYPE (inner_type);
808           start1 = build4 (ARRAY_REF, inner_type, start1,
809                            size_zero_node, NULL, NULL);
810           if (arg2)
811             start2 = build4 (ARRAY_REF, inner_type, start2,
812                              size_zero_node, NULL, NULL);
813         }
814       while (TREE_CODE (inner_type) == ARRAY_TYPE);
815       start1 = build_fold_addr_expr (start1);
816       if (arg2)
817         start2 = build_fold_addr_expr (start2);
818
819       end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
820       end1 = fold_convert (TREE_TYPE (start1), end1);
821       end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1);
822
823       p1 = create_tmp_var (TREE_TYPE (start1), NULL);
824       t = build2 (MODIFY_EXPR, void_type_node, p1, start1);
825       append_to_statement_list (t, &ret);
826
827       if (arg2)
828         {
829           p2 = create_tmp_var (TREE_TYPE (start2), NULL);
830           t = build2 (MODIFY_EXPR, void_type_node, p2, start2);
831           append_to_statement_list (t, &ret);
832         }
833
834       lab = create_artificial_label ();
835       t = build1 (LABEL_EXPR, void_type_node, lab);
836       append_to_statement_list (t, &ret);
837
838       t = tree_cons (NULL, p1, NULL);
839       if (arg2)
840         t = tree_cons (NULL, p2, t);
841       /* Handle default arguments.  */
842       i = 1 + (arg2 != NULL);
843       for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
844         t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
845                                                   TREE_PURPOSE (parm),
846                                                   fn, i++), t);
847       t = build_call (fn, nreverse (t));
848       append_to_statement_list (t, &ret);
849
850       t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type));
851       t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t);
852       t = build2 (MODIFY_EXPR, void_type_node, p1, t);
853       append_to_statement_list (t, &ret);
854
855       if (arg2)
856         {
857           t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type));
858           t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t);
859           t = build2 (MODIFY_EXPR, void_type_node, p2, t);
860           append_to_statement_list (t, &ret);
861         }
862
863       t = build2 (NE_EXPR, boolean_type_node, p1, end1);
864       t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
865       append_to_statement_list (t, &ret);
866
867       return ret;
868     }
869   else
870     {
871       tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL);
872       if (arg2)
873         t = tree_cons (NULL, build_fold_addr_expr (arg2), t);
874       /* Handle default arguments.  */
875       i = 1 + (arg2 != NULL);
876       for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
877         t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
878                                                   TREE_PURPOSE (parm),
879                                                   fn, i++), t);
880       return build_call (fn, nreverse (t));
881     }
882 }
883
884 /* Return code to initialize DECL with its default constructor, or
885    NULL if there's nothing to do.  */
886
887 tree
888 cxx_omp_clause_default_ctor (tree clause, tree decl)
889 {
890   tree info = CP_OMP_CLAUSE_INFO (clause);
891   tree ret = NULL;
892
893   if (info)
894     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
895
896   return ret;
897 }
898
899 /* Return code to initialize DST with a copy constructor from SRC.  */
900
901 tree
902 cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
903 {
904   tree info = CP_OMP_CLAUSE_INFO (clause);
905   tree ret = NULL;
906
907   if (info)
908     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
909   if (ret == NULL)
910     ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
911
912   return ret;
913 }
914
915 /* Similarly, except use an assignment operator instead.  */
916
917 tree
918 cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
919 {
920   tree info = CP_OMP_CLAUSE_INFO (clause);
921   tree ret = NULL;
922
923   if (info)
924     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
925   if (ret == NULL)
926     ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
927
928   return ret;
929 }
930
931 /* Return code to destroy DECL.  */
932
933 tree
934 cxx_omp_clause_dtor (tree clause, tree decl)
935 {
936   tree info = CP_OMP_CLAUSE_INFO (clause);
937   tree ret = NULL;
938
939   if (info)
940     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
941
942   return ret;
943 }
944
945 /* True if OpenMP should privatize what this DECL points to rather
946    than the DECL itself.  */
947
948 bool
949 cxx_omp_privatize_by_reference (tree decl)
950 {
951   return is_invisiref_parm (decl);
952 }