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