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)
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22 /* This file is the type analyzer for GNU C++. To debug it, define SPEW_DEBUG
23 when compiling parse.c and spew.c. */
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
39 /* fifo of tokens recognized and available to parser. */
41 /* The values for YYCHAR will fit in a short. */
47 static int do_aggr ();
50 /* the declaration found for the last IDENTIFIER token read in.
51 yylex must look this up to detect typedefs, which get token type TYPENAME,
52 so it is left around in case the identifier is not a typedef but is
53 used in a context which makes it a reference to a variable. */
54 extern tree lastiddecl
; /* let our brains leak out here too */
55 extern int yychar
; /* the lookahead symbol */
56 extern YYSTYPE yylval
; /* the semantic value of the */
57 /* lookahead symbol */
58 extern int end_of_file
;
60 struct obstack token_obstack
;
65 static unsigned int yylex_ctr
= 0;
66 static int debug_yychar ();
69 /* Initialize token_obstack. Called once, from init_lex. */
73 gcc_obstack_init(&token_obstack
);
77 /* Use functions for debugging... */
79 /* Return the number of tokens available on the fifo. */
83 return (obstack_object_size(&token_obstack
)/sizeof(struct token
))
87 /* Fetch the token N down the line from the head of the fifo. */
92 /* could just have this do slurp_ implicitly, but this way is easier
94 my_friendly_assert (n
< num_tokens(), 298);
95 return ((struct token
*)obstack_base(&token_obstack
))+n
+first_token
;
98 /* Add a token to the token fifo. */
103 obstack_grow(&token_obstack
,t
,sizeof (struct token
));
106 /* Consume the next token out of the fifo. */
110 if (num_tokens() == 1)
112 obstack_free(&token_obstack
, obstack_base (&token_obstack
));
120 /* ...otherwise use macros. */
122 #define num_tokens() \
123 ((obstack_object_size(&token_obstack)/sizeof(struct token)) - first_token)
125 #define nth_token(N) \
126 (((struct token*)obstack_base(&token_obstack))+(N)+first_token)
128 #define add_token(T) obstack_grow(&token_obstack, (T), sizeof (struct token))
130 #define consume_token() \
132 ? (obstack_free (&token_obstack, obstack_base (&token_obstack)), \
137 /* Pull in enough tokens from real_yylex that the queue is N long beyond
138 the current token. */
147 /* We cannot read past certain tokens, so make sure we don't. */
154 /* Never read past these characters: they might separate
155 the current input stream from one we save away later. */
156 if (tmp
->yychar
== '{' || tmp
->yychar
== ':' || tmp
->yychar
== ';')
160 while (num_tokens() <= n
)
162 obstack_blank(&token_obstack
,sizeof (struct token
));
163 tmp
= ((struct token
*)obstack_next_free (&token_obstack
))-1;
164 tmp
->yychar
= real_yylex();
165 tmp
->end_of_file
= end_of_file
;
166 tmp
->yylval
= yylval
;
168 if (tmp
->yychar
== '{'
169 || tmp
->yychar
== ':'
170 || tmp
->yychar
== ';')
173 while (num_tokens () <= n
)
175 obstack_blank(&token_obstack
,sizeof (struct token
));
176 tmp
= ((struct token
*)obstack_next_free (&token_obstack
))-1;
178 tmp
->end_of_file
= 0;
184 /* Create room for N tokens at the front of the fifo. This is used
185 to insert new tokens into the stream ahead of the current token. */
191 if (first_token
>= n
)
195 int old_token_count
= num_tokens ();
198 obstack_blank (&token_obstack
, (n
-first_token
) * sizeof (struct token
));
201 tmp
= (char *)alloca ((num_tokens () + (n
-first_token
))
202 * sizeof (struct token
));
203 /* This move does not rely on the system being able to handle
204 overlapping moves. */
205 bcopy (nth_token (0), tmp
, old_token_count
* sizeof (struct token
));
206 bcopy (tmp
, nth_token (n
), old_token_count
* sizeof (struct token
));
213 probe_obstack (h
, obj
, nlevels
)
216 unsigned int nlevels
;
218 register struct _obstack_chunk
* lp
; /* below addr of any objects in this chunk */
219 register struct _obstack_chunk
* plp
; /* point to previous chunk if any */
222 /* We use >= rather than > since the object cannot be exactly at
223 the beginning of the chunk but might be an empty object exactly
224 at the end of an adjacent chunk. */
225 for (; nlevels
!= 0 && lp
!= 0 && ((tree
)lp
>= obj
|| (tree
)lp
->limit
< obj
);
231 return nlevels
!= 0 && lp
!= 0;
235 /* Value is 1 (or 2) if we should try to make the next identifier look like
236 a typename (when it may be a local variable or a class variable).
237 Value is 0 if we treat this name in a default fashion. */
238 extern int looking_for_typename
;
239 int looking_for_template
;
241 extern struct obstack
*current_obstack
, *saveable_obstack
;
247 struct token tmp_token
;
255 fprintf(stderr
, "\t\t## %d ##",yylex_ctr
);
259 /* if we've got tokens, send them */
262 tmp_token
= *nth_token(0);
264 /* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack.
265 If we don't find it in CURRENT_OBSTACK's current or immediately
266 previous chunk, assume it was and copy it to the current obstack. */
267 if ((tmp_token
.yychar
== CONSTANT
268 || tmp_token
.yychar
== STRING
)
269 && ! TREE_PERMANENT (tmp_token
.yylval
.ttype
)
270 && ! probe_obstack (current_obstack
, tmp_token
.yylval
.ttype
, 2)
271 && ! probe_obstack (saveable_obstack
, tmp_token
.yylval
.ttype
, 2))
272 tmp_token
.yylval
.ttype
= copy_node (tmp_token
.yylval
.ttype
);
276 /* if not, grab the next one and think about it */
277 tmp_token
.yychar
= real_yylex ();
278 tmp_token
.yylval
= yylval
;
279 tmp_token
.end_of_file
= end_of_file
;
280 add_token(&tmp_token
);
283 /* many tokens just need to be returned. At first glance, all we
284 * have to do is send them back up, but some of them are needed to
285 * figure out local context. */
286 switch(tmp_token
.yychar
)
289 /* This is a lexical no-op. */
293 debug_yychar (tmp_token
.yychar
);
299 if (nth_token (1)->yychar
== SCOPE
)
300 /* Don't interfere with the setting from an 'aggr' prefix. */
301 looking_for_typename
++;
302 else if (nth_token (1)->yychar
== '<')
303 looking_for_template
= 1;
305 trrr
= lookup_name (tmp_token
.yylval
.ttype
, -2);
309 tmp_token
.yychar
= identifier_type (trrr
);
310 switch (tmp_token
.yychar
)
313 lastiddecl
= identifier_typedecl_value (tmp_token
.yylval
.ttype
);
314 if (lastiddecl
!= trrr
)
318 tmp_token
.yylval
.ttype
= DECL_NESTED_TYPENAME (trrr
);
325 lastiddecl
= NULL_TREE
;
328 my_friendly_abort (101);
333 got_scope
= NULL_TREE
;
334 /* and fall through to... */
338 if (looking_for_typename
> 0)
339 looking_for_typename
--;
340 looking_for_template
= 0;
344 /* do_aggr needs to check if the previous token was RID_FRIEND,
345 so just increment first_token instead of calling consume_token. */
353 *nth_token(0) = tmp_token
;
355 /* fall through to output... */
357 /* Set this again, in case we are rescanning. */
358 looking_for_typename
= 1;
359 /* fall through... */
364 yylval
= tmp_token
.yylval
;
365 yychar
= tmp_token
.yychar
;
366 end_of_file
= tmp_token
.end_of_file
;
369 debug_yychar(yychar
);
374 /* token[0] == AGGR (struct/union/enum)
375 * Thus, token[1] is either a TYPENAME or a TYPENAME_DEFN.
376 * If token[2] == '{' or ':' then it's TYPENAME_DEFN.
377 * It's also a definition if it's a forward declaration (as in 'struct Foo;')
378 * which we can tell lf token[2] == ';' *and* token[-1] != FRIEND.
386 yc1
= nth_token (1)->yychar
;
387 if (yc1
!= TYPENAME
&& yc1
!= IDENTIFIER
&& yc1
!= PTYPENAME
)
389 yc2
= nth_token (2)->yychar
;
392 /* It's a forward declaration iff we were not preceded by 'friend'. */
393 if (first_token
> 0 && nth_token (-1)->yychar
== SCSPEC
394 && nth_token (-1)->yylval
.ttype
== ridpointers
[(int) RID_FRIEND
])
397 else if (yc2
!= '{' && yc2
!= ':')
403 nth_token (1)->yychar
= TYPENAME_DEFN
;
406 nth_token (1)->yychar
= PTYPENAME_DEFN
;
409 nth_token (1)->yychar
= IDENTIFIER_DEFN
;
412 my_friendly_abort (102);
418 /* debug_yychar takes a yychar (token number) value and prints its name. */
424 extern char *debug_yytranslate ();
429 fprintf (stderr
, "<%d: %c >\n", yy
, yy
);
432 fprintf (stderr
, "<%d:%s>\n", yy
, debug_yytranslate (yy
));