remove unused files
[platform/upstream/gcc48.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-2013 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 3, 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 COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "tree.h"
27 #include "cp-tree.h"
28 #include "c-family/c-common.h"
29 #include "tree-iterator.h"
30 #include "gimple.h"
31 #include "hashtab.h"
32 #include "pointer-set.h"
33 #include "flags.h"
34 #include "splay-tree.h"
35
36 /* Forward declarations.  */
37
38 static tree cp_genericize_r (tree *, int *, void *);
39 static void cp_genericize_tree (tree*);
40
41 /* Local declarations.  */
42
43 enum bc_t { bc_break = 0, bc_continue = 1 };
44
45 /* Stack of labels which are targets for "break" or "continue",
46    linked through TREE_CHAIN.  */
47 static tree bc_label[2];
48
49 /* Begin a scope which can be exited by a break or continue statement.  BC
50    indicates which.
51
52    Just creates a label with location LOCATION and pushes it into the current
53    context.  */
54
55 static tree
56 begin_bc_block (enum bc_t bc, location_t location)
57 {
58   tree label = create_artificial_label (location);
59   DECL_CHAIN (label) = bc_label[bc];
60   bc_label[bc] = label;
61   return label;
62 }
63
64 /* Finish a scope which can be exited by a break or continue statement.
65    LABEL was returned from the most recent call to begin_bc_block.  BLOCK is
66    an expression for the contents of the scope.
67
68    If we saw a break (or continue) in the scope, append a LABEL_EXPR to
69    BLOCK.  Otherwise, just forget the label.  */
70
71 static void
72 finish_bc_block (tree *block, enum bc_t bc, tree label)
73 {
74   gcc_assert (label == bc_label[bc]);
75
76   if (TREE_USED (label))
77     append_to_statement_list (build1 (LABEL_EXPR, void_type_node, label),
78                               block);
79
80   bc_label[bc] = DECL_CHAIN (label);
81   DECL_CHAIN (label) = NULL_TREE;
82 }
83
84 /* Get the LABEL_EXPR to represent a break or continue statement
85    in the current block scope.  BC indicates which.  */
86
87 static tree
88 get_bc_label (enum bc_t bc)
89 {
90   tree label = bc_label[bc];
91
92   /* Mark the label used for finish_bc_block.  */
93   TREE_USED (label) = 1;
94   return label;
95 }
96
97 /* Genericize a TRY_BLOCK.  */
98
99 static void
100 genericize_try_block (tree *stmt_p)
101 {
102   tree body = TRY_STMTS (*stmt_p);
103   tree cleanup = TRY_HANDLERS (*stmt_p);
104
105   *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
106 }
107
108 /* Genericize a HANDLER by converting to a CATCH_EXPR.  */
109
110 static void
111 genericize_catch_block (tree *stmt_p)
112 {
113   tree type = HANDLER_TYPE (*stmt_p);
114   tree body = HANDLER_BODY (*stmt_p);
115
116   /* FIXME should the caught type go in TREE_TYPE?  */
117   *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
118 }
119
120 /* A terser interface for building a representation of an exception
121    specification.  */
122
123 static tree
124 build_gimple_eh_filter_tree (tree body, tree allowed, tree failure)
125 {
126   tree t;
127
128   /* FIXME should the allowed types go in TREE_TYPE?  */
129   t = build2 (EH_FILTER_EXPR, void_type_node, allowed, NULL_TREE);
130   append_to_statement_list (failure, &EH_FILTER_FAILURE (t));
131
132   t = build2 (TRY_CATCH_EXPR, void_type_node, NULL_TREE, t);
133   append_to_statement_list (body, &TREE_OPERAND (t, 0));
134
135   return t;
136 }
137
138 /* Genericize an EH_SPEC_BLOCK by converting it to a
139    TRY_CATCH_EXPR/EH_FILTER_EXPR pair.  */
140
141 static void
142 genericize_eh_spec_block (tree *stmt_p)
143 {
144   tree body = EH_SPEC_STMTS (*stmt_p);
145   tree allowed = EH_SPEC_RAISES (*stmt_p);
146   tree failure = build_call_n (call_unexpected_node, 1, build_exc_ptr ());
147
148   *stmt_p = build_gimple_eh_filter_tree (body, allowed, failure);
149   TREE_NO_WARNING (*stmt_p) = true;
150   TREE_NO_WARNING (TREE_OPERAND (*stmt_p, 1)) = true;
151 }
152
153 /* Genericize an IF_STMT by turning it into a COND_EXPR.  */
154
155 static void
156 genericize_if_stmt (tree *stmt_p)
157 {
158   tree stmt, cond, then_, else_;
159   location_t locus = EXPR_LOCATION (*stmt_p);
160
161   stmt = *stmt_p;
162   cond = IF_COND (stmt);
163   then_ = THEN_CLAUSE (stmt);
164   else_ = ELSE_CLAUSE (stmt);
165
166   if (!then_)
167     then_ = build_empty_stmt (locus);
168   if (!else_)
169     else_ = build_empty_stmt (locus);
170
171   if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
172     stmt = then_;
173   else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
174     stmt = else_;
175   else
176     stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
177   if (CAN_HAVE_LOCATION_P (stmt) && !EXPR_HAS_LOCATION (stmt))
178     SET_EXPR_LOCATION (stmt, locus);
179   *stmt_p = stmt;
180 }
181
182 /* Build a generic representation of one of the C loop forms.  COND is the
183    loop condition or NULL_TREE.  BODY is the (possibly compound) statement
184    controlled by the loop.  INCR is the increment expression of a for-loop,
185    or NULL_TREE.  COND_IS_FIRST indicates whether the condition is
186    evaluated before the loop body as in while and for loops, or after the
187    loop body as in do-while loops.  */
188
189 static void
190 genericize_cp_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
191                     tree incr, bool cond_is_first, int *walk_subtrees,
192                     void *data)
193 {
194   tree blab, clab;
195   tree entry = NULL, exit = NULL, t;
196   tree stmt_list = NULL;
197
198   blab = begin_bc_block (bc_break, start_locus);
199   clab = begin_bc_block (bc_continue, start_locus);
200
201   if (incr && EXPR_P (incr))
202     SET_EXPR_LOCATION (incr, start_locus);
203
204   cp_walk_tree (&cond, cp_genericize_r, data, NULL);
205   cp_walk_tree (&body, cp_genericize_r, data, NULL);
206   cp_walk_tree (&incr, cp_genericize_r, data, NULL);
207   *walk_subtrees = 0;
208
209   /* If condition is zero don't generate a loop construct.  */
210   if (cond && integer_zerop (cond))
211     {
212       if (cond_is_first)
213         {
214           t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
215                           get_bc_label (bc_break));
216           append_to_statement_list (t, &stmt_list);
217         }
218     }
219   else
220     {
221       /* Expand to gotos, just like c_finish_loop.  TODO: Use LOOP_EXPR.  */
222       tree top = build1 (LABEL_EXPR, void_type_node,
223                          create_artificial_label (start_locus));
224
225       /* If we have an exit condition, then we build an IF with gotos either
226          out of the loop, or to the top of it.  If there's no exit condition,
227          then we just build a jump back to the top.  */
228       exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
229
230       if (cond && !integer_nonzerop (cond))
231         {
232           /* Canonicalize the loop condition to the end.  This means
233              generating a branch to the loop condition.  Reuse the
234              continue label, if possible.  */
235           if (cond_is_first)
236             {
237               if (incr)
238                 {
239                   entry = build1 (LABEL_EXPR, void_type_node,
240                                   create_artificial_label (start_locus));
241                   t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
242                                   LABEL_EXPR_LABEL (entry));
243                 }
244               else
245                 t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
246                                 get_bc_label (bc_continue));
247               append_to_statement_list (t, &stmt_list);
248             }
249
250           t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
251           exit = fold_build3_loc (start_locus,
252                                   COND_EXPR, void_type_node, cond, exit, t);
253         }
254
255       append_to_statement_list (top, &stmt_list);
256     }
257
258   append_to_statement_list (body, &stmt_list);
259   finish_bc_block (&stmt_list, bc_continue, clab);
260   append_to_statement_list (incr, &stmt_list);
261   append_to_statement_list (entry, &stmt_list);
262   append_to_statement_list (exit, &stmt_list);
263   finish_bc_block (&stmt_list, bc_break, blab);
264
265   if (stmt_list == NULL_TREE)
266     stmt_list = build1 (NOP_EXPR, void_type_node, integer_zero_node);
267
268   *stmt_p = stmt_list;
269 }
270
271 /* Genericize a FOR_STMT node *STMT_P.  */
272
273 static void
274 genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data)
275 {
276   tree stmt = *stmt_p;
277   tree expr = NULL;
278   tree loop;
279   tree init = FOR_INIT_STMT (stmt);
280
281   if (init)
282     {
283       cp_walk_tree (&init, cp_genericize_r, data, NULL);
284       append_to_statement_list (init, &expr);
285     }
286
287   genericize_cp_loop (&loop, EXPR_LOCATION (stmt), FOR_COND (stmt),
288                       FOR_BODY (stmt), FOR_EXPR (stmt), 1, walk_subtrees, data);
289   append_to_statement_list (loop, &expr);
290   *stmt_p = expr;
291 }
292
293 /* Genericize a WHILE_STMT node *STMT_P.  */
294
295 static void
296 genericize_while_stmt (tree *stmt_p, int *walk_subtrees, void *data)
297 {
298   tree stmt = *stmt_p;
299   genericize_cp_loop (stmt_p, EXPR_LOCATION (stmt), WHILE_COND (stmt),
300                       WHILE_BODY (stmt), NULL_TREE, 1, walk_subtrees, data);
301 }
302
303 /* Genericize a DO_STMT node *STMT_P.  */
304
305 static void
306 genericize_do_stmt (tree *stmt_p, int *walk_subtrees, void *data)
307 {
308   tree stmt = *stmt_p;
309   genericize_cp_loop (stmt_p, EXPR_LOCATION (stmt), DO_COND (stmt),
310                       DO_BODY (stmt), NULL_TREE, 0, walk_subtrees, data);
311 }
312
313 /* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR.  */
314
315 static void
316 genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data)
317 {
318   tree stmt = *stmt_p;
319   tree break_block, body, cond, type;
320   location_t stmt_locus = EXPR_LOCATION (stmt);
321
322   break_block = begin_bc_block (bc_break, stmt_locus);
323
324   body = SWITCH_STMT_BODY (stmt);
325   if (!body)
326     body = build_empty_stmt (stmt_locus);
327   cond = SWITCH_STMT_COND (stmt);
328   type = SWITCH_STMT_TYPE (stmt);
329
330   cp_walk_tree (&body, cp_genericize_r, data, NULL);
331   cp_walk_tree (&cond, cp_genericize_r, data, NULL);
332   cp_walk_tree (&type, cp_genericize_r, data, NULL);
333   *walk_subtrees = 0;
334
335   *stmt_p = build3_loc (stmt_locus, SWITCH_EXPR, type, cond, body, NULL_TREE);
336   finish_bc_block (stmt_p, bc_break, break_block);
337 }
338
339 /* Genericize a CONTINUE_STMT node *STMT_P.  */
340
341 static void
342 genericize_continue_stmt (tree *stmt_p)
343 {
344   tree stmt_list = NULL;
345   tree pred = build_predict_expr (PRED_CONTINUE, NOT_TAKEN);
346   tree label = get_bc_label (bc_continue);
347   location_t location = EXPR_LOCATION (*stmt_p);
348   tree jump = build1_loc (location, GOTO_EXPR, void_type_node, label);
349   append_to_statement_list (pred, &stmt_list);
350   append_to_statement_list (jump, &stmt_list);
351   *stmt_p = stmt_list;
352 }
353
354 /* Genericize a BREAK_STMT node *STMT_P.  */
355
356 static void
357 genericize_break_stmt (tree *stmt_p)
358 {
359   tree label = get_bc_label (bc_break);
360   location_t location = EXPR_LOCATION (*stmt_p);
361   *stmt_p = build1_loc (location, GOTO_EXPR, void_type_node, label);
362 }
363
364 /* Genericize a OMP_FOR node *STMT_P.  */
365
366 static void
367 genericize_omp_for_stmt (tree *stmt_p, int *walk_subtrees, void *data)
368 {
369   tree stmt = *stmt_p;
370   location_t locus = EXPR_LOCATION (stmt);
371   tree clab = begin_bc_block (bc_continue, locus);
372
373   cp_walk_tree (&OMP_FOR_BODY (stmt), cp_genericize_r, data, NULL);
374   cp_walk_tree (&OMP_FOR_CLAUSES (stmt), cp_genericize_r, data, NULL);
375   cp_walk_tree (&OMP_FOR_INIT (stmt), cp_genericize_r, data, NULL);
376   cp_walk_tree (&OMP_FOR_COND (stmt), cp_genericize_r, data, NULL);
377   cp_walk_tree (&OMP_FOR_INCR (stmt), cp_genericize_r, data, NULL);
378   cp_walk_tree (&OMP_FOR_PRE_BODY (stmt), cp_genericize_r, data, NULL);
379   *walk_subtrees = 0;
380
381   finish_bc_block (&OMP_FOR_BODY (stmt), bc_continue, clab);
382 }
383
384 /* Hook into the middle of gimplifying an OMP_FOR node.  */
385
386 static enum gimplify_status
387 cp_gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
388 {
389   tree for_stmt = *expr_p;
390   gimple_seq seq = NULL;
391
392   /* Protect ourselves from recursion.  */
393   if (OMP_FOR_GIMPLIFYING_P (for_stmt))
394     return GS_UNHANDLED;
395   OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
396
397   gimplify_and_add (for_stmt, &seq);
398   gimple_seq_add_seq (pre_p, seq);
399
400   OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
401
402   return GS_ALL_DONE;
403 }
404
405 /*  Gimplify an EXPR_STMT node.  */
406
407 static void
408 gimplify_expr_stmt (tree *stmt_p)
409 {
410   tree stmt = EXPR_STMT_EXPR (*stmt_p);
411
412   if (stmt == error_mark_node)
413     stmt = NULL;
414
415   /* Gimplification of a statement expression will nullify the
416      statement if all its side effects are moved to *PRE_P and *POST_P.
417
418      In this case we will not want to emit the gimplified statement.
419      However, we may still want to emit a warning, so we do that before
420      gimplification.  */
421   if (stmt && warn_unused_value)
422     {
423       if (!TREE_SIDE_EFFECTS (stmt))
424         {
425           if (!IS_EMPTY_STMT (stmt)
426               && !VOID_TYPE_P (TREE_TYPE (stmt))
427               && !TREE_NO_WARNING (stmt))
428             warning (OPT_Wunused_value, "statement with no effect");
429         }
430       else
431         warn_if_unused_value (stmt, input_location);
432     }
433
434   if (stmt == NULL_TREE)
435     stmt = alloc_stmt_list ();
436
437   *stmt_p = stmt;
438 }
439
440 /* Gimplify initialization from an AGGR_INIT_EXPR.  */
441
442 static void
443 cp_gimplify_init_expr (tree *expr_p)
444 {
445   tree from = TREE_OPERAND (*expr_p, 1);
446   tree to = TREE_OPERAND (*expr_p, 0);
447   tree t;
448
449   /* What about code that pulls out the temp and uses it elsewhere?  I
450      think that such code never uses the TARGET_EXPR as an initializer.  If
451      I'm wrong, we'll abort because the temp won't have any RTL.  In that
452      case, I guess we'll need to replace references somehow.  */
453   if (TREE_CODE (from) == TARGET_EXPR)
454     from = TARGET_EXPR_INITIAL (from);
455
456   /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
457      inside the TARGET_EXPR.  */
458   for (t = from; t; )
459     {
460       tree sub = TREE_CODE (t) == COMPOUND_EXPR ? TREE_OPERAND (t, 0) : t;
461
462       /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
463          replace the slot operand with our target.
464
465          Should we add a target parm to gimplify_expr instead?  No, as in this
466          case we want to replace the INIT_EXPR.  */
467       if (TREE_CODE (sub) == AGGR_INIT_EXPR
468           || TREE_CODE (sub) == VEC_INIT_EXPR)
469         {
470           if (TREE_CODE (sub) == AGGR_INIT_EXPR)
471             AGGR_INIT_EXPR_SLOT (sub) = to;
472           else
473             VEC_INIT_EXPR_SLOT (sub) = to;
474           *expr_p = from;
475
476           /* The initialization is now a side-effect, so the container can
477              become void.  */
478           if (from != sub)
479             TREE_TYPE (from) = void_type_node;
480         }
481
482       if (t == sub)
483         break;
484       else
485         t = TREE_OPERAND (t, 1);
486     }
487
488 }
489
490 /* Gimplify a MUST_NOT_THROW_EXPR.  */
491
492 static enum gimplify_status
493 gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p)
494 {
495   tree stmt = *expr_p;
496   tree temp = voidify_wrapper_expr (stmt, NULL);
497   tree body = TREE_OPERAND (stmt, 0);
498   gimple_seq try_ = NULL;
499   gimple_seq catch_ = NULL;
500   gimple mnt;
501
502   gimplify_and_add (body, &try_);
503   mnt = gimple_build_eh_must_not_throw (terminate_node);
504   gimple_seq_add_stmt_without_update (&catch_, mnt);
505   mnt = gimple_build_try (try_, catch_, GIMPLE_TRY_CATCH);
506
507   gimple_seq_add_stmt_without_update (pre_p, mnt);
508   if (temp)
509     {
510       *expr_p = temp;
511       return GS_OK;
512     }
513
514   *expr_p = NULL;
515   return GS_ALL_DONE;
516 }
517
518 /* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
519
520 int
521 cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
522 {
523   int saved_stmts_are_full_exprs_p = 0;
524   enum tree_code code = TREE_CODE (*expr_p);
525   enum gimplify_status ret;
526
527   if (STATEMENT_CODE_P (code))
528     {
529       saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
530       current_stmt_tree ()->stmts_are_full_exprs_p
531         = STMT_IS_FULL_EXPR_P (*expr_p);
532     }
533
534   switch (code)
535     {
536     case PTRMEM_CST:
537       *expr_p = cplus_expand_constant (*expr_p);
538       ret = GS_OK;
539       break;
540
541     case AGGR_INIT_EXPR:
542       simplify_aggr_init_expr (expr_p);
543       ret = GS_OK;
544       break;
545
546     case VEC_INIT_EXPR:
547       {
548         location_t loc = input_location;
549         tree init = VEC_INIT_EXPR_INIT (*expr_p);
550         int from_array = (init && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE);
551         gcc_assert (EXPR_HAS_LOCATION (*expr_p));
552         input_location = EXPR_LOCATION (*expr_p);
553         *expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE,
554                                   init, VEC_INIT_EXPR_VALUE_INIT (*expr_p),
555                                   from_array,
556                                   tf_warning_or_error);
557         cp_genericize_tree (expr_p);
558         ret = GS_OK;
559         input_location = loc;
560       }
561       break;
562
563     case THROW_EXPR:
564       /* FIXME communicate throw type to back end, probably by moving
565          THROW_EXPR into ../tree.def.  */
566       *expr_p = TREE_OPERAND (*expr_p, 0);
567       ret = GS_OK;
568       break;
569
570     case MUST_NOT_THROW_EXPR:
571       ret = gimplify_must_not_throw_expr (expr_p, pre_p);
572       break;
573
574       /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
575          LHS of an assignment might also be involved in the RHS, as in bug
576          25979.  */
577     case INIT_EXPR:
578       cp_gimplify_init_expr (expr_p);
579       if (TREE_CODE (*expr_p) != INIT_EXPR)
580         return GS_OK;
581       /* Otherwise fall through.  */
582     case MODIFY_EXPR:
583       {
584         /* If the back end isn't clever enough to know that the lhs and rhs
585            types are the same, add an explicit conversion.  */
586         tree op0 = TREE_OPERAND (*expr_p, 0);
587         tree op1 = TREE_OPERAND (*expr_p, 1);
588
589         if (!error_operand_p (op0)
590             && !error_operand_p (op1)
591             && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0))
592                 || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1)))
593             && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
594           TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
595                                               TREE_TYPE (op0), op1);
596
597         else if ((is_gimple_lvalue (op1) || INDIRECT_REF_P (op1)
598                   || (TREE_CODE (op1) == CONSTRUCTOR
599                       && CONSTRUCTOR_NELTS (op1) == 0
600                       && !TREE_CLOBBER_P (op1))
601                   || (TREE_CODE (op1) == CALL_EXPR
602                       && !CALL_EXPR_RETURN_SLOT_OPT (op1)))
603                  && is_really_empty_class (TREE_TYPE (op0)))
604           {
605             /* Remove any copies of empty classes.  We check that the RHS
606                has a simple form so that TARGET_EXPRs and non-empty
607                CONSTRUCTORs get reduced properly, and we leave the return
608                slot optimization alone because it isn't a copy (FIXME so it
609                shouldn't be represented as one).
610
611                Also drop volatile variables on the RHS to avoid infinite
612                recursion from gimplify_expr trying to load the value.  */
613             if (!TREE_SIDE_EFFECTS (op1)
614                 || (DECL_P (op1) && TREE_THIS_VOLATILE (op1)))
615               *expr_p = op0;
616             else if (TREE_CODE (op1) == MEM_REF
617                      && TREE_THIS_VOLATILE (op1))
618               {
619                 /* Similarly for volatile MEM_REFs on the RHS.  */
620                 if (!TREE_SIDE_EFFECTS (TREE_OPERAND (op1, 0)))
621                   *expr_p = op0;
622                 else
623                   *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
624                                     TREE_OPERAND (op1, 0), op0);
625               }
626             else
627               *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p),
628                                 op0, op1);
629           }
630       }
631       ret = GS_OK;
632       break;
633
634     case EMPTY_CLASS_EXPR:
635       /* We create an empty CONSTRUCTOR with RECORD_TYPE.  */
636       *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
637       ret = GS_OK;
638       break;
639
640     case BASELINK:
641       *expr_p = BASELINK_FUNCTIONS (*expr_p);
642       ret = GS_OK;
643       break;
644
645     case TRY_BLOCK:
646       genericize_try_block (expr_p);
647       ret = GS_OK;
648       break;
649
650     case HANDLER:
651       genericize_catch_block (expr_p);
652       ret = GS_OK;
653       break;
654
655     case EH_SPEC_BLOCK:
656       genericize_eh_spec_block (expr_p);
657       ret = GS_OK;
658       break;
659
660     case USING_STMT:
661       gcc_unreachable ();
662
663     case FOR_STMT:
664     case WHILE_STMT:
665     case DO_STMT:
666     case SWITCH_STMT:
667     case CONTINUE_STMT:
668     case BREAK_STMT:
669       gcc_unreachable ();
670
671     case OMP_FOR:
672       ret = cp_gimplify_omp_for (expr_p, pre_p);
673       break;
674
675     case EXPR_STMT:
676       gimplify_expr_stmt (expr_p);
677       ret = GS_OK;
678       break;
679
680     case UNARY_PLUS_EXPR:
681       {
682         tree arg = TREE_OPERAND (*expr_p, 0);
683         tree type = TREE_TYPE (*expr_p);
684         *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
685                                             : arg;
686         ret = GS_OK;
687       }
688       break;
689
690     default:
691       ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p);
692       break;
693     }
694
695   /* Restore saved state.  */
696   if (STATEMENT_CODE_P (code))
697     current_stmt_tree ()->stmts_are_full_exprs_p
698       = saved_stmts_are_full_exprs_p;
699
700   return ret;
701 }
702
703 static inline bool
704 is_invisiref_parm (const_tree t)
705 {
706   return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
707           && DECL_BY_REFERENCE (t));
708 }
709
710 /* Return true if the uid in both int tree maps are equal.  */
711
712 int
713 cxx_int_tree_map_eq (const void *va, const void *vb)
714 {
715   const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
716   const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
717   return (a->uid == b->uid);
718 }
719
720 /* Hash a UID in a cxx_int_tree_map.  */
721
722 unsigned int
723 cxx_int_tree_map_hash (const void *item)
724 {
725   return ((const struct cxx_int_tree_map *)item)->uid;
726 }
727
728 /* A stable comparison routine for use with splay trees and DECLs.  */
729
730 static int
731 splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
732 {
733   tree a = (tree) xa;
734   tree b = (tree) xb;
735
736   return DECL_UID (a) - DECL_UID (b);
737 }
738
739 /* OpenMP context during genericization.  */
740
741 struct cp_genericize_omp_taskreg
742 {
743   bool is_parallel;
744   bool default_shared;
745   struct cp_genericize_omp_taskreg *outer;
746   splay_tree variables;
747 };
748
749 /* Return true if genericization should try to determine if
750    DECL is firstprivate or shared within task regions.  */
751
752 static bool
753 omp_var_to_track (tree decl)
754 {
755   tree type = TREE_TYPE (decl);
756   if (is_invisiref_parm (decl))
757     type = TREE_TYPE (type);
758   while (TREE_CODE (type) == ARRAY_TYPE)
759     type = TREE_TYPE (type);
760   if (type == error_mark_node || !CLASS_TYPE_P (type))
761     return false;
762   if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl))
763     return false;
764   if (cxx_omp_predetermined_sharing (decl) != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
765     return false;
766   return true;
767 }
768
769 /* Note DECL use in OpenMP region OMP_CTX during genericization.  */
770
771 static void
772 omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl)
773 {
774   splay_tree_node n = splay_tree_lookup (omp_ctx->variables,
775                                          (splay_tree_key) decl);
776   if (n == NULL)
777     {
778       int flags = OMP_CLAUSE_DEFAULT_SHARED;
779       if (omp_ctx->outer)
780         omp_cxx_notice_variable (omp_ctx->outer, decl);
781       if (!omp_ctx->default_shared)
782         {
783           struct cp_genericize_omp_taskreg *octx;
784
785           for (octx = omp_ctx->outer; octx; octx = octx->outer)
786             {
787               n = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
788               if (n && n->value != OMP_CLAUSE_DEFAULT_SHARED)
789                 {
790                   flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
791                   break;
792                 }
793               if (octx->is_parallel)
794                 break;
795             }
796           if (octx == NULL
797               && (TREE_CODE (decl) == PARM_DECL
798                   || (!(TREE_STATIC (decl) || DECL_EXTERNAL (decl))
799                       && DECL_CONTEXT (decl) == current_function_decl)))
800             flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
801           if (flags == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
802             {
803               /* DECL is implicitly determined firstprivate in
804                  the current task construct.  Ensure copy ctor and
805                  dtor are instantiated, because during gimplification
806                  it will be already too late.  */
807               tree type = TREE_TYPE (decl);
808               if (is_invisiref_parm (decl))
809                 type = TREE_TYPE (type);
810               while (TREE_CODE (type) == ARRAY_TYPE)
811                 type = TREE_TYPE (type);
812               get_copy_ctor (type, tf_none);
813               get_dtor (type, tf_none);
814             }
815         }
816       splay_tree_insert (omp_ctx->variables, (splay_tree_key) decl, flags);
817     }
818 }
819
820 /* Genericization context.  */
821
822 struct cp_genericize_data
823 {
824   struct pointer_set_t *p_set;
825   vec<tree> bind_expr_stack;
826   struct cp_genericize_omp_taskreg *omp_ctx;
827 };
828
829 /* Perform any pre-gimplification lowering of C++ front end trees to
830    GENERIC.  */
831
832 static tree
833 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
834 {
835   tree stmt = *stmt_p;
836   struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
837   struct pointer_set_t *p_set = wtd->p_set;
838
839   /* If in an OpenMP context, note var uses.  */
840   if (__builtin_expect (wtd->omp_ctx != NULL, 0)
841       && (TREE_CODE (stmt) == VAR_DECL
842           || TREE_CODE (stmt) == PARM_DECL
843           || TREE_CODE (stmt) == RESULT_DECL)
844       && omp_var_to_track (stmt))
845     omp_cxx_notice_variable (wtd->omp_ctx, stmt);
846
847   if (is_invisiref_parm (stmt)
848       /* Don't dereference parms in a thunk, pass the references through. */
849       && !(DECL_THUNK_P (current_function_decl)
850            && TREE_CODE (stmt) == PARM_DECL))
851     {
852       *stmt_p = convert_from_reference (stmt);
853       *walk_subtrees = 0;
854       return NULL;
855     }
856
857   /* Map block scope extern declarations to visible declarations with the
858      same name and type in outer scopes if any.  */
859   if (cp_function_chain->extern_decl_map
860       && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
861       && DECL_EXTERNAL (stmt))
862     {
863       struct cxx_int_tree_map *h, in;
864       in.uid = DECL_UID (stmt);
865       h = (struct cxx_int_tree_map *)
866           htab_find_with_hash (cp_function_chain->extern_decl_map,
867                                &in, in.uid);
868       if (h)
869         {
870           *stmt_p = h->to;
871           *walk_subtrees = 0;
872           return NULL;
873         }
874     }
875
876   /* Other than invisiref parms, don't walk the same tree twice.  */
877   if (pointer_set_contains (p_set, stmt))
878     {
879       *walk_subtrees = 0;
880       return NULL_TREE;
881     }
882
883   if (TREE_CODE (stmt) == ADDR_EXPR
884       && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
885     {
886       /* If in an OpenMP context, note var uses.  */
887       if (__builtin_expect (wtd->omp_ctx != NULL, 0)
888           && omp_var_to_track (TREE_OPERAND (stmt, 0)))
889         omp_cxx_notice_variable (wtd->omp_ctx, TREE_OPERAND (stmt, 0));
890       *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
891       *walk_subtrees = 0;
892     }
893   else if (TREE_CODE (stmt) == RETURN_EXPR
894            && TREE_OPERAND (stmt, 0)
895            && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
896     /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
897     *walk_subtrees = 0;
898   else if (TREE_CODE (stmt) == OMP_CLAUSE)
899     switch (OMP_CLAUSE_CODE (stmt))
900       {
901       case OMP_CLAUSE_LASTPRIVATE:
902         /* Don't dereference an invisiref in OpenMP clauses.  */
903         if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
904           {
905             *walk_subtrees = 0;
906             if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt))
907               cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt),
908                             cp_genericize_r, data, NULL);
909           }
910         break;
911       case OMP_CLAUSE_PRIVATE:
912         /* Don't dereference an invisiref in OpenMP clauses.  */
913         if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
914           *walk_subtrees = 0;
915         else if (wtd->omp_ctx != NULL)
916           {
917             /* Private clause doesn't cause any references to the
918                var in outer contexts, avoid calling
919                omp_cxx_notice_variable for it.  */
920             struct cp_genericize_omp_taskreg *old = wtd->omp_ctx;
921             wtd->omp_ctx = NULL;
922             cp_walk_tree (&OMP_CLAUSE_DECL (stmt), cp_genericize_r,
923                           data, NULL);
924             wtd->omp_ctx = old;
925             *walk_subtrees = 0;
926           }
927         break;
928       case OMP_CLAUSE_SHARED:
929       case OMP_CLAUSE_FIRSTPRIVATE:
930       case OMP_CLAUSE_COPYIN:
931       case OMP_CLAUSE_COPYPRIVATE:
932         /* Don't dereference an invisiref in OpenMP clauses.  */
933         if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
934           *walk_subtrees = 0;
935         break;
936       case OMP_CLAUSE_REDUCTION:
937         gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
938         break;
939       default:
940         break;
941       }
942   else if (IS_TYPE_OR_DECL_P (stmt))
943     *walk_subtrees = 0;
944
945   /* Due to the way voidify_wrapper_expr is written, we don't get a chance
946      to lower this construct before scanning it, so we need to lower these
947      before doing anything else.  */
948   else if (TREE_CODE (stmt) == CLEANUP_STMT)
949     *stmt_p = build2_loc (EXPR_LOCATION (stmt),
950                           CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
951                                                  : TRY_FINALLY_EXPR,
952                           void_type_node,
953                           CLEANUP_BODY (stmt),
954                           CLEANUP_EXPR (stmt));
955
956   else if (TREE_CODE (stmt) == IF_STMT)
957     {
958       genericize_if_stmt (stmt_p);
959       /* *stmt_p has changed, tail recurse to handle it again.  */
960       return cp_genericize_r (stmt_p, walk_subtrees, data);
961     }
962
963   /* COND_EXPR might have incompatible types in branches if one or both
964      arms are bitfields.  Fix it up now.  */
965   else if (TREE_CODE (stmt) == COND_EXPR)
966     {
967       tree type_left
968         = (TREE_OPERAND (stmt, 1)
969            ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1))
970            : NULL_TREE);
971       tree type_right
972         = (TREE_OPERAND (stmt, 2)
973            ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2))
974            : NULL_TREE);
975       if (type_left
976           && !useless_type_conversion_p (TREE_TYPE (stmt),
977                                          TREE_TYPE (TREE_OPERAND (stmt, 1))))
978         {
979           TREE_OPERAND (stmt, 1)
980             = fold_convert (type_left, TREE_OPERAND (stmt, 1));
981           gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
982                                                  type_left));
983         }
984       if (type_right
985           && !useless_type_conversion_p (TREE_TYPE (stmt),
986                                          TREE_TYPE (TREE_OPERAND (stmt, 2))))
987         {
988           TREE_OPERAND (stmt, 2)
989             = fold_convert (type_right, TREE_OPERAND (stmt, 2));
990           gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
991                                                  type_right));
992         }
993     }
994
995   else if (TREE_CODE (stmt) == BIND_EXPR)
996     {
997       if (__builtin_expect (wtd->omp_ctx != NULL, 0))
998         {
999           tree decl;
1000           for (decl = BIND_EXPR_VARS (stmt); decl; decl = DECL_CHAIN (decl))
1001             if (TREE_CODE (decl) == VAR_DECL
1002                 && !DECL_EXTERNAL (decl)
1003                 && omp_var_to_track (decl))
1004               {
1005                 splay_tree_node n
1006                   = splay_tree_lookup (wtd->omp_ctx->variables,
1007                                        (splay_tree_key) decl);
1008                 if (n == NULL)
1009                   splay_tree_insert (wtd->omp_ctx->variables,
1010                                      (splay_tree_key) decl,
1011                                      TREE_STATIC (decl)
1012                                      ? OMP_CLAUSE_DEFAULT_SHARED
1013                                      : OMP_CLAUSE_DEFAULT_PRIVATE);
1014               }
1015         }
1016       wtd->bind_expr_stack.safe_push (stmt);
1017       cp_walk_tree (&BIND_EXPR_BODY (stmt),
1018                     cp_genericize_r, data, NULL);
1019       wtd->bind_expr_stack.pop ();
1020     }
1021
1022   else if (TREE_CODE (stmt) == USING_STMT)
1023     {
1024       tree block = NULL_TREE;
1025
1026       /* Get the innermost inclosing GIMPLE_BIND that has a non NULL
1027          BLOCK, and append an IMPORTED_DECL to its
1028          BLOCK_VARS chained list.  */
1029       if (wtd->bind_expr_stack.exists ())
1030         {
1031           int i;
1032           for (i = wtd->bind_expr_stack.length () - 1; i >= 0; i--)
1033             if ((block = BIND_EXPR_BLOCK (wtd->bind_expr_stack[i])))
1034               break;
1035         }
1036       if (block)
1037         {
1038           tree using_directive;
1039           gcc_assert (TREE_OPERAND (stmt, 0));
1040
1041           using_directive = make_node (IMPORTED_DECL);
1042           TREE_TYPE (using_directive) = void_type_node;
1043
1044           IMPORTED_DECL_ASSOCIATED_DECL (using_directive)
1045             = TREE_OPERAND (stmt, 0);
1046           DECL_CHAIN (using_directive) = BLOCK_VARS (block);
1047           BLOCK_VARS (block) = using_directive;
1048         }
1049       /* The USING_STMT won't appear in GENERIC.  */
1050       *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
1051       *walk_subtrees = 0;
1052     }
1053
1054   else if (TREE_CODE (stmt) == DECL_EXPR
1055            && TREE_CODE (DECL_EXPR_DECL (stmt)) == USING_DECL)
1056     {
1057       /* Using decls inside DECL_EXPRs are just dropped on the floor.  */
1058       *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
1059       *walk_subtrees = 0;
1060     }
1061   else if (TREE_CODE (stmt) == OMP_PARALLEL || TREE_CODE (stmt) == OMP_TASK)
1062     {
1063       struct cp_genericize_omp_taskreg omp_ctx;
1064       tree c, decl;
1065       splay_tree_node n;
1066
1067       *walk_subtrees = 0;
1068       cp_walk_tree (&OMP_CLAUSES (stmt), cp_genericize_r, data, NULL);
1069       omp_ctx.is_parallel = TREE_CODE (stmt) == OMP_PARALLEL;
1070       omp_ctx.default_shared = omp_ctx.is_parallel;
1071       omp_ctx.outer = wtd->omp_ctx;
1072       omp_ctx.variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
1073       wtd->omp_ctx = &omp_ctx;
1074       for (c = OMP_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
1075         switch (OMP_CLAUSE_CODE (c))
1076           {
1077           case OMP_CLAUSE_SHARED:
1078           case OMP_CLAUSE_PRIVATE:
1079           case OMP_CLAUSE_FIRSTPRIVATE:
1080           case OMP_CLAUSE_LASTPRIVATE:
1081             decl = OMP_CLAUSE_DECL (c);
1082             if (decl == error_mark_node || !omp_var_to_track (decl))
1083               break;
1084             n = splay_tree_lookup (omp_ctx.variables, (splay_tree_key) decl);
1085             if (n != NULL)
1086               break;
1087             splay_tree_insert (omp_ctx.variables, (splay_tree_key) decl,
1088                                OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1089                                ? OMP_CLAUSE_DEFAULT_SHARED
1090                                : OMP_CLAUSE_DEFAULT_PRIVATE);
1091             if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE
1092                 && omp_ctx.outer)
1093               omp_cxx_notice_variable (omp_ctx.outer, decl);
1094             break;
1095           case OMP_CLAUSE_DEFAULT:
1096             if (OMP_CLAUSE_DEFAULT_KIND (c) == OMP_CLAUSE_DEFAULT_SHARED)
1097               omp_ctx.default_shared = true;
1098           default:
1099             break;
1100           }
1101       cp_walk_tree (&OMP_BODY (stmt), cp_genericize_r, data, NULL);
1102       wtd->omp_ctx = omp_ctx.outer;
1103       splay_tree_delete (omp_ctx.variables);
1104     }
1105   else if (TREE_CODE (stmt) == CONVERT_EXPR)
1106     gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt));
1107   else if (TREE_CODE (stmt) == FOR_STMT)
1108     genericize_for_stmt (stmt_p, walk_subtrees, data);
1109   else if (TREE_CODE (stmt) == WHILE_STMT)
1110     genericize_while_stmt (stmt_p, walk_subtrees, data);
1111   else if (TREE_CODE (stmt) == DO_STMT)
1112     genericize_do_stmt (stmt_p, walk_subtrees, data);
1113   else if (TREE_CODE (stmt) == SWITCH_STMT)
1114     genericize_switch_stmt (stmt_p, walk_subtrees, data);
1115   else if (TREE_CODE (stmt) == CONTINUE_STMT)
1116     genericize_continue_stmt (stmt_p);
1117   else if (TREE_CODE (stmt) == BREAK_STMT)
1118     genericize_break_stmt (stmt_p);
1119   else if (TREE_CODE (stmt) == OMP_FOR)
1120     genericize_omp_for_stmt (stmt_p, walk_subtrees, data);
1121   else if (TREE_CODE (stmt) == SIZEOF_EXPR)
1122     {
1123       if (SIZEOF_EXPR_TYPE_P (stmt))
1124         *stmt_p
1125           = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (stmt, 0)),
1126                                         SIZEOF_EXPR, false);
1127       else if (TYPE_P (TREE_OPERAND (stmt, 0)))
1128         *stmt_p = cxx_sizeof_or_alignof_type (TREE_OPERAND (stmt, 0),
1129                                               SIZEOF_EXPR, false);
1130       else
1131         *stmt_p = cxx_sizeof_or_alignof_expr (TREE_OPERAND (stmt, 0),
1132                                               SIZEOF_EXPR, false);
1133       if (*stmt_p == error_mark_node)
1134         *stmt_p = size_one_node;
1135       return NULL;
1136     }    
1137
1138   pointer_set_insert (p_set, *stmt_p);
1139
1140   return NULL;
1141 }
1142
1143 /* Lower C++ front end trees to GENERIC in T_P.  */
1144
1145 static void
1146 cp_genericize_tree (tree* t_p)
1147 {
1148   struct cp_genericize_data wtd;
1149
1150   wtd.p_set = pointer_set_create ();
1151   wtd.bind_expr_stack.create (0);
1152   wtd.omp_ctx = NULL;
1153   cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
1154   pointer_set_destroy (wtd.p_set);
1155   wtd.bind_expr_stack.release ();
1156 }
1157
1158 void
1159 cp_genericize (tree fndecl)
1160 {
1161   tree t;
1162
1163   /* Fix up the types of parms passed by invisible reference.  */
1164   for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t))
1165     if (TREE_ADDRESSABLE (TREE_TYPE (t)))
1166       {
1167         /* If a function's arguments are copied to create a thunk,
1168            then DECL_BY_REFERENCE will be set -- but the type of the
1169            argument will be a pointer type, so we will never get
1170            here.  */
1171         gcc_assert (!DECL_BY_REFERENCE (t));
1172         gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
1173         TREE_TYPE (t) = DECL_ARG_TYPE (t);
1174         DECL_BY_REFERENCE (t) = 1;
1175         TREE_ADDRESSABLE (t) = 0;
1176         relayout_decl (t);
1177       }
1178
1179   /* Do the same for the return value.  */
1180   if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
1181     {
1182       t = DECL_RESULT (fndecl);
1183       TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
1184       DECL_BY_REFERENCE (t) = 1;
1185       TREE_ADDRESSABLE (t) = 0;
1186       relayout_decl (t);
1187       if (DECL_NAME (t))
1188         {
1189           /* Adjust DECL_VALUE_EXPR of the original var.  */
1190           tree outer = outer_curly_brace_block (current_function_decl);
1191           tree var;
1192
1193           if (outer)
1194             for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
1195               if (DECL_NAME (t) == DECL_NAME (var)
1196                   && DECL_HAS_VALUE_EXPR_P (var)
1197                   && DECL_VALUE_EXPR (var) == t)
1198                 {
1199                   tree val = convert_from_reference (t);
1200                   SET_DECL_VALUE_EXPR (var, val);
1201                   break;
1202                 }
1203         }
1204     }
1205
1206   /* If we're a clone, the body is already GIMPLE.  */
1207   if (DECL_CLONED_FUNCTION_P (fndecl))
1208     return;
1209
1210   /* We do want to see every occurrence of the parms, so we can't just use
1211      walk_tree's hash functionality.  */
1212   cp_genericize_tree (&DECL_SAVED_TREE (fndecl));
1213
1214   /* Do everything else.  */
1215   c_genericize (fndecl);
1216
1217   gcc_assert (bc_label[bc_break] == NULL);
1218   gcc_assert (bc_label[bc_continue] == NULL);
1219 }
1220 \f
1221 /* Build code to apply FN to each member of ARG1 and ARG2.  FN may be
1222    NULL if there is in fact nothing to do.  ARG2 may be null if FN
1223    actually only takes one argument.  */
1224
1225 static tree
1226 cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
1227 {
1228   tree defparm, parm, t;
1229   int i = 0;
1230   int nargs;
1231   tree *argarray;
1232
1233   if (fn == NULL)
1234     return NULL;
1235
1236   nargs = list_length (DECL_ARGUMENTS (fn));
1237   argarray = XALLOCAVEC (tree, nargs);
1238
1239   defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
1240   if (arg2)
1241     defparm = TREE_CHAIN (defparm);
1242
1243   if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
1244     {
1245       tree inner_type = TREE_TYPE (arg1);
1246       tree start1, end1, p1;
1247       tree start2 = NULL, p2 = NULL;
1248       tree ret = NULL, lab;
1249
1250       start1 = arg1;
1251       start2 = arg2;
1252       do
1253         {
1254           inner_type = TREE_TYPE (inner_type);
1255           start1 = build4 (ARRAY_REF, inner_type, start1,
1256                            size_zero_node, NULL, NULL);
1257           if (arg2)
1258             start2 = build4 (ARRAY_REF, inner_type, start2,
1259                              size_zero_node, NULL, NULL);
1260         }
1261       while (TREE_CODE (inner_type) == ARRAY_TYPE);
1262       start1 = build_fold_addr_expr_loc (input_location, start1);
1263       if (arg2)
1264         start2 = build_fold_addr_expr_loc (input_location, start2);
1265
1266       end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
1267       end1 = fold_build_pointer_plus (start1, end1);
1268
1269       p1 = create_tmp_var (TREE_TYPE (start1), NULL);
1270       t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, start1);
1271       append_to_statement_list (t, &ret);
1272
1273       if (arg2)
1274         {
1275           p2 = create_tmp_var (TREE_TYPE (start2), NULL);
1276           t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, start2);
1277           append_to_statement_list (t, &ret);
1278         }
1279
1280       lab = create_artificial_label (input_location);
1281       t = build1 (LABEL_EXPR, void_type_node, lab);
1282       append_to_statement_list (t, &ret);
1283
1284       argarray[i++] = p1;
1285       if (arg2)
1286         argarray[i++] = p2;
1287       /* Handle default arguments.  */
1288       for (parm = defparm; parm && parm != void_list_node;
1289            parm = TREE_CHAIN (parm), i++)
1290         argarray[i] = convert_default_arg (TREE_VALUE (parm),
1291                                            TREE_PURPOSE (parm), fn, i,
1292                                            tf_warning_or_error);
1293       t = build_call_a (fn, i, argarray);
1294       t = fold_convert (void_type_node, t);
1295       t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
1296       append_to_statement_list (t, &ret);
1297
1298       t = fold_build_pointer_plus (p1, TYPE_SIZE_UNIT (inner_type));
1299       t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, t);
1300       append_to_statement_list (t, &ret);
1301
1302       if (arg2)
1303         {
1304           t = fold_build_pointer_plus (p2, TYPE_SIZE_UNIT (inner_type));
1305           t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, t);
1306           append_to_statement_list (t, &ret);
1307         }
1308
1309       t = build2 (NE_EXPR, boolean_type_node, p1, end1);
1310       t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
1311       append_to_statement_list (t, &ret);
1312
1313       return ret;
1314     }
1315   else
1316     {
1317       argarray[i++] = build_fold_addr_expr_loc (input_location, arg1);
1318       if (arg2)
1319         argarray[i++] = build_fold_addr_expr_loc (input_location, arg2);
1320       /* Handle default arguments.  */
1321       for (parm = defparm; parm && parm != void_list_node;
1322            parm = TREE_CHAIN (parm), i++)
1323         argarray[i] = convert_default_arg (TREE_VALUE (parm),
1324                                            TREE_PURPOSE (parm),
1325                                            fn, i, tf_warning_or_error);
1326       t = build_call_a (fn, i, argarray);
1327       t = fold_convert (void_type_node, t);
1328       return fold_build_cleanup_point_expr (TREE_TYPE (t), t);
1329     }
1330 }
1331
1332 /* Return code to initialize DECL with its default constructor, or
1333    NULL if there's nothing to do.  */
1334
1335 tree
1336 cxx_omp_clause_default_ctor (tree clause, tree decl, tree /*outer*/)
1337 {
1338   tree info = CP_OMP_CLAUSE_INFO (clause);
1339   tree ret = NULL;
1340
1341   if (info)
1342     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
1343
1344   return ret;
1345 }
1346
1347 /* Return code to initialize DST with a copy constructor from SRC.  */
1348
1349 tree
1350 cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
1351 {
1352   tree info = CP_OMP_CLAUSE_INFO (clause);
1353   tree ret = NULL;
1354
1355   if (info)
1356     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
1357   if (ret == NULL)
1358     ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
1359
1360   return ret;
1361 }
1362
1363 /* Similarly, except use an assignment operator instead.  */
1364
1365 tree
1366 cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
1367 {
1368   tree info = CP_OMP_CLAUSE_INFO (clause);
1369   tree ret = NULL;
1370
1371   if (info)
1372     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
1373   if (ret == NULL)
1374     ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
1375
1376   return ret;
1377 }
1378
1379 /* Return code to destroy DECL.  */
1380
1381 tree
1382 cxx_omp_clause_dtor (tree clause, tree decl)
1383 {
1384   tree info = CP_OMP_CLAUSE_INFO (clause);
1385   tree ret = NULL;
1386
1387   if (info)
1388     ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
1389
1390   return ret;
1391 }
1392
1393 /* True if OpenMP should privatize what this DECL points to rather
1394    than the DECL itself.  */
1395
1396 bool
1397 cxx_omp_privatize_by_reference (const_tree decl)
1398 {
1399   return is_invisiref_parm (decl);
1400 }
1401
1402 /* Return true if DECL is const qualified var having no mutable member.  */
1403 bool
1404 cxx_omp_const_qual_no_mutable (tree decl)
1405 {
1406   tree type = TREE_TYPE (decl);
1407   if (TREE_CODE (type) == REFERENCE_TYPE)
1408     {
1409       if (!is_invisiref_parm (decl))
1410         return false;
1411       type = TREE_TYPE (type);
1412
1413       if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl))
1414         {
1415           /* NVR doesn't preserve const qualification of the
1416              variable's type.  */
1417           tree outer = outer_curly_brace_block (current_function_decl);
1418           tree var;
1419
1420           if (outer)
1421             for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
1422               if (DECL_NAME (decl) == DECL_NAME (var)
1423                   && (TYPE_MAIN_VARIANT (type)
1424                       == TYPE_MAIN_VARIANT (TREE_TYPE (var))))
1425                 {
1426                   if (TYPE_READONLY (TREE_TYPE (var)))
1427                     type = TREE_TYPE (var);
1428                   break;
1429                 }
1430         }
1431     }
1432
1433   if (type == error_mark_node)
1434     return false;
1435
1436   /* Variables with const-qualified type having no mutable member
1437      are predetermined shared.  */
1438   if (TYPE_READONLY (type) && !cp_has_mutable_p (type))
1439     return true;
1440
1441   return false;
1442 }
1443
1444 /* True if OpenMP sharing attribute of DECL is predetermined.  */
1445
1446 enum omp_clause_default_kind
1447 cxx_omp_predetermined_sharing (tree decl)
1448 {
1449   /* Static data members are predetermined shared.  */
1450   if (TREE_STATIC (decl))
1451     {
1452       tree ctx = CP_DECL_CONTEXT (decl);
1453       if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
1454         return OMP_CLAUSE_DEFAULT_SHARED;
1455     }
1456
1457   /* Const qualified vars having no mutable member are predetermined
1458      shared.  */
1459   if (cxx_omp_const_qual_no_mutable (decl))
1460     return OMP_CLAUSE_DEFAULT_SHARED;
1461
1462   return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
1463 }
1464
1465 /* Finalize an implicitly determined clause.  */
1466
1467 void
1468 cxx_omp_finish_clause (tree c)
1469 {
1470   tree decl, inner_type;
1471   bool make_shared = false;
1472
1473   if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE)
1474     return;
1475
1476   decl = OMP_CLAUSE_DECL (c);
1477   decl = require_complete_type (decl);
1478   inner_type = TREE_TYPE (decl);
1479   if (decl == error_mark_node)
1480     make_shared = true;
1481   else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
1482     {
1483       if (is_invisiref_parm (decl))
1484         inner_type = TREE_TYPE (inner_type);
1485       else
1486         {
1487           error ("%qE implicitly determined as %<firstprivate%> has reference type",
1488                  decl);
1489           make_shared = true;
1490         }
1491     }
1492
1493   /* We're interested in the base element, not arrays.  */
1494   while (TREE_CODE (inner_type) == ARRAY_TYPE)
1495     inner_type = TREE_TYPE (inner_type);
1496
1497   /* Check for special function availability by building a call to one.
1498      Save the results, because later we won't be in the right context
1499      for making these queries.  */
1500   if (!make_shared
1501       && CLASS_TYPE_P (inner_type)
1502       && cxx_omp_create_clause_info (c, inner_type, false, true, false))
1503     make_shared = true;
1504
1505   if (make_shared)
1506     OMP_CLAUSE_CODE (c) = OMP_CLAUSE_SHARED;
1507 }