diff options
Diffstat (limited to 'contrib/gcc/cp/spew.c')
-rw-r--r-- | contrib/gcc/cp/spew.c | 1558 |
1 files changed, 0 insertions, 1558 deletions
diff --git a/contrib/gcc/cp/spew.c b/contrib/gcc/cp/spew.c deleted file mode 100644 index 5bd3fdf..0000000 --- a/contrib/gcc/cp/spew.c +++ /dev/null @@ -1,1558 +0,0 @@ -/* Type Analyzer for GNU C++. - Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002 Free Software Foundation, Inc. - Hacked... nay, bludgeoned... by Mark Eichin (eichin@cygnus.com) - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -/* This file is the type analyzer for GNU C++. To debug it, define SPEW_DEBUG - when compiling parse.c and spew.c. */ - -#include "config.h" -#include "system.h" -#include "input.h" -#include "tree.h" -#include "cp-tree.h" -#include "cpplib.h" -#include "c-pragma.h" -#include "lex.h" -#include "parse.h" -#include "flags.h" -#include "obstack.h" -#include "toplev.h" -#include "ggc.h" -#include "intl.h" -#include "timevar.h" - -#ifdef SPEW_DEBUG -#define SPEW_INLINE -#else -#define SPEW_INLINE inline -#endif - -/* This takes a token stream that hasn't decided much about types and - tries to figure out as much as it can, with excessive lookahead and - backtracking. */ - -/* fifo of tokens recognized and available to parser. */ -struct token GTY(()) -{ - /* The values for YYCHAR will fit in a short. */ - short yychar; - unsigned int lineno; - YYSTYPE GTY ((desc ("%1.yychar"))) yylval; -}; - -/* Since inline methods can refer to text which has not yet been seen, - we store the text of the method in a structure which is placed in the - DECL_PENDING_INLINE_INFO field of the FUNCTION_DECL. - After parsing the body of the class definition, the FUNCTION_DECL's are - scanned to see which ones have this field set. Those are then digested - one at a time. - - This function's FUNCTION_DECL will have a bit set in its common so - that we know to watch out for it. */ - -#define TOKEN_CHUNK_SIZE 20 -struct token_chunk GTY(()) -{ - struct token_chunk *next; - struct token toks[TOKEN_CHUNK_SIZE]; -}; - -struct unparsed_text GTY(()) -{ - struct unparsed_text *next; /* process this one next */ - tree decl; /* associated declaration */ - location_t locus; /* location we got the text from */ - int interface; /* remembering interface_unknown and interface_only */ - - struct token_chunk * tokens; /* Start of the token list. */ - - struct token_chunk *last_chunk; /* End of the token list. */ - short last_pos; /* Number of tokens used in the last chunk of - TOKENS. */ - - short cur_pos; /* Current token in 'cur_chunk', when rescanning. */ - struct token_chunk *cur_chunk; /* Current chunk, when rescanning. */ -}; - -/* Stack of state saved off when we return to an inline method or - default argument that has been stored for later parsing. */ -struct feed GTY(()) -{ - struct unparsed_text *input; - location_t locus; - int yychar; - YYSTYPE GTY ((desc ("%1.yychar"))) yylval; - int first_token; - struct obstack GTY ((skip (""))) token_obstack; - struct feed *next; -}; - -static GTY(()) struct feed *feed; - -static SPEW_INLINE void do_aggr PARAMS ((void)); -static SPEW_INLINE int identifier_type PARAMS ((tree)); -static void scan_tokens PARAMS ((int)); -static void feed_defarg PARAMS ((tree)); -static void finish_defarg PARAMS ((void)); -static void yylexstring PARAMS ((struct token *)); -static int read_token PARAMS ((struct token *)); - -static SPEW_INLINE int num_tokens PARAMS ((void)); -static SPEW_INLINE struct token *nth_token PARAMS ((int)); -static SPEW_INLINE int next_token PARAMS ((struct token *)); -static SPEW_INLINE int shift_token PARAMS ((void)); -static SPEW_INLINE void push_token PARAMS ((struct token *)); -static SPEW_INLINE void consume_token PARAMS ((void)); -static SPEW_INLINE int read_process_identifier PARAMS ((YYSTYPE *)); - -static SPEW_INLINE void feed_input PARAMS ((struct unparsed_text *)); -static SPEW_INLINE struct token * space_for_token - PARAMS ((struct unparsed_text *t)); -static SPEW_INLINE struct token * remove_last_token - PARAMS ((struct unparsed_text *t)); -static struct unparsed_text * alloc_unparsed_text - PARAMS ((const location_t *, tree decl, int interface)); - -static void snarf_block PARAMS ((struct unparsed_text *t)); -static tree snarf_defarg PARAMS ((void)); -static void snarf_parenthesized_expression (struct unparsed_text *); -static int frob_id PARAMS ((int, int, tree *)); - -/* The list of inline functions being held off until we reach the end of - the current class declaration. */ -static GTY(()) struct unparsed_text *pending_inlines; -static GTY(()) struct unparsed_text *pending_inlines_tail; - -/* The list of previously-deferred inline functions currently being parsed. - This exists solely to be a GC root. */ -static GTY(()) struct unparsed_text *processing_these_inlines; - -static void begin_parsing_inclass_inline PARAMS ((struct unparsed_text *)); - -#ifdef SPEW_DEBUG -int spew_debug = 0; -static unsigned int yylex_ctr = 0; - -static void debug_yychar PARAMS ((int)); - -/* In parse.y: */ -extern char *debug_yytranslate PARAMS ((int)); -#endif -static enum cpp_ttype last_token; -static tree last_token_id; - -/* From lex.c: */ -/* the declaration found for the last IDENTIFIER token read in. yylex - must look this up to detect typedefs, which get token type - tTYPENAME, so it is left around in case the identifier is not a - typedef but is used in a context which makes it a reference to a - variable. */ -extern tree lastiddecl; /* let our brains leak out here too */ -extern int yychar; /* the lookahead symbol */ -extern YYSTYPE yylval; /* the semantic value of the */ - /* lookahead symbol */ -/* The token fifo lives in this obstack. */ -static struct obstack token_obstack; -static int first_token; - -/* When we see a default argument in a method declaration, we snarf it as - text using snarf_defarg. When we get up to namespace scope, we then go - through and parse all of them using do_pending_defargs. Since yacc - parsers are not reentrant, we retain defargs state in these two - variables so that subsequent calls to do_pending_defargs can resume - where the previous call left off. DEFARG_FNS is a tree_list where - the TREE_TYPE is the current_class_type, TREE_VALUE is the FUNCTION_DECL, - and TREE_PURPOSE is the list unprocessed dependent functions. */ - -/* list of functions with unprocessed defargs */ -static GTY(()) tree defarg_fns; -/* current default parameter */ -static GTY(()) tree defarg_parm; -/* list of unprocessed fns met during current fn. */ -static GTY(()) tree defarg_depfns; -/* list of fns with circular defargs */ -static GTY(()) tree defarg_fnsdone; - -/* Initialize obstacks. Called once, from cxx_init. */ - -void -init_spew () -{ - gcc_obstack_init (&token_obstack); -} - -/* Subroutine of read_token. */ -static SPEW_INLINE int -read_process_identifier (pyylval) - YYSTYPE *pyylval; -{ - tree id = pyylval->ttype; - - if (C_IS_RESERVED_WORD (id)) - { - pyylval->ttype = ridpointers[C_RID_CODE (id)]; - return C_RID_YYCODE (id); - } - - /* Make sure that user does not collide with our internal naming - scheme. This is not necessary if '.' is used to remove them from - the user's namespace, but is if '$' or double underscores are. */ - -#if !defined(JOINER) || JOINER == '$' - if (VPTR_NAME_P (id) - || VTABLE_NAME_P (id) - || TEMP_NAME_P (id) - || ANON_AGGRNAME_P (id)) - warning ( -"identifier name `%s' conflicts with GNU C++ internal naming strategy", - IDENTIFIER_POINTER (id)); -#endif - return IDENTIFIER; -} - -/* Concatenate strings before returning them to the parser. This isn't quite - as good as having it done in the lexer, but it's better than nothing. */ - -static void -yylexstring (t) - struct token *t; -{ - enum cpp_ttype next_type; - tree next; - - next_type = c_lex (&next); - if (next_type == CPP_STRING || next_type == CPP_WSTRING) - { - varray_type strings; - - VARRAY_TREE_INIT (strings, 32, "strings"); - VARRAY_PUSH_TREE (strings, t->yylval.ttype); - - do - { - VARRAY_PUSH_TREE (strings, next); - next_type = c_lex (&next); - } - while (next_type == CPP_STRING || next_type == CPP_WSTRING); - - t->yylval.ttype = combine_strings (strings); - last_token_id = t->yylval.ttype; - } - - /* We will have always read one token too many. */ - _cpp_backup_tokens (parse_in, 1); - - t->yychar = STRING; -} - -/* Read the next token from the input file. The token is written into - T, and its type number is returned. */ -static int -read_token (t) - struct token *t; -{ - retry: - - last_token = c_lex (&last_token_id); - t->yylval.ttype = last_token_id; - - switch (last_token) - { -#define YYCHAR(YY) t->yychar = (YY); break; -#define YYCODE(C) t->yylval.code = (C); - - case CPP_EQ: YYCHAR('='); - case CPP_NOT: YYCHAR('!'); - case CPP_GREATER: YYCODE(GT_EXPR); YYCHAR('>'); - case CPP_LESS: YYCODE(LT_EXPR); YYCHAR('<'); - case CPP_PLUS: YYCODE(PLUS_EXPR); YYCHAR('+'); - case CPP_MINUS: YYCODE(MINUS_EXPR); YYCHAR('-'); - case CPP_MULT: YYCODE(MULT_EXPR); YYCHAR('*'); - case CPP_DIV: YYCODE(TRUNC_DIV_EXPR); YYCHAR('/'); - case CPP_MOD: YYCODE(TRUNC_MOD_EXPR); YYCHAR('%'); - case CPP_AND: YYCODE(BIT_AND_EXPR); YYCHAR('&'); - case CPP_OR: YYCODE(BIT_IOR_EXPR); YYCHAR('|'); - case CPP_XOR: YYCODE(BIT_XOR_EXPR); YYCHAR('^'); - case CPP_RSHIFT: YYCODE(RSHIFT_EXPR); YYCHAR(RSHIFT); - case CPP_LSHIFT: YYCODE(LSHIFT_EXPR); YYCHAR(LSHIFT); - - case CPP_COMPL: YYCHAR('~'); - case CPP_AND_AND: YYCHAR(ANDAND); - case CPP_OR_OR: YYCHAR(OROR); - case CPP_QUERY: YYCHAR('?'); - case CPP_COLON: YYCHAR(':'); - case CPP_COMMA: YYCHAR(','); - case CPP_OPEN_PAREN: YYCHAR('('); - case CPP_CLOSE_PAREN: YYCHAR(')'); - case CPP_EQ_EQ: YYCODE(EQ_EXPR); YYCHAR(EQCOMPARE); - case CPP_NOT_EQ: YYCODE(NE_EXPR); YYCHAR(EQCOMPARE); - case CPP_GREATER_EQ:YYCODE(GE_EXPR); YYCHAR(ARITHCOMPARE); - case CPP_LESS_EQ: YYCODE(LE_EXPR); YYCHAR(ARITHCOMPARE); - - case CPP_PLUS_EQ: YYCODE(PLUS_EXPR); YYCHAR(ASSIGN); - case CPP_MINUS_EQ: YYCODE(MINUS_EXPR); YYCHAR(ASSIGN); - case CPP_MULT_EQ: YYCODE(MULT_EXPR); YYCHAR(ASSIGN); - case CPP_DIV_EQ: YYCODE(TRUNC_DIV_EXPR); YYCHAR(ASSIGN); - case CPP_MOD_EQ: YYCODE(TRUNC_MOD_EXPR); YYCHAR(ASSIGN); - case CPP_AND_EQ: YYCODE(BIT_AND_EXPR); YYCHAR(ASSIGN); - case CPP_OR_EQ: YYCODE(BIT_IOR_EXPR); YYCHAR(ASSIGN); - case CPP_XOR_EQ: YYCODE(BIT_XOR_EXPR); YYCHAR(ASSIGN); - case CPP_RSHIFT_EQ: YYCODE(RSHIFT_EXPR); YYCHAR(ASSIGN); - case CPP_LSHIFT_EQ: YYCODE(LSHIFT_EXPR); YYCHAR(ASSIGN); - - case CPP_OPEN_SQUARE: YYCHAR('['); - case CPP_CLOSE_SQUARE: YYCHAR(']'); - case CPP_OPEN_BRACE: YYCHAR('{'); - case CPP_CLOSE_BRACE: YYCHAR('}'); - case CPP_SEMICOLON: YYCHAR(';'); - case CPP_ELLIPSIS: YYCHAR(ELLIPSIS); - - case CPP_PLUS_PLUS: YYCHAR(PLUSPLUS); - case CPP_MINUS_MINUS: YYCHAR(MINUSMINUS); - case CPP_DEREF: YYCHAR(POINTSAT); - case CPP_DOT: YYCHAR('.'); - - /* These tokens are C++ specific. */ - case CPP_SCOPE: YYCHAR(SCOPE); - case CPP_DEREF_STAR: YYCHAR(POINTSAT_STAR); - case CPP_DOT_STAR: YYCHAR(DOT_STAR); - case CPP_MIN_EQ: YYCODE(MIN_EXPR); YYCHAR(ASSIGN); - case CPP_MAX_EQ: YYCODE(MAX_EXPR); YYCHAR(ASSIGN); - case CPP_MIN: YYCODE(MIN_EXPR); YYCHAR(MIN_MAX); - case CPP_MAX: YYCODE(MAX_EXPR); YYCHAR(MIN_MAX); -#undef YYCHAR -#undef YYCODE - - case CPP_EOF: - t->yychar = 0; - break; - - case CPP_NAME: - t->yychar = read_process_identifier (&t->yylval); - break; - - case CPP_NUMBER: - case CPP_CHAR: - case CPP_WCHAR: - t->yychar = CONSTANT; - break; - - case CPP_STRING: - case CPP_WSTRING: - yylexstring (t); - break; - - default: - yyerror ("parse error"); - goto retry; - } - - t->lineno = lineno; - return t->yychar; -} - -static void -feed_input (input) - struct unparsed_text *input; -{ - struct feed *f; -#if 0 - if (feed) - abort (); -#endif - - f = ggc_alloc (sizeof (struct feed)); - - input->cur_chunk = input->tokens; - input->cur_pos = 0; - -#ifdef SPEW_DEBUG - if (spew_debug) - fprintf (stderr, "\tfeeding %s:%d [%d tokens]\n", - input->locus.file, input->locus.line, input->limit - input->pos); -#endif - - f->input = input; - f->locus.file = input_filename; - f->locus.line = lineno; - f->yychar = yychar; - f->yylval = yylval; - f->first_token = first_token; - f->token_obstack = token_obstack; - f->next = feed; - - input_filename = input->locus.file; - lineno = input->locus.line; - yychar = YYEMPTY; - yylval.ttype = NULL_TREE; - first_token = 0; - gcc_obstack_init (&token_obstack); - feed = f; -} - -void -end_input () -{ - struct feed *f = feed; - - input_filename = f->locus.file; - lineno = f->locus.line; - yychar = f->yychar; - yylval = f->yylval; - first_token = f->first_token; - obstack_free (&token_obstack, 0); - token_obstack = f->token_obstack; - feed = f->next; - -#ifdef SPEW_DEBUG - if (spew_debug) - fprintf (stderr, "\treturning to %s:%d\n", input_filename, lineno); -#endif -} - -/* Token queue management. */ - -/* Return the number of tokens available on the fifo. */ -static SPEW_INLINE int -num_tokens () -{ - return (obstack_object_size (&token_obstack) / sizeof (struct token)) - - first_token; -} - -/* Fetch the token N down the line from the head of the fifo. */ - -static SPEW_INLINE struct token* -nth_token (n) - int n; -{ -#ifdef ENABLE_CHECKING - /* could just have this do slurp_ implicitly, but this way is easier - to debug... */ - my_friendly_assert (n >= 0 && n < num_tokens (), 298); -#endif - return ((struct token*)obstack_base (&token_obstack)) + n + first_token; -} - -static const struct token Teosi = { END_OF_SAVED_INPUT, 0 UNION_INIT_ZERO }; -static const struct token Tpad = { EMPTY, 0 UNION_INIT_ZERO }; - -/* Copy the next token into T and return its value. */ -static SPEW_INLINE int -next_token (t) - struct token *t; -{ - if (!feed) - return read_token (t); - - if (feed->input->cur_chunk != feed->input->last_chunk - || feed->input->cur_pos != feed->input->last_pos) - { - if (feed->input->cur_pos == TOKEN_CHUNK_SIZE) - { - feed->input->cur_chunk = feed->input->cur_chunk->next; - feed->input->cur_pos = 0; - } - memcpy (t, feed->input->cur_chunk->toks + feed->input->cur_pos, - sizeof (struct token)); - feed->input->cur_pos++; - return t->yychar; - } - - return 0; -} - -/* Shift the next token onto the fifo. */ -static SPEW_INLINE int -shift_token () -{ - size_t point = obstack_object_size (&token_obstack); - obstack_blank (&token_obstack, sizeof (struct token)); - return next_token ((struct token *) (obstack_base (&token_obstack) + point)); -} - -/* Consume the next token out of the fifo. */ - -static SPEW_INLINE void -consume_token () -{ - if (num_tokens () == 1) - { - obstack_free (&token_obstack, obstack_base (&token_obstack)); - first_token = 0; - } - else - first_token++; -} - -/* Push a token at the head of the queue; it will be the next token read. */ -static SPEW_INLINE void -push_token (t) - struct token *t; -{ - if (first_token == 0) /* We hope this doesn't happen often. */ - { - size_t active = obstack_object_size (&token_obstack); - obstack_blank (&token_obstack, sizeof (struct token)); - if (active) - memmove (obstack_base (&token_obstack) + sizeof (struct token), - obstack_base (&token_obstack), active); - first_token++; - } - first_token--; - memcpy (nth_token (0), t, sizeof (struct token)); -} - - -/* Pull in enough tokens that the queue is N long beyond the current - token. */ - -static void -scan_tokens (n) - int n; -{ - int i; - int num = num_tokens (); - int yychar; - - /* First, prune any empty tokens at the end. */ - i = num; - while (i > 0 && nth_token (i - 1)->yychar == EMPTY) - i--; - if (i < num) - { - obstack_blank (&token_obstack, -((num - i) * sizeof (struct token))); - num = i; - } - - /* Now, if we already have enough tokens, return. */ - if (num > n) - return; - - /* Never read past these characters: they might separate - the current input stream from one we save away later. */ - for (i = 0; i < num; i++) - { - yychar = nth_token (i)->yychar; - if (yychar == '{' || yychar == ':' || yychar == ';') - goto pad_tokens; - } - - while (num_tokens () <= n) - { - yychar = shift_token (); - if (yychar == '{' || yychar == ':' || yychar == ';') - goto pad_tokens; - } - return; - - pad_tokens: - while (num_tokens () <= n) - obstack_grow (&token_obstack, &Tpad, sizeof (struct token)); -} - -int looking_for_typename; -int looking_for_template; - -static int after_friend; -static int after_new; -static int do_snarf_defarg; - -tree got_scope; -tree got_object; - -static SPEW_INLINE int -identifier_type (decl) - tree decl; -{ - tree t; - - if (TREE_CODE (decl) == TEMPLATE_DECL) - { - if (TREE_CODE (DECL_TEMPLATE_RESULT (decl)) == TYPE_DECL) - return PTYPENAME; - else if (looking_for_template) - return PFUNCNAME; - } - if (looking_for_template && really_overloaded_fn (decl)) - { - /* See through a baselink. */ - if (TREE_CODE (decl) == BASELINK) - decl = BASELINK_FUNCTIONS (decl); - - for (t = decl; t != NULL_TREE; t = OVL_CHAIN (t)) - if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t))) - return PFUNCNAME; - } - if (TREE_CODE (decl) == NAMESPACE_DECL) - return NSNAME; - if (TREE_CODE (decl) != TYPE_DECL) - return IDENTIFIER; - if (DECL_ARTIFICIAL (decl) && TREE_TYPE (decl) == current_class_type) - return SELFNAME; - - /* A constructor declarator for a template type will get here as an - implicit typename, a TYPENAME_TYPE with a type. */ - t = got_scope; - if (t && TREE_CODE (t) == TYPENAME_TYPE) - t = TREE_TYPE (t); - decl = TREE_TYPE (decl); - if (TREE_CODE (decl) == TYPENAME_TYPE) - decl = TREE_TYPE (decl); - if (t && t == decl) - return SELFNAME; - - return tTYPENAME; -} - -/* token[0] == AGGR (struct/union/enum) - Thus, token[1] is either a tTYPENAME or a TYPENAME_DEFN. - If token[2] == '{' or ':' then it's TYPENAME_DEFN. - It's also a definition if it's a forward declaration (as in 'struct Foo;') - which we can tell if token[2] == ';' *and* token[-1] != FRIEND or NEW. */ - -static SPEW_INLINE void -do_aggr () -{ - int yc1, yc2; - - scan_tokens (2); - yc1 = nth_token (1)->yychar; - if (yc1 != tTYPENAME && yc1 != IDENTIFIER && yc1 != PTYPENAME) - return; - yc2 = nth_token (2)->yychar; - if (yc2 == ';') - { - /* It's a forward declaration iff we were not preceded by - 'friend' or `new'. */ - if (after_friend || after_new) - return; - } - else if (yc2 != '{' && yc2 != ':') - return; - - switch (yc1) - { - case tTYPENAME: - nth_token (1)->yychar = TYPENAME_DEFN; - break; - case PTYPENAME: - nth_token (1)->yychar = PTYPENAME_DEFN; - break; - case IDENTIFIER: - nth_token (1)->yychar = IDENTIFIER_DEFN; - break; - default: - abort (); - } -} - -void -see_typename () -{ - /* Only types expected, not even namespaces. */ - looking_for_typename = 2; - if (yychar < 0) - if ((yychar = yylex ()) < 0) yychar = 0; - looking_for_typename = 0; - if (yychar == IDENTIFIER) - { - lastiddecl = lookup_name (yylval.ttype, -2); - if (lastiddecl) - yychar = identifier_type (lastiddecl); - } -} - -int -yylex () -{ - int yychr; - int old_looking_for_typename = 0; - int just_saw_new = 0; - int just_saw_friend = 0; - - timevar_push (TV_LEX); - - retry: -#ifdef SPEW_DEBUG - if (spew_debug) - { - yylex_ctr ++; - fprintf (stderr, "\t\t## %d @%d ", yylex_ctr, lineno); - } -#endif - - if (do_snarf_defarg) - { - do_snarf_defarg = 0; - yylval.ttype = snarf_defarg (); - yychar = DEFARG; - got_object = NULL_TREE; - timevar_pop (TV_LEX); - return DEFARG; - } - - /* if we've got tokens, send them */ - else if (num_tokens ()) - yychr = nth_token (0)->yychar; - else - yychr = shift_token (); - - /* many tokens just need to be returned. At first glance, all we - have to do is send them back up, but some of them are needed to - figure out local context. */ - switch (yychr) - { - case EMPTY: - /* This is a lexical no-op. */ -#ifdef SPEW_DEBUG - if (spew_debug) - debug_yychar (yychr); -#endif - consume_token (); - goto retry; - - case '(': - scan_tokens (1); - if (nth_token (1)->yychar == ')') - { - consume_token (); - yychr = LEFT_RIGHT; - } - break; - - case IDENTIFIER: - { - int peek; - - scan_tokens (1); - peek = nth_token (1)->yychar; - yychr = frob_id (yychr, peek, &nth_token (0)->yylval.ttype); - break; - } - case IDENTIFIER_DEFN: - case tTYPENAME: - case TYPENAME_DEFN: - case PTYPENAME: - case PTYPENAME_DEFN: - /* If we see a SCOPE next, restore the old value. - Otherwise, we got what we want. */ - looking_for_typename = old_looking_for_typename; - looking_for_template = 0; - break; - - case SCSPEC: - if (nth_token (0)->yylval.ttype == ridpointers[RID_EXTERN]) - { - scan_tokens (1); - if (nth_token (1)->yychar == STRING) - { - yychr = EXTERN_LANG_STRING; - nth_token (1)->yylval.ttype = get_identifier - (TREE_STRING_POINTER (nth_token (1)->yylval.ttype)); - consume_token (); - } - } - /* do_aggr needs to know if the previous token was `friend'. */ - else if (nth_token (0)->yylval.ttype == ridpointers[RID_FRIEND]) - just_saw_friend = 1; - - break; - - case NEW: - /* do_aggr needs to know if the previous token was `new'. */ - just_saw_new = 1; - break; - - case TYPESPEC: - case '{': - case ':': - case ';': - /* If this provides a type for us, then revert lexical - state to standard state. */ - looking_for_typename = 0; - break; - - case AGGR: - do_aggr (); - break; - - case ENUM: - /* Set this again, in case we are rescanning. */ - looking_for_typename = 2; - break; - - default: - break; - } - - after_friend = just_saw_friend; - after_new = just_saw_new; - - /* class member lookup only applies to the first token after the object - expression, except for explicit destructor calls. */ - if (yychr != '~') - got_object = NULL_TREE; - - yychar = yychr; - { - struct token *tok = nth_token (0); - - yylval = tok->yylval; - if (tok->lineno) - lineno = tok->lineno; - } - -#ifdef SPEW_DEBUG - if (spew_debug) - debug_yychar (yychr); -#endif - consume_token (); - - timevar_pop (TV_LEX); - return yychr; -} - -/* Unget character CH from the input stream. - If RESCAN is nonzero, then we want to `see' this - character as the next input token. */ - -void -yyungetc (ch, rescan) - int ch; - int rescan; -{ - /* Unget a character from the input stream. */ - if (yychar == YYEMPTY || rescan == 0) - { - struct token fake; - - fake.yychar = ch; - fake.yylval.ttype = 0; - fake.lineno = lineno; - - push_token (&fake); - } - else - { - yychar = ch; - } -} - -/* Lexer hackery to determine what *IDP really is. */ - -static int -frob_id (yyc, peek, idp) - int yyc; - int peek; - tree *idp; -{ - tree trrr; - int old_looking_for_typename = 0; - - if (peek == SCOPE) - { - /* Don't interfere with the setting from an 'aggr' prefix. */ - old_looking_for_typename = looking_for_typename; - looking_for_typename = 1; - } - else if (peek == '<') - looking_for_template = 1; - trrr = lookup_name (*idp, -2); - if (trrr) - { - yyc = identifier_type (trrr); - switch(yyc) - { - case tTYPENAME: - case SELFNAME: - case NSNAME: - case PTYPENAME: - /* If this got special lookup, remember it. In these - cases, we know it can't be a declarator-id. */ - if (got_scope || got_object) - *idp = trrr; - /* FALLTHROUGH */ - case PFUNCNAME: - case IDENTIFIER: - lastiddecl = trrr; - break; - default: - abort (); - } - } - else - lastiddecl = NULL_TREE; - got_scope = NULL_TREE; - looking_for_typename = old_looking_for_typename; - looking_for_template = 0; - return yyc; -} - -/* ID is an operator name. Duplicate the hackery in yylex to determine what - it really is. */ - -tree frob_opname (id) - tree id; -{ - scan_tokens (0); - frob_id (0, nth_token (0)->yychar, &id); - got_object = NULL_TREE; - return id; -} - -/* Set up the state required to correctly handle the definition of the - inline function whose preparsed state has been saved in PI. */ - -static void -begin_parsing_inclass_inline (pi) - struct unparsed_text *pi; -{ - tree context; - - /* Record that we are processing the chain of inlines starting at - PI for GC. */ - if (cfun) - cp_function_chain->unparsed_inlines = pi; - else - processing_these_inlines = pi; - - ggc_collect (); - - /* If this is an inline function in a local class, we must make sure - that we save all pertinent information about the function - surrounding the local class. */ - context = decl_function_context (pi->decl); - if (context) - push_function_context_to (context); - - feed_input (pi); - interface_unknown = pi->interface == 1; - interface_only = pi->interface == 0; - DECL_PENDING_INLINE_P (pi->decl) = 0; - DECL_PENDING_INLINE_INFO (pi->decl) = 0; - - /* Pass back a handle to the rest of the inline functions, so that they - can be processed later. */ - yychar = PRE_PARSED_FUNCTION_DECL; - yylval.pi = pi; - - start_function (NULL_TREE, pi->decl, NULL_TREE, - (SF_DEFAULT | SF_PRE_PARSED | SF_INCLASS_INLINE)); -} - -/* Called from the top level: if there are any pending inlines to - do, set up to process them now. This function sets up the first function - to be parsed; after it has been, the rule for fndef in parse.y will - call process_next_inline to start working on the next one. */ - -void -do_pending_inlines () -{ - /* Oops, we're still dealing with the last batch. */ - if (yychar == PRE_PARSED_FUNCTION_DECL) - return; - - if (pending_inlines) - { - /* Clear the chain, so that any inlines nested inside the batch - we're to process now don't refer to this batch. See e.g. - g++.other/lookup6.C. */ - struct unparsed_text *first = pending_inlines; - pending_inlines = pending_inlines_tail = 0; - - begin_parsing_inclass_inline (first); - } -} - -/* Called from the fndecl rule in the parser when the function just parsed - was declared using a PRE_PARSED_FUNCTION_DECL (i.e. came from - do_pending_inlines). */ - -void -process_next_inline (i) - struct unparsed_text *i; -{ - tree decl = i->decl; - tree context = decl_function_context (decl); - - if (context) - pop_function_context_from (context); - if (yychar == YYEMPTY) - yychar = yylex (); - if (yychar != END_OF_SAVED_INPUT) - error ("parse error at end of saved function text"); - end_input (); - - i = i->next; - if (i) - begin_parsing_inclass_inline (i); - else - { - if (cfun) - cp_function_chain->unparsed_inlines = 0; - else - processing_these_inlines = 0; - extract_interface_info (); - } -} - -/* Create a new token at the end of the token list in T. */ -static SPEW_INLINE struct token * -space_for_token (t) - struct unparsed_text *t; -{ - if (t->last_pos != TOKEN_CHUNK_SIZE) - return t->last_chunk->toks + (t->last_pos++); - - t->last_chunk->next = ggc_alloc_cleared (sizeof (*t->last_chunk->next)); - t->last_chunk = t->last_chunk->next; - t->last_chunk->next = NULL; - - t->last_pos = 1; - return t->last_chunk->toks; -} - -/* Shrink the token list in T by one token. */ -static SPEW_INLINE struct token * -remove_last_token (t) - struct unparsed_text *t; -{ - struct token *result = t->last_chunk->toks + t->last_pos - 1; - if (t->last_pos == 0) - abort (); - t->last_pos--; - if (t->last_pos == 0 && t->last_chunk != t->tokens) - { - struct token_chunk *c; - c = t->tokens; - while (c->next != t->last_chunk) - c = c->next; - c->next = NULL; - t->last_chunk = c; - t->last_pos = ARRAY_SIZE (c->toks); - } - return result; -} - -/* Allocate an 'unparsed_text' structure, ready to use space_for_token. */ -static struct unparsed_text * -alloc_unparsed_text (locus, decl, interface) - const location_t *locus; - tree decl; - int interface; -{ - struct unparsed_text *r; - r = ggc_alloc_cleared (sizeof (*r)); - r->decl = decl; - r->locus = *locus; - r->interface = interface; - r->tokens = r->last_chunk = ggc_alloc_cleared (sizeof (*r->tokens)); - return r; -} - -/* Accumulate the tokens that make up a parenthesized expression in T, - having already read the opening parenthesis. */ - -static void -snarf_parenthesized_expression (struct unparsed_text *t) -{ - int yyc; - int level = 1; - - while (1) - { - yyc = next_token (space_for_token (t)); - if (yyc == '(') - ++level; - else if (yyc == ')' && --level == 0) - break; - else if (yyc == 0) - { - error ("%Hend of file read inside definition", &t->locus); - break; - } - } -} - -/* Subroutine of snarf_method, deals with actual absorption of the block. */ - -static void -snarf_block (t) - struct unparsed_text *t; -{ - int blev = 1; - int look_for_semicolon = 0; - int look_for_lbrac = 0; - int look_for_catch = 0; - int yyc; - struct token *current; - - if (yychar == '{') - ; - else if (yychar == '=') - look_for_semicolon = 1; - else if (yychar == ':' || yychar == RETURN_KEYWORD || yychar == TRY) - { - if (yychar == TRY) - look_for_catch = 1; - look_for_lbrac = 1; - blev = 0; - } - else - yyerror ("parse error in method specification"); - - /* The current token is the first one to be recorded. */ - current = space_for_token (t); - current->yychar = yychar; - current->yylval = yylval; - current->lineno = lineno; - - for (;;) - { - yyc = next_token (space_for_token (t)); - - if (yyc == '{') - { - look_for_lbrac = 0; - blev++; - } - else if (yyc == '}') - { - blev--; - if (blev == 0 && !look_for_semicolon) - { - if (!look_for_catch) - break; - - if (next_token (space_for_token (t)) != CATCH) - { - push_token (remove_last_token (t)); - break; - } - - look_for_lbrac = 1; - } - } - else if (yyc == ';') - { - if (look_for_lbrac) - { - struct token *fake; - - error ("function body for constructor missing"); - /* fake a { } to avoid further errors */ - fake = space_for_token (t); - fake->yylval.ttype = 0; - fake->yychar = '{'; - fake = space_for_token (t); - fake->yylval.ttype = 0; - fake->yychar = '}'; - break; - } - else if (look_for_semicolon && blev == 0) - break; - } - else if (yyc == '(' && blev == 0) - snarf_parenthesized_expression (t); - else if (yyc == 0) - { - error ("%Hend of file read inside definition", &t->locus); - break; - } - } -} - -/* This function stores away the text for an inline function that should - be processed later (by do_pending_inlines). */ -void -snarf_method (decl) - tree decl; -{ - struct unparsed_text *meth; - location_t starting; - starting.file = input_filename; - starting.line = lineno; - - meth = alloc_unparsed_text (&starting, decl, (interface_unknown ? 1 - : (interface_only ? 0 : 2))); - - snarf_block (meth); - /* Add three END_OF_SAVED_INPUT tokens. We used to provide an - infinite stream of END_OF_SAVED_INPUT tokens -- but that can - cause the compiler to get stuck in an infinite loop when - encountering invalid code. We need more than one because the - parser sometimes peeks ahead several tokens. */ - memcpy (space_for_token (meth), &Teosi, sizeof (struct token)); - memcpy (space_for_token (meth), &Teosi, sizeof (struct token)); - memcpy (space_for_token (meth), &Teosi, sizeof (struct token)); - - /* Happens when we get two declarations of the same function in the - same scope. */ - if (decl == void_type_node - || (current_class_type && TYPE_REDEFINED (current_class_type))) - return; - -#ifdef SPEW_DEBUG - if (spew_debug) - fprintf (stderr, "\tsaved method of %d tokens from %s:%d\n", - meth->limit, starting.file, starting.line); -#endif - - DECL_PENDING_INLINE_INFO (decl) = meth; - DECL_PENDING_INLINE_P (decl) = 1; - - /* We need to know that this was defined in the class, so that - friend templates are handled correctly. */ - DECL_INITIALIZED_IN_CLASS_P (decl) = 1; - - if (pending_inlines_tail) - pending_inlines_tail->next = meth; - else - pending_inlines = meth; - pending_inlines_tail = meth; -} - -/* Consume a no-commas expression - a default argument - and return - a DEFAULT_ARG tree node. */ - -static tree -snarf_defarg () -{ - int yyc; - int plev = 0; - struct unparsed_text *buf; - tree arg; - location_t starting; - starting.file = input_filename; - starting.line = lineno; - - buf = alloc_unparsed_text (&starting, 0, 0); - - for (;;) - { - yyc = next_token (space_for_token (buf)); - - if (plev <= 0 && (yyc == ')' || yyc == ',')) - break; - else if (yyc == '(' || yyc == '[') - ++plev; - else if (yyc == ']' || yyc == ')') - --plev; - else if (yyc == 0) - { - error ("%Hend of file read inside default argument", &starting); - goto done; - } - } - - /* Unget the last token. */ - push_token (remove_last_token (buf)); - /* Add three END_OF_SAVED_INPUT tokens. We used to provide an - infinite stream of END_OF_SAVED_INPUT tokens -- but that can - cause the compiler to get stuck in an infinite loop when - encountering invalid code. We need more than one because the - parser sometimes peeks ahead several tokens. */ - memcpy (space_for_token (buf), &Teosi, sizeof (struct token)); - memcpy (space_for_token (buf), &Teosi, sizeof (struct token)); - memcpy (space_for_token (buf), &Teosi, sizeof (struct token)); - - done: -#ifdef SPEW_DEBUG - if (spew_debug) - fprintf (stderr, "\tsaved defarg of %d tokens from %s:%d\n", - buf->limit, starting.file, starting.line); -#endif - - arg = make_node (DEFAULT_ARG); - DEFARG_POINTER (arg) = (char *)buf; - - return arg; -} - -/* Decide whether the default argument we are about to see should be - gobbled up as text for later parsing. */ - -void -maybe_snarf_defarg () -{ - if (current_class_type && TYPE_BEING_DEFINED (current_class_type)) - do_snarf_defarg = 1; -} - -/* Called from grokfndecl to note a function decl with unparsed default - arguments for later processing. Also called from grokdeclarator - for function types with unparsed defargs; the call from grokfndecl - will always come second, so we can overwrite the entry from the type. */ - -void -add_defarg_fn (decl) - tree decl; -{ - if (TREE_CODE (decl) == FUNCTION_DECL) - TREE_VALUE (defarg_fns) = decl; - else - { - defarg_fns = tree_cons (NULL_TREE, decl, defarg_fns); - TREE_TYPE (defarg_fns) = current_class_type; - } -} - -/* Helper for do_pending_defargs. Starts the parsing of a default arg. */ - -static void -feed_defarg (p) - tree p; -{ - tree d = TREE_PURPOSE (p); - - feed_input ((struct unparsed_text *)DEFARG_POINTER (d)); - yychar = DEFARG_MARKER; - yylval.ttype = p; -} - -/* Helper for do_pending_defargs. Ends the parsing of a default arg. */ - -static void -finish_defarg () -{ - if (yychar == YYEMPTY) - yychar = yylex (); - if (yychar != END_OF_SAVED_INPUT) - error ("parse error at end of saved function text"); - - end_input (); -} - -/* Main function for deferred parsing of default arguments. Called from - the parser. */ - -void -do_pending_defargs () -{ - if (defarg_parm) - finish_defarg (); - - for (; defarg_fns;) - { - tree current = defarg_fns; - - tree defarg_fn = TREE_VALUE (defarg_fns); - if (defarg_parm == NULL_TREE) - { - push_nested_class (TREE_TYPE (defarg_fns), 1); - pushlevel (0); - if (TREE_CODE (defarg_fn) == FUNCTION_DECL) - maybe_begin_member_template_processing (defarg_fn); - - if (TREE_CODE (defarg_fn) == FUNCTION_DECL) - defarg_parm = TYPE_ARG_TYPES (TREE_TYPE (defarg_fn)); - else - defarg_parm = TYPE_ARG_TYPES (defarg_fn); - } - else - defarg_parm = TREE_CHAIN (defarg_parm); - - for (; defarg_parm; defarg_parm = TREE_CHAIN (defarg_parm)) - if (!TREE_PURPOSE (defarg_parm) - || TREE_CODE (TREE_PURPOSE (defarg_parm)) != DEFAULT_ARG) - ;/* OK */ - else if (TREE_PURPOSE (current) == error_mark_node) - DEFARG_POINTER (TREE_PURPOSE (defarg_parm)) = NULL; - else - { - feed_defarg (defarg_parm); - - /* Return to the parser, which will process this defarg - and call us again. */ - return; - } - - if (TREE_CODE (defarg_fn) == FUNCTION_DECL) - { - maybe_end_member_template_processing (); - check_default_args (defarg_fn); - } - - poplevel (0, 0, 0); - pop_nested_class (); - - defarg_fns = TREE_CHAIN (defarg_fns); - if (defarg_depfns) - { - /* This function's default args depend on unprocessed default args - of defarg_fns. We will need to reprocess this function, and - check for circular dependencies. */ - tree a, b; - - for (a = defarg_depfns, b = TREE_PURPOSE (current); a && b; - a = TREE_CHAIN (a), b = TREE_CHAIN (b)) - if (TREE_VALUE (a) != TREE_VALUE (b)) - goto different; - if (a || b) - { - different:; - TREE_CHAIN (current) = NULL_TREE; - defarg_fns = chainon (defarg_fns, current); - TREE_PURPOSE (current) = defarg_depfns; - } - else - { - cp_warning_at ("circular dependency in default args of `%#D'", defarg_fn); - /* No need to say what else is dependent, as they will be - picked up in another pass. */ - - /* Immediately repeat, but marked so that we break the loop. */ - defarg_fns = current; - TREE_PURPOSE (current) = error_mark_node; - } - defarg_depfns = NULL_TREE; - } - else if (TREE_PURPOSE (current) == error_mark_node) - defarg_fnsdone = tree_cons (NULL_TREE, defarg_fn, defarg_fnsdone); - } -} - -/* After parsing all the default arguments, we must clear any that remain, - which will be part of a circular dependency. */ -void -done_pending_defargs () -{ - for (; defarg_fnsdone; defarg_fnsdone = TREE_CHAIN (defarg_fnsdone)) - { - tree fn = TREE_VALUE (defarg_fnsdone); - tree parms; - - if (TREE_CODE (fn) == FUNCTION_DECL) - parms = TYPE_ARG_TYPES (TREE_TYPE (fn)); - else - parms = TYPE_ARG_TYPES (fn); - for (; parms; parms = TREE_CHAIN (parms)) - if (TREE_PURPOSE (parms) - && TREE_CODE (TREE_PURPOSE (parms)) == DEFAULT_ARG) - { - my_friendly_assert (!DEFARG_POINTER (TREE_PURPOSE (parms)), 20010107); - TREE_PURPOSE (parms) = NULL_TREE; - } - } -} - -/* In processing the current default arg, we called FN, but that call - required a default argument of FN, and that had not yet been processed. - Remember FN. */ - -void -unprocessed_defarg_fn (fn) - tree fn; -{ - defarg_depfns = tree_cons (NULL_TREE, fn, defarg_depfns); -} - -/* Called from the parser to update an element of TYPE_ARG_TYPES for some - FUNCTION_TYPE with the newly parsed version of its default argument, which - was previously digested as text. */ - -void -replace_defarg (arg, init) - tree arg, init; -{ - if (init == error_mark_node) - TREE_PURPOSE (arg) = error_mark_node; - else - { - if (! processing_template_decl - && ! can_convert_arg (TREE_VALUE (arg), TREE_TYPE (init), init)) - pedwarn ("invalid type `%T' for default argument to `%T'", - TREE_TYPE (init), TREE_VALUE (arg)); - if (!defarg_depfns) - TREE_PURPOSE (arg) = init; - } -} - -#ifdef SPEW_DEBUG -/* debug_yychar takes a yychar (token number) value and prints its name. */ - -static void -debug_yychar (yy) - int yy; -{ - if (yy<256) - fprintf (stderr, "->%d < %c >\n", lineno, yy); - else if (yy == IDENTIFIER || yy == tTYPENAME) - { - const char *id; - if (TREE_CODE (yylval.ttype) == IDENTIFIER_NODE) - id = IDENTIFIER_POINTER (yylval.ttype); - else if (TREE_CODE_CLASS (TREE_CODE (yylval.ttype)) == 'd') - id = IDENTIFIER_POINTER (DECL_NAME (yylval.ttype)); - else - id = ""; - fprintf (stderr, "->%d <%s `%s'>\n", lineno, debug_yytranslate (yy), id); - } - else - fprintf (stderr, "->%d <%s>\n", lineno, debug_yytranslate (yy)); -} - -#endif - -#define NAME(TYPE) cpp_type2name (TYPE) - -void -yyerror (msgid) - const char *msgid; -{ - const char *string = _(msgid); - - if (last_token == CPP_EOF) - error ("%s at end of input", string); - else if (last_token == CPP_CHAR || last_token == CPP_WCHAR) - { - if (yylval.ttype && TREE_CODE (yylval.ttype) == INTEGER_CST) - { - unsigned int val = TREE_INT_CST_LOW (yylval.ttype); - const char *const ell = (last_token == CPP_CHAR) ? "" : "L"; - if (val <= UCHAR_MAX && ISGRAPH (val)) - error ("%s before %s'%c'", string, ell, val); - else - error ("%s before %s'\\x%x'", string, ell, val); - } - else - error ("%s", string); - } - else if (last_token == CPP_STRING - || last_token == CPP_WSTRING) - error ("%s before string constant", string); - else if (last_token == CPP_NUMBER) - error ("%s before numeric constant", string); - else if (last_token == CPP_NAME) - { - if (TREE_CODE (last_token_id) == IDENTIFIER_NODE) - error ("%s before `%s'", string, IDENTIFIER_POINTER (last_token_id)); - else if (ISGRAPH (yychar)) - error ("%s before `%c'", string, yychar); - else - error ("%s before `\%o'", string, yychar); - } - else - error ("%s before `%s' token", string, NAME (last_token)); -} - -#include "gt-cp-spew.h" |