OSDN Git Service

2004-06-03 Chris Demetriou <cgd@broadcom.com>
[pf3gnuchains/gcc-fork.git] / gcc / c-semantics.c
1 /* This file contains the definitions and documentation for the common
2    tree codes used in the GNU C and C++ compilers (see c-common.def
3    for the standard codes).
4    Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
5    Written by Benjamin Chelf (chelf@codesourcery.com).
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING.  If not, write to the Free
21 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
22 02111-1307, USA.  */
23
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "tree.h"
29 #include "function.h"
30 #include "splay-tree.h"
31 #include "varray.h"
32 #include "c-common.h"
33 #include "except.h"
34 /* In order for the format checking to accept the C frontend
35    diagnostic framework extensions, you must define this token before
36    including toplev.h.  */
37 #define GCC_DIAG_STYLE __gcc_cdiag__
38 #include "toplev.h"
39 #include "flags.h"
40 #include "ggc.h"
41 #include "rtl.h"
42 #include "output.h"
43 #include "timevar.h"
44 #include "predict.h"
45 #include "tree-inline.h"
46 #include "langhooks.h"
47
48 /* Create an empty statement tree rooted at T.  */
49
50 void
51 begin_stmt_tree (tree *t)
52 {
53   /* We create a trivial EXPR_STMT so that last_tree is never NULL in
54      what follows.  We remove the extraneous statement in
55      finish_stmt_tree.  */
56   *t = build_nt (EXPR_STMT, void_zero_node);
57   last_tree = *t;
58   last_expr_type = NULL_TREE;
59   last_expr_filename = input_filename;
60 }
61
62 /* T is a statement.  Add it to the statement-tree.  */
63
64 tree
65 add_stmt (tree t)
66 {
67   if (!EXPR_LOCUS (t))
68     annotate_with_locus (t, input_location);
69
70   /* Add T to the statement-tree.  */
71   TREE_CHAIN (last_tree) = t;
72   last_tree = t;
73
74   /* When we expand a statement-tree, we must know whether or not the
75      statements are full-expressions.  We record that fact here.  */
76   STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
77
78   return t;
79 }
80
81 /* Create a declaration statement for the declaration given by the
82    DECL.  */
83
84 void
85 add_decl_stmt (tree decl)
86 {
87   tree decl_stmt;
88
89   /* We need the type to last until instantiation time.  */
90   decl_stmt = build_stmt (DECL_STMT, decl);
91   add_stmt (decl_stmt);
92 }
93
94 /* Add a scope-statement to the statement-tree.  BEGIN_P indicates
95    whether this statements opens or closes a scope.  PARTIAL_P is true
96    for a partial scope, i.e, the scope that begins after a label when
97    an object that needs a cleanup is created.  If BEGIN_P is nonzero,
98    returns a new TREE_LIST representing the top of the SCOPE_STMT
99    stack.  The TREE_PURPOSE is the new SCOPE_STMT.  If BEGIN_P is
100    zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT,
101    and whose TREE_PURPOSE is the matching SCOPE_STMT with
102    SCOPE_BEGIN_P set.  */
103
104 tree
105 add_scope_stmt (int begin_p, int partial_p)
106 {
107   tree *stack_ptr = current_scope_stmt_stack ();
108   tree ss;
109   tree top = *stack_ptr;
110
111   /* Build the statement.  */
112   ss = build_stmt (SCOPE_STMT, NULL_TREE);
113   SCOPE_BEGIN_P (ss) = begin_p;
114   SCOPE_PARTIAL_P (ss) = partial_p;
115
116   /* Keep the scope stack up to date.  */
117   if (begin_p)
118     {
119       top = tree_cons (ss, NULL_TREE, top);
120       *stack_ptr = top;
121     }
122   else
123     {
124       if (partial_p != SCOPE_PARTIAL_P (TREE_PURPOSE (top)))
125         abort ();
126       TREE_VALUE (top) = ss;
127       *stack_ptr = TREE_CHAIN (top);
128     }
129
130   /* Add the new statement to the statement-tree.  */
131   add_stmt (ss);
132
133   return top;
134 }
135
136 /* Finish the statement tree rooted at T.  */
137
138 void
139 finish_stmt_tree (tree *t)
140 {
141   tree stmt;
142
143   /* Remove the fake extra statement added in begin_stmt_tree.  */
144   stmt = TREE_CHAIN (*t);
145   *t = stmt;
146   last_tree = NULL_TREE;
147 }
148
149 /* Build a generic statement based on the given type of node and
150    arguments. Similar to `build_nt', except that we set
151    EXPR_LOCUS to be the current source location.  */
152 /* ??? This should be obsolete with the lineno_stmt productions
153    in the grammar.  */
154
155 tree
156 build_stmt (enum tree_code code, ...)
157 {
158   tree ret;
159   int length, i;
160   va_list p;
161   bool side_effects;
162
163   va_start (p, code);
164
165   ret = make_node (code);
166   length = TREE_CODE_LENGTH (code);
167   annotate_with_locus (ret, input_location);
168
169   /* Most statements have implicit side effects all on their own, 
170      such as control transfer.  For those that do, we'll compute
171      the real value of TREE_SIDE_EFFECTS from its arguments.  */
172   switch (code)
173     {
174     case EXPR_STMT:
175       side_effects = false;
176       break;
177     default:
178       side_effects = true;
179       break;
180     }
181
182   for (i = 0; i < length; i++)
183     {
184       tree t = va_arg (p, tree);
185       if (t && IS_NON_TYPE_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (t))))
186         side_effects |= TREE_SIDE_EFFECTS (t);
187       TREE_OPERAND (ret, i) = t;
188     }
189
190   TREE_SIDE_EFFECTS (ret) = side_effects;
191
192   va_end (p);
193   return ret;
194 }
195
196 /* Create RTL for the local static variable DECL.  */
197
198 void
199 make_rtl_for_local_static (tree decl)
200 {
201   const char *asmspec = NULL;
202
203   /* If we inlined this variable, we could see it's declaration
204      again.  */
205   if (TREE_ASM_WRITTEN (decl))
206     return;
207
208   /* If the DECL_ASSEMBLER_NAME is not the same as the DECL_NAME, then
209      either we already created RTL for this DECL (and since it was a
210      local variable, its DECL_ASSEMBLER_NAME got hacked up to prevent
211      clashes with other local statics with the same name by a previous
212      call to make_decl_rtl), or the user explicitly requested a
213      particular assembly name for this variable, using the GNU
214      extension for this purpose:
215
216        int i asm ("j");
217
218      There's no way to know which case we're in, here.  But, it turns
219      out we're safe.  If there's already RTL, then
220      rest_of_decl_compilation ignores the ASMSPEC parameter, so we
221      may as well not pass it in.  If there isn't RTL, then we didn't
222      already create RTL, which means that the modification to
223      DECL_ASSEMBLER_NAME came only via the explicit extension.  */
224   if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl)
225       && !DECL_RTL_SET_P (decl))
226     asmspec = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
227
228   rest_of_decl_compilation (decl, asmspec, /*top_level=*/0, /*at_end=*/0);
229 }
230
231 /* Let the back-end know about DECL.  */
232
233 void
234 emit_local_var (tree decl)
235 {
236   /* Create RTL for this variable.  */
237   if (!DECL_RTL_SET_P (decl))
238     {
239       if (DECL_HARD_REGISTER (decl))
240         /* The user specified an assembler name for this variable.
241            Set that up now.  */
242         rest_of_decl_compilation
243           (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
244            /*top_level=*/0, /*at_end=*/0);
245       else
246         expand_decl (decl);
247     }
248 }
249
250 /* Build the node for a return statement and return it.  */
251
252 tree
253 build_return_stmt (tree expr)
254 {
255   return (build_stmt (RETURN_STMT, expr));
256 }
257
258 /* Build a break statement node and return it.  */
259
260 tree
261 build_break_stmt (void)
262 {
263   return (build_stmt (BREAK_STMT));
264 }
265
266 /* Build a continue statement node and return it.  */
267
268 tree
269 build_continue_stmt (void)
270 {
271   return (build_stmt (CONTINUE_STMT));
272 }
273
274 /* Create a CASE_LABEL tree node and return it.  */
275
276 tree
277 build_case_label (tree low_value, tree high_value, tree label_decl)
278 {
279   return build_stmt (CASE_LABEL, low_value, high_value, label_decl);
280 }
281
282 /* We're about to expand T, a statement.  Set up appropriate context
283    for the substitution.  */
284
285 void
286 prep_stmt (tree t)
287 {
288   if (EXPR_LOCUS (t))
289     input_location = *EXPR_LOCUS (t);
290   current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
291 }