OSDN Git Service

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