/* Separate lexical analyzer for GNU C++.
- Copyright (C) 1987, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
#include "config.h"
#include "system.h"
-#include <setjmp.h>
#include "input.h"
#include "tree.h"
#include "lex.h"
extern struct obstack *current_obstack, *saveable_obstack;
extern void yyprint PROTO((FILE *, int, YYSTYPE));
-extern void compiler_error PROTO((char *, HOST_WIDE_INT,
- HOST_WIDE_INT));
-static tree get_time_identifier PROTO((char *));
+static tree get_time_identifier PROTO((const char *));
static int check_newline PROTO((void));
+static int whitespace_cr PROTO((int));
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((char *));
+static int interface_strcmp PROTO((const char *));
static int readescape PROTO((int *));
-static char *extend_token_buffer PROTO((char *));
+static char *extend_token_buffer PROTO((const char *));
static void consume_string PROTO((struct obstack *, int));
-static void set_typedecl_interface_info PROTO((tree, tree));
static void feed_defarg PROTO((tree, tree));
-static int set_vardecl_interface_info PROTO((tree, tree));
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((char *));
+static void cp_pragma_interface PROTO((char *));
+static void cp_pragma_implementation PROTO ((char *));
+static int handle_cp_pragma PROTO((const char *));
#ifdef HANDLE_GENERIC_PRAGMAS
static int handle_generic_pragma PROTO((int));
#endif
#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));
+static void extend_token_buffer_to PROTO((int));
+#ifdef HANDLE_PRAGMA
+static int pragma_getc PROTO((void));
+static void pragma_ungetc PROTO((int));
+#endif
+static int read_line_number PROTO((int *));
/* 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)
- char *x;
+ const char *x;
{
char *tmp = (char *) rindex (x, '/');
if (DIR_SEPARATOR != '/' && ! tmp)
if (tmp)
return (char *) (tmp + 1);
else
- return x;
+ return (char *) x;
}
/* This obstack is needed to hold text. It is not safe to use
extern cpp_reader parse_in;
extern cpp_options parse_options;
extern unsigned char *yy_cur, *yy_lim;
+extern enum cpp_token cpp_token;
#else
FILE *finput;
#endif
int end_of_file;
+int linemode;
+
/* Pending language change.
Positive is push count, negative is pop count. */
int pending_lang_change = 0;
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
/* Holds translations from TREE_CODEs to operator name strings,
i.e., opname_tab[PLUS_EXPR] == "+". */
-char **opname_tab;
-char **assignop_tab;
+const char **opname_tab;
+const char **assignop_tab;
\f
extern int yychar; /* the lookahead symbol */
extern YYSTYPE yylval; /* the semantic value of the */
tree ansi_opname[LAST_CPLUS_TREE_CODE];
tree ansi_assopname[LAST_CPLUS_TREE_CODE];
-char *
+const char *
operator_name_string (name)
tree name;
{
char *token_buffer; /* Pointer to token buffer.
Actual allocated length is maxtoken + 2. */
+static int indent_level; /* Number of { minus number of }. */
+
#include "hash.h"
\f
/* Nonzero tells yylex to ignore \ in string constants. */
-static int ignore_escape_flag = 0;
+static int ignore_escape_flag;
static tree
get_time_identifier (name)
- char *name;
+ const char *name;
{
tree time_identifier;
int len = strlen (name);
time_identifier = get_identifier (buf);
if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE)
{
- push_obstacks_nochange ();
- end_temporary_allocation ();
+ push_permanent_obstack ();
TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0);
TIME_IDENTIFIER_FILEINFO (time_identifier)
= build_int_2 (0, 1);
Used for printing out the tree and error messages. */
#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
-char *cplus_tree_code_name[] = {
+const char *cplus_tree_code_name[] = {
"@@dummy",
#include "cp-tree.def"
};
cpp_reader_init (&parse_in);
parse_in.opts = &parse_options;
cpp_options_init (&parse_options);
+ parse_options.cplusplus = 1;
#endif
/* Default exceptions on. */
/* 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);
}
void
lang_finish ()
{
- extern int errorcount, sorrycount;
if (flag_gnu_xref) GNU_xref_end (errorcount+sorrycount);
}
-char *
+const char *
lang_identify ()
{
return "cplusplus";
}
-void
+static void
init_filename_times ()
{
this_filename_time = get_time_identifier ("<top level>");
literal_codeset = getenv ("LANG");
#endif
-#if USE_CPPLIB
- parse_in.show_column = 1;
- if (! cpp_start_read (&parse_in, filename))
- abort ();
-
- /* 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);
-
-#else
+#if !USE_CPPLIB
/* Open input file. */
if (filename == 0 || !strcmp (filename, "-"))
{
#ifdef IO_BUFFER_SIZE
setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
#endif
+#else /* !USE_CPPLIB */
+ parse_in.show_column = 1;
+ if (! cpp_start_read (&parse_in, filename))
+ abort ();
+
+ if (filename == 0 || !strcmp (filename, "-"))
+ filename = "stdin";
+
+ /* 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);
+ cpp_token = CPP_DIRECTIVE;
+
#endif /* !USE_CPPLIB */
/* Initialize the lookahead machinery. */
set_identifier_size (sizeof (struct lang_identifier));
decl_printable_name = lang_printable_name;
+ init_cplus_unsave ();
init_cplus_expand ();
bcopy (cplus_tree_code_type,
(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 *));
+ opname_tab = (const 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 *));
+ assignop_tab = (const 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 ("<invalid operator>");
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 ("__op");
+ 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,
token_buffer = (char *) xmalloc (maxtoken + 2);
ridpointers[(int) RID_INT] = get_identifier ("int");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]));
ridpointers[(int) RID_BOOL] = get_identifier ("bool");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_BOOL],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_BOOL]));
ridpointers[(int) RID_CHAR] = get_identifier ("char");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CHAR],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]));
ridpointers[(int) RID_VOID] = get_identifier ("void");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOID],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]));
ridpointers[(int) RID_FLOAT] = get_identifier ("float");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FLOAT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_FLOAT]));
ridpointers[(int) RID_DOUBLE] = get_identifier ("double");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_DOUBLE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_DOUBLE]));
ridpointers[(int) RID_SHORT] = get_identifier ("short");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SHORT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_SHORT]));
ridpointers[(int) RID_LONG] = get_identifier ("long");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_LONG],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]));
ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_UNSIGNED],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]));
ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SIGNED],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_SIGNED]));
ridpointers[(int) RID_INLINE] = get_identifier ("inline");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INLINE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_INLINE]));
ridpointers[(int) RID_CONST] = get_identifier ("const");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CONST],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_CONST]));
- ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOLATILE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_VOLATILE]));
ridpointers[(int) RID_RESTRICT] = get_identifier ("__restrict");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_RESTRICT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_RESTRICT]));
+ ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
ridpointers[(int) RID_AUTO] = get_identifier ("auto");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_AUTO],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_AUTO]));
ridpointers[(int) RID_STATIC] = get_identifier ("static");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_STATIC],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]));
ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXTERN],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]));
ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TYPEDEF],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_TYPEDEF]));
ridpointers[(int) RID_REGISTER] = get_identifier ("register");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_REGISTER],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_REGISTER]));
ridpointers[(int) RID_COMPLEX] = get_identifier ("__complex");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_COMPLEX],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_COMPLEX]));
/* C++ extensions. These are probably not correctly named. */
ridpointers[(int) RID_WCHAR] = get_identifier ("__wchar_t");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_WCHAR],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_WCHAR]));
class_type_node = build_int_2 (class_type, 0);
TREE_TYPE (class_type_node) = class_type_node;
ridpointers[(int) RID_CLASS] = class_type_node;
ridpointers[(int) RID_ENUM] = enum_type_node;
ridpointers[(int) RID_VIRTUAL] = get_identifier ("virtual");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VIRTUAL],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_VIRTUAL]));
ridpointers[(int) RID_EXPLICIT] = get_identifier ("explicit");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXPLICIT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_EXPLICIT]));
ridpointers[(int) RID_EXPORT] = get_identifier ("export");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXPORT],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_EXPORT]));
ridpointers[(int) RID_FRIEND] = get_identifier ("friend");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FRIEND],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_FRIEND]));
ridpointers[(int) RID_PUBLIC] = get_identifier ("public");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PUBLIC],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_PUBLIC]));
ridpointers[(int) RID_PRIVATE] = get_identifier ("private");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PRIVATE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_PRIVATE]));
ridpointers[(int) RID_PROTECTED] = get_identifier ("protected");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_PROTECTED],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_PROTECTED]));
ridpointers[(int) RID_TEMPLATE] = get_identifier ("template");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TEMPLATE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_TEMPLATE]));
/* This is for ANSI C++. */
ridpointers[(int) RID_MUTABLE] = get_identifier ("mutable");
- SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_MUTABLE],
- build_tree_list (NULL_TREE, ridpointers[(int) RID_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
opname_tab[(int) CEIL_MOD_EXPR] = "(ceiling %)";
opname_tab[(int) FLOOR_MOD_EXPR] = "(floor %)";
opname_tab[(int) ROUND_MOD_EXPR] = "(round %)";
+ opname_tab[(int) EXACT_DIV_EXPR] = "/";
opname_tab[(int) NEGATE_EXPR] = "-";
opname_tab[(int) MIN_EXPR] = "<?";
opname_tab[(int) MAX_EXPR] = ">?";
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)
{
#if USE_CPPLIB
cpp_finish (&parse_in);
+ errorcount += parse_in.errors;
#else
fclose (finput);
#endif
case TYPENAME:
case TYPESPEC:
case PTYPENAME:
+ case PFUNCNAME:
case IDENTIFIER_DEFN:
case TYPENAME_DEFN:
case PTYPENAME_DEFN:
if (IDENTIFIER_POINTER (t))
fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
break;
+
case AGGR:
if (yylval.ttype == class_type_node)
fprintf (file, " `class'");
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);
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;
}
}
static int
interface_strcmp (s)
- char *s;
+ const char *s;
{
/* Set the interface/implementation bits for this scope. */
struct impl_files *ifiles;
- char *s1;
+ const char *s1;
for (ifiles = impl_file_chain; ifiles; ifiles = ifiles->next)
{
- char *t1 = ifiles->filename;
+ const char *t1 = ifiles->filename;
s1 = s;
if (*s1 != *t1 || *s1 == 0)
}
static void
-set_typedecl_interface_info (prev, vars)
- tree prev ATTRIBUTE_UNUSED, vars;
+cp_pragma_interface (main_filename)
+ char *main_filename;
{
- tree id = get_time_identifier (DECL_SOURCE_FILE (vars));
- tree fileinfo = TIME_IDENTIFIER_FILEINFO (id);
- tree type = TREE_TYPE (vars);
+ tree fileinfo
+ = TIME_IDENTIFIER_FILEINFO (get_time_identifier (input_filename));
+
+ 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;
- CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
- = interface_strcmp (file_name_nondirectory (DECL_SOURCE_FILE (vars)));
+#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;
}
-static int
-set_vardecl_interface_info (prev, vars)
- tree prev, vars;
+static void
+cp_pragma_implementation (main_filename)
+ char *main_filename;
{
- tree type = DECL_CONTEXT (vars);
+ tree fileinfo
+ = TIME_IDENTIFIER_FILEINFO (get_time_identifier (input_filename));
- if (CLASSTYPE_INTERFACE_KNOWN (type))
+ if (impl_file_chain)
{
- if (CLASSTYPE_INTERFACE_ONLY (type))
- set_typedecl_interface_info (prev, TYPE_MAIN_DECL (type));
- else
- CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
- DECL_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type);
- TREE_PUBLIC (vars) = 1;
- return 1;
+ 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;
+ }
}
- return 0;
+ else if ((main_input_filename != 0
+ && ! strcmp (main_input_filename, input_filename))
+ || ! strcmp (main_filename, input_filename))
+ {
+ 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;
}
\f
/* Set up the state required to correctly handle the definition of the
if (context)
push_cp_function_context (context);
- feed_input (pi->buf, pi->len);
- lineno = pi->lineno;
- input_filename = pi->filename;
+ feed_input (pi->buf, pi->len, pi->filename, pi->lineno);
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
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). */
/* 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;
+ hosed, feed back YYEMPTY. */
}
yychar = YYEMPTY;
end_input ();
int matching_char;
{
register int c;
- int starting_lineno = lineno;
+ int starting_lineno;
+
+#if USE_CPPLIB
+ if (cpp_token == CPP_STRING)
+ {
+ /* The C preprocessor will warn about newlines in strings. */
+ obstack_grow (this_obstack, yy_cur, (yy_lim - yy_cur));
+ yy_cur = yy_lim;
+ lineno = parse_in.lineno;
+ return;
+ }
+#endif
+
+ starting_lineno = lineno;
do
{
c = getch ();
while (c != matching_char);
}
-static int nextyychar = YYEMPTY;
-static YYSTYPE nextyylval;
-
struct pending_input {
- int nextchar, yychar, nextyychar, eof;
- YYSTYPE yylval, nextyylval;
+ int yychar, eof;
+ YYSTYPE yylval;
struct obstack token_obstack;
int first_token;
};
{
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;
+ yychar = YYEMPTY;
p->first_token = first_token;
p->token_obstack = token_obstack;
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;
/* Unget a character from the input stream. */
if (yychar == YYEMPTY || rescan == 0)
{
- if (nextchar >= 0)
- put_back (nextchar);
- nextchar = ch;
+ /* If we're putting back a brace, undo the change in indent_level
+ from the first time we saw it. */
+ if (ch == '{')
+ indent_level--;
+ else if (ch == '}')
+ indent_level++;
+
+ put_back (ch);
}
else
{
- my_friendly_assert (nextyychar == YYEMPTY, 232);
- nextyychar = yychar;
- nextyylval = yylval;
yychar = ch;
}
}
int pyychar;
struct obstack *obstackp;
{
- register int c = 0;
+ register int c;
int blev = 1;
int starting_lineno = lineno;
char *starting_filename = input_filename;
int look_for_lbrac = 0;
if (pyychar == '{')
- obstack_1grow (obstackp, '{');
+ {
+ obstack_1grow (obstackp, '{');
+ /* We incremented indent_level in yylex; undo that. */
+ indent_level--;
+ }
else if (pyychar == '=')
look_for_semicolon = 1;
else if (pyychar == ':')
look_for_lbrac = 1;
blev = 0;
}
- else if (pyychar == RETURN)
+ else if (pyychar == RETURN_KEYWORD)
{
obstack_grow (obstackp, "return", 6);
look_for_lbrac = 1;
obstack_1grow (obstackp, '{');
}
- if (nextchar != EOF)
- {
- c = nextchar;
- nextchar = EOF;
- }
- else
- c = getch ();
-
+ c = getch ();
+
while (c != EOF)
{
int this_lineno = lineno;
reinit_parse_for_expr (obstackp)
struct obstack *obstackp;
{
- register int c = 0;
+ register int c;
int starting_lineno = lineno;
char *starting_filename = input_filename;
int len;
int plev = 0;
- if (nextchar != EOF)
- {
- c = nextchar;
- nextchar = EOF;
- }
- else
- c = getch ();
-
+ c = getch ();
+
while (c != EOF)
{
int this_lineno = lineno;
tree f, p;
{
tree d = TREE_PURPOSE (p);
- feed_input (DEFARG_POINTER (d), DEFARG_LENGTH (d));
+ char *file;
+ int line;
if (TREE_CODE (f) == FUNCTION_DECL)
{
- lineno = DECL_SOURCE_LINE (f);
- input_filename = DECL_SOURCE_FILE (f);
+ line = DECL_SOURCE_LINE (f);
+ file = DECL_SOURCE_FILE (f);
+ }
+ else
+ {
+ line = lineno;
+ file = input_filename;
}
+
+ feed_input (DEFARG_POINTER (d), DEFARG_LENGTH (d), file, line);
yychar = DEFARG_MARKER;
yylval.ttype = p;
}
/* 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;
+ hosed, feed back YYEMPTY. */
}
yychar = YYEMPTY;
end_input ();
}
poplevel (0, 0, 0);
- pop_nested_class (1);
+ pop_nested_class ();
}
}
tree type, full_name;
int kind;
{
- extern tree void_list_node;
tree declspecs = NULL_TREE;
tree fn, args = NULL_TREE;
tree argtype;
clear_anon_tags ();
}
\f
+/* Iff C is a carriage return, warn about it - if appropriate -
+ and return nonzero. */
+static int
+whitespace_cr (c)
+ int c;
+{
+ static int newline_warning = 0;
+
+ if (c == '\r')
+ {
+ /* ANSI C says the effects of a carriage return in a source file
+ are undefined. */
+ if (pedantic && !newline_warning)
+ {
+ warning ("carriage return in source file");
+ warning ("(we only warn about the first carriage return)");
+ newline_warning = 1;
+ }
+ return 1;
+ }
+ return 0;
+}
+
/* If C is not whitespace, return C.
Otherwise skip whitespace and return first nonwhite char read. */
{
switch (c)
{
+ /* We don't recognize comments here, because
+ cpp output can include / and * consecutively as operators.
+ Also, there's no need, since cpp removes all comments. */
+
case '\n':
+ if (linemode)
+ {
+ put_back (c);
+ return EOF;
+ }
c = check_newline ();
break;
case ' ':
case '\t':
case '\f':
- case '\r':
case '\v':
case '\b':
- do
+#if USE_CPPLIB
+ /* While processing a # directive we don't get CPP_HSPACE
+ tokens, so we also need to handle whitespace the normal way. */
+ if (cpp_token == CPP_HSPACE)
+ c = yy_get_token ();
+ else
+#endif
c = getch ();
- while (c == ' ' || c == '\t');
+ break;
+
+ case '\r':
+ whitespace_cr (c);
+ c = getch ();
break;
case '\\':
}
}
-
-
/* 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 void
+extend_token_buffer_to (size)
+ int size;
+{
+ do
+ maxtoken = maxtoken * 2 + 10;
+ while (maxtoken < size);
+ token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
+}
+
static char *
extend_token_buffer (p)
- char *p;
+ const char *p;
{
int offset = p - token_buffer;
-
- maxtoken = maxtoken * 2 + 10;
- token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
-
+ extend_token_buffer_to (offset);
return token_buffer + offset;
}
\f
-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;
+ return getch ();
}
static void
pragma_ungetc (arg)
int arg;
{
- yyungetc (arg, 0);
+ put_back (arg);
+}
+#endif
+
+static int
+read_line_number (num)
+ int *num;
+{
+ register int token = real_yylex ();
+
+ if (token == CONSTANT
+ && TREE_CODE (yylval.ttype) == INTEGER_CST)
+ {
+ *num = TREE_INT_CST_LOW (yylval.ttype);
+ return 1;
+ }
+ else
+ {
+ if (token != END_OF_LINE)
+ error ("invalid #-line");
+ return 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. */
+ Otherwise, return the line's first non-whitespace character.
-int linemode;
-
-static int handle_cp_pragma PROTO((char *));
+ Note that in the case of USE_CPPLIB, we get the whole line as one
+ CPP_DIRECTIVE token. */
static int
check_newline ()
{
register int c;
register int token;
- int saw_line = 0;
+ int saw_line;
+ enum { act_none, act_push, act_pop } action;
+ int old_lineno, action_number, l;
+ int entering_c_header;
+ restart:
/* Read first nonwhite char on the line. Do this before incrementing the
line number, in case we're at the end of saved text. */
+#ifdef USE_CPPLIB
+ c = getch ();
+ /* In some cases where we're leaving an include file, we can get multiple
+ CPP_HSPACE tokens in a row, so we need to loop. */
+ while (cpp_token == CPP_HSPACE)
+ c = yy_get_token ();
+#else
do
c = getch ();
while (c == ' ' || c == '\t');
+#endif
lineno++;
if (c != '#')
{
+ /* Sequences of multiple newlines are very common; optimize them. */
+ if (c == '\n')
+ goto restart;
+
/* If not #, return it so caller will use it. */
return c;
}
/* Don't read beyond this line. */
+ saw_line = 0;
linemode = 1;
- /* Read first nonwhite char after the `#'. */
-
- do
- c = getch ();
- while (c == ' ' || c == '\t');
+#if USE_CPPLIB
+ if (cpp_token == CPP_VSPACE)
+ {
+ /* Format is "<space> <line number> <filename> <newline>".
+ Only the line number is interesting, and even that
+ we can get more efficiently than scanning the line. */
+ yy_cur = yy_lim - 1;
+ lineno = parse_in.lineno - 1;
+ goto skipline;
+ }
+#endif
- /* 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'. */
+ token = real_yylex ();
- if (ISALPHA (c))
+ if (token == IDENTIFIER)
{
- if (c == 'p')
+ /* 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'. */
+
+ const char *name = IDENTIFIER_POINTER (yylval.ttype);
+
+ if (!strcmp (name, "pragma"))
{
- 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;
+ token = real_yylex ();
+ if (token != IDENTIFIER
+ || TREE_CODE (yylval.ttype) != IDENTIFIER_NODE)
+ goto skipline;
+
+ /* 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;
#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;
+ /* 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;
+ 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);
- }
-
+ /* 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')
+ else if (!strcmp (name, "define"))
{
- if (getch () == 'e'
- && getch () == 'f'
- && getch () == 'i'
- && getch () == 'n'
- && getch () == 'e'
- && ((c = getch ()) == ' ' || c == '\t'))
- {
- debug_define (lineno, GET_DIRECTIVE_LINE ());
- goto skipline;
- }
+ debug_define (lineno, GET_DIRECTIVE_LINE ());
+ goto skipline;
}
- else if (c == 'u')
+ else if (!strcmp (name, "undef"))
{
- if (getch () == 'n'
- && getch () == 'd'
- && getch () == 'e'
- && getch () == 'f'
- && ((c = getch ()) == ' ' || c == '\t'))
- {
- debug_undef (lineno, GET_DIRECTIVE_LINE ());
- goto skipline;
- }
+ debug_undef (lineno, GET_DIRECTIVE_LINE ());
+ goto skipline;
}
- else if (c == 'l')
+ else if (!strcmp (name, "line"))
{
- if (getch () == 'i'
- && getch () == 'n'
- && getch () == 'e'
- && ((c = getch ()) == ' ' || c == '\t'))
- {
- saw_line = 1;
- goto linenum;
- }
+ saw_line = 1;
+ token = real_yylex ();
+ goto linenum;
}
- else if (c == 'i')
+ else if (!strcmp (name, "ident"))
{
- 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;
- }
+ /* #ident. The pedantic warning is now in cccp.c. */
- if (! flag_no_ident)
- {
-#ifdef ASM_OUTPUT_IDENT
- ASM_OUTPUT_IDENT (asm_out_file,
- TREE_STRING_POINTER (yylval.ttype));
-#endif
- }
+ /* Here we have just seen `#ident '.
+ A string constant should follow. */
- /* Skip the rest of this line. */
+ token = real_yylex ();
+ if (token == END_OF_LINE)
+ goto skipline;
+ if (token != STRING
+ || TREE_CODE (yylval.ttype) != STRING_CST)
+ {
+ error ("invalid #ident");
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'))
+
+ if (! flag_no_ident)
{
- /* Used to test incremental compilation. */
- sorry ("#pragma newworld");
- goto skipline;
+#ifdef ASM_OUTPUT_IDENT
+ ASM_OUTPUT_IDENT (asm_out_file,
+ TREE_STRING_POINTER (yylval.ttype));
+#endif
}
+
+ /* Skip the rest of this line. */
+ goto skipline;
}
- error ("undefined or invalid # directive");
+
+ error ("undefined or invalid # directive `%s'", name);
goto skipline;
}
+ /* If the # is the only nonwhite char on the line,
+ just ignore it. Check the new newline. */
+ if (token == END_OF_LINE)
+ goto skipline;
+
linenum:
/* Here we have either `#line' or `# <nonletter>'.
In either case, it should be a line number; a digit should follow. */
- while (c == ' ' || c == '\t')
- c = getch ();
+ if (token != CONSTANT
+ || TREE_CODE (yylval.ttype) != INTEGER_CST)
+ {
+ error ("invalid #-line");
+ goto skipline;
+ }
- /* If the # is the only nonwhite char on the line,
- just ignore it. Check the new newline. */
- if (c == EOF)
- goto skipline;
+ /* subtract one, because it is the following line that
+ gets the specified number */
- /* Something follows the #; read a token. */
+ l = TREE_INT_CST_LOW (yylval.ttype) - 1;
- put_back (c);
- token = real_yylex ();
+ /* More follows: it must be a string constant (filename).
+ It would be neat to use cpplib to quickly process the string, but
+ (1) we don't have a handy tokenization of the string, and
+ (2) I don't know how well that would work in the presense
+ of filenames that contain wide characters. */
- if (token == CONSTANT
- && TREE_CODE (yylval.ttype) == INTEGER_CST)
+ if (saw_line)
{
- int old_lineno = lineno;
- enum { act_none, act_push, act_pop } action = act_none;
- int entering_system_header = 0;
- int entering_c_header = 0;
+ /* 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;
+ }
- /* subtract one, because it is the following line that
- gets the specified number */
+ /* Read the string constant. */
+ token = real_yylex ();
- 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);
+ ignore_escape_flag = 0;
- /* More follows: it must be a string constant (filename). */
+ if (token == END_OF_LINE)
+ {
+ /* No more: store the line number and check following line. */
+ lineno = l;
+ goto skipline;
+ }
- 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;
- }
+ if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
+ {
+ error ("invalid #line");
+ goto skipline;
+ }
- /* Read the string constant. */
- token = real_yylex ();
+ /* 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;
+ }
- ignore_escape_flag = 0;
+ if (!TREE_PERMANENT (yylval.ttype))
+ {
+ input_filename
+ = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
+ strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
+ }
+ else
+ input_filename = TREE_STRING_POINTER (yylval.ttype);
- if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
+ GNU_xref_file (input_filename);
+
+ if (main_input_filename == 0)
+ {
+ struct impl_files *ifiles = impl_file_chain;
+
+ if (ifiles)
{
- error ("invalid #line");
- goto skipline;
+ while (ifiles->next)
+ ifiles = ifiles->next;
+ ifiles->filename = file_name_nondirectory (input_filename);
}
- /* Changing files again. This means currently collected time
- is charged against header time, and body time starts back
- at 0. */
- if (flag_detailed_statistics)
+ main_input_filename = input_filename;
+ }
+
+ extract_interface_info ();
+
+ old_lineno = lineno;
+ action = act_none;
+ action_number = 0;
+ lineno = l;
+
+ /* Each change of file name
+ reinitializes whether we are now in a system header. */
+ in_system_header = 0;
+ entering_c_header = 0;
+
+ if (!read_line_number (&action_number))
+ {
+ /* Update the name in the top element of input_file_stack. */
+ if (input_file_stack)
+ input_file_stack->name = input_filename;
+ }
+
+ /* `1' after file name means entering new file.
+ `2' after file name means just left a file. */
+
+ if (action_number == 1)
+ {
+ action = act_push;
+ read_line_number (&action_number);
+ }
+ else if (action_number == 2)
+ {
+ action = act_pop;
+ read_line_number (&action_number);
+ }
+ if (action_number == 3)
+ {
+ /* `3' after file name means this is a system header file. */
+ in_system_header = 1;
+ read_line_number (&action_number);
+ }
+ if (action_number == 4)
+ {
+ /* `4' after file name means this is a C header file. */
+ entering_c_header = 1;
+ read_line_number (&action_number);
+ }
+
+ /* Do the actions implied by the preceding numbers. */
+
+ if (action == act_push)
+ {
+ /* Pushing to a new file. */
+ struct file_stack *p
+ = (struct file_stack *) xmalloc (sizeof (struct file_stack));
+ input_file_stack->line = old_lineno;
+ p->next = input_file_stack;
+ p->name = input_filename;
+ p->indent_level = indent_level;
+ input_file_stack = p;
+ input_file_stack_tick++;
+ debug_start_source_file (input_filename);
+ if (c_header_level)
+ ++c_header_level;
+ else if (entering_c_header)
{
- 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;
+ c_header_level = 1;
+ ++pending_lang_change;
}
-
- 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)
+ }
+ else if (action == act_pop)
+ {
+ /* Popping out of a file. */
+ if (input_file_stack->next)
{
- struct impl_files *ifiles = impl_file_chain;
+ struct file_stack *p = input_file_stack;
- if (ifiles)
+ if (c_header_level && --c_header_level == 0)
{
- while (ifiles->next)
- ifiles = ifiles->next;
- ifiles->filename = file_name_nondirectory (input_filename);
+ if (entering_c_header)
+ warning ("badly nested C headers from preprocessor");
+ --pending_lang_change;
}
- main_input_filename = input_filename;
- if (write_virtuals == 3)
- walk_vtables (set_typedecl_interface_info, set_vardecl_interface_info);
+ if (indent_level != p->indent_level)
+ {
+ warning_with_file_and_line
+ (p->name, old_lineno,
+ "This file contains more `%c's than `%c's.",
+ indent_level > p->indent_level ? '{' : '}',
+ indent_level > p->indent_level ? '}' : '{');
+ }
+ 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");
+ }
- extract_interface_info ();
+ /* Now that we've pushed or popped the input stack,
+ update the name in the top element. */
+ if (input_file_stack)
+ input_file_stack->name = input_filename;
- c = get_last_nonwhite_on_line ();
- if (c == EOF)
+ /* skip the rest of this line. */
+ skipline:
+ linemode = 0;
+ end_of_file = 0;
+
+ do
+ c = getch ();
+ while (c != '\n' && c != EOF);
+ return c;
+}
+\f
+#ifdef HANDLE_GENERIC_PRAGMAS
+
+/* Handle a #pragma directive.
+ TOKEN is the token we read after `#pragma'. Processes the entire input
+ line and return non-zero iff the pragma has been 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)
{
- /* Update the name in the top element of input_file_stack. */
- if (input_file_stack)
- input_file_stack->name = input_filename;
+ 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);
}
- else
- {
- put_back (c);
+
+ token = real_yylex ();
+ }
+}
+#endif /* HANDLE_GENERIC_PRAGMAS */
- token = real_yylex ();
+static int
+handle_cp_pragma (pname)
+ const char *pname;
+{
+ register int token;
- /* `1' after file name means entering new file.
- `2' after file name means just left a file. */
+ if (! strcmp (pname, "vtable"))
+ {
+ extern tree pending_vtables;
- 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;
+ /* 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 (action)
- {
- c = get_last_nonwhite_on_line ();
- if (c != EOF)
- {
- put_back (c);
- token = real_yylex ();
- }
- }
- }
+ 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"))
+ {
+ char *main_filename = input_filename;
- /* `3' after file name means this is a system header file. */
+ main_filename = file_name_nondirectory (main_filename);
- if (token == CONSTANT
- && TREE_CODE (yylval.ttype) == INTEGER_CST
- && TREE_INT_CST_LOW (yylval.ttype) == 3)
+ token = real_yylex ();
+
+ if (token != END_OF_LINE)
+ {
+ if (token != STRING
+ || TREE_CODE (yylval.ttype) != STRING_CST)
{
- entering_system_header = 1;
-
- c = get_last_nonwhite_on_line ();
- if (c != EOF)
- {
- put_back (c);
- token = real_yylex ();
- }
+ error ("invalid `#pragma interface'");
+ return -1;
}
+ main_filename = TREE_STRING_POINTER (yylval.ttype);
+ token = real_yylex ();
+ }
- /* `4' after file name means this is a C header file. */
+ if (token != END_OF_LINE)
+ warning ("garbage after `#pragma interface' ignored");
- if (token == CONSTANT
- && TREE_CODE (yylval.ttype) == INTEGER_CST
- && TREE_INT_CST_LOW (yylval.ttype) == 4)
- {
- entering_c_header = 1;
+ cp_pragma_interface (main_filename);
- c = get_last_nonwhite_on_line ();
- if (c != EOF)
- {
- put_back (c);
- token = real_yylex ();
- }
- }
+ return 1;
+ }
+ else if (! strcmp (pname, "implementation"))
+ {
+ char *main_filename = main_input_filename ? main_input_filename : input_filename;
+
+ main_filename = file_name_nondirectory (main_filename);
- /* Do the actions implied by the preceding numbers. */
+ token = real_yylex ();
- if (action == act_push)
+ if (token != END_OF_LINE)
+ {
+ if (token != STRING
+ || TREE_CODE (yylval.ttype) != STRING_CST)
{
- /* 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;
- }
+ error ("invalid `#pragma implementation'");
+ return -1;
}
- else if (action == act_pop)
- {
- /* Popping out of a file. */
- if (input_file_stack->next)
- {
- struct file_stack *p;
+ main_filename = TREE_STRING_POINTER (yylval.ttype);
+ token = real_yylex ();
+ }
- 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;
+ if (token != END_OF_LINE)
+ warning ("garbage after `#pragma implementation' ignored");
- 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;
- }
+ cp_pragma_implementation (main_filename);
- /* If NEXTCHAR is not end of line, we don't care what it is. */
- if (nextchar == EOF)
- c = EOF;
+ return 1;
}
- 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;
+ return 0;
}
-
+\f
void
do_pending_lang_change ()
{
;
else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
|| (count > 1
- && (((unsigned)1 <<
- (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
+ && (((unsigned)1
+ << (TYPE_PRECISION (integer_type_node)
+ - (count - 1) * 4))
<= firstdig)))
pedwarn ("hex escape out of range");
return code;
pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c);
return c;
}
+\f
+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);
+}
+\f
/* 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. */
case TREE_LIST: d = TREE_VALUE (d); continue;
default:
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (d)) == 'd', 980629);
+
+ /* A template parameter is not really global, even though it
+ has no enclosing scope. */
+ if (DECL_TEMPLATE_PARM_P (d))
+ return 0;
+
d = CP_DECL_CONTEXT (d);
return TREE_CODE (d) == NAMESPACE_DECL;
}
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) != FIELD_DECL)
- my_friendly_abort (61);
- else
- {
- cp_error ("invalid use of member `%D'", field);
- id = error_mark_node;
- return 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 && current_class_type && parsing
- && TYPE_BEING_DEFINED (current_class_type)
- && ! IDENTIFIER_CLASS_VALUE (token)
+ 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)
- pushdecl_class_level (id);
-
- if (!id || id == error_mark_node)
- {
- if (id == error_mark_node && current_class_type != NULL_TREE)
- {
- id = lookup_nested_field (token, 1);
- /* In lookup_nested_field(), we marked this so we can gracefully
- leave this whole mess. */
- if (id && id != error_mark_node && TREE_TYPE (id) == error_mark_node)
- return id;
- }
+ maybe_note_name_used_in_class (token, id);
+ if (id == error_mark_node)
+ {
+ /* lookup_name quietly returns error_mark_node if we're parsing,
+ as we don't want to complain about an identifier that ends up
+ being used as a declarator. So we call it again to get the error
+ message. */
+ id = lookup_name (token, 0);
+ return error_mark_node;
+ }
+
+ if (!id)
+ {
if (current_template_parms)
return build_min_nt (LOOKUP_EXPR, token);
else if (IDENTIFIER_OPNAME_P (token))
/* TREE_USED is set in `hack_identifier'. */
if (TREE_CODE (id) == CONST_DECL)
{
+ /* Check access. */
if (IDENTIFIER_CLASS_VALUE (token) == id)
- {
- /* Check access. */
- tree access = compute_access (TYPE_BINFO (current_class_type), id);
- if (access == access_private_node)
- cp_error ("enum `%D' is private", id);
- /* protected is OK, since it's an enum of `this'. */
- }
+ enforce_access (DECL_REAL_CONTEXT(id), id);
if (!processing_template_decl || DECL_TEMPLATE_PARM_P (id))
id = DECL_INITIAL (id);
}
return NULL_TREE;
}
+struct pf_args
+{
+ /* Input */
+ int base;
+ char * p;
+ /* I/O */
+ int c;
+ /* Output */
+ int imag;
+ tree type;
+ int conversion_errno;
+ 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);
+ args->imag = 0;
+ args->conversion_errno = 0;
+ args->type = double_type_node;
+
+ 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;
+ errno = 0;
+ if (args->base == 16)
+ args->value = REAL_VALUE_HTOF (copy, TYPE_MODE (args->type));
+ else
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ args->conversion_errno = errno;
+ /* A diagnostic is required here by some ANSI C testsuites.
+ This is not pedwarn, because 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;
+ errno = 0;
+ if (args->base == 16)
+ args->value = REAL_VALUE_HTOF (copy, TYPE_MODE (args->type));
+ else
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ args->conversion_errno = errno;
+ if (REAL_VALUE_ISINF (args->value) && pedantic)
+ warning ("floating point number exceeds range of `long double'");
+ }
+ else
+ {
+ errno = 0;
+ if (args->base == 16)
+ args->value = REAL_VALUE_HTOF (copy, TYPE_MODE (args->type));
+ else
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ args->conversion_errno = errno;
+ if (REAL_VALUE_ISINF (args->value) && pedantic)
+ warning ("floating point number exceeds range of `double'");
+ }
+}
+
+/* Get the next character, staying within the current token if possible.
+ If we're lexing a token, we don't want to look beyond the end of the
+ token cpplib has prepared for us; otherwise, we end up reading in the
+ next token, which screws up feed_input. So just return a null
+ character. */
+
+inline int
+token_getch ()
+{
+#if USE_CPPLIB
+ if (yy_cur == yy_lim)
+ return '\0';
+#endif
+ return getch ();
+}
+
+inline void
+token_put_back (ch)
+ int ch;
+{
+#if USE_CPPLIB
+ if (ch == '\0')
+ return;
+#endif
+ put_back (ch);
+}
+
+/* Read a single token from the input stream, and assign it lexical
+ semantics.
+
+ Note: We used to do token pasting here, to produce compound tokens like
+ LEFT_RIGHT and EXTERN_LANG_STRING. That's now handled in spew.c, along
+ with symbol table interaction and other context-sensitivity. */
+
int
real_yylex ()
{
register int c;
+ register char *p;
register int value;
int wide_flag = 0;
- int dollar_seen = 0;
- int i;
- if (nextchar >= 0)
- c = nextchar, nextchar = -1;
- else
- c = getch ();
+ c = getch ();
/* Effectively do c = skip_white_space (c)
but do it faster in the usual cases. */
case '\f':
case '\v':
case '\b':
- c = getch ();
+#if USE_CPPLIB
+ if (cpp_token == CPP_HSPACE)
+ c = yy_get_token ();
+ else
+#endif
+ c = getch ();
break;
case '\r':
switch (c)
{
case EOF:
- token_buffer[0] = '\0';
end_of_file = 1;
- if (input_redirected ())
- value = END_OF_SAVED_INPUT;
- else if (linemode)
+ token_buffer[0] = 0;
+ if (linemode)
value = END_OF_LINE;
+ else if (input_redirected ())
+ value = END_OF_SAVED_INPUT;
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':
+#if USE_CPPLIB
+ if (cpp_token == CPP_NAME)
+ goto letter;
+#endif
/* Capital L may start a wide-string or wide-character constant. */
{
- register int c = getch ();
+ register int c = token_getch ();
if (c == '\'')
{
wide_flag = 1;
wide_flag = 1;
goto string_constant;
}
- put_back (c);
+ token_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 'u': case 'v': case 'w': case 'x': case 'y':
case 'z':
case '_':
+ case '$':
+#if USE_CPPLIB
letter:
+ if (cpp_token == CPP_NAME)
+ {
+ /* Note that one character has already been read from
+ yy_cur into token_buffer. Also, cpplib complains about
+ $ in identifiers, so we don't have to. */
+
+ int len = yy_lim - yy_cur + 1;
+ if (len >= maxtoken)
+ extend_token_buffer_to (len + 1);
+ memcpy (token_buffer + 1, yy_cur, len);
+ p = token_buffer + len;
+ yy_cur = yy_lim;
+ }
+ else
+#endif
+ {
+ p = token_buffer;
+ while (ISALNUM (c) || (c == '_') || c == '$')
+ {
+ /* Make sure this char really belongs in an identifier. */
+ 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 = token_getch ();
+ }
+
+ *p = 0;
+ token_put_back (c);
+ }
+
+ value = IDENTIFIER;
+ yylval.itype = 0;
+
+ /* Try to recognize a keyword. Uses minimum-perfect hash function */
+
{
- register char *p;
+ register struct resword *ptr;
- p = token_buffer;
- if (input == 0)
+ if ((ptr = is_reserved_word (token_buffer, p - token_buffer)))
{
- /* 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 (ptr->rid)
{
- if (c == '$')
+ if (ptr->token == VISSPEC)
{
- if (! dollars_in_ident)
- error ("`$' in identifier");
- else if (pedantic)
- pedwarn ("`$' in identifier");
+ 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);
+ }
}
-
- if (p >= token_buffer + maxtoken)
- p = extend_token_buffer (p);
-
- *p++ = c;
- c = getch ();
+ else
+ yylval.ttype = ridpointers[(int) ptr->rid];
}
-
- if (linemode && c == '\n')
+ else switch (ptr->token)
{
- 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 ();
+ case EQCOMPARE:
+ yylval.code = NE_EXPR;
+ token_buffer[0] = '!';
+ token_buffer[1] = '=';
+ token_buffer[2] = 0;
+ break;
- while (ISALNUM (c) || (c == '_') || c == '$')
- {
- if (c == '$')
+ case ASSIGN:
+ if (strcmp ("and_eq", token_buffer) == 0)
{
- if (! dollars_in_ident)
- error ("`$' in identifier");
- else if (pedantic)
- pedwarn ("`$' in identifier");
+ 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;
+ break;
- if (p >= token_buffer + maxtoken)
- p = extend_token_buffer (p);
+ case '&':
+ yylval.code = BIT_AND_EXPR;
+ token_buffer[0] = '&';
+ token_buffer[1] = 0;
+ break;
- *p++ = c;
- c = getch ();
+ case '|':
+ yylval.code = BIT_IOR_EXPR;
+ token_buffer[0] = '|';
+ token_buffer[1] = 0;
+ break;
+
+ case '^':
+ yylval.code = BIT_XOR_EXPR;
+ token_buffer[0] = '^';
+ token_buffer[1] = 0;
+ break;
}
+
+ value = (int) ptr->token;
}
+ }
- *p = 0;
- nextchar = c;
+ /* If we did not find a keyword, look for an identifier
+ (or a typename). */
- value = IDENTIFIER;
- yylval.itype = 0;
+ if (value == IDENTIFIER || value == TYPESPEC)
+ GNU_xref_ref (current_function_decl, token_buffer);
- /* Try to recognize a keyword. Uses minimum-perfect hash function */
+ 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 == '$'
+ && (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 ())
{
- register struct resword *ptr;
+ value = NEW;
+ goto done;
+ }
+ break;
- if ((ptr = is_reserved_word (token_buffer, p - token_buffer)))
+ case '.':
+#if USE_CPPLIB
+ if (yy_cur < yy_lim)
+#endif
+ {
+ /* It's hard to preserve tokenization on '.' because
+ it could be a symbol by itself, or it could be the
+ start of a floating point number and cpp won't tell us. */
+ register int c1 = token_getch ();
+ token_buffer[1] = c1;
+ if (c1 == '*')
{
- 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 == '^')
+ value = DOT_STAR;
+ token_buffer[2] = 0;
+ goto done;
+ }
+ if (c1 == '.')
+ {
+ c1 = token_getch ();
+ if (c1 == '.')
{
- yylval.code = BIT_XOR_EXPR;
- token_buffer[0] = '^';
- token_buffer[1] = 0;
+ token_buffer[2] = c1;
+ token_buffer[3] = 0;
+ value = ELLIPSIS;
+ goto done;
}
-
- value = (int) ptr->token;
+ error ("parse error at `..'");
+ }
+ if (ISDIGIT (c1))
+ {
+ token_put_back (c1);
+ goto number;
}
+ token_put_back (c1);
}
-
- /* 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;
- }
- }
+ value = '.';
+ token_buffer[1] = 0;
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. */
+ /* Optimize for most frequent case. */
{
- register int c1 = getch ();
- if (! ISALNUM (c1) && c1 != '.')
+ register int cond;
+
+#if USE_CPPLIB
+ cond = (yy_cur == yy_lim);
+#else
+ register int c1 = token_getch ();
+ token_put_back (c1);
+ cond = (! ISALNUM (c1) && c1 != '.');
+#endif
+ if (cond)
{
- /* 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;
+ yylval.ttype = (c == '0') ? integer_zero_node : integer_one_node;
value = CONSTANT;
- goto done;
+ break;
}
- put_back (c1);
+ /*FALLTHRU*/
}
- /* fall through... */
- case '2': case '3': case '4':
+ case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- resume_numerical_scan:
+ number:
{
- 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;
+ /* We actually store only HOST_BITS_PER_CHAR bits in each part.
+ The code below which fills the parts array assumes that a host
+ int is at least twice as wide as a host char, and that
+ HOST_BITS_PER_WIDE_INT is an even multiple of HOST_BITS_PER_CHAR.
+ Two HOST_WIDE_INTs is the largest int literal we can store.
+ In order to detect overflow below, the number of parts (TOTAL_PARTS)
+ must be exactly the number of parts needed to hold the bits
+ of two HOST_WIDE_INTs. */
+#define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2)
+ unsigned int parts[TOTAL_PARTS];
+
+ enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS, AFTER_EXPON }
+ floatflag = NOT_FLOAT;
for (count = 0; count < TOTAL_PARTS; count++)
parts[count] = 0;
if (c == '0')
{
- *p++ = (c = getch ());
+ *p++ = (c = token_getch ());
if ((c == 'x') || (c == 'X'))
{
base = 16;
- *p++ = (c = getch ());
+ *p++ = (c = token_getch ());
}
/* Leading 0 forces octal unless the 0 is the only digit. */
else if (c >= '0' && c <= '9')
/* Read all the digits-and-decimal-points. */
while (c == '.'
- || (ISALNUM (c) && (c != 'l') && (c != 'L')
- && (c != 'u') && (c != 'U')
+ || (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 (base == 16 && pedantic)
+ pedwarn ("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)
+ else if (floatflag == AFTER_POINT || floatflag == AFTER_EXPON)
{
error ("malformed floating constant");
floatflag = TOO_MANY_POINTS;
else
floatflag = AFTER_POINT;
- base = 10;
- *p++ = c = getch ();
+ if (base == 8)
+ base = 10;
+ *p++ = c = token_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. */
+ only when it is followed by a digit. */
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;
- }
+ my_friendly_abort (990710);
}
else
{
if (c == 'e' || c == 'E')
{
base = 10;
- floatflag = AFTER_POINT;
+ floatflag = AFTER_EXPON;
break; /* start of exponent */
}
error ("nondigits in number and not hexadecimal");
c = 0;
}
+ else if (base == 16 && (c == 'p' || c == 'P'))
+ {
+ floatflag = AFTER_EXPON;
+ break; /* start of exponent */
+ }
else if (c >= 'a')
{
c = c - 'a' + 10;
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 the highest-order part overflows (gets larger than
+ a host char will hold) then the whole number has
+ overflowed. Record this and truncate the highest-order
+ part. */
+ if (parts[TOTAL_PARTS - 1] >> HOST_BITS_PER_CHAR)
+ {
+ overflow = 1;
+ parts[TOTAL_PARTS - 1] &= (1 << HOST_BITS_PER_CHAR) - 1;
+ }
if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p);
- *p++ = (c = getch ());
+ *p++ = (c = token_getch ());
}
}
+ /* This can happen on input like `int i = 0x;' */
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 */
+ /* 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;
+ tree type;
+ int imag, conversion_errno;
REAL_VALUE_TYPE value;
- jmp_buf handler;
+ struct pf_args args;
/* Read explicit exponent if any, and put it in tokenbuf. */
- if ((c == 'e') || (c == 'E'))
+ if ((base == 10 && ((c == 'e') || (c == 'E')))
+ || (base == 16 && (c == 'p' || c == 'P')))
{
if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p);
*p++ = c;
- c = getch ();
+ c = token_getch ();
if ((c == '+') || (c == '-'))
{
*p++ = c;
- c = getch ();
+ c = token_getch ();
}
+ /* Exponent is decimal, even if string is a hex float. */
if (! ISDIGIT (c))
error ("floating constant exponent has no digits");
- while (ISDIGIT (c))
+ while (ISDIGIT (c))
{
if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p);
*p++ = c;
- c = getch ();
+ c = token_getch ();
}
}
+ if (base == 16 && floatflag != AFTER_EXPON)
+ error ("hexadecimal floating constant has no exponent");
*p = 0;
- errno = 0;
+
+ /* Setup input for parse_float() */
+ args.base = base;
+ args.p = p;
+ args.c = c;
/* Convert string to a double, checking for overflow. */
- if (setjmp (handler))
+ if (do_float_handler (parse_float, (PTR) &args))
{
- error ("floating constant out of range");
- value = dconst0;
+ /* Receive output from parse_float() */
+ value = args.value;
}
else
{
- 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 (p - token_buffer + 1);
- bcopy (token_buffer, copy, p - token_buffer + 1);
-
- set_float_handler (handler);
-
- while (1)
- {
- int lose = 0;
-
- /* Read the suffixes to choose a data type. */
- switch (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 (imag)
- error ("more than one `i' or `j' in numeric constant");
- else if (pedantic)
- pedwarn ("ANSI C++ forbids imaginary numeric constants");
- imag = 1;
- break;
+ /* We got an exception from parse_float() */
+ error ("floating constant out of range");
+ value = dconst0;
+ }
- default:
- lose = 1;
- }
+ /* Receive output from parse_float() */
+ c = args.c;
+ imag = args.imag;
+ type = args.type;
+ conversion_errno = args.conversion_errno;
+
+#ifdef ERANGE
+ /* ERANGE is also reported for underflow,
+ so test the value to distinguish overflow from that. */
+ if (conversion_errno == ERANGE && pedantic
+ && (REAL_VALUES_LESS (dconst1, value)
+ || REAL_VALUES_LESS (value, dconstm1)))
+ warning ("floating point number exceeds range of `double'");
+#endif
- if (lose)
- break;
-
- if (p >= token_buffer + maxtoken - 3)
- p = extend_token_buffer (p);
- *p++ = c;
- *p = 0;
- 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");
-
- type = float_type_node;
- value = REAL_VALUE_ATOF (copy, TYPE_MODE (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 (value) && pedantic)
- warning ("floating point number exceeds range of `float'");
- }
- else if (lflag)
- {
- type = long_double_type_node;
- value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
- if (REAL_VALUE_ISINF (value) && pedantic)
- warning ("floating point number exceeds range of `long double'");
- }
- else
- {
- value = REAL_VALUE_ATOF (copy, TYPE_MODE (type));
- if (REAL_VALUE_ISINF (value) && pedantic)
- warning ("floating point number exceeds range of `double'");
- }
-
- set_float_handler (NULL_PTR);
- }
-#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;
+ /* 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),
+ convert (type, integer_zero_node),
build_real (type, value));
else
yylval.ttype = build_real (type, value);
int spec_long = 0;
int spec_long_long = 0;
int spec_imag = 0;
- int bytes, warn;
+ int warn = 0;
+ int i;
while (1)
{
if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p);
*p++ = c;
- c = getch ();
+ c = token_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])
+ /* If the literal overflowed, pedwarn about it now. */
+ if (overflow)
+ {
warn = 1;
- if (warn)
- pedwarn ("integer constant out of range");
+ pedwarn ("integer constant is too large for this configuration of the compiler - truncated to %d bits", HOST_BITS_PER_WIDE_INT * 2);
+ }
/* 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++)
<< (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
+ 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)
+ 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
+ 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)
+ else if (! spec_long_long
+ && int_fits_type_p (yylval.ttype,
+ long_unsigned_type_node))
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
+ else if (int_fits_type_p (yylval.ttype,
+ long_long_unsigned_type_node))
type = long_long_unsigned_type_node;
+ else if (! spec_unsigned
+ && int_fits_type_p (yylval.ttype,
+ widest_integer_literal_type_node))
+ type = widest_integer_literal_type_node;
+ else
+ type = widest_unsigned_literal_type_node;
- if (!int_fits_type_p (yylval.ttype, type) && !warn)
- pedwarn ("integer constant out of range");
+ if (pedantic && !spec_long_long && !warn
+ && (TYPE_PRECISION (long_integer_type_node)
+ < TYPE_PRECISION (type)))
+ {
+ warn = 1;
+ pedwarn ("integer constant larger than the maximum value of an unsigned long int");
+ }
if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
- warning ("decimal integer constant is so large that it is unsigned");
+ warning ("decimal constant is so large that it is unsigned");
if (spec_imag)
{
<= TYPE_PRECISION (integer_type_node))
yylval.ttype
= build_complex (NULL_TREE, integer_zero_node,
- cp_convert (integer_type_node,
- yylval.ttype));
+ convert (integer_type_node,
+ yylval.ttype));
else
error ("complex integer constant is too wide for `__complex int'");
}
else
TREE_TYPE (yylval.ttype) = type;
+
+
+ /* If it's still an integer (not a complex), and it doesn't
+ fit in the type we choose for it, then pedwarn. */
+
+ if (! warn
+ && TREE_CODE (TREE_TYPE (yylval.ttype)) == INTEGER_TYPE
+ && ! int_fits_type_p (yylval.ttype, TREE_TYPE (yylval.ttype)))
+ pedwarn ("integer constant is larger than the maximum value for its type");
}
- put_back (c);
+ token_put_back (c);
*p = 0;
+ if (ISALNUM (c) || c == '.' || c == '_' || c == '$'
+ || ((c == '-' || c == '+')
+ && (p[-1] == 'e' || p[-1] == 'E')))
+ error ("missing white space after number `%s'", token_buffer);
+
value = CONSTANT; break;
}
int max_chars;
#ifdef MULTIBYTE_CHARS
int longest_char = local_mb_cur_max ();
- (void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
+ local_mbtowc (NULL_PTR, NULL_PTR, 0);
#endif
max_chars = TYPE_PRECISION (integer_type_node) / width;
while (1)
{
tryagain:
- c = getch ();
+ c = token_getch ();
if (c == '\'' || c == EOF)
break;
i);
if (char_len != -1)
break;
- c = getch ();
+ c = token_getch ();
}
if (char_len > 1)
{
/* mbtowc sometimes needs an extra char before accepting */
if (char_len < i)
- put_back (c);
+ token_put_back (c);
if (! wide_flag)
{
/* Merge character into result; ignore excess chars. */
else
{
if (char_len == -1)
- warning ("Ignoring invalid multibyte character");
- if (wide_flag)
- c = wc;
+ {
+ warning ("Ignoring invalid multibyte character");
+ /* Replace all but the first byte. */
+ for (--i; i > 1; --i)
+ token_put_back (token_buffer[i]);
+ wc = token_buffer[1];
+ }
#ifdef MAP_CHARACTER
- else
- c = MAP_CHARACTER (c);
+ c = MAP_CHARACTER (wc);
+#else
+ c = wc;
#endif
}
#else /* ! MULTIBYTE_CHARS */
}
/* Merge character into result; ignore excess chars. */
- num_chars++;
+ num_chars += (width / TYPE_PRECISION (char_type_node));
if (num_chars < max_chars + 1)
{
if (width < HOST_BITS_PER_INT)
= build_int_2 (result | ~(~(unsigned HOST_WIDE_INT) 0
>> (HOST_BITS_PER_WIDE_INT - num_bits)),
-1);
+ /* In C, a character constant has type 'int'; in C++, 'char'. */
if (chars_seen <= 1)
TREE_TYPE (yylval.ttype) = char_type_node;
else
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);
+ local_mbtowc (NULL_PTR, NULL_PTR, 0);
#endif
- c = getch ();
+ c = token_getch ();
p = token_buffer + 1;
- while (c != '"' && c >= 0)
+ while (c != '"' && c != EOF)
{
/* ignore_escape_flag is set for reading the filename in #line. */
if (!ignore_escape_flag && c == '\\')
goto skipnewline;
if (width < HOST_BITS_PER_INT
&& (unsigned) c >= ((unsigned)1 << width))
- warning ("escape sequence out of range for character");
+ pedwarn ("escape sequence out of range for character");
}
else if (c == '\n')
{
char_len = local_mbtowc (& wc, p, i + 1);
if (char_len != -1)
break;
- c = getch ();
+ c = token_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;
+ warning ("Ignoring invalid multibyte character");
+ /* Replace all except the first byte. */
+ token_put_back (c);
+ for (--i; i > 0; --i)
+ token_put_back (p[i]);
+ char_len = 1;
+ }
+ /* mbtowc sometimes needs an extra char before accepting */
+ if (char_len <= i)
+ token_put_back (c);
+ if (! wide_flag)
+ {
+ p += (i + 1);
+ c = token_getch ();
+ continue;
}
+ c = wc;
#endif /* MULTIBYTE_CHARS */
}
for (byte = 0; byte < WCHAR_BYTES; ++byte)
{
int value;
- if (byte >= (int) sizeof(c))
+ if (byte >= (int) sizeof (c))
value = 0;
else
value = (c >> (byte * width)) & bytemask;
}
skipnewline:
- c = getch ();
- if (c == EOF) {
- error ("Unterminated string");
- break;
- }
+ c = token_getch ();
}
/* Terminate the string value, either with a single byte zero
*p++ = 0;
}
+ if (c == EOF)
+ error ("Unterminated string constant");
+
/* We have read the entire constant.
Construct a STRING_CST for the result. */
case '-':
case '&':
case '|':
+ case ':':
case '<':
case '>':
case '*':
yylval.code = GT_EXPR; break;
}
- token_buffer[1] = c1 = getch ();
+ token_buffer[1] = c1 = token_getch ();
token_buffer[2] = 0;
if (c1 == '=')
case '>':
c = RSHIFT;
goto combine;
+ case ':':
+ value = SCOPE;
+ yylval.itype = 1;
+ goto done;
}
- 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 ();
+ c1 = token_getch ();
yylval.code = (c == '<' ? MIN_EXPR : MAX_EXPR);
if (c1 == '=')
{
else
{
value = MIN_MAX;
- nextchar = c1;
+ token_put_back (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;
+ else
+ switch (c)
+ {
+ case '-':
+ if (c1 == '>')
+ {
+ c1 = token_getch ();
+ if (c1 == '*')
+ value = POINTSAT_STAR;
+ else
+ {
+ token_put_back (c1);
+ value = POINTSAT;
+ }
+ goto done;
+ }
+ break;
+
+ /* digraphs */
+ case ':':
+ if (c1 == '>')
+ { value = ']'; goto done; }
+ break;
+ case '<':
+ if (c1 == '%')
+ { value = '{'; indent_level++; goto done; }
+ if (c1 == ':')
+ { value = '['; goto done; }
+ break;
+ case '%':
+ if (c1 == '>')
+ { value = '}'; indent_level--; goto done; }
+ break;
+ }
+
+ token_put_back (c1);
token_buffer[1] = 0;
+ /* Here the C frontend changes < and > to ARITHCOMPARE. We don't
+ do that because of templates. */
+
value = c;
- goto done;
+ break;
}
- case ':':
- c = getch ();
- if (c == ':')
- {
- token_buffer[1] = ':';
- token_buffer[2] = '\0';
- value = SCOPE;
- yylval.itype = 1;
- }
- else if (c == '>')
- {
- value = ']';
- goto done;
- }
- else
- {
- nextchar = c;
- value = ':';
- }
- break;
-
case 0:
/* Don't make yyparse think this is eof. */
value = 1;
break;
- 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 == ')')
- {
- nextchar = -1;
- yylval.ttype = NULL_TREE;
- value = LEFT_RIGHT;
- }
- else value = c;
+ case '{':
+ indent_level++;
+ value = c;
+ break;
+
+ case '}':
+ indent_level--;
+ value = c;
break;
default:
#endif
/* Place to save freed lang_decls which were allocated on the
- permanent_obstack. @@ Not currently used. */
-tree free_lang_decl_chain;
+ permanent_obstack. */
+struct lang_decl *free_lang_decl_chain;
tree
build_lang_decl (code, name, type)
tree type;
{
register tree t = build_decl (code, name, type);
+ retrofit_lang_decl (t);
+ return t;
+}
+
+/* Add DECL_LANG_SPECIFIC info to T. Called from build_lang_decl
+ and pushdecl (for functions generated by the backend). */
+
+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;
+
+ my_friendly_assert (CAN_HAVE_FULL_LANG_DECL_P (t), 19990816);
if (! TREE_PERMANENT (t))
obstack = saveable_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);
+ ld = free_lang_decl_chain;
+ free_lang_decl_chain = free_lang_decl_chain->u.next;
}
else
- pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
+ ld = ((struct lang_decl *)
+ obstack_alloc (obstack, sizeof (struct lang_decl)));
- while (i > 0)
- pi[--i] = 0;
+ bzero (ld, sizeof (struct lang_decl));
- 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_LANG_SPECIFIC (t) = ld;
+ LANG_DECL_PERMANENT (ld) = obstack == &permanent_obstack;
+ my_friendly_assert (LANG_DECL_PERMANENT (ld) == TREE_PERMANENT (t), 234);
DECL_MAIN_VARIANT (t) = t;
if (current_lang_name == lang_name_cplusplus)
DECL_LANGUAGE (t) = lang_cplusplus;
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;
- }
-
-#endif
#ifdef GATHER_STATISTICS
tree_node_counts[(int)lang_decl] += 1;
tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl);
#endif
-
- return t;
}
+/* Like build_decl, except that a new lang_decl_flags structure is
+ placed in DECL_LANG_SPECIFIC. */
+
tree
build_lang_field_decl (code, name, type)
enum tree_code code;
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
if (! TREE_PERMANENT (t))
obstack = saveable_obstack;
else
my_friendly_assert (obstack == &permanent_obstack, 235);
- pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl_flags));
- while (i > 0)
- pi[--i] = 0;
+ my_friendly_assert (!CAN_HAVE_FULL_LANG_DECL_P (t), 19990816);
- DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
+ DECL_LANG_SPECIFIC (t)
+ = ((struct lang_decl *)
+ obstack_alloc (obstack, sizeof (struct lang_decl_flags)));
+ bzero (DECL_LANG_SPECIFIC (t), sizeof (struct lang_decl_flags));
return t;
}
if (! DECL_LANG_SPECIFIC (node))
return;
- if (TREE_CODE (node) == FIELD_DECL)
+ if (!CAN_HAVE_FULL_LANG_DECL_P (node))
size = sizeof (struct lang_decl_flags);
else
size = sizeof (struct lang_decl);
bzero ((char *) pi, (int) sizeof (struct lang_type));
TYPE_LANG_SPECIFIC (t) = pi;
- CLASSTYPE_AS_LIST (t) = build_expr_list (NULL_TREE, t);
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
- TYPE_BINFO (t) = make_binfo (integer_zero_node, t, NULL_TREE, NULL_TREE);
- CLASSTYPE_BINFO_AS_LIST (t)
- = build_tree_list (NULL_TREE, TYPE_BINFO (t));
/* Make sure this is laid out, for ease of use later. In the
presence of parse errors, the normal was of assuring this
clear it here. */
TYPE_ALIAS_SET (t) = 0;
+ /* We need to allocate a TYPE_BINFO even for TEMPALTE_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);
+
return t;
}
}
void
-compiler_error (s, v, v2)
- char *s;
- HOST_WIDE_INT v, v2; /* @@also used as pointer */
-{
- char buf[1024];
- sprintf (buf, s, v, v2);
- error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
-}
-\f
-void
-yyerror (string)
- char *string;
+compiler_error VPROTO ((const char *msg, ...))
{
- 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 (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);
-}
-\f
-static int
-handle_cp_pragma (pname)
- 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");
-
-#ifndef MULTIPLE_SYMBOL_SPACES
- 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;
+#ifndef ANSI_PROTOTYPES
+ const char *msg;
#endif
- }
-
- interface_only = interface_strcmp (main_filename);
- interface_unknown = 0;
- TREE_INT_CST_LOW (fileinfo) = interface_only;
- TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
-#endif /* MULTIPLE_SYMBOL_SPACES */
-
- 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");
-
-#ifndef MULTIPLE_SYMBOL_SPACES
- 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;
+ char buf[1024];
+ va_list ap;
+
+ VA_START (ap, msg);
+
+#ifndef ANSI_PROTOTYPES
+ msg = va_arg (ap, const char *);
#endif
- TREE_INT_CST_LOW (fileinfo) = interface_only;
- TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
-#endif /* MULTIPLE_SYMBOL_SPACES */
- return 1;
- }
-
- return 0;
+ vsprintf (buf, msg, ap);
+ error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
}
-
+\f
/* Return the type-qualifier corresponding to the identifier given by
RID. */
my_friendly_abort (0);
return TYPE_UNQUALIFIED;
}
-
-\f
-#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);
- }
-
- token = real_yylex ();
- }
-}
-#endif /* HANDLE_GENERIC_PRAGMAS */