xref: /openbsd/gnu/gcc/gcc/cp/cp-gimplify.c (revision 404b540a)
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
begin_bc_block(enum bc_t bc)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
finish_bc_block(enum bc_t bc,tree label,tree body)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
build_bc_goto(enum bc_t bc)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
genericize_try_block(tree * stmt_p)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
genericize_catch_block(tree * stmt_p)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
genericize_eh_spec_block(tree * stmt_p)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
gimplify_if_stmt(tree * stmt_p)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
gimplify_cp_loop(tree cond,tree body,tree incr,bool cond_is_first)191 gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
192 {
193   tree top, entry, exit, cont_block, break_block, stmt_list, t;
194   location_t stmt_locus;
195 
196   stmt_locus = input_location;
197   stmt_list = NULL_TREE;
198   entry = NULL_TREE;
199 
200   break_block = begin_bc_block (bc_break);
201   cont_block = begin_bc_block (bc_continue);
202 
203   /* If condition is zero don't generate a loop construct.  */
204   if (cond && integer_zerop (cond))
205     {
206       top = NULL_TREE;
207       exit = NULL_TREE;
208       if (cond_is_first)
209 	{
210 	  t = build_bc_goto (bc_break);
211 	  append_to_statement_list (t, &stmt_list);
212 	}
213     }
214   else
215     {
216       /* If we use a LOOP_EXPR here, we have to feed the whole thing
217 	 back through the main gimplifier to lower it.  Given that we
218 	 have to gimplify the loop body NOW so that we can resolve
219 	 break/continue stmts, seems easier to just expand to gotos.  */
220       top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
221 
222       /* If we have an exit condition, then we build an IF with gotos either
223 	 out of the loop, or to the top of it.  If there's no exit condition,
224 	 then we just build a jump back to the top.  */
225       exit = build_and_jump (&LABEL_EXPR_LABEL (top));
226       if (cond && !integer_nonzerop (cond))
227 	{
228 	  t = build_bc_goto (bc_break);
229 	  exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
230 	  gimplify_stmt (&exit);
231 
232 	  if (cond_is_first)
233 	    {
234 	      if (incr)
235 		{
236 		  entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
237 		  t = build_and_jump (&LABEL_EXPR_LABEL (entry));
238 		}
239 	      else
240 		t = build_bc_goto (bc_continue);
241 	      append_to_statement_list (t, &stmt_list);
242 	    }
243 	}
244     }
245 
246   gimplify_stmt (&body);
247   gimplify_stmt (&incr);
248 
249   body = finish_bc_block (bc_continue, cont_block, body);
250 
251   append_to_statement_list (top, &stmt_list);
252   append_to_statement_list (body, &stmt_list);
253   append_to_statement_list (incr, &stmt_list);
254   append_to_statement_list (entry, &stmt_list);
255   append_to_statement_list (exit, &stmt_list);
256 
257   annotate_all_with_locus (&stmt_list, stmt_locus);
258 
259   return finish_bc_block (bc_break, break_block, stmt_list);
260 }
261 
262 /* Gimplify a FOR_STMT node.  Move the stuff in the for-init-stmt into the
263    prequeue and hand off to gimplify_cp_loop.  */
264 
265 static void
gimplify_for_stmt(tree * stmt_p,tree * pre_p)266 gimplify_for_stmt (tree *stmt_p, tree *pre_p)
267 {
268   tree stmt = *stmt_p;
269 
270   if (FOR_INIT_STMT (stmt))
271     gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
272 
273   *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
274 			      FOR_EXPR (stmt), 1);
275 }
276 
277 /* Gimplify a WHILE_STMT node.  */
278 
279 static void
gimplify_while_stmt(tree * stmt_p)280 gimplify_while_stmt (tree *stmt_p)
281 {
282   tree stmt = *stmt_p;
283   *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
284 			      NULL_TREE, 1);
285 }
286 
287 /* Gimplify a DO_STMT node.  */
288 
289 static void
gimplify_do_stmt(tree * stmt_p)290 gimplify_do_stmt (tree *stmt_p)
291 {
292   tree stmt = *stmt_p;
293   *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
294 			      NULL_TREE, 0);
295 }
296 
297 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
298 
299 static void
gimplify_switch_stmt(tree * stmt_p)300 gimplify_switch_stmt (tree *stmt_p)
301 {
302   tree stmt = *stmt_p;
303   tree break_block, body;
304   location_t stmt_locus = input_location;
305 
306   break_block = begin_bc_block (bc_break);
307 
308   body = SWITCH_STMT_BODY (stmt);
309   if (!body)
310     body = build_empty_stmt ();
311 
312   *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
313 		    SWITCH_STMT_COND (stmt), body, NULL_TREE);
314   SET_EXPR_LOCATION (*stmt_p, stmt_locus);
315   gimplify_stmt (stmt_p);
316 
317   *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p);
318 }
319 
320 /* Hook into the middle of gimplifying an OMP_FOR node.  This is required
321    in order to properly gimplify CONTINUE statements.  Here we merely
322    manage the continue stack; the rest of the job is performed by the
323    regular gimplifier.  */
324 
325 static enum gimplify_status
cp_gimplify_omp_for(tree * expr_p)326 cp_gimplify_omp_for (tree *expr_p)
327 {
328   tree for_stmt = *expr_p;
329   tree cont_block;
330 
331   /* Protect ourselves from recursion.  */
332   if (OMP_FOR_GIMPLIFYING_P (for_stmt))
333     return GS_UNHANDLED;
334   OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
335 
336   /* Note that while technically the continue label is enabled too soon
337      here, we should have already diagnosed invalid continues nested within
338      statement expressions within the INIT, COND, or INCR expressions.  */
339   cont_block = begin_bc_block (bc_continue);
340 
341   gimplify_stmt (expr_p);
342 
343   OMP_FOR_BODY (for_stmt)
344     = finish_bc_block (bc_continue, cont_block, OMP_FOR_BODY (for_stmt));
345   OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
346 
347   return GS_ALL_DONE;
348 }
349 
350 /*  Gimplify an EXPR_STMT node.  */
351 
352 static void
gimplify_expr_stmt(tree * stmt_p)353 gimplify_expr_stmt (tree *stmt_p)
354 {
355   tree stmt = EXPR_STMT_EXPR (*stmt_p);
356 
357   if (stmt == error_mark_node)
358     stmt = NULL;
359 
360   /* Gimplification of a statement expression will nullify the
361      statement if all its side effects are moved to *PRE_P and *POST_P.
362 
363      In this case we will not want to emit the gimplified statement.
364      However, we may still want to emit a warning, so we do that before
365      gimplification.  */
366   if (stmt && (extra_warnings || warn_unused_value))
367     {
368       if (!TREE_SIDE_EFFECTS (stmt))
369 	{
370 	  if (!IS_EMPTY_STMT (stmt)
371 	      && !VOID_TYPE_P (TREE_TYPE (stmt))
372 	      && !TREE_NO_WARNING (stmt))
373 	    warning (OPT_Wextra, "statement with no effect");
374 	}
375       else if (warn_unused_value)
376 	warn_if_unused_value (stmt, input_location);
377     }
378 
379   if (stmt == NULL_TREE)
380     stmt = alloc_stmt_list ();
381 
382   *stmt_p = stmt;
383 }
384 
385 /* Gimplify initialization from an AGGR_INIT_EXPR.  */
386 
387 static void
cp_gimplify_init_expr(tree * expr_p,tree * pre_p,tree * post_p)388 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
389 {
390   tree from = TREE_OPERAND (*expr_p, 1);
391   tree to = TREE_OPERAND (*expr_p, 0);
392   tree sub;
393 
394   /* 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 
425 static void
gimplify_must_not_throw_expr(tree * expr_p,tree * pre_p)426 gimplify_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 
448 int
cp_gimplify_expr(tree * expr_p,tree * pre_p,tree * post_p)449 cp_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 
594 static inline bool
is_invisiref_parm(tree t)595 is_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 
603 int
cxx_int_tree_map_eq(const void * va,const void * vb)604 cxx_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 
613 unsigned int
cxx_int_tree_map_hash(const void * item)614 cxx_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 
622 static tree
cp_genericize_r(tree * stmt_p,int * walk_subtrees,void * data)623 cp_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 
712 void
cp_genericize(tree fndecl)713 cp_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 
765 static tree
cxx_omp_clause_apply_fn(tree fn,tree arg1,tree arg2)766 cxx_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 
869 tree
cxx_omp_clause_default_ctor(tree clause,tree decl)870 cxx_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 
883 tree
cxx_omp_clause_copy_ctor(tree clause,tree dst,tree src)884 cxx_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 
899 tree
cxx_omp_clause_assign_op(tree clause,tree dst,tree src)900 cxx_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 
915 tree
cxx_omp_clause_dtor(tree clause,tree decl)916 cxx_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 
930 bool
cxx_omp_privatize_by_reference(tree decl)931 cxx_omp_privatize_by_reference (tree decl)
932 {
933   return is_invisiref_parm (decl);
934 }
935