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