home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / bbs / gnu / gcc-2.3.3-src.lha / GNU / src / amiga / gcc-2.3.3 / cp-spew.c < prev    next >
C/C++ Source or Header  |  1994-02-06  |  28KB  |  1,061 lines

  1. /* Type Analyzer for GNU C++.
  2.    Copyright (C) 1987, 1989, 1992 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21.  
  22. /* This file is the type analyzer for GNU C++.  To debug it, define SPEW_DEBUG
  23.    when compiling cp-parse.c and cp-spew.c.  */
  24.  
  25. #include "config.h"
  26. #include <stdio.h>
  27. #include "input.h"
  28. #include "tree.h"
  29. #include "cp-lex.h"
  30. #include "cp-parse.h"
  31. #include "cp-tree.h"
  32. #include "flags.h"
  33. #include "obstack.h"
  34.  
  35. /* This takes a token stream that hasn't decided much about types and
  36.    tries to figure out as much as it can, with excessive lookahead and
  37.    backtracking. */
  38.  
  39. /* fifo of tokens recognized and available to parser. */
  40. struct token  {
  41.   /* The values for YYCHAR will fit in a short.  */
  42.   short        yychar;
  43.   short        end_of_file;
  44.   YYSTYPE    yylval;
  45. };
  46.  
  47. static int do_aggr ();
  48. static struct token frob_identifier ();
  49. static struct token hack_scope ();
  50. static tree hack_ptype ();
  51. static tree hack_more_ids ();
  52.  
  53. /* From cp-lex.c: */
  54. /* the declaration found for the last IDENTIFIER token read in.
  55.    yylex must look this up to detect typedefs, which get token type TYPENAME,
  56.    so it is left around in case the identifier is not a typedef but is
  57.    used in a context which makes it a reference to a variable.  */
  58. extern tree lastiddecl;        /* let our brains leak out here too */
  59. extern int    yychar;        /*  the lookahead symbol        */
  60. extern YYSTYPE    yylval;        /*  the semantic value of the        */
  61.                 /*  lookahead symbol            */
  62. extern int end_of_file;
  63.  
  64. struct obstack token_obstack;
  65. int first_token;
  66.   
  67. #ifdef SPEW_DEBUG
  68. int spew_debug = 0;
  69. static unsigned int yylex_ctr = 0;
  70. static int debug_yychar ();
  71. #endif
  72.  
  73. static char follows_typename[END_OF_SAVED_INPUT+1];
  74. static char follows_identifier[END_OF_SAVED_INPUT+1];
  75.  
  76. /* This is a hack!!! TEMPLATE_TYPE_SEEN_BEFORE_SCOPE consists of the name
  77.  * of the last template_type parsed in cp-parse.y if it is followed by a
  78.  * scope operator.  It will be reset inside the next invocation of yylex().
  79.  * This is used for recognizing nested types inside templates.
  80.  * - niklas@appli.se */
  81. tree template_type_seen_before_scope;
  82.  
  83. /* Initialize token_obstack. Called once, from init_lex.  */
  84. void
  85. init_spew ()
  86. {
  87.   static char *chars_following_identifier = ".+-|/%^!?:";
  88.   short *ps;
  89.   static short toks_follow_ids[] =
  90.     { POINTSAT_LEFT_RIGHT, ASSIGN, RANGE, OROR, ANDAND, MIN_MAX, EQCOMPARE,
  91.       ARITHCOMPARE, LSHIFT, RSHIFT, UNARY, PLUSPLUS, MINUSMINUS, POINTSAT,
  92.       POINTSAT_STAR, DOT_STAR, CONSTANT, STRING, SIZEOF, ENUM, IF,
  93.       ELSE, WHILE, DO, FOR, SWITCH, CASE, DEFAULT, BREAK, CONTINUE,
  94.       RETURN, GOTO, ASM_KEYWORD, TYPEOF, ALIGNOF, HEADOF, CLASSOF, ATTRIBUTE,
  95.       AGGR, VISSPEC, DELETE, RAISE, RERAISE, TRY, EXCEPT, CATCH,
  96.       THROW, ANSI_TRY, ANSI_THROW, EXTERN_LANG_STRING, ALL,
  97.       END_OF_SAVED_INPUT, -1 };
  98.   static short toks_follow_types[] =
  99.     { IDENTIFIER, TYPENAME, SCOPED_TYPENAME, SCSPEC, TYPESPEC, TYPE_QUAL,
  100.       ELLIPSIS, THIS, OPERATOR, DYNAMIC, TEMPLATE, SCOPE, START_DECLARATOR,
  101.       TYPENAME_COLON, PAREN_STAR_PAREN, TYPENAME_ELLIPSIS, PTYPENAME,
  102.       PRE_PARSED_FUNCTION_DECL, PRE_PARSED_CLASS_DECL, -1 };
  103.  
  104.   gcc_obstack_init(&token_obstack);
  105.  
  106.   /* Initialize the arrays saying what tokens are definitely
  107.      (or possibly) valid following typenames and identifiers.  */
  108.   while (*chars_following_identifier)
  109.     follows_identifier[*chars_following_identifier++] = 1;
  110.   for (ps = toks_follow_ids; *ps != -1; ps++)
  111.     follows_identifier[*ps] = 1;
  112.   for (ps = toks_follow_types; *ps != -1; ps++)
  113.     follows_typename[*ps] = 1;
  114. }
  115.  
  116. #ifdef SPEW_DEBUG
  117. /* Use functions for debugging...  */
  118.  
  119. /* Return the number of tokens available on the fifo. */
  120. static int
  121. num_tokens ()
  122. {
  123.   return (obstack_object_size(&token_obstack)/sizeof(struct token))
  124.     - first_token;
  125. }
  126.  
  127. /* Fetch the token N down the line from the head of the fifo. */
  128. static struct token*
  129. nth_token (n)
  130.      int n;
  131. {
  132.   /* could just have this do slurp_ implicitly, but this way is easier
  133.    * to debug... */
  134.   my_friendly_assert (n < num_tokens(), 298);
  135.   return ((struct token*)obstack_base(&token_obstack))+n+first_token;
  136. }
  137.  
  138. /* Add a token to the token fifo. */
  139. static void
  140. add_token (t)
  141.      struct token* t;
  142. {
  143.   obstack_grow(&token_obstack,t,sizeof (struct token));
  144. }
  145.  
  146. /* Consume the next token out of the fifo.  */
  147. static void
  148. consume_token()
  149. {
  150.   if (num_tokens() == 1)
  151.     {
  152.       obstack_free(&token_obstack, obstack_base (&token_obstack));
  153.       first_token = 0;
  154.     }
  155.   else
  156.     first_token++;
  157. }
  158.  
  159. #else
  160. /* ...otherwise use macros.  */
  161.  
  162. #define num_tokens() \
  163.   ((obstack_object_size(&token_obstack)/sizeof(struct token)) - first_token)
  164.  
  165. #define nth_token(N) \
  166.   (((struct token*)obstack_base(&token_obstack))+(N)+first_token)
  167.  
  168. #define add_token(T) obstack_grow(&token_obstack, (T), sizeof (struct token))
  169.  
  170. #define consume_token() \
  171.   (num_tokens() == 1                            \
  172.    ? (obstack_free (&token_obstack, obstack_base (&token_obstack)),    \
  173.       (first_token = 0))                        \
  174.    : first_token++)
  175. #endif
  176.  
  177. /* Pull in enough tokens from real_yylex that the queue is N long.  */
  178.  
  179. static void
  180. scan_tokens (n)
  181.      int n;
  182. {
  183.   int i;
  184.   struct token *tmp;
  185.  
  186.   /* We cannot read past certain tokens, so make sure we don't.  */
  187.   i = num_tokens ();
  188.   if (i > n)
  189.     return;
  190.   while (i-- > 0)
  191.     {
  192.       tmp = nth_token (i);
  193.       /* Never read past these characters: they might separate
  194.      the current input stream from one we save away later.  */
  195.       if (tmp->yychar == '{' || tmp->yychar == ':')
  196.     goto pad_tokens;
  197.     }
  198.  
  199.   while (num_tokens() <= n)
  200.     {
  201.       obstack_blank(&token_obstack,sizeof (struct token));
  202.       tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
  203.       tmp->yychar = real_yylex();
  204.       tmp->end_of_file = end_of_file;
  205.       tmp->yylval = yylval;
  206.       end_of_file = 0;
  207.       if (tmp->yychar == '{'
  208.       || tmp->yychar == ':'
  209.       || tmp->yychar == ';')
  210.     {
  211.     pad_tokens:
  212.       while (num_tokens () <= n)
  213.         {
  214.           obstack_blank(&token_obstack,sizeof (struct token));
  215.           tmp = ((struct token *)obstack_next_free (&token_obstack))-1;
  216.           tmp->yychar = EMPTY;
  217.           tmp->end_of_file = 0;
  218.         }
  219.     }
  220.     }
  221. }
  222.  
  223. /* Create room for N tokens at the front of the fifo.  This is used
  224.    to insert new tokens into the stream ahead of the current token.  */
  225.  
  226. static void
  227. shift_tokens (n)
  228.      int n;
  229. {
  230.   if (first_token >= n)
  231.     first_token -= n;
  232.   else
  233.     {
  234.       int old_token_count = num_tokens ();
  235.       char *tmp;
  236.  
  237.       obstack_blank (&token_obstack, (n-first_token) * sizeof (struct token));
  238.       if (old_token_count)
  239.     {
  240.       tmp = (char *)alloca ((num_tokens () + (n-first_token))
  241.                 * sizeof (struct token));
  242.       /* This move does not rely on the system being able to handle
  243.          overlapping moves.  */
  244.       bcopy (nth_token (0), tmp, old_token_count * sizeof (struct token));
  245.       bcopy (tmp, nth_token (n), old_token_count * sizeof (struct token));
  246.     }
  247.       first_token = 0;
  248.     }
  249. }
  250.  
  251. int
  252. probe_obstack (h, obj, nlevels)
  253.      struct obstack *h;
  254.      tree obj;
  255.      unsigned int nlevels;
  256. {
  257.   register struct _obstack_chunk*  lp;    /* below addr of any objects in this chunk */
  258.   register struct _obstack_chunk*  plp;    /* point to previous chunk if any */
  259.  
  260.   lp = (h)->chunk;
  261.   /* We use >= rather than > since the object cannot be exactly at
  262.      the beginning of the chunk but might be an empty object exactly
  263.      at the end of an adjacent chunk. */
  264.   for (; nlevels > 0 && lp != 0 && ((tree)lp >= obj || (tree)lp->limit < obj);
  265.        nlevels -= 1)
  266.     {
  267.       plp = lp->prev;
  268.       lp = plp;