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