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
191260919Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
192260919Spfggimplify_cp_loop (tree cond, tree body, tree incr, tree attrs,
193260919Spfg		  bool cond_is_first, tree inner_foreach)
194260919Spfg/* 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
203169689Skan  break_block = begin_bc_block (bc_break);
204169689Skan  cont_block = begin_bc_block (bc_continue);
205169689Skan
206169689Skan  /* If condition is zero don't generate a loop construct.  */
207169689Skan  if (cond && integer_zerop (cond))
208169689Skan    {
209169689Skan      top = NULL_TREE;
210169689Skan      exit = NULL_TREE;
211169689Skan      if (cond_is_first)
212169689Skan	{
213169689Skan	  t = build_bc_goto (bc_break);
214169689Skan	  append_to_statement_list (t, &stmt_list);
215169689Skan	}
216169689Skan    }
217169689Skan  else
218169689Skan    {
219169689Skan      /* If we use a LOOP_EXPR here, we have to feed the whole thing
220169689Skan	 back through the main gimplifier to lower it.  Given that we
221169689Skan	 have to gimplify the loop body NOW so that we can resolve
222169689Skan	 break/continue stmts, seems easier to just expand to gotos.  */
223169689Skan      top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
224169689Skan
225169689Skan      /* If we have an exit condition, then we build an IF with gotos either
226169689Skan	 out of the loop, or to the top of it.  If there's no exit condition,
227169689Skan	 then we just build a jump back to the top.  */
228169689Skan      exit = build_and_jump (&LABEL_EXPR_LABEL (top));
229260919Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
230260919Spfg
231260919Spfg      /* Add the attributes to the 'top' label.  */
232260919Spfg      decl_attributes (&LABEL_EXPR_LABEL (top), attrs, 0);
233260919Spfg
234260919Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
235169689Skan      if (cond && !integer_nonzerop (cond))
236169689Skan	{
237169689Skan	  t = build_bc_goto (bc_break);
238169689Skan	  exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
239169689Skan	  gimplify_stmt (&exit);
240169689Skan
241169689Skan	  if (cond_is_first)
242169689Skan	    {
243169689Skan	      if (incr)
244169689Skan		{
245169689Skan		  entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
246169689Skan		  t = build_and_jump (&LABEL_EXPR_LABEL (entry));
247169689Skan		}
248169689Skan	      else
249169689Skan		t = build_bc_goto (bc_continue);
250169689Skan	      append_to_statement_list (t, &stmt_list);
251169689Skan	    }
252169689Skan	}
253169689Skan    }
254169689Skan
255169689Skan  gimplify_stmt (&body);
256169689Skan  gimplify_stmt (&incr);
257169689Skan
258169689Skan  body = finish_bc_block (bc_continue, cont_block, body);
259169689Skan
260169689Skan  append_to_statement_list (top, &stmt_list);
261169689Skan  append_to_statement_list (body, &stmt_list);
262169689Skan  append_to_statement_list (incr, &stmt_list);
263169689Skan  append_to_statement_list (entry, &stmt_list);
264169689Skan  append_to_statement_list (exit, &stmt_list);
265169689Skan
266169689Skan  annotate_all_with_locus (&stmt_list, stmt_locus);
267169689Skan
268169689Skan  return finish_bc_block (bc_break, break_block, stmt_list);
269169689Skan}
270169689Skan
271169689Skan/* Gimplify a FOR_STMT node.  Move the stuff in the for-init-stmt into the
272169689Skan   prequeue and hand off to gimplify_cp_loop.  */
273169689Skan
274169689Skanstatic void
275169689Skangimplify_for_stmt (tree *stmt_p, tree *pre_p)
276169689Skan{
277169689Skan  tree stmt = *stmt_p;
278169689Skan
279169689Skan  if (FOR_INIT_STMT (stmt))
280169689Skan    gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
281169689Skan
282260919Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
283169689Skan  *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
284260919Spfg			      FOR_EXPR (stmt), FOR_ATTRIBUTES (stmt), 1,
285260919Spfg			      NULL_TREE);
286260919Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
287169689Skan}
288169689Skan
289169689Skan/* Gimplify a WHILE_STMT node.  */
290169689Skan
291169689Skanstatic void
292169689Skangimplify_while_stmt (tree *stmt_p)
293169689Skan{
294169689Skan  tree stmt = *stmt_p;
295260919Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
296169689Skan  *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
297260919Spfg			      NULL_TREE, WHILE_ATTRIBUTES (stmt), 1,
298260919Spfg			      NULL_TREE);
299260919Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
300169689Skan}
301169689Skan
302169689Skan/* Gimplify a DO_STMT node.  */
303169689Skan
304169689Skanstatic void
305169689Skangimplify_do_stmt (tree *stmt_p)
306169689Skan{
307169689Skan  tree stmt = *stmt_p;
308260919Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \
309169689Skan  *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
310260919Spfg			      NULL_TREE, DO_ATTRIBUTES (stmt), 0,
311260919Spfg			      DO_FOREACH (stmt));
312260919Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \
313169689Skan}
314169689Skan
315169689Skan/* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
316169689Skan
317169689Skanstatic void
318169689Skangimplify_switch_stmt (tree *stmt_p)
319169689Skan{
320169689Skan  tree stmt = *stmt_p;
321169689Skan  tree break_block, body;
322169689Skan  location_t stmt_locus = input_location;
323169689Skan
324169689Skan  break_block = begin_bc_block (bc_break);
325169689Skan
326169689Skan  body = SWITCH_STMT_BODY (stmt);
327169689Skan  if (!body)
328169689Skan    body = build_empty_stmt ();
329169689Skan
330169689Skan  *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
331169689Skan		    SWITCH_STMT_COND (stmt), body, NULL_TREE);
332169689Skan  SET_EXPR_LOCATION (*stmt_p, stmt_locus);
333169689Skan  gimplify_stmt (stmt_p);
334169689Skan
335169689Skan  *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p);
336169689Skan}
337169689Skan
338169689Skan/* Hook into the middle of gimplifying an OMP_FOR node.  This is required
339169689Skan   in order to properly gimplify CONTINUE statements.  Here we merely
340169689Skan   manage the continue stack; the rest of the job is performed by the
341169689Skan   regular gimplifier.  */
342169689Skan
343169689Skanstatic enum gimplify_status
344169689Skancp_gimplify_omp_for (tree *expr_p)
345169689Skan{
346169689Skan  tree for_stmt = *expr_p;
347169689Skan  tree cont_block;
348169689Skan
349169689Skan  /* Protect ourselves from recursion.  */
350169689Skan  if (OMP_FOR_GIMPLIFYING_P (for_stmt))
351169689Skan    return GS_UNHANDLED;
352169689Skan  OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
353169689Skan
354169689Skan  /* Note that while technically the continue label is enabled too soon
355169689Skan     here, we should have already diagnosed invalid continues nested within
356169689Skan     statement expressions within the INIT, COND, or INCR expressions.  */
357169689Skan  cont_block = begin_bc_block (bc_continue);
358169689Skan
359169689Skan  gimplify_stmt (expr_p);
360169689Skan
361169689Skan  OMP_FOR_BODY (for_stmt)
362169689Skan    = finish_bc_block (bc_continue, cont_block, OMP_FOR_BODY (for_stmt));
363169689Skan  OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
364169689Skan
365169689Skan  return GS_ALL_DONE;
366169689Skan}
367169689Skan
368169689Skan/*  Gimplify an EXPR_STMT node.  */
369169689Skan
370169689Skanstatic void
371169689Skangimplify_expr_stmt (tree *stmt_p)
372169689Skan{
373169689Skan  tree stmt = EXPR_STMT_EXPR (*stmt_p);
374169689Skan
375169689Skan  if (stmt == error_mark_node)
376169689Skan    stmt = NULL;
377169689Skan
378169689Skan  /* Gimplification of a statement expression will nullify the
379169689Skan     statement if all its side effects are moved to *PRE_P and *POST_P.
380169689Skan
381169689Skan     In this case we will not want to emit the gimplified statement.
382169689Skan     However, we may still want to emit a warning, so we do that before
383169689Skan     gimplification.  */
384169689Skan  if (stmt && (extra_warnings || warn_unused_value))
385169689Skan    {
386169689Skan      if (!TREE_SIDE_EFFECTS (stmt))
387169689Skan	{
388169689Skan	  if (!IS_EMPTY_STMT (stmt)
389169689Skan	      && !VOID_TYPE_P (TREE_TYPE (stmt))
390169689Skan	      && !TREE_NO_WARNING (stmt))
391169689Skan	    warning (OPT_Wextra, "statement with no effect");
392169689Skan	}
393169689Skan      else if (warn_unused_value)
394169689Skan	warn_if_unused_value (stmt, input_location);
395169689Skan    }
396169689Skan
397169689Skan  if (stmt == NULL_TREE)
398169689Skan    stmt = alloc_stmt_list ();
399169689Skan
400169689Skan  *stmt_p = stmt;
401169689Skan}
402169689Skan
403169689Skan/* Gimplify initialization from an AGGR_INIT_EXPR.  */
404169689Skan
405169689Skanstatic void
406169689Skancp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
407169689Skan{
408169689Skan  tree from = TREE_OPERAND (*expr_p, 1);
409169689Skan  tree to = TREE_OPERAND (*expr_p, 0);
410169689Skan  tree sub;
411169689Skan
412169689Skan  /* What about code that pulls out the temp and uses it elsewhere?  I
413169689Skan     think that such code never uses the TARGET_EXPR as an initializer.  If
414169689Skan     I'm wrong, we'll abort because the temp won't have any RTL.  In that
415169689Skan     case, I guess we'll need to replace references somehow.  */
416169689Skan  if (TREE_CODE (from) == TARGET_EXPR)
417169689Skan    from = TARGET_EXPR_INITIAL (from);
418169689Skan
419169689Skan  /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
420169689Skan     inside the TARGET_EXPR.  */
421169689Skan  sub = expr_last (from);
422169689Skan
423169689Skan  /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
424169689Skan     replace the slot operand with our target.
425169689Skan
426169689Skan     Should we add a target parm to gimplify_expr instead?  No, as in this
427169689Skan     case we want to replace the INIT_EXPR.  */
428169689Skan  if (TREE_CODE (sub) == AGGR_INIT_EXPR)
429169689Skan    {
430169689Skan      gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
431169689Skan      TREE_OPERAND (sub, 2) = to;
432169689Skan      *expr_p = from;
433169689Skan
434169689Skan      /* The initialization is now a side-effect, so the container can
435169689Skan	 become void.  */
436169689Skan      if (from != sub)
437169689Skan	TREE_TYPE (from) = void_type_node;
438169689Skan    }
439169689Skan}
440169689Skan
441169689Skan/* Gimplify a MUST_NOT_THROW_EXPR.  */
442169689Skan
443169689Skanstatic void
444169689Skangimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
445169689Skan{
446169689Skan  tree stmt = *expr_p;
447169689Skan  tree temp = voidify_wrapper_expr (stmt, NULL);
448169689Skan  tree body = TREE_OPERAND (stmt, 0);
449169689Skan
450169689Skan  gimplify_stmt (&body);
451169689Skan
452169689Skan  stmt = gimple_build_eh_filter (body, NULL_TREE,
453169689Skan				 build_call (terminate_node, NULL_TREE));
454169689Skan
455169689Skan  if (temp)
456169689Skan    {
457169689Skan      append_to_statement_list (stmt, pre_p);
458169689Skan      *expr_p = temp;
459169689Skan    }
460169689Skan  else
461169689Skan    *expr_p = stmt;
462169689Skan}
463169689Skan
464169689Skan/* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
465169689Skan
466169689Skanint
467169689Skancp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
468169689Skan{
469169689Skan  int saved_stmts_are_full_exprs_p = 0;
470169689Skan  enum tree_code code = TREE_CODE (*expr_p);
471169689Skan  enum gimplify_status ret;
472169689Skan
473169689Skan  if (STATEMENT_CODE_P (code))
474169689Skan    {
475169689Skan      saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
476169689Skan      current_stmt_tree ()->stmts_are_full_exprs_p
477169689Skan	= STMT_IS_FULL_EXPR_P (*expr_p);
478169689Skan    }
479169689Skan
480169689Skan  switch (code)
481169689Skan    {
482169689Skan    case PTRMEM_CST:
483169689Skan      *expr_p = cplus_expand_constant (*expr_p);
484169689Skan      ret = GS_OK;
485169689Skan      break;
486169689Skan
487169689Skan    case AGGR_INIT_EXPR:
488169689Skan      simplify_aggr_init_expr (expr_p);
489169689Skan      ret = GS_OK;
490169689Skan      break;
491169689Skan
492169689Skan    case THROW_EXPR:
493169689Skan      /* FIXME communicate throw type to backend, probably by moving
494169689Skan	 THROW_EXPR into ../tree.def.  */
495169689Skan      *expr_p = TREE_OPERAND (*expr_p, 0);
496169689Skan      ret = GS_OK;
497169689Skan      break;
498169689Skan
499169689Skan    case MUST_NOT_THROW_EXPR:
500169689Skan      gimplify_must_not_throw_expr (expr_p, pre_p);
501169689Skan      ret = GS_OK;
502169689Skan      break;
503169689Skan
504169689Skan      /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
505169689Skan	 LHS of an assignment might also be involved in the RHS, as in bug
506169689Skan	 25979.  */
507169689Skan    case INIT_EXPR:
508169689Skan      cp_gimplify_init_expr (expr_p, pre_p, post_p);
509169689Skan      ret = GS_OK;
510169689Skan      break;
511169689Skan
512169689Skan    case EMPTY_CLASS_EXPR:
513169689Skan      /* We create an empty CONSTRUCTOR with RECORD_TYPE.  */
514169689Skan      *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
515169689Skan      ret = GS_OK;
516169689Skan      break;
517169689Skan
518169689Skan    case BASELINK:
519169689Skan      *expr_p = BASELINK_FUNCTIONS (*expr_p);
520169689Skan      ret = GS_OK;
521169689Skan      break;
522169689Skan
523169689Skan    case TRY_BLOCK:
524169689Skan      genericize_try_block (expr_p);
525169689Skan      ret = GS_OK;
526169689Skan      break;
527169689Skan
528169689Skan    case HANDLER:
529169689Skan      genericize_catch_block (expr_p);
530169689Skan      ret = GS_OK;
531169689Skan      break;
532169689Skan
533169689Skan    case EH_SPEC_BLOCK:
534169689Skan      genericize_eh_spec_block (expr_p);
535169689Skan      ret = GS_OK;
536169689Skan      break;
537169689Skan
538169689Skan    case USING_STMT:
539169689Skan      /* Just ignore for now.  Eventually we will want to pass this on to
540169689Skan	 the debugger.  */
541169689Skan      *expr_p = build_empty_stmt ();
542169689Skan      ret = GS_ALL_DONE;
543169689Skan      break;
544169689Skan
545169689Skan    case IF_STMT:
546169689Skan      gimplify_if_stmt (expr_p);
547169689Skan      ret = GS_OK;
548169689Skan      break;
549169689Skan
550169689Skan    case FOR_STMT:
551169689Skan      gimplify_for_stmt (expr_p, pre_p);
552169689Skan      ret = GS_ALL_DONE;
553169689Skan      break;
554169689Skan
555169689Skan    case WHILE_STMT:
556169689Skan      gimplify_while_stmt (expr_p);
557169689Skan      ret = GS_ALL_DONE;
558169689Skan      break;
559169689Skan
560169689Skan    case DO_STMT:
561169689Skan      gimplify_do_stmt (expr_p);
562169689Skan      ret = GS_ALL_DONE;
563169689Skan      break;
564169689Skan
565169689Skan    case SWITCH_STMT:
566169689Skan      gimplify_switch_stmt (expr_p);
567169689Skan      ret = GS_ALL_DONE;
568169689Skan      break;
569169689Skan
570169689Skan    case OMP_FOR:
571169689Skan      ret = cp_gimplify_omp_for (expr_p);
572169689Skan      break;
573169689Skan
574169689Skan    case CONTINUE_STMT:
575169689Skan      *expr_p = build_bc_goto (bc_continue);
576169689Skan      ret = GS_ALL_DONE;
577169689Skan      break;
578169689Skan
579169689Skan    case BREAK_STMT:
580169689Skan      *expr_p = build_bc_goto (bc_break);
581169689Skan      ret = GS_ALL_DONE;
582169689Skan      break;
583169689Skan
584169689Skan    case EXPR_STMT:
585169689Skan      gimplify_expr_stmt (expr_p);
586169689Skan      ret = GS_OK;
587169689Skan      break;
588169689Skan
589169689Skan    case UNARY_PLUS_EXPR:
590169689Skan      {
591169689Skan	tree arg = TREE_OPERAND (*expr_p, 0);
592169689Skan	tree type = TREE_TYPE (*expr_p);
593169689Skan	*expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
594169689Skan					    : arg;
595169689Skan	ret = GS_OK;
596169689Skan      }
597169689Skan      break;
598169689Skan
599169689Skan    default:
600169689Skan      ret = c_gimplify_expr (expr_p, pre_p, post_p);
601169689Skan      break;
602169689Skan    }
603169689Skan
604169689Skan  /* Restore saved state.  */
605169689Skan  if (STATEMENT_CODE_P (code))
606169689Skan    current_stmt_tree ()->stmts_are_full_exprs_p
607169689Skan      = saved_stmts_are_full_exprs_p;
608169689Skan
609169689Skan  return ret;
610169689Skan}
611169689Skan
612169689Skanstatic inline bool
613169689Skanis_invisiref_parm (tree t)
614169689Skan{
615169689Skan  return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
616169689Skan	  && DECL_BY_REFERENCE (t));
617169689Skan}
618169689Skan
619169689Skan/* Return true if the uid in both int tree maps are equal.  */
620169689Skan
621169689Skanint
622169689Skancxx_int_tree_map_eq (const void *va, const void *vb)
623169689Skan{
624169689Skan  const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va;
625169689Skan  const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb;
626169689Skan  return (a->uid == b->uid);
627169689Skan}
628169689Skan
629169689Skan/* Hash a UID in a cxx_int_tree_map.  */
630169689Skan
631169689Skanunsigned int
632169689Skancxx_int_tree_map_hash (const void *item)
633169689Skan{
634169689Skan  return ((const struct cxx_int_tree_map *)item)->uid;
635169689Skan}
636169689Skan
637169689Skan/* Perform any pre-gimplification lowering of C++ front end trees to
638169689Skan   GENERIC.  */
639169689Skan
640169689Skanstatic tree
641169689Skancp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
642169689Skan{
643169689Skan  tree stmt = *stmt_p;
644169689Skan  struct pointer_set_t *p_set = (struct pointer_set_t*) data;
645169689Skan
646169689Skan  if (is_invisiref_parm (stmt)
647169689Skan      /* Don't dereference parms in a thunk, pass the references through. */
648169689Skan      && !(DECL_THUNK_P (current_function_decl)
649169689Skan	   && TREE_CODE (stmt) == PARM_DECL))
650169689Skan    {
651169689Skan      *stmt_p = convert_from_reference (stmt);
652169689Skan      *walk_subtrees = 0;
653169689Skan      return NULL;
654169689Skan    }
655169689Skan
656169689Skan  /* Map block scope extern declarations to visible declarations with the
657169689Skan     same name and type in outer scopes if any.  */
658169689Skan  if (cp_function_chain->extern_decl_map
659169689Skan      && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL)
660169689Skan      && DECL_EXTERNAL (stmt))
661169689Skan    {
662169689Skan      struct cxx_int_tree_map *h, in;
663169689Skan      in.uid = DECL_UID (stmt);
664169689Skan      h = (struct cxx_int_tree_map *)
665169689Skan	  htab_find_with_hash (cp_function_chain->extern_decl_map,
666169689Skan			       &in, in.uid);
667169689Skan      if (h)
668169689Skan	{
669169689Skan	  *stmt_p = h->to;
670169689Skan	  *walk_subtrees = 0;
671169689Skan	  return NULL;
672169689Skan	}
673169689Skan    }
674169689Skan
675169689Skan  /* Other than invisiref parms, don't walk the same tree twice.  */
676169689Skan  if (pointer_set_contains (p_set, stmt))
677169689Skan    {
678169689Skan      *walk_subtrees = 0;
679169689Skan      return NULL_TREE;
680169689Skan    }
681169689Skan
682169689Skan  if (TREE_CODE (stmt) == ADDR_EXPR
683169689Skan      && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
684169689Skan    {
685169689Skan      *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
686169689Skan      *walk_subtrees = 0;
687169689Skan    }
688169689Skan  else if (TREE_CODE (stmt) == RETURN_EXPR
689169689Skan	   && TREE_OPERAND (stmt, 0)
690169689Skan	   && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
691169689Skan    /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
692169689Skan    *walk_subtrees = 0;
693169689Skan  else if (TREE_CODE (stmt) == OMP_CLAUSE)
694169689Skan    switch (OMP_CLAUSE_CODE (stmt))
695169689Skan      {
696169689Skan      case OMP_CLAUSE_PRIVATE:
697169689Skan      case OMP_CLAUSE_SHARED:
698169689Skan      case OMP_CLAUSE_FIRSTPRIVATE:
699169689Skan      case OMP_CLAUSE_LASTPRIVATE:
700169689Skan      case OMP_CLAUSE_COPYIN:
701169689Skan      case OMP_CLAUSE_COPYPRIVATE:
702169689Skan	/* Don't dereference an invisiref in OpenMP clauses.  */
703169689Skan	if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
704169689Skan	  *walk_subtrees = 0;
705169689Skan	break;
706169689Skan      case OMP_CLAUSE_REDUCTION:
707169689Skan	gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt)));
708169689Skan	break;
709169689Skan      default:
710169689Skan	break;
711169689Skan      }
712169689Skan  else if (IS_TYPE_OR_DECL_P (stmt))
713169689Skan    *walk_subtrees = 0;
714169689Skan
715169689Skan  /* Due to the way voidify_wrapper_expr is written, we don't get a chance
716169689Skan     to lower this construct before scanning it, so we need to lower these
717169689Skan     before doing anything else.  */
718169689Skan  else if (TREE_CODE (stmt) == CLEANUP_STMT)
719169689Skan    *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
720169689Skan					     : TRY_FINALLY_EXPR,
721169689Skan		      void_type_node,
722169689Skan		      CLEANUP_BODY (stmt),
723169689Skan		      CLEANUP_EXPR (stmt));
724169689Skan
725169689Skan  pointer_set_insert (p_set, *stmt_p);
726169689Skan
727169689Skan  return NULL;
728169689Skan}
729169689Skan
730169689Skanvoid
731169689Skancp_genericize (tree fndecl)
732169689Skan{
733169689Skan  tree t;
734169689Skan  struct pointer_set_t *p_set;
735169689Skan
736169689Skan  /* Fix up the types of parms passed by invisible reference.  */
737169689Skan  for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
738169689Skan    if (TREE_ADDRESSABLE (TREE_TYPE (t)))
739169689Skan      {
740169689Skan	/* If a function's arguments are copied to create a thunk,
741169689Skan	   then DECL_BY_REFERENCE will be set -- but the type of the
742169689Skan	   argument will be a pointer type, so we will never get
743169689Skan	   here.  */
744169689Skan	gcc_assert (!DECL_BY_REFERENCE (t));
745169689Skan	gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
746169689Skan	TREE_TYPE (t) = DECL_ARG_TYPE (t);
747169689Skan	DECL_BY_REFERENCE (t) = 1;
748169689Skan	TREE_ADDRESSABLE (t) = 0;
749169689Skan	relayout_decl (t);
750169689Skan      }
751169689Skan
752169689Skan  /* Do the same for the return value.  */
753169689Skan  if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
754169689Skan    {
755169689Skan      t = DECL_RESULT (fndecl);
756169689Skan      TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
757169689Skan      DECL_BY_REFERENCE (t) = 1;
758169689Skan      TREE_ADDRESSABLE (t) = 0;
759169689Skan      relayout_decl (t);
760169689Skan    }
761169689Skan
762169689Skan  /* If we're a clone, the body is already GIMPLE.  */
763169689Skan  if (DECL_CLONED_FUNCTION_P (fndecl))
764169689Skan    return;
765169689Skan
766169689Skan  /* We do want to see every occurrence of the parms, so we can't just use
767169689Skan     walk_tree's hash functionality.  */
768169689Skan  p_set = pointer_set_create ();
769169689Skan  walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
770169689Skan  pointer_set_destroy (p_set);
771169689Skan
772169689Skan  /* Do everything else.  */
773169689Skan  c_genericize (fndecl);
774169689Skan
775169689Skan  gcc_assert (bc_label[bc_break] == NULL);
776169689Skan  gcc_assert (bc_label[bc_continue] == NULL);
777169689Skan}
778169689Skan
779169689Skan/* Build code to apply FN to each member of ARG1 and ARG2.  FN may be
780169689Skan   NULL if there is in fact nothing to do.  ARG2 may be null if FN
781169689Skan   actually only takes one argument.  */
782169689Skan
783169689Skanstatic tree
784169689Skancxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
785169689Skan{
786169689Skan  tree defparm, parm;
787169689Skan  int i;
788169689Skan
789169689Skan  if (fn == NULL)
790169689Skan    return NULL;
791169689Skan
792169689Skan  defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
793169689Skan  if (arg2)
794169689Skan    defparm = TREE_CHAIN (defparm);
795169689Skan
796169689Skan  if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
797169689Skan    {
798169689Skan      tree inner_type = TREE_TYPE (arg1);
799169689Skan      tree start1, end1, p1;
800169689Skan      tree start2 = NULL, p2 = NULL;
801169689Skan      tree ret = NULL, lab, t;
802169689Skan
803169689Skan      start1 = arg1;
804169689Skan      start2 = arg2;
805169689Skan      do
806169689Skan	{
807169689Skan	  inner_type = TREE_TYPE (inner_type);
808169689Skan	  start1 = build4 (ARRAY_REF, inner_type, start1,
809169689Skan			   size_zero_node, NULL, NULL);
810169689Skan	  if (arg2)
811169689Skan	    start2 = build4 (ARRAY_REF, inner_type, start2,
812169689Skan			     size_zero_node, NULL, NULL);
813169689Skan	}
814169689Skan      while (TREE_CODE (inner_type) == ARRAY_TYPE);
815169689Skan      start1 = build_fold_addr_expr (start1);
816169689Skan      if (arg2)
817169689Skan	start2 = build_fold_addr_expr (start2);
818169689Skan
819169689Skan      end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
820169689Skan      end1 = fold_convert (TREE_TYPE (start1), end1);
821169689Skan      end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1);
822169689Skan
823169689Skan      p1 = create_tmp_var (TREE_TYPE (start1), NULL);
824169689Skan      t = build2 (MODIFY_EXPR, void_type_node, p1, start1);
825169689Skan      append_to_statement_list (t, &ret);
826169689Skan
827169689Skan      if (arg2)
828169689Skan	{
829169689Skan	  p2 = create_tmp_var (TREE_TYPE (start2), NULL);
830169689Skan	  t = build2 (MODIFY_EXPR, void_type_node, p2, start2);
831169689Skan	  append_to_statement_list (t, &ret);
832169689Skan	}
833169689Skan
834169689Skan      lab = create_artificial_label ();
835169689Skan      t = build1 (LABEL_EXPR, void_type_node, lab);
836169689Skan      append_to_statement_list (t, &ret);
837169689Skan
838169689Skan      t = tree_cons (NULL, p1, NULL);
839169689Skan      if (arg2)
840169689Skan	t = tree_cons (NULL, p2, t);
841169689Skan      /* Handle default arguments.  */
842169689Skan      i = 1 + (arg2 != NULL);
843169689Skan      for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
844169689Skan	t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
845169689Skan						  TREE_PURPOSE (parm),
846169689Skan						  fn, i++), t);
847169689Skan      t = build_call (fn, nreverse (t));
848169689Skan      append_to_statement_list (t, &ret);
849169689Skan
850169689Skan      t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type));
851169689Skan      t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t);
852169689Skan      t = build2 (MODIFY_EXPR, void_type_node, p1, t);
853169689Skan      append_to_statement_list (t, &ret);
854169689Skan
855169689Skan      if (arg2)
856169689Skan	{
857169689Skan	  t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type));
858169689Skan	  t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t);
859169689Skan	  t = build2 (MODIFY_EXPR, void_type_node, p2, t);
860169689Skan	  append_to_statement_list (t, &ret);
861169689Skan	}
862169689Skan
863169689Skan      t = build2 (NE_EXPR, boolean_type_node, p1, end1);
864169689Skan      t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
865169689Skan      append_to_statement_list (t, &ret);
866169689Skan
867169689Skan      return ret;
868169689Skan    }
869169689Skan  else
870169689Skan    {
871169689Skan      tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL);
872169689Skan      if (arg2)
873169689Skan	t = tree_cons (NULL, build_fold_addr_expr (arg2), t);
874169689Skan      /* Handle default arguments.  */
875169689Skan      i = 1 + (arg2 != NULL);
876169689Skan      for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
877169689Skan	t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
878169689Skan						  TREE_PURPOSE (parm),
879169689Skan						  fn, i++), t);
880169689Skan      return build_call (fn, nreverse (t));
881169689Skan    }
882169689Skan}
883169689Skan
884169689Skan/* Return code to initialize DECL with its default constructor, or
885169689Skan   NULL if there's nothing to do.  */
886169689Skan
887169689Skantree
888169689Skancxx_omp_clause_default_ctor (tree clause, tree decl)
889169689Skan{
890169689Skan  tree info = CP_OMP_CLAUSE_INFO (clause);
891169689Skan  tree ret = NULL;
892169689Skan
893169689Skan  if (info)
894169689Skan    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL);
895169689Skan
896169689Skan  return ret;
897169689Skan}
898169689Skan
899169689Skan/* Return code to initialize DST with a copy constructor from SRC.  */
900169689Skan
901169689Skantree
902169689Skancxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
903169689Skan{
904169689Skan  tree info = CP_OMP_CLAUSE_INFO (clause);
905169689Skan  tree ret = NULL;
906169689Skan
907169689Skan  if (info)
908169689Skan    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src);
909169689Skan  if (ret == NULL)
910169689Skan    ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
911169689Skan
912169689Skan  return ret;
913169689Skan}
914169689Skan
915169689Skan/* Similarly, except use an assignment operator instead.  */
916169689Skan
917169689Skantree
918169689Skancxx_omp_clause_assign_op (tree clause, tree dst, tree src)
919169689Skan{
920169689Skan  tree info = CP_OMP_CLAUSE_INFO (clause);
921169689Skan  tree ret = NULL;
922169689Skan
923169689Skan  if (info)
924169689Skan    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src);
925169689Skan  if (ret == NULL)
926169689Skan    ret = build2 (MODIFY_EXPR, void_type_node, dst, src);
927169689Skan
928169689Skan  return ret;
929169689Skan}
930169689Skan
931169689Skan/* Return code to destroy DECL.  */
932169689Skan
933169689Skantree
934169689Skancxx_omp_clause_dtor (tree clause, tree decl)
935169689Skan{
936169689Skan  tree info = CP_OMP_CLAUSE_INFO (clause);
937169689Skan  tree ret = NULL;
938169689Skan
939169689Skan  if (info)
940169689Skan    ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL);
941169689Skan
942169689Skan  return ret;
943169689Skan}
944169689Skan
945169689Skan/* True if OpenMP should privatize what this DECL points to rather
946169689Skan   than the DECL itself.  */
947169689Skan
948169689Skanbool
949169689Skancxx_omp_privatize_by_reference (tree decl)
950169689Skan{
951169689Skan  return is_invisiref_parm (decl);
952169689Skan}
953