Commit | Line | Data |
---|---|---|
e7dce25e C |
1 | /* Type Analyzer for GNU C++. |
2 | Copyright (C) 1987, 1989, 1992 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, 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 | |
23 | when compiling cp-parse.c and cp-spew.c. */ | |
24 | ||
25 | #include "config.h" | |
26 | #include <stdio.h> | |
27 | #include "input.h" | |
28 | #include "tree.h" | |
29 | #include "cp-lex.h" | |
30 | #include "cp-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. */ | |
40 | struct token { | |
41 | /* The values for YYCHAR will fit in a short. */ | |
42 | short yychar; | |
43 | short end_of_file; | |
44 | YYSTYPE yylval; | |
45 | }; | |
46 | ||
47 | static int do_aggr (); | |
48 | static struct token frob_identifier (); | |
49 | static struct token hack_scope (); | |
50 | static tree hack_ptype (); | |
51 | static tree hack_more_ids (); | |
52 | ||
53 | /* From cp-lex.c: */ | |
54 | /* the declaration found for the last IDENTIFIER token read in. | |
55 | yylex must look this up to detect typedefs, which get token type TYPENAME, | |
56 | so it is left around in case the identifier is not a typedef but is | |
57 | used in a context which makes it a reference to a variable. */ | |
58 | extern tree lastiddecl; /* let our brains leak out here too */ | |
59 | extern int yychar; /* the lookahead symbol */ | |
60 | extern YYSTYPE yylval; /* the semantic value of the */ | |
61 | /* lookahead symbol */ | |
62 | extern int end_of_file; | |
63 | ||
64 | struct obstack token_obstack; | |
65 | int first_token; | |
66 | ||
67 | #ifdef SPEW_DEBUG | |
68 | int spew_debug = 0; | |
69 | static unsigned int yylex_ctr = 0; | |
70 | static int debug_yychar (); | |
71 | #endif | |
72 | ||
73 | static char follows_typename[END_OF_SAVED_INPUT+1]; | |
74 | static char follows_identifier[END_OF_SAVED_INPUT+1]; | |
75 | ||
76 | /* This is a hack!!! TEMPLATE_TYPE_SEEN_BEFORE_SCOPE consists of the name | |
77 | * of the last template_type parsed in cp-parse.y if it is followed by a | |
78 | * scope operator. It will be reset inside the next invocation of yylex(). | |
79 | * This is used for recognizing nested types inside templates. | |
80 | * - niklas@appli.se */ | |
81 | tree template_type_seen_before_scope; | |
82 | ||
83 | /* Initialize token_obstack. Called once, from init_lex. */ | |
84 | void | |
85 | init_spew () | |
86 | { | |
87 | static char *chars_following_identifier = ".+-|/%^!?:"; | |
88 | short *ps; | |
89 | static short toks_follow_ids[] = | |
90 | { POINTSAT_LEFT_RIGHT, ASSIGN, RANGE, OROR, ANDAND, MIN_MAX, EQCOMPARE, | |
91 | ARITHCOMPARE, LSHIFT, RSHIFT, UNARY, PLUSPLUS, MINUSMINUS, POINTSAT, | |
92 | POINTSAT_STAR, DOT_STAR, CONSTANT, STRING, SIZEOF, ENUM, IF, | |
93 | ELSE, WHILE, DO, FOR, SWITCH, CASE, DEFAULT, BREAK, CONTINUE, | |
94 | RETURN, GOTO, ASM_KEYWORD, TYPEOF, ALIGNOF, HEADOF, CLASSOF, ATTRIBUTE, | |
95 | AGGR, VISSPEC, DELETE, RAISE, RERAISE, TRY, EXCEPT, CATCH, | |
96 | THROW, ANSI_TRY, ANSI_THROW, EXTERN_LANG_STRING, ALL, | |
97 | END_OF_SAVED_INPUT, -1 }; | |
98 | static short toks_follow_types[] = | |
99 | { IDENTIFIER, TYPENAME, SCOPED_TYPENAME, SCSPEC, TYPESPEC, TYPE_QUAL, | |
100 | ELLIPSIS, THIS, OPERATOR, DYNAMIC, TEMPLATE, SCOPE, START_DECLARATOR, | |
101 | TYPENAME_COLON, PAREN_STAR_PAREN, TYPENAME_ELLIPSIS, PTYPENAME, | |
102 | PRE_PARSED_FUNCTION_DECL, PRE_PARSED_CLASS_DECL, -1 }; | |
103 | ||
104 | gcc_obstack_init(&token_obstack); | |
105 | ||
106 | /* Initialize the arrays saying what tokens are definitely | |
107 | (or possibly) valid following typenames and identifiers. */ | |
108 | while (*chars_following_identifier) | |
109 | follows_identifier[*chars_following_identifier++] = 1; | |
110 | for (ps = toks_follow_ids; *ps != -1; ps++) | |
111 | follows_identifier[*ps] = 1; | |
112 | for (ps = toks_follow_types; *ps != -1; ps++) | |
113 | follows_typename[*ps] = 1; | |
114 | } | |
115 | ||
116 | #ifdef SPEW_DEBUG | |
117 | /* Use functions for debugging... */ | |
118 | ||
119 | /* Return the number of tokens available on the fifo. */ | |
120 | static int | |
121 | num_tokens () | |
122 | { | |
123 | return (obstack_object_size(&token_obstack)/sizeof(struct token)) | |
124 | - first_token; | |
125 | } | |
126 | ||
127 | /* Fetch the token N down the line from the head of the fifo. */ | |
128 | static struct token* | |
129 | nth_token (n) | |
130 | int n; | |
131 | { | |
132 | /* could just have this do slurp_ implicitly, but this way is easier | |
133 | * to debug... */ | |
134 | my_friendly_assert (n < num_tokens(), 298); | |
135 | return ((struct token*)obstack_base(&token_obstack))+n+first_token; | |
136 | } | |
137 | ||
138 | /* Add a token to the token fifo. */ | |
139 | static void | |
140 | add_token (t) | |
141 | struct token* t; | |
142 | { | |
143 | obstack_grow(&token_obstack,t,sizeof (struct token)); | |
144 | } | |
145 | ||
146 | /* Consume the next token out of the fifo. */ | |
147 | static void | |
148 | consume_token() | |
149 | { | |
150 | if (num_tokens() == 1) | |
151 | { | |
152 | obstack_free(&token_obstack, obstack_base (&token_obstack)); | |
153 | first_token = 0; | |
154 | } | |
155 | else | |
156 | first_token++; | |
157 | } | |
158 | ||
159 | #else | |
160 | /* ...otherwise use macros. */ | |
161 | ||
162 | #define num_tokens() \ | |
163 | ((obstack_object_size(&token_obstack)/sizeof(struct token)) - first_token) | |
164 | ||
165 | #define nth_token(N) \ | |
166 | (((struct token*)obstack_base(&token_obstack))+(N)+first_token) | |
167 | ||
168 | #define add_token(T) obstack_grow(&token_obstack, (T), sizeof (struct token)) | |
169 | ||
170 | #define consume_token() \ | |
171 | (num_tokens() == 1 \ | |
172 | ? (obstack_free (&token_obstack, obstack_base (&token_obstack)), \ | |
173 | (first_token = 0)) \ | |
174 | : first_token++) | |
175 | #endif | |
176 | ||
177 | /* Pull in enough tokens from real_yylex that the queue is N long. */ | |
178 | ||
179 | static void | |
180 | scan_tokens (n) | |
181 | int n; | |
182 | { | |
183 | int i; | |
184 | struct token *tmp; | |
185 | ||
186 | /* We cannot read past certain tokens, so make sure we don't. */ | |
187 | i = num_tokens (); | |
188 | if (i > n) | |
189 | return; | |
190 | while (i-- > 0) | |
191 | { | |
192 | tmp = nth_token (i); | |
193 | /* Never read past these characters: they might separate | |
194 | the current input stream from one we save away later. */ | |
195 | if (tmp->yychar == '{' || tmp->yychar == ':') | |
196 | goto pad_tokens; | |
197 | } | |
198 | ||
199 | while (num_tokens() <= n) | |
200 | { | |
201 | obstack_blank(&token_obstack,sizeof (struct token)); | |
202 | tmp = ((struct token *)obstack_next_free (&token_obstack))-1; | |
203 | tmp->yychar = real_yylex(); | |
204 | tmp->end_of_file = end_of_file; | |
205 | tmp->yylval = yylval; | |
206 | end_of_file = 0; | |
207 | if (tmp->yychar == '{' | |
208 | || tmp->yychar == ':' | |
209 | || tmp->yychar == ';') | |
210 | { | |
211 | pad_tokens: | |
212 | while (num_tokens () <= n) | |
213 | { | |
214 | obstack_blank(&token_obstack,sizeof (struct token)); | |
215 | tmp = ((struct token *)obstack_next_free (&token_obstack))-1; | |
216 | tmp->yychar = EMPTY; | |
217 | tmp->end_of_file = 0; | |
218 | } | |
219 | } | |
220 | } | |
221 | } | |
222 | ||
223 | /* Create room for N tokens at the front of the fifo. This is used | |
224 | to insert new tokens into the stream ahead of the current token. */ | |
225 | ||
226 | static void | |
227 | shift_tokens (n) | |
228 | int n; | |
229 | { | |
230 | if (first_token >= n) | |
231 | first_token -= n; | |
232 | else | |
233 | { | |
234 | int old_token_count = num_tokens (); | |
235 | char *tmp; | |
236 | ||
237 | obstack_blank (&token_obstack, (n-first_token) * sizeof (struct token)); | |
238 | if (old_token_count) | |
239 | { | |
240 | tmp = (char *)alloca ((num_tokens () + (n-first_token)) | |
241 | * sizeof (struct token)); | |
242 | /* This move does not rely on the system being able to handle | |
243 | overlapping moves. */ | |
244 | bcopy (nth_token (0), tmp, old_token_count * sizeof (struct token)); | |
245 | bcopy (tmp, nth_token (n), old_token_count * sizeof (struct token)); | |
246 | } | |
247 | first_token = 0; | |
248 | } | |
249 | } | |
250 | ||
251 | int | |
252 | probe_obstack (h, obj, nlevels) | |
253 | struct obstack *h; | |
254 | tree obj; | |
255 | unsigned int nlevels; | |
256 | { | |
257 | register struct _obstack_chunk* lp; /* below addr of any objects in this chunk */ | |
258 | register struct _obstack_chunk* plp; /* point to previous chunk if any */ | |
259 | ||
260 | lp = (h)->chunk; | |
261 | /* We use >= rather than > since the object cannot be exactly at | |
262 | the beginning of the chunk but might be an empty object exactly | |
263 | at the end of an adjacent chunk. */ | |
264 | for (; nlevels > 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj); | |
265 | nlevels -= 1) | |
266 | { | |
267 | plp = lp->prev; | |
268 | lp = plp; | |
269 | } | |
270 | return nlevels > 0 && lp != 0; | |
271 | } | |
272 | ||
273 | /* from cp-lex.c: */ | |
274 | /* Value is 1 if we should try to make the next identifier look like a | |
275 | typename (when it may be a local variable or a class variable). | |
276 | Value is 0 if we treat this name in a default fashion. | |
277 | Value is -1 if we must not see a type name. */ | |
278 | extern int looking_for_typename; | |
279 | ||
280 | extern struct obstack *current_obstack, *saveable_obstack; | |
281 | ||
282 | int | |
283 | yylex() | |
284 | { | |
285 | struct token tmp_token; | |
286 | tree trrr; | |
287 | ||
288 | retry: | |
289 | #ifdef SPEW_DEBUG | |
290 | if (spew_debug) | |
291 | { | |
292 | yylex_ctr ++; | |
293 | fprintf(stderr, "\t\t## %d ##",yylex_ctr); | |
294 | } | |
295 | #endif | |
296 | ||
297 | /* This is a kludge for recognizing nested types in templates */ | |
298 | if (template_type_seen_before_scope) | |
299 | { | |
300 | shift_tokens (2); /* Sync in hack_more_ids (yes, it's ugly) */ | |
301 | nth_token (1)->yychar = SCOPE; | |
302 | yylval.ttype = hack_more_ids (0, template_type_seen_before_scope); | |
303 | template_type_seen_before_scope = 0; | |
304 | if (!yylval.ttype) | |
305 | { | |
306 | /* Sync back again, leaving SCOPE on the token stream, because we | |
307 | * failed to substitute the original SCOPE token with a | |
308 | * SCOPED_TYPENAME. See rule "template_type" in cp-parse.y */ | |
309 | consume_token (); | |
310 | } | |
311 | else | |
312 | { | |
313 | yychar = SCOPED_TYPENAME; | |
314 | #ifdef SPEW_DEBUG | |
315 | if (spew_debug) | |
316 | debug_yychar(yychar); | |
317 | #endif | |
318 | return yychar; | |
319 | } | |
320 | } | |
321 | ||
322 | /* if we've got tokens, send them */ | |
323 | if (num_tokens()) | |
324 | { | |
325 | tmp_token= *nth_token(0); | |
326 | ||
327 | /* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack. | |
328 | If we don't find it in CURRENT_OBSTACK's current or immediately | |
329 | previous chunk, assume it was and copy it to the current obstack. */ | |
330 | if ((tmp_token.yychar == CONSTANT | |
331 | || tmp_token.yychar == STRING) | |
332 | && ! TREE_PERMANENT (tmp_token.yylval.ttype) | |
333 | && ! probe_obstack (current_obstack, tmp_token.yylval.ttype, 2) | |
334 | && ! probe_obstack (saveable_obstack, tmp_token.yylval.ttype, 2)) | |
335 | tmp_token.yylval.ttype = copy_node (tmp_token.yylval.ttype); | |
336 | } | |
337 | else | |
338 | { | |
339 | /* if not, grab the next one and think about it */ | |
340 | tmp_token.yychar = real_yylex (); | |
341 | tmp_token.yylval = yylval; | |
342 | tmp_token.end_of_file = end_of_file; | |
343 | add_token(&tmp_token); | |
344 | } | |
345 | ||
346 | /* many tokens just need to be returned. At first glance, all we | |
347 | * have to do is send them back up, but some of them are needed to | |
348 | * figure out local context. */ | |
349 | switch(tmp_token.yychar) | |
350 | { | |
351 | case EMPTY: | |
352 | /* This is a lexical no-op. */ | |
353 | consume_token (); | |
354 | #ifdef SPEW_DEBUG | |
355 | if (spew_debug) | |
356 | debug_yychar (tmp_token.yychar); | |
357 | #endif | |
358 | goto retry; | |
359 | ||
360 | case IDENTIFIER: | |
361 | /* Note: this calls arbitrate_lookup. */ | |
362 | trrr = lookup_name (tmp_token.yylval.ttype, -1); | |
363 | if (trrr) | |
364 | { | |
365 | tmp_token.yychar = identifier_type (trrr); | |
366 | switch (tmp_token.yychar) | |
367 | { | |
368 | case TYPENAME: | |
369 | lastiddecl = IDENTIFIER_TYPEDECL_VALUE (tmp_token.yylval.ttype); | |
370 | break; | |
371 | case IDENTIFIER: | |
372 | lastiddecl = trrr; | |
373 | break; | |
374 | case PTYPENAME: | |
375 | /* This is for cases like | |
376 | template<class A> X<A>::operator[] ... | |
377 | since "X" is (presumably) a PTYPENAME; we might want to | |
378 | avoid seeing the entire thing as a type name, but X<A> | |
379 | must be one. | |
380 | ||
381 | It might not work right if the thing after the :: | |
382 | can be a typename nested in X<A>, but I don't think the | |
383 | PT code would be up to dealing with that anyways. --KR */ | |
384 | if (looking_for_typename == -1) | |
385 | { | |
386 | scan_tokens (2); | |
387 | if (nth_token(1)->yychar == '<') | |
388 | looking_for_typename = 0; | |
389 | } | |
390 | break; | |
391 | default: | |
392 | my_friendly_abort (101); | |
393 | } | |
394 | } | |
395 | else | |
396 | lastiddecl = trrr; | |
397 | /* and fall through to... */ | |
398 | case TYPENAME: | |
399 | case PTYPENAME: | |
400 | /* if (new_token) add_token (&tmp_token); */ | |
401 | *nth_token(0) = tmp_token; | |
402 | tmp_token = frob_identifier (); | |
403 | if (looking_for_typename < 0) | |
404 | { | |
405 | tmp_token.yychar = IDENTIFIER; | |
406 | lastiddecl = 0; | |
407 | looking_for_typename = 0; | |
408 | } | |
409 | else if (lastiddecl && TREE_CODE (lastiddecl) == TYPE_DECL) | |
410 | { | |
411 | scan_tokens (2); | |
412 | if (nth_token(0)->yychar == IDENTIFIER | |
413 | && nth_token (1)->yychar != SCOPE) | |
414 | looking_for_typename = -1; | |
415 | else | |
416 | looking_for_typename = 0; | |
417 | goto finish_typename_processing; | |
418 | } | |
419 | else | |
420 | looking_for_typename = 0; | |
421 | break; | |
422 | ||
423 | case TYPESPEC: | |
424 | case SCSPEC: | |
425 | consume_token (); | |
426 | finish_typename_processing: | |
427 | /* Now see if we should insert a START_DECLARATOR token. | |
428 | Here are the cases caught: | |
429 | ||
430 | typespec ( * ID ) ( // ptr to function | |
431 | typespec ( & ID ) ( // ref to function | |
432 | typespec ( * ID ) [ // array of pointers | |
433 | typespec ( & ID ) [ // array of references | |
434 | ||
435 | This is a terrible kludge. */ | |
436 | ||
437 | scan_tokens (2); | |
438 | if (nth_token (0)->yychar == '(' | |
439 | && (nth_token (1)->yychar == '*' | |
440 | || nth_token (1)->yychar == '&')) | |
441 | { | |
442 | scan_tokens (5); | |
443 | if (nth_token (3)->yychar == ')' | |
444 | && (nth_token (4)->yychar == '(' | |
445 | || nth_token (4)->yychar == '[' | |
446 | || nth_token (4)->yychar == LEFT_RIGHT) | |
447 | && (nth_token (2)->yychar == IDENTIFIER | |
448 | || nth_token (2)->yychar == TYPENAME)) | |
449 | { | |
450 | shift_tokens (1); | |
451 | nth_token (0)->yychar = START_DECLARATOR; | |
452 | } | |
453 | } | |
454 | break; | |
455 | ||
456 | #if 0 | |
457 | case '(': | |
458 | /* Handle casts. We are looking for one of: | |
459 | `( TYPENAME' followed by `)', or | |
460 | `( TYPENAME *' followed by one of `[,*,&,)', or | |
461 | `( TYPENAME &' followed by one of `[,*,&,)', or | |
462 | `( TYPENAME [' followed by `]'. We are punting | |
463 | generality on scanning casts to array types. */ | |
464 | scan_tokens (4); | |
465 | if (nth_token (1)->yychar == IDENTIFIER) | |
466 | { | |
467 | tree type = identifier_typedecl_value (nth_token (1)->yylval.ttype); | |
468 | if (type) | |
469 | switch (nth_token (2)->yychar) | |
470 | { | |
471 | default: | |
472 | break; | |
473 | } | |
474 | } | |
475 | break; | |
476 | ||
477 | case SCOPE: | |
478 | /* if (new_token) add_token (&tmp_token); */ | |
479 | *nth_token(0) = tmp_token; | |
480 | tmp_token = hack_scope (); | |
481 | break; | |
482 | #endif | |
483 | ||
484 | case AGGR: | |
485 | *nth_token(0) = tmp_token; | |
486 | do_aggr (); | |
487 | /* fall through to output... */ | |
488 | case ENUM: | |
489 | /* Set this again, in case we are rescanning. */ | |
490 | looking_for_typename = 1; | |
491 | /* fall through... */ | |
492 | default: | |
493 | #ifdef SPEW_DEBUG | |
494 | if (spew_debug) | |
495 | debug_yychar(tmp_token.yychar); | |
496 | #endif | |
497 | consume_token(); | |
498 | yylval = tmp_token.yylval; | |
499 | yychar = tmp_token.yychar; | |
500 | end_of_file = tmp_token.end_of_file; | |
501 | return tmp_token.yychar; | |
502 | } | |
503 | ||
504 | if (tmp_token.yychar == SCOPED_TYPENAME) | |
505 | { | |
506 | #if 0 | |
507 | tree t2 = resolve_scope_to_name (NULL_TREE, tmp_token.yylval.ttype); | |
508 | if (t2 != NULL_TREE) | |
509 | { | |
510 | tmp_token.yylval.ttype = t2; | |
511 | tmp_token.yychar = TYPENAME; | |
512 | } | |
513 | else | |
514 | { | |
515 | /* unwind? */ | |
516 | } | |
517 | } | |
518 | else | |
519 | { | |
520 | /* couldn't get here, as is... */ | |
521 | #endif | |
522 | tmp_token.yychar = TYPENAME; | |
523 | } | |
524 | ||
525 | yylval = tmp_token.yylval; | |
526 | yychar = tmp_token.yychar; | |
527 | end_of_file = tmp_token.end_of_file; | |
528 | #ifdef SPEW_DEBUG | |
529 | if (spew_debug) | |
530 | debug_yychar(yychar); | |
531 | #endif | |
532 | /* consume_token(); */ /* already eaten by frob_identifier?... */ | |
533 | return yychar; | |
534 | } | |
535 | ||
536 | /* token[0] == AGGR (struct/union/enum) | |
537 | * thus, token[1] is either a TYPENAME or a TYPENAME_DEFN | |
538 | * if token[2] == '{' or ':' then it's TYPENAME_DEFN | |
539 | */ | |
540 | static int | |
541 | do_aggr () | |
542 | { | |
543 | int yc1, yc2; | |
544 | ||
545 | scan_tokens (2); | |
546 | yc1 = nth_token (1)->yychar; | |
547 | if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME) | |
548 | return 0; | |
549 | yc2 = nth_token (2)->yychar; | |
550 | if (yc2 == '{' || yc2 == ':') | |
551 | { | |
552 | switch (yc1) | |
553 | { | |
554 | case TYPENAME: | |
555 | nth_token (1)->yychar = TYPENAME_DEFN; | |
556 | break; | |
557 | case PTYPENAME: | |
558 | nth_token (1)->yychar = PTYPENAME_DEFN; | |
559 | break; | |
560 | case IDENTIFIER: | |
561 | nth_token (1)->yychar = IDENTIFIER_DEFN; | |
562 | break; | |
563 | default: | |
564 | my_friendly_abort (102); | |
565 | } | |
566 | } | |
567 | return 0; | |
568 | } | |
569 | ||
570 | static struct token | |
571 | frob_identifier () | |
572 | { | |
573 | /* we could have a type, if it is followed by :: (if so, suck it all up); */ | |
574 | /* we could have a ptypename; */ | |
575 | /* we could have a normal identifier. */ | |
576 | tree t1; | |
577 | struct token rt; | |
578 | ||
579 | scan_tokens(1); | |
580 | rt = *nth_token(0); | |
581 | ||
582 | #if 0 | |
583 | if (nth_token(1)->yychar == '<') | |
584 | { | |
585 | t1 = hack_ptype(); /* suck up the whole thing */ | |
586 | if (t1) | |
587 | { | |
588 | rt.yylval.ttype = t1; | |
589 | rt.yychar = TYPENAME; | |
590 | *nth_token(0) = rt; | |
591 | } | |
592 | /* else fall out bottom */ | |
593 | } | |
594 | #endif | |
595 | ||
596 | if (nth_token(1)->yychar == SCOPE) | |
597 | { | |
598 | #if 0 | |
599 | t1 = hack_more_ids(0); | |
600 | if (t1 && TREE_CODE(t1) == SCOPE_REF) | |
601 | #else | |
602 | t1 = hack_more_ids(0, nth_token (0)->yylval.ttype); | |
603 | if (t1) | |
604 | #endif | |
605 | { | |
606 | rt.yylval.ttype = t1; | |
607 | rt.yychar = SCOPED_TYPENAME ; | |
608 | return rt; | |
609 | } | |
610 | else | |
611 | { | |
612 | /* deal with types (enums?) in classes... */ | |
613 | struct token *tok; | |
614 | tree ta, tb; | |
615 | scan_tokens(3); | |
616 | ||
617 | /* Have to check for a type conversion operator | |
618 | to a nested type. */ | |
619 | if (nth_token (2)->yychar == OPERATOR) | |
620 | tok = nth_token (3); | |
621 | else | |
622 | tok = nth_token(2); | |
623 | ||
624 | if (tok->yychar == IDENTIFIER || tok->yychar == TYPENAME) | |
625 | { | |
626 | ta = build_parse_node (SCOPE_REF, | |
627 | nth_token(0)->yylval.ttype, | |
628 | tok->yylval.ttype); | |
629 | tb = resolve_scope_to_name (NULL_TREE, ta); | |
630 | ||
631 | if (tb != NULL_TREE) | |
632 | { | |
633 | if (nth_token (2)->yychar == OPERATOR) | |
634 | { | |
635 | /* Have to keep these tokens around | |
636 | so we can finish parsing the declaration. | |
637 | What do we do for | |
638 | ||
639 | int foo::operator bar::baz (); | |
640 | ||
641 | where bar is a nested class in foo? */ | |
642 | nth_token (3)->yychar = TYPENAME; | |
643 | nth_token (3)->yylval.ttype = tb; | |
644 | } | |
645 | else | |
646 | { | |
647 | consume_token (); /* base type */ | |
648 | consume_token (); /* SCOPE */ | |
649 | consume_token (); /* member type */ | |
650 | rt.yychar = TYPENAME; | |
651 | rt.yylval.ttype = tb; | |
652 | rt.end_of_file = tok->end_of_file; | |
653 | return rt; | |
654 | } | |
655 | ||
656 | } | |
657 | } | |
658 | /* else fall out bottom */ | |
659 | } | |
660 | } | |
661 | ||
662 | consume_token(); | |
663 | return rt; | |
664 | } | |
665 | ||
666 | /* When this function is called, nth_token(0) is the current | |
667 | token we are scanning. This means that the next token we'll | |
668 | scan is nth_token (1). Usually the next token we'll scan | |
669 | is nth_token (0) (and the current token is in [yylval,yychar]). */ | |
670 | tree | |
671 | arbitrate_lookup (name, exp_decl, type_decl) | |
672 | tree name, exp_decl, type_decl; | |
673 | { | |
674 | int ch; | |
675 | ||
676 | scan_tokens (3); | |
677 | ch = nth_token (1)->yychar; | |
678 | ||
679 | switch (ch) | |
680 | { | |
681 | case '(': | |
682 | case LEFT_RIGHT: | |
683 | /* If we guessed wrong here, `build_functional_cast' can fix it. */ | |
684 | return type_decl; | |
685 | ||
686 | case '=': | |
687 | if (global_bindings_p ()) | |
688 | /* Probably a default parameter. */ | |
689 | return type_decl; | |
690 | /* Probably not an initialization. */ | |
691 | return exp_decl; | |
692 | ||
693 | case '[': | |
694 | /* This needs special help because an expression inside the | |
695 | brackets means nothing. */ | |
696 | { | |
697 | int i; | |
698 | ||
699 | for (i = 0; i < 42; i++) | |
700 | { | |
701 | int ith_yychar; | |
702 | ||
703 | scan_tokens (3+i); | |
704 | ith_yychar = nth_token (2+i)->yychar; | |
705 | ||
706 | /* If we hit an undefined identifier, assume | |
707 | the decl in arbitration is its type specifier. */ | |
708 | if (ith_yychar == IDENTIFIER | |
709 | && lookup_name (nth_token (2+i)->yylval.ttype, 0) == 0) | |
710 | return type_decl; | |
711 | else if (ith_yychar == ']') | |
712 | { | |
713 | /* There are only a few things we expect after a ']' | |
714 | in a declarator. */ | |
715 | i += 1; | |
716 | scan_tokens (4+i); | |
717 | ith_yychar = nth_token (2+i)->yychar; | |
718 | ||
719 | /* These are inconclusive. */ | |
720 | if (ith_yychar == LEFT_RIGHT | |
721 | || ith_yychar == '(' | |
722 | || ith_yychar == '[' | |
723 | || ith_yychar == ',') | |
724 | continue; | |
725 | /* stmt or decl? We'll probably never know. */ | |
726 | else if (ith_yychar == ';') | |
727 | goto warn_ambiguous; | |
728 | ||
729 | if (ith_yychar == '=') | |
730 | { | |
731 | if (nth_token (3+i)->yychar == '{') | |
732 | return type_decl; | |
733 | continue; | |
734 | } | |
735 | ||
736 | /* Whatever it is, it looks like we're processing an expr. */ | |
737 | return exp_decl; | |
738 | } | |
739 | } | |
740 | goto warn_ambiguous; | |
741 | } | |
742 | ||
743 | case ',': | |
744 | case ';': | |
745 | case '&': | |
746 | case '<': | |
747 | case '*': | |
748 | case ']': | |
749 | case ')': | |
750 | case '>': | |
751 | /* see if the next token looks like it wants to be part | |
752 | of a declaration list or an expression list. */ | |
753 | { | |
754 | int i; | |
755 | ||
756 | /* Some heuristics: if we are inside a function definition, | |
757 | prefer the local declaration. */ | |
758 | if (! global_bindings_p ()) | |
759 | { | |
760 | if (IDENTIFIER_LOCAL_VALUE (name) == exp_decl) | |
761 | return exp_decl; | |
762 | if (IDENTIFIER_LOCAL_VALUE (name) != type_decl | |
763 | && IDENTIFIER_CLASS_VALUE (name) == exp_decl) | |
764 | return exp_decl; | |
765 | } | |
766 | /* If these symbols follow in a list, we know it's a list of | |
767 | expressions. */ | |
768 | if (follows_identifier[nth_token (2)->yychar]) | |
769 | return exp_decl; | |
770 | ||
771 | /* If we see a id&, or id&) the we are probably in an argument list. */ | |
772 | if (ch=='&' | |
773 | && (nth_token (2)->yychar == ',' || nth_token (2)->yychar == ')')) | |
774 | return type_decl; | |
775 | ||
776 | /* Look for the first identifier or other distinguishing token | |
777 | we find in the next several tokens. */ | |
778 | for (i = 0; i < 42; i++) | |
779 | { | |
780 | int ith_yychar; | |
781 | ||
782 | scan_tokens (3+i); | |
783 | ith_yychar = nth_token (2+i)->yychar; | |
784 | ||
785 | if (ith_yychar == IDENTIFIER) | |
786 | { | |
787 | tree as_type = lookup_name (nth_token (2+i)->yylval.ttype, 1); | |
788 | if (as_type && TREE_CODE (as_type) != TYPE_DECL) | |
789 | return exp_decl; | |
790 | /* An undeclared identifier or a typename means we're | |
791 | probably looking at a typename. */ | |
792 | return type_decl; | |
793 | } | |
794 | else if (ith_yychar == EMPTY | |
795 | || follows_identifier[ith_yychar]) | |
796 | return exp_decl; | |
797 | else if (follows_typename[ith_yychar]) | |
798 | return type_decl; | |
799 | /* stmt or decl? We'll probably never know. */ | |
800 | else if (ith_yychar == ';') | |
801 | goto warn_ambiguous; | |
802 | } | |
803 | goto warn_ambiguous; | |
804 | } | |
805 | ||
806 | default: | |
807 | if (follows_identifier[ch]) | |
808 | return exp_decl; | |
809 | if (follows_typename[ch]) | |
810 | return type_decl; | |
811 | ||
812 | /* Fall through... */ | |
813 | warn_ambiguous: | |
814 | warning ("name `%s' could be type or expression; compiler assuming type", | |
815 | IDENTIFIER_POINTER (DECL_NAME (type_decl))); | |
816 | return type_decl; | |
817 | } | |
818 | } | |
819 | ||
820 | /* now returns decl_node */ | |
821 | ||
822 | #if 0 | |
823 | static tree | |
824 | hack_ptype() | |
825 | { | |
826 | /* when we get here, we know that [0] is a ptype and [1] is '<'. | |
827 | * now we loop over simple parameters. */ | |
828 | struct token this_param; | |
829 | int n = 2; | |
830 | tree tplist = 0; | |
831 | tree tc; | |
832 | scan_tokens(n+1); | |
833 | ||
834 | while((this_param = *nth_token(n)).yychar != '>') | |
835 | { | |
836 | /* if it is a type, add it to the list */ | |
837 | tree thistype; | |
838 | ||
839 | switch(this_param.yychar) | |
840 | { | |
841 | case IDENTIFIER: | |
842 | case TYPENAME: | |
843 | case TYPESPEC: | |
844 | break; | |
845 | default: | |
846 | return 0; | |
847 | } | |
848 | ||
849 | thistype = this_param.yylval.ttype; | |
850 | thistype = lookup_name(thistype, 1); | |
851 | thistype = TREE_TYPE (thistype); | |
852 | ||
853 | if (tplist) | |
854 | tplist = chainon (tplist, build_tree_list (NULL_TREE, thistype)); | |
855 | else | |
856 | tplist = build_tree_list(NULL_TREE, thistype); | |
857 | ||
858 | ||
859 | /* then suck up the comma */ | |
860 | n++; | |
861 | scan_tokens(n+1); | |
862 | this_param = *nth_token(n); | |
863 | if (this_param.yychar == ',') | |
864 | { | |
865 | n++; | |
866 | scan_tokens(n+1); | |
867 | continue; | |
868 | } | |
869 | if (this_param.yychar == '>') | |
870 | break; | |
871 | return 0; | |
872 | } | |
873 | ||
874 | /* once we're done, lookup_template_class -> identifier */ | |
875 | tc = lookup_template_class (nth_token(0)->yylval.ttype,tplist); | |
876 | /* then lookup_name on that to get a type, if there is one */ | |
877 | tc = lookup_name (tc, 1); | |
878 | if (tc) | |
879 | { | |
880 | int i; | |
881 | /* don't actually eat the trailing '>'... we can replace it! */ | |
882 | for (i=0; i<n; i++) | |
883 | consume_token(); | |
884 | /* IDENTIFIER_TYPE_VALUE (DECL_NAME (tc)) = */ | |
885 | return DECL_NAME (tc); | |
886 | } | |
887 | return NULL_TREE; | |
888 | } | |
889 | #endif | |
890 | ||
891 | #if 0 | |
892 | static tree | |
893 | hack_more_ids (n) | |
894 | int n; | |
895 | { | |
896 | /* | |
897 | * The recursion should probably do consume_tokens(), since once we've started | |
898 | * down an IDENTIFIER SCOPE ... chain, we don't need to back-track - we just | |
899 | * get as much as we can, make SCOPE_REF's out of it, and return it. | |
900 | */ | |
901 | struct token this_iter, this2_iter; | |
902 | int tmp_y; | |
903 | ||
904 | scan_tokens(n+1); | |
905 | this_iter = *nth_token(n); | |
906 | ||
907 | tmp_y = nth_token(n)->yychar; | |
908 | if (tmp_y == IDENTIFIER || tmp_y == TYPENAME) | |
909 | { | |
910 | scan_tokens(n+2+2); | |
911 | if (nth_token(n+1)->yychar == SCOPE) | |
912 | { | |
913 | if (nth_token(n+1+2)->yychar == SCOPE) | |
914 | { | |
915 | tree hmi; | |
916 | ||
917 | consume_token(); /* last IDENTIFIER (this_iter) */ | |
918 | consume_token(); /* last SCOPE */ | |
919 | this2_iter = *nth_token(n); | |
920 | ||
921 | hmi = hack_more_ids (n); | |
922 | ||
923 | if (hmi) | |
924 | return build_parse_node (SCOPE_REF, this_iter.yylval.ttype, hmi); | |
925 | consume_token(); /* last IDENTIFIER (this2_iter) */ | |
926 | return build_parse_node (SCOPE_REF, this_iter.yylval.ttype, | |
927 | this2_iter.yylval.ttype); | |
928 | } | |
929 | else | |
930 | { | |
931 | /* consume_token(); */ /* last IDENTIFIER */ | |
932 | /* leave whatever else we got */ | |
933 | /* return this_iter.yylval.ttype; */ | |
934 | return NULL_TREE; | |
935 | } | |
936 | } | |
937 | } | |
938 | return NULL_TREE; /* @@ may need to backtrack */ | |
939 | } | |
940 | #else | |
941 | /* niklas@appli.se says: I didn't understand how the code above was intended | |
942 | * to work, so I rewrote it (also changed the interface a bit). This code | |
943 | * dives down an IDENTIFIER/TYPENAME SCOPE ... chain as long as the parsed | |
944 | * type prefix constitutes recognizable (by resolve_scope_to_name) types. | |
945 | * Interface changed like this: | |
946 | * 1. Takes an extra argument containing the name of the the type recognized | |
947 | * so far. | |
948 | * 2. Now returns the name of the type instead of a SCOPE_REF. */ | |
949 | static tree | |
950 | hack_more_ids(n, outer) | |
951 | int n; | |
952 | tree outer; | |
953 | { | |
954 | int ch; | |
955 | tree type, val; | |
956 | ||
957 | scan_tokens (n + 2); | |
958 | if (nth_token (n + 1)->yychar != SCOPE | |
959 | || ((ch = nth_token (n + 2)->yychar) != IDENTIFIER && ch != TYPENAME)) | |
960 | return NULL_TREE; | |
961 | val = build_parse_node (SCOPE_REF, outer, nth_token (n + 2)->yylval.ttype); | |
962 | type = resolve_scope_to_name (NULL_TREE, val); | |
963 | if (type == NULL_TREE) | |
964 | return NULL_TREE; | |
965 | consume_token (); | |
966 | consume_token (); | |
967 | val = hack_more_ids (n, type); | |
968 | if (! val) | |
969 | consume_token (); | |
970 | return val ? val : type; | |
971 | } | |
972 | #endif | |
973 | ||
974 | #if 0 | |
975 | static struct token | |
976 | hack_scope () | |
977 | { | |
978 | /* we've got a :: - what follows is either a global var or a type. */ | |
979 | /* hmm, template names can be in the global scope too... */ | |
980 | tree t1; | |
981 | struct token rt; | |
982 | ||
983 | scan_tokens(1); | |
984 | if (nth_token(1)->yychar == IDENTIFIER) | |
985 | { | |
986 | /* @@ this is probably not right, but doesn't get hit yet */ | |
987 | t1 = build_parse_node (SCOPE_REF, | |
988 | NULL_TREE, /* to get "global" scope */ | |
989 | hack_more_ids(0)); /* do some prefetching */ | |
990 | rt.yylval.ttype = t1; | |
991 | rt.yychar = /*SCOPED_*/TYPENAME; | |
992 | return rt; | |
993 | } | |
994 | else | |
995 | { | |
996 | rt = *nth_token(0); | |
997 | consume_token(); | |
998 | return rt; | |
999 | } | |
1000 | } | |
1001 | #endif | |
1002 | ||
1003 | /* | |
1004 | * Generations: | |
1005 | * | |
1006 | * PINST: PTYPE { saved_arg_count = arg_count($1) } | |
1007 | * '<' { arg_c = 0; } PARGS '>' | |
1008 | * ; | |
1009 | * PARG: TYPE | |
1010 | * | VALUE | |
1011 | * ; | |
1012 | * (of course the arg counting doesn't work for recursion... Do it right.) | |
1013 | * PARGS: PARG { assert(arg_c == saved_arg_count); } | |
1014 | * | PARG ',' PARGS { arg_c++; } | |
1015 | * ; | |
1016 | * ATYPE: PINST | |
1017 | * | TYPEID | |
1018 | * ; | |
1019 | * TYPE: ATYPE | |
1020 | * | ATYPE { basetype = $1; } '::' TYPEKIDS | |
1021 | * ; | |
1022 | * TYPEKIDS: TYPE { assert ($1 is a member of basetype); } | |
1023 | * | TYPEKIDS { basetype += $1} TYPE { assert( $3 is in basetype ); } | |
1024 | * ; | |
1025 | * | |
1026 | * | |
1027 | * state0: ; ATYPE | |
1028 | * TYPE '<': ac = args($0), base = CALL state1, state3 | |
1029 | * TYPE '::': base=$0, state3 | |
1030 | * else return TYPE | |
1031 | * state1: ; begin PARGS | |
1032 | * if(ac < list length) punt | |
1033 | * PARG ",": add to list, state1 | |
1034 | * PARG ">": add to list, return | |
1035 | * else unravel | |
1036 | * state3: ; begin TYPEKIDS | |
1037 | * TYPE: | |
1038 | */ | |
1039 | ||
1040 | ||
1041 | #ifdef SPEW_DEBUG | |
1042 | /* debug_yychar takes a yychar (token number) value and prints its name. */ | |
1043 | static int | |
1044 | debug_yychar (yy) | |
1045 | int yy; | |
1046 | { | |
1047 | /* In cp-parse.y: */ | |
1048 | extern char *debug_yytranslate (); | |
1049 | ||
1050 | int i; | |
1051 | ||
1052 | if(yy<256) { | |
1053 | fprintf (stderr, "<%d: %c >\n", yy, yy); | |
1054 | return 0; | |
1055 | } | |
1056 | fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy)); | |
1057 | return 1; | |
1058 | } | |
1059 | ||
1060 | #endif |