xref: /freebsd-12.1/contrib/gcc/cp/cp-gimplify.c (revision 5bfc7db4)
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 <[email protected]>
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
191 /* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
gimplify_cp_loop(tree cond,tree body,tree incr,tree attrs,bool cond_is_first,tree inner_foreach)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
gimplify_for_stmt(tree * stmt_p,tree * pre_p)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
gimplify_while_stmt(tree * stmt_p)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
gimplify_do_stmt(tree * stmt_p)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
gimplify_switch_stmt(tree * stmt_p)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
cp_gimplify_omp_for(tree * expr_p)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
gimplify_expr_stmt(tree * stmt_p)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
cp_gimplify_init_expr(tree * expr_p,tree * pre_p,tree * post_p)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
gimplify_must_not_throw_expr(tree * expr_p,tree * pre_p)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
cp_gimplify_expr(tree * expr_p,tree * pre_p,tree * post_p)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
is_invisiref_parm(tree t)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
cxx_int_tree_map_eq(const void * va,const void * vb)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
cxx_int_tree_map_hash(const void * item)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
cp_genericize_r(tree * stmt_p,int * walk_subtrees,void * data)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
cp_genericize(tree fndecl)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 
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
cxx_omp_clause_apply_fn(tree fn,tree arg1,tree arg2)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
cxx_omp_clause_default_ctor(tree clause,tree decl)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
cxx_omp_clause_copy_ctor(tree clause,tree dst,tree src)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
cxx_omp_clause_assign_op(tree clause,tree dst,tree src)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
cxx_omp_clause_dtor(tree clause,tree decl)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
cxx_omp_privatize_by_reference(tree decl)970 cxx_omp_privatize_by_reference (tree decl)
971 {
972   return is_invisiref_parm (decl);
973 }
974