1 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
3 Copyright (C) 2002, 2003 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
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
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
25 #include "coretypes.h"
31 #include "tree-gimple.h"
34 /* Genericize a TRY_BLOCK. */
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. */;
47 gimplify_stmt (&cleanup);
49 *stmt_p = build (TRY_CATCH_EXPR, void_type_node, body, cleanup);
52 /* Genericize a HANDLER by converting to a CATCH_EXPR. */
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 = build (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. */
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 (),
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. */
85 gimplify_if_stmt (tree *stmt_p)
87 tree stmt, then_, else_;
90 then_ = THEN_CLAUSE (stmt);
91 else_ = ELSE_CLAUSE (stmt);
94 then_ = build_empty_stmt ();
96 else_ = build_empty_stmt ();
98 stmt = build (COND_EXPR, void_type_node, IF_COND (stmt), then_, else_);
102 /* Gimplify initialization from an AGGR_INIT_EXPR. */
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);
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);
120 /* Look through any COMPOUND_EXPRs. */
121 sub = expr_last (from);
123 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
124 replace the slot operand with our target.
126 Should we add a target parm to gimplify_expr instead? No, as in this
127 case we want to replace the INIT_EXPR. */
128 if (TREE_CODE (sub) == AGGR_INIT_EXPR)
130 gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
131 TREE_OPERAND (sub, 2) = to;
134 /* The initialization is now a side-effect, so the container can
137 TREE_TYPE (from) = void_type_node;
141 /* Gimplify a MUST_NOT_THROW_EXPR. */
144 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
147 tree temp = voidify_wrapper_expr (stmt, NULL);
148 tree body = TREE_OPERAND (stmt, 0);
150 gimplify_stmt (&body);
152 stmt = gimple_build_eh_filter (body, NULL_TREE,
153 build_call (terminate_node, NULL_TREE));
157 append_to_statement_list (stmt, pre_p);
164 /* Do C++-specific gimplification. Args are as for gimplify_expr. */
167 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
169 int saved_stmts_are_full_exprs_p = 0;
170 enum tree_code code = TREE_CODE (*expr_p);
171 enum gimplify_status ret;
173 if (STATEMENT_CODE_P (code))
175 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
176 current_stmt_tree ()->stmts_are_full_exprs_p
177 = STMT_IS_FULL_EXPR_P (*expr_p);
183 *expr_p = cplus_expand_constant (*expr_p);
188 simplify_aggr_init_expr (expr_p);
193 /* FIXME communicate throw type to backend, probably by moving
194 THROW_EXPR into ../tree.def. */
195 *expr_p = TREE_OPERAND (*expr_p, 0);
199 case MUST_NOT_THROW_EXPR:
200 gimplify_must_not_throw_expr (expr_p, pre_p);
206 cp_gimplify_init_expr (expr_p, pre_p, post_p);
210 case EMPTY_CLASS_EXPR:
212 /* Yes, an INTEGER_CST with RECORD_TYPE. */
213 tree i = build_int_2 (0, 0);
214 TREE_TYPE (i) = TREE_TYPE (*expr_p);
221 *expr_p = BASELINK_FUNCTIONS (*expr_p);
226 genericize_try_block (expr_p);
231 genericize_catch_block (expr_p);
236 genericize_eh_spec_block (expr_p);
241 /* Just ignore for now. Eventually we will want to pass this on to
243 *expr_p = build_empty_stmt ();
248 gimplify_if_stmt (expr_p);
253 ret = c_gimplify_expr (expr_p, pre_p, post_p);
257 /* Restore saved state. */
258 if (STATEMENT_CODE_P (code))
259 current_stmt_tree ()->stmts_are_full_exprs_p
260 = saved_stmts_are_full_exprs_p;
265 /* Genericize a CLEANUP_STMT. This just turns into a TRY_FINALLY or
266 TRY_CATCH depending on whether it's EH-only. */
269 gimplify_cleanup_stmt (tree *stmt_p, int *walk_subtrees,
270 void *data ATTRIBUTE_UNUSED)
274 if (DECL_P (stmt) || TYPE_P (stmt))
276 else if (TREE_CODE (stmt) == CLEANUP_STMT)
277 *stmt_p = build (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR,
278 void_type_node, CLEANUP_BODY (stmt), CLEANUP_EXPR (stmt));
284 cp_genericize (tree fndecl)
286 /* Due to the way voidify_wrapper_expr is written, we don't get a chance
287 to lower this construct before scanning it. So we need to lower these
288 before doing anything else. */
289 walk_tree (&DECL_SAVED_TREE (fndecl), gimplify_cleanup_stmt, NULL, NULL);
291 /* Do everything else. */
292 c_genericize (fndecl);