OSDN Git Service

* typeck.c (string_conv_p): Pass appropiate
[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, 51 Franklin Street, Fifth Floor, Boston, MA
21 02110-1301, 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 = fold_build3 (COND_EXPR, void_type_node, cond, exit, t);
251           gimplify_stmt (&exit);
252
253           if (cond_is_first)
254             {
255               if (incr)
256                 {
257                   entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
258                   t = build_and_jump (&LABEL_EXPR_LABEL (entry));
259                 }
260               else
261                 t = build_bc_goto (bc_continue);
262               append_to_statement_list (t, &stmt_list);
263             }
264         }
265     }
266
267   gimplify_stmt (&body);
268   gimplify_stmt (&incr);
269
270   body = finish_bc_block (bc_continue, cont_block, body);
271
272   append_to_statement_list (top, &stmt_list);
273   append_to_statement_list (body, &stmt_list);
274   append_to_statement_list (incr, &stmt_list);
275   append_to_statement_list (entry, &stmt_list);
276   append_to_statement_list (exit, &stmt_list);
277
278   annotate_all_with_locus (&stmt_list, stmt_locus);
279
280   return finish_bc_block (bc_break, break_block, stmt_list);
281 }
282
283 /* Gimplify a FOR_STMT node.  Move the stuff in the for-init-stmt into the
284    prequeue and hand off to gimplify_cp_loop.  */
285
286 static void
287 gimplify_for_stmt (tree *stmt_p, tree *pre_p)
288 {
289   tree stmt = *stmt_p;
290
291   if (FOR_INIT_STMT (stmt))
292     gimplify_and_add (FOR_INIT_STMT (stmt), pre_p);
293
294   *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt),
295                               FOR_EXPR (stmt), 1);
296 }
297
298 /* Gimplify a WHILE_STMT node.  */
299
300 static void
301 gimplify_while_stmt (tree *stmt_p)
302 {
303   tree stmt = *stmt_p;
304   *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt),
305                               NULL_TREE, 1);
306 }
307
308 /* Gimplify a DO_STMT node.  */
309
310 static void
311 gimplify_do_stmt (tree *stmt_p)
312 {
313   tree stmt = *stmt_p;
314   *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt),
315                               NULL_TREE, 0);
316 }
317
318 /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR.  */
319
320 static void
321 gimplify_switch_stmt (tree *stmt_p)
322 {
323   tree stmt = *stmt_p;
324   tree break_block, body;
325   location_t stmt_locus = input_location;
326
327   break_block = begin_bc_block (bc_break);
328
329   body = SWITCH_STMT_BODY (stmt);
330   if (!body)
331     body = build_empty_stmt ();
332
333   *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt),
334                     SWITCH_STMT_COND (stmt), body, NULL_TREE);
335   SET_EXPR_LOCATION (*stmt_p, stmt_locus);
336   gimplify_stmt (stmt_p);
337
338   *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p);
339 }
340
341 /*  Gimplify an EXPR_STMT node.  */
342
343 static void
344 gimplify_expr_stmt (tree *stmt_p)
345 {
346   tree stmt = EXPR_STMT_EXPR (*stmt_p);
347
348   if (stmt == error_mark_node)
349     stmt = NULL;
350
351   /* Gimplification of a statement expression will nullify the
352      statement if all its side effects are moved to *PRE_P and *POST_P.
353
354      In this case we will not want to emit the gimplified statement.
355      However, we may still want to emit a warning, so we do that before
356      gimplification.  */
357   if (stmt && (extra_warnings || warn_unused_value))
358     {
359       if (!TREE_SIDE_EFFECTS (stmt))
360         {
361           if (!IS_EMPTY_STMT (stmt)
362               && !VOID_TYPE_P (TREE_TYPE (stmt))
363               && !TREE_NO_WARNING (stmt))
364             warning (OPT_Wextra, "statement with no effect");
365         }
366       else if (warn_unused_value)
367         warn_if_unused_value (stmt, input_location);
368     }
369
370   if (stmt == NULL_TREE)
371     stmt = alloc_stmt_list ();
372
373   *stmt_p = stmt;
374 }
375
376 /* Gimplify initialization from an AGGR_INIT_EXPR.  */
377
378 static void
379 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
380 {
381   tree from = TREE_OPERAND (*expr_p, 1);
382   tree to = TREE_OPERAND (*expr_p, 0);
383   tree sub;
384
385   /* If we are initializing something from a TARGET_EXPR, strip the
386      TARGET_EXPR and initialize it directly.  */
387   /* What about code that pulls out the temp and uses it elsewhere?  I
388      think that such code never uses the TARGET_EXPR as an initializer.  If
389      I'm wrong, we'll abort because the temp won't have any RTL.  In that
390      case, I guess we'll need to replace references somehow.  */
391   if (TREE_CODE (from) == TARGET_EXPR)
392     from = TARGET_EXPR_INITIAL (from);
393   if (TREE_CODE (from) == CLEANUP_POINT_EXPR)
394     from = TREE_OPERAND (from, 0);
395
396   /* Look through any COMPOUND_EXPRs.  */
397   sub = expr_last (from);
398
399   /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
400      replace the slot operand with our target.
401
402      Should we add a target parm to gimplify_expr instead?  No, as in this
403      case we want to replace the INIT_EXPR.  */
404   if (TREE_CODE (sub) == AGGR_INIT_EXPR)
405     {
406       gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
407       TREE_OPERAND (sub, 2) = to;
408       *expr_p = from;
409
410       /* The initialization is now a side-effect, so the container can
411          become void.  */
412       if (from != sub)
413         TREE_TYPE (from) = void_type_node;
414     }
415 }
416
417 /* Gimplify a MUST_NOT_THROW_EXPR.  */
418
419 static void
420 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
421 {
422   tree stmt = *expr_p;
423   tree temp = voidify_wrapper_expr (stmt, NULL);
424   tree body = TREE_OPERAND (stmt, 0);
425
426   gimplify_stmt (&body);
427
428   stmt = gimple_build_eh_filter (body, NULL_TREE,
429                                  build_call (terminate_node, NULL_TREE));
430
431   if (temp)
432     {
433       append_to_statement_list (stmt, pre_p);
434       *expr_p = temp;
435     }
436   else
437     *expr_p = stmt;
438 }
439
440 /* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
441
442 int
443 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
444 {
445   int saved_stmts_are_full_exprs_p = 0;
446   enum tree_code code = TREE_CODE (*expr_p);
447   enum gimplify_status ret;
448
449   if (STATEMENT_CODE_P (code))
450     {
451       saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
452       current_stmt_tree ()->stmts_are_full_exprs_p
453         = STMT_IS_FULL_EXPR_P (*expr_p);
454     }
455
456   switch (code)
457     {
458     case PTRMEM_CST:
459       *expr_p = cplus_expand_constant (*expr_p);
460       ret = GS_OK;
461       break;
462
463     case AGGR_INIT_EXPR:
464       simplify_aggr_init_expr (expr_p);
465       ret = GS_OK;
466       break;
467
468     case THROW_EXPR:
469       /* FIXME communicate throw type to backend, probably by moving
470          THROW_EXPR into ../tree.def.  */
471       *expr_p = TREE_OPERAND (*expr_p, 0);
472       ret = GS_OK;
473       break;
474
475     case MUST_NOT_THROW_EXPR:
476       gimplify_must_not_throw_expr (expr_p, pre_p);
477       ret = GS_OK;
478       break;
479
480     case INIT_EXPR:
481     case MODIFY_EXPR:
482       cp_gimplify_init_expr (expr_p, pre_p, post_p);
483       ret = GS_OK;
484       break;
485
486     case EMPTY_CLASS_EXPR:
487       /* We create an empty CONSTRUCTOR with RECORD_TYPE.  */
488       *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
489       ret = GS_OK;
490       break;
491
492     case BASELINK:
493       *expr_p = BASELINK_FUNCTIONS (*expr_p);
494       ret = GS_OK;
495       break;
496
497     case TRY_BLOCK:
498       genericize_try_block (expr_p);
499       ret = GS_OK;
500       break;
501
502     case HANDLER:
503       genericize_catch_block (expr_p);
504       ret = GS_OK;
505       break;
506
507     case EH_SPEC_BLOCK:
508       genericize_eh_spec_block (expr_p);
509       ret = GS_OK;
510       break;
511
512     case USING_STMT:
513       /* Just ignore for now.  Eventually we will want to pass this on to
514          the debugger.  */
515       *expr_p = build_empty_stmt ();
516       ret = GS_ALL_DONE;
517       break;
518
519     case IF_STMT:
520       gimplify_if_stmt (expr_p);
521       ret = GS_OK;
522       break;
523
524     case FOR_STMT:
525       gimplify_for_stmt (expr_p, pre_p);
526       ret = GS_ALL_DONE;
527       break;
528
529     case WHILE_STMT:
530       gimplify_while_stmt (expr_p);
531       ret = GS_ALL_DONE;
532       break;
533
534     case DO_STMT:
535       gimplify_do_stmt (expr_p);
536       ret = GS_ALL_DONE;
537       break;
538
539     case SWITCH_STMT:
540       gimplify_switch_stmt (expr_p);
541       ret = GS_ALL_DONE;
542       break;
543
544     case CONTINUE_STMT:
545       *expr_p = build_bc_goto (bc_continue);
546       ret = GS_ALL_DONE;
547       break;
548
549     case BREAK_STMT:
550       *expr_p = build_bc_goto (bc_break);
551       ret = GS_ALL_DONE;
552       break;
553
554     case EXPR_STMT:
555       gimplify_expr_stmt (expr_p);
556       ret = GS_OK;
557       break;
558
559     case UNARY_PLUS_EXPR:
560       {
561         tree arg = TREE_OPERAND (*expr_p, 0);
562         tree type = TREE_TYPE (*expr_p);
563         *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
564                                             : arg;
565         ret = GS_OK;
566       }
567       break;
568
569     default:
570       ret = c_gimplify_expr (expr_p, pre_p, post_p);
571       break;
572     }
573
574   /* Restore saved state.  */
575   if (STATEMENT_CODE_P (code))
576     current_stmt_tree ()->stmts_are_full_exprs_p
577       = saved_stmts_are_full_exprs_p;
578
579   return ret;
580 }
581
582 static inline bool
583 is_invisiref_parm (tree t)
584 {
585   return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
586           && DECL_BY_REFERENCE (t));
587 }
588
589 /* Perform any pre-gimplification lowering of C++ front end trees to
590    GENERIC.  */
591
592 static tree
593 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
594 {
595   tree stmt = *stmt_p;
596   struct pointer_set_t *p_set = (struct pointer_set_t*) data;
597
598   if (is_invisiref_parm (stmt)
599       /* Don't dereference parms in a thunk, pass the references through. */
600       && !(DECL_THUNK_P (current_function_decl)
601            && TREE_CODE (stmt) == PARM_DECL))
602     {
603       *stmt_p = convert_from_reference (stmt);
604       *walk_subtrees = 0;
605       return NULL;
606     }
607
608   /* Other than invisiref parms, don't walk the same tree twice.  */
609   if (pointer_set_contains (p_set, stmt))
610     {
611       *walk_subtrees = 0;
612       return NULL_TREE;
613     }
614
615   if (TREE_CODE (stmt) == ADDR_EXPR
616       && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
617     {
618       *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
619       *walk_subtrees = 0;
620     }
621   else if (TREE_CODE (stmt) == RETURN_EXPR
622            && TREE_OPERAND (stmt, 0)
623            && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
624     /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR.  */
625     *walk_subtrees = 0;
626   else if (IS_TYPE_OR_DECL_P (stmt))
627     *walk_subtrees = 0;
628
629   /* Due to the way voidify_wrapper_expr is written, we don't get a chance
630      to lower this construct before scanning it, so we need to lower these
631      before doing anything else.  */
632   else if (TREE_CODE (stmt) == CLEANUP_STMT)
633     *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
634                                              : TRY_FINALLY_EXPR,
635                       void_type_node,
636                       CLEANUP_BODY (stmt),
637                       CLEANUP_EXPR (stmt));
638
639   pointer_set_insert (p_set, *stmt_p);
640
641   return NULL;
642 }
643
644 void
645 cp_genericize (tree fndecl)
646 {
647   tree t;
648   struct pointer_set_t *p_set;
649
650   /* Fix up the types of parms passed by invisible reference.  */
651   for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
652     if (TREE_ADDRESSABLE (TREE_TYPE (t)))
653       {
654         /* If a function's arguments are copied to create a thunk,
655            then DECL_BY_REFERENCE will be set -- but the type of the
656            argument will be a pointer type, so we will never get
657            here.  */
658         gcc_assert (!DECL_BY_REFERENCE (t));
659         gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
660         TREE_TYPE (t) = DECL_ARG_TYPE (t);
661         DECL_BY_REFERENCE (t) = 1;
662         TREE_ADDRESSABLE (t) = 0;
663         relayout_decl (t);
664       }
665
666   /* Do the same for the return value.  */
667   if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
668     {
669       t = DECL_RESULT (fndecl);
670       TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
671       DECL_BY_REFERENCE (t) = 1;
672       TREE_ADDRESSABLE (t) = 0;
673       relayout_decl (t);
674     }
675
676   /* If we're a clone, the body is already GIMPLE.  */
677   if (DECL_CLONED_FUNCTION_P (fndecl))
678     return;
679
680   /* We do want to see every occurrence of the parms, so we can't just use
681      walk_tree's hash functionality.  */
682   p_set = pointer_set_create ();
683   walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
684   pointer_set_destroy (p_set);
685
686   /* Do everything else.  */
687   push_context ();
688   c_genericize (fndecl);
689   pop_context ();
690 }