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