OSDN Git Service

Fix copyrights
[pf3gnuchains/gcc-fork.git] / gcc / cp / spew.c
1 /* Type Analyzer for GNU C++.
2    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3    1999, 2000 Free Software Foundation, Inc.
4    Hacked... nay, bludgeoned... by Mark Eichin (eichin@cygnus.com)
5
6 This file is part of GNU CC.
7
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING.  If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23
24 /* This file is the type analyzer for GNU C++.  To debug it, define SPEW_DEBUG
25    when compiling parse.c and spew.c.  */
26
27 #include "config.h"
28 #include "system.h"
29 #include "input.h"
30 #include "tree.h"
31 #include "lex.h"
32 #include "cp-tree.h"
33 #include "parse.h"
34 #include "flags.h"
35 #include "obstack.h"
36 #include "toplev.h"
37
38 /* This takes a token stream that hasn't decided much about types and
39    tries to figure out as much as it can, with excessive lookahead and
40    backtracking.  */
41
42 /* fifo of tokens recognized and available to parser.  */
43 struct token  {
44   /* The values for YYCHAR will fit in a short.  */
45   short         yychar;
46   short         end_of_file;
47   YYSTYPE       yylval;
48 };
49
50 static int do_aggr PARAMS ((void));
51 static void scan_tokens PARAMS ((unsigned int));
52
53 #ifdef SPEW_DEBUG
54 static int num_tokens PARAMS ((void));
55 static struct token *nth_token PARAMS ((int));
56 static void add_token PARAMS ((struct token *));
57 static void consume_token PARAMS ((void));
58 static int debug_yychar PARAMS ((int));
59 #endif
60
61 /* From lex.c: */
62 /* the declaration found for the last IDENTIFIER token read in.
63    yylex must look this up to detect typedefs, which get token type TYPENAME,
64    so it is left around in case the identifier is not a typedef but is
65    used in a context which makes it a reference to a variable.  */
66 extern tree lastiddecl;         /* let our brains leak out here too */
67 extern int      yychar;         /*  the lookahead symbol                */
68 extern YYSTYPE  yylval;         /*  the semantic value of the           */
69                                 /*  lookahead symbol                    */
70 extern int end_of_file;
71
72 struct obstack token_obstack;
73 int first_token;
74   
75 #ifdef SPEW_DEBUG
76 int spew_debug = 0;
77 static unsigned int yylex_ctr = 0;
78 static int debug_yychar ();
79 #endif
80
81 /* Initialize token_obstack. Called once, from init_parse.  */
82
83 void
84 init_spew ()
85 {
86   gcc_obstack_init (&token_obstack);
87 }
88
89 #ifdef SPEW_DEBUG
90 /* Use functions for debugging...  */
91
92 /* Return the number of tokens available on the fifo.  */
93
94 static int
95 num_tokens ()
96 {
97   return (obstack_object_size (&token_obstack) / sizeof (struct token))
98     - first_token;
99 }
100
101 /* Fetch the token N down the line from the head of the fifo.  */
102
103 static struct token*
104 nth_token (n)
105      int n;
106 {
107   /* could just have this do slurp_ implicitly, but this way is easier
108      to debug...  */
109   my_friendly_assert (n < num_tokens (), 298);
110   return ((struct token*)obstack_base (&token_obstack)) + n + first_token;
111 }
112
113 /* Add a token to the token fifo.  */
114
115 static void
116 add_token (t)
117      struct token* t;
118 {
119   obstack_grow (&token_obstack, t, sizeof (struct token));
120 }
121
122 /* Consume the next token out of the fifo.  */
123
124 static void
125 consume_token ()
126 {
127   if (num_tokens () == 1)
128     {
129       obstack_free (&token_obstack, obstack_base (&token_obstack));
130       first_token = 0;
131     }
132   else
133     first_token++;
134 }
135
136 #else
137 /* ...otherwise use macros.  */
138
139 #define num_tokens() \
140   ((obstack_object_size (&token_obstack) / sizeof (struct token)) - first_token)
141
142 #define nth_token(N) \
143   (((struct token*)obstack_base (&token_obstack))+(N)+first_token)
144
145 #define add_token(T) obstack_grow (&token_obstack, (T), sizeof (struct token))
146
147 #define consume_token() \
148   (num_tokens () == 1                                                   \
149    ? (obstack_free (&token_obstack, obstack_base (&token_obstack)),     \
150       (first_token = 0))                                                \
151    : first_token++)
152 #endif
153
154 /* Pull in enough tokens from real_yylex that the queue is N long beyond
155    the current token.  */
156
157 static void
158 scan_tokens (n)
159      unsigned int n;
160 {
161   unsigned int i;
162   struct token *tmp;
163
164   /* We cannot read past certain tokens, so make sure we don't.  */
165   i = num_tokens ();
166   if (i > n)
167     return;
168   while (i-- > 0)
169     {
170       tmp = nth_token (i);
171       /* Never read past these characters: they might separate
172          the current input stream from one we save away later.  */
173       if (tmp->yychar == '{' || tmp->yychar == ':' || tmp->yychar == ';')
174         goto pad_tokens;
175     }
176
177   while (num_tokens () <= n)
178     {
179       obstack_blank (&token_obstack, sizeof (struct token));
180       tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
181       tmp->yychar = real_yylex ();
182       tmp->end_of_file = end_of_file;
183       tmp->yylval = yylval;
184       end_of_file = 0;
185       if (tmp->yychar == '{'
186           || tmp->yychar == ':'
187           || tmp->yychar == ';')
188         {
189         pad_tokens:
190           while (num_tokens () <= n)
191             {
192               obstack_blank (&token_obstack, sizeof (struct token));
193               tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
194               tmp->yychar = EMPTY;
195               tmp->end_of_file = 0;
196             }
197         }
198     }
199 }
200
201 /* from lex.c: */
202 /* Value is 1 (or 2) if we should try to make the next identifier look like
203    a typename (when it may be a local variable or a class variable).
204    Value is 0 if we treat this name in a default fashion.  */
205 extern int looking_for_typename;
206 int looking_for_template;
207 extern int do_snarf_defarg;
208
209 tree got_scope;
210 tree got_object;
211
212 int
213 peekyylex ()
214 {
215   scan_tokens (0);
216   return nth_token (0)->yychar;
217 }
218
219 int
220 yylex ()
221 {
222   struct token tmp_token;
223   tree trrr = NULL_TREE;
224   int old_looking_for_typename = 0;
225
226  retry:
227 #ifdef SPEW_DEBUG
228   if (spew_debug)
229   {
230     yylex_ctr ++;
231     fprintf (stderr, "\t\t## %d ##", yylex_ctr);
232   }
233 #endif
234
235   if (do_snarf_defarg)
236     {
237       my_friendly_assert (num_tokens () == 0, 2837);
238       tmp_token.yychar = DEFARG;
239       tmp_token.yylval.ttype = snarf_defarg ();
240       tmp_token.end_of_file = 0;
241       do_snarf_defarg = 0;
242       add_token (&tmp_token);
243     }
244
245   /* if we've got tokens, send them */
246   else if (num_tokens ())
247     tmp_token= *nth_token (0);
248   else
249     {
250       /* if not, grab the next one and think about it */
251       tmp_token.yychar = real_yylex ();
252       tmp_token.yylval = yylval;
253       tmp_token.end_of_file = end_of_file;
254       add_token (&tmp_token);
255     }
256
257   /* many tokens just need to be returned. At first glance, all we
258      have to do is send them back up, but some of them are needed to
259      figure out local context.  */
260   switch (tmp_token.yychar)
261     {
262     case EMPTY:
263       /* This is a lexical no-op.  */
264       consume_token ();
265 #ifdef SPEW_DEBUG    
266       if (spew_debug)
267         debug_yychar (tmp_token.yychar);
268 #endif
269       goto retry;
270
271     case '(':
272       scan_tokens (1);
273       if (nth_token (1)->yychar == ')')
274         {
275           consume_token ();
276           tmp_token.yychar = LEFT_RIGHT;
277         }
278       consume_token ();
279       break;
280
281     case IDENTIFIER:
282       scan_tokens (1);
283       if (nth_token (1)->yychar == SCOPE)
284         {
285           /* Don't interfere with the setting from an 'aggr' prefix.  */
286           old_looking_for_typename = looking_for_typename;
287           looking_for_typename = 1;
288         }
289       else if (nth_token (1)->yychar == '<')
290         looking_for_template = 1;
291
292       trrr = lookup_name (tmp_token.yylval.ttype, -2);
293
294       if (trrr)
295         {
296           tmp_token.yychar = identifier_type (trrr);
297           switch (tmp_token.yychar)
298             {
299             case TYPENAME:
300             case SELFNAME:
301             case NSNAME:
302             case PTYPENAME:
303               lastiddecl = trrr;
304
305               /* If this got special lookup, remember it.  In these
306                  cases, we know it can't be a declarator-id. */
307               if (got_scope || got_object)
308                 tmp_token.yylval.ttype = trrr;
309               break;
310
311             case PFUNCNAME:
312             case IDENTIFIER:
313               lastiddecl = trrr;
314               break;
315
316             default:
317               my_friendly_abort (101);
318             }
319         }
320       else
321         lastiddecl = NULL_TREE;
322       got_scope = NULL_TREE;
323       /* and fall through to...  */
324     case IDENTIFIER_DEFN:
325     case TYPENAME:
326     case TYPENAME_DEFN:
327     case PTYPENAME:
328     case PTYPENAME_DEFN:
329       consume_token ();
330       /* If we see a SCOPE next, restore the old value.
331          Otherwise, we got what we want. */
332       looking_for_typename = old_looking_for_typename;
333       looking_for_template = 0;
334       break;
335
336     case SCSPEC:
337       if (tmp_token.yylval.ttype == ridpointers[RID_EXTERN])
338         {
339           scan_tokens (1);
340           if (nth_token (1)->yychar == STRING)
341             {
342               tmp_token.yychar = EXTERN_LANG_STRING;
343               tmp_token.yylval.ttype = get_identifier
344                 (TREE_STRING_POINTER (nth_token (1)->yylval.ttype));
345               consume_token ();
346             }
347         }
348       /* If export, warn that it's unimplemented and go on. */
349       else if (tmp_token.yylval.ttype == ridpointers[RID_EXPORT])
350         {
351           warning ("keyword 'export' not implemented and will be ignored");
352           consume_token ();
353           goto retry;
354         }
355       /* do_aggr needs to check if the previous token was `friend',
356          so just increment first_token instead of calling consume_token.  */
357       ++first_token;
358       break;
359
360     case NEW:
361       /* do_aggr needs to check if the previous token was `new',
362          so just increment first_token instead of calling consume_token.  */
363       ++first_token;
364       break;
365
366     case TYPESPEC:
367       /* If this provides a type for us, then revert lexical
368          state to standard state.  */
369       looking_for_typename = 0;
370       consume_token ();
371       break;
372
373     case AGGR:
374       *nth_token (0) = tmp_token;
375       do_aggr ();
376       /* fall through to output...  */
377     case ENUM:
378       /* Set this again, in case we are rescanning.  */
379       looking_for_typename = 2;
380       /* fall through...  */
381     default:
382       consume_token ();
383     }
384
385   /* class member lookup only applies to the first token after the object
386      expression, except for explicit destructor calls.  */
387   if (tmp_token.yychar != '~')
388     got_object = NULL_TREE;
389
390   /* Clear looking_for_typename if we got 'enum { ... };'.  */
391   if (tmp_token.yychar == '{' || tmp_token.yychar == ':'
392       || tmp_token.yychar == ';')
393     looking_for_typename = 0;
394
395   yylval = tmp_token.yylval;
396   yychar = tmp_token.yychar;
397   end_of_file = tmp_token.end_of_file;
398 #ifdef SPEW_DEBUG    
399   if (spew_debug)
400     debug_yychar (yychar);
401 #endif
402
403   return yychar;
404 }
405
406 /* token[0] == AGGR (struct/union/enum)
407    Thus, token[1] is either a TYPENAME or a TYPENAME_DEFN.
408    If token[2] == '{' or ':' then it's TYPENAME_DEFN.
409    It's also a definition if it's a forward declaration (as in 'struct Foo;')
410    which we can tell if token[2] == ';' *and* token[-1] != FRIEND or NEW.  */
411
412 static int
413 do_aggr ()
414 {
415   int yc1, yc2;
416   
417   scan_tokens (2);
418   yc1 = nth_token (1)->yychar;
419   if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME)
420     return 0;
421   yc2 = nth_token (2)->yychar;
422   if (yc2 == ';')
423     {
424       /* It's a forward declaration iff we were not preceded by
425          'friend' or `new'.  */
426       if (first_token > 0)
427         {
428           if (nth_token (-1)->yychar == SCSPEC
429               && nth_token (-1)->yylval.ttype == ridpointers[(int) RID_FRIEND])
430             return 0;
431           if (nth_token (-1)->yychar == NEW)
432             return 0;
433         }
434     }
435   else if (yc2 != '{' && yc2 != ':')
436     return 0;
437
438   switch (yc1)
439     {
440     case TYPENAME:
441       nth_token (1)->yychar = TYPENAME_DEFN;
442       break;
443     case PTYPENAME:
444       nth_token (1)->yychar = PTYPENAME_DEFN;
445       break;
446     case IDENTIFIER:
447       nth_token (1)->yychar = IDENTIFIER_DEFN;
448       break;
449     default:
450       my_friendly_abort (102);
451     }
452   return 0;
453 }  
454   
455 #ifdef SPEW_DEBUG    
456 /* debug_yychar takes a yychar (token number) value and prints its name.  */
457
458 static int
459 debug_yychar (yy)
460      int yy;
461 {
462   /* In parse.y: */
463   extern char *debug_yytranslate ();
464   
465   int i;
466   
467   if (yy<256) {
468     fprintf (stderr, "<%d: %c >\n", yy, yy);
469     return 0;
470   }
471   fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy));
472   return 1;
473 }
474
475 #endif