OSDN Git Service

* cp-tree.def (UNARY_PLUS_EXPR): New C++ unary tree code.
[pf3gnuchains/gcc-fork.git] / gcc / cp / cp-gimplify.c
1 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
2
3    Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
4    Contributed by Jason Merrill <jason@redhat.com>
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING.  If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA.  */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "tree.h"
28 #include "cp-tree.h"
29 #include "c-common.h"
30 #include "toplev.h"
31 #include "tree-gimple.h"
32 #include "hashtab.h"
33 #include "pointer-set.h"
34 #include "flags.h"
35
36 /* Local declarations.  */
37
38 enum bc_t { bc_break = 0, bc_continue = 1 };
39
40 static struct cp_gimplify_ctx
41 {
42   /* Stack of labels which are targets for "break" or "continue",
43      linked through TREE_CHAIN.  */
44   tree current_label[2];
45 } *ctxp;
46
47 static void
48 push_context (void)
49 {
50   gcc_assert (!ctxp);
51   ctxp = ((struct cp_gimplify_ctx *)
52           xcalloc (1, sizeof (struct cp_gimplify_ctx)));
53 }
54
55 static void
56 pop_context (void)
57 {
58   gcc_assert (ctxp
59               && !ctxp->current_label[0]
60               && !ctxp->current_label[1]);
61   free (ctxp);
62   ctxp = NULL;
63 }
64
65 /* Begin a scope which can be exited by a break or continue statement.  BC
66    indicates which.
67
68    Just creates a label and pushes it into the current context.  */
69
70 static tree
71 begin_bc_block (enum bc_t bc)
72 {
73   tree label = create_artificial_label ();
74   TREE_CHAIN (label) = ctxp->current_label[bc];
75   ctxp->current_label[bc] = label;
76   return label;
77 }
78
79 /* Finish a scope which can be exited by a break or continue statement.
80    LABEL was returned from the most recent call to begin_bc_block.  BODY is
81    an expression for the contents of the scope.
82
83    If we saw a break (or continue) in the scope, append a LABEL_EXPR to
84    body.  Otherwise, just forget the label.  */
85
86 static tree
87 finish_bc_block (enum bc_t bc, tree label, tree body)
88 {
89   gcc_assert (label == ctxp->current_label[bc]);
90
91   if (TREE_USED (label))
92     {
93       tree t, sl = NULL;
94
95       t = build1 (LABEL_EXPR, void_type_node, label);
96
97       append_to_statement_list (body, &sl);
98       append_to_statement_list (t, &sl);
99       body = sl;
100     }
101
102   ctxp->current_label[bc] = TREE_CHAIN (label);
103   TREE_CHAIN (label) = NULL_TREE;
104   return body;
105 }
106
107 /* Build a GOTO_EXPR to represent a break or continue statement.  BC
108    indicates which.  */
109
110 static tree
111 build_bc_goto (enum bc_t bc)
112 {
113   tree label = ctxp->current_label[bc];
114
115   if (label == NULL_TREE)
116     {
117       if (bc == bc_break)
118         error ("break statement not within loop or switch");
119       else
120         error ("continue statement not within loop or switch");
121
122       return NULL_TREE;
123     }
124
125   /* Mark the label used for finish_bc_block.  */
126   TREE_USED (label) = 1;
127   return build1 (GOTO_EXPR, void_type_node, label);
128 }
129
130 /* Genericize a TRY_BLOCK.  */
131
132 static void
133 genericize_try_block (tree *stmt_p)
134 {
135   tree body = TRY_STMTS (*stmt_p);
136   tree cleanup = TRY_HANDLERS (*stmt_p);
137
138   gimplify_stmt (&body);
139
140   if (CLEANUP_P (*stmt_p))
141     /* A cleanup is an expression, so it doesn't need to be genericized.  */;
142   else
143     gimplify_stmt (&cleanup);
144
145   *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
146 }
147
148 /* Genericize a HANDLER by converting to a CATCH_EXPR.  */
149
150 static void
151 genericize_catch_block (tree *stmt_p)
152 {
153   tree type = HANDLER_TYPE (*stmt_p);
154   tree body = HANDLER_BODY (*stmt_p);
155
156   gimplify_stmt (&body);
157
158   /* FIXME should the caught type go in TREE_TYPE?  */
159   *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
160 }
161
162 /* Genericize an EH_SPEC_BLOCK by converting it to a
163    TRY_CATCH_EXPR/EH_FILTER_EXPR pair.  */
164
165 static void
166 genericize_eh_spec_block (tree *stmt_p)
167 {
168   tree body = EH_SPEC_STMTS (*stmt_p);
169   tree allowed = EH_SPEC_RAISES (*stmt_p);
170   tree failure = build_call (call_unexpected_node,
171                              tree_cons (NULL_TREE, build_exc_ptr (),
172                                         NULL_TREE));
173   gimplify_stmt (&body);
174
175   *stmt_p = gimple_build_eh_filter (body, allowed, failure);
176 }
177
178 /* Genericize an IF_STMT by turning it into a COND_EXPR.  */
179
180 static void
181 gimplify_if_stmt (tree *stmt_p)
182 {
183   tree stmt, cond, then_, else_;
184
185   stmt = *stmt_p;
186   cond = IF_COND (stmt);
187   then_ = THEN_CLAUSE (stmt);
188   else_ = ELSE_CLAUSE (stmt);
189
190   if (!then_)
191     then_ = build_empty_stmt ();
192   if (!else_)
193     else_ = build_empty_stmt ();
194
195   if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
196     stmt = then_;
197   else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
198     stmt = else_;
199   else
200     stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
201   *stmt_p = stmt;
202 }
203
204 /* Build a generic representation of one of the C loop forms.  COND is the
205    loop condition or NULL_TREE.  BODY is the (possibly compound) statement
206    controlled by the loop.  INCR is the increment expression of a for-loop,
207    or NULL_TREE.  COND_IS_FIRST indicates whether the condition is
208    evaluated before the loop body as in while and for loops, or after the
209    loop body as in do-while loops.  */
210
211 static tree
212 gimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first)
213 {
214   tree top, entry, exit, cont_block, break_block, stmt_list, t;
215   location_t stmt_locus;
216
217   stmt_locus = input_location;
218   stmt_list = NULL_TREE;
219   entry = NULL_TREE;
220
221   break_block = begin_bc_block (bc_break);
222   cont_block = begin_bc_block (bc_continue);
223
224   /* If condition is zero don't generate a loop construct.  */
225   if (cond && integer_zerop (cond))
226     {
227       top = NULL_TREE;
228       exit = NULL_TREE;
229       if (cond_is_first)
230         {
231           t = build_bc_goto (bc_break);
232           append_to_statement_list (t, &stmt_list);
233         }
234     }
235   else
236     {
237       /* If we use a LOOP_EXPR here, we have to feed the whole thing
238          back through the main gimplifier to lower it.  Given that we
239          have to gimplify the loop body NOW so that we can resolve
240          break/continue stmts, seems easier to just expand to gotos.  */
241       top = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
242
243       /* If we have an exit condition, then we build an IF with gotos either
244          out of the loop, or to the top of it.  If there's no exit condition,
245          then we just build a jump back to the top.  */
246       exit = build_and_jump (&LABEL_EXPR_LABEL (top));
247       if (cond && !integer_nonzerop (cond))
248         {
249           t = build_bc_goto (bc_break);
250           exit = build3 (COND_EXPR, void_type_node, cond, exit, t);
251           exit = fold (exit);
252           gimplify_stmt (&exit);
253
254           if (cond_is_first)
255             {
256               if (incr)
257                 {
258                   entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
259                   t = build_and_jump (&LABEL_EXPR_LABEL (entry));
260                 }
261               else
262                 t = build_bc_goto (bc_continue);
263               append_to_statement_list (t, &stmt_list);
264             }
265         }
266     }
267
268   gimplify_stmt (&body);
269   gimplify_stmt (&incr);
270
271   body = finish_bc_block (bc_continue, cont_block, body);
272
273   append_to_statement_list (top, &stmt_list);
274   append_to_statement_list (body, &stmt_list);
275   append_to_statement_list (incr, &stmt_list);
276   append_to_statement_list (entry, &stmt_list);
277   append_to_statement_list (exit, &stmt_list);
278
279   annotate_all_with_locus (&stmt_list, stmt_locus);
280
281   return finish_bc_block (bc_break, break_block, stmt_list);
282 }
283
284 /* Gimplify a FOR_STMT node.  Move the stuff in the for-init-stmt into the
285    prequeue and hand off to gimplify_cp_loop.  */
286
287 static void
288 gimplify_for_stmt (tree *stmt_p, tree *pre_p)
289 {
290   tree stmt = *stmt_p;
291
292   if (FOR_INIT_STMT (stmt))
293     gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
294
295   *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
296                               FOR_EXPR (stmt), 1);
297 }
298
299 /* Gimplify a WHILE_STMT node.  */
300
301 static void
302 gimplify_while_stmt (tree *stmt_p)
303 {
304   tree stmt = *stmt_p;
305   *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
306                               NULL_TREE, 1);
307 }
308
309 /* Gimplify a DO_STMT node.  */
310
311 static void
312 gimplify_do_stmt (tree *stmt_p)
313 {
314   tree stmt = *stmt_p;
315   *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
316                               NULL_TREE, 0);
317 }
318
319 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
320
321 static void
322 gimplify_switch_stmt (tree *stmt_p)
323 {
324   tree stmt = *stmt_p;
325   tree break_block, body;
326   location_t stmt_locus = input_location;
327
328   break_block = begin_bc_block (bc_break);
329
330   body = SWITCH_STMT_BODY (stmt);
331   if (!body)
332     body = build_empty_stmt ();
333
334   *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
335                     SWITCH_STMT_COND (stmt), body, NULL_TREE);
336   SET_EXPR_LOCATION (*stmt_p, stmt_locus);
337   gimplify_stmt (stmt_p);
338
339   *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p);
340 }
341
342 /*  Gimplify an EXPR_STMT node.  */
343
344 static void
345 gimplify_expr_stmt (tree *stmt_p)
346 {
347   tree stmt = EXPR_STMT_EXPR (*stmt_p);
348
349   if (stmt == error_mark_node)
350     stmt = NULL;
351
352   /* Gimplification of a statement expression will nullify the
353      statement if all its side effects are moved to *PRE_P and *POST_P.
354
355      In this case we will not want to emit the gimplified statement.
356      However, we may still want to emit a warning, so we do that before
357      gimplification.  */
358   if (stmt && (extra_warnings || warn_unused_value))
359     {
360       if (!TREE_SIDE_EFFECTS (stmt))
361         {
362           if (!IS_EMPTY_STMT (stmt)
363               && !VOID_TYPE_P (TREE_TYPE (stmt))
364               && !TREE_NO_WARNING (stmt))
365             warning (0, "statement with no effect");
366         }
367       else if (warn_unused_value)
368         warn_if_unused_value (stmt, input_location);
369     }
370
371   if (stmt == NULL_TREE)
372     stmt = alloc_stmt_list ();
373
374   *stmt_p = stmt;
375 }
376
377 /* Gimplify initialization from an AGGR_INIT_EXPR.  */
378
379 static void
380 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
381 {
382   tree from = TREE_OPERAND (*expr_p, 1);
383   tree to = TREE_OPERAND (*expr_p, 0);
384   tree sub;
385
386   /* If we are initializing something from a TARGET_EXPR, strip the
387      TARGET_EXPR and initialize it directly.  */
388   /* What about code that pulls out the temp and uses it elsewhere?  I
389      think that such code never uses the TARGET_EXPR as an initializer.  If
390      I'm wrong, we'll abort because the temp won't have any RTL.  In that
391      case, I guess we'll need to replace references somehow.  */
392   if (TREE_CODE (from) == TARGET_EXPR)
393     from = TARGET_EXPR_INITIAL (from);
394   if (TREE_CODE (from) == CLEANUP_POINT_EXPR)
395     from = TREE_OPERAND (from, 0);
396
397   /* Look through any COMPOUND_EXPRs.  */
398   sub = expr_last (from);
399
400   /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
401      replace the slot operand with our target.
402
403      Should we add a target parm to gimplify_expr instead?  No, as in this
404      case we want to replace the INIT_EXPR.  */
405   if (TREE_CODE (sub) == AGGR_INIT_EXPR)
406     {
407       gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
408       TREE_OPERAND (sub, 2) = to;
409       *expr_p = from;
410
411       /* The initialization is now a side-effect, so the container can
412          become void.  */
413       if (from != sub)
414         TREE_TYPE (from) = void_type_node;
415     }
416 }
417
418 /* Gimplify a MUST_NOT_THROW_EXPR.  */
419
420 static void
421 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
422 {
423   tree stmt = *expr_p;
424   tree temp = voidify_wrapper_expr (stmt, NULL);
425   tree body = TREE_OPERAND (stmt, 0);
426
427   gimplify_stmt (&body);
428
429   stmt = gimple_build_eh_filter (body, NULL_TREE,
430                                  build_call (terminate_node, NULL_TREE));
431
432   if (temp)
433     {
434       append_to_statement_list (stmt, pre_p);
435       *expr_p = temp;
436     }
437   else
438     *expr_p = stmt;
439 }
440
441 /* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
442
443 int
444 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
445 {
446   int saved_stmts_are_full_exprs_p = 0;
447   enum tree_code code = TREE_CODE (*expr_p);
448   enum gimplify_status ret;
449
450   if (STATEMENT_CODE_P (code))
451     {
452       saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
453       current_stmt_tree ()->stmts_are_full_exprs_p
454         = STMT_IS_FULL_EXPR_P (*expr_p);
455     }
456
457   switch (code)
458     {
459     case PTRMEM_CST:
460       *expr_p = cplus_expand_constant (*expr_p);
461       ret = GS_OK;
462       break;
463
464     case AGGR_INIT_EXPR:
465       simplify_aggr_init_expr (expr_p);
466       ret = GS_OK;
467       break;
468
469     case THROW_EXPR:
470       /* FIXME communicate throw type to backend, probably by moving
471          THROW_EXPR into ../tree.def.  */
472       *expr_p = TREE_OPERAND (*expr_p, 0);
473       ret = GS_OK;
474       break;
475
476     case MUST_NOT_THROW_EXPR:
477       gimplify_must_not_throw_expr (expr_p, pre_p);
478       ret = GS_OK;
479       break;
480
481     case INIT_EXPR:
482     case MODIFY_EXPR:
483       cp_gimplify_init_expr (expr_p, pre_p, post_p);
484       ret = GS_OK;
485       break;
486
487     case EMPTY_CLASS_EXPR:
488       /* We create an INTEGER_CST with RECORD_TYPE and value zero.  */
489       *expr_p = build_int_cst (TREE_TYPE (*expr_p), 0);
490       ret = GS_OK;
491       break;
492
493     case BASELINK:
494       *expr_p = BASELINK_FUNCTIONS (*expr_p);
495       ret = GS_OK;
496       break;
497
498     case TRY_BLOCK:
499       genericize_try_block (expr_p);
500       ret = GS_OK;
501       break;
502
503     case HANDLER:
504       genericize_catch_block (expr_p);
505       ret = GS_OK;
506       break;
507
508     case EH_SPEC_BLOCK:
509       genericize_eh_spec_block (expr_p);
510       ret = GS_OK;
511       break;
512
513     case USING_STMT:
514       /* Just ignore for now.  Eventually we will want to pass this on to
515          the debugger.  */
516       *expr_p = build_empty_stmt ();
517       ret = GS_ALL_DONE;
518       break;
519
520     case IF_STMT:
521       gimplify_if_stmt (expr_p);
522       ret = GS_OK;
523       break;
524
525     case FOR_STMT:
526       gimplify_for_stmt (expr_p, pre_p);
527       ret = GS_ALL_DONE;
528       break;
529
530     case WHILE_STMT:
531       gimplify_while_stmt (expr_p);
532       ret = GS_ALL_DONE;
533       break;
534
535     case DO_STMT:
536       gimplify_do_stmt (expr_p);
537       ret = GS_ALL_DONE;
538       break;
539
540     case SWITCH_STMT:
541       gimplify_switch_stmt (expr_p);
542       ret = GS_ALL_DONE;
543       break;
544
545     case CONTINUE_STMT:
546       *expr_p = build_bc_goto (bc_continue);
547       ret = GS_ALL_DONE;
548       break;
549
550     case BREAK_STMT:
551       *expr_p = build_bc_goto (bc_break);
552       ret = GS_ALL_DONE;
553       break;
554
555     case EXPR_STMT:
556       gimplify_expr_stmt (expr_p);
557       ret = GS_OK;
558       break;
559
560     case UNARY_PLUS_EXPR:
561       {
562         tree arg = TREE_OPERAND (*expr_p, 0);
563         tree type = TREE_TYPE (*expr_p);
564         *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
565                                             : arg;
566         ret = GS_OK;
567       }
568       break;
569
570     default:
571       ret = c_gimplify_expr (expr_p, pre_p, post_p);
572       break;
573     }
574
575   /* Restore saved state.  */
576   if (STATEMENT_CODE_P (code))
577     current_stmt_tree ()->stmts_are_full_exprs_p
578       = saved_stmts_are_full_exprs_p;
579
580   return ret;
581 }
582
583 static inline bool
584 is_invisiref_parm (tree t)
585 {
586   return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
587           && DECL_BY_REFERENCE (t));
588 }
589
590 /* Perform any pre-gimplification lowering of C++ front end trees to
591    GENERIC.  */
592
593 static tree
594 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
595 {
596   tree stmt = *stmt_p;
597   struct pointer_set_t *p_set = (struct pointer_set_t*) data;
598
599   if (is_invisiref_parm (stmt))
600     {
601       *stmt_p = convert_from_reference (stmt);
602       *walk_subtrees = 0;
603       return NULL;
604     }
605
606   /* Other than invisiref parms, don't walk the same tree twice.  */
607   if (pointer_set_contains (p_set, stmt))
608     {
609       *walk_subtrees = 0;
610       return NULL_TREE;
611     }
612
613   if (TREE_CODE (stmt) == ADDR_EXPR
614       && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
615     {
616       *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
617       *walk_subtrees = 0;
618     }
619   else if (TREE_CODE (stmt) == RETURN_EXPR
620            && TREE_OPERAND (stmt, 0)
621            && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
622     /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
623     *walk_subtrees = 0;
624   else if (IS_TYPE_OR_DECL_P (stmt))
625     *walk_subtrees = 0;
626
627   /* Due to the way voidify_wrapper_expr is written, we don't get a chance
628      to lower this construct before scanning it, so we need to lower these
629      before doing anything else.  */
630   else if (TREE_CODE (stmt) == CLEANUP_STMT)
631     *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
632                                              : TRY_FINALLY_EXPR,
633                       void_type_node,
634                       CLEANUP_BODY (stmt),
635                       CLEANUP_EXPR (stmt));
636
637   pointer_set_insert (p_set, *stmt_p);
638   
639   return NULL;
640 }
641
642 void
643 cp_genericize (tree fndecl)
644 {
645   tree t;
646   struct pointer_set_t *p_set;
647
648   /* Fix up the types of parms passed by invisible reference.  */
649   for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
650     if (TREE_ADDRESSABLE (TREE_TYPE (t)))
651       {
652         /* If a function's arguments are copied to create a thunk,
653            then DECL_BY_REFERENCE will be set -- but the type of the
654            argument will be a pointer type, so we will never get
655            here.  */
656         gcc_assert (!DECL_BY_REFERENCE (t));
657         gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
658         TREE_TYPE (t) = DECL_ARG_TYPE (t);
659         DECL_BY_REFERENCE (t) = 1;
660         TREE_ADDRESSABLE (t) = 0;
661         relayout_decl (t);
662       }
663
664   /* Do the same for the return value.  */
665   if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
666     {
667       t = DECL_RESULT (fndecl);
668       TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
669       DECL_BY_REFERENCE (t) = 1;
670       TREE_ADDRESSABLE (t) = 0;
671       relayout_decl (t);
672     }
673
674   /* If we're a clone, the body is already GIMPLE.  */
675   if (DECL_CLONED_FUNCTION_P (fndecl))
676     return;
677
678   /* We do want to see every occurrence of the parms, so we can't just use
679      walk_tree's hash functionality.  */
680   p_set = pointer_set_create ();
681   walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
682   pointer_set_destroy (p_set);
683
684   /* Do everything else.  */
685   push_context ();
686   c_genericize (fndecl);
687   pop_context ();
688 }