From c9ab9ae440a8066b2c2b85b157b1fdadcf09916a Mon Sep 17 00:00:00 2001 From: obrien Date: Fri, 1 Feb 2002 18:16:02 +0000 Subject: Enlist the FreeBSD-CURRENT users as testers of what is to become Gcc 3.1.0. These bits are taken from the FSF anoncvs repo on 1-Feb-2002 08:20 PST. --- contrib/gcc/cp/lex.c | 5157 +++++++++----------------------------------------- 1 file changed, 912 insertions(+), 4245 deletions(-) (limited to 'contrib/gcc/cp/lex.c') diff --git a/contrib/gcc/cp/lex.c b/contrib/gcc/cp/lex.c index d9f2262..0287f70 100644 --- a/contrib/gcc/cp/lex.c +++ b/contrib/gcc/cp/lex.c @@ -1,5 +1,6 @@ /* Separate lexical analyzer for GNU C++. - Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc. + Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2001 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -29,126 +30,65 @@ Boston, MA 02111-1307, USA. */ #include "system.h" #include "input.h" #include "tree.h" -#include "lex.h" #include "cp-tree.h" +#include "cpplib.h" +#include "c-lex.h" +#include "lex.h" #include "parse.h" #include "flags.h" -#include "obstack.h" #include "c-pragma.h" #include "toplev.h" #include "output.h" +#include "ggc.h" +#include "tm_p.h" +#include "timevar.h" +#include "diagnostic.h" #ifdef MULTIBYTE_CHARS #include "mbchar.h" #include #endif -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free +extern void yyprint PARAMS ((FILE *, int, YYSTYPE)); -#ifndef DIR_SEPARATOR -#define DIR_SEPARATOR '/' -#endif +static int interface_strcmp PARAMS ((const char *)); +static int *init_cpp_parse PARAMS ((void)); +static void init_cp_pragma PARAMS ((void)); + +static tree parse_strconst_pragma PARAMS ((const char *, int)); +static void handle_pragma_vtable PARAMS ((cpp_reader *)); +static void handle_pragma_unit PARAMS ((cpp_reader *)); +static void handle_pragma_interface PARAMS ((cpp_reader *)); +static void handle_pragma_implementation PARAMS ((cpp_reader *)); +static void handle_pragma_java_exceptions PARAMS ((cpp_reader *)); -extern struct obstack permanent_obstack; -extern struct obstack *current_obstack, *saveable_obstack; - -extern void yyprint PROTO((FILE *, int, YYSTYPE)); - -static tree get_time_identifier PROTO((const char *)); -static int check_newline PROTO((void)); -static int skip_white_space PROTO((int)); -static void finish_defarg PROTO((void)); -static int my_get_run_time PROTO((void)); -static int get_last_nonwhite_on_line PROTO((void)); -static int interface_strcmp PROTO((const char *)); -static int readescape PROTO((int *)); -static char *extend_token_buffer PROTO((const char *)); -static void consume_string PROTO((struct obstack *, int)); -static int set_typedecl_interface_info PROTO((tree *, void *)); -static void feed_defarg PROTO((tree, tree)); -static int set_vardecl_interface_info PROTO((tree *, void *)); -static void store_pending_inline PROTO((tree, struct pending_inline *)); -static void reinit_parse_for_expr PROTO((struct obstack *)); -static int *init_cpp_parse PROTO((void)); -static int handle_cp_pragma PROTO((const char *)); -#ifdef HANDLE_GENERIC_PRAGMAS -static int handle_generic_pragma PROTO((int)); -#endif #ifdef GATHER_STATISTICS #ifdef REDUCE_LENGTH -static int reduce_cmp PROTO((int *, int *)); -static int token_cmp PROTO((int *, int *)); +static int reduce_cmp PARAMS ((int *, int *)); +static int token_cmp PARAMS ((int *, int *)); #endif #endif -static void begin_definition_of_inclass_inline PROTO((struct pending_inline*)); -static void parse_float PROTO((PTR)); -static int is_global PROTO((tree)); -static void init_filename_times PROTO((void)); - -/* Given a file name X, return the nondirectory portion. - Keep in mind that X can be computed more than once. */ -char * -file_name_nondirectory (x) - const char *x; -{ - char *tmp = (char *) rindex (x, '/'); - if (DIR_SEPARATOR != '/' && ! tmp) - tmp = (char *) rindex (x, DIR_SEPARATOR); - if (tmp) - return (char *) (tmp + 1); - else - return (char *) x; -} - -/* This obstack is needed to hold text. It is not safe to use - TOKEN_BUFFER because `check_newline' calls `yylex'. */ -struct obstack inline_text_obstack; -char *inline_text_firstobj; +static int is_global PARAMS ((tree)); +static void init_operators PARAMS ((void)); +static void copy_lang_type PARAMS ((tree)); -#if USE_CPPLIB -#include "cpplib.h" -extern cpp_reader parse_in; -extern cpp_options parse_options; -extern unsigned char *yy_cur, *yy_lim; +/* A constraint that can be tested at compile time. */ +#ifdef __STDC__ +#define CONSTRAINT(name, expr) extern int constraint_##name [(expr) ? 1 : -1] #else -FILE *finput; +#define CONSTRAINT(name, expr) extern int constraint_/**/name [(expr) ? 1 : -1] #endif -int end_of_file; - -/* Pending language change. - Positive is push count, negative is pop count. */ -int pending_lang_change = 0; -/* Wrap the current header file in extern "C". */ -static int c_header_level = 0; - -extern int first_token; -extern struct obstack token_obstack; - -/* ??? Don't really know where this goes yet. */ -#if 1 -#include "input.c" -#else -extern void put_back (/* int */); -extern int input_redirected (); -extern void feed_input (/* char *, int */); -#endif +#include "cpplib.h" -/* Holds translations from TREE_CODEs to operator name strings, - i.e., opname_tab[PLUS_EXPR] == "+". */ -char **opname_tab; -char **assignop_tab; - extern int yychar; /* the lookahead symbol */ extern YYSTYPE yylval; /* the semantic value of the */ /* lookahead symbol */ -#if 0 -YYLTYPE yylloc; /* location data for the lookahead */ - /* symbol */ -#endif - +/* These flags are used by c-lex.c. In C++, they're always off and on, + respectively. */ +int warn_traditional = 0; +int flag_digraphs = 1; /* the declaration found for the last IDENTIFIER token read in. yylex must look this up to detect typedefs, which get token type TYPENAME, @@ -156,18 +96,36 @@ YYLTYPE yylloc; /* location data for the lookahead */ used in a context which makes it a reference to a variable. */ tree lastiddecl; -/* The elements of `ridpointers' are identifier nodes - for the reserved type names and storage classes. - It is indexed by a RID_... value. */ -tree ridpointers[(int) RID_MAX]; - -/* We may keep statistics about how long which files took to compile. */ -static int header_time, body_time; -static tree filename_times; -static tree this_filename_time; - /* Array for holding counts of the numbers of tokens seen. */ extern int *token_count; + +/* Functions and data structures for #pragma interface. + + `#pragma implementation' means that the main file being compiled + is considered to implement (provide) the classes that appear in + its main body. I.e., if this is file "foo.cc", and class `bar' + is defined in "foo.cc", then we say that "foo.cc implements bar". + + All main input files "implement" themselves automagically. + + `#pragma interface' means that unless this file (of the form "foo.h" + is not presently being included by file "foo.cc", the + CLASSTYPE_INTERFACE_ONLY bit gets set. The effect is that none + of the vtables nor any of the inline functions defined in foo.h + will ever be output. + + There are cases when we want to link files such as "defs.h" and + "main.cc". In this case, we give "defs.h" a `#pragma interface', + and "main.cc" has `#pragma implementation "defs.h"'. */ + +struct impl_files +{ + const char *filename; + struct impl_files *next; +}; + +static struct impl_files *impl_file_chain; + /* Return something to represent absolute declarators containing a *. TARGET is the absolute declarator that the * contains. @@ -184,7 +142,7 @@ make_pointer_declarator (cv_qualifiers, target) if (target && TREE_CODE (target) == IDENTIFIER_NODE && ANON_AGGRNAME_P (target)) error ("type name expected before `*'"); - target = build_parse_node (INDIRECT_REF, target); + target = build_nt (INDIRECT_REF, target); TREE_TYPE (target) = cv_qualifiers; return target; } @@ -196,7 +154,7 @@ make_pointer_declarator (cv_qualifiers, target) We return an ADDR_EXPR whose "contents" are TARGET and whose type is the modifier list. */ - + tree make_reference_declarator (cv_qualifiers, target) tree cv_qualifiers, target; @@ -216,7 +174,7 @@ make_reference_declarator (cv_qualifiers, target) if (TREE_CODE (target) == IDENTIFIER_NODE && ANON_AGGRNAME_P (target)) error ("type name expected before `&'"); } - target = build_parse_node (ADDR_EXPR, target); + target = build_nt (ADDR_EXPR, target); TREE_TYPE (target) = cv_qualifiers; return target; } @@ -225,8 +183,12 @@ tree make_call_declarator (target, parms, cv_qualifiers, exception_specification) tree target, parms, cv_qualifiers, exception_specification; { - target = build_parse_node (CALL_EXPR, target, parms, cv_qualifiers); - TREE_TYPE (target) = exception_specification; + target = build_nt (CALL_EXPR, target, + tree_cons (parms, cv_qualifiers, NULL_TREE), + /* The third operand is really RTL. We + shouldn't put anything there. */ + NULL_TREE); + CALL_DECLARATOR_EXCEPTION_SPEC (target) = exception_specification; return target; } @@ -234,54 +196,8 @@ void set_quals_and_spec (call_declarator, cv_qualifiers, exception_specification) tree call_declarator, cv_qualifiers, exception_specification; { - TREE_OPERAND (call_declarator, 2) = cv_qualifiers; - TREE_TYPE (call_declarator) = exception_specification; -} - -/* Build names and nodes for overloaded operators. */ - -tree ansi_opname[LAST_CPLUS_TREE_CODE]; -tree ansi_assopname[LAST_CPLUS_TREE_CODE]; - -char * -operator_name_string (name) - tree name; -{ - char *opname = IDENTIFIER_POINTER (name) + 2; - tree *opname_table; - int i, assign; - - /* Works for builtin and user defined types. */ - if (IDENTIFIER_GLOBAL_VALUE (name) - && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == TYPE_DECL) - return IDENTIFIER_POINTER (name); - - if (opname[0] == 'a' && opname[2] != '\0' && opname[2] != '_') - { - opname += 1; - assign = 1; - opname_table = ansi_assopname; - } - else - { - assign = 0; - opname_table = ansi_opname; - } - - for (i = 0; i < (int) LAST_CPLUS_TREE_CODE; i++) - { - if (opname[0] == IDENTIFIER_POINTER (opname_table[i])[2+assign] - && opname[1] == IDENTIFIER_POINTER (opname_table[i])[3+assign]) - break; - } - - if (i == LAST_CPLUS_TREE_CODE) - return ""; - - if (assign) - return assignop_tab[i]; - else - return opname_tab[i]; + CALL_DECLARATOR_QUALS (call_declarator) = cv_qualifiers; + CALL_DECLARATOR_EXCEPTION_SPEC (call_declarator) = exception_specification; } int interface_only; /* whether or not current file is only for @@ -289,75 +205,11 @@ int interface_only; /* whether or not current file is only for int interface_unknown; /* whether or not we know this class to behave according to #pragma interface. */ -/* lexical analyzer */ - -#ifndef WCHAR_TYPE_SIZE -#ifdef INT_TYPE_SIZE -#define WCHAR_TYPE_SIZE INT_TYPE_SIZE -#else -#define WCHAR_TYPE_SIZE BITS_PER_WORD -#endif -#endif - -/* Number of bytes in a wide character. */ -#define WCHAR_BYTES (WCHAR_TYPE_SIZE / BITS_PER_UNIT) - -static int maxtoken; /* Current nominal length of token buffer. */ -char *token_buffer; /* Pointer to token buffer. - Actual allocated length is maxtoken + 2. */ - -#include "hash.h" - - -/* Nonzero tells yylex to ignore \ in string constants. */ -static int ignore_escape_flag = 0; - -static tree -get_time_identifier (name) - const char *name; -{ - tree time_identifier; - int len = strlen (name); - char *buf = (char *) alloca (len + 6); - strcpy (buf, "file "); - bcopy (name, buf+5, len); - buf[len+5] = '\0'; - time_identifier = get_identifier (buf); - if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE) - { - push_obstacks_nochange (); - end_temporary_allocation (); - TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0); - TIME_IDENTIFIER_FILEINFO (time_identifier) - = build_int_2 (0, 1); - SET_IDENTIFIER_GLOBAL_VALUE (time_identifier, filename_times); - filename_times = time_identifier; - pop_obstacks (); - } - return time_identifier; -} - -#ifdef __GNUC__ -__inline -#endif -static int -my_get_run_time () -{ - int old_quiet_flag = quiet_flag; - int this_time; - quiet_flag = 0; - this_time = get_run_time (); - quiet_flag = old_quiet_flag; - return this_time; -} - -/* Table indexed by tree code giving a string containing a character - classifying the tree code. Possibilities are - t, d, s, c, r, <, 1 and 2. See cp/cp-tree.def for details. */ +/* Tree code classes. */ #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE, -char cplus_tree_code_type[] = { +static const char cplus_tree_code_type[] = { 'x', #include "cp-tree.def" }; @@ -369,7 +221,7 @@ char cplus_tree_code_type[] = { #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH, -int cplus_tree_code_length[] = { +static const int cplus_tree_code_length[] = { 0, #include "cp-tree.def" }; @@ -379,335 +231,485 @@ int cplus_tree_code_length[] = { Used for printing out the tree and error messages. */ #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME, -const char *cplus_tree_code_name[] = { +static const char *const cplus_tree_code_name[] = { "@@dummy", #include "cp-tree.def" }; #undef DEFTREECODE -/* toplev.c needs to call these. */ - -void -lang_init_options () -{ -#if USE_CPPLIB - cpp_reader_init (&parse_in); - parse_in.opts = &parse_options; - cpp_options_init (&parse_options); -#endif - - /* Default exceptions on. */ - flag_exceptions = 1; -} - +/* Post-switch processing. */ void -lang_init () +cxx_post_options () { - /* the beginning of the file is a new line; check for # */ - /* With luck, we discover the real source file's name from that - and put it in input_filename. */ -#if ! USE_CPPLIB - put_back (check_newline ()); -#else - check_newline (); - yy_cur--; -#endif - if (flag_gnu_xref) GNU_xref_begin (input_filename); - init_repo (input_filename); + c_common_post_options (); } +/* Initialization before switch parsing. */ void -lang_finish () +cxx_init_options () { - extern int errorcount, sorrycount; - if (flag_gnu_xref) GNU_xref_end (errorcount+sorrycount); -} - -char * -lang_identify () -{ - return "cplusplus"; -} + c_common_init_options (clk_cplusplus); -static void -init_filename_times () -{ - this_filename_time = get_time_identifier (""); - if (flag_detailed_statistics) - { - header_time = 0; - body_time = my_get_run_time (); - TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time)) - = body_time; - } + /* Default exceptions on. */ + flag_exceptions = 1; + /* By default wrap lines at 80 characters. Is getenv ("COLUMNS") + preferable? */ + diagnostic_line_cutoff (global_dc) = 80; + /* By default, emit location information once for every + diagnostic message. */ + diagnostic_prefixing_rule (global_dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE; } -/* Change by Bryan Boreham, Kewill, Thu Jul 27 09:46:05 1989. - Stuck this hack in to get the files open correctly; this is called - in place of init_parse if we are an unexec'd binary. */ - -#if 0 void -reinit_lang_specific () +cxx_finish () { - init_filename_times (); - reinit_search_statistics (); + if (flag_gnu_xref) + GNU_xref_end (errorcount + sorrycount); + c_common_finish (); } -#endif static int * init_cpp_parse () { #ifdef GATHER_STATISTICS #ifdef REDUCE_LENGTH - reduce_count = (int *)malloc (sizeof (int) * (REDUCE_LENGTH + 1)); - bzero (reduce_count, sizeof (int) * (REDUCE_LENGTH + 1)); + reduce_count = (int *) xcalloc (sizeof (int), (REDUCE_LENGTH + 1)); reduce_count += 1; - token_count = (int *)malloc (sizeof (int) * (TOKEN_LENGTH + 1)); - bzero (token_count, sizeof (int) * (TOKEN_LENGTH + 1)); + token_count = (int *) xcalloc (sizeof (int), (TOKEN_LENGTH + 1)); token_count += 1; #endif #endif return token_count; } -char * -init_parse (filename) - char *filename; -{ - extern int flag_no_gnu_keywords; - extern int flag_operator_names; +/* A mapping from tree codes to operator name information. */ +operator_name_info_t operator_name_info[(int) LAST_CPLUS_TREE_CODE]; +/* Similar, but for assignment operators. */ +operator_name_info_t assignment_operator_name_info[(int) LAST_CPLUS_TREE_CODE]; - int i; +/* Initialize data structures that keep track of operator names. */ -#ifdef MULTIBYTE_CHARS - /* Change to the native locale for multibyte conversions. */ - setlocale (LC_CTYPE, ""); - literal_codeset = getenv ("LANG"); -#endif +#define DEF_OPERATOR(NAME, C, M, AR, AP) \ + CONSTRAINT (C, sizeof "operator " + sizeof NAME <= 256); +#include "operators.def" +#undef DEF_OPERATOR -#if USE_CPPLIB - parse_in.show_column = 1; - if (! cpp_start_read (&parse_in, filename)) - abort (); +static void +init_operators () +{ + tree identifier; + char buffer[256]; + struct operator_name_info_t *oni; + +#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, ASSN_P) \ + sprintf (buffer, ISALPHA (NAME[0]) ? "operator %s" : "operator%s", NAME); \ + identifier = get_identifier (buffer); \ + IDENTIFIER_OPNAME_P (identifier) = 1; \ + \ + oni = (ASSN_P \ + ? &assignment_operator_name_info[(int) CODE] \ + : &operator_name_info[(int) CODE]); \ + oni->identifier = identifier; \ + oni->name = NAME; \ + oni->mangled_name = MANGLING; + +#include "operators.def" +#undef DEF_OPERATOR + + operator_name_info[(int) ERROR_MARK].identifier + = get_identifier (""); + + /* Handle some special cases. These operators are not defined in + the language, but can be produced internally. We may need them + for error-reporting. (Eventually, we should ensure that this + does not happen. Error messages involving these operators will + be confusing to users.) */ + + operator_name_info [(int) INIT_EXPR].name + = operator_name_info [(int) MODIFY_EXPR].name; + operator_name_info [(int) EXACT_DIV_EXPR].name = "(ceiling /)"; + operator_name_info [(int) CEIL_DIV_EXPR].name = "(ceiling /)"; + operator_name_info [(int) FLOOR_DIV_EXPR].name = "(floor /)"; + operator_name_info [(int) ROUND_DIV_EXPR].name = "(round /)"; + operator_name_info [(int) CEIL_MOD_EXPR].name = "(ceiling %)"; + operator_name_info [(int) FLOOR_MOD_EXPR].name = "(floor %)"; + operator_name_info [(int) ROUND_MOD_EXPR].name = "(round %)"; + operator_name_info [(int) ABS_EXPR].name = "abs"; + operator_name_info [(int) FFS_EXPR].name = "ffs"; + operator_name_info [(int) BIT_ANDTC_EXPR].name = "&~"; + operator_name_info [(int) TRUTH_AND_EXPR].name = "strict &&"; + operator_name_info [(int) TRUTH_OR_EXPR].name = "strict ||"; + operator_name_info [(int) IN_EXPR].name = "in"; + operator_name_info [(int) RANGE_EXPR].name = "..."; + operator_name_info [(int) CONVERT_EXPR].name = "+"; + + assignment_operator_name_info [(int) EXACT_DIV_EXPR].name + = "(exact /=)"; + assignment_operator_name_info [(int) CEIL_DIV_EXPR].name + = "(ceiling /=)"; + assignment_operator_name_info [(int) FLOOR_DIV_EXPR].name + = "(floor /=)"; + assignment_operator_name_info [(int) ROUND_DIV_EXPR].name + = "(round /=)"; + assignment_operator_name_info [(int) CEIL_MOD_EXPR].name + = "(ceiling %=)"; + assignment_operator_name_info [(int) FLOOR_MOD_EXPR].name + = "(floor %=)"; + assignment_operator_name_info [(int) ROUND_MOD_EXPR].name + = "(round %=)"; +} + +/* The reserved keyword table. */ +struct resword +{ + const char *const word; + const ENUM_BITFIELD(rid) rid : 16; + const unsigned int disable : 16; +}; - /* cpp_start_read always puts at least one line directive into the - token buffer. We must arrange to read it out here. */ - yy_cur = parse_in.token_buffer; - yy_lim = CPP_PWRITTEN (&parse_in); +/* Disable mask. Keywords are disabled if (reswords[i].disable & mask) is + _true_. */ +#define D_EXT 0x01 /* GCC extension */ +#define D_ASM 0x02 /* in C99, but has a switch to turn it off */ +#define D_OPNAME 0x04 /* operator names */ + +CONSTRAINT(ridbits_fit, RID_LAST_MODIFIER < sizeof(unsigned long) * CHAR_BIT); + +static const struct resword reswords[] = +{ + { "_Complex", RID_COMPLEX, 0 }, + { "__FUNCTION__", RID_FUNCTION_NAME, 0 }, + { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 }, + { "__alignof", RID_ALIGNOF, 0 }, + { "__alignof__", RID_ALIGNOF, 0 }, + { "__asm", RID_ASM, 0 }, + { "__asm__", RID_ASM, 0 }, + { "__attribute", RID_ATTRIBUTE, 0 }, + { "__attribute__", RID_ATTRIBUTE, 0 }, + { "__builtin_va_arg", RID_VA_ARG, 0 }, + { "__complex", RID_COMPLEX, 0 }, + { "__complex__", RID_COMPLEX, 0 }, + { "__const", RID_CONST, 0 }, + { "__const__", RID_CONST, 0 }, + { "__extension__", RID_EXTENSION, 0 }, + { "__func__", RID_C99_FUNCTION_NAME, 0 }, + { "__imag", RID_IMAGPART, 0 }, + { "__imag__", RID_IMAGPART, 0 }, + { "__inline", RID_INLINE, 0 }, + { "__inline__", RID_INLINE, 0 }, + { "__label__", RID_LABEL, 0 }, + { "__null", RID_NULL, 0 }, + { "__real", RID_REALPART, 0 }, + { "__real__", RID_REALPART, 0 }, + { "__restrict", RID_RESTRICT, 0 }, + { "__restrict__", RID_RESTRICT, 0 }, + { "__signed", RID_SIGNED, 0 }, + { "__signed__", RID_SIGNED, 0 }, + { "__typeof", RID_TYPEOF, 0 }, + { "__typeof__", RID_TYPEOF, 0 }, + { "__volatile", RID_VOLATILE, 0 }, + { "__volatile__", RID_VOLATILE, 0 }, + { "asm", RID_ASM, D_ASM }, + { "and", RID_AND, D_OPNAME }, + { "and_eq", RID_AND_EQ, D_OPNAME }, + { "auto", RID_AUTO, 0 }, + { "bitand", RID_BITAND, D_OPNAME }, + { "bitor", RID_BITOR, D_OPNAME }, + { "bool", RID_BOOL, 0 }, + { "break", RID_BREAK, 0 }, + { "case", RID_CASE, 0 }, + { "catch", RID_CATCH, 0 }, + { "char", RID_CHAR, 0 }, + { "class", RID_CLASS, 0 }, + { "compl", RID_COMPL, D_OPNAME }, + { "const", RID_CONST, 0 }, + { "const_cast", RID_CONSTCAST, 0 }, + { "continue", RID_CONTINUE, 0 }, + { "default", RID_DEFAULT, 0 }, + { "delete", RID_DELETE, 0 }, + { "do", RID_DO, 0 }, + { "double", RID_DOUBLE, 0 }, + { "dynamic_cast", RID_DYNCAST, 0 }, + { "else", RID_ELSE, 0 }, + { "enum", RID_ENUM, 0 }, + { "explicit", RID_EXPLICIT, 0 }, + { "export", RID_EXPORT, 0 }, + { "extern", RID_EXTERN, 0 }, + { "false", RID_FALSE, 0 }, + { "float", RID_FLOAT, 0 }, + { "for", RID_FOR, 0 }, + { "friend", RID_FRIEND, 0 }, + { "goto", RID_GOTO, 0 }, + { "if", RID_IF, 0 }, + { "inline", RID_INLINE, 0 }, + { "int", RID_INT, 0 }, + { "long", RID_LONG, 0 }, + { "mutable", RID_MUTABLE, 0 }, + { "namespace", RID_NAMESPACE, 0 }, + { "new", RID_NEW, 0 }, + { "not", RID_NOT, D_OPNAME }, + { "not_eq", RID_NOT_EQ, D_OPNAME }, + { "operator", RID_OPERATOR, 0 }, + { "or", RID_OR, D_OPNAME }, + { "or_eq", RID_OR_EQ, D_OPNAME }, + { "private", RID_PRIVATE, 0 }, + { "protected", RID_PROTECTED, 0 }, + { "public", RID_PUBLIC, 0 }, + { "register", RID_REGISTER, 0 }, + { "reinterpret_cast", RID_REINTCAST, 0 }, + { "return", RID_RETURN, 0 }, + { "short", RID_SHORT, 0 }, + { "signed", RID_SIGNED, 0 }, + { "sizeof", RID_SIZEOF, 0 }, + { "static", RID_STATIC, 0 }, + { "static_cast", RID_STATCAST, 0 }, + { "struct", RID_STRUCT, 0 }, + { "switch", RID_SWITCH, 0 }, + { "template", RID_TEMPLATE, 0 }, + { "this", RID_THIS, 0 }, + { "throw", RID_THROW, 0 }, + { "true", RID_TRUE, 0 }, + { "try", RID_TRY, 0 }, + { "typedef", RID_TYPEDEF, 0 }, + { "typename", RID_TYPENAME, 0 }, + { "typeid", RID_TYPEID, 0 }, + { "typeof", RID_TYPEOF, D_ASM|D_EXT }, + { "union", RID_UNION, 0 }, + { "unsigned", RID_UNSIGNED, 0 }, + { "using", RID_USING, 0 }, + { "virtual", RID_VIRTUAL, 0 }, + { "void", RID_VOID, 0 }, + { "volatile", RID_VOLATILE, 0 }, + { "wchar_t", RID_WCHAR, 0 }, + { "while", RID_WHILE, 0 }, + { "xor", RID_XOR, D_OPNAME }, + { "xor_eq", RID_XOR_EQ, D_OPNAME }, -#else - /* Open input file. */ - if (filename == 0 || !strcmp (filename, "-")) +}; +#define N_reswords (sizeof reswords / sizeof (struct resword)) + +/* Table mapping from RID_* constants to yacc token numbers. + Unfortunately we have to have entries for all the keywords in all + three languages. */ +const short rid_to_yy[RID_MAX] = +{ + /* RID_STATIC */ SCSPEC, + /* RID_UNSIGNED */ TYPESPEC, + /* RID_LONG */ TYPESPEC, + /* RID_CONST */ CV_QUALIFIER, + /* RID_EXTERN */ SCSPEC, + /* RID_REGISTER */ SCSPEC, + /* RID_TYPEDEF */ SCSPEC, + /* RID_SHORT */ TYPESPEC, + /* RID_INLINE */ SCSPEC, + /* RID_VOLATILE */ CV_QUALIFIER, + /* RID_SIGNED */ TYPESPEC, + /* RID_AUTO */ SCSPEC, + /* RID_RESTRICT */ CV_QUALIFIER, + + /* C extensions. Bounded pointers are not yet in C++ */ + /* RID_BOUNDED */ 0, + /* RID_UNBOUNDED */ 0, + /* RID_COMPLEX */ TYPESPEC, + + /* C++ */ + /* RID_FRIEND */ SCSPEC, + /* RID_VIRTUAL */ SCSPEC, + /* RID_EXPLICIT */ SCSPEC, + /* RID_EXPORT */ EXPORT, + /* RID_MUTABLE */ SCSPEC, + + /* ObjC */ + /* RID_IN */ 0, + /* RID_OUT */ 0, + /* RID_INOUT */ 0, + /* RID_BYCOPY */ 0, + /* RID_BYREF */ 0, + /* RID_ONEWAY */ 0, + + /* C */ + /* RID_INT */ TYPESPEC, + /* RID_CHAR */ TYPESPEC, + /* RID_FLOAT */ TYPESPEC, + /* RID_DOUBLE */ TYPESPEC, + /* RID_VOID */ TYPESPEC, + /* RID_ENUM */ ENUM, + /* RID_STRUCT */ AGGR, + /* RID_UNION */ AGGR, + /* RID_IF */ IF, + /* RID_ELSE */ ELSE, + /* RID_WHILE */ WHILE, + /* RID_DO */ DO, + /* RID_FOR */ FOR, + /* RID_SWITCH */ SWITCH, + /* RID_CASE */ CASE, + /* RID_DEFAULT */ DEFAULT, + /* RID_BREAK */ BREAK, + /* RID_CONTINUE */ CONTINUE, + /* RID_RETURN */ RETURN_KEYWORD, + /* RID_GOTO */ GOTO, + /* RID_SIZEOF */ SIZEOF, + + /* C extensions */ + /* RID_ASM */ ASM_KEYWORD, + /* RID_TYPEOF */ TYPEOF, + /* RID_ALIGNOF */ ALIGNOF, + /* RID_ATTRIBUTE */ ATTRIBUTE, + /* RID_VA_ARG */ VA_ARG, + /* RID_EXTENSION */ EXTENSION, + /* RID_IMAGPART */ IMAGPART, + /* RID_REALPART */ REALPART, + /* RID_LABEL */ LABEL, + /* RID_PTRBASE */ 0, + /* RID_PTREXTENT */ 0, + /* RID_PTRVALUE */ 0, + /* RID_CHOOSE_EXPR */ 0, + /* RID_TYPES_COMPATIBLE_P */ 0, + + /* RID_FUNCTION_NAME */ VAR_FUNC_NAME, + /* RID_PRETTY_FUNCTION_NAME */ VAR_FUNC_NAME, + /* RID_c99_FUNCTION_NAME */ VAR_FUNC_NAME, + + /* C++ */ + /* RID_BOOL */ TYPESPEC, + /* RID_WCHAR */ TYPESPEC, + /* RID_CLASS */ AGGR, + /* RID_PUBLIC */ VISSPEC, + /* RID_PRIVATE */ VISSPEC, + /* RID_PROTECTED */ VISSPEC, + /* RID_TEMPLATE */ TEMPLATE, + /* RID_NULL */ CONSTANT, + /* RID_CATCH */ CATCH, + /* RID_DELETE */ DELETE, + /* RID_FALSE */ CXX_FALSE, + /* RID_NAMESPACE */ NAMESPACE, + /* RID_NEW */ NEW, + /* RID_OPERATOR */ OPERATOR, + /* RID_THIS */ THIS, + /* RID_THROW */ THROW, + /* RID_TRUE */ CXX_TRUE, + /* RID_TRY */ TRY, + /* RID_TYPENAME */ TYPENAME_KEYWORD, + /* RID_TYPEID */ TYPEID, + /* RID_USING */ USING, + + /* casts */ + /* RID_CONSTCAST */ CONST_CAST, + /* RID_DYNCAST */ DYNAMIC_CAST, + /* RID_REINTCAST */ REINTERPRET_CAST, + /* RID_STATCAST */ STATIC_CAST, + + /* alternate spellings */ + /* RID_AND */ ANDAND, + /* RID_AND_EQ */ ASSIGN, + /* RID_NOT */ '!', + /* RID_NOT_EQ */ EQCOMPARE, + /* RID_OR */ OROR, + /* RID_OR_EQ */ ASSIGN, + /* RID_XOR */ '^', + /* RID_XOR_EQ */ ASSIGN, + /* RID_BITAND */ '&', + /* RID_BITOR */ '|', + /* RID_COMPL */ '~', + + /* Objective C */ + /* RID_ID */ 0, + /* RID_AT_ENCODE */ 0, + /* RID_AT_END */ 0, + /* RID_AT_CLASS */ 0, + /* RID_AT_ALIAS */ 0, + /* RID_AT_DEFS */ 0, + /* RID_AT_PRIVATE */ 0, + /* RID_AT_PROTECTED */ 0, + /* RID_AT_PUBLIC */ 0, + /* RID_AT_PROTOCOL */ 0, + /* RID_AT_SELECTOR */ 0, + /* RID_AT_INTERFACE */ 0, + /* RID_AT_IMPLEMENTATION */ 0 +}; + +void +init_reswords () +{ + unsigned int i; + tree id; + int mask = ((flag_operator_names ? 0 : D_OPNAME) + | (flag_no_asm ? D_ASM : 0) + | (flag_no_gnu_keywords ? D_EXT : 0)); + + /* It is not necessary to register ridpointers as a GC root, because + all the trees it points to are permanently interned in the + get_identifier hash anyway. */ + ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree)); + for (i = 0; i < N_reswords; i++) { - finput = stdin; - filename = "stdin"; + id = get_identifier (reswords[i].word); + C_RID_CODE (id) = reswords[i].rid; + ridpointers [(int) reswords[i].rid] = id; + if (! (reswords[i].disable & mask)) + C_IS_RESERVED_WORD (id) = 1; } - else - finput = fopen (filename, "r"); - if (finput == 0) - pfatal_with_name (filename); +} -#ifdef IO_BUFFER_SIZE - setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE); -#endif -#endif /* !USE_CPPLIB */ +static void +init_cp_pragma () +{ + cpp_register_pragma (parse_in, 0, "vtable", handle_pragma_vtable); + cpp_register_pragma (parse_in, 0, "unit", handle_pragma_unit); - /* Initialize the lookahead machinery. */ - init_spew (); + cpp_register_pragma (parse_in, 0, "interface", handle_pragma_interface); + cpp_register_pragma (parse_in, 0, "implementation", + handle_pragma_implementation); + + cpp_register_pragma (parse_in, "GCC", "interface", handle_pragma_interface); + cpp_register_pragma (parse_in, "GCC", "implementation", + handle_pragma_implementation); + cpp_register_pragma (parse_in, "GCC", "java_exceptions", + handle_pragma_java_exceptions); +} - /* Make identifier nodes long enough for the language-specific slots. */ - set_identifier_size (sizeof (struct lang_identifier)); +/* Initialize the C++ front end. This function is very sensitive to + the exact order that things are done here. It would be nice if the + initialization done by this routine were moved to its subroutines, + and the ordering dependencies clarified and reduced. */ +const char * +cxx_init (filename) + const char *filename; +{ decl_printable_name = lang_printable_name; + input_filename = ""; + init_reswords (); + init_spew (); + init_tree (); init_cplus_expand (); + init_cp_semantics (); - bcopy (cplus_tree_code_type, - tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE, - (int)LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE); - bcopy ((char *)cplus_tree_code_length, - (char *)(tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE), - (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (int)); - bcopy ((char *)cplus_tree_code_name, - (char *)(tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE), - (LAST_CPLUS_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *)); - - opname_tab = (char **)oballoc ((int)LAST_CPLUS_TREE_CODE * sizeof (char *)); - bzero ((char *)opname_tab, (int)LAST_CPLUS_TREE_CODE * sizeof (char *)); - assignop_tab = (char **)oballoc ((int)LAST_CPLUS_TREE_CODE * sizeof (char *)); - bzero ((char *)assignop_tab, (int)LAST_CPLUS_TREE_CODE * sizeof (char *)); - - ansi_opname[0] = get_identifier (""); - for (i = 0; i < (int) LAST_CPLUS_TREE_CODE; i++) - { - ansi_opname[i] = ansi_opname[0]; - ansi_assopname[i] = ansi_opname[0]; - } + add_c_tree_codes (); - ansi_opname[(int) MULT_EXPR] = get_identifier ("__ml"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) MULT_EXPR]) = 1; - ansi_opname[(int) INDIRECT_REF] = ansi_opname[(int) MULT_EXPR]; - ansi_assopname[(int) MULT_EXPR] = get_identifier ("__aml"); - IDENTIFIER_OPNAME_P (ansi_assopname[(int) MULT_EXPR]) = 1; - ansi_assopname[(int) INDIRECT_REF] = ansi_assopname[(int) MULT_EXPR]; - ansi_opname[(int) TRUNC_MOD_EXPR] = get_identifier ("__md"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUNC_MOD_EXPR]) = 1; - ansi_assopname[(int) TRUNC_MOD_EXPR] = get_identifier ("__amd"); - IDENTIFIER_OPNAME_P (ansi_assopname[(int) TRUNC_MOD_EXPR]) = 1; - ansi_opname[(int) CEIL_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR]; - ansi_opname[(int) FLOOR_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR]; - ansi_opname[(int) ROUND_MOD_EXPR] = ansi_opname[(int) TRUNC_MOD_EXPR]; - ansi_opname[(int) MINUS_EXPR] = get_identifier ("__mi"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) MINUS_EXPR]) = 1; - ansi_opname[(int) NEGATE_EXPR] = ansi_opname[(int) MINUS_EXPR]; - ansi_assopname[(int) MINUS_EXPR] = get_identifier ("__ami"); - IDENTIFIER_OPNAME_P (ansi_assopname[(int) MINUS_EXPR]) = 1; - ansi_assopname[(int) NEGATE_EXPR] = ansi_assopname[(int) MINUS_EXPR]; - ansi_opname[(int) RSHIFT_EXPR] = get_identifier ("__rs"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) RSHIFT_EXPR]) = 1; - ansi_assopname[(int) RSHIFT_EXPR] = get_identifier ("__ars"); - IDENTIFIER_OPNAME_P (ansi_assopname[(int) RSHIFT_EXPR]) = 1; - ansi_opname[(int) NE_EXPR] = get_identifier ("__ne"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) NE_EXPR]) = 1; - ansi_opname[(int) GT_EXPR] = get_identifier ("__gt"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) GT_EXPR]) = 1; - ansi_opname[(int) GE_EXPR] = get_identifier ("__ge"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) GE_EXPR]) = 1; - ansi_opname[(int) BIT_IOR_EXPR] = get_identifier ("__or"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_IOR_EXPR]) = 1; - ansi_assopname[(int) BIT_IOR_EXPR] = get_identifier ("__aor"); - IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_IOR_EXPR]) = 1; - ansi_opname[(int) TRUTH_ANDIF_EXPR] = get_identifier ("__aa"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_ANDIF_EXPR]) = 1; - ansi_opname[(int) TRUTH_NOT_EXPR] = get_identifier ("__nt"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_NOT_EXPR]) = 1; - ansi_opname[(int) PREINCREMENT_EXPR] = get_identifier ("__pp"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) PREINCREMENT_EXPR]) = 1; - ansi_opname[(int) POSTINCREMENT_EXPR] = ansi_opname[(int) PREINCREMENT_EXPR]; - ansi_opname[(int) MODIFY_EXPR] = get_identifier ("__as"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) MODIFY_EXPR]) = 1; - ansi_assopname[(int) NOP_EXPR] = ansi_opname[(int) MODIFY_EXPR]; - ansi_opname[(int) COMPOUND_EXPR] = get_identifier ("__cm"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) COMPOUND_EXPR]) = 1; - ansi_opname[(int) EXACT_DIV_EXPR] = get_identifier ("__dv"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) EXACT_DIV_EXPR]) = 1; - ansi_assopname[(int) EXACT_DIV_EXPR] = get_identifier ("__adv"); - IDENTIFIER_OPNAME_P (ansi_assopname[(int) EXACT_DIV_EXPR]) = 1; - ansi_opname[(int) TRUNC_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR]; - ansi_opname[(int) CEIL_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR]; - ansi_opname[(int) FLOOR_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR]; - ansi_opname[(int) ROUND_DIV_EXPR] = ansi_opname[(int) EXACT_DIV_EXPR]; - ansi_opname[(int) PLUS_EXPR] = get_identifier ("__pl"); - ansi_assopname[(int) TRUNC_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR]; - ansi_assopname[(int) CEIL_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR]; - ansi_assopname[(int) FLOOR_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR]; - ansi_assopname[(int) ROUND_DIV_EXPR] = ansi_assopname[(int) EXACT_DIV_EXPR]; - IDENTIFIER_OPNAME_P (ansi_opname[(int) PLUS_EXPR]) = 1; - ansi_assopname[(int) PLUS_EXPR] = get_identifier ("__apl"); - IDENTIFIER_OPNAME_P (ansi_assopname[(int) PLUS_EXPR]) = 1; - ansi_opname[(int) CONVERT_EXPR] = ansi_opname[(int) PLUS_EXPR]; - ansi_assopname[(int) CONVERT_EXPR] = ansi_assopname[(int) PLUS_EXPR]; - ansi_opname[(int) LSHIFT_EXPR] = get_identifier ("__ls"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) LSHIFT_EXPR]) = 1; - ansi_assopname[(int) LSHIFT_EXPR] = get_identifier ("__als"); - IDENTIFIER_OPNAME_P (ansi_assopname[(int) LSHIFT_EXPR]) = 1; - ansi_opname[(int) EQ_EXPR] = get_identifier ("__eq"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) EQ_EXPR]) = 1; - ansi_opname[(int) LT_EXPR] = get_identifier ("__lt"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) LT_EXPR]) = 1; - ansi_opname[(int) LE_EXPR] = get_identifier ("__le"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) LE_EXPR]) = 1; - ansi_opname[(int) BIT_AND_EXPR] = get_identifier ("__ad"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_AND_EXPR]) = 1; - ansi_assopname[(int) BIT_AND_EXPR] = get_identifier ("__aad"); - IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_AND_EXPR]) = 1; - ansi_opname[(int) ADDR_EXPR] = ansi_opname[(int) BIT_AND_EXPR]; - ansi_assopname[(int) ADDR_EXPR] = ansi_assopname[(int) BIT_AND_EXPR]; - ansi_opname[(int) BIT_XOR_EXPR] = get_identifier ("__er"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_XOR_EXPR]) = 1; - ansi_assopname[(int) BIT_XOR_EXPR] = get_identifier ("__aer"); - IDENTIFIER_OPNAME_P (ansi_assopname[(int) BIT_XOR_EXPR]) = 1; - ansi_opname[(int) TRUTH_ORIF_EXPR] = get_identifier ("__oo"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) TRUTH_ORIF_EXPR]) = 1; - ansi_opname[(int) BIT_NOT_EXPR] = get_identifier ("__co"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) BIT_NOT_EXPR]) = 1; - ansi_opname[(int) PREDECREMENT_EXPR] = get_identifier ("__mm"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) PREDECREMENT_EXPR]) = 1; - ansi_opname[(int) POSTDECREMENT_EXPR] = ansi_opname[(int) PREDECREMENT_EXPR]; - ansi_opname[(int) COMPONENT_REF] = get_identifier ("__rf"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) COMPONENT_REF]) = 1; - ansi_opname[(int) MEMBER_REF] = get_identifier ("__rm"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) MEMBER_REF]) = 1; - ansi_opname[(int) CALL_EXPR] = get_identifier ("__cl"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) CALL_EXPR]) = 1; - ansi_opname[(int) ARRAY_REF] = get_identifier ("__vc"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) ARRAY_REF]) = 1; - ansi_opname[(int) NEW_EXPR] = get_identifier ("__nw"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) NEW_EXPR]) = 1; - ansi_opname[(int) DELETE_EXPR] = get_identifier ("__dl"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) DELETE_EXPR]) = 1; - ansi_opname[(int) VEC_NEW_EXPR] = get_identifier ("__vn"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_NEW_EXPR]) = 1; - ansi_opname[(int) VEC_DELETE_EXPR] = get_identifier ("__vd"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) VEC_DELETE_EXPR]) = 1; - ansi_opname[(int) TYPE_EXPR] = get_identifier (OPERATOR_TYPENAME_FORMAT); - IDENTIFIER_OPNAME_P (ansi_opname[(int) TYPE_EXPR]) = 1; - - /* This is not true: these operators are not defined in ANSI, - but we need them anyway. */ - ansi_opname[(int) MIN_EXPR] = get_identifier ("__mn"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) MIN_EXPR]) = 1; - ansi_opname[(int) MAX_EXPR] = get_identifier ("__mx"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) MAX_EXPR]) = 1; - ansi_opname[(int) COND_EXPR] = get_identifier ("__cn"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) COND_EXPR]) = 1; - ansi_opname[(int) SIZEOF_EXPR] = get_identifier ("__sz"); - IDENTIFIER_OPNAME_P (ansi_opname[(int) SIZEOF_EXPR]) = 1; + memcpy (tree_code_type + (int) LAST_C_TREE_CODE, + cplus_tree_code_type, + (int)LAST_CPLUS_TREE_CODE - (int)LAST_C_TREE_CODE); + memcpy (tree_code_length + (int) LAST_C_TREE_CODE, + cplus_tree_code_length, + (LAST_CPLUS_TREE_CODE - (int)LAST_C_TREE_CODE) * sizeof (int)); + memcpy (tree_code_name + (int) LAST_C_TREE_CODE, + cplus_tree_code_name, + (LAST_CPLUS_TREE_CODE - (int)LAST_C_TREE_CODE) * sizeof (char *)); + init_operators (); init_method (); init_error (); - gcc_obstack_init (&inline_text_obstack); - inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0); - /* Start it at 0, because check_newline is called at the very beginning - and will increment it to 1. */ - lineno = 0; - input_filename = ""; current_function_decl = NULL; - maxtoken = 40; - token_buffer = (char *) xmalloc (maxtoken + 2); - - ridpointers[(int) RID_INT] = get_identifier ("int"); - ridpointers[(int) RID_BOOL] = get_identifier ("bool"); - ridpointers[(int) RID_CHAR] = get_identifier ("char"); - ridpointers[(int) RID_VOID] = get_identifier ("void"); - ridpointers[(int) RID_FLOAT] = get_identifier ("float"); - ridpointers[(int) RID_DOUBLE] = get_identifier ("double"); - ridpointers[(int) RID_SHORT] = get_identifier ("short"); - ridpointers[(int) RID_LONG] = get_identifier ("long"); - ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned"); - ridpointers[(int) RID_SIGNED] = get_identifier ("signed"); - ridpointers[(int) RID_INLINE] = get_identifier ("inline"); - ridpointers[(int) RID_CONST] = get_identifier ("const"); - ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile"); - ridpointers[(int) RID_RESTRICT] = get_identifier ("__restrict"); - ridpointers[(int) RID_AUTO] = get_identifier ("auto"); - ridpointers[(int) RID_STATIC] = get_identifier ("static"); - ridpointers[(int) RID_EXTERN] = get_identifier ("extern"); - ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef"); - ridpointers[(int) RID_REGISTER] = get_identifier ("register"); - ridpointers[(int) RID_COMPLEX] = get_identifier ("__complex"); - - /* C++ extensions. These are probably not correctly named. */ - ridpointers[(int) RID_WCHAR] = get_identifier ("__wchar_t"); class_type_node = build_int_2 (class_type, 0); TREE_TYPE (class_type_node) = class_type_node; ridpointers[(int) RID_CLASS] = class_type_node; record_type_node = build_int_2 (record_type, 0); TREE_TYPE (record_type_node) = record_type_node; - ridpointers[(int) RID_RECORD] = record_type_node; + ridpointers[(int) RID_STRUCT] = record_type_node; union_type_node = build_int_2 (union_type, 0); TREE_TYPE (union_type_node) = union_type_node; @@ -717,186 +719,28 @@ init_parse (filename) TREE_TYPE (enum_type_node) = enum_type_node; ridpointers[(int) RID_ENUM] = enum_type_node; - ridpointers[(int) RID_VIRTUAL] = get_identifier ("virtual"); - ridpointers[(int) RID_EXPLICIT] = get_identifier ("explicit"); - ridpointers[(int) RID_EXPORT] = get_identifier ("export"); - ridpointers[(int) RID_FRIEND] = get_identifier ("friend"); - - ridpointers[(int) RID_PUBLIC] = get_identifier ("public"); - ridpointers[(int) RID_PRIVATE] = get_identifier ("private"); - ridpointers[(int) RID_PROTECTED] = get_identifier ("protected"); - ridpointers[(int) RID_TEMPLATE] = get_identifier ("template"); - /* This is for ANSI C++. */ - ridpointers[(int) RID_MUTABLE] = get_identifier ("mutable"); - - /* Signature handling extensions. */ - signature_type_node = build_int_2 (signature_type, 0); - TREE_TYPE (signature_type_node) = signature_type_node; - ridpointers[(int) RID_SIGNATURE] = signature_type_node; - - /* Create the built-in __null node. Note that we can't yet call for - type_for_size here because integer_type_node and so forth are not - set up. Therefore, we don't set the type of these nodes until - init_decl_processing. */ + cxx_init_decl_processing (); + + /* Create the built-in __null node. */ null_node = build_int_2 (0, 0); + TREE_TYPE (null_node) = type_for_size (POINTER_SIZE, 0); ridpointers[RID_NULL] = null_node; - opname_tab[(int) COMPONENT_REF] = "->"; - opname_tab[(int) MEMBER_REF] = "->*"; - opname_tab[(int) INDIRECT_REF] = "*"; - opname_tab[(int) ARRAY_REF] = "[]"; - opname_tab[(int) MODIFY_EXPR] = "="; - opname_tab[(int) NEW_EXPR] = "new"; - opname_tab[(int) DELETE_EXPR] = "delete"; - opname_tab[(int) VEC_NEW_EXPR] = "new []"; - opname_tab[(int) VEC_DELETE_EXPR] = "delete []"; - opname_tab[(int) COND_EXPR] = "?:"; - opname_tab[(int) CALL_EXPR] = "()"; - opname_tab[(int) PLUS_EXPR] = "+"; - opname_tab[(int) MINUS_EXPR] = "-"; - opname_tab[(int) MULT_EXPR] = "*"; - opname_tab[(int) TRUNC_DIV_EXPR] = "/"; - opname_tab[(int) CEIL_DIV_EXPR] = "(ceiling /)"; - opname_tab[(int) FLOOR_DIV_EXPR] = "(floor /)"; - opname_tab[(int) ROUND_DIV_EXPR] = "(round /)"; - opname_tab[(int) TRUNC_MOD_EXPR] = "%"; - opname_tab[(int) CEIL_MOD_EXPR] = "(ceiling %)"; - opname_tab[(int) FLOOR_MOD_EXPR] = "(floor %)"; - opname_tab[(int) ROUND_MOD_EXPR] = "(round %)"; - opname_tab[(int) NEGATE_EXPR] = "-"; - opname_tab[(int) MIN_EXPR] = "?"; - opname_tab[(int) ABS_EXPR] = "abs"; - opname_tab[(int) FFS_EXPR] = "ffs"; - opname_tab[(int) LSHIFT_EXPR] = "<<"; - opname_tab[(int) RSHIFT_EXPR] = ">>"; - opname_tab[(int) BIT_IOR_EXPR] = "|"; - opname_tab[(int) BIT_XOR_EXPR] = "^"; - opname_tab[(int) BIT_AND_EXPR] = "&"; - opname_tab[(int) BIT_ANDTC_EXPR] = "&~"; - opname_tab[(int) BIT_NOT_EXPR] = "~"; - opname_tab[(int) TRUTH_ANDIF_EXPR] = "&&"; - opname_tab[(int) TRUTH_ORIF_EXPR] = "||"; - opname_tab[(int) TRUTH_AND_EXPR] = "strict &&"; - opname_tab[(int) TRUTH_OR_EXPR] = "strict ||"; - opname_tab[(int) TRUTH_NOT_EXPR] = "!"; - opname_tab[(int) LT_EXPR] = "<"; - opname_tab[(int) LE_EXPR] = "<="; - opname_tab[(int) GT_EXPR] = ">"; - opname_tab[(int) GE_EXPR] = ">="; - opname_tab[(int) EQ_EXPR] = "=="; - opname_tab[(int) NE_EXPR] = "!="; - opname_tab[(int) IN_EXPR] = "in"; - opname_tab[(int) RANGE_EXPR] = "..."; - opname_tab[(int) CONVERT_EXPR] = "+"; - opname_tab[(int) ADDR_EXPR] = "&"; - opname_tab[(int) PREDECREMENT_EXPR] = "--"; - opname_tab[(int) PREINCREMENT_EXPR] = "++"; - opname_tab[(int) POSTDECREMENT_EXPR] = "--"; - opname_tab[(int) POSTINCREMENT_EXPR] = "++"; - opname_tab[(int) COMPOUND_EXPR] = ","; - - assignop_tab[(int) NOP_EXPR] = "="; - assignop_tab[(int) PLUS_EXPR] = "+="; - assignop_tab[(int) CONVERT_EXPR] = "+="; - assignop_tab[(int) MINUS_EXPR] = "-="; - assignop_tab[(int) NEGATE_EXPR] = "-="; - assignop_tab[(int) MULT_EXPR] = "*="; - assignop_tab[(int) INDIRECT_REF] = "*="; - assignop_tab[(int) TRUNC_DIV_EXPR] = "/="; - assignop_tab[(int) EXACT_DIV_EXPR] = "(exact /=)"; - assignop_tab[(int) CEIL_DIV_EXPR] = "(ceiling /=)"; - assignop_tab[(int) FLOOR_DIV_EXPR] = "(floor /=)"; - assignop_tab[(int) ROUND_DIV_EXPR] = "(round /=)"; - assignop_tab[(int) TRUNC_MOD_EXPR] = "%="; - assignop_tab[(int) CEIL_MOD_EXPR] = "(ceiling %=)"; - assignop_tab[(int) FLOOR_MOD_EXPR] = "(floor %=)"; - assignop_tab[(int) ROUND_MOD_EXPR] = "(round %=)"; - assignop_tab[(int) MIN_EXPR] = "?="; - assignop_tab[(int) LSHIFT_EXPR] = "<<="; - assignop_tab[(int) RSHIFT_EXPR] = ">>="; - assignop_tab[(int) BIT_IOR_EXPR] = "|="; - assignop_tab[(int) BIT_XOR_EXPR] = "^="; - assignop_tab[(int) BIT_AND_EXPR] = "&="; - assignop_tab[(int) ADDR_EXPR] = "&="; - - init_filename_times (); - - /* Some options inhibit certain reserved words. - Clear those words out of the hash table so they won't be recognized. */ -#define UNSET_RESERVED_WORD(STRING) \ - do { struct resword *s = is_reserved_word (STRING, sizeof (STRING) - 1); \ - if (s) s->name = ""; } while (0) - -#if 0 - /* let's parse things, and if they use it, then give them an error. */ - if (!flag_exceptions) - { - UNSET_RESERVED_WORD ("throw"); - UNSET_RESERVED_WORD ("try"); - UNSET_RESERVED_WORD ("catch"); - } -#endif - - if (!flag_rtti || flag_no_gnu_keywords) - { - UNSET_RESERVED_WORD ("classof"); - UNSET_RESERVED_WORD ("headof"); - } - - if (! flag_handle_signatures || flag_no_gnu_keywords) - { - /* Easiest way to not recognize signature - handling extensions... */ - UNSET_RESERVED_WORD ("signature"); - UNSET_RESERVED_WORD ("sigof"); - } - if (flag_no_asm || flag_no_gnu_keywords) - UNSET_RESERVED_WORD ("typeof"); - if (! flag_operator_names) - { - /* These are new ANSI keywords that may break code. */ - UNSET_RESERVED_WORD ("and"); - UNSET_RESERVED_WORD ("and_eq"); - UNSET_RESERVED_WORD ("bitand"); - UNSET_RESERVED_WORD ("bitor"); - UNSET_RESERVED_WORD ("compl"); - UNSET_RESERVED_WORD ("not"); - UNSET_RESERVED_WORD ("not_eq"); - UNSET_RESERVED_WORD ("or"); - UNSET_RESERVED_WORD ("or_eq"); - UNSET_RESERVED_WORD ("xor"); - UNSET_RESERVED_WORD ("xor_eq"); - } - token_count = init_cpp_parse (); interface_unknown = 1; - return filename; -} + filename = c_common_init (filename); -void -finish_parse () -{ -#if USE_CPPLIB - cpp_finish (&parse_in); -#else - fclose (finput); -#endif -} + init_cp_pragma (); -void -reinit_parse_for_function () -{ - current_base_init_list = NULL_TREE; - current_member_init_list = NULL_TREE; + if (flag_gnu_xref) + GNU_xref_begin (filename); + init_repo (filename); + + return filename; } -#ifdef __GNUC__ -__inline -#endif -void +inline void yyprint (file, yychar, yylval) FILE *file; int yychar; @@ -909,6 +753,7 @@ yyprint (file, yychar, yylval) case TYPENAME: case TYPESPEC: case PTYPENAME: + case PFUNCNAME: case IDENTIFIER_DEFN: case TYPENAME_DEFN: case PTYPENAME_DEFN: @@ -924,6 +769,7 @@ yyprint (file, yychar, yylval) if (IDENTIFIER_POINTER (t)) fprintf (file, " `%s'", IDENTIFIER_POINTER (t)); break; + case AGGR: if (yylval.ttype == class_type_node) fprintf (file, " `class'"); @@ -933,10 +779,32 @@ yyprint (file, yychar, yylval) fprintf (file, " `union'"); else if (yylval.ttype == enum_type_node) fprintf (file, " `enum'"); - else if (yylval.ttype == signature_type_node) - fprintf (file, " `signature'"); else - my_friendly_abort (80); + abort (); + break; + + case CONSTANT: + t = yylval.ttype; + if (TREE_CODE (t) == INTEGER_CST) + fprintf (file, +#if HOST_BITS_PER_WIDE_INT == 64 +#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT + " 0x%x%016x", +#else +#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG + " 0x%lx%016lx", +#else + " 0x%llx%016llx", +#endif +#endif +#else +#if HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_INT + " 0x%lx%08lx", +#else + " 0x%x%08x", +#endif +#endif + TREE_INT_CST_HIGH (t), TREE_INT_CST_LOW (t)); break; } } @@ -986,7 +854,7 @@ print_parse_statistics () int i; int maxlen = REDUCE_LENGTH; unsigned *sorted; - + if (reduce_count[-1] == 0) return; @@ -1032,65 +900,40 @@ print_parse_statistics () in order to build the compiler. */ void -set_yydebug (value) +cxx_set_yydebug (value) int value; { #if YYDEBUG != 0 extern int yydebug; yydebug = value; #else - warning ("YYDEBUG not defined."); + warning ("YYDEBUG not defined"); #endif } - -/* Functions and data structures for #pragma interface. - - `#pragma implementation' means that the main file being compiled - is considered to implement (provide) the classes that appear in - its main body. I.e., if this is file "foo.cc", and class `bar' - is defined in "foo.cc", then we say that "foo.cc implements bar". - - All main input files "implement" themselves automagically. - - `#pragma interface' means that unless this file (of the form "foo.h" - is not presently being included by file "foo.cc", the - CLASSTYPE_INTERFACE_ONLY bit gets set. The effect is that none - of the vtables nor any of the inline functions defined in foo.h - will ever be output. - - There are cases when we want to link files such as "defs.h" and - "main.cc". In this case, we give "defs.h" a `#pragma interface', - and "main.cc" has `#pragma implementation "defs.h"'. */ - -struct impl_files -{ - char *filename; - struct impl_files *next; -}; - -static struct impl_files *impl_file_chain; - /* Helper function to load global variables with interface information. */ void extract_interface_info () { - tree fileinfo = 0; + struct c_fileinfo *finfo = 0; if (flag_alt_external_templates) { - struct tinst_level *til = tinst_for_decl (); - + tree til = tinst_for_decl (); + if (til) - fileinfo = get_time_identifier (til->file); + finfo = get_fileinfo (TINST_FILE (til)); } - if (!fileinfo) - fileinfo = get_time_identifier (input_filename); - fileinfo = TIME_IDENTIFIER_FILEINFO (fileinfo); - interface_only = TREE_INT_CST_LOW (fileinfo); - interface_unknown = TREE_INT_CST_HIGH (fileinfo); + if (!finfo) + finfo = get_fileinfo (input_filename); + + interface_only = finfo->interface_only; + interface_unknown = finfo->interface_unknown; + + /* This happens to be a convenient place to put this. */ + if (flag_gnu_xref) GNU_xref_file (input_filename); } /* Return nonzero if S is not considered part of an @@ -1120,7 +963,7 @@ interface_strcmp (s) return 0; /* Don't get faked out by xxx.yyy.cc vs xxx.zzz.cc. */ - if (index (s1, '.') || index (t1, '.')) + if (strchr (s1, '.') || strchr (t1, '.')) continue; if (*s1 == '\0' || s1[-1] != '.' || t1[-1] != '.') @@ -1134,1685 +977,207 @@ interface_strcmp (s) return 1; } -static int -set_typedecl_interface_info (t, data) - tree *t; - void *data ATTRIBUTE_UNUSED; -{ - tree id = get_time_identifier (DECL_SOURCE_FILE (*t)); - tree fileinfo = TIME_IDENTIFIER_FILEINFO (id); - tree type = TREE_TYPE (*t); - - CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo) - = interface_strcmp (file_name_nondirectory (DECL_SOURCE_FILE (*t))); - return 0; -} +/* Heuristic to tell whether the user is missing a semicolon + after a struct or enum declaration. Emit an error message + if we know the user has blown it. */ -static int -set_vardecl_interface_info (t, data) - tree *t; - void *data ATTRIBUTE_UNUSED; +void +check_for_missing_semicolon (type) + tree type; { - tree type = DECL_CONTEXT (*t); + if (yychar < 0) + yychar = yylex (); - if (CLASSTYPE_INTERFACE_KNOWN (type)) + if ((yychar > 255 + && yychar != SCSPEC + && yychar != IDENTIFIER + && yychar != TYPENAME + && yychar != CV_QUALIFIER + && yychar != SELFNAME) + || yychar == 0 /* EOF */) { - if (CLASSTYPE_INTERFACE_ONLY (type)) - set_typedecl_interface_info (&TYPE_MAIN_DECL (type), data); + if (TYPE_ANONYMOUS_P (type)) + error ("semicolon missing after %s declaration", + TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct"); else - CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1; - DECL_EXTERNAL (*t) = CLASSTYPE_INTERFACE_ONLY (type); - TREE_PUBLIC (*t) = 1; - return 1; + error ("semicolon missing after declaration of `%T'", type); + shadow_tag (build_tree_list (0, type)); } - return 0; + /* Could probably also hack cases where class { ... } f (); appears. */ + clear_anon_tags (); } - -/* 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_definition_of_inclass_inline (pi) - struct pending_inline* pi; +void +note_got_semicolon (type) + tree type; { - tree context; - - if (!pi->fndecl) - return; - - /* 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 = hack_decl_function_context (pi->fndecl); - if (context) - push_cp_function_context (context); - - feed_input (pi->buf, pi->len); - lineno = pi->lineno; - input_filename = pi->filename; - yychar = PRE_PARSED_FUNCTION_DECL; - yylval.ttype = build_tree_list ((tree) pi, pi->fndecl); - /* Pass back a handle to the rest of the inline functions, so that they - can be processed later. */ - DECL_PENDING_INLINE_INFO (pi->fndecl) = 0; - interface_unknown = pi->interface == 1; - interface_only = pi->interface == 0; + if (!TYPE_P (type)) + abort (); + if (CLASS_TYPE_P (type)) + CLASSTYPE_GOT_SEMICOLON (type) = 1; } -/* 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 () +note_list_got_semicolon (declspecs) + tree declspecs; { - struct pending_inline *t; - - /* Oops, we're still dealing with the last batch. */ - if (yychar == PRE_PARSED_FUNCTION_DECL) - return; - - /* Reverse the pending inline functions, since - they were cons'd instead of appended. */ - { - struct pending_inline *prev = 0, *tail; - t = pending_inlines; - pending_inlines = 0; - - for (; t; t = tail) - { - tail = t->next; - t->next = prev; - t->deja_vu = 1; - prev = t; - } - t = prev; - } - - if (t == 0) - return; - - /* Now start processing the first inline function. */ - begin_definition_of_inclass_inline (t); -} - -static int nextchar = -1; - -/* 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 (t) - tree t; -{ - tree context; - struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t); - context = hack_decl_function_context (i->fndecl); - if (context) - pop_cp_function_context (context); - i = i->next; - if (yychar == YYEMPTY) - yychar = yylex (); - if (yychar != END_OF_SAVED_INPUT) - { - error ("parse error at end of saved function text"); - - /* restore_pending_input will abort unless yychar is either - END_OF_SAVED_INPUT or YYEMPTY; since we already know we're - hosed, feed back YYEMPTY. We also need to discard nextchar, - since that may have gotten set as well. */ - nextchar = -1; - } - yychar = YYEMPTY; - end_input (); - if (i) - begin_definition_of_inclass_inline (i); - else - extract_interface_info (); -} - -/* 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. */ - -static void -consume_string (this_obstack, matching_char) - register struct obstack *this_obstack; - int matching_char; -{ - register int c; - int starting_lineno = lineno; - do - { - c = getch (); - if (c == EOF) - { - int save_lineno = lineno; - lineno = starting_lineno; - if (matching_char == '"') - error ("end of file encountered inside string constant"); - else - error ("end of file encountered inside character constant"); - lineno = save_lineno; - return; - } - if (c == '\\') - { - obstack_1grow (this_obstack, c); - c = getch (); - obstack_1grow (this_obstack, c); - - /* Make sure we continue the loop */ - c = 0; - continue; - } - if (c == '\n') - { - if (pedantic) - pedwarn ("ANSI C++ forbids newline in string constant"); - lineno++; - } - obstack_1grow (this_obstack, c); - } - while (c != matching_char); -} - -static int nextyychar = YYEMPTY; -static YYSTYPE nextyylval; - -struct pending_input { - int nextchar, yychar, nextyychar, eof; - YYSTYPE yylval, nextyylval; - struct obstack token_obstack; - int first_token; -}; - -struct pending_input * -save_pending_input () -{ - struct pending_input *p; - p = (struct pending_input *) xmalloc (sizeof (struct pending_input)); - p->nextchar = nextchar; - p->yychar = yychar; - p->nextyychar = nextyychar; - p->yylval = yylval; - p->nextyylval = nextyylval; - p->eof = end_of_file; - yychar = nextyychar = YYEMPTY; - nextchar = -1; - p->first_token = first_token; - p->token_obstack = token_obstack; - - first_token = 0; - gcc_obstack_init (&token_obstack); - end_of_file = 0; - return p; -} - -void -restore_pending_input (p) - struct pending_input *p; -{ - my_friendly_assert (nextchar == -1, 229); - nextchar = p->nextchar; - my_friendly_assert (yychar == YYEMPTY || yychar == END_OF_SAVED_INPUT, 230); - yychar = p->yychar; - my_friendly_assert (nextyychar == YYEMPTY, 231); - nextyychar = p->nextyychar; - yylval = p->yylval; - nextyylval = p->nextyylval; - first_token = p->first_token; - obstack_free (&token_obstack, (char *) 0); - token_obstack = p->token_obstack; - end_of_file = p->eof; - free (p); -} - -/* Unget character CH from the input stream. - If RESCAN is non-zero, 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) - { - if (nextchar >= 0) - put_back (nextchar); - nextchar = ch; - } - else - { - my_friendly_assert (nextyychar == YYEMPTY, 232); - nextyychar = yychar; - nextyylval = yylval; - yychar = ch; - } -} - -void -clear_inline_text_obstack () -{ - obstack_free (&inline_text_obstack, inline_text_firstobj); -} - -/* This function stores away the text for an inline function that should - be processed later. It decides how much later, and may need to move - the info between obstacks; therefore, the caller should not refer to - the T parameter after calling this function. */ - -static void -store_pending_inline (decl, t) - tree decl; - struct pending_inline *t; -{ - t->fndecl = decl; - DECL_PENDING_INLINE_INFO (decl) = t; - - /* Because we use obstacks, we must process these in precise order. */ - t->next = pending_inlines; - pending_inlines = t; -} - -void -reinit_parse_for_method (yychar, decl) - int yychar; - tree decl; -{ - int len; - int starting_lineno = lineno; - char *starting_filename = input_filename; - - reinit_parse_for_block (yychar, &inline_text_obstack); - - len = obstack_object_size (&inline_text_obstack); - current_base_init_list = NULL_TREE; - current_member_init_list = NULL_TREE; - if (decl == void_type_node - || (current_class_type && TYPE_REDEFINED (current_class_type))) - { - /* Happens when we get two declarations of the same - function in the same scope. */ - char *buf = obstack_finish (&inline_text_obstack); - obstack_free (&inline_text_obstack, buf); - return; - } - else - { - struct pending_inline *t; - char *buf = obstack_finish (&inline_text_obstack); - - t = (struct pending_inline *) obstack_alloc (&inline_text_obstack, - sizeof (struct pending_inline)); - t->lineno = starting_lineno; - t->filename = starting_filename; - t->token = YYEMPTY; - t->token_value = 0; - t->buf = buf; - t->len = len; - t->deja_vu = 0; -#if 0 - if (interface_unknown && processing_template_defn && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl)) - warn_if_unknown_interface (decl); -#endif - t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2)); - store_pending_inline (decl, t); - } -} - -/* Consume a block -- actually, a method beginning - with `:' or `{' -- and save it away on the specified obstack. */ - -void -reinit_parse_for_block (pyychar, obstackp) - int pyychar; - struct obstack *obstackp; -{ - register int c = 0; - int blev = 1; - int starting_lineno = lineno; - char *starting_filename = input_filename; - int len; - int look_for_semicolon = 0; - int look_for_lbrac = 0; - - if (pyychar == '{') - obstack_1grow (obstackp, '{'); - else if (pyychar == '=') - look_for_semicolon = 1; - else if (pyychar == ':') - { - obstack_1grow (obstackp, pyychar); - /* Add a space so we don't get confused by ': ::A(20)'. */ - obstack_1grow (obstackp, ' '); - look_for_lbrac = 1; - blev = 0; - } - else if (pyychar == RETURN_KEYWORD) - { - obstack_grow (obstackp, "return", 6); - look_for_lbrac = 1; - blev = 0; - } - else if (pyychar == TRY) - { - obstack_grow (obstackp, "try", 3); - look_for_lbrac = 1; - blev = 0; - } - else - { - yyerror ("parse error in method specification"); - obstack_1grow (obstackp, '{'); - } - - if (nextchar != EOF) - { - c = nextchar; - nextchar = EOF; - } - else - c = getch (); - - while (c != EOF) - { - int this_lineno = lineno; - - c = skip_white_space (c); - - /* Don't lose our cool if there are lots of comments. */ - if (lineno == this_lineno + 1) - obstack_1grow (obstackp, '\n'); - else if (lineno == this_lineno) - ; - else if (lineno - this_lineno < 10) - { - int i; - for (i = lineno - this_lineno; i > 0; i--) - obstack_1grow (obstackp, '\n'); - } - else - { - char buf[16]; - sprintf (buf, "\n# %d \"", lineno); - len = strlen (buf); - obstack_grow (obstackp, buf, len); - - len = strlen (input_filename); - obstack_grow (obstackp, input_filename, len); - obstack_1grow (obstackp, '\"'); - obstack_1grow (obstackp, '\n'); - } - - while (c > ' ') /* ASCII dependent... */ - { - obstack_1grow (obstackp, c); - if (c == '{') - { - look_for_lbrac = 0; - blev++; - } - else if (c == '}') - { - blev--; - if (blev == 0 && !look_for_semicolon) - { - if (pyychar == TRY) - { - if (peekyylex () == CATCH) - { - yylex (); - obstack_grow (obstackp, " catch ", 7); - look_for_lbrac = 1; - } - else - { - yychar = '{'; - goto done; - } - } - else - { - goto done; - } - } - } - else if (c == '\\') - { - /* Don't act on the next character...e.g, doing an escaped - double-quote. */ - c = getch (); - if (c == EOF) - { - error_with_file_and_line (starting_filename, - starting_lineno, - "end of file read inside definition"); - goto done; - } - obstack_1grow (obstackp, c); - } - else if (c == '\"') - consume_string (obstackp, c); - else if (c == '\'') - consume_string (obstackp, c); - else if (c == ';') - { - if (look_for_lbrac) - { - error ("function body for constructor missing"); - obstack_1grow (obstackp, '{'); - obstack_1grow (obstackp, '}'); - len += 2; - goto done; - } - else if (look_for_semicolon && blev == 0) - goto done; - } - c = getch (); - } - - if (c == EOF) - { - error_with_file_and_line (starting_filename, - starting_lineno, - "end of file read inside definition"); - goto done; - } - else if (c != '\n') - { - obstack_1grow (obstackp, c); - c = getch (); - } - } - done: - obstack_1grow (obstackp, '\0'); -} - -/* Consume a no-commas expression -- actually, a default argument -- and - save it away on the specified obstack. */ - -static void -reinit_parse_for_expr (obstackp) - struct obstack *obstackp; -{ - register int c = 0; - int starting_lineno = lineno; - char *starting_filename = input_filename; - int len; - int plev = 0; - - if (nextchar != EOF) - { - c = nextchar; - nextchar = EOF; - } - else - c = getch (); - - while (c != EOF) - { - int this_lineno = lineno; - - c = skip_white_space (c); - - /* Don't lose our cool if there are lots of comments. */ - if (lineno == this_lineno + 1) - obstack_1grow (obstackp, '\n'); - else if (lineno == this_lineno) - ; - else if (lineno - this_lineno < 10) - { - int i; - for (i = lineno - this_lineno; i > 0; --i) - obstack_1grow (obstackp, '\n'); - } - else - { - char buf[16]; - sprintf (buf, "\n# %d \"", lineno); - len = strlen (buf); - obstack_grow (obstackp, buf, len); - - len = strlen (input_filename); - obstack_grow (obstackp, input_filename, len); - obstack_1grow (obstackp, '\"'); - obstack_1grow (obstackp, '\n'); - } - - while (c > ' ') /* ASCII dependent... */ - { - if (plev <= 0 && (c == ')' || c == ',')) - { - put_back (c); - goto done; - } - obstack_1grow (obstackp, c); - if (c == '(' || c == '[') - ++plev; - else if (c == ']' || c == ')') - --plev; - else if (c == '\\') - { - /* Don't act on the next character...e.g, doing an escaped - double-quote. */ - c = getch (); - if (c == EOF) - { - error_with_file_and_line (starting_filename, - starting_lineno, - "end of file read inside definition"); - goto done; - } - obstack_1grow (obstackp, c); - } - else if (c == '\"') - consume_string (obstackp, c); - else if (c == '\'') - consume_string (obstackp, c); - c = getch (); - } - - if (c == EOF) - { - error_with_file_and_line (starting_filename, - starting_lineno, - "end of file read inside definition"); - goto done; - } - else if (c != '\n') - { - obstack_1grow (obstackp, c); - c = getch (); - } - } - done: - obstack_1grow (obstackp, '\0'); -} - -int do_snarf_defarg; - -/* 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; -} - -/* 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. */ - -tree defarg_fns; -tree defarg_parm; - -tree -snarf_defarg () -{ - int len; - char *buf; - tree arg; - - reinit_parse_for_expr (&inline_text_obstack); - len = obstack_object_size (&inline_text_obstack); - buf = obstack_finish (&inline_text_obstack); - - push_obstacks (&inline_text_obstack, &inline_text_obstack); - arg = make_node (DEFAULT_ARG); - DEFARG_LENGTH (arg) = len - 1; - DEFARG_POINTER (arg) = buf; - pop_obstacks (); - - return arg; -} - -/* 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 - { - push_obstacks (&inline_text_obstack, &inline_text_obstack); - defarg_fns = tree_cons (current_class_type, decl, defarg_fns); - pop_obstacks (); - } -} - -/* Helper for do_pending_defargs. Starts the parsing of a default arg. */ - -static void -feed_defarg (f, p) - tree f, p; -{ - tree d = TREE_PURPOSE (p); - feed_input (DEFARG_POINTER (d), DEFARG_LENGTH (d)); - if (TREE_CODE (f) == FUNCTION_DECL) - { - lineno = DECL_SOURCE_LINE (f); - input_filename = DECL_SOURCE_FILE (f); - } - 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"); - - /* restore_pending_input will abort unless yychar is either - END_OF_SAVED_INPUT or YYEMPTY; since we already know we're - hosed, feed back YYEMPTY. We also need to discard nextchar, - since that may have gotten set as well. */ - nextchar = -1; - } - yychar = YYEMPTY; - 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; defarg_fns = TREE_CHAIN (defarg_fns)) - { - tree defarg_fn = TREE_VALUE (defarg_fns); - if (defarg_parm == NULL_TREE) - { - push_nested_class (TREE_PURPOSE (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) - { -#if 0 - tree p; - for (p = DECL_ARGUMENTS (defarg_fn); p; p = TREE_CHAIN (p)) - pushdecl (copy_node (p)); -#endif - 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) - { - feed_defarg (defarg_fn, 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 (); - } -} - -/* Build a default function named NAME for type TYPE. - KIND says what to build. - - When KIND == 0, build default destructor. - When KIND == 1, build virtual destructor. - When KIND == 2, build default constructor. - When KIND == 3, build default X(const X&) constructor. - When KIND == 4, build default X(X&) constructor. - When KIND == 5, build default operator = (const X&). - When KIND == 6, build default operator = (X&). */ - -tree -cons_up_default_function (type, full_name, kind) - tree type, full_name; - int kind; -{ - extern tree void_list_node; - tree declspecs = NULL_TREE; - tree fn, args = NULL_TREE; - tree argtype; - int retref = 0; - tree name = constructor_name (full_name); - - switch (kind) - { - /* Destructors. */ - case 1: - declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_VIRTUAL]); - /* Fall through... */ - case 0: - name = build_parse_node (BIT_NOT_EXPR, name); - args = void_list_node; - break; - - case 2: - /* Default constructor. */ - args = void_list_node; - break; - - case 3: - type = build_qualified_type (type, TYPE_QUAL_CONST); - /* Fall through... */ - case 4: - /* According to ARM $12.8, the default copy ctor will be declared, but - not defined, unless it's needed. */ - argtype = build_reference_type (type); - args = tree_cons (NULL_TREE, - build_tree_list (hash_tree_chain (argtype, NULL_TREE), - get_identifier ("_ctor_arg")), - void_list_node); - break; - - case 5: - case 6: - retref = 1; - declspecs = build_decl_list (NULL_TREE, type); - - if (kind == 5) - type = build_qualified_type (type, TYPE_QUAL_CONST); - - name = ansi_opname [(int) MODIFY_EXPR]; - - argtype = build_reference_type (type); - args = tree_cons (NULL_TREE, - build_tree_list (hash_tree_chain (argtype, NULL_TREE), - get_identifier ("_ctor_arg")), - void_list_node); - break; - - default: - my_friendly_abort (59); - } - - declspecs = decl_tree_cons (NULL_TREE, ridpointers [(int) RID_INLINE], - declspecs); - - TREE_PARMLIST (args) = 1; - - { - tree declarator = make_call_declarator (name, args, NULL_TREE, NULL_TREE); - if (retref) - declarator = build_parse_node (ADDR_EXPR, declarator); - - fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE); - } - - if (fn == void_type_node) - return fn; - - if (kind > 2) - SET_DECL_ARTIFICIAL (TREE_CHAIN (DECL_ARGUMENTS (fn))); - -#if 0 - if (processing_template_defn) - { - SET_DECL_IMPLICIT_INSTANTIATION (fn); - repo_template_used (fn); - } -#endif - -#if 0 - if (CLASSTYPE_INTERFACE_KNOWN (type)) - { - DECL_INTERFACE_KNOWN (fn) = 1; - DECL_NOT_REALLY_EXTERN (fn) = (!CLASSTYPE_INTERFACE_ONLY (type) - && flag_implement_inlines); - } - else -#endif - DECL_NOT_REALLY_EXTERN (fn) = 1; - - mark_inline_for_output (fn); - -#ifdef DEBUG_DEFAULT_FUNCTIONS - { char *fn_type = NULL; - tree t = name; - switch (kind) - { - case 0: fn_type = "default destructor"; break; - case 1: fn_type = "virtual destructor"; break; - case 2: fn_type = "default constructor"; break; - case 3: fn_type = "default X(const X&)"; break; - case 4: fn_type = "default X(X&)"; break; - } - if (fn_type) - { - if (TREE_CODE (name) == BIT_NOT_EXPR) - t = TREE_OPERAND (name, 0); - fprintf (stderr, "[[[[ %s for %s:\n%s]]]]\n", fn_type, - IDENTIFIER_POINTER (t), func_buf); - } - } -#endif /* DEBUG_DEFAULT_FUNCTIONS */ - - /* Show that this function was generated by the compiler. */ - SET_DECL_ARTIFICIAL (fn); - - return fn; -} - -/* Heuristic to tell whether the user is missing a semicolon - after a struct or enum declaration. Emit an error message - if we know the user has blown it. */ - -void -check_for_missing_semicolon (type) - tree type; -{ - if (yychar < 0) - yychar = yylex (); - - if ((yychar > 255 - && yychar != SCSPEC - && yychar != IDENTIFIER - && yychar != TYPENAME - && yychar != CV_QUALIFIER - && yychar != SELFNAME) - || end_of_file) - { - if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type))) - error ("semicolon missing after %s declaration", - TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct"); - else - cp_error ("semicolon missing after declaration of `%T'", type); - shadow_tag (build_tree_list (0, type)); - } - /* Could probably also hack cases where class { ... } f (); appears. */ - clear_anon_tags (); -} - -void -note_got_semicolon (type) - tree type; -{ - if (TREE_CODE_CLASS (TREE_CODE (type)) != 't') - my_friendly_abort (60); - if (CLASS_TYPE_P (type)) - CLASSTYPE_GOT_SEMICOLON (type) = 1; -} - -void -note_list_got_semicolon (declspecs) - tree declspecs; -{ - tree link; + tree link; for (link = declspecs; link; link = TREE_CHAIN (link)) { tree type = TREE_VALUE (link); - if (TREE_CODE_CLASS (TREE_CODE (type)) == 't') + if (type && TYPE_P (type)) note_got_semicolon (type); } clear_anon_tags (); } -/* If C is not whitespace, return C. - Otherwise skip whitespace and return first nonwhite char read. */ - -static int -skip_white_space (c) - register int c; -{ - for (;;) - { - switch (c) - { - case '\n': - c = check_newline (); - break; - - case ' ': - case '\t': - case '\f': - case '\r': - case '\v': - case '\b': - do - c = getch (); - while (c == ' ' || c == '\t'); - break; - - case '\\': - c = getch (); - if (c == '\n') - lineno++; - else - error ("stray '\\' in program"); - c = getch (); - break; - - default: - return (c); - } - } -} - - - -/* Make the token buffer longer, preserving the data in it. - P should point to just beyond the last valid character in the old buffer. - The value we return is a pointer to the new buffer - at a place corresponding to P. */ - -static char * -extend_token_buffer (p) - const char *p; -{ - int offset = p - token_buffer; - - maxtoken = maxtoken * 2 + 10; - token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2); - - return token_buffer + offset; -} - -static int -get_last_nonwhite_on_line () -{ - register int c; - - /* Is this the last nonwhite stuff on the line? */ - if (nextchar >= 0) - c = nextchar, nextchar = -1; - else - c = getch (); - - while (c == ' ' || c == '\t') - c = getch (); - return c; -} - -#if defined HANDLE_PRAGMA -/* Local versions of these macros, that can be passed as function pointers. */ -static int -pragma_getc () -{ - int c; - - if (nextchar != EOF) - { - c = nextchar; - nextchar = EOF; - } - else - c = getch (); - - return c; -} - -static void -pragma_ungetc (arg) - int arg; -{ - yyungetc (arg, 0); -} -#endif /* HANDLE_PRAGMA */ - -/* At the beginning of a line, increment the line number - and process any #-directive on this line. - If the line is a #-directive, read the entire line and return a newline. - Otherwise, return the line's first non-whitespace character. */ - -int linemode; -static int -check_newline () +/* Parse a #pragma whose sole argument is a string constant. + If OPT is true, the argument is optional. */ +static tree +parse_strconst_pragma (name, opt) + const char *name; + int opt; { - register int c; - register int token; - int saw_line = 0; - - /* Read first nonwhite char on the line. Do this before incrementing the - line number, in case we're at the end of saved text. */ + tree result, x; + enum cpp_ttype t; - do - c = getch (); - while (c == ' ' || c == '\t'); - - lineno++; - - if (c != '#') - { - /* If not #, return it so caller will use it. */ - return c; - } - - /* Don't read beyond this line. */ - linemode = 1; - - /* Read first nonwhite char after the `#'. */ - - do - c = getch (); - while (c == ' ' || c == '\t'); - - /* If a letter follows, then if the word here is `line', skip - it and ignore it; otherwise, ignore the line, with an error - if the word isn't `pragma'. */ - - if (ISALPHA (c)) + t = c_lex (&x); + if (t == CPP_STRING) { - if (c == 'p') - { - if (getch () == 'r' - && getch () == 'a' - && getch () == 'g' - && getch () == 'm' - && getch () == 'a') - { - token = real_yylex (); - if (token == IDENTIFIER - && TREE_CODE (yylval.ttype) == IDENTIFIER_NODE) - { - /* If this is 1, we handled it; if it's -1, it was one we - wanted but had something wrong with it. Only if it's - 0 was it not handled. */ - if (handle_cp_pragma (IDENTIFIER_POINTER (yylval.ttype))) - goto skipline; - } - else if (token == END_OF_LINE) - goto skipline; - -#ifdef HANDLE_PRAGMA - /* We invoke HANDLE_PRAGMA before HANDLE_GENERIC_PRAGMAS - (if both are defined), in order to give the back - end a chance to override the interpretation of - SYSV style pragmas. */ - if (HANDLE_PRAGMA (pragma_getc, pragma_ungetc, - IDENTIFIER_POINTER (yylval.ttype))) - goto skipline; -#endif /* HANDLE_PRAGMA */ - -#ifdef HANDLE_GENERIC_PRAGMAS - if (handle_generic_pragma (token)) - goto skipline; -#endif /* HANDLE_GENERIC_PRAGMAS */ - - /* Issue a warning message if we have been asked to do so. - Ignoring unknown pragmas in system header file unless - an explcit -Wunknown-pragmas has been given. */ - if (warn_unknown_pragmas > 1 - || (warn_unknown_pragmas && ! in_system_header)) - warning ("ignoring pragma: %s", token_buffer); - } - - goto skipline; - } - else if (c == 'd') - { - if (getch () == 'e' - && getch () == 'f' - && getch () == 'i' - && getch () == 'n' - && getch () == 'e' - && ((c = getch ()) == ' ' || c == '\t')) - { - debug_define (lineno, GET_DIRECTIVE_LINE ()); - goto skipline; - } - } - else if (c == 'u') - { - if (getch () == 'n' - && getch () == 'd' - && getch () == 'e' - && getch () == 'f' - && ((c = getch ()) == ' ' || c == '\t')) - { - debug_undef (lineno, GET_DIRECTIVE_LINE ()); - goto skipline; - } - } - else if (c == 'l') - { - if (getch () == 'i' - && getch () == 'n' - && getch () == 'e' - && ((c = getch ()) == ' ' || c == '\t')) - { - saw_line = 1; - goto linenum; - } - } - else if (c == 'i') - { - if (getch () == 'd' - && getch () == 'e' - && getch () == 'n' - && getch () == 't' - && ((c = getch ()) == ' ' || c == '\t')) - { - /* #ident. The pedantic warning is now in cccp.c. */ - - /* Here we have just seen `#ident '. - A string constant should follow. */ - - token = real_yylex (); - if (token == END_OF_LINE) - goto skipline; - if (token != STRING - || TREE_CODE (yylval.ttype) != STRING_CST) - { - error ("invalid #ident"); - goto skipline; - } - - if (! flag_no_ident) - { -#ifdef ASM_OUTPUT_IDENT - ASM_OUTPUT_IDENT (asm_out_file, - TREE_STRING_POINTER (yylval.ttype)); -#endif - } - - /* Skip the rest of this line. */ - goto skipline; - } - } - else if (c == 'n') - { - if (getch () == 'e' - && getch () == 'w' - && getch () == 'w' - && getch () == 'o' - && getch () == 'r' - && getch () == 'l' - && getch () == 'd' - && ((c = getch ()) == ' ' || c == '\t')) - { - /* Used to test incremental compilation. */ - sorry ("#pragma newworld"); - goto skipline; - } - } - error ("undefined or invalid # directive"); - goto skipline; + result = x; + if (c_lex (&x) != CPP_EOF) + warning ("junk at end of #pragma %s", name); + return result; } -linenum: - /* Here we have either `#line' or `# '. - In either case, it should be a line number; a digit should follow. */ - - while (c == ' ' || c == '\t') - c = getch (); - - /* If the # is the only nonwhite char on the line, - just ignore it. Check the new newline. */ - if (c == EOF) - goto skipline; - - /* Something follows the #; read a token. */ - - put_back (c); - token = real_yylex (); - - if (token == CONSTANT - && TREE_CODE (yylval.ttype) == INTEGER_CST) - { - int old_lineno = lineno; - enum { act_none, act_push, act_pop } action = act_none; - int entering_system_header = 0; - int entering_c_header = 0; - - /* subtract one, because it is the following line that - gets the specified number */ - - int l = TREE_INT_CST_LOW (yylval.ttype) - 1; - c = get_last_nonwhite_on_line (); - if (c == EOF) - { - /* No more: store the line number and check following line. */ - lineno = l; - goto skipline; - } - put_back (c); - - /* More follows: it must be a string constant (filename). */ - - if (saw_line) - { - /* Don't treat \ as special if we are processing #line 1 "...". - If you want it to be treated specially, use # 1 "...". */ - ignore_escape_flag = 1; - } - - /* Read the string constant. */ - token = real_yylex (); - - ignore_escape_flag = 0; - - if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST) - { - error ("invalid #line"); - goto skipline; - } - - /* Changing files again. This means currently collected time - is charged against header time, and body time starts back - at 0. */ - if (flag_detailed_statistics) - { - int this_time = my_get_run_time (); - tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype)); - header_time += this_time - body_time; - TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time)) - += this_time - body_time; - this_filename_time = time_identifier; - body_time = this_time; - } - - input_filename - = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1); - strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype)); - lineno = l; - GNU_xref_file (input_filename); - - if (main_input_filename == 0) - { - struct impl_files *ifiles = impl_file_chain; - - if (ifiles) - { - while (ifiles->next) - ifiles = ifiles->next; - ifiles->filename = file_name_nondirectory (input_filename); - } - - main_input_filename = input_filename; - if (write_virtuals == 3) - { - walk_globals (vtable_decl_p, - set_vardecl_interface_info, - /*data=*/0); - walk_globals (vtype_decl_p, - set_typedecl_interface_info, - /*data=*/0); - } - } - - extract_interface_info (); - - c = get_last_nonwhite_on_line (); - if (c == EOF) - { - /* Update the name in the top element of input_file_stack. */ - if (input_file_stack) - input_file_stack->name = input_filename; - } - else - { - put_back (c); - - token = real_yylex (); - - /* `1' after file name means entering new file. - `2' after file name means just left a file. */ - - if (token == CONSTANT - && TREE_CODE (yylval.ttype) == INTEGER_CST) - { - if (TREE_INT_CST_LOW (yylval.ttype) == 1) - action = act_push; - else if (TREE_INT_CST_LOW (yylval.ttype) == 2) - action = act_pop; - - if (action) - { - c = get_last_nonwhite_on_line (); - if (c != EOF) - { - put_back (c); - token = real_yylex (); - } - } - } - - /* `3' after file name means this is a system header file. */ - - if (token == CONSTANT - && TREE_CODE (yylval.ttype) == INTEGER_CST - && TREE_INT_CST_LOW (yylval.ttype) == 3) - { - entering_system_header = 1; - - c = get_last_nonwhite_on_line (); - if (c != EOF) - { - put_back (c); - token = real_yylex (); - } - } - - /* `4' after file name means this is a C header file. */ - - if (token == CONSTANT - && TREE_CODE (yylval.ttype) == INTEGER_CST - && TREE_INT_CST_LOW (yylval.ttype) == 4) - { - entering_c_header = 1; - - c = get_last_nonwhite_on_line (); - if (c != EOF) - { - put_back (c); - token = real_yylex (); - } - } - - /* Do the actions implied by the preceding numbers. */ - - if (action == act_push) - { - /* Pushing to a new file. */ - struct file_stack *p; - - p = (struct file_stack *) xmalloc (sizeof (struct file_stack)); - input_file_stack->line = old_lineno; - p->next = input_file_stack; - p->name = input_filename; - input_file_stack = p; - input_file_stack_tick++; - debug_start_source_file (input_filename); - in_system_header = entering_system_header; - if (c_header_level) - ++c_header_level; - else if (entering_c_header) - { - c_header_level = 1; - ++pending_lang_change; - } - } - else if (action == act_pop) - { - /* Popping out of a file. */ - if (input_file_stack->next) - { - struct file_stack *p; - - if (c_header_level && --c_header_level == 0) - { - if (entering_c_header) - warning ("badly nested C headers from preprocessor"); - --pending_lang_change; - } - in_system_header = entering_system_header; - - p = input_file_stack; - input_file_stack = p->next; - free (p); - input_file_stack_tick++; - debug_end_source_file (input_file_stack->line); - } - else - error ("#-lines for entering and leaving files don't match"); - } - else - in_system_header = entering_system_header; - } + if (t == CPP_EOF && opt) + return 0; - /* If NEXTCHAR is not end of line, we don't care what it is. */ - if (nextchar == EOF) - c = EOF; - } - else - error ("invalid #-line"); - - /* skip the rest of this line. */ - skipline: - linemode = 0; - end_of_file = 0; - nextchar = -1; - while ((c = getch ()) != EOF && c != '\n'); - return c; + error ("invalid #pragma %s", name); + return (tree)-1; } -void -do_pending_lang_change () +static void +handle_pragma_vtable (dfile) + cpp_reader *dfile ATTRIBUTE_UNUSED; { - for (; pending_lang_change > 0; --pending_lang_change) - push_lang_context (lang_name_c); - for (; pending_lang_change < 0; ++pending_lang_change) - pop_lang_context (); + parse_strconst_pragma ("vtable", 0); + sorry ("#pragma vtable no longer supported"); } - -#define ENDFILE -1 /* token that represents end-of-file */ - -/* Read an escape sequence, returning its equivalent as a character, - or store 1 in *ignore_ptr if it is backslash-newline. */ - -static int -readescape (ignore_ptr) - int *ignore_ptr; -{ - register int c = getch (); - register int code; - register unsigned count; - unsigned firstdig = 0; - int nonnull; - - switch (c) - { - case 'x': - code = 0; - count = 0; - nonnull = 0; - while (1) - { - c = getch (); - if (! ISXDIGIT (c)) - { - put_back (c); - break; - } - code *= 16; - if (c >= 'a' && c <= 'f') - code += c - 'a' + 10; - if (c >= 'A' && c <= 'F') - code += c - 'A' + 10; - if (c >= '0' && c <= '9') - code += c - '0'; - if (code != 0 || count != 0) - { - if (count == 0) - firstdig = code; - count++; - } - nonnull = 1; - } - if (! nonnull) - error ("\\x used with no following hex digits"); - else if (count == 0) - /* Digits are all 0's. Ok. */ - ; - else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node) - || (count > 1 - && (((unsigned)1 << - (TYPE_PRECISION (integer_type_node) - (count - 1) * 4)) - <= firstdig))) - pedwarn ("hex escape out of range"); - return code; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': - code = 0; - count = 0; - while ((c <= '7') && (c >= '0') && (count++ < 3)) - { - code = (code * 8) + (c - '0'); - c = getch (); - } - put_back (c); - return code; - case '\\': case '\'': case '"': - return c; +static void +handle_pragma_unit (dfile) + cpp_reader *dfile ATTRIBUTE_UNUSED; +{ + /* Validate syntax, but don't do anything. */ + parse_strconst_pragma ("unit", 0); +} - case '\n': - lineno++; - *ignore_ptr = 1; - return 0; +static void +handle_pragma_interface (dfile) + cpp_reader *dfile ATTRIBUTE_UNUSED; +{ + tree fname = parse_strconst_pragma ("interface", 1); + struct c_fileinfo *finfo; + const char *main_filename; - case 'n': - return TARGET_NEWLINE; + if (fname == (tree)-1) + return; + else if (fname == 0) + main_filename = lbasename (input_filename); + else + main_filename = TREE_STRING_POINTER (fname); - case 't': - return TARGET_TAB; + finfo = get_fileinfo (input_filename); - case 'r': - return TARGET_CR; + if (impl_file_chain == 0) + { + /* If this is zero at this point, then we are + auto-implementing. */ + if (main_input_filename == 0) + main_input_filename = input_filename; + } - case 'f': - return TARGET_FF; + interface_only = interface_strcmp (main_filename); +#ifdef MULTIPLE_SYMBOL_SPACES + if (! interface_only) +#endif + interface_unknown = 0; - case 'b': - return TARGET_BS; + finfo->interface_only = interface_only; + finfo->interface_unknown = interface_unknown; +} - case 'a': - return TARGET_BELL; +/* Note that we have seen a #pragma implementation for the key MAIN_FILENAME. + We used to only allow this at toplevel, but that restriction was buggy + in older compilers and it seems reasonable to allow it in the headers + themselves, too. It only needs to precede the matching #p interface. - case 'v': - return TARGET_VT; + We don't touch interface_only or interface_unknown; the user must specify + a matching #p interface for this to have any effect. */ - case 'e': - case 'E': - if (pedantic) - pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c); - return 033; +static void +handle_pragma_implementation (dfile) + cpp_reader *dfile ATTRIBUTE_UNUSED; +{ + tree fname = parse_strconst_pragma ("implementation", 1); + const char *main_filename; + struct impl_files *ifiles = impl_file_chain; - case '?': - return c; + if (fname == (tree)-1) + return; - /* `\(', etc, are used at beginning of line to avoid confusing Emacs. */ - case '(': - case '{': - case '[': - /* `\%' is used to prevent SCCS from getting confused. */ - case '%': - if (pedantic) - pedwarn ("unknown escape sequence `\\%c'", c); - return c; + if (fname == 0) + { + if (main_input_filename) + main_filename = main_input_filename; + else + main_filename = input_filename; + main_filename = lbasename (main_filename); } - if (ISGRAPH (c)) - pedwarn ("unknown escape sequence `\\%c'", c); else - pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c); - return c; -} - -/* Value is 1 (or 2) if we should try to make the next identifier look like - a typename (when it may be a local variable or a class variable). - Value is 0 if we treat this name in a default fashion. */ -int looking_for_typename; + { + main_filename = TREE_STRING_POINTER (fname); + if (cpp_included (parse_in, main_filename)) + warning ("#pragma implementation for %s appears after file is included", + main_filename); + } -#ifdef __GNUC__ -__inline -#endif -int -identifier_type (decl) - tree decl; -{ - tree t; - if (TREE_CODE (decl) == TEMPLATE_DECL) + for (; ifiles; ifiles = ifiles->next) { - if (TREE_CODE (DECL_RESULT (decl)) == TYPE_DECL) - return PTYPENAME; - else if (looking_for_template) - return PFUNCNAME; + if (! strcmp (ifiles->filename, main_filename)) + break; } - if (looking_for_template && really_overloaded_fn (decl)) + if (ifiles == 0) { - /* See through a baselink. */ - if (TREE_CODE (decl) == TREE_LIST) - decl = TREE_VALUE (decl); - - for (t = decl; t != NULL_TREE; t = OVL_CHAIN (t)) - if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t))) - return PFUNCNAME; + ifiles = (struct impl_files*) xmalloc (sizeof (struct impl_files)); + ifiles->filename = main_filename; + ifiles->next = impl_file_chain; + impl_file_chain = ifiles; } - 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 TYPENAME; +} + +/* Indicate that this file uses Java-personality exception handling. */ +static void +handle_pragma_java_exceptions (dfile) + cpp_reader *dfile ATTRIBUTE_UNUSED; +{ + tree x; + if (c_lex (&x) != CPP_EOF) + warning ("junk at end of #pragma GCC java_exceptions"); + + choose_personality_routine (lang_java); } void -see_typename () +do_pending_lang_change () { - /* 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 == 0) - { - if (flag_labels_ok) - lastiddecl = IDENTIFIER_LABEL_VALUE (yylval.ttype); - } - else - yychar = identifier_type (lastiddecl); - } + for (; pending_lang_change > 0; --pending_lang_change) + push_lang_context (lang_name_c); + for (; pending_lang_change < 0; ++pending_lang_change) + pop_lang_context (); } /* Return true if d is in a global scope. */ @@ -2830,9 +1195,9 @@ is_global (d) case OVERLOAD: d = OVL_FUNCTION (d); continue; case TREE_LIST: d = TREE_VALUE (d); continue; default: - my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (d)) == 'd', 980629); - d = CP_DECL_CONTEXT (d); - return TREE_CODE (d) == NAMESPACE_DECL; + my_friendly_assert (DECL_P (d), 980629); + + return DECL_NAMESPACE_SCOPE_P (d); } } @@ -2844,64 +1209,28 @@ do_identifier (token, parsing, args) { register tree id; int lexing = (parsing == 1); - int in_call = (parsing == 2); - if (! lexing || IDENTIFIER_OPNAME_P (token)) + if (! lexing) id = lookup_name (token, 0); else id = lastiddecl; - /* Scope class declarations before global - declarations. */ - if ((!id || is_global (id)) - && current_class_type != 0 - && TYPE_SIZE (current_class_type) == 0) - { - /* Could be from one of the base classes. */ - tree field = lookup_field (current_class_type, token, 1, 0); - if (field == 0) - ; - else if (field == error_mark_node) - /* We have already generated the error message. - But we still want to return this value. */ - id = lookup_field (current_class_type, token, 0, 0); - else if (TREE_CODE (field) == VAR_DECL - || TREE_CODE (field) == CONST_DECL - || TREE_CODE (field) == TEMPLATE_DECL) - id = field; - else if (TREE_CODE (field) == TYPE_DECL - && DECL_ARTIFICIAL (field) - && IMPLICIT_TYPENAME_P (TREE_TYPE (field))) - /* When we did name-lookup before, we will have eschewed - implicit typenames in favor of global bindings. Therefore, - if lookup_field returns an implicit typename, but ID is not - an implicit typename, then we should skip this one, too. */ - ; - else if (TREE_CODE (field) != FIELD_DECL) - my_friendly_abort (61); - else - { - cp_error ("invalid use of member `%D'", field); - id = error_mark_node; - return id; - } - } + if (lexing && id && TREE_DEPRECATED (id)) + warn_deprecated_use (id); /* Do Koenig lookup if appropriate (inside templates we build lookup - expressions instead). */ + expressions instead). + + [basic.lookup.koenig]: If the ordinary unqualified lookup of the name + finds the declaration of a class member function, the associated + namespaces and classes are not considered. */ + if (args && !current_template_parms && (!id || is_global (id))) - /* If we have arguments and we only found global names, do Koenig - lookup. */ id = lookup_arg_dependent (token, id, args); /* Remember that this name has been used in the class definition, as per [class.scope0] */ - if (id && parsing - /* Avoid breaking if we get called for a default argument that - refers to an overloaded method. Eventually this will not be - necessary, since default arguments shouldn't be parsed until - after the class is complete. (jason 3/12/97) */ - && TREE_CODE (id) != OVERLOAD) + if (id && parsing) maybe_note_name_used_in_class (token, id); if (id == error_mark_node) @@ -2913,24 +1242,21 @@ do_identifier (token, parsing, args) id = lookup_name (token, 0); return error_mark_node; } - - if (!id) + + if (!id || (TREE_CODE (id) == FUNCTION_DECL + && DECL_ANTICIPATED (id))) { if (current_template_parms) return build_min_nt (LOOKUP_EXPR, token); else if (IDENTIFIER_OPNAME_P (token)) { - if (token != ansi_opname[ERROR_MARK]) - cp_error ("`%D' not defined", token); + if (token != ansi_opname (ERROR_MARK)) + error ("`%D' not defined", token); id = error_mark_node; } - else if (in_call && ! flag_strict_prototype) - { - id = implicitly_declare (token); - } else if (current_function_decl == 0) { - cp_error ("`%D' was not declared in this scope", token); + error ("`%D' was not declared in this scope", token); id = error_mark_node; } else @@ -2940,12 +1266,11 @@ do_identifier (token, parsing, args) { static int undeclared_variable_notice; - cp_error ("`%D' undeclared (first use this function)", token); + error ("`%D' undeclared (first use this function)", token); if (! undeclared_variable_notice) { - error ("(Each undeclared identifier is reported only once"); - error ("for each function it appears in.)"); + error ("(Each undeclared identifier is reported only once for each function it appears in.)"); undeclared_variable_notice = 1; } } @@ -2970,7 +1295,7 @@ do_identifier (token, parsing, args) { warning ("name lookup of `%s' changed", IDENTIFIER_POINTER (token)); - cp_warning_at (" matches this `%D' under current ANSI rules", + cp_warning_at (" matches this `%D' under ISO standard rules", shadowed); cp_warning_at (" matches this `%D' under old rules", id); DECL_ERROR_REPORTED (id) = 1; @@ -2979,18 +1304,18 @@ do_identifier (token, parsing, args) } else if (!DECL_ERROR_REPORTED (id)) { - static char msg[] - = "name lookup of `%s' changed for new ANSI `for' scoping"; DECL_ERROR_REPORTED (id) = 1; - if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (id))) + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (id))) { - error (msg, IDENTIFIER_POINTER (token)); + error ("name lookup of `%s' changed for new ISO `for' scoping", + IDENTIFIER_POINTER (token)); cp_error_at (" cannot use obsolete binding at `%D' because it has a destructor", id); id = error_mark_node; } else { - pedwarn (msg, IDENTIFIER_POINTER (token)); + pedwarn ("name lookup of `%s' changed for new ISO `for' scoping", + IDENTIFIER_POINTER (token)); cp_pedwarn_at (" using obsolete binding at `%D'", id); } } @@ -3000,7 +1325,7 @@ do_identifier (token, parsing, args) { /* Check access. */ if (IDENTIFIER_CLASS_VALUE (token) == id) - enforce_access (DECL_REAL_CONTEXT(id), id); + enforce_access (CP_DECL_CONTEXT(id), id); if (!processing_template_decl || DECL_TEMPLATE_PARM_P (id)) id = DECL_INITIAL (id); } @@ -3016,22 +1341,15 @@ do_identifier (token, parsing, args) like local variables, rather than creating TEMPLATE_DECLs for the local variables and then finding matching instantiations. */ if (current_template_parms - && (is_overloaded_fn (id) - /* If it's not going to be around at instantiation time, we - look it up then. This is a hack, and should go when we - really get dependent/independent name lookup right. */ - || !TREE_PERMANENT (id) - /* Some local VAR_DECLs (such as those for local variables - in member functions of local classes) are built on the - permanent obstack. */ - || (TREE_CODE (id) == VAR_DECL + && (is_overloaded_fn (id) + || (TREE_CODE (id) == VAR_DECL && CP_DECL_CONTEXT (id) && TREE_CODE (CP_DECL_CONTEXT (id)) == FUNCTION_DECL) || TREE_CODE (id) == PARM_DECL || TREE_CODE (id) == RESULT_DECL || TREE_CODE (id) == USING_DECL)) id = build_min_nt (LOOKUP_EXPR, token); - + return id; } @@ -3043,1463 +1361,90 @@ do_scoped_id (token, parsing) tree id; /* during parsing, this is ::name. Otherwise, it is black magic. */ if (parsing) - { - struct tree_binding _b; - id = binding_init (&_b); - if (!qualified_lookup_using_namespace (token, global_namespace, id, 0)) - id = NULL_TREE; - else - id = BINDING_VALUE (id); - } - else - id = IDENTIFIER_GLOBAL_VALUE (token); - if (parsing && yychar == YYEMPTY) - yychar = yylex (); - if (! id) - { - if (processing_template_decl) - { - id = build_min_nt (LOOKUP_EXPR, token); - LOOKUP_EXPR_GLOBAL (id) = 1; - return id; - } - if (parsing && (yychar == '(' || yychar == LEFT_RIGHT) - && ! flag_strict_prototype) - id = implicitly_declare (token); - else - { - if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node) - cp_error ("`::%D' undeclared (first use here)", token); - id = error_mark_node; - /* Prevent repeated error messages. */ - SET_IDENTIFIER_NAMESPACE_VALUE (token, error_mark_node); - } - } - else - { - if (TREE_CODE (id) == ADDR_EXPR) - mark_used (TREE_OPERAND (id, 0)); - else if (TREE_CODE (id) != OVERLOAD) - mark_used (id); - } - if (TREE_CODE (id) == CONST_DECL && ! processing_template_decl) - { - /* XXX CHS - should we set TREE_USED of the constant? */ - id = DECL_INITIAL (id); - /* This is to prevent an enum whose value is 0 - from being considered a null pointer constant. */ - id = build1 (NOP_EXPR, TREE_TYPE (id), id); - TREE_CONSTANT (id) = 1; - } - - if (processing_template_decl) - { - if (is_overloaded_fn (id)) - { - id = build_min_nt (LOOKUP_EXPR, token); - LOOKUP_EXPR_GLOBAL (id) = 1; - return id; - } - /* else just use the decl */ - } - return convert_from_reference (id); -} - -tree -identifier_typedecl_value (node) - tree node; -{ - tree t, type; - type = IDENTIFIER_TYPE_VALUE (node); - if (type == NULL_TREE) - return NULL_TREE; - - if (IDENTIFIER_BINDING (node)) - { - t = IDENTIFIER_VALUE (node); - if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) - return t; - } - if (IDENTIFIER_NAMESPACE_VALUE (node)) - { - t = IDENTIFIER_NAMESPACE_VALUE (node); - if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) - return t; - } - - /* Will this one ever happen? */ - if (TYPE_MAIN_DECL (type)) - return TYPE_MAIN_DECL (type); - - /* We used to do an internal error of 62 here, but instead we will - handle the return of a null appropriately in the callers. */ - return NULL_TREE; -} - -struct pf_args -{ - /* Input */ - /* I/O */ - char *p; - int c; - int imag; - tree type; - /* Output */ - REAL_VALUE_TYPE value; -}; - -static void -parse_float (data) - PTR data; -{ - struct pf_args * args = (struct pf_args *) data; - int fflag = 0, lflag = 0; - /* Copy token_buffer now, while it has just the number - and not the suffixes; once we add `f' or `i', - REAL_VALUE_ATOF may not work any more. */ - char *copy = (char *) alloca (args->p - token_buffer + 1); - bcopy (token_buffer, copy, args->p - token_buffer + 1); - - while (1) - { - int lose = 0; - - /* Read the suffixes to choose a data type. */ - switch (args->c) - { - case 'f': case 'F': - if (fflag) - error ("more than one `f' in numeric constant"); - fflag = 1; - break; - - case 'l': case 'L': - if (lflag) - error ("more than one `l' in numeric constant"); - lflag = 1; - break; - - case 'i': case 'I': - if (args->imag) - error ("more than one `i' or `j' in numeric constant"); - else if (pedantic) - pedwarn ("ANSI C++ forbids imaginary numeric constants"); - args->imag = 1; - break; - - default: - lose = 1; - } - - if (lose) - break; - - if (args->p >= token_buffer + maxtoken - 3) - args->p = extend_token_buffer (args->p); - *(args->p++) = args->c; - *(args->p) = 0; - args->c = getch (); - } - - /* The second argument, machine_mode, of REAL_VALUE_ATOF - tells the desired precision of the binary result - of decimal-to-binary conversion. */ - - if (fflag) - { - if (lflag) - error ("both `f' and `l' in floating constant"); - - args->type = float_type_node; - args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type)); - /* A diagnostic is required here by some ANSI C testsuites. - This is not pedwarn, become some people don't want - an error for this. */ - if (REAL_VALUE_ISINF (args->value) && pedantic) - warning ("floating point number exceeds range of `float'"); - } - else if (lflag) - { - args->type = long_double_type_node; - args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type)); - if (REAL_VALUE_ISINF (args->value) && pedantic) - warning ("floating point number exceeds range of `long double'"); - } - else - { - args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type)); - if (REAL_VALUE_ISINF (args->value) && pedantic) - warning ("floating point number exceeds range of `double'"); - } -} - -int -real_yylex () -{ - register int c; - register int value; - int wide_flag = 0; - int dollar_seen = 0; - int i; - - if (nextchar >= 0) - c = nextchar, nextchar = -1; - else - c = getch (); - - /* Effectively do c = skip_white_space (c) - but do it faster in the usual cases. */ - while (1) - switch (c) - { - case ' ': - case '\t': - case '\f': - case '\v': - case '\b': - c = getch (); - break; - - case '\r': - /* Call skip_white_space so we can warn if appropriate. */ - - case '\n': - case '/': - case '\\': - c = skip_white_space (c); - default: - goto found_nonwhite; - } - found_nonwhite: - - token_buffer[0] = c; - token_buffer[1] = 0; - -/* yylloc.first_line = lineno; */ - - switch (c) - { - case EOF: - token_buffer[0] = '\0'; - end_of_file = 1; - if (input_redirected ()) - value = END_OF_SAVED_INPUT; - else if (linemode) - value = END_OF_LINE; - else - value = ENDFILE; - break; - - case '$': - if (! dollars_in_ident) - error ("`$' in identifier"); - else if (pedantic) - pedwarn ("`$' in identifier"); - dollar_seen = 1; - goto letter; - - case 'L': - /* Capital L may start a wide-string or wide-character constant. */ - { - register int c = getch (); - if (c == '\'') - { - wide_flag = 1; - goto char_constant; - } - if (c == '"') - { - wide_flag = 1; - goto string_constant; - } - put_back (c); - } - - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': case 'G': case 'H': case 'I': case 'J': - case 'K': case 'M': case 'N': case 'O': - case 'P': case 'Q': case 'R': case 'S': case 'T': - case 'U': case 'V': case 'W': case 'X': case 'Y': - case 'Z': - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': case 'g': case 'h': case 'i': case 'j': - case 'k': case 'l': case 'm': case 'n': case 'o': - case 'p': case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'x': case 'y': - case 'z': - case '_': - letter: - { - register char *p; - - p = token_buffer; - if (input == 0) - { - /* We know that `token_buffer' can hold at least on char, - so we install C immediately. - We may have to read the value in `putback_char', so call - `getch' once. */ - *p++ = c; - c = getch (); - - /* Make this run fast. We know that we are reading straight - from FINPUT in this case (since identifiers cannot straddle - input sources. */ - while (ISALNUM (c) || (c == '_') || c == '$') - { - if (c == '$') - { - if (! dollars_in_ident) - error ("`$' in identifier"); - else if (pedantic) - pedwarn ("`$' in identifier"); - } - - if (p >= token_buffer + maxtoken) - p = extend_token_buffer (p); - - *p++ = c; - c = getch (); - } - - if (linemode && c == '\n') - { - put_back (c); - c = EOF; - } - } - else - { - /* We know that `token_buffer' can hold at least on char, - so we install C immediately. */ - *p++ = c; - c = getch (); - - while (ISALNUM (c) || (c == '_') || c == '$') - { - if (c == '$') - { - if (! dollars_in_ident) - error ("`$' in identifier"); - else if (pedantic) - pedwarn ("`$' in identifier"); - } - - if (p >= token_buffer + maxtoken) - p = extend_token_buffer (p); - - *p++ = c; - c = getch (); - } - } - - *p = 0; - nextchar = c; - - value = IDENTIFIER; - yylval.itype = 0; - - /* Try to recognize a keyword. Uses minimum-perfect hash function */ - - { - register struct resword *ptr; - - if ((ptr = is_reserved_word (token_buffer, p - token_buffer))) - { - if (ptr->rid) - { - tree old_ttype = ridpointers[(int) ptr->rid]; - - /* If this provides a type for us, then revert lexical - state to standard state. */ - if (TREE_CODE (old_ttype) == IDENTIFIER_NODE - && IDENTIFIER_GLOBAL_VALUE (old_ttype) != 0 - && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (old_ttype)) == TYPE_DECL) - looking_for_typename = 0; - else if (ptr->token == AGGR || ptr->token == ENUM) - looking_for_typename = 2; - - /* Check if this is a language-type declaration. - Just glimpse the next non-white character. */ - nextchar = skip_white_space (nextchar); - if (nextchar == '"') - { - /* We are looking at a string. Complain - if the token before the string is no `extern'. - - Could cheat some memory by placing this string - on the temporary_, instead of the saveable_ - obstack. */ - - if (ptr->rid != RID_EXTERN) - error ("invalid modifier `%s' for language string", - ptr->name); - real_yylex (); - value = EXTERN_LANG_STRING; - yylval.ttype = get_identifier (TREE_STRING_POINTER (yylval.ttype)); - break; - } - if (ptr->token == VISSPEC) - { - switch (ptr->rid) - { - case RID_PUBLIC: - yylval.ttype = access_public_node; - break; - case RID_PRIVATE: - yylval.ttype = access_private_node; - break; - case RID_PROTECTED: - yylval.ttype = access_protected_node; - break; - default: - my_friendly_abort (63); - } - } - else - yylval.ttype = old_ttype; - } - else if (ptr->token == EQCOMPARE) - { - yylval.code = NE_EXPR; - token_buffer[0] = '!'; - token_buffer[1] = '='; - token_buffer[2] = 0; - } - else if (ptr->token == ASSIGN) - { - if (strcmp ("and_eq", token_buffer) == 0) - { - yylval.code = BIT_AND_EXPR; - token_buffer[0] = '&'; - } - else if (strcmp ("or_eq", token_buffer) == 0) - { - yylval.code = BIT_IOR_EXPR; - token_buffer[0] = '|'; - } - else if (strcmp ("xor_eq", token_buffer) == 0) - { - yylval.code = BIT_XOR_EXPR; - token_buffer[0] = '^'; - } - token_buffer[1] = '='; - token_buffer[2] = 0; - } - else if (ptr->token == '&') - { - yylval.code = BIT_AND_EXPR; - token_buffer[0] = '&'; - token_buffer[1] = 0; - } - else if (ptr->token == '|') - { - yylval.code = BIT_IOR_EXPR; - token_buffer[0] = '|'; - token_buffer[1] = 0; - } - else if (ptr->token == '^') - { - yylval.code = BIT_XOR_EXPR; - token_buffer[0] = '^'; - token_buffer[1] = 0; - } - - value = (int) ptr->token; - } - } - - /* If we did not find a keyword, look for an identifier - (or a typename). */ - - if (value == IDENTIFIER || value == TYPESPEC) - GNU_xref_ref (current_function_decl, token_buffer); - - if (value == IDENTIFIER) - { - register tree tmp = get_identifier (token_buffer); - -#if !defined(VMS) && defined(JOINER) - /* Make sure that user does not collide with our internal - naming scheme. */ - if (JOINER == '$' - && dollar_seen - && (THIS_NAME_P (tmp) - || VPTR_NAME_P (tmp) - || DESTRUCTOR_NAME_P (tmp) - || VTABLE_NAME_P (tmp) - || TEMP_NAME_P (tmp) - || ANON_AGGRNAME_P (tmp) - || ANON_PARMNAME_P (tmp))) - warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy", - token_buffer); -#endif - - yylval.ttype = tmp; - } - if (value == NEW && ! global_bindings_p ()) - { - value = NEW; - goto done; - } - } - break; - - case '.': - { - register int c1 = getch (); - token_buffer[0] = c; - token_buffer[1] = c1; - if (c1 == '*') - { - value = DOT_STAR; - token_buffer[2] = 0; - goto done; - } - if (c1 == '.') - { - c1 = getch (); - if (c1 == '.') - { - token_buffer[2] = c1; - token_buffer[3] = 0; - value = ELLIPSIS; - goto done; - } - error ("parse error at `..'"); - } - if (ISDIGIT (c1)) - { - put_back (c1); - goto resume_numerical_scan; - } - nextchar = c1; - value = '.'; - token_buffer[1] = 0; - goto done; - } - case '0': case '1': - /* Optimize for most frequent case. */ - { - register int c1 = getch (); - if (! ISALNUM (c1) && c1 != '.') - { - /* Terminate string. */ - token_buffer[0] = c; - token_buffer[1] = 0; - if (c == '0') - yylval.ttype = integer_zero_node; - else - yylval.ttype = integer_one_node; - nextchar = c1; - value = CONSTANT; - goto done; - } - put_back (c1); - } - /* fall through... */ - case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - resume_numerical_scan: - { - register char *p; - int base = 10; - int count = 0; - int largest_digit = 0; - int numdigits = 0; - /* for multi-precision arithmetic, - we actually store only HOST_BITS_PER_CHAR bits in each part. - The number of parts is chosen so as to be sufficient to hold - the enough bits to fit into the two HOST_WIDE_INTs that contain - the integer value (this is always at least as many bits as are - in a target `long long' value, but may be wider). */ -#define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2 + 2) - int parts[TOTAL_PARTS]; - int overflow = 0; - - enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag - = NOT_FLOAT; - - for (count = 0; count < TOTAL_PARTS; count++) - parts[count] = 0; - - p = token_buffer; - *p++ = c; - - if (c == '0') - { - *p++ = (c = getch ()); - if ((c == 'x') || (c == 'X')) - { - base = 16; - *p++ = (c = getch ()); - } - /* Leading 0 forces octal unless the 0 is the only digit. */ - else if (c >= '0' && c <= '9') - { - base = 8; - numdigits++; - } - else - numdigits++; - } - - /* Read all the digits-and-decimal-points. */ - - while (c == '.' - || (ISALNUM (c) && (c != 'l') && (c != 'L') - && (c != 'u') && (c != 'U') - && c != 'i' && c != 'I' && c != 'j' && c != 'J' - && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F'))))) - { - if (c == '.') - { - if (base == 16) - error ("floating constant may not be in radix 16"); - if (floatflag == TOO_MANY_POINTS) - /* We have already emitted an error. Don't need another. */ - ; - else if (floatflag == AFTER_POINT) - { - error ("malformed floating constant"); - floatflag = TOO_MANY_POINTS; - /* Avoid another error from atof by forcing all characters - from here on to be ignored. */ - p[-1] = '\0'; - } - else - floatflag = AFTER_POINT; - - base = 10; - *p++ = c = getch (); - /* Accept '.' as the start of a floating-point number - only when it is followed by a digit. - Otherwise, unread the following non-digit - and use the '.' as a structural token. */ - if (p == token_buffer + 2 && !ISDIGIT (c)) - { - if (c == '.') - { - c = getch (); - if (c == '.') - { - *p++ = '.'; - *p = '\0'; - value = ELLIPSIS; - goto done; - } - error ("parse error at `..'"); - } - nextchar = c; - token_buffer[1] = '\0'; - value = '.'; - goto done; - } - } - else - { - /* It is not a decimal point. - It should be a digit (perhaps a hex digit). */ - - if (ISDIGIT (c)) - { - c = c - '0'; - } - else if (base <= 10) - { - if (c == 'e' || c == 'E') - { - base = 10; - floatflag = AFTER_POINT; - break; /* start of exponent */ - } - error ("nondigits in number and not hexadecimal"); - c = 0; - } - else if (c >= 'a') - { - c = c - 'a' + 10; - } - else - { - c = c - 'A' + 10; - } - if (c >= largest_digit) - largest_digit = c; - numdigits++; - - for (count = 0; count < TOTAL_PARTS; count++) - { - parts[count] *= base; - if (count) - { - parts[count] - += (parts[count-1] >> HOST_BITS_PER_CHAR); - parts[count-1] - &= (1 << HOST_BITS_PER_CHAR) - 1; - } - else - parts[0] += c; - } - - /* If the extra highest-order part ever gets anything in it, - the number is certainly too big. */ - if (parts[TOTAL_PARTS - 1] != 0) - overflow = 1; - - if (p >= token_buffer + maxtoken - 3) - p = extend_token_buffer (p); - *p++ = (c = getch ()); - } - } - - if (numdigits == 0) - error ("numeric constant with no digits"); - - if (largest_digit >= base) - error ("numeric constant contains digits beyond the radix"); - - /* Remove terminating char from the token buffer and delimit the string */ - *--p = 0; - - if (floatflag != NOT_FLOAT) - { - tree type = double_type_node; - int exceeds_double = 0; - int imag = 0; - REAL_VALUE_TYPE value; - struct pf_args args; - - /* Read explicit exponent if any, and put it in tokenbuf. */ - - if ((c == 'e') || (c == 'E')) - { - if (p >= token_buffer + maxtoken - 3) - p = extend_token_buffer (p); - *p++ = c; - c = getch (); - if ((c == '+') || (c == '-')) - { - *p++ = c; - c = getch (); - } - if (! ISDIGIT (c)) - error ("floating constant exponent has no digits"); - while (ISDIGIT (c)) - { - if (p >= token_buffer + maxtoken - 3) - p = extend_token_buffer (p); - *p++ = c; - c = getch (); - } - } - - *p = 0; - errno = 0; - - /* Setup input for parse_float() */ - args.p = p; - args.c = c; - args.imag = imag; - args.type = type; - - /* Convert string to a double, checking for overflow. */ - if (do_float_handler (parse_float, (PTR) &args)) - { - /* Receive output from parse_float() */ - value = args.value; - } - else - { - /* We got an exception from parse_float() */ - error ("floating constant out of range"); - value = dconst0; - } - - /* Receive output from parse_float() */ - p = args.p; - c = args.c; - imag = args.imag; - type = args.type; - -#ifdef ERANGE - if (errno == ERANGE && pedantic) - { - /* ERANGE is also reported for underflow, - so test the value to distinguish overflow from that. */ - if (REAL_VALUES_LESS (dconst1, value) - || REAL_VALUES_LESS (value, dconstm1)) - { - pedwarn ("floating point number exceeds range of `%s'", - IDENTIFIER_POINTER (TYPE_IDENTIFIER (type))); - exceeds_double = 1; - } - } -#endif - - /* If the result is not a number, assume it must have been - due to some error message above, so silently convert - it to a zero. */ - if (REAL_VALUE_ISNAN (value)) - value = dconst0; - - /* Create a node with determined type and value. */ - if (imag) - yylval.ttype = build_complex (NULL_TREE, - cp_convert (type, integer_zero_node), - build_real (type, value)); - else - yylval.ttype = build_real (type, value); - } - else - { - tree type; - HOST_WIDE_INT high, low; - int spec_unsigned = 0; - int spec_long = 0; - int spec_long_long = 0; - int spec_imag = 0; - int bytes, warn; - - while (1) - { - if (c == 'u' || c == 'U') - { - if (spec_unsigned) - error ("two `u's in integer constant"); - spec_unsigned = 1; - } - else if (c == 'l' || c == 'L') - { - if (spec_long) - { - if (spec_long_long) - error ("three `l's in integer constant"); - else if (pedantic && ! in_system_header && warn_long_long) - pedwarn ("ANSI C++ forbids long long integer constants"); - spec_long_long = 1; - } - spec_long = 1; - } - else if (c == 'i' || c == 'j' || c == 'I' || c == 'J') - { - if (spec_imag) - error ("more than one `i' or `j' in numeric constant"); - else if (pedantic) - pedwarn ("ANSI C++ forbids imaginary numeric constants"); - spec_imag = 1; - } - else - break; - if (p >= token_buffer + maxtoken - 3) - p = extend_token_buffer (p); - *p++ = c; - c = getch (); - } - - /* If the constant is not long long and it won't fit in an - unsigned long, or if the constant is long long and won't fit - in an unsigned long long, then warn that the constant is out - of range. */ - - /* ??? This assumes that long long and long integer types are - a multiple of 8 bits. This better than the original code - though which assumed that long was exactly 32 bits and long - long was exactly 64 bits. */ - - if (spec_long_long) - bytes = TYPE_PRECISION (long_long_integer_type_node) / 8; - else - bytes = TYPE_PRECISION (long_integer_type_node) / 8; - - warn = overflow; - for (i = bytes; i < TOTAL_PARTS; i++) - if (parts[i]) - warn = 1; - if (warn) - pedwarn ("integer constant out of range"); - - /* This is simplified by the fact that our constant - is always positive. */ - high = low = 0; - - for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++) - { - high |= ((HOST_WIDE_INT) parts[i + (HOST_BITS_PER_WIDE_INT - / HOST_BITS_PER_CHAR)] - << (i * HOST_BITS_PER_CHAR)); - low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR); - } - - - yylval.ttype = build_int_2 (low, high); - TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node; - - /* Calculate the ANSI type. */ - if (!spec_long && !spec_unsigned - && int_fits_type_p (yylval.ttype, integer_type_node)) - type = integer_type_node; - else if (!spec_long && (base != 10 || spec_unsigned) - && int_fits_type_p (yylval.ttype, unsigned_type_node)) - /* Nondecimal constants try unsigned even in traditional C. */ - type = unsigned_type_node; - else if (!spec_unsigned && !spec_long_long - && int_fits_type_p (yylval.ttype, long_integer_type_node)) - type = long_integer_type_node; - else if (! spec_long_long) - type = long_unsigned_type_node; - else if (! spec_unsigned - /* Verify value does not overflow into sign bit. */ - && TREE_INT_CST_HIGH (yylval.ttype) >= 0 - && int_fits_type_p (yylval.ttype, - long_long_integer_type_node)) - type = long_long_integer_type_node; - else - type = long_long_unsigned_type_node; - - if (!int_fits_type_p (yylval.ttype, type) && !warn) - pedwarn ("integer constant out of range"); - - if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type)) - warning ("decimal integer constant is so large that it is unsigned"); - - if (spec_imag) - { - if (TYPE_PRECISION (type) - <= TYPE_PRECISION (integer_type_node)) - yylval.ttype - = build_complex (NULL_TREE, integer_zero_node, - cp_convert (integer_type_node, - yylval.ttype)); - else - error ("complex integer constant is too wide for `__complex int'"); - } - else - TREE_TYPE (yylval.ttype) = type; - } - - put_back (c); - *p = 0; - - value = CONSTANT; break; - } - - case '\'': - char_constant: - { - register int result = 0; - register int num_chars = 0; - int chars_seen = 0; - unsigned width = TYPE_PRECISION (char_type_node); - int max_chars; -#ifdef MULTIBYTE_CHARS - int longest_char = local_mb_cur_max (); - (void) local_mbtowc (NULL_PTR, NULL_PTR, 0); -#endif - - max_chars = TYPE_PRECISION (integer_type_node) / width; - if (wide_flag) - width = WCHAR_TYPE_SIZE; - - while (1) - { - tryagain: - c = getch (); - - if (c == '\'' || c == EOF) - break; - - ++chars_seen; - if (c == '\\') - { - int ignore = 0; - c = readescape (&ignore); - if (ignore) - goto tryagain; - if (width < HOST_BITS_PER_INT - && (unsigned) c >= ((unsigned)1 << width)) - pedwarn ("escape sequence out of range for character"); -#ifdef MAP_CHARACTER - if (ISPRINT (c)) - c = MAP_CHARACTER (c); -#endif - } - else if (c == '\n') - { - if (pedantic) - pedwarn ("ANSI C forbids newline in character constant"); - lineno++; - } - else - { -#ifdef MULTIBYTE_CHARS - wchar_t wc; - int i; - int char_len = -1; - for (i = 1; i <= longest_char; ++i) - { - if (i > maxtoken - 4) - extend_token_buffer (token_buffer); - - token_buffer[i] = c; - char_len = local_mbtowc (& wc, - token_buffer + 1, - i); - if (char_len != -1) - break; - c = getch (); - } - if (char_len > 1) - { - /* mbtowc sometimes needs an extra char before accepting */ - if (char_len < i) - put_back (c); - if (! wide_flag) - { - /* Merge character into result; ignore excess chars. */ - for (i = 1; i <= char_len; ++i) - { - if (i > max_chars) - break; - if (width < HOST_BITS_PER_INT) - result = (result << width) - | (token_buffer[i] - & ((1 << width) - 1)); - else - result = token_buffer[i]; - } - num_chars += char_len; - goto tryagain; - } - c = wc; - } - else - { - if (char_len == -1) - warning ("Ignoring invalid multibyte character"); - if (wide_flag) - c = wc; -#ifdef MAP_CHARACTER - else - c = MAP_CHARACTER (c); -#endif - } -#else /* ! MULTIBYTE_CHARS */ -#ifdef MAP_CHARACTER - c = MAP_CHARACTER (c); -#endif -#endif /* ! MULTIBYTE_CHARS */ - } - - if (wide_flag) - { - if (chars_seen == 1) /* only keep the first one */ - result = c; - goto tryagain; - } - - /* Merge character into result; ignore excess chars. */ - num_chars++; - if (num_chars < max_chars + 1) - { - if (width < HOST_BITS_PER_INT) - result = (result << width) | (c & ((1 << width) - 1)); - else - result = c; - } - } - - if (c != '\'') - error ("malformatted character constant"); - else if (chars_seen == 0) - error ("empty character constant"); - else if (num_chars > max_chars) - { - num_chars = max_chars; - error ("character constant too long"); - } - else if (chars_seen != 1 && warn_multichar) - warning ("multi-character character constant"); - - /* If char type is signed, sign-extend the constant. */ - if (! wide_flag) - { - int num_bits = num_chars * width; - if (num_bits == 0) - /* We already got an error; avoid invalid shift. */ - yylval.ttype = build_int_2 (0, 0); - else if (TREE_UNSIGNED (char_type_node) - || ((result >> (num_bits - 1)) & 1) == 0) - yylval.ttype - = build_int_2 (result & (~(unsigned HOST_WIDE_INT) 0 - >> (HOST_BITS_PER_WIDE_INT - num_bits)), - 0); - else - yylval.ttype - = build_int_2 (result | ~(~(unsigned HOST_WIDE_INT) 0 - >> (HOST_BITS_PER_WIDE_INT - num_bits)), - -1); - if (chars_seen <= 1) - TREE_TYPE (yylval.ttype) = char_type_node; - else - TREE_TYPE (yylval.ttype) = integer_type_node; - } - else - { - yylval.ttype = build_int_2 (result, 0); - TREE_TYPE (yylval.ttype) = wchar_type_node; - } - - value = CONSTANT; - break; - } - - case '"': - string_constant: - { - register char *p; - unsigned width = wide_flag ? WCHAR_TYPE_SIZE - : TYPE_PRECISION (char_type_node); -#ifdef MULTIBYTE_CHARS - int longest_char = local_mb_cur_max (); - (void) local_mbtowc (NULL_PTR, NULL_PTR, 0); -#endif - - c = getch (); - p = token_buffer + 1; - - while (c != '"' && c >= 0) - { - /* ignore_escape_flag is set for reading the filename in #line. */ - if (!ignore_escape_flag && c == '\\') - { - int ignore = 0; - c = readescape (&ignore); - if (ignore) - goto skipnewline; - if (width < HOST_BITS_PER_INT - && (unsigned) c >= ((unsigned)1 << width)) - warning ("escape sequence out of range for character"); - } - else if (c == '\n') - { - if (pedantic) - pedwarn ("ANSI C++ forbids newline in string constant"); - lineno++; - } - else - { -#ifdef MULTIBYTE_CHARS - wchar_t wc; - int i; - int char_len = -1; - for (i = 0; i < longest_char; ++i) - { - if (p + i >= token_buffer + maxtoken) - p = extend_token_buffer (p); - p[i] = c; - - char_len = local_mbtowc (& wc, p, i + 1); - if (char_len != -1) - break; - c = getch (); - } - if (char_len == -1) - warning ("Ignoring invalid multibyte character"); - else - { - /* mbtowc sometimes needs an extra char before accepting */ - if (char_len <= i) - put_back (c); - if (! wide_flag) - { - p += (i + 1); - c = getch (); - continue; - } - c = wc; - } -#endif /* MULTIBYTE_CHARS */ - } - - /* Add this single character into the buffer either as a wchar_t - or as a single byte. */ - if (wide_flag) - { - unsigned width = TYPE_PRECISION (char_type_node); - unsigned bytemask = (1 << width) - 1; - int byte; - - if (p + WCHAR_BYTES > token_buffer + maxtoken) - p = extend_token_buffer (p); - - for (byte = 0; byte < WCHAR_BYTES; ++byte) - { - int value; - if (byte >= (int) sizeof(c)) - value = 0; - else - value = (c >> (byte * width)) & bytemask; - if (BYTES_BIG_ENDIAN) - p[WCHAR_BYTES - byte - 1] = value; - else - p[byte] = value; - } - p += WCHAR_BYTES; - } - else - { - if (p >= token_buffer + maxtoken) - p = extend_token_buffer (p); - *p++ = c; - } - - skipnewline: - c = getch (); - if (c == EOF) { - error ("Unterminated string"); - break; - } - } - - /* Terminate the string value, either with a single byte zero - or with a wide zero. */ - if (wide_flag) - { - if (p + WCHAR_BYTES > token_buffer + maxtoken) - p = extend_token_buffer (p); - bzero (p, WCHAR_BYTES); - p += WCHAR_BYTES; - } - else - { - if (p >= token_buffer + maxtoken) - p = extend_token_buffer (p); - *p++ = 0; - } - - /* We have read the entire constant. - Construct a STRING_CST for the result. */ - - if (processing_template_decl) - push_obstacks (&permanent_obstack, &permanent_obstack); - yylval.ttype = build_string (p - (token_buffer + 1), token_buffer + 1); - if (processing_template_decl) - pop_obstacks (); - - if (wide_flag) - TREE_TYPE (yylval.ttype) = wchar_array_type_node; - else - TREE_TYPE (yylval.ttype) = char_array_type_node; - - value = STRING; break; - } - - case '+': - case '-': - case '&': - case '|': - case '<': - case '>': - case '*': - case '/': - case '%': - case '^': - case '!': - case '=': - { - register int c1; - - combine: - - switch (c) - { - case '+': - yylval.code = PLUS_EXPR; break; - case '-': - yylval.code = MINUS_EXPR; break; - case '&': - yylval.code = BIT_AND_EXPR; break; - case '|': - yylval.code = BIT_IOR_EXPR; break; - case '*': - yylval.code = MULT_EXPR; break; - case '/': - yylval.code = TRUNC_DIV_EXPR; break; - case '%': - yylval.code = TRUNC_MOD_EXPR; break; - case '^': - yylval.code = BIT_XOR_EXPR; break; - case LSHIFT: - yylval.code = LSHIFT_EXPR; break; - case RSHIFT: - yylval.code = RSHIFT_EXPR; break; - case '<': - yylval.code = LT_EXPR; break; - case '>': - yylval.code = GT_EXPR; break; - } - - token_buffer[1] = c1 = getch (); - token_buffer[2] = 0; - - if (c1 == '=') - { - switch (c) - { - case '<': - value = ARITHCOMPARE; yylval.code = LE_EXPR; goto done; - case '>': - value = ARITHCOMPARE; yylval.code = GE_EXPR; goto done; - case '!': - value = EQCOMPARE; yylval.code = NE_EXPR; goto done; - case '=': - value = EQCOMPARE; yylval.code = EQ_EXPR; goto done; - } - value = ASSIGN; goto done; - } - else if (c == c1) - switch (c) - { - case '+': - value = PLUSPLUS; goto done; - case '-': - value = MINUSMINUS; goto done; - case '&': - value = ANDAND; goto done; - case '|': - value = OROR; goto done; - case '<': - c = LSHIFT; - goto combine; - case '>': - c = RSHIFT; - goto combine; - } - else if ((c == '-') && (c1 == '>')) - { - nextchar = getch (); - if (nextchar == '*') - { - nextchar = -1; - value = POINTSAT_STAR; - } - else - value = POINTSAT; - goto done; - } - else if (c1 == '?' && (c == '<' || c == '>')) - { - token_buffer[3] = 0; - - c1 = getch (); - yylval.code = (c == '<' ? MIN_EXPR : MAX_EXPR); - if (c1 == '=') - { - /* ?= expression. */ - token_buffer[2] = c1; - value = ASSIGN; - } - else - { - value = MIN_MAX; - nextchar = c1; - } - if (pedantic) - pedwarn ("use of `operator %s' is not standard C++", - token_buffer); - goto done; - } - /* digraphs */ - else if (c == '<' && c1 == '%') - { value = '{'; goto done; } - else if (c == '<' && c1 == ':') - { value = '['; goto done; } - else if (c == '%' && c1 == '>') - { value = '}'; goto done; } - else if (c == '%' && c1 == ':') - { value = '#'; goto done; } - - nextchar = c1; - token_buffer[1] = 0; - - value = c; - goto done; - } - - case ':': - c = getch (); - if (c == ':') - { - token_buffer[1] = ':'; - token_buffer[2] = '\0'; - value = SCOPE; - yylval.itype = 1; - } - else if (c == '>') - { - value = ']'; - goto done; - } + { + id = make_node (CPLUS_BINDING); + if (!qualified_lookup_using_namespace (token, global_namespace, id, 0)) + id = NULL_TREE; else + id = BINDING_VALUE (id); + } + else + id = IDENTIFIER_GLOBAL_VALUE (token); + if (parsing && yychar == YYEMPTY) + yychar = yylex (); + if (! id) + { + if (processing_template_decl) { - nextchar = c; - value = ':'; + id = build_min_nt (LOOKUP_EXPR, token); + LOOKUP_EXPR_GLOBAL (id) = 1; + return id; } - break; - - case 0: - /* Don't make yyparse think this is eof. */ - value = 1; - break; + if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node) + error ("`::%D' undeclared (first use here)", token); + id = error_mark_node; + /* Prevent repeated error messages. */ + SET_IDENTIFIER_NAMESPACE_VALUE (token, error_mark_node); + } + else + { + if (TREE_CODE (id) == ADDR_EXPR) + mark_used (TREE_OPERAND (id, 0)); + else if (TREE_CODE (id) != OVERLOAD) + mark_used (id); + } + if (TREE_CODE (id) == CONST_DECL && ! processing_template_decl) + { + /* XXX CHS - should we set TREE_USED of the constant? */ + id = DECL_INITIAL (id); + /* This is to prevent an enum whose value is 0 + from being considered a null pointer constant. */ + id = build1 (NOP_EXPR, TREE_TYPE (id), id); + TREE_CONSTANT (id) = 1; + } - case '(': - /* try, weakly, to handle casts to pointers to functions. */ - nextchar = skip_white_space (getch ()); - if (nextchar == '*') - { - int next_c = skip_white_space (getch ()); - if (next_c == ')') - { - nextchar = -1; - yylval.ttype = build1 (INDIRECT_REF, 0, 0); - value = PAREN_STAR_PAREN; - } - else - { - put_back (next_c); - value = c; - } - } - else if (nextchar == ')') + if (processing_template_decl) + { + if (is_overloaded_fn (id)) { - nextchar = -1; - yylval.ttype = NULL_TREE; - value = LEFT_RIGHT; + id = build_min_nt (LOOKUP_EXPR, token); + LOOKUP_EXPR_GLOBAL (id) = 1; + return id; } - else value = c; - break; - - default: - value = c; + /* else just use the decl */ } - -done: -/* yylloc.last_line = lineno; */ -#ifdef GATHER_STATISTICS -#ifdef REDUCE_LENGTH - token_count[value] += 1; -#endif -#endif - - return value; + return convert_from_reference (id); } -int -is_rid (t) - tree t; +tree +identifier_typedecl_value (node) + tree node; { - return !!is_reserved_word (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t)); + tree t, type; + type = IDENTIFIER_TYPE_VALUE (node); + if (type == NULL_TREE) + return NULL_TREE; + + if (IDENTIFIER_BINDING (node)) + { + t = IDENTIFIER_VALUE (node); + if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) + return t; + } + if (IDENTIFIER_NAMESPACE_VALUE (node)) + { + t = IDENTIFIER_NAMESPACE_VALUE (node); + if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) + return t; + } + + /* Will this one ever happen? */ + if (TYPE_MAIN_DECL (type)) + return TYPE_MAIN_DECL (type); + + /* We used to do an internal error of 62 here, but instead we will + handle the return of a null appropriately in the callers. */ + return NULL_TREE; } #ifdef GATHER_STATISTICS @@ -4531,18 +1476,17 @@ extern int tree_node_counts[]; extern int tree_node_sizes[]; #endif -/* Place to save freed lang_decls which were allocated on the - permanent_obstack. @@ Not currently used. */ -tree free_lang_decl_chain; - tree build_lang_decl (code, name, type) enum tree_code code; tree name; tree type; { - register tree t = build_decl (code, name, type); + tree t; + + t = build_decl (code, name, type); retrofit_lang_decl (t); + return t; } @@ -4553,133 +1497,130 @@ void retrofit_lang_decl (t) tree t; { - struct obstack *obstack = current_obstack; - register int i = sizeof (struct lang_decl) / sizeof (int); - register int *pi; + struct lang_decl *ld; + size_t size; - if (! TREE_PERMANENT (t)) - obstack = saveable_obstack; - else - /* Could be that saveable is permanent and current is not. */ - obstack = &permanent_obstack; - - if (free_lang_decl_chain && obstack == &permanent_obstack) - { - pi = (int *)free_lang_decl_chain; - free_lang_decl_chain = TREE_CHAIN (free_lang_decl_chain); - } + if (CAN_HAVE_FULL_LANG_DECL_P (t)) + size = sizeof (struct lang_decl); else - pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl)); + size = sizeof (struct lang_decl_flags); - while (i > 0) - pi[--i] = 0; + ld = (struct lang_decl *) ggc_alloc_cleared (size); - DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi; - LANG_DECL_PERMANENT ((struct lang_decl *) pi) - = obstack == &permanent_obstack; - my_friendly_assert (LANG_DECL_PERMANENT ((struct lang_decl *) pi) - == TREE_PERMANENT (t), 234); - DECL_MAIN_VARIANT (t) = t; + DECL_LANG_SPECIFIC (t) = ld; if (current_lang_name == lang_name_cplusplus) - DECL_LANGUAGE (t) = lang_cplusplus; + SET_DECL_LANGUAGE (t, lang_cplusplus); else if (current_lang_name == lang_name_c) - DECL_LANGUAGE (t) = lang_c; + SET_DECL_LANGUAGE (t, lang_c); else if (current_lang_name == lang_name_java) - DECL_LANGUAGE (t) = lang_java; - else my_friendly_abort (64); - -#if 0 /* not yet, should get fixed properly later */ - if (code == TYPE_DECL) - { - tree id; - id = get_identifier (build_overload_name (type, 1, 1)); - DECL_ASSEMBLER_NAME (t) = id; - } + SET_DECL_LANGUAGE (t, lang_java); + else abort (); -#endif #ifdef GATHER_STATISTICS tree_node_counts[(int)lang_decl] += 1; - tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl); + tree_node_sizes[(int)lang_decl] += size; #endif } -tree -build_lang_field_decl (code, name, type) - enum tree_code code; - tree name; - tree type; +void +copy_lang_decl (node) + tree node; { - extern struct obstack *current_obstack, *saveable_obstack; - register tree t = build_decl (code, name, type); - struct obstack *obstack = current_obstack; - register int i = sizeof (struct lang_decl_flags) / sizeof (int); - register int *pi; -#if 0 /* not yet, should get fixed properly later */ - - if (code == TYPE_DECL) - { - tree id; - id = get_identifier (build_overload_name (type, 1, 1)); - DECL_ASSEMBLER_NAME (t) = id; - } -#endif + int size; + struct lang_decl *ld; + + if (! DECL_LANG_SPECIFIC (node)) + return; - if (! TREE_PERMANENT (t)) - obstack = saveable_obstack; + if (!CAN_HAVE_FULL_LANG_DECL_P (node)) + size = sizeof (struct lang_decl_flags); else - my_friendly_assert (obstack == &permanent_obstack, 235); + size = sizeof (struct lang_decl); + ld = (struct lang_decl *) ggc_alloc (size); + memcpy (ld, DECL_LANG_SPECIFIC (node), size); + DECL_LANG_SPECIFIC (node) = ld; + +#ifdef GATHER_STATISTICS + tree_node_counts[(int)lang_decl] += 1; + tree_node_sizes[(int)lang_decl] += size; +#endif +} - pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl_flags)); - while (i > 0) - pi[--i] = 0; +/* Copy DECL, including any language-specific parts. */ - DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi; - return t; +tree +copy_decl (decl) + tree decl; +{ + tree copy; + + copy = copy_node (decl); + copy_lang_decl (copy); + return copy; } -void -copy_lang_decl (node) +/* Replace the shared language-specific parts of NODE with a new copy. */ + +static void +copy_lang_type (node) tree node; { int size; - int *pi; + struct lang_type *lt; - if (! DECL_LANG_SPECIFIC (node)) + if (! TYPE_LANG_SPECIFIC (node)) return; - if (TREE_CODE (node) == FIELD_DECL) - size = sizeof (struct lang_decl_flags); - else - size = sizeof (struct lang_decl); - pi = (int *)obstack_alloc (&permanent_obstack, size); - bcopy ((char *)DECL_LANG_SPECIFIC (node), (char *)pi, size); - DECL_LANG_SPECIFIC (node) = (struct lang_decl *)pi; + size = sizeof (struct lang_type); + lt = (struct lang_type *) ggc_alloc (size); + memcpy (lt, TYPE_LANG_SPECIFIC (node), size); + TYPE_LANG_SPECIFIC (node) = lt; + +#ifdef GATHER_STATISTICS + tree_node_counts[(int)lang_type] += 1; + tree_node_sizes[(int)lang_type] += size; +#endif +} + +/* Copy TYPE, including any language-specific parts. */ + +tree +copy_type (type) + tree type; +{ + tree copy; + + copy = copy_node (type); + copy_lang_type (copy); + return copy; } tree -make_lang_type (code) +cp_make_lang_type (code) enum tree_code code; { - extern struct obstack *current_obstack, *saveable_obstack; register tree t = make_node (code); - /* Set up some flags that give proper default behavior. */ - if (IS_AGGR_TYPE_CODE (code)) + /* Create lang_type structure. */ + if (IS_AGGR_TYPE_CODE (code) + || code == BOUND_TEMPLATE_TEMPLATE_PARM) { - struct obstack *obstack = current_obstack; struct lang_type *pi; - SET_IS_AGGR_TYPE (t, 1); + pi = ((struct lang_type *) + ggc_alloc_cleared (sizeof (struct lang_type))); - if (! TREE_PERMANENT (t)) - obstack = saveable_obstack; - else - my_friendly_assert (obstack == &permanent_obstack, 236); + TYPE_LANG_SPECIFIC (t) = pi; - pi = (struct lang_type *) obstack_alloc (obstack, sizeof (struct lang_type)); - bzero ((char *) pi, (int) sizeof (struct lang_type)); +#ifdef GATHER_STATISTICS + tree_node_counts[(int)lang_type] += 1; + tree_node_sizes[(int)lang_type] += sizeof (struct lang_type); +#endif + } - TYPE_LANG_SPECIFIC (t) = pi; + /* Set up some flags that give proper default behavior. */ + if (IS_AGGR_TYPE_CODE (code)) + { SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown); CLASSTYPE_INTERFACE_ONLY (t) = interface_only; @@ -4687,11 +1628,6 @@ make_lang_type (code) presence of parse errors, the normal was of assuring this might not ever get executed, so we lay it out *immediately*. */ build_pointer_type (t); - -#ifdef GATHER_STATISTICS - tree_node_counts[(int)lang_type] += 1; - tree_node_sizes[(int)lang_type] += sizeof (struct lang_type); -#endif } else /* We use TYPE_ALIAS_SET for the CLASSTYPE_MARKED bits. But, @@ -4699,269 +1635,42 @@ make_lang_type (code) clear it here. */ TYPE_ALIAS_SET (t) = 0; - /* We need to allocate a TYPE_BINFO even for TEMPALTE_TYPE_PARMs + /* We need to allocate a TYPE_BINFO even for TEMPLATE_TYPE_PARMs since they can be virtual base types, and we then need a canonical binfo for them. Ideally, this would be done lazily for all types. */ - if (IS_AGGR_TYPE_CODE (code) || code == TEMPLATE_TYPE_PARM) - TYPE_BINFO (t) = make_binfo (integer_zero_node, t, NULL_TREE, NULL_TREE); + if (IS_AGGR_TYPE_CODE (code) || code == TEMPLATE_TYPE_PARM + || code == BOUND_TEMPLATE_TEMPLATE_PARM + || code == TYPENAME_TYPE) + TYPE_BINFO (t) = make_binfo (size_zero_node, t, NULL_TREE, NULL_TREE); return t; } -void -dump_time_statistics () +tree +make_aggr_type (code) + enum tree_code code; { - register tree prev = 0, decl, next; - int this_time = my_get_run_time (); - TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time)) - += this_time - body_time; - - fprintf (stderr, "\n******\n"); - print_time ("header files (total)", header_time); - print_time ("main file (total)", this_time - body_time); - fprintf (stderr, "ratio = %g : 1\n", - (double)header_time / (double)(this_time - body_time)); - fprintf (stderr, "\n******\n"); - - for (decl = filename_times; decl; decl = next) - { - next = IDENTIFIER_GLOBAL_VALUE (decl); - SET_IDENTIFIER_GLOBAL_VALUE (decl, prev); - prev = decl; - } + tree t = cp_make_lang_type (code); + + if (IS_AGGR_TYPE_CODE (code)) + SET_IS_AGGR_TYPE (t, 1); - for (decl = prev; decl; decl = IDENTIFIER_GLOBAL_VALUE (decl)) - print_time (IDENTIFIER_POINTER (decl), - TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (decl))); + return t; } void -compiler_error VPROTO ((const char *msg, ...)) +compiler_error VPARAMS ((const char *msg, ...)) { -#ifndef ANSI_PROTOTYPES - const char *msg; -#endif char buf[1024]; - va_list ap; - - VA_START (ap, msg); - -#ifndef ANSI_PROTOTYPES - msg = va_arg (ap, const char *); -#endif - - vsprintf (buf, msg, ap); - error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf); -} - -void -yyerror (string) - const char *string; -{ - extern int end_of_file; - char buf[200]; - - strcpy (buf, string); - - /* We can't print string and character constants well - because the token_buffer contains the result of processing escapes. */ - if (end_of_file) - strcat (buf, input_redirected () - ? " at end of saved text" - : " at end of input"); - else if (token_buffer[0] == 0) - strcat (buf, " at null character"); - else if (token_buffer[0] == '"') - strcat (buf, " before string constant"); - else if (token_buffer[0] == '\'') - strcat (buf, " before character constant"); - else if (!ISGRAPH ((unsigned char)token_buffer[0])) - sprintf (buf + strlen (buf), " before character 0%o", - (unsigned char) token_buffer[0]); - else - strcat (buf, " before `%s'"); - - error (buf, token_buffer); -} - -static int -handle_cp_pragma (pname) - const char *pname; -{ - register int token; - - if (! strcmp (pname, "vtable")) - { - extern tree pending_vtables; - - /* More follows: it must be a string constant (class name). */ - token = real_yylex (); - if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST) - { - error ("invalid #pragma vtable"); - return -1; - } - if (write_virtuals != 2) - { - warning ("use `+e2' option to enable #pragma vtable"); - return -1; - } - pending_vtables - = perm_tree_cons (NULL_TREE, - get_identifier (TREE_STRING_POINTER (yylval.ttype)), - pending_vtables); - token = real_yylex (); - if (token != END_OF_LINE) - warning ("trailing characters ignored"); - return 1; - } - else if (! strcmp (pname, "unit")) - { - /* More follows: it must be a string constant (unit name). */ - token = real_yylex (); - if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST) - { - error ("invalid #pragma unit"); - return -1; - } - token = real_yylex (); - if (token != END_OF_LINE) - warning ("trailing characters ignored"); - return 1; - } - else if (! strcmp (pname, "interface")) - { - tree fileinfo - = TIME_IDENTIFIER_FILEINFO (get_time_identifier (input_filename)); - char *main_filename = input_filename; - - main_filename = file_name_nondirectory (main_filename); - - token = real_yylex (); - - if (token != END_OF_LINE) - { - if (token != STRING - || TREE_CODE (yylval.ttype) != STRING_CST) - { - error ("invalid `#pragma interface'"); - return -1; - } - main_filename = TREE_STRING_POINTER (yylval.ttype); - token = real_yylex (); - } - - if (token != END_OF_LINE) - warning ("garbage after `#pragma interface' ignored"); - - write_virtuals = 3; - - if (impl_file_chain == 0) - { - /* If this is zero at this point, then we are - auto-implementing. */ - if (main_input_filename == 0) - main_input_filename = input_filename; - -#ifdef AUTO_IMPLEMENT - filename = file_name_nondirectory (main_input_filename); - fi = get_time_identifier (filename); - fi = TIME_IDENTIFIER_FILEINFO (fi); - TREE_INT_CST_LOW (fi) = 0; - TREE_INT_CST_HIGH (fi) = 1; - /* Get default. */ - impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files)); - impl_file_chain->filename = filename; - impl_file_chain->next = 0; -#endif - } - - interface_only = interface_strcmp (main_filename); -#ifdef MULTIPLE_SYMBOL_SPACES - if (! interface_only) - interface_unknown = 0; -#else /* MULTIPLE_SYMBOL_SPACES */ - interface_unknown = 0; -#endif /* MULTIPLE_SYMBOL_SPACES */ - TREE_INT_CST_LOW (fileinfo) = interface_only; - TREE_INT_CST_HIGH (fileinfo) = interface_unknown; - - return 1; - } - else if (! strcmp (pname, "implementation")) - { - tree fileinfo - = TIME_IDENTIFIER_FILEINFO (get_time_identifier (input_filename)); - char *main_filename = main_input_filename ? main_input_filename : input_filename; - - main_filename = file_name_nondirectory (main_filename); - token = real_yylex (); - if (token != END_OF_LINE) - { - if (token != STRING - || TREE_CODE (yylval.ttype) != STRING_CST) - { - error ("invalid `#pragma implementation'"); - return -1; - } - main_filename = TREE_STRING_POINTER (yylval.ttype); - token = real_yylex (); - } - - if (token != END_OF_LINE) - warning ("garbage after `#pragma implementation' ignored"); - - if (write_virtuals == 3) - { - struct impl_files *ifiles = impl_file_chain; - while (ifiles) - { - if (! strcmp (ifiles->filename, main_filename)) - break; - ifiles = ifiles->next; - } - if (ifiles == 0) - { - ifiles = (struct impl_files*) permalloc (sizeof (struct impl_files)); - ifiles->filename = main_filename; - ifiles->next = impl_file_chain; - impl_file_chain = ifiles; - } - } - else if ((main_input_filename != 0 - && ! strcmp (main_input_filename, input_filename)) - || ! strcmp (input_filename, main_filename)) - { - write_virtuals = 3; - if (impl_file_chain == 0) - { - impl_file_chain = (struct impl_files*) permalloc (sizeof (struct impl_files)); - impl_file_chain->filename = main_filename; - impl_file_chain->next = 0; - } - } - else - error ("`#pragma implementation' can only appear at top-level"); - interface_only = 0; -#if 1 - /* We make this non-zero so that we infer decl linkage - in the impl file only for variables first declared - in the interface file. */ - interface_unknown = 1; -#else - /* We make this zero so that templates in the impl - file will be emitted properly. */ - interface_unknown = 0; -#endif - TREE_INT_CST_LOW (fileinfo) = interface_only; - TREE_INT_CST_HIGH (fileinfo) = interface_unknown; + VA_OPEN (ap, msg); + VA_FIXEDARG (ap, const char *, msg); - return 1; - } + vsprintf (buf, msg, ap); + VA_CLOSE (ap); - return 0; + error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf); } /* Return the type-qualifier corresponding to the identifier given by @@ -4978,48 +1687,6 @@ cp_type_qual_from_rid (rid) else if (rid == ridpointers[(int) RID_RESTRICT]) return TYPE_QUAL_RESTRICT; - my_friendly_abort (0); + abort (); return TYPE_UNQUALIFIED; } - - -#ifdef HANDLE_GENERIC_PRAGMAS - -/* Handle a #pragma directive. TOKEN is the type of the word following - the #pragma directive on the line. Process the entire input line and - return non-zero iff the directive successfully parsed. */ - -/* This function has to be in this file, in order to get at - the token types. */ - -static int -handle_generic_pragma (token) - register int token; -{ - for (;;) - { - switch (token) - { - case IDENTIFIER: - case TYPENAME: - case STRING: - case CONSTANT: - handle_pragma_token (token_buffer, yylval.ttype); - break; - - case LEFT_RIGHT: - handle_pragma_token ("(", NULL_TREE); - handle_pragma_token (")", NULL_TREE); - break; - - case END_OF_LINE: - return handle_pragma_token (NULL_PTR, NULL_TREE); - - default: - handle_pragma_token (token_buffer, NULL_TREE); - } - - token = real_yylex (); - } -} -#endif /* HANDLE_GENERIC_PRAGMAS */ -- cgit v1.1