OSDN Git Service

When a class template is explicitly instantiated, its member should be too.
[pf3gnuchains/gcc-fork.git] / gcc / cp / cp-gimplify.c
1 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
2
3    Copyright (C) 2002, 2003 Free Software Foundation, Inc.
4    Contributed by Jason Merrill <jason@redhat.com>
5
6 This file is part of GCC.
7
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.
12
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.
17
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.  */
22
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
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 *);
38
39 /* Genericize a C++ _STMT.  Called from c_gimplify_stmt.  */
40
41 int
42 cp_gimplify_stmt (tree *stmt_p, tree *next_p ATTRIBUTE_UNUSED)
43 {
44   tree stmt = *stmt_p;
45   switch (TREE_CODE (stmt))
46     {
47     case TRY_BLOCK:
48       genericize_try_block (stmt_p);
49       return 1;
50
51     case HANDLER:
52       genericize_catch_block (stmt_p);
53       return 1;
54
55     case EH_SPEC_BLOCK:
56       genericize_eh_spec_block (stmt_p);
57       return 1;
58
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;
64
65     default:
66       break;
67     }
68   return 0;
69 }
70
71 /* Genericize a TRY_BLOCK.  */
72
73 static void
74 genericize_try_block (tree *stmt_p)
75 {
76   tree body = TRY_STMTS (*stmt_p);
77   tree cleanup = TRY_HANDLERS (*stmt_p);
78
79   c_gimplify_stmt (&body);
80
81   if (CLEANUP_P (*stmt_p))
82     /* A cleanup is an expression, so it doesn't need to be genericized.  */;
83   else
84     c_gimplify_stmt (&cleanup);
85
86   *stmt_p = build (TRY_CATCH_EXPR, void_type_node, body, cleanup);
87 }
88
89 /* Genericize a HANDLER by converting to a CATCH_EXPR.  */
90
91 static void
92 genericize_catch_block (tree *stmt_p)
93 {
94   tree type = HANDLER_TYPE (*stmt_p);
95   tree body = HANDLER_BODY (*stmt_p);
96
97   c_gimplify_stmt (&body);
98
99   /* FIXME should the caught type go in TREE_TYPE?  */
100   *stmt_p = build (CATCH_EXPR, void_type_node, type, body);
101 }
102
103 /* Genericize an EH_SPEC_BLOCK by converting it to a
104    TRY_CATCH_EXPR/EH_FILTER_EXPR pair.  */
105
106 static void
107 genericize_eh_spec_block (tree *stmt_p)
108 {
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   c_gimplify_stmt (&body);
115
116   *stmt_p = gimple_build_eh_filter (body, allowed, failure);
117 }
118
119 /* Do C++-specific gimplification.  Args are as for gimplify_expr.  */
120
121 int
122 cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
123 {
124   switch (TREE_CODE (*expr_p))
125     {
126     case PTRMEM_CST:
127       *expr_p = cplus_expand_constant (*expr_p);
128       return GS_OK;
129
130     case AGGR_INIT_EXPR:
131       simplify_aggr_init_expr (expr_p);
132       return GS_OK;
133
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;
139
140     case MUST_NOT_THROW_EXPR:
141       gimplify_must_not_throw_expr (expr_p, pre_p);
142       return GS_OK;
143
144     case INIT_EXPR:
145     case MODIFY_EXPR:
146       cp_gimplify_init_expr (expr_p, pre_p, post_p);
147       return GS_OK;
148
149     case EMPTY_CLASS_EXPR:
150       {
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;
155       }
156       return GS_OK;
157
158     case BASELINK:
159       *expr_p = BASELINK_FUNCTIONS (*expr_p);
160       return GS_OK;
161
162     default:
163       return c_gimplify_expr (expr_p, pre_p, post_p);
164     }
165 }
166
167 /* Gimplify initialization from an AGGR_INIT_EXPR.  */
168
169 static void
170 cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
171 {
172   tree from = TREE_OPERAND (*expr_p, 1);
173   tree to = TREE_OPERAND (*expr_p, 0);
174   tree sub;
175
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);
184
185   sub = from;
186
187   /* If we are initializing from a STMT_EXPR, extract the returned
188      expression.  */
189   if (TREE_CODE (from) == STMT_EXPR)
190     sub = EXPR_STMT_EXPR (stmt_expr_last_stmt (from));
191
192   /* Look through any COMPOUND_EXPRs.  */
193   while (TREE_CODE (sub) == COMPOUND_EXPR)
194     sub = TREE_OPERAND (sub, 1);
195
196   /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
197      replace the slot operand with our target.
198
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)
202     {
203       gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue);
204       TREE_OPERAND (sub, 2) = to;
205       *expr_p = from;
206
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.  */
210       if (from != sub)
211         TREE_TYPE (from) = void_type_node;
212     }
213 }
214
215 /* Gimplify a MUST_NOT_THROW_EXPR.  */
216
217 static void
218 gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
219 {
220   tree stmt = *expr_p;
221   tree temp = voidify_wrapper_expr (stmt);
222   tree body = TREE_OPERAND (stmt, 0);
223
224   gimplify_stmt (&body);
225
226   stmt = gimple_build_eh_filter (body, NULL_TREE,
227                                  build_call (terminate_node, NULL_TREE));
228
229   if (temp)
230     {
231       append_to_statement_list (stmt, pre_p);
232       *expr_p = temp;
233     }
234   else
235     *expr_p = stmt;
236 }