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"
33 static void genericize_try_block (tree
*);
34 static void genericize_catch_block (tree
*);
35 static void genericize_eh_spec_block (tree
*);
36 static void gimplify_must_not_throw_expr (tree
*, tree
*);
37 static void cp_gimplify_init_expr (tree
*, tree
*, tree
*);
39 /* Genericize a C++ _STMT. Called from c_gimplify_stmt. */
42 cp_gimplify_stmt (tree
*stmt_p
, tree
*next_p ATTRIBUTE_UNUSED
)
45 switch (TREE_CODE (stmt
))
48 genericize_try_block (stmt_p
);
52 genericize_catch_block (stmt_p
);
56 genericize_eh_spec_block (stmt_p
);
60 /* Just ignore for now. Eventually we will want to pass this on to
62 *stmt_p
= build_empty_stmt ();
71 /* Genericize a TRY_BLOCK. */
74 genericize_try_block (tree
*stmt_p
)
76 tree body
= TRY_STMTS (*stmt_p
);
77 tree cleanup
= TRY_HANDLERS (*stmt_p
);
79 c_gimplify_stmt (&body
);
81 if (CLEANUP_P (*stmt_p
))
82 /* A cleanup is an expression, so it doesn't need to be genericized. */;
84 c_gimplify_stmt (&cleanup
);
86 *stmt_p
= build (TRY_CATCH_EXPR
, void_type_node
, body
, cleanup
);
89 /* Genericize a HANDLER by converting to a CATCH_EXPR. */
92 genericize_catch_block (tree
*stmt_p
)
94 tree type
= HANDLER_TYPE (*stmt_p
);
95 tree body
= HANDLER_BODY (*stmt_p
);
97 c_gimplify_stmt (&body
);
99 /* FIXME should the caught type go in TREE_TYPE? */
100 *stmt_p
= build (CATCH_EXPR
, void_type_node
, type
, body
);
103 /* Genericize an EH_SPEC_BLOCK by converting it to a
104 TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
107 genericize_eh_spec_block (tree
*stmt_p
)
109 tree body
= EH_SPEC_STMTS (*stmt_p
);
110 tree allowed
= EH_SPEC_RAISES (*stmt_p
);
111 tree failure
= build_call (call_unexpected_node
,
112 tree_cons (NULL_TREE
, build_exc_ptr (),
114 c_gimplify_stmt (&body
);
116 *stmt_p
= gimple_build_eh_filter (body
, allowed
, failure
);
119 /* Do C++-specific gimplification. Args are as for gimplify_expr. */
122 cp_gimplify_expr (tree
*expr_p
, tree
*pre_p
, tree
*post_p
)
124 switch (TREE_CODE (*expr_p
))
127 *expr_p
= cplus_expand_constant (*expr_p
);
131 simplify_aggr_init_expr (expr_p
);
135 /* FIXME communicate throw type to backend, probably by moving
136 THROW_EXPR into ../tree.def. */
137 *expr_p
= TREE_OPERAND (*expr_p
, 0);
140 case MUST_NOT_THROW_EXPR
:
141 gimplify_must_not_throw_expr (expr_p
, pre_p
);
146 cp_gimplify_init_expr (expr_p
, pre_p
, post_p
);
149 case EMPTY_CLASS_EXPR
:
151 /* Yes, an INTEGER_CST with RECORD_TYPE. */
152 tree i
= build_int_2 (0, 0);
153 TREE_TYPE (i
) = TREE_TYPE (*expr_p
);
159 *expr_p
= BASELINK_FUNCTIONS (*expr_p
);
163 return c_gimplify_expr (expr_p
, pre_p
, post_p
);
167 /* Gimplify initialization from an AGGR_INIT_EXPR. */
170 cp_gimplify_init_expr (tree
*expr_p
, tree
*pre_p
, tree
*post_p
)
172 tree from
= TREE_OPERAND (*expr_p
, 1);
173 tree to
= TREE_OPERAND (*expr_p
, 0);
176 /* If we are initializing something from a TARGET_EXPR, strip the
177 TARGET_EXPR and initialize it directly. */
178 /* What about code that pulls out the temp and uses it elsewhere? I
179 think that such code never uses the TARGET_EXPR as an initializer. If
180 I'm wrong, we'll abort because the temp won't have any RTL. In that
181 case, I guess we'll need to replace references somehow. */
182 if (TREE_CODE (from
) == TARGET_EXPR
)
183 from
= TARGET_EXPR_INITIAL (from
);
187 /* If we are initializing from a STMT_EXPR, extract the returned
189 if (TREE_CODE (from
) == STMT_EXPR
)
190 sub
= EXPR_STMT_EXPR (stmt_expr_last_stmt (from
));
192 /* Look through any COMPOUND_EXPRs. */
193 while (TREE_CODE (sub
) == COMPOUND_EXPR
)
194 sub
= TREE_OPERAND (sub
, 1);
196 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
197 replace the slot operand with our target.
199 Should we add a target parm to gimplify_expr instead? No, as in this
200 case we want to replace the INIT_EXPR. */
201 if (TREE_CODE (sub
) == AGGR_INIT_EXPR
)
203 gimplify_expr (&to
, pre_p
, post_p
, is_gimple_lvalue
, fb_lvalue
);
204 TREE_OPERAND (sub
, 2) = to
;
207 /* The initialization is now a side-effect, so the container can
208 become void. This is important for a STMT_EXPR, so we don't try
209 to voidify it later by creating a temporary. */
211 TREE_TYPE (from
) = void_type_node
;
215 /* Gimplify a MUST_NOT_THROW_EXPR. */
218 gimplify_must_not_throw_expr (tree
*expr_p
, tree
*pre_p
)
221 tree temp
= voidify_wrapper_expr (stmt
);
222 tree body
= TREE_OPERAND (stmt
, 0);
224 gimplify_stmt (&body
);
226 stmt
= gimple_build_eh_filter (body
, NULL_TREE
,
227 build_call (terminate_node
, NULL_TREE
));
231 append_to_statement_list (stmt
, pre_p
);