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