OSDN Git Service

* c-common.c, c-common.h (lang_gimplify_stmt): Remove.
[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 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
33
34 /* Genericize a TRY_BLOCK.  */
35
36 static void
37 genericize_try_block (tree *stmt_p)
38 {
39   tree body = TRY_STMTS (*stmt_p);
40   tree cleanup = TRY_HANDLERS (*stmt_p);
41
42   gimplify_stmt (&body);
43
44   if (CLEANUP_P (*stmt_p))
45     /* A cleanup is an expression, so it doesn't need to be genericized.  */;
46   else
47     gimplify_stmt (&cleanup);
48
49   *stmt_p = build (TRY_CATCH_EXPR, void_type_node, body, cleanup);
50 }
51
52 /* Genericize a HANDLER by converting to a CATCH_EXPR.  */
53
54 static void
55 genericize_catch_block (tree *stmt_p)
56 {
57   tree type = HANDLER_TYPE (*stmt_p);
58   tree body = HANDLER_BODY (*stmt_p);
59
60   gimplify_stmt (&body);
61
62   /* FIXME should the caught type go in TREE_TYPE?  */
63   *stmt_p = build (CATCH_EXPR, void_type_node, type, body);
64 }
65
66 /* Genericize an EH_SPEC_BLOCK by converting it to a
67    TRY_CATCH_EXPR/EH_FILTER_EXPR pair.  */
68
69 static void
70 genericize_eh_spec_block (tree *stmt_p)
71 {
72   tree body = EH_SPEC_STMTS (*stmt_p);
73   tree allowed = EH_SPEC_RAISES (*stmt_p);
74   tree failure = build_call (call_unexpected_node,
75                              tree_cons (NULL_TREE, build_exc_ptr (),
76                                         NULL_TREE));
77   gimplify_stmt (&body);
78
79   *stmt_p = gimple_build_eh_filter (body, allowed, failure);
80 }
81
82 /* Gimplify initialization from an AGGR_INIT_EXPR.  */
83
84 static void
85 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
86 {
87   tree from = TREE_OPERAND (*expr_p, 1);
88   tree to = TREE_OPERAND (*expr_p, 0);
89   tree sub;
90
91   /* If we are initializing something from a TARGET_EXPR, strip the
92      TARGET_EXPR and initialize it directly.  */
93   /* What about code that pulls out the temp and uses it elsewhere?  I
94      think that such code never uses the TARGET_EXPR as an initializer.  If
95      I'm wrong, we'll abort because the temp won't have any RTL.  In that
96      case, I guess we'll need to replace references somehow.  */
97   if (TREE_CODE (from) == TARGET_EXPR)
98     from = TARGET_EXPR_INITIAL (from);
99
100   /* Look through any COMPOUND_EXPRs.  */
101   sub = expr_last (from);
102
103   /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
104      replace the slot operand with our target.
105
106      Should we add a target parm to gimplify_expr instead?  No, as in this
107      case we want to replace the INIT_EXPR.  */
108   if (TREE_CODE (sub) == AGGR_INIT_EXPR)
109     {
110       gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
111       TREE_OPERAND (sub, 2) = to;
112       *expr_p = from;
113
114       /* The initialization is now a side-effect, so the container can
115          become void.  */
116       if (from != sub)
117         TREE_TYPE (from) = void_type_node;
118     }
119 }
120
121 /* Gimplify a MUST_NOT_THROW_EXPR.  */
122
123 static void
124 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
125 {
126   tree stmt = *expr_p;
127   tree temp = voidify_wrapper_expr (stmt, NULL);
128   tree body = TREE_OPERAND (stmt, 0);
129
130   gimplify_stmt (&body);
131
132   stmt = gimple_build_eh_filter (body, NULL_TREE,
133                                  build_call (terminate_node, NULL_TREE));
134
135   if (temp)
136     {
137       append_to_statement_list (stmt, pre_p);
138       *expr_p = temp;
139     }
140   else
141     *expr_p = stmt;
142 }
143
144 /* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
145
146 int
147 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
148 {
149   int saved_stmts_are_full_exprs_p = 0;
150   enum tree_code code = TREE_CODE (*expr_p);
151   enum gimplify_status ret;
152
153   if (STATEMENT_CODE_P (code))
154     {
155       saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
156       current_stmt_tree ()->stmts_are_full_exprs_p
157         = STMT_IS_FULL_EXPR_P (*expr_p);
158     }
159
160   switch (code)
161     {
162     case PTRMEM_CST:
163       *expr_p = cplus_expand_constant (*expr_p);
164       ret = GS_OK;
165       break;
166
167     case AGGR_INIT_EXPR:
168       simplify_aggr_init_expr (expr_p);
169       ret = GS_OK;
170       break;
171
172     case THROW_EXPR:
173       /* FIXME communicate throw type to backend, probably by moving
174          THROW_EXPR into ../tree.def.  */
175       *expr_p = TREE_OPERAND (*expr_p, 0);
176       ret = GS_OK;
177       break;
178
179     case MUST_NOT_THROW_EXPR:
180       gimplify_must_not_throw_expr (expr_p, pre_p);
181       ret = GS_OK;
182       break;
183
184     case INIT_EXPR:
185     case MODIFY_EXPR:
186       cp_gimplify_init_expr (expr_p, pre_p, post_p);
187       ret = GS_OK;
188       break;
189
190     case EMPTY_CLASS_EXPR:
191       {
192         /* Yes, an INTEGER_CST with RECORD_TYPE.  */
193         tree i = build_int_2 (0, 0);
194         TREE_TYPE (i) = TREE_TYPE (*expr_p);
195         *expr_p = i;
196       }
197       ret = GS_OK;
198       break;
199
200     case BASELINK:
201       *expr_p = BASELINK_FUNCTIONS (*expr_p);
202       ret = GS_OK;
203       break;
204
205     case TRY_BLOCK:
206       genericize_try_block (expr_p);
207       ret = GS_OK;
208       break;
209
210     case HANDLER:
211       genericize_catch_block (expr_p);
212       ret = GS_OK;
213       break;
214
215     case EH_SPEC_BLOCK:
216       genericize_eh_spec_block (expr_p);
217       ret = GS_OK;
218       break;
219
220     case USING_STMT:
221       /* Just ignore for now.  Eventually we will want to pass this on to
222          the debugger.  */
223       *expr_p = build_empty_stmt ();
224       ret = GS_ALL_DONE;
225       break;
226
227     default:
228       ret = c_gimplify_expr (expr_p, pre_p, post_p);
229       break;
230     }
231
232   /* Restore saved state.  */
233   if (STATEMENT_CODE_P (code))
234     current_stmt_tree ()->stmts_are_full_exprs_p
235       = saved_stmts_are_full_exprs_p;
236
237   return ret;
238 }