* trans-stmt.c (gfc_trans_simple_do): New function.
[official-gcc.git] / gcc / cp / cp-gimplify.c
blobd6a2f18ff05364ab864afe37a590f63ed147532c
1 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
3 Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
4 Contributed by Jason Merrill <jason@redhat.com>
6 This file is part of GCC.
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.
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.
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. */
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"
34 /* Genericize a TRY_BLOCK. */
36 static void
37 genericize_try_block (tree *stmt_p)
39 tree body = TRY_STMTS (*stmt_p);
40 tree cleanup = TRY_HANDLERS (*stmt_p);
42 gimplify_stmt (&body);
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);
49 *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
52 /* Genericize a HANDLER by converting to a CATCH_EXPR. */
54 static void
55 genericize_catch_block (tree *stmt_p)
57 tree type = HANDLER_TYPE (*stmt_p);
58 tree body = HANDLER_BODY (*stmt_p);
60 gimplify_stmt (&body);
62 /* FIXME should the caught type go in TREE_TYPE? */
63 *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
66 /* Genericize an EH_SPEC_BLOCK by converting it to a
67 TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
69 static void
70 genericize_eh_spec_block (tree *stmt_p)
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);
79 *stmt_p = gimple_build_eh_filter (body, allowed, failure);
82 /* Genericize an IF_STMT by turning it into a COND_EXPR. */
84 static void
85 gimplify_if_stmt (tree *stmt_p)
87 tree stmt, then_, else_;
89 stmt = *stmt_p;
90 then_ = THEN_CLAUSE (stmt);
91 else_ = ELSE_CLAUSE (stmt);
93 if (!then_)
94 then_ = build_empty_stmt ();
95 if (!else_)
96 else_ = build_empty_stmt ();
98 stmt = build3 (COND_EXPR, void_type_node, IF_COND (stmt), then_, else_);
99 *stmt_p = stmt;
102 /* Gimplify initialization from an AGGR_INIT_EXPR. */
104 static void
105 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
107 tree from = TREE_OPERAND (*expr_p, 1);
108 tree to = TREE_OPERAND (*expr_p, 0);
109 tree sub;
111 /* If we are initializing something from a TARGET_EXPR, strip the
112 TARGET_EXPR and initialize it directly. */
113 /* What about code that pulls out the temp and uses it elsewhere? I
114 think that such code never uses the TARGET_EXPR as an initializer. If
115 I'm wrong, we'll abort because the temp won't have any RTL. In that
116 case, I guess we'll need to replace references somehow. */
117 if (TREE_CODE (from) == TARGET_EXPR)
118 from = TARGET_EXPR_INITIAL (from);
119 if (TREE_CODE (from) == CLEANUP_POINT_EXPR)
120 from = TREE_OPERAND (from, 0);
122 /* Look through any COMPOUND_EXPRs. */
123 sub = expr_last (from);
125 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
126 replace the slot operand with our target.
128 Should we add a target parm to gimplify_expr instead? No, as in this
129 case we want to replace the INIT_EXPR. */
130 if (TREE_CODE (sub) == AGGR_INIT_EXPR)
132 gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
133 TREE_OPERAND (sub, 2) = to;
134 *expr_p = from;
136 /* The initialization is now a side-effect, so the container can
137 become void. */
138 if (from != sub)
139 TREE_TYPE (from) = void_type_node;
143 /* Gimplify a MUST_NOT_THROW_EXPR. */
145 static void
146 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
148 tree stmt = *expr_p;
149 tree temp = voidify_wrapper_expr (stmt, NULL);
150 tree body = TREE_OPERAND (stmt, 0);
152 gimplify_stmt (&body);
154 stmt = gimple_build_eh_filter (body, NULL_TREE,
155 build_call (terminate_node, NULL_TREE));
157 if (temp)
159 append_to_statement_list (stmt, pre_p);
160 *expr_p = temp;
162 else
163 *expr_p = stmt;
166 /* Do C++-specific gimplification. Args are as for gimplify_expr. */
169 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
171 int saved_stmts_are_full_exprs_p = 0;
172 enum tree_code code = TREE_CODE (*expr_p);
173 enum gimplify_status ret;
175 if (STATEMENT_CODE_P (code))
177 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
178 current_stmt_tree ()->stmts_are_full_exprs_p
179 = STMT_IS_FULL_EXPR_P (*expr_p);
182 switch (code)
184 case PTRMEM_CST:
185 *expr_p = cplus_expand_constant (*expr_p);
186 ret = GS_OK;
187 break;
189 case AGGR_INIT_EXPR:
190 simplify_aggr_init_expr (expr_p);
191 ret = GS_OK;
192 break;
194 case THROW_EXPR:
195 /* FIXME communicate throw type to backend, probably by moving
196 THROW_EXPR into ../tree.def. */
197 *expr_p = TREE_OPERAND (*expr_p, 0);
198 ret = GS_OK;
199 break;
201 case MUST_NOT_THROW_EXPR:
202 gimplify_must_not_throw_expr (expr_p, pre_p);
203 ret = GS_OK;
204 break;
206 case INIT_EXPR:
207 case MODIFY_EXPR:
208 cp_gimplify_init_expr (expr_p, pre_p, post_p);
209 ret = GS_OK;
210 break;
212 case EMPTY_CLASS_EXPR:
213 /* We create an INTEGER_CST with RECORD_TYPE and value zero. */
214 *expr_p = build_int_cst (TREE_TYPE (*expr_p), 0);
215 ret = GS_OK;
216 break;
218 case BASELINK:
219 *expr_p = BASELINK_FUNCTIONS (*expr_p);
220 ret = GS_OK;
221 break;
223 case TRY_BLOCK:
224 genericize_try_block (expr_p);
225 ret = GS_OK;
226 break;
228 case HANDLER:
229 genericize_catch_block (expr_p);
230 ret = GS_OK;
231 break;
233 case EH_SPEC_BLOCK:
234 genericize_eh_spec_block (expr_p);
235 ret = GS_OK;
236 break;
238 case USING_STMT:
239 /* Just ignore for now. Eventually we will want to pass this on to
240 the debugger. */
241 *expr_p = build_empty_stmt ();
242 ret = GS_ALL_DONE;
243 break;
245 case IF_STMT:
246 gimplify_if_stmt (expr_p);
247 ret = GS_OK;
248 break;
250 default:
251 ret = c_gimplify_expr (expr_p, pre_p, post_p);
252 break;
255 /* Restore saved state. */
256 if (STATEMENT_CODE_P (code))
257 current_stmt_tree ()->stmts_are_full_exprs_p
258 = saved_stmts_are_full_exprs_p;
260 return ret;
263 static inline bool
264 is_invisiref_parm (tree t)
266 return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
267 && DECL_BY_REFERENCE (t));
270 /* Perform any pre-gimplification lowering of C++ front end trees to
271 GENERIC. */
273 static tree
274 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
276 tree stmt = *stmt_p;
277 htab_t htab = (htab_t) data;
278 void **slot;
280 if (is_invisiref_parm (stmt))
282 *stmt_p = convert_from_reference (stmt);
283 *walk_subtrees = 0;
284 return NULL;
287 /* Other than invisiref parms, don't walk the same tree twice. */
288 slot = htab_find_slot (htab, stmt, INSERT);
289 if (*slot)
291 *walk_subtrees = 0;
292 return NULL_TREE;
295 if (TREE_CODE (stmt) == ADDR_EXPR
296 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
298 *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
299 *walk_subtrees = 0;
301 else if (TREE_CODE (stmt) == RETURN_EXPR
302 && TREE_OPERAND (stmt, 0)
303 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
304 /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */
305 *walk_subtrees = 0;
306 else if (IS_TYPE_OR_DECL_P (stmt))
307 *walk_subtrees = 0;
309 /* Due to the way voidify_wrapper_expr is written, we don't get a chance
310 to lower this construct before scanning it, so we need to lower these
311 before doing anything else. */
312 else if (TREE_CODE (stmt) == CLEANUP_STMT)
313 *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
314 : TRY_FINALLY_EXPR,
315 void_type_node,
316 CLEANUP_BODY (stmt),
317 CLEANUP_EXPR (stmt));
319 *slot = *stmt_p;
320 return NULL;
323 void
324 cp_genericize (tree fndecl)
326 tree t;
327 htab_t htab;
329 /* Fix up the types of parms passed by invisible reference. */
330 for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
332 gcc_assert (!DECL_BY_REFERENCE (t));
333 if (TREE_ADDRESSABLE (TREE_TYPE (t)))
335 gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
336 TREE_TYPE (t) = DECL_ARG_TYPE (t);
337 DECL_BY_REFERENCE (t) = 1;
338 TREE_ADDRESSABLE (t) = 0;
339 relayout_decl (t);
343 /* Do the same for the return value. */
344 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
346 t = DECL_RESULT (fndecl);
347 TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
348 DECL_BY_REFERENCE (t) = 1;
349 TREE_ADDRESSABLE (t) = 0;
350 relayout_decl (t);
353 /* If we're a clone, the body is already GIMPLE. */
354 if (DECL_CLONED_FUNCTION_P (fndecl))
355 return;
357 /* We do want to see every occurrence of the parms, so we can't just use
358 walk_tree's hash functionality. */
359 htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
360 walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, htab, NULL);
361 htab_delete (htab);
363 /* Do everything else. */
364 c_genericize (fndecl);