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