1169689Skan/* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
2169689Skan
3169689Skan   Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
4169689Skan   Contributed by Jason Merrill <jason@redhat.com>
5169689Skan
6169689SkanThis file is part of GCC.
7169689Skan
8169689SkanGCC is free software; you can redistribute it and/or modify it under
9169689Skanthe terms of the GNU General Public License as published by the Free
10169689SkanSoftware Foundation; either version 2, or (at your option) any later
11169689Skanversion.
12169689Skan
13169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
14169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
15169689SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16169689Skanfor more details.
17169689Skan
18169689SkanYou should have received a copy of the GNU General Public License
19169689Skanalong with GCC; see the file COPYING.  If not, write to the Free
20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21169689Skan02110-1301, USA.  */
22169689Skan
23169689Skan#include "config.h"
24169689Skan#include "system.h"
25169689Skan#include "coretypes.h"
26169689Skan#include "tm.h"
27169689Skan#include "tree.h"
28169689Skan#include "cp-tree.h"
29169689Skan#include "c-common.h"
30169689Skan#include "toplev.h"
31169689Skan#include "tree-gimple.h"
32169689Skan#include "hashtab.h"
33169689Skan#include "pointer-set.h"
34169689Skan#include "flags.h"
35169689Skan
36169689Skan/* Local declarations.  */
37169689Skan
38169689Skanenum bc_t { bc_break = 0, bc_continue = 1 };
39169689Skan
40169689Skan/* Stack of labels which are targets for "break" or "continue",
41169689Skan   linked through TREE_CHAIN.  */
42169689Skanstatic tree bc_label[2];
43169689Skan
44169689Skan/* Begin a scope which can be exited by a break or continue statement.  BC
45169689Skan   indicates which.
46169689Skan
47169689Skan   Just creates a label and pushes it into the current context.  */
48169689Skan
49169689Skanstatic tree
50169689Skanbegin_bc_block (enum bc_t bc)
51169689Skan{
52169689Skan  tree label = create_artificial_label ();
53169689Skan  TREE_CHAIN (label) = bc_label[bc];
54169689Skan  bc_label[bc] = label;
55169689Skan  return label;
56169689Skan}
57169689Skan
58169689Skan/* Finish a scope which can be exited by a break or continue statement.
59169689Skan   LABEL was returned from the most recent call to begin_bc_block.  BODY is
60169689Skan   an expression for the contents of the scope.
61169689Skan
62169689Skan   If we saw a break (or continue) in the scope, append a LABEL_EXPR to
63169689Skan   body.  Otherwise, just forget the label.  */
64169689Skan
65169689Skanstatic tree
66169689Skanfinish_bc_block (enum bc_t bc, tree label, tree body)
67169689Skan{
68169689Skan  gcc_assert (label == bc_label[bc]);
69169689Skan
70169689Skan  if (TREE_USED (label))
71169689Skan    {
72169689Skan      tree t, sl = NULL;
73169689Skan
74169689Skan      t = build1 (LABEL_EXPR, void_type_node, label);
75169689Skan
76169689Skan      append_to_statement_list (body, &sl);
77169689Skan      append_to_statement_list (t, &sl);
78169689Skan      body = sl;
79169689Skan    }
80169689Skan
81169689Skan  bc_label[bc] = TREE_CHAIN (label);
82169689Skan  TREE_CHAIN (label) = NULL_TREE;
83169689Skan  return body;
84169689Skan}
85169689Skan
86169689Skan/* Build a GOTO_EXPR to represent a break or continue statement.  BC
87169689Skan   indicates which.  */
88169689Skan
89169689Skanstatic tree
90169689Skanbuild_bc_goto (enum bc_t bc)
91169689Skan{
92169689Skan  tree label = bc_label[bc];
93169689Skan
94169689Skan  if (label == NULL_TREE)
95169689Skan    {
96169689Skan      if (bc == bc_break)
97169689Skan	error ("break statement not within loop or switch");
98169689Skan      else
99169689Skan	error ("continue statement not within loop or switch");
100169689Skan
101169689Skan      return NULL_TREE;
102169689Skan    }
103169689Skan
104169689Skan  /* Mark the label used for finish_bc_block.  */
105169689Skan  TREE_USED (label) = 1;
106169689Skan  return build1 (GOTO_EXPR, void_type_node, label);
107169689Skan}
108169689Skan
109169689Skan/* Genericize a TRY_BLOCK.  */
110169689Skan
111169689Skanstatic void
112169689Skangenericize_try_block (tree *stmt_p)
113169689Skan{
114169689Skan  tree body = TRY_STMTS (*stmt_p);
115169689Skan  tree cleanup = TRY_HANDLERS (*stmt_p);
116169689Skan
117169689Skan  gimplify_stmt (&body);
118169689Skan
119169689Skan  if (CLEANUP_P (*stmt_p))
120169689Skan    /* A cleanup is an expression, so it doesn't need to be genericized.  */;
121169689Skan  else
122169689Skan    gimplify_stmt (&cleanup);
123169689Skan
124169689Skan  *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
125169689Skan}
126169689Skan
127169689Skan/* Genericize a HANDLER by converting to a CATCH_EXPR.  */
128169689Skan
129169689Skanstatic void
130169689Skangenericize_catch_block (tree *stmt_p)
131169689Skan{
132169689Skan  tree type = HANDLER_TYPE (*stmt_p);
133169689Skan  tree body = HANDLER_BODY (*stmt_p);
134169689Skan
135169689Skan  gimplify_stmt (&body);
136169689Skan
137169689Skan  /* FIXME should the caught type go in TREE_TYPE?  */
138169689Skan  *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
139169689Skan}
140169689Skan
141169689Skan/* Genericize an EH_SPEC_BLOCK by converting it to a
142169689Skan   TRY_CATCH_EXPR/EH_FILTER_EXPR pair.  */
143169689Skan
144169689Skanstatic void
145169689Skangenericize_eh_spec_block (tree *stmt_p)
146169689Skan{
147169689Skan  tree body = EH_SPEC_STMTS (*stmt_p);
148169689Skan  tree allowed = EH_SPEC_RAISES (*stmt_p);
149169689Skan  tree failure = build_call (call_unexpected_node,
150169689Skan			     tree_cons (NULL_TREE, build_exc_ptr (),
151169689Skan					NULL_TREE));
152169689Skan  gimplify_stmt (&body);
153169689Skan
154169689Skan  *stmt_p = gimple_build_eh_filter (body, allowed, failure);
155169689Skan}
156169689Skan
157169689Skan/* Genericize an IF_STMT by turning it into a COND_EXPR.  */
158169689Skan
159169689Skanstatic void
160169689Skangimplify_if_stmt (tree *stmt_p)
161169689Skan{
162169689Skan  tree stmt, cond, then_, else_;
163169689Skan
164169689Skan  stmt = *stmt_p;
165169689Skan  cond = IF_COND (stmt);
166169689Skan  then_ = THEN_CLAUSE (stmt);
167169689Skan  else_ = ELSE_CLAUSE (stmt);
168169689Skan
169169689Skan  if (!then_)
170169689Skan    then_ = build_empty_stmt ();
171169689Skan  if (!else_)
172169689Skan    else_ = build_empty_stmt ();
173169689Skan
174169689Skan  if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
175169689Skan    stmt = then_;
176169689Skan  else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
177169689Skan    stmt = else_;
178169689Skan  else
179169689Skan    stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
180169689Skan  *stmt_p = stmt;
181169689Skan}
182169689Skan
183169689Skan/* Build a generic representation of one of the C loop forms.  COND is the
184169689Skan   loop condition or NULL_TREE.  BODY is the (possibly compound) statement
185169689Skan   controlled by the loop.  INCR is the increment expression of a for-loop,
186169689Skan   or NULL_TREE.  COND_IS_FIRST indicates whether the condition is
187169689Skan   evaluated before the loop body as in while and for loops, or after the
188169689Skan   loop body as in do-while loops.  */
189169689Skan
190169689Skanstatic tree
191260918Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
192260918Spfggimplify_cp_loop (tree cond, tree body, tree incr, tree attrs,
193260918Spfg		  bool cond_is_first, tree inner_foreach)
194260918Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
195169689Skan{
196169689Skan  tree top, entry, exit, cont_block, break_block, stmt_list, t;
197169689Skan  location_t stmt_locus;
198169689Skan
199169689Skan  stmt_locus = input_location;
200169689Skan  stmt_list = NULL_TREE;
201169689Skan  entry = NULL_TREE;
202169689Skan
203261188Spfg  /* APPLE LOCAL begin C* language */
204261188Spfg  /* Order of label addition to stack is important for objc's foreach-stmt. */
205261188Spfg  /* APPLE LOCAL radar 4667060 */
206261188Spfg  if (inner_foreach == integer_zero_node)
207261188Spfg    {
208261188Spfg      cont_block = begin_bc_block (bc_continue);
209261188Spfg      break_block = begin_bc_block (bc_break);
210261188Spfg    }
211261188Spfg  else
212261188Spfg    {
213261188Spfg      break_block = begin_bc_block (bc_break);
214261188Spfg      cont_block = begin_bc_block (bc_continue);
215261188Spfg    }
216261188Spfg  /* APPLE LOCAL end C* language */
217169689Skan
218169689Skan  /* If condition is zero don't generate a loop construct.  */
219169689Skan  if (cond && integer_zerop (cond))
220169689Skan    {
221169689Skan      top = NULL_TREE;
222169689Skan      exit = NULL_TREE;
223169689Skan      if (cond_is_first)
224169689Skan	{
225169689Skan	  t = build_bc_goto (bc_break);
226169689Skan	  append_to_statement_list (t, &stmt_list);
227169689Skan	}
228169689Skan    }
229169689Skan  else
230169689Skan    {
231169689Skan      /* If we use a LOOP_EXPR here, we have to feed the whole thing
232169689Skan	 back through the main gimplifier to lower it.  Given that we
233169689Skan	 have to gimplify the loop body NOW so that we can resolve
234169689Skan	 break/continue stmts, seems easier to just expand to gotos.  */
235169689Skan      top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
236169689Skan
237169689Skan      /* If we have an exit condition, then we build an IF with gotos either
238169689Skan	 out of the loop, or to the top of it.  If there's no exit condition,
239169689Skan	 then we just build a jump back to the top.  */
240169689Skan      exit = build_and_jump (&LABEL_EXPR_LABEL (top));
241260918Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
242260918Spfg
243260918Spfg      /* Add the attributes to the 'top' label.  */
244260918Spfg      decl_attributes (&LABEL_EXPR_LABEL (top), attrs, 0);
245260918Spfg
246260918Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
247169689Skan      if (cond && !integer_nonzerop (cond))
248169689Skan	{
249169689Skan	  t = build_bc_goto (bc_break);
250169689Skan	  exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
251169689Skan	  gimplify_stmt (&exit);
252169689Skan
253169689Skan	  if (cond_is_first)
254169689Skan	    {
255169689Skan	      if (incr)
256169689Skan		{
257169689Skan		  entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
258169689Skan		  t = build_and_jump (&LABEL_EXPR_LABEL (entry));
259169689Skan		}
260169689Skan	      else
261169689Skan		t = build_bc_goto (bc_continue);
262169689Skan	      append_to_statement_list (t, &stmt_list);
263169689Skan	    }
264169689Skan	}
265169689Skan    }
266169689Skan
267261188Spfg  /* APPLE LOCAL begin radar 4547045 */
268261188Spfg  /* Pop foreach's inner loop break label so outer loop's
269261188Spfg     break label becomes target of inner loop body's break statements.
270261188Spfg  */
271261188Spfg  t = NULL_TREE;
272169689Skan  gimplify_stmt (&body);
273169689Skan  gimplify_stmt (&incr);
274169689Skan
275169689Skan  body = finish_bc_block (bc_continue, cont_block, body);
276261188Spfg  /* APPLE LOCAL begin radar 4547045 */
277261188Spfg  /* Push back inner loop's own 'break' label so rest
278261188Spfg     of code works seemlessly. */
279261188Spfg  /* APPLE LOCAL radar 4667060 */
280169689Skan
281169689Skan  append_to_statement_list (top, &stmt_list);
282169689Skan  append_to_statement_list (body, &stmt_list);
283169689Skan  append_to_statement_list (incr, &stmt_list);
284169689Skan  append_to_statement_list (entry, &stmt_list);
285169689Skan  append_to_statement_list (exit, &stmt_list);
286169689Skan
287169689Skan  annotate_all_with_locus (&stmt_list, stmt_locus);
288169689Skan
289169689Skan  return finish_bc_block (bc_break, break_block, stmt_list);
290169689Skan}
291169689Skan
292169689Skan/* Gimplify a FOR_STMT node.  Move the stuff in the for-init-stmt into the
293169689Skan   prequeue and hand off to gimplify_cp_loop.  */
294169689Skan
295169689Skanstatic void
296169689Skangimplify_for_stmt (tree *stmt_p, tree *pre_p)
297169689Skan{
298169689Skan  tree stmt = *stmt_p;
299169689Skan
300169689Skan  if (FOR_INIT_STMT (stmt))
301169689Skan    gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
302169689Skan
303260918Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
304169689Skan  *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
305260918Spfg			      FOR_EXPR (stmt), FOR_ATTRIBUTES (stmt), 1,
306260918Spfg			      NULL_TREE);
307260918Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
308169689Skan}
309169689Skan
310169689Skan/* Gimplify a WHILE_STMT node.  */
311169689Skan
312169689Skanstatic void
313169689Skangimplify_while_stmt (tree *stmt_p)
314169689Skan{
315169689Skan  tree stmt = *stmt_p;
316260918Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
317169689Skan  *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
318260918Spfg			      NULL_TREE, WHILE_ATTRIBUTES (stmt), 1,
319260918Spfg			      NULL_TREE);
320260918Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
321169689Skan}
322169689Skan
323169689Skan/* Gimplify a DO_STMT node.  */
324169689Skan
325169689Skanstatic void
326169689Skangimplify_do_stmt (tree *stmt_p)
327169689Skan{
328169689Skan  tree stmt = *stmt_p;
329260918Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
330169689Skan  *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
331260918Spfg			      NULL_TREE, DO_ATTRIBUTES (stmt), 0,
332260918Spfg			      DO_FOREACH (stmt));
333260918Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
334169689Skan}
335169689Skan
336169689Skan/* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
337169689Skan
338169689Skanstatic void
339169689Skangimplify_switch_stmt (tree *stmt_p)
340169689Skan{
341169689Skan  tree stmt = *stmt_p;
342169689Skan  tree break_block, body;
343169689Skan  location_t stmt_locus = input_location;
344169689Skan
345169689Skan  break_block = begin_bc_block (bc_break);
346169689Skan
347169689Skan  body = SWITCH_STMT_BODY (stmt);
348169689Skan  if (!body)
349169689Skan    body = build_empty_stmt ();
350169689Skan
351169689Skan  *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
352169689Skan		    SWITCH_STMT_COND (stmt), body, NULL_TREE);
353169689Skan  SET_EXPR_LOCATION (*stmt_p, stmt_locus);
354169689Skan  gimplify_stmt (stmt_p);
355169689Skan
356169689Skan  *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p);
357169689Skan}
358169689Skan
359169689Skan/* Hook into the middle of gimplifying an OMP_FOR node.  This is required
360169689Skan   in order to properly gimplify CONTINUE statements.  Here we merely
361169689Skan   manage the continue stack; the rest of the job is performed by the
362169689Skan   regular gimplifier.  */
363169689Skan
364169689Skanstatic enum gimplify_status
365169689Skancp_gimplify_omp_for (tree *expr_p)
366169689Skan{
367169689Skan  tree for_stmt = *expr_p;
368169689Skan  tree cont_block;
369169689Skan
370169689Skan  /* Protect ourselves from recursion.  */
371169689Skan  if (OMP_FOR_GIMPLIFYING_P (for_stmt))
372169689Skan    return GS_UNHANDLED;
373169689Skan  OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
374169689Skan
375169689Skan  /* Note that while technically the continue label is enabled too soon
376169689Skan     here, we should have already diagnosed invalid continues nested within
377169689Skan     statement expressions within the INIT, COND, or INCR expressions.  */
378169689Skan  cont_block = begin_bc_block (bc_continue);
379169689Skan
380169689Skan  gimplify_stmt (expr_p);
381169689Skan
382169689Skan  OMP_FOR_BODY (for_stmt)
383169689Skan    = finish_bc_block (bc_continue, cont_block, OMP_FOR_BODY (for_stmt));
384169689Skan  OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
385169689Skan
386169689Skan  return GS_ALL_DONE;
387169689Skan}
388169689Skan
389169689Skan/*  Gimplify an EXPR_STMT node.  */
390169689Skan
391169689Skanstatic void
392169689Skangimplify_expr_stmt (tree *stmt_p)
393169689Skan{
394169689Skan  tree stmt = EXPR_STMT_EXPR (*stmt_p);
395169689Skan
396169689Skan  if (stmt == error_mark_node)
397169689Skan    stmt = NULL;
398169689Skan
399169689Skan  /* Gimplification of a statement expression will nullify the
400169689Skan     statement if all its side effects are moved to *PRE_P and *POST_P.
401169689Skan
402169689Skan     In this case we will not want to emit the gimplified statement.
403169689Skan     However, we may still want to emit a warning, so we do that before
404169689Skan     gimplification.  */
405169689Skan  if (stmt && (extra_warnings || warn_unused_value))
406169689Skan    {
407169689Skan      if (!TREE_SIDE_EFFECTS (stmt))
408169689Skan	{
409169689Skan	  if (!IS_EMPTY_STMT (stmt)
410169689Skan	      && !VOID_TYPE_P (TREE_TYPE (stmt))
411169689Skan	      && !TREE_NO_WARNING (stmt))
412169689Skan	    warning (OPT_Wextra, "statement with no effect");
413169689Skan	}
414169689Skan      else if (warn_unused_value)
415169689Skan	warn_if_unused_value (stmt, input_location);
416169689Skan    }
417169689Skan
418169689Skan  if (stmt == NULL_TREE)
419169689Skan    stmt = alloc_stmt_list ();
420169689Skan
421169689Skan  *stmt_p = stmt;
422169689Skan}
423169689Skan
424169689Skan/* Gimplify initialization from an AGGR_INIT_EXPR.  */
425169689Skan
426169689Skanstatic void
427169689Skancp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
428169689Skan{
429169689Skan  tree from = TREE_OPERAND (*expr_p, 1);
430169689Skan  tree to = TREE_OPERAND (*expr_p, 0);
431169689Skan  tree sub;
432169689Skan
433169689Skan  /* What about code that pulls out the temp and uses it elsewhere?  I
434169689Skan     think that such code never uses the TARGET_EXPR as an initializer.  If
435169689Skan     I'm wrong, we'll abort because the temp won't have any RTL.  In that
436169689Skan     case, I guess we'll need to replace references somehow.  */
437169689Skan  if (TREE_CODE (from) == TARGET_EXPR)
438169689Skan    from = TARGET_EXPR_INITIAL (from);
439169689Skan
440169689Skan  /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
441169689Skan     inside the TARGET_EXPR.  */
442169689Skan  sub = expr_last (from);
443169689Skan
444169689Skan  /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
445169689Skan     replace the slot operand with our target.
446169689Skan
447169689Skan     Should we add a target parm to gimplify_expr instead?  No, as in this
448169689Skan     case we want to replace the INIT_EXPR.  */
449169689Skan  if (TREE_CODE (sub) == AGGR_INIT_EXPR)
450169689Skan    {
451169689Skan      gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
452169689Skan      TREE_OPERAND (sub, 2) = to;
453169689Skan      *expr_p = from;
454169689Skan
455169689Skan      /* The initialization is now a side-effect, so the container can
456169689Skan	 become void.  */
457169689Skan      if (from != sub)
458169689Skan	TREE_TYPE (from) = void_type_node;
459169689Skan    }
460169689Skan}
461169689Skan
462169689Skan/* Gimplify a MUST_NOT_THROW_EXPR.  */
463169689Skan
464169689Skanstatic void
465169689Skangimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
466169689Skan{
467169689Skan  tree stmt = *expr_p;
468169689Skan  tree temp = voidify_wrapper_expr (stmt, NULL);
469169689Skan  tree body = TREE_OPERAND (stmt, 0);
470169689Skan
471169689Skan  gimplify_stmt (&body);
472169689Skan
473169689Skan  stmt = gimple_build_eh_filter (body, NULL_TREE,
474169689Skan				 build_call (terminate_node, NULL_TREE));
475169689Skan
476169689Skan  if (temp)
477169689Skan    {
478169689Skan      append_to_statement_list (stmt, pre_p);
479169689Skan      *expr_p = temp;
480169689Skan    }
481169689Skan  else
482169689Skan    *expr_p = stmt;
483169689Skan}
484169689Skan
485169689Skan/* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
486169689Skan
487169689Skanint
488169689Skancp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
489169689Skan{
490169689Skan  int saved_stmts_are_full_exprs_p = 0;
491169689Skan  enum tree_code code = TREE_CODE (*expr_p);
492169689Skan  enum gimplify_status ret;
493169689Skan
494169689Skan  if (STATEMENT_CODE_P (code))
495169689Skan    {
496169689Skan      saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
497169689Skan      current_stmt_tree ()->stmts_are_full_exprs_p
498169689Skan	= STMT_IS_FULL_EXPR_P (*expr_p);
499169689Skan    }
500169689Skan
501169689Skan  switch (code)
502169689Skan    {
503169689Skan    case PTRMEM_CST:
504169689Skan      *expr_p = cplus_expand_constant (*expr_p);
505169689Skan      ret = GS_OK;
506169689Skan      break;
507169689Skan
508169689Skan    case AGGR_INIT_EXPR:
509169689Skan      simplify_aggr_init_expr (expr_p);
510169689Skan      ret = GS_OK;
511169689Skan      break;
512169689Skan
513169689Skan    case THROW_EXPR:
514169689Skan      /* FIXME communicate throw type to backend, probably by moving
515169689Skan	 THROW_EXPR into ../tree.def.  */
516169689Skan      *expr_p = TREE_OPERAND (*expr_p, 0);
517169689Skan      ret = GS_OK;
518169689Skan      break;
519169689Skan
520169689Skan    case MUST_NOT_THROW_EXPR:
521169689Skan      gimplify_must_not_throw_expr (expr_p, pre_p);
522169689Skan      ret = GS_OK;
523169689Skan      break;
524169689Skan
525169689Skan      /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
526169689Skan	 LHS of an assignment might also be involved in the RHS, as in bug
527169689Skan	 25979.  */
528169689Skan    case INIT_EXPR:
529169689Skan      cp_gimplify_init_expr (expr_p, pre_p, post_p);
530169689Skan      ret = GS_OK;
531169689Skan      break;
532169689Skan
533169689Skan    case EMPTY_CLASS_EXPR:
534169689Skan      /* We create an empty CONSTRUCTOR with RECORD_TYPE.  */
535169689Skan      *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
536169689Skan      ret = GS_OK;
537169689Skan      break;
538169689Skan
539169689Skan    case BASELINK:
540169689Skan      *expr_p = BASELINK_FUNCTIONS (*expr_p);
541169689Skan      ret = GS_OK;
542169689Skan      break;
543169689Skan
544169689Skan    case TRY_BLOCK:
545169689Skan      genericize_try_block (expr_p);
546169689Skan      ret = GS_OK;
547169689Skan      break;
548169689Skan
549169689Skan    case HANDLER:
550169689Skan      genericize_catch_block (expr_p);
551169689Skan      ret = GS_OK;
552169689Skan      break;
553169689Skan
554169689Skan    case EH_SPEC_BLOCK:
555169689Skan      genericize_eh_spec_block (expr_p);
556169689Skan      ret = GS_OK;
557169689Skan      break;
558169689Skan
559169689Skan    case USING_STMT:
560169689Skan      /* Just ignore for now.  Eventually we will want to pass this on to
561169689Skan	 the debugger.  */
562169689Skan      *expr_p = build_empty_stmt ();
563169689Skan      ret = GS_ALL_DONE;
564169689Skan      break;
565169689Skan
566169689Skan    case IF_STMT:
567169689Skan      gimplify_if_stmt (expr_p);
568169689Skan      ret = GS_OK;
569169689Skan      break;
570169689Skan
571169689Skan    case FOR_STMT:
572169689Skan      gimplify_for_stmt (expr_p, pre_p);
573169689Skan      ret = GS_ALL_DONE;
574169689Skan      break;
575169689Skan
576169689Skan    case WHILE_STMT:
577169689Skan      gimplify_while_stmt (expr_p);
578169689Skan      ret = GS_ALL_DONE;
579169689Skan      break;
580169689Skan
581169689Skan    case DO_STMT:
582169689Skan      gimplify_do_stmt (expr_p);
583169689Skan      ret = GS_ALL_DONE;
584169689Skan      break;
585169689Skan
586169689Skan    case SWITCH_STMT:
587169689Skan      gimplify_switch_stmt (expr_p);
588169689Skan      ret = GS_ALL_DONE;
589169689Skan      break;
590169689Skan
591169689Skan    case OMP_FOR:
592169689Skan      ret = cp_gimplify_omp_for (expr_p);
593169689Skan      break;
594169689Skan
595169689Skan    case CONTINUE_STMT:
596169689Skan      *expr_p = build_bc_goto (bc_continue);
597169689Skan      ret = GS_ALL_DONE;
598169689Skan      break;
599169689Skan
600169689Skan    case BREAK_STMT:
601169689Skan      *expr_p = build_bc_goto (bc_break);
602169689Skan      ret = GS_ALL_DONE;
603169689Skan      break;
604169689Skan
605169689Skan    case EXPR_STMT:
606169689Skan      gimplify_expr_stmt (expr_p);
607169689Skan      ret = GS_OK;
608169689Skan      break;
609169689Skan
610169689Skan    case UNARY_PLUS_EXPR:
611169689Skan      {
612169689Skan	tree arg = TREE_OPERAND (*expr_p, 0);
613169689Skan	tree type = TREE_TYPE (*expr_p);
614169689Skan	*expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
615169689Skan					    : arg;
616169689Skan	ret = GS_OK;
617169689Skan      }
618169689Skan      break;
619169689Skan
620169689Skan    default:
621169689Skan      ret = c_gimplify_expr (expr_p, pre_p, post_p);
622169689Skan      break;
623169689Skan    }
624169689Skan
625169689Skan  /* Restore saved state.  */
626169689Skan  if (STATEMENT_CODE_P (code))
627169689Skan    current_stmt_tree ()->stmts_are_full_exprs_p
628169689Skan      = saved_stmts_are_full_exprs_p;
629169689Skan
630169689Skan  return ret;
631169689Skan}
632169689Skan
633169689Skanstatic inline bool
634169689Skanis_invisiref_parm (tree t)
635169689Skan{
636169689Skan  return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
637169689Skan	  && DECL_BY_REFERENCE (t));
638169689Skan}
639169689Skan
640169689Skan/* Return true if the uid in both int tree maps are equal.  */
641169689Skan
642169689Skanint
643169689Skancxx_int_tree_map_eq (const void *va, const void *vb)
644169689Skan{
645169689Skan  const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
646169689Skan  const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
647169689Skan  return (a->uid == b->uid);
648169689Skan}
649169689Skan
650169689Skan/* Hash a UID in a cxx_int_tree_map.  */
651169689Skan
652169689Skanunsigned int
653169689Skancxx_int_tree_map_hash (const void *item)
654169689Skan{
655169689Skan  return ((const struct cxx_int_tree_map *)item)->uid;
656169689Skan}
657169689Skan
658169689Skan/* Perform any pre-gimplification lowering of C++ front end trees to
659169689Skan   GENERIC.  */
660169689Skan
661169689Skanstatic tree
662169689Skancp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
663169689Skan{
664169689Skan  tree stmt = *stmt_p;
665169689Skan  struct pointer_set_t *p_set = (struct pointer_set_t*) data;
666169689Skan
667169689Skan  if (is_invisiref_parm (stmt)
668169689Skan      /* Don't dereference parms in a thunk, pass the references through. */
669169689Skan      && !(DECL_THUNK_P (current_function_decl)
670169689Skan	   && TREE_CODE (stmt) == PARM_DECL))
671169689Skan    {
672169689Skan      *stmt_p = convert_from_reference (stmt);
673169689Skan      *walk_subtrees = 0;
674169689Skan      return NULL;
675169689Skan    }
676169689Skan
677169689Skan  /* Map block scope extern declarations to visible declarations with the
678169689Skan     same name and type in outer scopes if any.  */
679169689Skan  if (cp_function_chain->extern_decl_map
680169689Skan      && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
681169689Skan      && DECL_EXTERNAL (stmt))
682169689Skan    {
683169689Skan      struct cxx_int_tree_map *h, in;
684169689Skan      in.uid = DECL_UID (stmt);
685169689Skan      h = (struct cxx_int_tree_map *)
686169689Skan	  htab_find_with_hash (cp_function_chain->extern_decl_map,
687169689Skan			       &in, in.uid);
688169689Skan      if (h)
689169689Skan	{
690169689Skan	  *stmt_p = h->to;
691169689Skan	  *walk_subtrees = 0;
692169689Skan	  return NULL;
693169689Skan	}
694169689Skan    }
695169689Skan
696169689Skan  /* Other than invisiref parms, don't walk the same tree twice.  */
697169689Skan  if (pointer_set_contains (p_set, stmt))
698169689Skan    {
699169689Skan      *walk_subtrees = 0;
700169689Skan      return NULL_TREE;
701169689Skan    }
702169689Skan
703169689Skan  if (TREE_CODE (stmt) == ADDR_EXPR
704169689Skan      && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
705169689Skan    {
706169689Skan      *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
707169689Skan      *walk_subtrees = 0;
708169689Skan    }
709169689Skan  else if (TREE_CODE (stmt) == RETURN_EXPR
710169689Skan	   && TREE_OPERAND (stmt, 0)
711169689Skan	   && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
712169689Skan    /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
713169689Skan    *walk_subtrees = 0;
714169689Skan  else if (TREE_CODE (stmt) == OMP_CLAUSE)
715169689Skan    switch (OMP_CLAUSE_CODE (stmt))
716169689Skan      {
717169689Skan      case OMP_CLAUSE_PRIVATE:
718169689Skan      case OMP_CLAUSE_SHARED:
719169689Skan      case OMP_CLAUSE_FIRSTPRIVATE:
720169689Skan      case OMP_CLAUSE_LASTPRIVATE:
721169689Skan      case OMP_CLAUSE_COPYIN:
722169689Skan      case OMP_CLAUSE_COPYPRIVATE:
723169689Skan	/* Don't dereference an invisiref in OpenMP clauses.  */
724169689Skan	if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
725169689Skan	  *walk_subtrees = 0;
726169689Skan	break;
727169689Skan      case OMP_CLAUSE_REDUCTION:
728169689Skan	gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
729169689Skan	break;
730169689Skan      default:
731169689Skan	break;
732169689Skan      }
733169689Skan  else if (IS_TYPE_OR_DECL_P (stmt))
734169689Skan    *walk_subtrees = 0;
735169689Skan
736169689Skan  /* Due to the way voidify_wrapper_expr is written, we don't get a chance
737169689Skan     to lower this construct before scanning it, so we need to lower these
738169689Skan     before doing anything else.  */
739169689Skan  else if (TREE_CODE (stmt) == CLEANUP_STMT)
740169689Skan    *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
741169689Skan					     : TRY_FINALLY_EXPR,
742169689Skan		      void_type_node,
743169689Skan		      CLEANUP_BODY (stmt),
744169689Skan		      CLEANUP_EXPR (stmt));
745169689Skan
746169689Skan  pointer_set_insert (p_set, *stmt_p);
747169689Skan
748169689Skan  return NULL;
749169689Skan}
750169689Skan
751169689Skanvoid
752169689Skancp_genericize (tree fndecl)
753169689Skan{
754169689Skan  tree t;
755169689Skan  struct pointer_set_t *p_set;
756169689Skan
757169689Skan  /* Fix up the types of parms passed by invisible reference.  */
758169689Skan  for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
759169689Skan    if (TREE_ADDRESSABLE (TREE_TYPE (t)))
760169689Skan      {
761169689Skan	/* If a function's arguments are copied to create a thunk,
762169689Skan	   then DECL_BY_REFERENCE will be set -- but the type of the
763169689Skan	   argument will be a pointer type, so we will never get
764169689Skan	   here.  */
765169689Skan	gcc_assert (!DECL_BY_REFERENCE (t));
766169689Skan	gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
767169689Skan	TREE_TYPE (t) = DECL_ARG_TYPE (t);
768169689Skan	DECL_BY_REFERENCE (t) = 1;
769169689Skan	TREE_ADDRESSABLE (t) = 0;
770169689Skan	relayout_decl (t);
771169689Skan      }
772169689Skan
773169689Skan  /* Do the same for the return value.  */
774169689Skan  if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
775169689Skan    {
776169689Skan      t = DECL_RESULT (fndecl);
777169689Skan      TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
778169689Skan      DECL_BY_REFERENCE (t) = 1;
779169689Skan      TREE_ADDRESSABLE (t) = 0;
780169689Skan      relayout_decl (t);
781169689Skan    }
782169689Skan
783169689Skan  /* If we're a clone, the body is already GIMPLE.  */
784169689Skan  if (DECL_CLONED_FUNCTION_P (fndecl))
785169689Skan    return;
786169689Skan
787169689Skan  /* We do want to see every occurrence of the parms, so we can't just use
788169689Skan     walk_tree's hash functionality.  */
789169689Skan  p_set = pointer_set_create ();
790169689Skan  walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
791169689Skan  pointer_set_destroy (p_set);
792169689Skan
793169689Skan  /* Do everything else.  */
794169689Skan  c_genericize (fndecl);
795169689Skan
796169689Skan  gcc_assert (bc_label[bc_break] == NULL);
797169689Skan  gcc_assert (bc_label[bc_continue] == NULL);
798169689Skan}
799169689Skan
800169689Skan/* Build code to apply FN to each member of ARG1 and ARG2.  FN may be
801169689Skan   NULL if there is in fact nothing to do.  ARG2 may be null if FN
802169689Skan   actually only takes one argument.  */
803169689Skan
804169689Skanstatic tree
805169689Skancxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
806169689Skan{
807169689Skan  tree defparm, parm;
808169689Skan  int i;
809169689Skan
810169689Skan  if (fn == NULL)
811169689Skan    return NULL;
812169689Skan
813169689Skan  defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
814169689Skan  if (arg2)
815169689Skan    defparm = TREE_CHAIN (defparm);
816169689Skan
817169689Skan  if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
818169689Skan    {
819169689Skan      tree inner_type = TREE_TYPE (arg1);
820169689Skan      tree start1, end1, p1;
821169689Skan      tree start2 = NULL, p2 = NULL;
822169689Skan      tree ret = NULL, lab, t;
823169689Skan
824169689Skan      start1 = arg1;
825169689Skan      start2 = arg2;
826169689Skan      do
827169689Skan	{
828169689Skan	  inner_type = TREE_TYPE (inner_type);
829169689Skan	  start1 = build4 (ARRAY_REF, inner_type, start1,
830169689Skan			   size_zero_node, NULL, NULL);
831169689Skan	  if (arg2)
832169689Skan	    start2 = build4 (ARRAY_REF, inner_type, start2,
833169689Skan			     size_zero_node, NULL, NULL);
834169689Skan	}
835169689Skan      while (TREE_CODE (inner_type) == ARRAY_TYPE);
836169689Skan      start1 = build_fold_addr_expr (start1);
837169689Skan      if (arg2)
838169689Skan	start2 = build_fold_addr_expr (start2);
839169689Skan
840169689Skan      end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
841169689Skan      end1 = fold_convert (TREE_TYPE (start1), end1);
842169689Skan      end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1);
843169689Skan
844169689Skan      p1 = create_tmp_var (TREE_TYPE (start1), NULL);
845169689Skan      t = build2 (MODIFY_EXPR, void_type_node, p1, start1);
846169689Skan      append_to_statement_list (t, &ret);
847169689Skan
848169689Skan      if (arg2)
849169689Skan	{
850169689Skan	  p2 = create_tmp_var (TREE_TYPE (start2), NULL);
851169689Skan	  t = build2 (MODIFY_EXPR, void_type_node, p2, start2);
852169689Skan	  append_to_statement_list (t, &ret);
853169689Skan	}
854169689Skan
855169689Skan      lab = create_artificial_label ();
856169689Skan      t = build1 (LABEL_EXPR, void_type_node, lab);
857169689Skan      append_to_statement_list (t, &ret);
858169689Skan
859169689Skan      t = tree_cons (NULL, p1, NULL);
860169689Skan      if (arg2)
861169689Skan	t = tree_cons (NULL, p2, t);
862169689Skan      /* Handle default arguments.  */
863169689Skan      i = 1 + (arg2 != NULL);
864169689Skan      for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
865169689Skan	t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
866169689Skan						  TREE_PURPOSE (parm),
867169689Skan						  fn, i++), t);
868169689Skan      t = build_call (fn, nreverse (t));
869169689Skan      append_to_statement_list (t, &ret);
870169689Skan
871169689Skan      t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type));
872169689Skan      t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t);
873169689Skan      t = build2 (MODIFY_EXPR, void_type_node, p1, t);
874169689Skan      append_to_statement_list (t, &ret);
875169689Skan
876169689Skan      if (arg2)
877169689Skan	{
878169689Skan	  t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type));
879169689Skan	  t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t);
880169689Skan	  t = build2 (MODIFY_EXPR, void_type_node, p2, t);
881169689Skan	  append_to_statement_list (t, &ret);
882169689Skan	}
883169689Skan
884169689Skan      t = build2 (NE_EXPR, boolean_type_node, p1, end1);
885169689Skan      t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
886169689Skan      append_to_statement_list (t, &ret);
887169689Skan
888169689Skan      return ret;
889169689Skan    }
890169689Skan  else
891169689Skan    {
892169689Skan      tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL);
893169689Skan      if (arg2)
894169689Skan	t = tree_cons (NULL, build_fold_addr_expr (arg2), t);
895169689Skan      /* Handle default arguments.  */
896169689Skan      i = 1 + (arg2 != NULL);
897169689Skan      for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
898169689Skan	t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
899169689Skan						  TREE_PURPOSE (parm),
900169689Skan						  fn, i++), t);
901169689Skan      return build_call (fn, nreverse (t));
902169689Skan    }
903169689Skan}
904169689Skan
905169689Skan/* Return code to initialize DECL with its default constructor, or
906169689Skan   NULL if there's nothing to do.  */
907169689Skan
908169689Skantree
909169689Skancxx_omp_clause_default_ctor (tree clause, tree decl)
910169689Skan{
911169689Skan  tree info = CP_OMP_CLAUSE_INFO (clause);
912169689Skan  tree ret = NULL;
913169689Skan
914169689Skan  if (info)
915169689Skan    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
916169689Skan
917169689Skan  return ret;
918169689Skan}
919169689Skan
920169689Skan/* Return code to initialize DST with a copy constructor from SRC.  */
921169689Skan
922169689Skantree
923169689Skancxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
924169689Skan{
925169689Skan  tree info = CP_OMP_CLAUSE_INFO (clause);
926169689Skan  tree ret = NULL;
927169689Skan
928169689Skan  if (info)
929169689Skan    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
930169689Skan  if (ret == NULL)
931169689Skan    ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
932169689Skan
933169689Skan  return ret;
934169689Skan}
935169689Skan
936169689Skan/* Similarly, except use an assignment operator instead.  */
937169689Skan
938169689Skantree
939169689Skancxx_omp_clause_assign_op (tree clause, tree dst, tree src)
940169689Skan{
941169689Skan  tree info = CP_OMP_CLAUSE_INFO (clause);
942169689Skan  tree ret = NULL;
943169689Skan
944169689Skan  if (info)
945169689Skan    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
946169689Skan  if (ret == NULL)
947169689Skan    ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
948169689Skan
949169689Skan  return ret;
950169689Skan}
951169689Skan
952169689Skan/* Return code to destroy DECL.  */
953169689Skan
954169689Skantree
955169689Skancxx_omp_clause_dtor (tree clause, tree decl)
956169689Skan{
957169689Skan  tree info = CP_OMP_CLAUSE_INFO (clause);
958169689Skan  tree ret = NULL;
959169689Skan
960169689Skan  if (info)
961169689Skan    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
962169689Skan
963169689Skan  return ret;
964169689Skan}
965169689Skan
966169689Skan/* True if OpenMP should privatize what this DECL points to rather
967169689Skan   than the DECL itself.  */
968169689Skan
969169689Skanbool
970169689Skancxx_omp_privatize_by_reference (tree decl)
971169689Skan{
972169689Skan  return is_invisiref_parm (decl);
973169689Skan}
974