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)
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. */
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
40 /* fifo of tokens recognized and available to parser. */
42 /* The values for YYCHAR will fit in a short. */
48 static int do_aggr ();
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;
66 static unsigned int yylex_ctr = 0;
67 static int debug_yychar ();
70 /* Initialize token_obstack. Called once, from init_lex. */
75 gcc_obstack_init (&token_obstack);
79 /* Use functions for debugging... */
81 /* Return the number of tokens available on the fifo. */
86 return (obstack_object_size (&token_obstack) / sizeof (struct token))
90 /* Fetch the token N down the line from the head of the fifo. */
96 /* could just have this do slurp_ implicitly, but this way is easier
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. */
108 obstack_grow (&token_obstack, t, sizeof (struct token));
111 /* Consume the next token out of the fifo. */
116 if (num_tokens () == 1)
118 obstack_free (&token_obstack, obstack_base (&token_obstack));
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)), \
143 /* Pull in enough tokens from real_yylex that the queue is N long beyond
144 the current token. */
153 /* We cannot read past certain tokens, so make sure we don't. */
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 == ';')
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;
174 if (tmp->yychar == '{'
175 || tmp->yychar == ':'
176 || tmp->yychar == ';')
179 while (num_tokens () <= n)
181 obstack_blank (&token_obstack, sizeof (struct token));
182 tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
184 tmp->end_of_file = 0;
191 probe_obstack (h, obj, nlevels)
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 */
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);
209 return nlevels != 0 && lp != 0;
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;
219 extern struct obstack *current_obstack, *saveable_obstack;
227 return nth_token (0)->yychar;
233 struct token tmp_token;
241 fprintf (stderr, "\t\t## %d ##", yylex_ctr);
245 /* if we've got tokens, send them */
248 tmp_token= *nth_token (0);
250 /* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack.
251 If we don't find it in CURRENT_OBSTACK's current or immediately
252 previous chunk, assume it was and copy it to the current obstack. */
253 if ((tmp_token.yychar == CONSTANT
254 || tmp_token.yychar == STRING)
255 && ! TREE_PERMANENT (tmp_token.yylval.ttype)
256 && ! probe_obstack (current_obstack, tmp_token.yylval.ttype, 2)
257 && ! probe_obstack (saveable_obstack, tmp_token.yylval.ttype, 2))
258 tmp_token.yylval.ttype = copy_node (tmp_token.yylval.ttype);
262 /* if not, grab the next one and think about it */
263 tmp_token.yychar = real_yylex ();
264 tmp_token.yylval = yylval;
265 tmp_token.end_of_file = end_of_file;
266 add_token (&tmp_token);
269 /* many tokens just need to be returned. At first glance, all we
270 have to do is send them back up, but some of them are needed to
271 figure out local context. */
272 switch (tmp_token.yychar)
275 /* This is a lexical no-op. */
279 debug_yychar (tmp_token.yychar);
285 if (nth_token (1)->yychar == SCOPE)
286 /* Don't interfere with the setting from an 'aggr' prefix. */
287 looking_for_typename++;
288 else if (nth_token (1)->yychar == '<')
289 looking_for_template = 1;
291 trrr = lookup_name (tmp_token.yylval.ttype, -2);
295 tmp_token.yychar = identifier_type (trrr);
296 switch (tmp_token.yychar)
300 lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype);
301 if (lastiddecl != trrr)
305 tmp_token.yylval.ttype = trrr;
312 lastiddecl = NULL_TREE;
317 tmp_token.yylval.ttype = trrr;
320 my_friendly_abort (101);
325 got_scope = NULL_TREE;
326 /* and fall through to... */
327 case IDENTIFIER_DEFN:
333 if (looking_for_typename > 0)
334 looking_for_typename--;
335 looking_for_template = 0;
340 /* do_aggr needs to check if the previous token was RID_NEW,
341 so just increment first_token instead of calling consume_token. */
350 *nth_token (0) = tmp_token;
352 /* fall through to output... */
354 /* Set this again, in case we are rescanning. */
355 looking_for_typename = 1;
356 /* fall through... */
361 got_object = NULL_TREE;
362 yylval = tmp_token.yylval;
363 yychar = tmp_token.yychar;
364 end_of_file = tmp_token.end_of_file;
367 debug_yychar (yychar);
372 /* token[0] == AGGR (struct/union/enum)
373 Thus, token[1] is either a TYPENAME or a TYPENAME_DEFN.
374 If token[2] == '{' or ':' then it's TYPENAME_DEFN.
375 It's also a definition if it's a forward declaration (as in 'struct Foo;')
376 which we can tell if token[2] == ';' *and* token[-1] != FRIEND or NEW. */
384 yc1 = nth_token (1)->yychar;
385 if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME)
387 yc2 = nth_token (2)->yychar;
390 /* It's a forward declaration iff we were not preceded by
391 'friend' or `new'. */
394 if (nth_token (-1)->yychar == SCSPEC
395 && nth_token (-1)->yylval.ttype == ridpointers[(int) RID_FRIEND])
397 if (nth_token (-1)->yychar == NEW)
401 else if (yc2 != '{' && yc2 != ':')
407 nth_token (1)->yychar = TYPENAME_DEFN;
410 nth_token (1)->yychar = PTYPENAME_DEFN;
413 nth_token (1)->yychar = IDENTIFIER_DEFN;
416 my_friendly_abort (102);
422 /* debug_yychar takes a yychar (token number) value and prints its name. */
429 extern char *debug_yytranslate ();
434 fprintf (stderr, "<%d: %c >\n", yy, yy);
437 fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy));