PR tree-optimization/15991
[official-gcc.git] / gcc / cp / cp-gimplify.c
blob2884d8b5b2df347660c2acd2227b349cc6e59db7
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
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"
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. */
41 int
42 cp_gimplify_stmt (tree *stmt_p)
44 tree stmt = *stmt_p;
45 switch (TREE_CODE (stmt))
47 case TRY_BLOCK:
48 genericize_try_block (stmt_p);
49 return 1;
51 case HANDLER:
52 genericize_catch_block (stmt_p);
53 return 1;
55 case EH_SPEC_BLOCK:
56 genericize_eh_spec_block (stmt_p);
57 return 1;
59 case USING_STMT:
60 /* Just ignore for now. Eventually we will want to pass this on to
61 the debugger. */
62 *stmt_p = build_empty_stmt ();
63 return 1;
65 default:
66 break;
68 return 0;
71 /* Genericize a TRY_BLOCK. */
73 static void
74 genericize_try_block (tree *stmt_p)
76 tree body = TRY_STMTS (*stmt_p);
77 tree cleanup = TRY_HANDLERS (*stmt_p);
79 gimplify_stmt (&body);
81 if (CLEANUP_P (*stmt_p))
82 /* A cleanup is an expression, so it doesn't need to be genericized. */;
83 else
84 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. */
91 static void
92 genericize_catch_block (tree *stmt_p)
94 tree type = HANDLER_TYPE (*stmt_p);
95 tree body = HANDLER_BODY (*stmt_p);
97 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. */
106 static void
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 (),
113 NULL_TREE));
114 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))
126 case PTRMEM_CST:
127 *expr_p = cplus_expand_constant (*expr_p);
128 return GS_OK;
130 case AGGR_INIT_EXPR:
131 simplify_aggr_init_expr (expr_p);
132 return GS_OK;
134 case THROW_EXPR:
135 /* FIXME communicate throw type to backend, probably by moving
136 THROW_EXPR into ../tree.def. */
137 *expr_p = TREE_OPERAND (*expr_p, 0);
138 return GS_OK;
140 case MUST_NOT_THROW_EXPR:
141 gimplify_must_not_throw_expr (expr_p, pre_p);
142 return GS_OK;
144 case INIT_EXPR:
145 case MODIFY_EXPR:
146 cp_gimplify_init_expr (expr_p, pre_p, post_p);
147 return GS_OK;
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);
154 *expr_p = i;
156 return GS_OK;
158 case BASELINK:
159 *expr_p = BASELINK_FUNCTIONS (*expr_p);
160 return GS_OK;
162 default:
163 return c_gimplify_expr (expr_p, pre_p, post_p);
167 /* Gimplify initialization from an AGGR_INIT_EXPR. */
169 static void
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);
174 tree sub;
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);
185 /* Look through any COMPOUND_EXPRs. */
186 sub = expr_last (from);
188 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
189 replace the slot operand with our target.
191 Should we add a target parm to gimplify_expr instead? No, as in this
192 case we want to replace the INIT_EXPR. */
193 if (TREE_CODE (sub) == AGGR_INIT_EXPR)
195 gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
196 TREE_OPERAND (sub, 2) = to;
197 *expr_p = from;
199 /* The initialization is now a side-effect, so the container can
200 become void. */
201 if (from != sub)
202 TREE_TYPE (from) = void_type_node;
206 /* Gimplify a MUST_NOT_THROW_EXPR. */
208 static void
209 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
211 tree stmt = *expr_p;
212 tree temp = voidify_wrapper_expr (stmt, NULL);
213 tree body = TREE_OPERAND (stmt, 0);
215 gimplify_stmt (&body);
217 stmt = gimple_build_eh_filter (body, NULL_TREE,
218 build_call (terminate_node, NULL_TREE));
220 if (temp)
222 append_to_statement_list (stmt, pre_p);
223 *expr_p = temp;
225 else
226 *expr_p = stmt;