Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / gcc / cp / cp-gimplify.c
blob413a93380104e6d340511d1bf874d583f8ebe899
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"
33 #include "pointer-set.h"
35 /* Genericize a TRY_BLOCK. */
37 static void
38 genericize_try_block (tree *stmt_p)
40 tree body = TRY_STMTS (*stmt_p);
41 tree cleanup = TRY_HANDLERS (*stmt_p);
43 gimplify_stmt (&body);
45 if (CLEANUP_P (*stmt_p))
46 /* A cleanup is an expression, so it doesn't need to be genericized. */;
47 else
48 gimplify_stmt (&cleanup);
50 *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
53 /* Genericize a HANDLER by converting to a CATCH_EXPR. */
55 static void
56 genericize_catch_block (tree *stmt_p)
58 tree type = HANDLER_TYPE (*stmt_p);
59 tree body = HANDLER_BODY (*stmt_p);
61 gimplify_stmt (&body);
63 /* FIXME should the caught type go in TREE_TYPE? */
64 *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
67 /* Genericize an EH_SPEC_BLOCK by converting it to a
68 TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
70 static void
71 genericize_eh_spec_block (tree *stmt_p)
73 tree body = EH_SPEC_STMTS (*stmt_p);
74 tree allowed = EH_SPEC_RAISES (*stmt_p);
75 tree failure = build_call (call_unexpected_node,
76 tree_cons (NULL_TREE, build_exc_ptr (),
77 NULL_TREE));
78 gimplify_stmt (&body);
80 *stmt_p = gimple_build_eh_filter (body, allowed, failure);
83 /* Genericize an IF_STMT by turning it into a COND_EXPR. */
85 static void
86 gimplify_if_stmt (tree *stmt_p)
88 tree stmt, cond, then_, else_;
90 stmt = *stmt_p;
91 cond = IF_COND (stmt);
92 then_ = THEN_CLAUSE (stmt);
93 else_ = ELSE_CLAUSE (stmt);
95 if (!then_)
96 then_ = build_empty_stmt ();
97 if (!else_)
98 else_ = build_empty_stmt ();
100 if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
101 stmt = then_;
102 else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
103 stmt = else_;
104 else
105 stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
106 *stmt_p = stmt;
109 /* Gimplify initialization from an AGGR_INIT_EXPR. */
111 static void
112 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
114 tree from = TREE_OPERAND (*expr_p, 1);
115 tree to = TREE_OPERAND (*expr_p, 0);
116 tree sub;
118 /* If we are initializing something from a TARGET_EXPR, strip the
119 TARGET_EXPR and initialize it directly. */
120 /* What about code that pulls out the temp and uses it elsewhere? I
121 think that such code never uses the TARGET_EXPR as an initializer. If
122 I'm wrong, we'll abort because the temp won't have any RTL. In that
123 case, I guess we'll need to replace references somehow. */
124 if (TREE_CODE (from) == TARGET_EXPR)
125 from = TARGET_EXPR_INITIAL (from);
126 if (TREE_CODE (from) == CLEANUP_POINT_EXPR)
127 from = TREE_OPERAND (from, 0);
129 /* Look through any COMPOUND_EXPRs. */
130 sub = expr_last (from);
132 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
133 replace the slot operand with our target.
135 Should we add a target parm to gimplify_expr instead? No, as in this
136 case we want to replace the INIT_EXPR. */
137 if (TREE_CODE (sub) == AGGR_INIT_EXPR)
139 gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
140 TREE_OPERAND (sub, 2) = to;
141 *expr_p = from;
143 /* The initialization is now a side-effect, so the container can
144 become void. */
145 if (from != sub)
146 TREE_TYPE (from) = void_type_node;
150 /* Gimplify a MUST_NOT_THROW_EXPR. */
152 static void
153 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
155 tree stmt = *expr_p;
156 tree temp = voidify_wrapper_expr (stmt, NULL);
157 tree body = TREE_OPERAND (stmt, 0);
159 gimplify_stmt (&body);
161 stmt = gimple_build_eh_filter (body, NULL_TREE,
162 build_call (terminate_node, NULL_TREE));
164 if (temp)
166 append_to_statement_list (stmt, pre_p);
167 *expr_p = temp;
169 else
170 *expr_p = stmt;
173 /* Do C++-specific gimplification. Args are as for gimplify_expr. */
176 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
178 int saved_stmts_are_full_exprs_p = 0;
179 enum tree_code code = TREE_CODE (*expr_p);
180 enum gimplify_status ret;
182 if (STATEMENT_CODE_P (code))
184 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
185 current_stmt_tree ()->stmts_are_full_exprs_p
186 = STMT_IS_FULL_EXPR_P (*expr_p);
189 switch (code)
191 case PTRMEM_CST:
192 *expr_p = cplus_expand_constant (*expr_p);
193 ret = GS_OK;
194 break;
196 case AGGR_INIT_EXPR:
197 simplify_aggr_init_expr (expr_p);
198 ret = GS_OK;
199 break;
201 case THROW_EXPR:
202 /* FIXME communicate throw type to backend, probably by moving
203 THROW_EXPR into ../tree.def. */
204 *expr_p = TREE_OPERAND (*expr_p, 0);
205 ret = GS_OK;
206 break;
208 case MUST_NOT_THROW_EXPR:
209 gimplify_must_not_throw_expr (expr_p, pre_p);
210 ret = GS_OK;
211 break;
213 case INIT_EXPR:
214 case MODIFY_EXPR:
215 cp_gimplify_init_expr (expr_p, pre_p, post_p);
216 ret = GS_OK;
217 break;
219 case EMPTY_CLASS_EXPR:
220 /* We create an INTEGER_CST with RECORD_TYPE and value zero. */
221 *expr_p = build_int_cst (TREE_TYPE (*expr_p), 0);
222 ret = GS_OK;
223 break;
225 case BASELINK:
226 *expr_p = BASELINK_FUNCTIONS (*expr_p);
227 ret = GS_OK;
228 break;
230 case TRY_BLOCK:
231 genericize_try_block (expr_p);
232 ret = GS_OK;
233 break;
235 case HANDLER:
236 genericize_catch_block (expr_p);
237 ret = GS_OK;
238 break;
240 case EH_SPEC_BLOCK:
241 genericize_eh_spec_block (expr_p);
242 ret = GS_OK;
243 break;
245 case USING_STMT:
246 /* Just ignore for now. Eventually we will want to pass this on to
247 the debugger. */
248 *expr_p = build_empty_stmt ();
249 ret = GS_ALL_DONE;
250 break;
252 case IF_STMT:
253 gimplify_if_stmt (expr_p);
254 ret = GS_OK;
255 break;
257 default:
258 ret = c_gimplify_expr (expr_p, pre_p, post_p);
259 break;
262 /* Restore saved state. */
263 if (STATEMENT_CODE_P (code))
264 current_stmt_tree ()->stmts_are_full_exprs_p
265 = saved_stmts_are_full_exprs_p;
267 return ret;
270 static inline bool
271 is_invisiref_parm (tree t)
273 return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
274 && DECL_BY_REFERENCE (t));
277 /* Perform any pre-gimplification lowering of C++ front end trees to
278 GENERIC. */
280 static tree
281 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
283 tree stmt = *stmt_p;
284 struct pointer_set_t *p_set = (struct pointer_set_t*) data;
286 if (is_invisiref_parm (stmt))
288 *stmt_p = convert_from_reference (stmt);
289 *walk_subtrees = 0;
290 return NULL;
293 /* Other than invisiref parms, don't walk the same tree twice. */
294 if (pointer_set_contains (p_set, stmt))
296 *walk_subtrees = 0;
297 return NULL_TREE;
300 if (TREE_CODE (stmt) == ADDR_EXPR
301 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
303 *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
304 *walk_subtrees = 0;
306 else if (TREE_CODE (stmt) == RETURN_EXPR
307 && TREE_OPERAND (stmt, 0)
308 && is_invisiref_parm (TREE_OPERAND (stmt, 0)))
309 /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */
310 *walk_subtrees = 0;
311 else if (IS_TYPE_OR_DECL_P (stmt))
312 *walk_subtrees = 0;
314 /* Due to the way voidify_wrapper_expr is written, we don't get a chance
315 to lower this construct before scanning it, so we need to lower these
316 before doing anything else. */
317 else if (TREE_CODE (stmt) == CLEANUP_STMT)
318 *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
319 : TRY_FINALLY_EXPR,
320 void_type_node,
321 CLEANUP_BODY (stmt),
322 CLEANUP_EXPR (stmt));
324 pointer_set_insert (p_set, *stmt_p);
326 return NULL;
329 void
330 cp_genericize (tree fndecl)
332 tree t;
333 struct pointer_set_t *p_set;
335 /* Fix up the types of parms passed by invisible reference. */
336 for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
337 if (TREE_ADDRESSABLE (TREE_TYPE (t)))
339 /* If a function's arguments are copied to create a thunk,
340 then DECL_BY_REFERENCE will be set -- but the type of the
341 argument will be a pointer type, so we will never get
342 here. */
343 gcc_assert (!DECL_BY_REFERENCE (t));
344 gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
345 TREE_TYPE (t) = DECL_ARG_TYPE (t);
346 DECL_BY_REFERENCE (t) = 1;
347 TREE_ADDRESSABLE (t) = 0;
348 relayout_decl (t);
351 /* Do the same for the return value. */
352 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
354 t = DECL_RESULT (fndecl);
355 TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
356 DECL_BY_REFERENCE (t) = 1;
357 TREE_ADDRESSABLE (t) = 0;
358 relayout_decl (t);
361 /* If we're a clone, the body is already GIMPLE. */
362 if (DECL_CLONED_FUNCTION_P (fndecl))
363 return;
365 /* We do want to see every occurrence of the parms, so we can't just use
366 walk_tree's hash functionality. */
367 p_set = pointer_set_create ();
368 walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
369 pointer_set_destroy (p_set);
371 /* Do everything else. */
372 c_genericize (fndecl);