]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/spew.c
53rd Cygnus<->FSF merge
[gcc.git] / gcc / cp / spew.c
CommitLineData
8d08fdba
MS
1/* Type Analyzer for GNU C++.
2 Copyright (C) 1987, 1989, 1992, 1993 Free Software Foundation, Inc.
3 Hacked... nay, bludgeoned... by Mark Eichin (eichin@cygnus.com)
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21
22/* This file is the type analyzer for GNU C++. To debug it, define SPEW_DEBUG
51c184be 23 when compiling parse.c and spew.c. */
8d08fdba
MS
24
25#include "config.h"
26#include <stdio.h>
27#include "input.h"
28#include "tree.h"
29#include "lex.h"
30#include "parse.h"
31#include "cp-tree.h"
32#include "flags.h"
33#include "obstack.h"
34
35/* This takes a token stream that hasn't decided much about types and
36 tries to figure out as much as it can, with excessive lookahead and
37 backtracking. */
38
39/* fifo of tokens recognized and available to parser. */
40struct token {
41 /* The values for YYCHAR will fit in a short. */
42 short yychar;
43 short end_of_file;
44 YYSTYPE yylval;
45};
46
47static int do_aggr ();
8d08fdba 48
51c184be 49/* From lex.c: */
8d08fdba
MS
50/* the declaration found for the last IDENTIFIER token read in.
51 yylex must look this up to detect typedefs, which get token type TYPENAME,
52 so it is left around in case the identifier is not a typedef but is
53 used in a context which makes it a reference to a variable. */
54extern tree lastiddecl; /* let our brains leak out here too */
55extern int yychar; /* the lookahead symbol */
56extern YYSTYPE yylval; /* the semantic value of the */
57 /* lookahead symbol */
58extern int end_of_file;
59
60struct obstack token_obstack;
61int first_token;
62
63#ifdef SPEW_DEBUG
64int spew_debug = 0;
65static unsigned int yylex_ctr = 0;
66static int debug_yychar ();
67#endif
68
8d08fdba
MS
69/* Initialize token_obstack. Called once, from init_lex. */
70void
71init_spew ()
72{
8926095f 73 gcc_obstack_init(&token_obstack);
8d08fdba
MS
74}
75
76#ifdef SPEW_DEBUG
77/* Use functions for debugging... */
78
79/* Return the number of tokens available on the fifo. */
80static int
81num_tokens ()
82{
83 return (obstack_object_size(&token_obstack)/sizeof(struct token))
84 - first_token;
85}
86
87/* Fetch the token N down the line from the head of the fifo. */
88static struct token*
89nth_token (n)
90 int n;
91{
92 /* could just have this do slurp_ implicitly, but this way is easier
93 * to debug... */
94 my_friendly_assert (n < num_tokens(), 298);
95 return ((struct token*)obstack_base(&token_obstack))+n+first_token;
96}
97
98/* Add a token to the token fifo. */
99static void
100add_token (t)
101 struct token* t;
102{
103 obstack_grow(&token_obstack,t,sizeof (struct token));
104}
105
106/* Consume the next token out of the fifo. */
107static void
108consume_token()
109{
110 if (num_tokens() == 1)
111 {
112 obstack_free(&token_obstack, obstack_base (&token_obstack));
113 first_token = 0;
114 }
115 else
116 first_token++;
117}
118
119#else
120/* ...otherwise use macros. */
121
122#define num_tokens() \
123 ((obstack_object_size(&token_obstack)/sizeof(struct token)) - first_token)
124
125#define nth_token(N) \
126 (((struct token*)obstack_base(&token_obstack))+(N)+first_token)
127
128#define add_token(T) obstack_grow(&token_obstack, (T), sizeof (struct token))
129
130#define consume_token() \
131 (num_tokens() == 1 \
132 ? (obstack_free (&token_obstack, obstack_base (&token_obstack)), \
133 (first_token = 0)) \
134 : first_token++)
135#endif
136
a28e3c7f
MS
137/* Pull in enough tokens from real_yylex that the queue is N long beyond
138 the current token. */
8d08fdba
MS
139
140static void
141scan_tokens (n)
142 int n;
143{
144 int i;
145 struct token *tmp;
146
147 /* We cannot read past certain tokens, so make sure we don't. */
148 i = num_tokens ();
149 if (i > n)
150 return;
151 while (i-- > 0)
152 {
153 tmp = nth_token (i);
154 /* Never read past these characters: they might separate
155 the current input stream from one we save away later. */
156 if (tmp->yychar == '{' || tmp->yychar == ':' || tmp->yychar == ';')
157 goto pad_tokens;
158 }
159
160 while (num_tokens() <= n)
161 {
162 obstack_blank(&token_obstack,sizeof (struct token));
163 tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
164 tmp->yychar = real_yylex();
165 tmp->end_of_file = end_of_file;
166 tmp->yylval = yylval;
167 end_of_file = 0;
168 if (tmp->yychar == '{'
169 || tmp->yychar == ':'
170 || tmp->yychar == ';')
171 {
172 pad_tokens:
173 while (num_tokens () <= n)
174 {
175 obstack_blank(&token_obstack,sizeof (struct token));
176 tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
177 tmp->yychar = EMPTY;
178 tmp->end_of_file = 0;
179 }
180 }
181 }
182}
183
184/* Create room for N tokens at the front of the fifo. This is used
185 to insert new tokens into the stream ahead of the current token. */
186
187static void
188shift_tokens (n)
189 int n;
190{
191 if (first_token >= n)
192 first_token -= n;
193 else
194 {
195 int old_token_count = num_tokens ();
196 char *tmp;
197
198 obstack_blank (&token_obstack, (n-first_token) * sizeof (struct token));
199 if (old_token_count)
200 {
201 tmp = (char *)alloca ((num_tokens () + (n-first_token))
202 * sizeof (struct token));
203 /* This move does not rely on the system being able to handle
204 overlapping moves. */
1daa5dd8
JM
205 bcopy ((char *) nth_token (0), tmp,
206 old_token_count * sizeof (struct token));
207 bcopy (tmp, (char *) nth_token (n),
208 old_token_count * sizeof (struct token));
8d08fdba
MS
209 }
210 first_token = 0;
211 }
212}
213
214static int
215probe_obstack (h, obj, nlevels)
216 struct obstack *h;
217 tree obj;
218 unsigned int nlevels;
219{
220 register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
221 register struct _obstack_chunk* plp; /* point to previous chunk if any */
222
223 lp = (h)->chunk;
224 /* We use >= rather than > since the object cannot be exactly at
225 the beginning of the chunk but might be an empty object exactly
226 at the end of an adjacent chunk. */
227 for (; nlevels != 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj);
228 nlevels -= 1)
229 {
230 plp = lp->prev;
231 lp = plp;
232 }
233 return nlevels != 0 && lp != 0;
234}
235
51c184be 236/* from lex.c: */
a28e3c7f
MS
237/* Value is 1 (or 2) if we should try to make the next identifier look like
238 a typename (when it may be a local variable or a class variable).
239 Value is 0 if we treat this name in a default fashion. */
8d08fdba 240extern int looking_for_typename;
a0a33927 241int looking_for_template;
8d08fdba
MS
242
243extern struct obstack *current_obstack, *saveable_obstack;
a28e3c7f 244tree got_scope;
e1cd6e56 245tree got_object;
8d08fdba
MS
246
247int
248yylex()
249{
250 struct token tmp_token;
251 tree trrr;
252
253 retry:
254#ifdef SPEW_DEBUG
255 if (spew_debug)
256 {
257 yylex_ctr ++;
258 fprintf(stderr, "\t\t## %d ##",yylex_ctr);
259 }
260#endif
8d08fdba
MS
261
262 /* if we've got tokens, send them */
263 if (num_tokens())
264 {
265 tmp_token= *nth_token(0);
266
267 /* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack.
268 If we don't find it in CURRENT_OBSTACK's current or immediately
269 previous chunk, assume it was and copy it to the current obstack. */
270 if ((tmp_token.yychar == CONSTANT
271 || tmp_token.yychar == STRING)
272 && ! TREE_PERMANENT (tmp_token.yylval.ttype)
273 && ! probe_obstack (current_obstack, tmp_token.yylval.ttype, 2)
274 && ! probe_obstack (saveable_obstack, tmp_token.yylval.ttype, 2))
275 tmp_token.yylval.ttype = copy_node (tmp_token.yylval.ttype);
276 }
277 else
278 {
279 /* if not, grab the next one and think about it */
280 tmp_token.yychar = real_yylex ();
281 tmp_token.yylval = yylval;
282 tmp_token.end_of_file = end_of_file;
283 add_token(&tmp_token);
284 }
285
286 /* many tokens just need to be returned. At first glance, all we
287 * have to do is send them back up, but some of them are needed to
288 * figure out local context. */
289 switch(tmp_token.yychar)
290 {
291 case EMPTY:
292 /* This is a lexical no-op. */
293 consume_token ();
294#ifdef SPEW_DEBUG
295 if (spew_debug)
296 debug_yychar (tmp_token.yychar);
297#endif
298 goto retry;
299
300 case IDENTIFIER:
a28e3c7f
MS
301 scan_tokens (1);
302 if (nth_token (1)->yychar == SCOPE)
303 /* Don't interfere with the setting from an 'aggr' prefix. */
304 looking_for_typename++;
a0a33927
MS
305 else if (nth_token (1)->yychar == '<')
306 looking_for_template = 1;
a28e3c7f 307
8d08fdba 308 trrr = lookup_name (tmp_token.yylval.ttype, -2);
a28e3c7f 309
8d08fdba
MS
310 if (trrr)
311 {
312 tmp_token.yychar = identifier_type (trrr);
313 switch (tmp_token.yychar)
314 {
315 case TYPENAME:
316 lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype);
a28e3c7f
MS
317 if (lastiddecl != trrr)
318 {
319 lastiddecl = trrr;
e1cd6e56 320 if (got_scope || got_object)
7177d104 321 tmp_token.yylval.ttype = DECL_NESTED_TYPENAME (trrr);
a28e3c7f 322 }
8d08fdba
MS
323 break;
324 case IDENTIFIER:
325 lastiddecl = trrr;
326 break;
327 case PTYPENAME:
a28e3c7f 328 lastiddecl = NULL_TREE;
8d08fdba
MS
329 break;
330 default:
331 my_friendly_abort (101);
332 }
333 }
334 else
335 lastiddecl = trrr;
7177d104 336 got_scope = NULL_TREE;
8d08fdba 337 /* and fall through to... */
e1cd6e56 338 case IDENTIFIER_DEFN:
8d08fdba 339 case TYPENAME:
e1cd6e56 340 case TYPENAME_DEFN:
8d08fdba 341 case PTYPENAME:
e1cd6e56 342 case PTYPENAME_DEFN:
a28e3c7f
MS
343 consume_token ();
344 if (looking_for_typename > 0)
345 looking_for_typename--;
a0a33927 346 looking_for_template = 0;
8d08fdba
MS
347 break;
348
349 case SCSPEC:
350 /* do_aggr needs to check if the previous token was RID_FRIEND,
351 so just increment first_token instead of calling consume_token. */
352 first_token++;
a28e3c7f 353 break;
8d08fdba
MS
354 case TYPESPEC:
355 consume_token ();
8d08fdba
MS
356 break;
357
8d08fdba
MS
358 case AGGR:
359 *nth_token(0) = tmp_token;
360 do_aggr ();
361 /* fall through to output... */
362 case ENUM:
363 /* Set this again, in case we are rescanning. */
364 looking_for_typename = 1;
365 /* fall through... */
366 default:
8d08fdba 367 consume_token();
8d08fdba
MS
368 }
369
370 yylval = tmp_token.yylval;
371 yychar = tmp_token.yychar;
372 end_of_file = tmp_token.end_of_file;
373#ifdef SPEW_DEBUG
374 if (spew_debug)
375 debug_yychar(yychar);
376#endif
8d08fdba
MS
377 return yychar;
378}
379
380/* token[0] == AGGR (struct/union/enum)
381 * Thus, token[1] is either a TYPENAME or a TYPENAME_DEFN.
382 * If token[2] == '{' or ':' then it's TYPENAME_DEFN.
383 * It's also a definition if it's a forward declaration (as in 'struct Foo;')
384 * which we can tell lf token[2] == ';' *and* token[-1] != FRIEND.
385 */
386static int
387do_aggr ()
388{
389 int yc1, yc2;
390
391 scan_tokens (2);
392 yc1 = nth_token (1)->yychar;
393 if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME)
394 return 0;
395 yc2 = nth_token (2)->yychar;
396 if (yc2 == ';')
397 {
398 /* It's a forward declaration iff we were not preceded by 'friend'. */
399 if (first_token > 0 && nth_token (-1)->yychar == SCSPEC
400 && nth_token (-1)->yylval.ttype == ridpointers[(int) RID_FRIEND])
401 return 0;
402 }
403 else if (yc2 != '{' && yc2 != ':')
404 return 0;
405
406 switch (yc1)
407 {
408 case TYPENAME:
409 nth_token (1)->yychar = TYPENAME_DEFN;
410 break;
411 case PTYPENAME:
412 nth_token (1)->yychar = PTYPENAME_DEFN;
413 break;
414 case IDENTIFIER:
415 nth_token (1)->yychar = IDENTIFIER_DEFN;
416 break;
417 default:
418 my_friendly_abort (102);
419 }
420 return 0;
421}
8d08fdba
MS
422
423#ifdef SPEW_DEBUG
424/* debug_yychar takes a yychar (token number) value and prints its name. */
425static int
426debug_yychar (yy)
427 int yy;
428{
51c184be 429 /* In parse.y: */
8d08fdba
MS
430 extern char *debug_yytranslate ();
431
432 int i;
433
434 if(yy<256) {
435 fprintf (stderr, "<%d: %c >\n", yy, yy);
436 return 0;
437 }
438 fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy));
439 return 1;
440}
441
442#endif
This page took 0.124859 seconds and 5 git commands to generate.