Remove the last vestiges of -DCCVER from 2.95.x contrib so we can remove
[dragonfly.git] / contrib / gcc / cp / spew.c
1 /* Type Analyzer for GNU C++.
2    Copyright (C) 1987, 89, 92-97, 1998 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 "system.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 #include "toplev.h"
36
37 /* This takes a token stream that hasn't decided much about types and
38    tries to figure out as much as it can, with excessive lookahead and
39    backtracking.  */
40
41 /* fifo of tokens recognized and available to parser.  */
42 struct token  {
43   /* The values for YYCHAR will fit in a short.  */
44   short         yychar;
45   short         end_of_file;
46   YYSTYPE       yylval;
47 };
48
49 static int do_aggr PROTO((void));
50 static int probe_obstack PROTO((struct obstack *, tree, unsigned int));
51 static void scan_tokens PROTO((unsigned int));
52
53 #ifdef SPEW_DEBUG
54 static int num_tokens PROTO((void));
55 static struct token *nth_token PROTO((int));
56 static void add_token PROTO((struct token *));
57 static void consume_token PROTO((void));
58 static int debug_yychar PROTO((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 /* Like _obstack_allocated_p, but stop after checking NLEVELS chunks.  */
202
203 static int
204 probe_obstack (h, obj, nlevels)
205      struct obstack *h;
206      tree obj;
207      unsigned int nlevels;
208 {
209   register struct _obstack_chunk*  lp;  /* below addr of any objects in this chunk */
210   register struct _obstack_chunk*  plp; /* point to previous chunk if any */
211
212   lp = (h)->chunk;
213   /* We use >= rather than > since the object cannot be exactly at
214      the beginning of the chunk but might be an empty object exactly
215      at the end of an adjacent chunk.  */
216   for (; nlevels != 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj);
217        nlevels -= 1)
218     {
219       plp = lp->prev;
220       lp = plp;      
221     }
222   return nlevels != 0 && lp != 0;
223 }
224
225 /* from lex.c: */
226 /* Value is 1 (or 2) if we should try to make the next identifier look like
227    a typename (when it may be a local variable or a class variable).
228    Value is 0 if we treat this name in a default fashion.  */
229 extern int looking_for_typename;
230 int looking_for_template;
231 extern int do_snarf_defarg;
232
233 extern struct obstack *current_obstack, *saveable_obstack;
234 tree got_scope;
235 tree got_object;
236
237 int
238 peekyylex ()
239 {
240   scan_tokens (0);
241   return nth_token (0)->yychar;
242 }
243
244 int
245 yylex ()
246 {
247   struct token tmp_token;
248   tree trrr = NULL_TREE;
249   int old_looking_for_typename = 0;
250
251  retry:
252 #ifdef SPEW_DEBUG
253   if (spew_debug)
254   {
255     yylex_ctr ++;
256     fprintf (stderr, "\t\t## %d ##", yylex_ctr);
257   }
258 #endif
259
260   if (do_snarf_defarg)
261     {
262       my_friendly_assert (num_tokens () == 0, 2837);
263       tmp_token.yychar = DEFARG;
264       tmp_token.yylval.ttype = snarf_defarg ();
265       tmp_token.end_of_file = 0;
266       do_snarf_defarg = 0;
267       add_token (&tmp_token);
268     }
269
270   /* if we've got tokens, send them */
271   else if (num_tokens ())
272     {
273       tmp_token= *nth_token (0);
274
275       /* TMP_TOKEN.YYLVAL.TTYPE may have been allocated on the wrong obstack.
276          If we don't find it in CURRENT_OBSTACK's current or immediately
277          previous chunk, assume it was and copy it to the current obstack.  */
278       if ((tmp_token.yychar == CONSTANT
279            || tmp_token.yychar == STRING)
280           && ! TREE_PERMANENT (tmp_token.yylval.ttype)
281           && ! probe_obstack (current_obstack, tmp_token.yylval.ttype, 2)
282           && ! probe_obstack (saveable_obstack, tmp_token.yylval.ttype, 2))
283         tmp_token.yylval.ttype = copy_node (tmp_token.yylval.ttype);
284     }
285   else
286     {
287       /* if not, grab the next one and think about it */
288       tmp_token.yychar = real_yylex ();
289       tmp_token.yylval = yylval;
290       tmp_token.end_of_file = end_of_file;
291       add_token (&tmp_token);
292     }
293
294   /* many tokens just need to be returned. At first glance, all we
295      have to do is send them back up, but some of them are needed to
296      figure out local context.  */
297   switch (tmp_token.yychar)
298     {
299     case EMPTY:
300       /* This is a lexical no-op.  */
301       consume_token ();
302 #ifdef SPEW_DEBUG    
303       if (spew_debug)
304         debug_yychar (tmp_token.yychar);
305 #endif
306       goto retry;
307
308     case IDENTIFIER:
309       scan_tokens (1);
310       if (nth_token (1)->yychar == SCOPE)
311         {
312           /* Don't interfere with the setting from an 'aggr' prefix.  */
313           old_looking_for_typename = looking_for_typename;
314           looking_for_typename = 1;
315         }
316       else if (nth_token (1)->yychar == '<')
317         looking_for_template = 1;
318
319       trrr = lookup_name (tmp_token.yylval.ttype, -2);
320
321       if (trrr)
322         {
323           tmp_token.yychar = identifier_type (trrr);
324           switch (tmp_token.yychar)
325             {
326             case TYPENAME:
327             case SELFNAME:
328             case NSNAME:
329             case PTYPENAME:
330               lastiddecl = trrr;
331
332               /* If this got special lookup, remember it.  In these cases,
333                  we don't have to worry about being a declarator-id. */
334               if (got_scope || got_object)
335                 tmp_token.yylval.ttype = trrr;
336               break;
337
338             case PFUNCNAME:
339             case IDENTIFIER:
340               lastiddecl = trrr;
341               break;
342
343             default:
344               my_friendly_abort (101);
345             }
346         }
347       else
348         lastiddecl = NULL_TREE;
349       got_scope = NULL_TREE;
350       /* and fall through to...  */
351     case IDENTIFIER_DEFN:
352     case TYPENAME:
353     case TYPENAME_DEFN:
354     case PTYPENAME:
355     case PTYPENAME_DEFN:
356       consume_token ();
357       /* If we see a SCOPE next, restore the old value.
358          Otherwise, we got what we want. */
359       looking_for_typename = old_looking_for_typename;
360       looking_for_template = 0;
361       break;
362
363     case SCSPEC:
364       /* If export, warn that it's unimplemented and go on. */
365       if (tmp_token.yylval.ttype == get_identifier("export"))
366         {
367           warning ("keyword 'export' not implemented and will be ignored");
368           consume_token ();
369           goto retry;
370         }
371       else
372         {
373           ++first_token;
374           break;
375         }
376
377     case NEW:
378       /* do_aggr needs to check if the previous token was RID_NEW,
379          so just increment first_token instead of calling consume_token.  */
380       ++first_token;
381       break;
382
383     case TYPESPEC:
384       consume_token ();
385       break;
386
387     case AGGR:
388       *nth_token (0) = tmp_token;
389       do_aggr ();
390       /* fall through to output...  */
391     case ENUM:
392       /* Set this again, in case we are rescanning.  */
393       looking_for_typename = 2;
394       /* fall through...  */
395     default:
396       consume_token ();
397     }
398
399   /* class member lookup only applies to the first token after the object
400      expression, except for explicit destructor calls.  */
401   if (tmp_token.yychar != '~')
402     got_object = NULL_TREE;
403
404   /* Clear looking_for_typename if we got 'enum { ... };'.  */
405   if (tmp_token.yychar == '{' || tmp_token.yychar == ':'
406       || tmp_token.yychar == ';')
407     looking_for_typename = 0;
408
409   yylval = tmp_token.yylval;
410   yychar = tmp_token.yychar;
411   end_of_file = tmp_token.end_of_file;
412 #ifdef SPEW_DEBUG    
413   if (spew_debug)
414     debug_yychar (yychar);
415 #endif
416
417   return yychar;
418 }
419
420 /* token[0] == AGGR (struct/union/enum)
421    Thus, token[1] is either a TYPENAME or a TYPENAME_DEFN.
422    If token[2] == '{' or ':' then it's TYPENAME_DEFN.
423    It's also a definition if it's a forward declaration (as in 'struct Foo;')
424    which we can tell if token[2] == ';' *and* token[-1] != FRIEND or NEW.  */
425
426 static int
427 do_aggr ()
428 {
429   int yc1, yc2;
430   
431   scan_tokens (2);
432   yc1 = nth_token (1)->yychar;
433   if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME)
434     return 0;
435   yc2 = nth_token (2)->yychar;
436   if (yc2 == ';')
437     {
438       /* It's a forward declaration iff we were not preceded by
439          'friend' or `new'.  */
440       if (first_token > 0)
441         {
442           if (nth_token (-1)->yychar == SCSPEC
443               && nth_token (-1)->yylval.ttype == ridpointers[(int) RID_FRIEND])
444             return 0;
445           if (nth_token (-1)->yychar == NEW)
446             return 0;
447         }
448     }
449   else if (yc2 != '{' && yc2 != ':')
450     return 0;
451
452   switch (yc1)
453     {
454     case TYPENAME:
455       nth_token (1)->yychar = TYPENAME_DEFN;
456       break;
457     case PTYPENAME:
458       nth_token (1)->yychar = PTYPENAME_DEFN;
459       break;
460     case IDENTIFIER:
461       nth_token (1)->yychar = IDENTIFIER_DEFN;
462       break;
463     default:
464       my_friendly_abort (102);
465     }
466   return 0;
467 }  
468   
469 #ifdef SPEW_DEBUG    
470 /* debug_yychar takes a yychar (token number) value and prints its name.  */
471
472 static int
473 debug_yychar (yy)
474      int yy;
475 {
476   /* In parse.y: */
477   extern char *debug_yytranslate ();
478   
479   int i;
480   
481   if (yy<256) {
482     fprintf (stderr, "<%d: %c >\n", yy, yy);
483     return 0;
484   }
485   fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy));
486   return 1;
487 }
488
489 #endif