OSDN Git Service

(TARGET_SWITCHES): Add new target name: cpu32.
[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                 lastiddecl = trrr;
303               if (got_scope)
304                 tmp_token.yylval.ttype = trrr;
305               break;
306             case IDENTIFIER:
307               lastiddecl = trrr;
308               break;
309             case PTYPENAME:
310               lastiddecl = NULL_TREE;
311               break;
312             case NSNAME:
313               lastiddecl = trrr;
314               if (got_scope)
315                 tmp_token.yylval.ttype = trrr;
316               break;
317             default:
318               my_friendly_abort (101);
319             }
320         }
321       else
322         lastiddecl = trrr;
323       got_scope = NULL_TREE;
324       /* and fall through to...  */
325     case IDENTIFIER_DEFN:
326     case TYPENAME:
327     case TYPENAME_DEFN:
328     case PTYPENAME:
329     case PTYPENAME_DEFN:
330       consume_token ();
331       if (looking_for_typename > 0)
332         looking_for_typename--;
333       looking_for_template = 0;
334       break;
335
336     case SCSPEC:
337     case NEW:
338       /* do_aggr needs to check if the previous token was RID_NEW,
339          so just increment first_token instead of calling consume_token.  */
340       ++first_token;
341       break;
342
343     case TYPESPEC:
344       consume_token ();
345       break;
346
347     case AGGR:
348       *nth_token (0) = tmp_token;
349       do_aggr ();
350       /* fall through to output...  */
351     case ENUM:
352       /* Set this again, in case we are rescanning.  */
353       looking_for_typename = 1;
354       /* fall through...  */
355     default:
356       consume_token ();
357     }
358
359   got_object = NULL_TREE;
360   yylval = tmp_token.yylval;
361   yychar = tmp_token.yychar;
362   end_of_file = tmp_token.end_of_file;
363 #ifdef SPEW_DEBUG    
364   if (spew_debug)
365     debug_yychar (yychar);
366 #endif
367   return yychar;
368 }
369
370 /* token[0] == AGGR (struct/union/enum)
371    Thus, token[1] is either a TYPENAME or a TYPENAME_DEFN.
372    If token[2] == '{' or ':' then it's TYPENAME_DEFN.
373    It's also a definition if it's a forward declaration (as in 'struct Foo;')
374    which we can tell if token[2] == ';' *and* token[-1] != FRIEND or NEW.  */
375
376 static int
377 do_aggr ()
378 {
379   int yc1, yc2;
380   
381   scan_tokens (2);
382   yc1 = nth_token (1)->yychar;
383   if (yc1 != TYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME)
384     return 0;
385   yc2 = nth_token (2)->yychar;
386   if (yc2 == ';')
387     {
388       /* It's a forward declaration iff we were not preceded by
389          'friend' or `new'.  */
390       if (first_token > 0)
391         {
392           if (nth_token (-1)->yychar == SCSPEC
393               && nth_token (-1)->yylval.ttype == ridpointers[(int) RID_FRIEND])
394             return 0;
395           if (nth_token (-1)->yychar == NEW)
396             return 0;
397         }
398     }
399   else if (yc2 != '{' && yc2 != ':')
400     return 0;
401
402   switch (yc1)
403     {
404     case TYPENAME:
405       nth_token (1)->yychar = TYPENAME_DEFN;
406       break;
407     case PTYPENAME:
408       nth_token (1)->yychar = PTYPENAME_DEFN;
409       break;
410     case IDENTIFIER:
411       nth_token (1)->yychar = IDENTIFIER_DEFN;
412       break;
413     default:
414       my_friendly_abort (102);
415     }
416   return 0;
417 }  
418   
419 #ifdef SPEW_DEBUG    
420 /* debug_yychar takes a yychar (token number) value and prints its name.  */
421
422 static int
423 debug_yychar (yy)
424      int yy;
425 {
426   /* In parse.y: */
427   extern char *debug_yytranslate ();
428   
429   int i;
430   
431   if (yy<256) {
432     fprintf (stderr, "<%d: %c >\n", yy, yy);
433     return 0;
434   }
435   fprintf (stderr, "<%d:%s>\n", yy, debug_yytranslate (yy));
436   return 1;
437 }
438
439 #endif