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
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING.  If not, write to the Free
20Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2102110-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
38enum 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.  */
42static 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
49static tree
50begin_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
65static tree
66finish_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
89static tree
90build_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
111static void
112genericize_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
129static void
130genericize_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
144static void
145genericize_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
159static void
160gimplify_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
190static tree
191/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
192gimplify_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
295static void
296gimplify_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
312static void
313gimplify_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
325static void
326gimplify_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
338static void
339gimplify_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
364static enum gimplify_status
365cp_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
391static void
392gimplify_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
426static void
427cp_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
464static void
465gimplify_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
487int
488cp_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
633static inline bool
634is_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
642int
643cxx_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
652unsigned int
653cxx_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
661static tree
662cp_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
751void
752cp_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
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
804static tree
805cxx_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
908tree
909cxx_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
922tree
923cxx_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
938tree
939cxx_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
954tree
955cxx_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
969bool
970cxx_omp_privatize_by_reference (tree decl)
971{
972  return is_invisiref_parm (decl);
973}
974