OSDN Git Service

PR c++/39109
[pf3gnuchains/gcc-fork.git] / gcc / cp / cp-gimplify.c
1 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
2
3    Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
4    Free Software Foundation, Inc.
5    Contributed by Jason Merrill <jason@redhat.com>
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3.  If not see
21 <http://www.gnu.org/licenses/>.  */
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-iterator.h"
32 #include "gimple.h"
33 #include "hashtab.h"
34 #include "pointer-set.h"
35 #include "flags.h"
36
37 /* Local declarations.  */
38
39 enum bc_t { bc_break = 0, bc_continue = 1 };
40
41 /* Stack of labels which are targets for "break" or "continue",
42    linked through TREE_CHAIN.  */
43 static tree bc_label[2];
44
45 /* Begin a scope which can be exited by a break or continue statement.  BC
46    indicates which.
47
48    Just creates a label and pushes it into the current context.  */
49
50 static tree
51 begin_bc_block (enum bc_t bc)
52 {
53   tree label = create_artificial_label ();
54   TREE_CHAIN (label) = bc_label[bc];
55   bc_label[bc] = label;
56   return label;
57 }
58
59 /* Finish a scope which can be exited by a break or continue statement.
60    LABEL was returned from the most recent call to begin_bc_block.  BODY is
61    an expression for the contents of the scope.
62
63    If we saw a break (or continue) in the scope, append a LABEL_EXPR to
64    body.  Otherwise, just forget the label.  */
65
66 static gimple_seq
67 finish_bc_block (enum bc_t bc, tree label, gimple_seq body)
68 {
69   gcc_assert (label == bc_label[bc]);
70
71   if (TREE_USED (label))
72     {
73       gimple_seq_add_stmt (&body, gimple_build_label (label));
74     }
75
76   bc_label[bc] = TREE_CHAIN (label);
77   TREE_CHAIN (label) = NULL_TREE;
78   return body;
79 }
80
81 /* Get the LABEL_EXPR to represent a break or continue statement
82    in the current block scope.  BC indicates which.  */
83
84 static tree
85 get_bc_label (enum bc_t bc)
86 {
87   tree label = bc_label[bc];
88
89   if (label == NULL_TREE)
90     {
91       if (bc == bc_break)
92         error ("break statement not within loop or switch");
93       else
94         error ("continue statement not within loop or switch");
95
96       return NULL_TREE;
97     }
98
99   /* Mark the label used for finish_bc_block.  */
100   TREE_USED (label) = 1;
101   return label;
102 }
103
104 /* Genericize a TRY_BLOCK.  */
105
106 static void
107 genericize_try_block (tree *stmt_p)
108 {
109   tree body = TRY_STMTS (*stmt_p);
110   tree cleanup = TRY_HANDLERS (*stmt_p);
111
112   *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
113 }
114
115 /* Genericize a HANDLER by converting to a CATCH_EXPR.  */
116
117 static void
118 genericize_catch_block (tree *stmt_p)
119 {
120   tree type = HANDLER_TYPE (*stmt_p);
121   tree body = HANDLER_BODY (*stmt_p);
122
123   /* FIXME should the caught type go in TREE_TYPE?  */
124   *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
125 }
126
127 /* A terser interface for building a representation of an exception
128    specification.  */
129
130 static tree
131 build_gimple_eh_filter_tree (tree body, tree allowed, tree failure)
132 {
133   tree t;
134
135   /* FIXME should the allowed types go in TREE_TYPE?  */
136   t = build2 (EH_FILTER_EXPR, void_type_node, allowed, NULL_TREE);
137   append_to_statement_list (failure, &EH_FILTER_FAILURE (t));
138
139   t = build2 (TRY_CATCH_EXPR, void_type_node, NULL_TREE, t);
140   append_to_statement_list (body, &TREE_OPERAND (t, 0));
141
142   return t;
143 }
144
145 /* Genericize an EH_SPEC_BLOCK by converting it to a
146    TRY_CATCH_EXPR/EH_FILTER_EXPR pair.  */
147
148 static void
149 genericize_eh_spec_block (tree *stmt_p)
150 {
151   tree body = EH_SPEC_STMTS (*stmt_p);
152   tree allowed = EH_SPEC_RAISES (*stmt_p);
153   tree failure = build_call_n (call_unexpected_node, 1, build_exc_ptr ());
154
155   *stmt_p = build_gimple_eh_filter_tree (body, allowed, failure);
156 }
157
158 /* Genericize an IF_STMT by turning it into a COND_EXPR.  */
159
160 static void
161 genericize_if_stmt (tree *stmt_p)
162 {
163   tree stmt, cond, then_, else_;
164   location_t locus = EXPR_LOCATION (*stmt_p);
165
166   stmt = *stmt_p;
167   cond = IF_COND (stmt);
168   then_ = THEN_CLAUSE (stmt);
169   else_ = ELSE_CLAUSE (stmt);
170
171   if (!then_)
172     then_ = build_empty_stmt ();
173   if (!else_)
174     else_ = build_empty_stmt ();
175
176   if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
177     stmt = then_;
178   else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
179     stmt = else_;
180   else
181     stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
182   if (CAN_HAVE_LOCATION_P (stmt) && !EXPR_HAS_LOCATION (stmt))
183     SET_EXPR_LOCATION (stmt, locus);
184   *stmt_p = stmt;
185 }
186
187 /* Build a generic representation of one of the C loop forms.  COND is the
188    loop condition or NULL_TREE.  BODY is the (possibly compound) statement
189    controlled by the loop.  INCR is the increment expression of a for-loop,
190    or NULL_TREE.  COND_IS_FIRST indicates whether the condition is
191    evaluated before the loop body as in while and for loops, or after the
192    loop body as in do-while loops.  */
193
194 static gimple_seq
195 gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
196 {
197   gimple top, entry, stmt;
198   gimple_seq stmt_list, body_seq, incr_seq, exit_seq;
199   tree cont_block, break_block;
200   location_t stmt_locus;
201
202   stmt_locus = input_location;
203   stmt_list = NULL;
204   body_seq = NULL;
205   incr_seq = NULL;
206   exit_seq = NULL;
207   entry = NULL;
208
209   break_block = begin_bc_block (bc_break);
210   cont_block = begin_bc_block (bc_continue);
211
212   /* If condition is zero don't generate a loop construct.  */
213   if (cond && integer_zerop (cond))
214     {
215       top = NULL;
216       if (cond_is_first)
217         {
218           stmt = gimple_build_goto (get_bc_label (bc_break));
219           gimple_set_location (stmt, stmt_locus);
220           gimple_seq_add_stmt (&stmt_list, stmt);
221         }
222     }
223   else
224     {
225       /* If we use a LOOP_EXPR here, we have to feed the whole thing
226          back through the main gimplifier to lower it.  Given that we
227          have to gimplify the loop body NOW so that we can resolve
228          break/continue stmts, seems easier to just expand to gotos.  */
229       top = gimple_build_label (create_artificial_label ());
230
231       /* If we have an exit condition, then we build an IF with gotos either
232          out of the loop, or to the top of it.  If there's no exit condition,
233          then we just build a jump back to the top.  */
234       if (cond && !integer_nonzerop (cond))
235         {
236           if (cond != error_mark_node)
237             { 
238               gimplify_expr (&cond, &exit_seq, NULL, is_gimple_val, fb_rvalue);
239               stmt = gimple_build_cond (NE_EXPR, cond,
240                                         build_int_cst (TREE_TYPE (cond), 0),
241                                         gimple_label_label (top),
242                                         get_bc_label (bc_break));
243               gimple_seq_add_stmt (&exit_seq, stmt);
244             }
245
246           if (cond_is_first)
247             {
248               if (incr)
249                 {
250                   entry = gimple_build_label (create_artificial_label ());
251                   stmt = gimple_build_goto (gimple_label_label (entry));
252                 }
253               else
254                 stmt = gimple_build_goto (get_bc_label (bc_continue));
255               gimple_set_location (stmt, stmt_locus);
256               gimple_seq_add_stmt (&stmt_list, stmt);
257             }
258         }
259       else
260         {
261           stmt = gimple_build_goto (gimple_label_label (top));
262           gimple_seq_add_stmt (&exit_seq, stmt);
263         }
264     }
265
266   gimplify_stmt (&body, &body_seq);
267   gimplify_stmt (&incr, &incr_seq);
268
269   body_seq = finish_bc_block (bc_continue, cont_block, body_seq);
270
271   gimple_seq_add_stmt (&stmt_list, top);
272   gimple_seq_add_seq (&stmt_list, body_seq);
273   gimple_seq_add_seq (&stmt_list, incr_seq);
274   gimple_seq_add_stmt (&stmt_list, entry);
275   gimple_seq_add_seq (&stmt_list, exit_seq);
276
277   annotate_all_with_location (stmt_list, stmt_locus);
278
279   return finish_bc_block (bc_break, break_block, stmt_list);
280 }
281
282 /* Gimplify a FOR_STMT node.  Move the stuff in the for-init-stmt into the
283    prequeue and hand off to gimplify_cp_loop.  */
284
285 static void
286 gimplify_for_stmt (tree *stmt_p, gimple_seq *pre_p)
287 {
288   tree stmt = *stmt_p;
289
290   if (FOR_INIT_STMT (stmt))
291     gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
292
293   gimple_seq_add_seq (pre_p,
294                       gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
295                                         FOR_EXPR (stmt), 1));
296   *stmt_p = NULL_TREE;
297 }
298
299 /* Gimplify a WHILE_STMT node.  */
300
301 static void
302 gimplify_while_stmt (tree *stmt_p, gimple_seq *pre_p)
303 {
304   tree stmt = *stmt_p;
305   gimple_seq_add_seq (pre_p,
306                       gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
307                                         NULL_TREE, 1));
308   *stmt_p = NULL_TREE;
309 }
310
311 /* Gimplify a DO_STMT node.  */
312
313 static void
314 gimplify_do_stmt (tree *stmt_p, gimple_seq *pre_p)
315 {
316   tree stmt = *stmt_p;
317   gimple_seq_add_seq (pre_p,
318                       gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
319                                         NULL_TREE, 0));
320   *stmt_p = NULL_TREE;
321 }
322
323 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
324
325 static void
326 gimplify_switch_stmt (tree *stmt_p, gimple_seq *pre_p)
327 {
328   tree stmt = *stmt_p;
329   tree break_block, body, t;
330   location_t stmt_locus = input_location;
331   gimple_seq seq = NULL;
332
333   break_block = begin_bc_block (bc_break);
334
335   body = SWITCH_STMT_BODY (stmt);
336   if (!body)
337     body = build_empty_stmt ();
338
339   t = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
340               SWITCH_STMT_COND (stmt), body, NULL_TREE);
341   SET_EXPR_LOCATION (t, stmt_locus);
342   gimplify_and_add (t, &seq);
343
344   seq = finish_bc_block (bc_break, break_block, seq);
345   gimple_seq_add_seq (pre_p, seq);
346   *stmt_p = NULL_TREE;
347 }
348
349 /* Hook into the middle of gimplifying an OMP_FOR node.  This is required
350    in order to properly gimplify CONTINUE statements.  Here we merely
351    manage the continue stack; the rest of the job is performed by the
352    regular gimplifier.  */
353
354 static enum gimplify_status
355 cp_gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
356 {
357   tree for_stmt = *expr_p;
358   tree cont_block;
359   gimple stmt;
360   gimple_seq seq = NULL;
361
362   /* Protect ourselves from recursion.  */
363   if (OMP_FOR_GIMPLIFYING_P (for_stmt))
364     return GS_UNHANDLED;
365   OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
366
367   /* Note that while technically the continue label is enabled too soon
368      here, we should have already diagnosed invalid continues nested within
369      statement expressions within the INIT, COND, or INCR expressions.  */
370   cont_block = begin_bc_block (bc_continue);
371
372   gimplify_and_add (for_stmt, &seq);
373   stmt = gimple_seq_last_stmt (seq);
374   if (gimple_code (stmt) == GIMPLE_OMP_FOR)
375     gimple_omp_set_body (stmt, finish_bc_block (bc_continue, cont_block,
376                                                 gimple_omp_body (stmt)));
377   else
378     seq = finish_bc_block (bc_continue, cont_block, seq);
379   gimple_seq_add_seq (pre_p, seq);
380
381   OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
382
383   return GS_ALL_DONE;
384 }
385
386 /*  Gimplify an EXPR_STMT node.  */
387
388 static void
389 gimplify_expr_stmt (tree *stmt_p)
390 {
391   tree stmt = EXPR_STMT_EXPR (*stmt_p);
392
393   if (stmt == error_mark_node)
394     stmt = NULL;
395
396   /* Gimplification of a statement expression will nullify the
397      statement if all its side effects are moved to *PRE_P and *POST_P.
398
399      In this case we will not want to emit the gimplified statement.
400      However, we may still want to emit a warning, so we do that before
401      gimplification.  */
402   if (stmt && warn_unused_value)
403     {
404       if (!TREE_SIDE_EFFECTS (stmt))
405         {
406           if (!IS_EMPTY_STMT (stmt)
407               && !VOID_TYPE_P (TREE_TYPE (stmt))
408               && !TREE_NO_WARNING (stmt))
409             warning (OPT_Wunused_value, "statement with no effect");
410         }
411       else
412         warn_if_unused_value (stmt, input_location);
413     }
414
415   if (stmt == NULL_TREE)
416     stmt = alloc_stmt_list ();
417
418   *stmt_p = stmt;
419 }
420
421 /* Gimplify initialization from an AGGR_INIT_EXPR.  */
422
423 static void
424 cp_gimplify_init_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
425 {
426   tree from = TREE_OPERAND (*expr_p, 1);
427   tree to = TREE_OPERAND (*expr_p, 0);
428   tree t;
429   tree slot = NULL_TREE;
430
431   /* What about code that pulls out the temp and uses it elsewhere?  I
432      think that such code never uses the TARGET_EXPR as an initializer.  If
433      I'm wrong, we'll abort because the temp won't have any RTL.  In that
434      case, I guess we'll need to replace references somehow.  */
435   if (TREE_CODE (from) == TARGET_EXPR)
436     {
437       slot = TARGET_EXPR_SLOT (from);
438       from = TARGET_EXPR_INITIAL (from);
439     }
440
441   /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
442      inside the TARGET_EXPR.  */
443   for (t = from; t; )
444     {
445       tree sub = TREE_CODE (t) == COMPOUND_EXPR ? TREE_OPERAND (t, 0) : t;
446
447       /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
448          replace the slot operand with our target.
449
450          Should we add a target parm to gimplify_expr instead?  No, as in this
451          case we want to replace the INIT_EXPR.  */
452       if (TREE_CODE (sub) == AGGR_INIT_EXPR)
453         {
454           gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
455           AGGR_INIT_EXPR_SLOT (sub) = to;
456           *expr_p = from;
457
458           /* The initialization is now a side-effect, so the container can
459              become void.  */
460           if (from != sub)
461             TREE_TYPE (from) = void_type_node;
462         }
463
464       if (t == sub)
465         break;
466       else
467         t = TREE_OPERAND (t, 1);
468     }
469
470 }
471
472 /* Gimplify a MUST_NOT_THROW_EXPR.  */
473
474 static enum gimplify_status
475 gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p)
476 {
477   tree stmt = *expr_p;
478   tree temp = voidify_wrapper_expr (stmt, NULL);
479   tree body = TREE_OPERAND (stmt, 0);
480
481   stmt = build_gimple_eh_filter_tree (body, NULL_TREE,
482                                       build_call_n (terminate_node, 0));
483
484   gimplify_and_add (stmt, pre_p);
485   if (temp)
486     {
487       *expr_p = temp;
488       return GS_OK;
489     }
490
491   *expr_p = NULL;
492   return GS_ALL_DONE;
493 }
494
495 /* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
496
497 int
498 cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
499 {
500   int saved_stmts_are_full_exprs_p = 0;
501   enum tree_code code = TREE_CODE (*expr_p);
502   enum gimplify_status ret;
503   tree block = NULL;
504   VEC(gimple, heap) *bind_expr_stack = NULL;
505
506   if (STATEMENT_CODE_P (code))
507     {
508       saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
509       current_stmt_tree ()->stmts_are_full_exprs_p
510         = STMT_IS_FULL_EXPR_P (*expr_p);
511     }
512
513   switch (code)
514     {
515     case PTRMEM_CST:
516       *expr_p = cplus_expand_constant (*expr_p);
517       ret = GS_OK;
518       break;
519
520     case AGGR_INIT_EXPR:
521       simplify_aggr_init_expr (expr_p);
522       ret = GS_OK;
523       break;
524
525     case THROW_EXPR:
526       /* FIXME communicate throw type to back end, probably by moving
527          THROW_EXPR into ../tree.def.  */
528       *expr_p = TREE_OPERAND (*expr_p, 0);
529       ret = GS_OK;
530       break;
531
532     case MUST_NOT_THROW_EXPR:
533       ret = gimplify_must_not_throw_expr (expr_p, pre_p);
534       break;
535
536       /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
537          LHS of an assignment might also be involved in the RHS, as in bug
538          25979.  */
539     case INIT_EXPR:
540       cp_gimplify_init_expr (expr_p, pre_p, post_p);
541       ret = GS_OK;
542       break;
543
544     case EMPTY_CLASS_EXPR:
545       /* We create an empty CONSTRUCTOR with RECORD_TYPE.  */
546       *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
547       ret = GS_OK;
548       break;
549
550     case BASELINK:
551       *expr_p = BASELINK_FUNCTIONS (*expr_p);
552       ret = GS_OK;
553       break;
554
555     case TRY_BLOCK:
556       genericize_try_block (expr_p);
557       ret = GS_OK;
558       break;
559
560     case HANDLER:
561       genericize_catch_block (expr_p);
562       ret = GS_OK;
563       break;
564
565     case EH_SPEC_BLOCK:
566       genericize_eh_spec_block (expr_p);
567       ret = GS_OK;
568       break;
569
570     case USING_STMT:
571       /* Get the innermost inclosing GIMPLE_BIND that has a non NULL
572          BLOCK, and append an IMPORTED_DECL to its
573          BLOCK_VARS chained list.  */
574
575       bind_expr_stack = gimple_bind_expr_stack ();
576       if (bind_expr_stack)
577         {
578           int i;
579           for (i = VEC_length (gimple, bind_expr_stack) - 1; i >= 0; i--)
580             if ((block = gimple_bind_block (VEC_index (gimple,
581                                                        bind_expr_stack,
582                                                        i))))
583               break;
584         }
585       if (block)
586         {
587           tree using_directive;
588           gcc_assert (TREE_OPERAND (*expr_p,0)
589                       && NAMESPACE_DECL_CHECK (TREE_OPERAND (*expr_p, 0)));
590
591           using_directive = make_node (IMPORTED_DECL);
592           TREE_TYPE (using_directive) = void_type_node;
593
594           IMPORTED_DECL_ASSOCIATED_DECL (using_directive)
595             = TREE_OPERAND (*expr_p, 0);
596           DECL_NAME (using_directive)
597             = DECL_NAME (TREE_OPERAND (*expr_p, 0));
598           TREE_CHAIN (using_directive) = BLOCK_VARS (block);
599           BLOCK_VARS (block) = using_directive;
600         }
601       /* The USING_STMT won't appear in GIMPLE.  */
602       *expr_p = NULL;
603       ret = GS_ALL_DONE;
604       break;
605
606     case FOR_STMT:
607       gimplify_for_stmt (expr_p, pre_p);
608       ret = GS_OK;
609       break;
610
611     case WHILE_STMT:
612       gimplify_while_stmt (expr_p, pre_p);
613       ret = GS_OK;
614       break;
615
616     case DO_STMT:
617       gimplify_do_stmt (expr_p, pre_p);
618       ret = GS_OK;
619       break;
620
621     case SWITCH_STMT:
622       gimplify_switch_stmt (expr_p, pre_p);
623       ret = GS_OK;
624       break;
625
626     case OMP_FOR:
627       ret = cp_gimplify_omp_for (expr_p, pre_p);
628       break;
629
630     case CONTINUE_STMT:
631       gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_CONTINUE, NOT_TAKEN));
632       gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_continue)));
633       *expr_p = NULL_TREE;
634       ret = GS_ALL_DONE;
635       break;
636
637     case BREAK_STMT:
638       gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_break)));
639       *expr_p = NULL_TREE;
640       ret = GS_ALL_DONE;
641       break;
642
643     case EXPR_STMT:
644       gimplify_expr_stmt (expr_p);
645       ret = GS_OK;
646       break;
647
648     case UNARY_PLUS_EXPR:
649       {
650         tree arg = TREE_OPERAND (*expr_p, 0);
651         tree type = TREE_TYPE (*expr_p);
652         *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
653                                             : arg;
654         ret = GS_OK;
655       }
656       break;
657
658     default:
659       ret = c_gimplify_expr (expr_p, pre_p, post_p);
660       break;
661     }
662
663   /* Restore saved state.  */
664   if (STATEMENT_CODE_P (code))
665     current_stmt_tree ()->stmts_are_full_exprs_p
666       = saved_stmts_are_full_exprs_p;
667
668   return ret;
669 }
670
671 static inline bool
672 is_invisiref_parm (const_tree t)
673 {
674   return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
675           && DECL_BY_REFERENCE (t));
676 }
677
678 /* Return true if the uid in both int tree maps are equal.  */
679
680 int
681 cxx_int_tree_map_eq (const void *va, const void *vb)
682 {
683   const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
684   const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
685   return (a->uid == b->uid);
686 }
687
688 /* Hash a UID in a cxx_int_tree_map.  */
689
690 unsigned int
691 cxx_int_tree_map_hash (const void *item)
692 {
693   return ((const struct cxx_int_tree_map *)item)->uid;
694 }
695
696 /* Perform any pre-gimplification lowering of C++ front end trees to
697    GENERIC.  */
698
699 static tree
700 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
701 {
702   tree stmt = *stmt_p;
703   struct pointer_set_t *p_set = (struct pointer_set_t*) data;
704
705   if (is_invisiref_parm (stmt)
706       /* Don't dereference parms in a thunk, pass the references through. */
707       && !(DECL_THUNK_P (current_function_decl)
708            && TREE_CODE (stmt) == PARM_DECL))
709     {
710       *stmt_p = convert_from_reference (stmt);
711       *walk_subtrees = 0;
712       return NULL;
713     }
714
715   /* Map block scope extern declarations to visible declarations with the
716      same name and type in outer scopes if any.  */
717   if (cp_function_chain->extern_decl_map
718       && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
719       && DECL_EXTERNAL (stmt))
720     {
721       struct cxx_int_tree_map *h, in;
722       in.uid = DECL_UID (stmt);
723       h = (struct cxx_int_tree_map *)
724           htab_find_with_hash (cp_function_chain->extern_decl_map,
725                                &in, in.uid);
726       if (h)
727         {
728           *stmt_p = h->to;
729           *walk_subtrees = 0;
730           return NULL;
731         }
732     }
733
734   /* Other than invisiref parms, don't walk the same tree twice.  */
735   if (pointer_set_contains (p_set, stmt))
736     {
737       *walk_subtrees = 0;
738       return NULL_TREE;
739     }
740
741   if (TREE_CODE (stmt) == ADDR_EXPR
742       && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
743     {
744       *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
745       *walk_subtrees = 0;
746     }
747   else if (TREE_CODE (stmt) == RETURN_EXPR
748            && TREE_OPERAND (stmt, 0)
749            && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
750     /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
751     *walk_subtrees = 0;
752   else if (TREE_CODE (stmt) == OMP_CLAUSE)
753     switch (OMP_CLAUSE_CODE (stmt))
754       {
755       case OMP_CLAUSE_LASTPRIVATE:
756         /* Don't dereference an invisiref in OpenMP clauses.  */
757         if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
758           {
759             *walk_subtrees = 0;
760             if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt))
761               cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt),
762                             cp_genericize_r, p_set, NULL);
763           }
764         break;
765       case OMP_CLAUSE_PRIVATE:
766       case OMP_CLAUSE_SHARED:
767       case OMP_CLAUSE_FIRSTPRIVATE:
768       case OMP_CLAUSE_COPYIN:
769       case OMP_CLAUSE_COPYPRIVATE:
770         /* Don't dereference an invisiref in OpenMP clauses.  */
771         if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
772           *walk_subtrees = 0;
773         break;
774       case OMP_CLAUSE_REDUCTION:
775         gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
776         break;
777       default:
778         break;
779       }
780   else if (IS_TYPE_OR_DECL_P (stmt))
781     *walk_subtrees = 0;
782
783   /* Due to the way voidify_wrapper_expr is written, we don't get a chance
784      to lower this construct before scanning it, so we need to lower these
785      before doing anything else.  */
786   else if (TREE_CODE (stmt) == CLEANUP_STMT)
787     *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
788                                              : TRY_FINALLY_EXPR,
789                       void_type_node,
790                       CLEANUP_BODY (stmt),
791                       CLEANUP_EXPR (stmt));
792
793   else if (TREE_CODE (stmt) == IF_STMT)
794     {
795       genericize_if_stmt (stmt_p);
796       /* *stmt_p has changed, tail recurse to handle it again.  */
797       return cp_genericize_r (stmt_p, walk_subtrees, data);
798     }
799
800   /* COND_EXPR might have incompatible types in branches if one or both
801      arms are bitfields.  Fix it up now.  */
802   else if (TREE_CODE (stmt) == COND_EXPR)
803     {
804       tree type_left
805         = (TREE_OPERAND (stmt, 1)
806            ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1))
807            : NULL_TREE);
808       tree type_right
809         = (TREE_OPERAND (stmt, 2)
810            ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2))
811            : NULL_TREE);
812       if (type_left
813           && !useless_type_conversion_p (TREE_TYPE (stmt),
814                                          TREE_TYPE (TREE_OPERAND (stmt, 1))))
815         {
816           TREE_OPERAND (stmt, 1)
817             = fold_convert (type_left, TREE_OPERAND (stmt, 1));
818           gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
819                                                  type_left));
820         }
821       if (type_right
822           && !useless_type_conversion_p (TREE_TYPE (stmt),
823                                          TREE_TYPE (TREE_OPERAND (stmt, 2))))
824         {
825           TREE_OPERAND (stmt, 2)
826             = fold_convert (type_right, TREE_OPERAND (stmt, 2));
827           gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
828                                                  type_right));
829         }
830     }
831
832   pointer_set_insert (p_set, *stmt_p);
833
834   return NULL;
835 }
836
837 void
838 cp_genericize (tree fndecl)
839 {
840   tree t;
841   struct pointer_set_t *p_set;
842
843   /* Fix up the types of parms passed by invisible reference.  */
844   for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
845     if (TREE_ADDRESSABLE (TREE_TYPE (t)))
846       {
847         /* If a function's arguments are copied to create a thunk,
848            then DECL_BY_REFERENCE will be set -- but the type of the
849            argument will be a pointer type, so we will never get
850            here.  */
851         gcc_assert (!DECL_BY_REFERENCE (t));
852         gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
853         TREE_TYPE (t) = DECL_ARG_TYPE (t);
854         DECL_BY_REFERENCE (t) = 1;
855         TREE_ADDRESSABLE (t) = 0;
856         relayout_decl (t);
857       }
858
859   /* Do the same for the return value.  */
860   if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
861     {
862       t = DECL_RESULT (fndecl);
863       TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
864       DECL_BY_REFERENCE (t) = 1;
865       TREE_ADDRESSABLE (t) = 0;
866       relayout_decl (t);
867     }
868
869   /* If we're a clone, the body is already GIMPLE.  */
870   if (DECL_CLONED_FUNCTION_P (fndecl))
871     return;
872
873   /* We do want to see every occurrence of the parms, so we can't just use
874      walk_tree's hash functionality.  */
875   p_set = pointer_set_create ();
876   cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
877   pointer_set_destroy (p_set);
878
879   /* Do everything else.  */
880   c_genericize (fndecl);
881
882   gcc_assert (bc_label[bc_break] == NULL);
883   gcc_assert (bc_label[bc_continue] == NULL);
884 }
885 \f
886 /* Build code to apply FN to each member of ARG1 and ARG2.  FN may be
887    NULL if there is in fact nothing to do.  ARG2 may be null if FN
888    actually only takes one argument.  */
889
890 static tree
891 cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
892 {
893   tree defparm, parm, t;
894   int i = 0;
895   int nargs;
896   tree *argarray;
897
898   if (fn == NULL)
899     return NULL;
900
901   nargs = list_length (DECL_ARGUMENTS (fn));
902   argarray = (tree *) alloca (nargs * sizeof (tree));
903
904   defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
905   if (arg2)
906     defparm = TREE_CHAIN (defparm);
907
908   if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
909     {
910       tree inner_type = TREE_TYPE (arg1);
911       tree start1, end1, p1;
912       tree start2 = NULL, p2 = NULL;
913       tree ret = NULL, lab;
914
915       start1 = arg1;
916       start2 = arg2;
917       do
918         {
919           inner_type = TREE_TYPE (inner_type);
920           start1 = build4 (ARRAY_REF, inner_type, start1,
921                            size_zero_node, NULL, NULL);
922           if (arg2)
923             start2 = build4 (ARRAY_REF, inner_type, start2,
924                              size_zero_node, NULL, NULL);
925         }
926       while (TREE_CODE (inner_type) == ARRAY_TYPE);
927       start1 = build_fold_addr_expr (start1);
928       if (arg2)
929         start2 = build_fold_addr_expr (start2);
930
931       end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
932       end1 = build2 (POINTER_PLUS_EXPR, TREE_TYPE (start1), start1, end1);
933
934       p1 = create_tmp_var (TREE_TYPE (start1), NULL);
935       t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, start1);
936       append_to_statement_list (t, &ret);
937
938       if (arg2)
939         {
940           p2 = create_tmp_var (TREE_TYPE (start2), NULL);
941           t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, start2);
942           append_to_statement_list (t, &ret);
943         }
944
945       lab = create_artificial_label ();
946       t = build1 (LABEL_EXPR, void_type_node, lab);
947       append_to_statement_list (t, &ret);
948
949       argarray[i++] = p1;
950       if (arg2)
951         argarray[i++] = p2;
952       /* Handle default arguments.  */
953       for (parm = defparm; parm && parm != void_list_node;
954            parm = TREE_CHAIN (parm), i++)
955         argarray[i] = convert_default_arg (TREE_VALUE (parm),
956                                            TREE_PURPOSE (parm), fn, i);
957       t = build_call_a (fn, i, argarray);
958       t = fold_convert (void_type_node, t);
959       t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
960       append_to_statement_list (t, &ret);
961
962       t = TYPE_SIZE_UNIT (inner_type);
963       t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p1), p1, t);
964       t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, t);
965       append_to_statement_list (t, &ret);
966
967       if (arg2)
968         {
969           t = TYPE_SIZE_UNIT (inner_type);
970           t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (p2), p2, t);
971           t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, t);
972           append_to_statement_list (t, &ret);
973         }
974
975       t = build2 (NE_EXPR, boolean_type_node, p1, end1);
976       t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
977       append_to_statement_list (t, &ret);
978
979       return ret;
980     }
981   else
982     {
983       argarray[i++] = build_fold_addr_expr (arg1);
984       if (arg2)
985         argarray[i++] = build_fold_addr_expr (arg2);
986       /* Handle default arguments.  */
987       for (parm = defparm; parm && parm != void_list_node;
988            parm = TREE_CHAIN (parm), i++)
989         argarray[i] = convert_default_arg (TREE_VALUE (parm),
990                                            TREE_PURPOSE (parm),
991                                            fn, i);
992       t = build_call_a (fn, i, argarray);
993       t = fold_convert (void_type_node, t);
994       return fold_build_cleanup_point_expr (TREE_TYPE (t), t);
995     }
996 }
997
998 /* Return code to initialize DECL with its default constructor, or
999    NULL if there's nothing to do.  */
1000
1001 tree
1002 cxx_omp_clause_default_ctor (tree clause, tree decl,
1003                              tree outer ATTRIBUTE_UNUSED)
1004 {
1005   tree info = CP_OMP_CLAUSE_INFO (clause);
1006   tree ret = NULL;
1007
1008   if (info)
1009     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
1010
1011   return ret;
1012 }
1013
1014 /* Return code to initialize DST with a copy constructor from SRC.  */
1015
1016 tree
1017 cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
1018 {
1019   tree info = CP_OMP_CLAUSE_INFO (clause);
1020   tree ret = NULL;
1021
1022   if (info)
1023     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
1024   if (ret == NULL)
1025     ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
1026
1027   return ret;
1028 }
1029
1030 /* Similarly, except use an assignment operator instead.  */
1031
1032 tree
1033 cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
1034 {
1035   tree info = CP_OMP_CLAUSE_INFO (clause);
1036   tree ret = NULL;
1037
1038   if (info)
1039     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
1040   if (ret == NULL)
1041     ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
1042
1043   return ret;
1044 }
1045
1046 /* Return code to destroy DECL.  */
1047
1048 tree
1049 cxx_omp_clause_dtor (tree clause, tree decl)
1050 {
1051   tree info = CP_OMP_CLAUSE_INFO (clause);
1052   tree ret = NULL;
1053
1054   if (info)
1055     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
1056
1057   return ret;
1058 }
1059
1060 /* True if OpenMP should privatize what this DECL points to rather
1061    than the DECL itself.  */
1062
1063 bool
1064 cxx_omp_privatize_by_reference (const_tree decl)
1065 {
1066   return is_invisiref_parm (decl);
1067 }
1068
1069 /* True if OpenMP sharing attribute of DECL is predetermined.  */
1070
1071 enum omp_clause_default_kind
1072 cxx_omp_predetermined_sharing (tree decl)
1073 {
1074   tree type;
1075
1076   /* Static data members are predetermined as shared.  */
1077   if (TREE_STATIC (decl))
1078     {
1079       tree ctx = CP_DECL_CONTEXT (decl);
1080       if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
1081         return OMP_CLAUSE_DEFAULT_SHARED;
1082     }
1083
1084   type = TREE_TYPE (decl);
1085   if (TREE_CODE (type) == REFERENCE_TYPE)
1086     {
1087       if (!is_invisiref_parm (decl))
1088         return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
1089       type = TREE_TYPE (type);
1090
1091       if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl))
1092         {
1093           /* NVR doesn't preserve const qualification of the
1094              variable's type.  */
1095           tree outer = outer_curly_brace_block (current_function_decl);
1096           tree var;
1097
1098           if (outer)
1099             for (var = BLOCK_VARS (outer); var; var = TREE_CHAIN (var))
1100               if (DECL_NAME (decl) == DECL_NAME (var)
1101                   && (TYPE_MAIN_VARIANT (type)
1102                       == TYPE_MAIN_VARIANT (TREE_TYPE (var))))
1103                 {
1104                   if (TYPE_READONLY (TREE_TYPE (var)))
1105                     type = TREE_TYPE (var);
1106                   break;
1107                 }
1108         }
1109     }
1110
1111   if (type == error_mark_node)
1112     return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
1113
1114   /* Variables with const-qualified type having no mutable member
1115      are predetermined shared.  */
1116   if (TYPE_READONLY (type) && !cp_has_mutable_p (type))
1117     return OMP_CLAUSE_DEFAULT_SHARED;
1118
1119   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
1120 }
1121
1122 /* Finalize an implicitly determined clause.  */
1123
1124 void
1125 cxx_omp_finish_clause (tree c)
1126 {
1127   tree decl, inner_type;
1128   bool make_shared = false;
1129
1130   if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
1131     return;
1132
1133   decl = OMP_CLAUSE_DECL (c);
1134   decl = require_complete_type (decl);
1135   inner_type = TREE_TYPE (decl);
1136   if (decl == error_mark_node)
1137     make_shared = true;
1138   else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
1139     {
1140       if (is_invisiref_parm (decl))
1141         inner_type = TREE_TYPE (inner_type);
1142       else
1143         {
1144           error ("%qE implicitly determined as %<firstprivate%> has reference type",
1145                  decl);
1146           make_shared = true;
1147         }
1148     }
1149
1150   /* We're interested in the base element, not arrays.  */
1151   while (TREE_CODE (inner_type) == ARRAY_TYPE)
1152     inner_type = TREE_TYPE (inner_type);
1153
1154   /* Check for special function availability by building a call to one.
1155      Save the results, because later we won't be in the right context
1156      for making these queries.  */
1157   if (!make_shared
1158       && CLASS_TYPE_P (inner_type)
1159       && cxx_omp_create_clause_info (c, inner_type, false, true, false))
1160     make_shared = true;
1161
1162   if (make_shared)
1163     OMP_CLAUSE_CODE (c) = OMP_CLAUSE_SHARED;
1164 }