Initial revision
[official-gcc.git] / gcc / cp / spew.c
blob15a1aa9f1a740bf46ad60870ca895b01402f93f5
1 /* Type Analyzer for GNU C++.
2 Copyright (C) 1987, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
3 Hacked... nay, bludgeoned... by Mark Eichin (eichin@cygnus.com)
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
23 /* This file is the type analyzer for GNU C++. To debug it, define SPEW_DEBUG
24 when compiling parse.c and spew.c. */
26 #include "config.h"
27 #include <stdio.h>
28 #include "input.h"
29 #include "tree.h"
30 #include "lex.h"
31 #include "cp-tree.h"
32 #include "parse.h"
33 #include "flags.h"
34 #include "obstack.h"
36 /* This takes a token stream that hasn't decided much about types and
37 tries to figure out as much as it can, with excessive lookahead and
38 backtracking. */
40 /* fifo of tokens recognized and available to parser. */
41 struct token {
42 /* The values for YYCHAR will fit in a short. */
43 short yychar;
44 short end_of_file;
45 YYSTYPE yylval;
48 static int do_aggr ();
50 /* From lex.c: */
51 /* the declaration found for the last IDENTIFIER token read in.
52 yylex must look this up to detect typedefs, which get token type TYPENAME,
53 so it is left around in case the identifier is not a typedef but is
54 used in a context which makes it a reference to a variable. */
55 extern tree lastiddecl; /* let our brains leak out here too */
56 extern int yychar; /* the lookahead symbol */
57 extern YYSTYPE yylval; /* the semantic value of the */
58 /* lookahead symbol */
59 extern int end_of_file;
61 struct obstack token_obstack;
62 int first_token;
64 #ifdef SPEW_DEBUG
65 int spew_debug = 0;
66 static unsigned int yylex_ctr = 0;
67 static int debug_yychar ();
68 #endif
70 /* Initialize token_obstack. Called once, from init_lex. */
72 void
73 init_spew ()
75 gcc_obstack_init (&token_obstack);
78 #ifdef SPEW_DEBUG
79 /* Use functions for debugging... */
81 /* Return the number of tokens available on the fifo. */
83 static int
84 num_tokens ()
86 return (obstack_object_size (&token_obstack) / sizeof (struct token))
87 - first_token;
90 /* Fetch the token N down the line from the head of the fifo. */
92 static struct token*
93 nth_token (n)
94 int n;
96 /* could just have this do slurp_ implicitly, but this way is easier
97 to debug... */
98 my_friendly_assert (n < num_tokens (), 298);
99 return ((struct token*)obstack_base (&token_obstack)) + n + first_token;
102 /* Add a token to the token fifo. */
104 static void
105 add_token (t)
106 struct token* t;
108 obstack_grow (&token_obstack, t, sizeof (struct token));
111 /* Consume the next token out of the fifo. */
113 static void
114 consume_token ()
116 if (num_tokens () == 1)
118 obstack_free (&token_obstack, obstack_base (&token_obstack));
119 first_token = 0;
121 else
122 first_token++;
125 #else
126 /* ...otherwise use macros. */
128 #define num_tokens() \
129 ((obstack_object_size (&token_obstack) / sizeof (struct token)) - first_token)
131 #define nth_token(N) \
132 (((struct token*)obstack_base (&token_obstack))+(N)+first_token)
134 #define add_token(T) obstack_grow (&token_obstack, (T), sizeof (struct token))
136 #define consume_token() \
137 (num_tokens () == 1 \
138 ? (obstack_free (&token_obstack, obstack_base (&token_obstack)), \
139 (first_token = 0)) \
140 : first_token++)
141 #endif
143 /* Pull in enough tokens from real_yylex that the queue is N long beyond
144 the current token. */
146 static void
147 scan_tokens (n)
148 int n;
150 int i;
151 struct token *tmp;
153 /* We cannot read past certain tokens, so make sure we don't. */
154 i = num_tokens ();
155 if (i > n)
156 return;
157 while (i-- > 0)
159 tmp = nth_token (i);
160 /* Never read past these characters: they might separate
161 the current input stream from one we save away later. */
162 if (tmp->yychar == '{' || tmp->yychar == ':' || tmp->yychar == ';')
163 goto pad_tokens;
166 while (num_tokens () <= n)
168 obstack_blank (&token_obstack, sizeof (struct token));
169 tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
170 tmp->yychar = real_yylex ();
171 tmp->end_of_file = end_of_file;
172 tmp->yylval = yylval;
173 end_of_file = 0;
174 if (tmp->yychar == '{'
175 || tmp->yychar == ':'
176 || tmp->yychar == ';')
178 pad_tokens:
179 while (num_tokens () <= n)
181 obstack_blank (&token_obstack, sizeof (struct token));
182 tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
183 tmp->yychar = EMPTY;
184 tmp->end_of_file = 0;
190 static int
191 probe_obstack (h, obj, nlevels)
192 struct obstack *h;
193 tree obj;
194 unsigned int nlevels;
196 register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */
197 register struct _obstack_chunk* plp; /* point to previous chunk if any */
199 lp = (h)->chunk;
200 /* We use >= rather than > since the object cannot be exactly at
201 the beginning of the chunk but might be an empty object exactly
202 at the end of an adjacent chunk. */
203 for (; nlevels != 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj);
204 nlevels -= 1)
206 plp = lp->prev;
207 lp = plp;
209 return nlevels != 0 && lp != 0;
212 /* from lex.c: */
213 /* Value is 1 (or 2) if we should try to make the next identifier look like
214 a typename (when it may be a local variable or a class variable).
215 Value is 0 if we treat this name in a default fashion. */
216 extern int looking_for_typename;
217 int looking_for_template;
218 extern int do_snarf_defarg;
220 extern struct obstack *current_obstack, *saveable_obstack;
221 tree got_scope;
222 tree got_object;
225 peekyylex ()
227 scan_tokens (0);
228 return nth_token (0)->yychar;
231 extern tree snarf_defarg ();
234 yylex ()
236 struct token tmp_token;
237 tree trrr;
239 retry:
240 #ifdef SPEW_DEBUG
241 if (spew_debug)
243 yylex_ctr ++;
244 fprintf (stderr, "\t\t## %d ##", yylex_ctr);
246 #endif
248 if (do_snarf_defarg)
250 my_friendly_assert (num_tokens () == 0, 2837);
251 tmp_token.yychar = DEFARG;
252 tmp_token.yylval.ttype = snarf_defarg ();
253 tmp_token.end_of_file = 0;
254 do_snarf_defarg = 0;
255 add_token (&tmp_token);
258 /* if we've got tokens, send them */
259 else if (num_tokens ())
261 tmp_token= *nth_token (0);
263 /* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack.
264 If we don't find it in CURRENT_OBSTACK's current or immediately
265 previous chunk, assume it was and copy it to the current obstack. */
266 if ((tmp_token.yychar == CONSTANT
267 || tmp_token.yychar == STRING)
268 && ! TREE_PERMANENT (tmp_token.yylval.ttype)
269 && ! probe_obstack (current_obstack, tmp_token.yylval.ttype, 2)
270 && ! probe_obstack (saveable_obstack, tmp_token.yylval.ttype, 2))
271 tmp_token.yylval.ttype = copy_node (tmp_token.yylval.ttype);
273 else
275 /* if not, grab the next one and think about it */
276 tmp_token.yychar = real_yylex ();
277 tmp_token.yylval = yylval;
278 tmp_token.end_of_file = end_of_file;
279 add_token (&tmp_token);
282 /* many tokens just need to be returned. At first glance, all we
283 have to do is send them back up, but some of them are needed to
284 figure out local context. */
285 switch (tmp_token.yychar)
287 case EMPTY:
288 /* This is a lexical no-op. */
289 consume_token ();
290 #ifdef SPEW_DEBUG
291 if (spew_debug)
292 debug_yychar (tmp_token.yychar);
293 #endif
294 goto retry;
296 case IDENTIFIER:
297 scan_tokens (1);
298 if (nth_token (1)->yychar == SCOPE)
299 /* Don't interfere with the setting from an 'aggr' prefix. */
300 looking_for_typename++;
301 else if (nth_token (1)->yychar == '<')
302 looking_for_template = 1;
304 trrr = lookup_name (tmp_token.yylval.ttype, -2);
306 if (trrr)
308 tmp_token.yychar = identifier_type (trrr);
309 switch (tmp_token.yychar)
311 case TYPENAME:
312 case SELFNAME:
313 lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype);
314 if (lastiddecl != trrr)
315 lastiddecl = trrr;
316 if (got_scope)
317 tmp_token.yylval.ttype = trrr;
318 break;
319 case IDENTIFIER:
320 lastiddecl = trrr;
321 break;
322 case PTYPENAME:
323 lastiddecl = NULL_TREE;
324 break;
325 case NSNAME:
326 lastiddecl = trrr;
327 if (got_scope)
328 tmp_token.yylval.ttype = trrr;
329 break;
330 default:
331 my_friendly_abort (101);
334 else
335 lastiddecl = trrr;
336 got_scope = NULL_TREE;
337 /* and fall through to... */
338 case IDENTIFIER_DEFN:
339 case TYPENAME:
340 case TYPENAME_DEFN:
341 case PTYPENAME:
342 case PTYPENAME_DEFN:
343 consume_token ();
344 if (looking_for_typename > 0)
345 looking_for_typename--;
346 looking_for_template = 0;
347 break;
349 case SCSPEC:
350 case NEW:
351 /* do_aggr needs to check if the previous token was RID_NEW,
352 so just increment first_token instead of calling consume_token. */
353 ++first_token;
354 break;
356 case TYPESPEC:
357 consume_token ();
358 break;
360 case AGGR:
361 *nth_token (0) = tmp_token;
362 do_aggr ();
363 /* fall through to output... */
364 case ENUM:
365 /* Set this again, in case we are rescanning. */
366 looking_for_typename = 1;
367 /* fall through... */
368 default:
369 consume_token ();
372 got_object = NULL_TREE;
373 yylval = tmp_token.yylval;
374 yychar = tmp_token.yychar;
375 end_of_file = tmp_token.end_of_file;
376 #ifdef SPEW_DEBUG
377 if (spew_debug)
378 debug_yychar (yychar);
379 #endif
380 return yychar;
383 /* token[0] == AGGR (struct/union/enum)
384 Thus, token[1] is either a TYPENAME or a TYPENAME_DEFN.
385 If token[2] == '{' or ':' then it's TYPENAME_DEFN.
386 It's also a definition if it's a forward declaration (as in 'struct Foo;')
387 which we can tell if token[2] == ';' *and* token[-1] != FRIEND or NEW. */
389 static int
390 do_aggr ()
392 int yc1, yc2;
394 scan_tokens (2);
395 yc1 = nth_token (1)->yychar;
396 if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME)
397 return 0;
398 yc2 = nth_token (2)->yychar;
399 if (yc2 == ';')
401 /* It's a forward declaration iff we were not preceded by
402 'friend' or `new'. */
403 if (first_token > 0)
405 if (nth_token (-1)->yychar == SCSPEC
406 && nth_token (-1)->yylval.ttype == ridpointers[(int) RID_FRIEND])
407 return 0;
408 if (nth_token (-1)->yychar == NEW)
409 return 0;
412 else if (yc2 != '{' && yc2 != ':')
413 return 0;
415 switch (yc1)
417 case TYPENAME:
418 nth_token (1)->yychar = TYPENAME_DEFN;
419 break;
420 case PTYPENAME:
421 nth_token (1)->yychar = PTYPENAME_DEFN;
422 break;
423 case IDENTIFIER:
424 nth_token (1)->yychar = IDENTIFIER_DEFN;
425 break;
426 default:
427 my_friendly_abort (102);
429 return 0;
432 #ifdef SPEW_DEBUG
433 /* debug_yychar takes a yychar (token number) value and prints its name. */
435 static int
436 debug_yychar (yy)
437 int yy;
439 /* In parse.y: */
440 extern char *debug_yytranslate ();
442 int i;
444 if (yy<256) {
445 fprintf (stderr, "<%d: %c >\n", yy, yy);
446 return 0;
448 fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy));
449 return 1;
452 #endif