1 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
3 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
4 Free Software Foundation, Inc.
5 Contributed by Jason Merrill <jason@redhat.com>
7 This file is part of GCC.
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
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
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/>. */
25 #include "coretypes.h"
29 #include "c-family/c-common.h"
30 #include "tree-iterator.h"
33 #include "pointer-set.h"
35 #include "splay-tree.h"
37 /* Forward declarations. */
39 static tree
cp_genericize_r (tree
*, int *, void *);
40 static void cp_genericize_tree (tree
*);
42 /* Local declarations. */
44 enum bc_t
{ bc_break
= 0, bc_continue
= 1 };
46 /* Stack of labels which are targets for "break" or "continue",
47 linked through TREE_CHAIN. */
48 static tree bc_label
[2];
50 /* Begin a scope which can be exited by a break or continue statement. BC
53 Just creates a label with location LOCATION and pushes it into the current
57 begin_bc_block (enum bc_t bc
, location_t location
)
59 tree label
= create_artificial_label (location
);
60 DECL_CHAIN (label
) = bc_label
[bc
];
65 /* Finish a scope which can be exited by a break or continue statement.
66 LABEL was returned from the most recent call to begin_bc_block. BLOCK is
67 an expression for the contents of the scope.
69 If we saw a break (or continue) in the scope, append a LABEL_EXPR to
70 BLOCK. Otherwise, just forget the label. */
73 finish_bc_block (tree
*block
, enum bc_t bc
, tree label
)
75 gcc_assert (label
== bc_label
[bc
]);
77 if (TREE_USED (label
))
78 append_to_statement_list (build1 (LABEL_EXPR
, void_type_node
, label
),
81 bc_label
[bc
] = DECL_CHAIN (label
);
82 DECL_CHAIN (label
) = NULL_TREE
;
85 /* Get the LABEL_EXPR to represent a break or continue statement
86 in the current block scope. BC indicates which. */
89 get_bc_label (enum bc_t bc
)
91 tree label
= bc_label
[bc
];
93 /* Mark the label used for finish_bc_block. */
94 TREE_USED (label
) = 1;
98 /* Genericize a TRY_BLOCK. */
101 genericize_try_block (tree
*stmt_p
)
103 tree body
= TRY_STMTS (*stmt_p
);
104 tree cleanup
= TRY_HANDLERS (*stmt_p
);
106 *stmt_p
= build2 (TRY_CATCH_EXPR
, void_type_node
, body
, cleanup
);
109 /* Genericize a HANDLER by converting to a CATCH_EXPR. */
112 genericize_catch_block (tree
*stmt_p
)
114 tree type
= HANDLER_TYPE (*stmt_p
);
115 tree body
= HANDLER_BODY (*stmt_p
);
117 /* FIXME should the caught type go in TREE_TYPE? */
118 *stmt_p
= build2 (CATCH_EXPR
, void_type_node
, type
, body
);
121 /* A terser interface for building a representation of an exception
125 build_gimple_eh_filter_tree (tree body
, tree allowed
, tree failure
)
129 /* FIXME should the allowed types go in TREE_TYPE? */
130 t
= build2 (EH_FILTER_EXPR
, void_type_node
, allowed
, NULL_TREE
);
131 append_to_statement_list (failure
, &EH_FILTER_FAILURE (t
));
133 t
= build2 (TRY_CATCH_EXPR
, void_type_node
, NULL_TREE
, t
);
134 append_to_statement_list (body
, &TREE_OPERAND (t
, 0));
139 /* Genericize an EH_SPEC_BLOCK by converting it to a
140 TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
143 genericize_eh_spec_block (tree
*stmt_p
)
145 tree body
= EH_SPEC_STMTS (*stmt_p
);
146 tree allowed
= EH_SPEC_RAISES (*stmt_p
);
147 tree failure
= build_call_n (call_unexpected_node
, 1, build_exc_ptr ());
149 *stmt_p
= build_gimple_eh_filter_tree (body
, allowed
, failure
);
150 TREE_NO_WARNING (*stmt_p
) = true;
151 TREE_NO_WARNING (TREE_OPERAND (*stmt_p
, 1)) = true;
154 /* Genericize an IF_STMT by turning it into a COND_EXPR. */
157 genericize_if_stmt (tree
*stmt_p
)
159 tree stmt
, cond
, then_
, else_
;
160 location_t locus
= EXPR_LOCATION (*stmt_p
);
163 cond
= IF_COND (stmt
);
164 then_
= THEN_CLAUSE (stmt
);
165 else_
= ELSE_CLAUSE (stmt
);
168 then_
= build_empty_stmt (locus
);
170 else_
= build_empty_stmt (locus
);
172 if (integer_nonzerop (cond
) && !TREE_SIDE_EFFECTS (else_
))
174 else if (integer_zerop (cond
) && !TREE_SIDE_EFFECTS (then_
))
177 stmt
= build3 (COND_EXPR
, void_type_node
, cond
, then_
, else_
);
178 if (CAN_HAVE_LOCATION_P (stmt
) && !EXPR_HAS_LOCATION (stmt
))
179 SET_EXPR_LOCATION (stmt
, locus
);
183 /* Build a generic representation of one of the C loop forms. COND is the
184 loop condition or NULL_TREE. BODY is the (possibly compound) statement
185 controlled by the loop. INCR is the increment expression of a for-loop,
186 or NULL_TREE. COND_IS_FIRST indicates whether the condition is
187 evaluated before the loop body as in while and for loops, or after the
188 loop body as in do-while loops. */
191 genericize_cp_loop (tree
*stmt_p
, location_t start_locus
, tree cond
, tree body
,
192 tree incr
, bool cond_is_first
, int *walk_subtrees
,
196 tree entry
= NULL
, exit
= NULL
, t
;
197 tree stmt_list
= NULL
;
199 blab
= begin_bc_block (bc_break
, start_locus
);
200 clab
= begin_bc_block (bc_continue
, start_locus
);
202 if (incr
&& EXPR_P (incr
))
203 SET_EXPR_LOCATION (incr
, start_locus
);
205 cp_walk_tree (&cond
, cp_genericize_r
, data
, NULL
);
206 cp_walk_tree (&body
, cp_genericize_r
, data
, NULL
);
207 cp_walk_tree (&incr
, cp_genericize_r
, data
, NULL
);
210 /* If condition is zero don't generate a loop construct. */
211 if (cond
&& integer_zerop (cond
))
215 t
= build1_loc (start_locus
, GOTO_EXPR
, void_type_node
,
216 get_bc_label (bc_break
));
217 append_to_statement_list (t
, &stmt_list
);
222 /* Expand to gotos, just like c_finish_loop. TODO: Use LOOP_EXPR. */
223 tree top
= build1 (LABEL_EXPR
, void_type_node
,
224 create_artificial_label (start_locus
));
226 /* If we have an exit condition, then we build an IF with gotos either
227 out of the loop, or to the top of it. If there's no exit condition,
228 then we just build a jump back to the top. */
229 exit
= build1 (GOTO_EXPR
, void_type_node
, LABEL_EXPR_LABEL (top
));
231 if (cond
&& !integer_nonzerop (cond
))
233 /* Canonicalize the loop condition to the end. This means
234 generating a branch to the loop condition. Reuse the
235 continue label, if possible. */
240 entry
= build1 (LABEL_EXPR
, void_type_node
,
241 create_artificial_label (start_locus
));
242 t
= build1_loc (start_locus
, GOTO_EXPR
, void_type_node
,
243 LABEL_EXPR_LABEL (entry
));
246 t
= build1_loc (start_locus
, GOTO_EXPR
, void_type_node
,
247 get_bc_label (bc_continue
));
248 append_to_statement_list (t
, &stmt_list
);
251 t
= build1 (GOTO_EXPR
, void_type_node
, get_bc_label (bc_break
));
252 exit
= fold_build3_loc (start_locus
,
253 COND_EXPR
, void_type_node
, cond
, exit
, t
);
256 append_to_statement_list (top
, &stmt_list
);
259 append_to_statement_list (body
, &stmt_list
);
260 finish_bc_block (&stmt_list
, bc_continue
, clab
);
261 append_to_statement_list (incr
, &stmt_list
);
262 append_to_statement_list (entry
, &stmt_list
);
263 append_to_statement_list (exit
, &stmt_list
);
264 finish_bc_block (&stmt_list
, bc_break
, blab
);
266 if (stmt_list
== NULL_TREE
)
267 stmt_list
= build1 (NOP_EXPR
, void_type_node
, integer_zero_node
);
272 /* Genericize a FOR_STMT node *STMT_P. */
275 genericize_for_stmt (tree
*stmt_p
, int *walk_subtrees
, void *data
)
280 tree init
= FOR_INIT_STMT (stmt
);
284 cp_walk_tree (&init
, cp_genericize_r
, data
, NULL
);
285 append_to_statement_list (init
, &expr
);
288 genericize_cp_loop (&loop
, EXPR_LOCATION (stmt
), FOR_COND (stmt
),
289 FOR_BODY (stmt
), FOR_EXPR (stmt
), 1, walk_subtrees
, data
);
290 append_to_statement_list (loop
, &expr
);
294 /* Genericize a WHILE_STMT node *STMT_P. */
297 genericize_while_stmt (tree
*stmt_p
, int *walk_subtrees
, void *data
)
300 genericize_cp_loop (stmt_p
, EXPR_LOCATION (stmt
), WHILE_COND (stmt
),
301 WHILE_BODY (stmt
), NULL_TREE
, 1, walk_subtrees
, data
);
304 /* Genericize a DO_STMT node *STMT_P. */
307 genericize_do_stmt (tree
*stmt_p
, int *walk_subtrees
, void *data
)
310 genericize_cp_loop (stmt_p
, EXPR_LOCATION (stmt
), DO_COND (stmt
),
311 DO_BODY (stmt
), NULL_TREE
, 0, walk_subtrees
, data
);
314 /* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR. */
317 genericize_switch_stmt (tree
*stmt_p
, int *walk_subtrees
, void *data
)
320 tree break_block
, body
, cond
, type
;
321 location_t stmt_locus
= EXPR_LOCATION (stmt
);
323 break_block
= begin_bc_block (bc_break
, stmt_locus
);
325 body
= SWITCH_STMT_BODY (stmt
);
327 body
= build_empty_stmt (stmt_locus
);
328 cond
= SWITCH_STMT_COND (stmt
);
329 type
= SWITCH_STMT_TYPE (stmt
);
331 cp_walk_tree (&body
, cp_genericize_r
, data
, NULL
);
332 cp_walk_tree (&cond
, cp_genericize_r
, data
, NULL
);
333 cp_walk_tree (&type
, cp_genericize_r
, data
, NULL
);
336 *stmt_p
= build3_loc (stmt_locus
, SWITCH_EXPR
, type
, cond
, body
, NULL_TREE
);
337 finish_bc_block (stmt_p
, bc_break
, break_block
);
340 /* Genericize a CONTINUE_STMT node *STMT_P. */
343 genericize_continue_stmt (tree
*stmt_p
)
345 tree stmt_list
= NULL
;
346 tree pred
= build_predict_expr (PRED_CONTINUE
, NOT_TAKEN
);
347 tree label
= get_bc_label (bc_continue
);
348 location_t location
= EXPR_LOCATION (*stmt_p
);
349 tree jump
= build1_loc (location
, GOTO_EXPR
, void_type_node
, label
);
350 append_to_statement_list (pred
, &stmt_list
);
351 append_to_statement_list (jump
, &stmt_list
);
355 /* Genericize a BREAK_STMT node *STMT_P. */
358 genericize_break_stmt (tree
*stmt_p
)
360 tree label
= get_bc_label (bc_break
);
361 location_t location
= EXPR_LOCATION (*stmt_p
);
362 *stmt_p
= build1_loc (location
, GOTO_EXPR
, void_type_node
, label
);
365 /* Genericize a OMP_FOR node *STMT_P. */
368 genericize_omp_for_stmt (tree
*stmt_p
, int *walk_subtrees
, void *data
)
371 location_t locus
= EXPR_LOCATION (stmt
);
372 tree clab
= begin_bc_block (bc_continue
, locus
);
374 cp_walk_tree (&OMP_FOR_BODY (stmt
), cp_genericize_r
, data
, NULL
);
375 cp_walk_tree (&OMP_FOR_CLAUSES (stmt
), cp_genericize_r
, data
, NULL
);
376 cp_walk_tree (&OMP_FOR_INIT (stmt
), cp_genericize_r
, data
, NULL
);
377 cp_walk_tree (&OMP_FOR_COND (stmt
), cp_genericize_r
, data
, NULL
);
378 cp_walk_tree (&OMP_FOR_INCR (stmt
), cp_genericize_r
, data
, NULL
);
379 cp_walk_tree (&OMP_FOR_PRE_BODY (stmt
), cp_genericize_r
, data
, NULL
);
382 finish_bc_block (&OMP_FOR_BODY (stmt
), bc_continue
, clab
);
385 /* Hook into the middle of gimplifying an OMP_FOR node. */
387 static enum gimplify_status
388 cp_gimplify_omp_for (tree
*expr_p
, gimple_seq
*pre_p
)
390 tree for_stmt
= *expr_p
;
391 gimple_seq seq
= NULL
;
393 /* Protect ourselves from recursion. */
394 if (OMP_FOR_GIMPLIFYING_P (for_stmt
))
396 OMP_FOR_GIMPLIFYING_P (for_stmt
) = 1;
398 gimplify_and_add (for_stmt
, &seq
);
399 gimple_seq_add_seq (pre_p
, seq
);
401 OMP_FOR_GIMPLIFYING_P (for_stmt
) = 0;
406 /* Gimplify an EXPR_STMT node. */
409 gimplify_expr_stmt (tree
*stmt_p
)
411 tree stmt
= EXPR_STMT_EXPR (*stmt_p
);
413 if (stmt
== error_mark_node
)
416 /* Gimplification of a statement expression will nullify the
417 statement if all its side effects are moved to *PRE_P and *POST_P.
419 In this case we will not want to emit the gimplified statement.
420 However, we may still want to emit a warning, so we do that before
422 if (stmt
&& warn_unused_value
)
424 if (!TREE_SIDE_EFFECTS (stmt
))
426 if (!IS_EMPTY_STMT (stmt
)
427 && !VOID_TYPE_P (TREE_TYPE (stmt
))
428 && !TREE_NO_WARNING (stmt
))
429 warning (OPT_Wunused_value
, "statement with no effect");
432 warn_if_unused_value (stmt
, input_location
);
435 if (stmt
== NULL_TREE
)
436 stmt
= alloc_stmt_list ();
441 /* Gimplify initialization from an AGGR_INIT_EXPR. */
444 cp_gimplify_init_expr (tree
*expr_p
)
446 tree from
= TREE_OPERAND (*expr_p
, 1);
447 tree to
= TREE_OPERAND (*expr_p
, 0);
450 /* What about code that pulls out the temp and uses it elsewhere? I
451 think that such code never uses the TARGET_EXPR as an initializer. If
452 I'm wrong, we'll abort because the temp won't have any RTL. In that
453 case, I guess we'll need to replace references somehow. */
454 if (TREE_CODE (from
) == TARGET_EXPR
)
455 from
= TARGET_EXPR_INITIAL (from
);
457 /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
458 inside the TARGET_EXPR. */
461 tree sub
= TREE_CODE (t
) == COMPOUND_EXPR
? TREE_OPERAND (t
, 0) : t
;
463 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
464 replace the slot operand with our target.
466 Should we add a target parm to gimplify_expr instead? No, as in this
467 case we want to replace the INIT_EXPR. */
468 if (TREE_CODE (sub
) == AGGR_INIT_EXPR
469 || TREE_CODE (sub
) == VEC_INIT_EXPR
)
471 if (TREE_CODE (sub
) == AGGR_INIT_EXPR
)
472 AGGR_INIT_EXPR_SLOT (sub
) = to
;
474 VEC_INIT_EXPR_SLOT (sub
) = to
;
477 /* The initialization is now a side-effect, so the container can
480 TREE_TYPE (from
) = void_type_node
;
486 t
= TREE_OPERAND (t
, 1);
491 /* Gimplify a MUST_NOT_THROW_EXPR. */
493 static enum gimplify_status
494 gimplify_must_not_throw_expr (tree
*expr_p
, gimple_seq
*pre_p
)
497 tree temp
= voidify_wrapper_expr (stmt
, NULL
);
498 tree body
= TREE_OPERAND (stmt
, 0);
499 gimple_seq try_
= NULL
;
500 gimple_seq catch_
= NULL
;
503 gimplify_and_add (body
, &try_
);
504 mnt
= gimple_build_eh_must_not_throw (terminate_node
);
505 gimple_seq_add_stmt_without_update (&catch_
, mnt
);
506 mnt
= gimple_build_try (try_
, catch_
, GIMPLE_TRY_CATCH
);
508 gimple_seq_add_stmt_without_update (pre_p
, mnt
);
519 /* Do C++-specific gimplification. Args are as for gimplify_expr. */
522 cp_gimplify_expr (tree
*expr_p
, gimple_seq
*pre_p
, gimple_seq
*post_p
)
524 int saved_stmts_are_full_exprs_p
= 0;
525 enum tree_code code
= TREE_CODE (*expr_p
);
526 enum gimplify_status ret
;
528 if (STATEMENT_CODE_P (code
))
530 saved_stmts_are_full_exprs_p
= stmts_are_full_exprs_p ();
531 current_stmt_tree ()->stmts_are_full_exprs_p
532 = STMT_IS_FULL_EXPR_P (*expr_p
);
538 *expr_p
= cplus_expand_constant (*expr_p
);
543 simplify_aggr_init_expr (expr_p
);
549 location_t loc
= input_location
;
550 tree init
= VEC_INIT_EXPR_INIT (*expr_p
);
551 int from_array
= (init
&& TREE_CODE (TREE_TYPE (init
)) == ARRAY_TYPE
);
552 gcc_assert (EXPR_HAS_LOCATION (*expr_p
));
553 input_location
= EXPR_LOCATION (*expr_p
);
554 *expr_p
= build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p
), NULL_TREE
,
555 init
, VEC_INIT_EXPR_VALUE_INIT (*expr_p
),
557 tf_warning_or_error
);
558 cp_genericize_tree (expr_p
);
560 input_location
= loc
;
565 /* FIXME communicate throw type to back end, probably by moving
566 THROW_EXPR into ../tree.def. */
567 *expr_p
= TREE_OPERAND (*expr_p
, 0);
571 case MUST_NOT_THROW_EXPR
:
572 ret
= gimplify_must_not_throw_expr (expr_p
, pre_p
);
575 /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
576 LHS of an assignment might also be involved in the RHS, as in bug
579 cp_gimplify_init_expr (expr_p
);
580 if (TREE_CODE (*expr_p
) != INIT_EXPR
)
582 /* Otherwise fall through. */
585 /* If the back end isn't clever enough to know that the lhs and rhs
586 types are the same, add an explicit conversion. */
587 tree op0
= TREE_OPERAND (*expr_p
, 0);
588 tree op1
= TREE_OPERAND (*expr_p
, 1);
590 if (!error_operand_p (op0
)
591 && !error_operand_p (op1
)
592 && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0
))
593 || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1
)))
594 && !useless_type_conversion_p (TREE_TYPE (op1
), TREE_TYPE (op0
)))
595 TREE_OPERAND (*expr_p
, 1) = build1 (VIEW_CONVERT_EXPR
,
596 TREE_TYPE (op0
), op1
);
598 else if ((is_gimple_lvalue (op1
) || INDIRECT_REF_P (op1
)
599 || (TREE_CODE (op1
) == CONSTRUCTOR
600 && CONSTRUCTOR_NELTS (op1
) == 0
601 && !TREE_CLOBBER_P (op1
))
602 || (TREE_CODE (op1
) == CALL_EXPR
603 && !CALL_EXPR_RETURN_SLOT_OPT (op1
)))
604 && is_really_empty_class (TREE_TYPE (op0
)))
606 /* Remove any copies of empty classes. We check that the RHS
607 has a simple form so that TARGET_EXPRs and non-empty
608 CONSTRUCTORs get reduced properly, and we leave the return
609 slot optimization alone because it isn't a copy (FIXME so it
610 shouldn't be represented as one).
612 Also drop volatile variables on the RHS to avoid infinite
613 recursion from gimplify_expr trying to load the value. */
614 if (!TREE_SIDE_EFFECTS (op1
)
615 || (DECL_P (op1
) && TREE_THIS_VOLATILE (op1
)))
617 else if (TREE_CODE (op1
) == MEM_REF
618 && TREE_THIS_VOLATILE (op1
))
620 /* Similarly for volatile MEM_REFs on the RHS. */
621 if (!TREE_SIDE_EFFECTS (TREE_OPERAND (op1
, 0)))
624 *expr_p
= build2 (COMPOUND_EXPR
, TREE_TYPE (*expr_p
),
625 TREE_OPERAND (op1
, 0), op0
);
628 *expr_p
= build2 (COMPOUND_EXPR
, TREE_TYPE (*expr_p
),
635 case EMPTY_CLASS_EXPR
:
636 /* We create an empty CONSTRUCTOR with RECORD_TYPE. */
637 *expr_p
= build_constructor (TREE_TYPE (*expr_p
), NULL
);
642 *expr_p
= BASELINK_FUNCTIONS (*expr_p
);
647 genericize_try_block (expr_p
);
652 genericize_catch_block (expr_p
);
657 genericize_eh_spec_block (expr_p
);
673 ret
= cp_gimplify_omp_for (expr_p
, pre_p
);
677 gimplify_expr_stmt (expr_p
);
681 case UNARY_PLUS_EXPR
:
683 tree arg
= TREE_OPERAND (*expr_p
, 0);
684 tree type
= TREE_TYPE (*expr_p
);
685 *expr_p
= (TREE_TYPE (arg
) != type
) ? fold_convert (type
, arg
)
692 ret
= (enum gimplify_status
) c_gimplify_expr (expr_p
, pre_p
, post_p
);
696 /* Restore saved state. */
697 if (STATEMENT_CODE_P (code
))
698 current_stmt_tree ()->stmts_are_full_exprs_p
699 = saved_stmts_are_full_exprs_p
;
705 is_invisiref_parm (const_tree t
)
707 return ((TREE_CODE (t
) == PARM_DECL
|| TREE_CODE (t
) == RESULT_DECL
)
708 && DECL_BY_REFERENCE (t
));
711 /* Return true if the uid in both int tree maps are equal. */
714 cxx_int_tree_map_eq (const void *va
, const void *vb
)
716 const struct cxx_int_tree_map
*a
= (const struct cxx_int_tree_map
*) va
;
717 const struct cxx_int_tree_map
*b
= (const struct cxx_int_tree_map
*) vb
;
718 return (a
->uid
== b
->uid
);
721 /* Hash a UID in a cxx_int_tree_map. */
724 cxx_int_tree_map_hash (const void *item
)
726 return ((const struct cxx_int_tree_map
*)item
)->uid
;
729 /* A stable comparison routine for use with splay trees and DECLs. */
732 splay_tree_compare_decl_uid (splay_tree_key xa
, splay_tree_key xb
)
737 return DECL_UID (a
) - DECL_UID (b
);
740 /* OpenMP context during genericization. */
742 struct cp_genericize_omp_taskreg
746 struct cp_genericize_omp_taskreg
*outer
;
747 splay_tree variables
;
750 /* Return true if genericization should try to determine if
751 DECL is firstprivate or shared within task regions. */
754 omp_var_to_track (tree decl
)
756 tree type
= TREE_TYPE (decl
);
757 if (is_invisiref_parm (decl
))
758 type
= TREE_TYPE (type
);
759 while (TREE_CODE (type
) == ARRAY_TYPE
)
760 type
= TREE_TYPE (type
);
761 if (type
== error_mark_node
|| !CLASS_TYPE_P (type
))
763 if (TREE_CODE (decl
) == VAR_DECL
&& DECL_THREAD_LOCAL_P (decl
))
765 if (cxx_omp_predetermined_sharing (decl
) != OMP_CLAUSE_DEFAULT_UNSPECIFIED
)
770 /* Note DECL use in OpenMP region OMP_CTX during genericization. */
773 omp_cxx_notice_variable (struct cp_genericize_omp_taskreg
*omp_ctx
, tree decl
)
775 splay_tree_node n
= splay_tree_lookup (omp_ctx
->variables
,
776 (splay_tree_key
) decl
);
779 int flags
= OMP_CLAUSE_DEFAULT_SHARED
;
781 omp_cxx_notice_variable (omp_ctx
->outer
, decl
);
782 if (!omp_ctx
->default_shared
)
784 struct cp_genericize_omp_taskreg
*octx
;
786 for (octx
= omp_ctx
->outer
; octx
; octx
= octx
->outer
)
788 n
= splay_tree_lookup (octx
->variables
, (splay_tree_key
) decl
);
789 if (n
&& n
->value
!= OMP_CLAUSE_DEFAULT_SHARED
)
791 flags
= OMP_CLAUSE_DEFAULT_FIRSTPRIVATE
;
794 if (octx
->is_parallel
)
798 && (TREE_CODE (decl
) == PARM_DECL
799 || (!(TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
800 && DECL_CONTEXT (decl
) == current_function_decl
)))
801 flags
= OMP_CLAUSE_DEFAULT_FIRSTPRIVATE
;
802 if (flags
== OMP_CLAUSE_DEFAULT_FIRSTPRIVATE
)
804 /* DECL is implicitly determined firstprivate in
805 the current task construct. Ensure copy ctor and
806 dtor are instantiated, because during gimplification
807 it will be already too late. */
808 tree type
= TREE_TYPE (decl
);
809 if (is_invisiref_parm (decl
))
810 type
= TREE_TYPE (type
);
811 while (TREE_CODE (type
) == ARRAY_TYPE
)
812 type
= TREE_TYPE (type
);
813 get_copy_ctor (type
, tf_none
);
814 get_dtor (type
, tf_none
);
817 splay_tree_insert (omp_ctx
->variables
, (splay_tree_key
) decl
, flags
);
821 /* Genericization context. */
823 struct cp_genericize_data
825 struct pointer_set_t
*p_set
;
826 VEC (tree
, heap
) *bind_expr_stack
;
827 struct cp_genericize_omp_taskreg
*omp_ctx
;
830 /* Perform any pre-gimplification lowering of C++ front end trees to
834 cp_genericize_r (tree
*stmt_p
, int *walk_subtrees
, void *data
)
837 struct cp_genericize_data
*wtd
= (struct cp_genericize_data
*) data
;
838 struct pointer_set_t
*p_set
= wtd
->p_set
;
840 /* If in an OpenMP context, note var uses. */
841 if (__builtin_expect (wtd
->omp_ctx
!= NULL
, 0)
842 && (TREE_CODE (stmt
) == VAR_DECL
843 || TREE_CODE (stmt
) == PARM_DECL
844 || TREE_CODE (stmt
) == RESULT_DECL
)
845 && omp_var_to_track (stmt
))
846 omp_cxx_notice_variable (wtd
->omp_ctx
, stmt
);
848 if (is_invisiref_parm (stmt
)
849 /* Don't dereference parms in a thunk, pass the references through. */
850 && !(DECL_THUNK_P (current_function_decl
)
851 && TREE_CODE (stmt
) == PARM_DECL
))
853 *stmt_p
= convert_from_reference (stmt
);
858 /* Map block scope extern declarations to visible declarations with the
859 same name and type in outer scopes if any. */
860 if (cp_function_chain
->extern_decl_map
861 && (TREE_CODE (stmt
) == FUNCTION_DECL
|| TREE_CODE (stmt
) == VAR_DECL
)
862 && DECL_EXTERNAL (stmt
))
864 struct cxx_int_tree_map
*h
, in
;
865 in
.uid
= DECL_UID (stmt
);
866 h
= (struct cxx_int_tree_map
*)
867 htab_find_with_hash (cp_function_chain
->extern_decl_map
,
877 /* Other than invisiref parms, don't walk the same tree twice. */
878 if (pointer_set_contains (p_set
, stmt
))
884 if (TREE_CODE (stmt
) == ADDR_EXPR
885 && is_invisiref_parm (TREE_OPERAND (stmt
, 0)))
887 /* If in an OpenMP context, note var uses. */
888 if (__builtin_expect (wtd
->omp_ctx
!= NULL
, 0)
889 && omp_var_to_track (TREE_OPERAND (stmt
, 0)))
890 omp_cxx_notice_variable (wtd
->omp_ctx
, TREE_OPERAND (stmt
, 0));
891 *stmt_p
= convert (TREE_TYPE (stmt
), TREE_OPERAND (stmt
, 0));
894 else if (TREE_CODE (stmt
) == RETURN_EXPR
895 && TREE_OPERAND (stmt
, 0)
896 && is_invisiref_parm (TREE_OPERAND (stmt
, 0)))
897 /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */
899 else if (TREE_CODE (stmt
) == OMP_CLAUSE
)
900 switch (OMP_CLAUSE_CODE (stmt
))
902 case OMP_CLAUSE_LASTPRIVATE
:
903 /* Don't dereference an invisiref in OpenMP clauses. */
904 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt
)))
907 if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt
))
908 cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt
),
909 cp_genericize_r
, data
, NULL
);
912 case OMP_CLAUSE_PRIVATE
:
913 /* Don't dereference an invisiref in OpenMP clauses. */
914 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt
)))
916 else if (wtd
->omp_ctx
!= NULL
)
918 /* Private clause doesn't cause any references to the
919 var in outer contexts, avoid calling
920 omp_cxx_notice_variable for it. */
921 struct cp_genericize_omp_taskreg
*old
= wtd
->omp_ctx
;
923 cp_walk_tree (&OMP_CLAUSE_DECL (stmt
), cp_genericize_r
,
929 case OMP_CLAUSE_SHARED
:
930 case OMP_CLAUSE_FIRSTPRIVATE
:
931 case OMP_CLAUSE_COPYIN
:
932 case OMP_CLAUSE_COPYPRIVATE
:
933 /* Don't dereference an invisiref in OpenMP clauses. */
934 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt
)))
937 case OMP_CLAUSE_REDUCTION
:
938 gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt
)));
943 else if (IS_TYPE_OR_DECL_P (stmt
))
946 /* Due to the way voidify_wrapper_expr is written, we don't get a chance
947 to lower this construct before scanning it, so we need to lower these
948 before doing anything else. */
949 else if (TREE_CODE (stmt
) == CLEANUP_STMT
)
950 *stmt_p
= build2 (CLEANUP_EH_ONLY (stmt
) ? TRY_CATCH_EXPR
954 CLEANUP_EXPR (stmt
));
956 else if (TREE_CODE (stmt
) == IF_STMT
)
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
);
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
)
968 = (TREE_OPERAND (stmt
, 1)
969 ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt
, 1))
972 = (TREE_OPERAND (stmt
, 2)
973 ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt
, 2))
976 && !useless_type_conversion_p (TREE_TYPE (stmt
),
977 TREE_TYPE (TREE_OPERAND (stmt
, 1))))
979 TREE_OPERAND (stmt
, 1)
980 = fold_convert (type_left
, TREE_OPERAND (stmt
, 1));
981 gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt
),
985 && !useless_type_conversion_p (TREE_TYPE (stmt
),
986 TREE_TYPE (TREE_OPERAND (stmt
, 2))))
988 TREE_OPERAND (stmt
, 2)
989 = fold_convert (type_right
, TREE_OPERAND (stmt
, 2));
990 gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt
),
995 else if (TREE_CODE (stmt
) == BIND_EXPR
)
997 if (__builtin_expect (wtd
->omp_ctx
!= NULL
, 0))
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
))
1006 = splay_tree_lookup (wtd
->omp_ctx
->variables
,
1007 (splay_tree_key
) decl
);
1009 splay_tree_insert (wtd
->omp_ctx
->variables
,
1010 (splay_tree_key
) decl
,
1012 ? OMP_CLAUSE_DEFAULT_SHARED
1013 : OMP_CLAUSE_DEFAULT_PRIVATE
);
1016 VEC_safe_push (tree
, heap
, wtd
->bind_expr_stack
, stmt
);
1017 cp_walk_tree (&BIND_EXPR_BODY (stmt
),
1018 cp_genericize_r
, data
, NULL
);
1019 VEC_pop (tree
, wtd
->bind_expr_stack
);
1022 else if (TREE_CODE (stmt
) == USING_STMT
)
1024 tree block
= NULL_TREE
;
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
)
1032 for (i
= VEC_length (tree
, wtd
->bind_expr_stack
) - 1; i
>= 0; i
--)
1033 if ((block
= BIND_EXPR_BLOCK (VEC_index (tree
,
1034 wtd
->bind_expr_stack
, i
))))
1039 tree using_directive
;
1040 gcc_assert (TREE_OPERAND (stmt
, 0));
1042 using_directive
= make_node (IMPORTED_DECL
);
1043 TREE_TYPE (using_directive
) = void_type_node
;
1045 IMPORTED_DECL_ASSOCIATED_DECL (using_directive
)
1046 = TREE_OPERAND (stmt
, 0);
1047 DECL_CHAIN (using_directive
) = BLOCK_VARS (block
);
1048 BLOCK_VARS (block
) = using_directive
;
1050 /* The USING_STMT won't appear in GENERIC. */
1051 *stmt_p
= build1 (NOP_EXPR
, void_type_node
, integer_zero_node
);
1055 else if (TREE_CODE (stmt
) == DECL_EXPR
1056 && TREE_CODE (DECL_EXPR_DECL (stmt
)) == USING_DECL
)
1058 /* Using decls inside DECL_EXPRs are just dropped on the floor. */
1059 *stmt_p
= build1 (NOP_EXPR
, void_type_node
, integer_zero_node
);
1062 else if (TREE_CODE (stmt
) == OMP_PARALLEL
|| TREE_CODE (stmt
) == OMP_TASK
)
1064 struct cp_genericize_omp_taskreg omp_ctx
;
1069 cp_walk_tree (&OMP_CLAUSES (stmt
), cp_genericize_r
, data
, NULL
);
1070 omp_ctx
.is_parallel
= TREE_CODE (stmt
) == OMP_PARALLEL
;
1071 omp_ctx
.default_shared
= omp_ctx
.is_parallel
;
1072 omp_ctx
.outer
= wtd
->omp_ctx
;
1073 omp_ctx
.variables
= splay_tree_new (splay_tree_compare_decl_uid
, 0, 0);
1074 wtd
->omp_ctx
= &omp_ctx
;
1075 for (c
= OMP_CLAUSES (stmt
); c
; c
= OMP_CLAUSE_CHAIN (c
))
1076 switch (OMP_CLAUSE_CODE (c
))
1078 case OMP_CLAUSE_SHARED
:
1079 case OMP_CLAUSE_PRIVATE
:
1080 case OMP_CLAUSE_FIRSTPRIVATE
:
1081 case OMP_CLAUSE_LASTPRIVATE
:
1082 decl
= OMP_CLAUSE_DECL (c
);
1083 if (decl
== error_mark_node
|| !omp_var_to_track (decl
))
1085 n
= splay_tree_lookup (omp_ctx
.variables
, (splay_tree_key
) decl
);
1088 splay_tree_insert (omp_ctx
.variables
, (splay_tree_key
) decl
,
1089 OMP_CLAUSE_CODE (c
) == OMP_CLAUSE_SHARED
1090 ? OMP_CLAUSE_DEFAULT_SHARED
1091 : OMP_CLAUSE_DEFAULT_PRIVATE
);
1092 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_PRIVATE
1094 omp_cxx_notice_variable (omp_ctx
.outer
, decl
);
1096 case OMP_CLAUSE_DEFAULT
:
1097 if (OMP_CLAUSE_DEFAULT_KIND (c
) == OMP_CLAUSE_DEFAULT_SHARED
)
1098 omp_ctx
.default_shared
= true;
1102 cp_walk_tree (&OMP_BODY (stmt
), cp_genericize_r
, data
, NULL
);
1103 wtd
->omp_ctx
= omp_ctx
.outer
;
1104 splay_tree_delete (omp_ctx
.variables
);
1106 else if (TREE_CODE (stmt
) == CONVERT_EXPR
)
1107 gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt
));
1108 else if (TREE_CODE (stmt
) == FOR_STMT
)
1109 genericize_for_stmt (stmt_p
, walk_subtrees
, data
);
1110 else if (TREE_CODE (stmt
) == WHILE_STMT
)
1111 genericize_while_stmt (stmt_p
, walk_subtrees
, data
);
1112 else if (TREE_CODE (stmt
) == DO_STMT
)
1113 genericize_do_stmt (stmt_p
, walk_subtrees
, data
);
1114 else if (TREE_CODE (stmt
) == SWITCH_STMT
)
1115 genericize_switch_stmt (stmt_p
, walk_subtrees
, data
);
1116 else if (TREE_CODE (stmt
) == CONTINUE_STMT
)
1117 genericize_continue_stmt (stmt_p
);
1118 else if (TREE_CODE (stmt
) == BREAK_STMT
)
1119 genericize_break_stmt (stmt_p
);
1120 else if (TREE_CODE (stmt
) == OMP_FOR
)
1121 genericize_omp_for_stmt (stmt_p
, walk_subtrees
, data
);
1123 pointer_set_insert (p_set
, *stmt_p
);
1128 /* Lower C++ front end trees to GENERIC in T_P. */
1131 cp_genericize_tree (tree
* t_p
)
1133 struct cp_genericize_data wtd
;
1135 wtd
.p_set
= pointer_set_create ();
1136 wtd
.bind_expr_stack
= NULL
;
1138 cp_walk_tree (t_p
, cp_genericize_r
, &wtd
, NULL
);
1139 pointer_set_destroy (wtd
.p_set
);
1140 VEC_free (tree
, heap
, wtd
.bind_expr_stack
);
1144 cp_genericize (tree fndecl
)
1148 /* Fix up the types of parms passed by invisible reference. */
1149 for (t
= DECL_ARGUMENTS (fndecl
); t
; t
= DECL_CHAIN (t
))
1150 if (TREE_ADDRESSABLE (TREE_TYPE (t
)))
1152 /* If a function's arguments are copied to create a thunk,
1153 then DECL_BY_REFERENCE will be set -- but the type of the
1154 argument will be a pointer type, so we will never get
1156 gcc_assert (!DECL_BY_REFERENCE (t
));
1157 gcc_assert (DECL_ARG_TYPE (t
) != TREE_TYPE (t
));
1158 TREE_TYPE (t
) = DECL_ARG_TYPE (t
);
1159 DECL_BY_REFERENCE (t
) = 1;
1160 TREE_ADDRESSABLE (t
) = 0;
1164 /* Do the same for the return value. */
1165 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl
))))
1167 t
= DECL_RESULT (fndecl
);
1168 TREE_TYPE (t
) = build_reference_type (TREE_TYPE (t
));
1169 DECL_BY_REFERENCE (t
) = 1;
1170 TREE_ADDRESSABLE (t
) = 0;
1174 /* Adjust DECL_VALUE_EXPR of the original var. */
1175 tree outer
= outer_curly_brace_block (current_function_decl
);
1179 for (var
= BLOCK_VARS (outer
); var
; var
= DECL_CHAIN (var
))
1180 if (DECL_NAME (t
) == DECL_NAME (var
)
1181 && DECL_HAS_VALUE_EXPR_P (var
)
1182 && DECL_VALUE_EXPR (var
) == t
)
1184 tree val
= convert_from_reference (t
);
1185 SET_DECL_VALUE_EXPR (var
, val
);
1191 /* If we're a clone, the body is already GIMPLE. */
1192 if (DECL_CLONED_FUNCTION_P (fndecl
))
1195 /* We do want to see every occurrence of the parms, so we can't just use
1196 walk_tree's hash functionality. */
1197 cp_genericize_tree (&DECL_SAVED_TREE (fndecl
));
1199 /* Do everything else. */
1200 c_genericize (fndecl
);
1202 gcc_assert (bc_label
[bc_break
] == NULL
);
1203 gcc_assert (bc_label
[bc_continue
] == NULL
);
1206 /* Build code to apply FN to each member of ARG1 and ARG2. FN may be
1207 NULL if there is in fact nothing to do. ARG2 may be null if FN
1208 actually only takes one argument. */
1211 cxx_omp_clause_apply_fn (tree fn
, tree arg1
, tree arg2
)
1213 tree defparm
, parm
, t
;
1221 nargs
= list_length (DECL_ARGUMENTS (fn
));
1222 argarray
= XALLOCAVEC (tree
, nargs
);
1224 defparm
= TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn
)));
1226 defparm
= TREE_CHAIN (defparm
);
1228 if (TREE_CODE (TREE_TYPE (arg1
)) == ARRAY_TYPE
)
1230 tree inner_type
= TREE_TYPE (arg1
);
1231 tree start1
, end1
, p1
;
1232 tree start2
= NULL
, p2
= NULL
;
1233 tree ret
= NULL
, lab
;
1239 inner_type
= TREE_TYPE (inner_type
);
1240 start1
= build4 (ARRAY_REF
, inner_type
, start1
,
1241 size_zero_node
, NULL
, NULL
);
1243 start2
= build4 (ARRAY_REF
, inner_type
, start2
,
1244 size_zero_node
, NULL
, NULL
);
1246 while (TREE_CODE (inner_type
) == ARRAY_TYPE
);
1247 start1
= build_fold_addr_expr_loc (input_location
, start1
);
1249 start2
= build_fold_addr_expr_loc (input_location
, start2
);
1251 end1
= TYPE_SIZE_UNIT (TREE_TYPE (arg1
));
1252 end1
= fold_build_pointer_plus (start1
, end1
);
1254 p1
= create_tmp_var (TREE_TYPE (start1
), NULL
);
1255 t
= build2 (MODIFY_EXPR
, TREE_TYPE (p1
), p1
, start1
);
1256 append_to_statement_list (t
, &ret
);
1260 p2
= create_tmp_var (TREE_TYPE (start2
), NULL
);
1261 t
= build2 (MODIFY_EXPR
, TREE_TYPE (p2
), p2
, start2
);
1262 append_to_statement_list (t
, &ret
);
1265 lab
= create_artificial_label (input_location
);
1266 t
= build1 (LABEL_EXPR
, void_type_node
, lab
);
1267 append_to_statement_list (t
, &ret
);
1272 /* Handle default arguments. */
1273 for (parm
= defparm
; parm
&& parm
!= void_list_node
;
1274 parm
= TREE_CHAIN (parm
), i
++)
1275 argarray
[i
] = convert_default_arg (TREE_VALUE (parm
),
1276 TREE_PURPOSE (parm
), fn
, i
,
1277 tf_warning_or_error
);
1278 t
= build_call_a (fn
, i
, argarray
);
1279 t
= fold_convert (void_type_node
, t
);
1280 t
= fold_build_cleanup_point_expr (TREE_TYPE (t
), t
);
1281 append_to_statement_list (t
, &ret
);
1283 t
= fold_build_pointer_plus (p1
, TYPE_SIZE_UNIT (inner_type
));
1284 t
= build2 (MODIFY_EXPR
, TREE_TYPE (p1
), p1
, t
);
1285 append_to_statement_list (t
, &ret
);
1289 t
= fold_build_pointer_plus (p2
, TYPE_SIZE_UNIT (inner_type
));
1290 t
= build2 (MODIFY_EXPR
, TREE_TYPE (p2
), p2
, t
);
1291 append_to_statement_list (t
, &ret
);
1294 t
= build2 (NE_EXPR
, boolean_type_node
, p1
, end1
);
1295 t
= build3 (COND_EXPR
, void_type_node
, t
, build_and_jump (&lab
), NULL
);
1296 append_to_statement_list (t
, &ret
);
1302 argarray
[i
++] = build_fold_addr_expr_loc (input_location
, arg1
);
1304 argarray
[i
++] = build_fold_addr_expr_loc (input_location
, arg2
);
1305 /* Handle default arguments. */
1306 for (parm
= defparm
; parm
&& parm
!= void_list_node
;
1307 parm
= TREE_CHAIN (parm
), i
++)
1308 argarray
[i
] = convert_default_arg (TREE_VALUE (parm
),
1309 TREE_PURPOSE (parm
),
1310 fn
, i
, tf_warning_or_error
);
1311 t
= build_call_a (fn
, i
, argarray
);
1312 t
= fold_convert (void_type_node
, t
);
1313 return fold_build_cleanup_point_expr (TREE_TYPE (t
), t
);
1317 /* Return code to initialize DECL with its default constructor, or
1318 NULL if there's nothing to do. */
1321 cxx_omp_clause_default_ctor (tree clause
, tree decl
, tree
/*outer*/)
1323 tree info
= CP_OMP_CLAUSE_INFO (clause
);
1327 ret
= cxx_omp_clause_apply_fn (TREE_VEC_ELT (info
, 0), decl
, NULL
);
1332 /* Return code to initialize DST with a copy constructor from SRC. */
1335 cxx_omp_clause_copy_ctor (tree clause
, tree dst
, tree src
)
1337 tree info
= CP_OMP_CLAUSE_INFO (clause
);
1341 ret
= cxx_omp_clause_apply_fn (TREE_VEC_ELT (info
, 0), dst
, src
);
1343 ret
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
1348 /* Similarly, except use an assignment operator instead. */
1351 cxx_omp_clause_assign_op (tree clause
, tree dst
, tree src
)
1353 tree info
= CP_OMP_CLAUSE_INFO (clause
);
1357 ret
= cxx_omp_clause_apply_fn (TREE_VEC_ELT (info
, 2), dst
, src
);
1359 ret
= build2 (MODIFY_EXPR
, TREE_TYPE (dst
), dst
, src
);
1364 /* Return code to destroy DECL. */
1367 cxx_omp_clause_dtor (tree clause
, tree decl
)
1369 tree info
= CP_OMP_CLAUSE_INFO (clause
);
1373 ret
= cxx_omp_clause_apply_fn (TREE_VEC_ELT (info
, 1), decl
, NULL
);
1378 /* True if OpenMP should privatize what this DECL points to rather
1379 than the DECL itself. */
1382 cxx_omp_privatize_by_reference (const_tree decl
)
1384 return is_invisiref_parm (decl
);
1387 /* Return true if DECL is const qualified var having no mutable member. */
1389 cxx_omp_const_qual_no_mutable (tree decl
)
1391 tree type
= TREE_TYPE (decl
);
1392 if (TREE_CODE (type
) == REFERENCE_TYPE
)
1394 if (!is_invisiref_parm (decl
))
1396 type
= TREE_TYPE (type
);
1398 if (TREE_CODE (decl
) == RESULT_DECL
&& DECL_NAME (decl
))
1400 /* NVR doesn't preserve const qualification of the
1402 tree outer
= outer_curly_brace_block (current_function_decl
);
1406 for (var
= BLOCK_VARS (outer
); var
; var
= DECL_CHAIN (var
))
1407 if (DECL_NAME (decl
) == DECL_NAME (var
)
1408 && (TYPE_MAIN_VARIANT (type
)
1409 == TYPE_MAIN_VARIANT (TREE_TYPE (var
))))
1411 if (TYPE_READONLY (TREE_TYPE (var
)))
1412 type
= TREE_TYPE (var
);
1418 if (type
== error_mark_node
)
1421 /* Variables with const-qualified type having no mutable member
1422 are predetermined shared. */
1423 if (TYPE_READONLY (type
) && !cp_has_mutable_p (type
))
1429 /* True if OpenMP sharing attribute of DECL is predetermined. */
1431 enum omp_clause_default_kind
1432 cxx_omp_predetermined_sharing (tree decl
)
1434 /* Static data members are predetermined shared. */
1435 if (TREE_STATIC (decl
))
1437 tree ctx
= CP_DECL_CONTEXT (decl
);
1438 if (TYPE_P (ctx
) && MAYBE_CLASS_TYPE_P (ctx
))
1439 return OMP_CLAUSE_DEFAULT_SHARED
;
1442 /* Const qualified vars having no mutable member are predetermined
1444 if (cxx_omp_const_qual_no_mutable (decl
))
1445 return OMP_CLAUSE_DEFAULT_SHARED
;
1447 return OMP_CLAUSE_DEFAULT_UNSPECIFIED
;
1450 /* Finalize an implicitly determined clause. */
1453 cxx_omp_finish_clause (tree c
)
1455 tree decl
, inner_type
;
1456 bool make_shared
= false;
1458 if (OMP_CLAUSE_CODE (c
) != OMP_CLAUSE_FIRSTPRIVATE
)
1461 decl
= OMP_CLAUSE_DECL (c
);
1462 decl
= require_complete_type (decl
);
1463 inner_type
= TREE_TYPE (decl
);
1464 if (decl
== error_mark_node
)
1466 else if (TREE_CODE (TREE_TYPE (decl
)) == REFERENCE_TYPE
)
1468 if (is_invisiref_parm (decl
))
1469 inner_type
= TREE_TYPE (inner_type
);
1472 error ("%qE implicitly determined as %<firstprivate%> has reference type",
1478 /* We're interested in the base element, not arrays. */
1479 while (TREE_CODE (inner_type
) == ARRAY_TYPE
)
1480 inner_type
= TREE_TYPE (inner_type
);
1482 /* Check for special function availability by building a call to one.
1483 Save the results, because later we won't be in the right context
1484 for making these queries. */
1486 && CLASS_TYPE_P (inner_type
)
1487 && cxx_omp_create_clause_info (c
, inner_type
, false, true, false))
1491 OMP_CLAUSE_CODE (c
) = OMP_CLAUSE_SHARED
;