]> gcc.gnu.org Git - gcc.git/blob - gcc/cp/spew.c
decl.c: Lose arg_looking_for_template.
[gcc.git] / gcc / cp / spew.c
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)
4
5 This file is part of GNU CC.
6
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.
11
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.
16
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. */
21
22
23 /* This file is the type analyzer for GNU C++. To debug it, define SPEW_DEBUG
24 when compiling parse.c and spew.c. */
25
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"
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
38 backtracking. */
39
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;
46 };
47
48 static int do_aggr PROTO((void));
49 static int probe_obstack PROTO((struct obstack *, tree, unsigned int));
50 static void scan_tokens PROTO((int));
51
52 /* From lex.c: */
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. */
57 extern tree lastiddecl; /* let our brains leak out here too */
58 extern int yychar; /* the lookahead symbol */
59 extern YYSTYPE yylval; /* the semantic value of the */
60 /* lookahead symbol */
61 extern int end_of_file;
62
63 struct obstack token_obstack;
64 int first_token;
65
66 #ifdef SPEW_DEBUG
67 int spew_debug = 0;
68 static unsigned int yylex_ctr = 0;
69 static int debug_yychar ();
70 #endif
71
72 /* Initialize token_obstack. Called once, from init_lex. */
73
74 void
75 init_spew ()
76 {
77 gcc_obstack_init (&token_obstack);
78 }
79
80 #ifdef SPEW_DEBUG
81 /* Use functions for debugging... */
82
83 /* Return the number of tokens available on the fifo. */
84
85 static int
86 num_tokens ()
87 {
88 return (obstack_object_size (&token_obstack) / sizeof (struct token))
89 - first_token;
90 }
91
92 /* Fetch the token N down the line from the head of the fifo. */
93
94 static struct token*
95 nth_token (n)
96 int n;
97 {
98 /* could just have this do slurp_ implicitly, but this way is easier
99 to debug... */
100 my_friendly_assert (n < num_tokens (), 298);
101 return ((struct token*)obstack_base (&token_obstack)) + n + first_token;
102 }
103
104 /* Add a token to the token fifo. */
105
106 static void
107 add_token (t)
108 struct token* t;
109 {
110 obstack_grow (&token_obstack, t, sizeof (struct token));
111 }
112
113 /* Consume the next token out of the fifo. */
114
115 static void
116 consume_token ()
117 {
118 if (num_tokens () == 1)
119 {
120 obstack_free (&token_obstack, obstack_base (&token_obstack));
121 first_token = 0;
122 }
123 else
124 first_token++;
125 }
126
127 #else
128 /* ...otherwise use macros. */
129
130 #define num_tokens() \
131 ((obstack_object_size (&token_obstack) / sizeof (struct token)) - first_token)
132
133 #define nth_token(N) \
134 (((struct token*)obstack_base (&token_obstack))+(N)+first_token)
135
136 #define add_token(T) obstack_grow (&token_obstack, (T), sizeof (struct token))
137
138 #define consume_token() \
139 (num_tokens () == 1 \
140 ? (obstack_free (&token_obstack, obstack_base (&token_obstack)), \
141 (first_token = 0)) \
142 : first_token++)
143 #endif
144
145 /* Pull in enough tokens from real_yylex that the queue is N long beyond
146 the current token. */
147
148 static void
149 scan_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
168 while (num_tokens () <= n)
169 {
170 obstack_blank (&token_obstack, sizeof (struct token));
171 tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
172 tmp->yychar = real_yylex ();
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 {
183 obstack_blank (&token_obstack, sizeof (struct token));
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
192 /* Like _obstack_allocated_p, but stop after checking NLEVELS chunks. */
193
194 static int
195 probe_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
206 at the end of an adjacent chunk. */
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
216 /* from lex.c: */
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).
219 Value is 0 if we treat this name in a default fashion. */
220 extern int looking_for_typename;
221 int looking_for_template;
222 extern int do_snarf_defarg;
223
224 extern struct obstack *current_obstack, *saveable_obstack;
225 tree got_scope;
226 tree got_object;
227
228 int
229 peekyylex ()
230 {
231 scan_tokens (0);
232 return nth_token (0)->yychar;
233 }
234
235 int
236 yylex ()
237 {
238 struct token tmp_token;
239 tree trrr;
240
241 retry:
242 #ifdef SPEW_DEBUG
243 if (spew_debug)
244 {
245 yylex_ctr ++;
246 fprintf (stderr, "\t\t## %d ##", yylex_ctr);
247 }
248 #endif
249
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
260 /* if we've got tokens, send them */
261 else if (num_tokens ())
262 {
263 tmp_token= *nth_token (0);
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;
281 add_token (&tmp_token);
282 }
283
284 /* many tokens just need to be returned. At first glance, all we
285 have to do is send them back up, but some of them are needed to
286 figure out local context. */
287 switch (tmp_token.yychar)
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:
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++;
303 else if (nth_token (1)->yychar == '<')
304 looking_for_template = 1;
305
306 trrr = lookup_name (tmp_token.yylval.ttype, -2);
307
308 if (trrr)
309 {
310 tmp_token.yychar = identifier_type (trrr);
311 switch (tmp_token.yychar)
312 {
313 case TYPENAME:
314 case SELFNAME:
315 case NSNAME:
316 lastiddecl = trrr;
317 if (got_scope)
318 tmp_token.yylval.ttype = trrr;
319 break;
320
321 case PFUNCNAME:
322 case IDENTIFIER:
323 case PTYPENAME:
324 lastiddecl = trrr;
325 break;
326
327 default:
328 my_friendly_abort (101);
329 }
330 }
331 else
332 lastiddecl = trrr;
333 got_scope = NULL_TREE;
334 /* and fall through to... */
335 case IDENTIFIER_DEFN:
336 case TYPENAME:
337 case TYPENAME_DEFN:
338 case PTYPENAME:
339 case PTYPENAME_DEFN:
340 consume_token ();
341 if (looking_for_typename > 0)
342 looking_for_typename--;
343 looking_for_template = 0;
344 break;
345
346 case SCSPEC:
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;
351 break;
352
353 case TYPESPEC:
354 consume_token ();
355 break;
356
357 case AGGR:
358 *nth_token (0) = tmp_token;
359 do_aggr ();
360 /* fall through to output... */
361 case ENUM:
362 /* Set this again, in case we are rescanning. */
363 looking_for_typename = 1;
364 /* fall through... */
365 default:
366 consume_token ();
367 }
368
369 got_object = NULL_TREE;
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
377
378 return yychar;
379 }
380
381 /* token[0] == AGGR (struct/union/enum)
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
387 static int
388 do_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 {
399 /* It's a forward declaration iff we were not preceded by
400 'friend' or `new'. */
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 }
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 }
429
430 #ifdef SPEW_DEBUG
431 /* debug_yychar takes a yychar (token number) value and prints its name. */
432
433 static int
434 debug_yychar (yy)
435 int yy;
436 {
437 /* In parse.y: */
438 extern char *debug_yytranslate ();
439
440 int i;
441
442 if (yy<256) {
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.051949 seconds and 5 git commands to generate.