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