OSDN Git Service

87 Cygnus<->FSF 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
72 void
73 init_spew ()
74 {
75   gcc_obstack_init (&token_obstack);
76 }
77
78 #ifdef SPEW_DEBUG
79 /* Use functions for debugging...  */
80
81 /* Return the number of tokens available on the fifo.  */
82
83 static int
84 num_tokens ()
85 {
86   return (obstack_object_size (&token_obstack) / sizeof (struct token))
87     - first_token;
88 }
89
90 /* Fetch the token N down the line from the head of the fifo.  */
91
92 static struct token*
93 nth_token (n)
94      int n;
95 {
96   /* could just have this do slurp_ implicitly, but this way is easier
97      to debug...  */
98   my_friendly_assert (n < num_tokens (), 298);
99   return ((struct token*)obstack_base (&token_obstack)) + n + first_token;
100 }
101
102 /* Add a token to the token fifo.  */
103
104 static void
105 add_token (t)
106      struct token* t;
107 {
108   obstack_grow (&token_obstack, t, sizeof (struct token));
109 }
110
111 /* Consume the next token out of the fifo.  */
112
113 static void
114 consume_token ()
115 {
116   if (num_tokens () == 1)
117     {
118       obstack_free (&token_obstack, obstack_base (&token_obstack));
119       first_token = 0;
120     }
121   else
122     first_token++;
123 }
124
125 #else
126 /* ...otherwise use macros.  */
127
128 #define num_tokens() \
129   ((obstack_object_size (&token_obstack) / sizeof (struct token)) - first_token)
130
131 #define nth_token(N) \
132   (((struct token*)obstack_base (&token_obstack))+(N)+first_token)
133
134 #define add_token(T) obstack_grow (&token_obstack, (T), sizeof (struct token))
135
136 #define consume_token() \
137   (num_tokens () == 1                                                   \
138    ? (obstack_free (&token_obstack, obstack_base (&token_obstack)),     \
139       (first_token = 0))                                                \
140    : first_token++)
141 #endif
142
143 /* Pull in enough tokens from real_yylex that the queue is N long beyond
144    the current token.  */
145
146 static void
147 scan_tokens (n)
148      int n;
149 {
150   int i;
151   struct token *tmp;
152
153   /* We cannot read past certain tokens, so make sure we don't.  */
154   i = num_tokens ();
155   if (i > n)
156     return;
157   while (i-- > 0)
158     {
159       tmp = nth_token (i);
160       /* Never read past these characters: they might separate
161          the current input stream from one we save away later.  */
162       if (tmp->yychar == '{' || tmp->yychar == ':' || tmp->yychar == ';')
163         goto pad_tokens;
164     }
165
166   while (num_tokens () <= n)
167     {
168       obstack_blank (&token_obstack, sizeof (struct token));
169       tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
170       tmp->yychar = real_yylex ();
171       tmp->end_of_file = end_of_file;
172       tmp->yylval = yylval;
173       end_of_file = 0;
174       if (tmp->yychar == '{'
175           || tmp->yychar == ':'
176           || tmp->yychar == ';')
177         {
178         pad_tokens:
179           while (num_tokens () <= n)
180             {
181               obstack_blank (&token_obstack, sizeof (struct token));
182               tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
183               tmp->yychar = EMPTY;
184               tmp->end_of_file = 0;
185             }
186         }
187     }
188 }
189
190 static int
191 probe_obstack (h, obj, nlevels)
192      struct obstack *h;
193      tree obj;
194      unsigned int nlevels;
195 {
196   register struct _obstack_chunk*  lp;  /* below addr of any objects in this chunk */
197   register struct _obstack_chunk*  plp; /* point to previous chunk if any */
198
199   lp = (h)->chunk;
200   /* We use >= rather than > since the object cannot be exactly at
201      the beginning of the chunk but might be an empty object exactly
202      at the end of an adjacent chunk.  */
203   for (; nlevels != 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj);
204        nlevels -= 1)
205     {
206       plp = lp->prev;
207       lp = plp;      
208     }
209   return nlevels != 0 && lp != 0;
210 }
211
212 /* from lex.c: */
213 /* Value is 1 (or 2) if we should try to make the next identifier look like
214    a typename (when it may be a local variable or a class variable).
215    Value is 0 if we treat this name in a default fashion.  */
216 extern int looking_for_typename;
217 int looking_for_template;
218
219 extern struct obstack *current_obstack, *saveable_obstack;
220 tree got_scope;
221 tree got_object;
222
223 int
224 peekyylex ()
225 {
226   scan_tokens (0);
227   return nth_token (0)->yychar;
228 }
229
230 int
231 yylex ()
232 {
233   struct token tmp_token;
234   tree trrr;
235
236  retry:
237 #ifdef SPEW_DEBUG
238   if (spew_debug)
239   {
240     yylex_ctr ++;
241     fprintf (stderr, "\t\t## %d ##", yylex_ctr);
242   }
243 #endif
244
245   /* if we've got tokens, send them */
246   if (num_tokens ())
247     {
248       tmp_token= *nth_token (0);
249
250       /* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack.
251          If we don't find it in CURRENT_OBSTACK's current or immediately
252          previous chunk, assume it was and copy it to the current obstack.  */
253       if ((tmp_token.yychar == CONSTANT
254            || tmp_token.yychar == STRING)
255           && ! TREE_PERMANENT (tmp_token.yylval.ttype)
256           && ! probe_obstack (current_obstack, tmp_token.yylval.ttype, 2)
257           && ! probe_obstack (saveable_obstack, tmp_token.yylval.ttype, 2))
258         tmp_token.yylval.ttype = copy_node (tmp_token.yylval.ttype);
259     }
260   else
261     {
262       /* if not, grab the next one and think about it */
263       tmp_token.yychar = real_yylex ();
264       tmp_token.yylval = yylval;
265       tmp_token.end_of_file = end_of_file;
266       add_token (&tmp_token);
267     }
268
269   /* many tokens just need to be returned. At first glance, all we
270      have to do is send them back up, but some of them are needed to
271      figure out local context.  */
272   switch (tmp_token.yychar)
273     {
274     case EMPTY:
275       /* This is a lexical no-op.  */
276       consume_token ();
277 #ifdef SPEW_DEBUG    
278       if (spew_debug)
279         debug_yychar (tmp_token.yychar);
280 #endif
281       goto retry;
282
283     case IDENTIFIER:
284       scan_tokens (1);
285       if (nth_token (1)->yychar == SCOPE)
286         /* Don't interfere with the setting from an 'aggr' prefix.  */
287         looking_for_typename++;
288       else if (nth_token (1)->yychar == '<')
289         looking_for_template = 1;
290
291       trrr = lookup_name (tmp_token.yylval.ttype, -2);
292
293       if (trrr)
294         {
295           tmp_token.yychar = identifier_type (trrr);
296           switch (tmp_token.yychar)
297             {
298             case TYPENAME:
299             case SELFNAME:
300               lastiddecl = identifier_typedecl_value (tmp_token.yylval.ttype);
301               if (lastiddecl != trrr)
302                 {
303                   lastiddecl = trrr;
304                   if (got_scope)
305                     tmp_token.yylval.ttype = trrr;
306                 }
307               break;
308             case IDENTIFIER:
309               lastiddecl = trrr;
310               break;
311             case PTYPENAME:
312               lastiddecl = NULL_TREE;
313               break;
314             case NSNAME:
315               lastiddecl = trrr;
316               if (got_scope)
317                 tmp_token.yylval.ttype = trrr;
318               break;
319             default:
320               my_friendly_abort (101);
321             }
322         }
323       else
324         lastiddecl = trrr;
325       got_scope = NULL_TREE;
326       /* and fall through to...  */
327     case IDENTIFIER_DEFN:
328     case TYPENAME:
329     case TYPENAME_DEFN:
330     case PTYPENAME:
331     case PTYPENAME_DEFN:
332       consume_token ();
333       if (looking_for_typename > 0)
334         looking_for_typename--;
335       looking_for_template = 0;
336       break;
337
338     case SCSPEC:
339     case NEW:
340       /* do_aggr needs to check if the previous token was RID_NEW,
341          so just increment first_token instead of calling consume_token.  */
342       ++first_token;
343       break;
344
345     case TYPESPEC:
346       consume_token ();
347       break;
348
349     case AGGR:
350       *nth_token (0) = tmp_token;
351       do_aggr ();
352       /* fall through to output...  */
353     case ENUM:
354       /* Set this again, in case we are rescanning.  */
355       looking_for_typename = 1;
356       /* fall through...  */
357     default:
358       consume_token ();
359     }
360
361   got_object = NULL_TREE;
362   yylval = tmp_token.yylval;
363   yychar = tmp_token.yychar;
364   end_of_file = tmp_token.end_of_file;
365 #ifdef SPEW_DEBUG    
366   if (spew_debug)
367     debug_yychar (yychar);
368 #endif
369   return yychar;
370 }
371
372 /* token[0] == AGGR (struct/union/enum)
373    Thus, token[1] is either a TYPENAME or a TYPENAME_DEFN.
374    If token[2] == '{' or ':' then it's TYPENAME_DEFN.
375    It's also a definition if it's a forward declaration (as in 'struct Foo;')
376    which we can tell if token[2] == ';' *and* token[-1] != FRIEND or NEW.  */
377
378 static int
379 do_aggr ()
380 {
381   int yc1, yc2;
382   
383   scan_tokens (2);
384   yc1 = nth_token (1)->yychar;
385   if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME)
386     return 0;
387   yc2 = nth_token (2)->yychar;
388   if (yc2 == ';')
389     {
390       /* It's a forward declaration iff we were not preceded by
391          'friend' or `new'.  */
392       if (first_token > 0)
393         {
394           if (nth_token (-1)->yychar == SCSPEC
395               && nth_token (-1)->yylval.ttype == ridpointers[(int) RID_FRIEND])
396             return 0;
397           if (nth_token (-1)->yychar == NEW)
398             return 0;
399         }
400     }
401   else if (yc2 != '{' && yc2 != ':')
402     return 0;
403
404   switch (yc1)
405     {
406     case TYPENAME:
407       nth_token (1)->yychar = TYPENAME_DEFN;
408       break;
409     case PTYPENAME:
410       nth_token (1)->yychar = PTYPENAME_DEFN;
411       break;
412     case IDENTIFIER:
413       nth_token (1)->yychar = IDENTIFIER_DEFN;
414       break;
415     default:
416       my_friendly_abort (102);
417     }
418   return 0;
419 }  
420   
421 #ifdef SPEW_DEBUG    
422 /* debug_yychar takes a yychar (token number) value and prints its name.  */
423
424 static int
425 debug_yychar (yy)
426      int yy;
427 {
428   /* In parse.y: */
429   extern char *debug_yytranslate ();
430   
431   int i;
432   
433   if (yy<256) {
434     fprintf (stderr, "<%d: %c >\n", yy, yy);
435     return 0;
436   }
437   fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy));
438   return 1;
439 }
440
441 #endif