Commit 1ceb5ff3 by Jason Merrill Committed by Jason Merrill

lex.c: Sync with C frontend.

	* lex.c: Sync with C frontend.
	(whitespace_cr): New fn.
	(skip_white_space): Use it.
	(init_parse): Reorder.
	(yyprint): Support CONSTANT.
	(pragma_getc, pragma_ungetc): Bring back.
	(read_line_number): Change in_system_header directly.
	(handle_generic_pragma, handle_cp_pragma, yyerror): Move up in file.
	(parse_float): Update to C version.
	(yylex): Handle '$' under the letter case.
	Remove looking_for_typename handling.
	Support hex floating point constants.
	Follow C's lead for choosing type of integer constants.
	Rearrange stuff to match C frontend.
	(yyungetc, reinit_parse_for_block, yylex): Support indent_level.
	* spew.c (yylex): Clear looking_for_typename if we see a TYPESPEC.

From-SVN: r28230
parent b0385db8
1999-07-23 Jason Merrill <jason@yorick.cygnus.com>
* lex.c: Sync with C frontend.
(whitespace_cr): New fn.
(skip_white_space): Use it.
(init_parse): Reorder.
(yyprint): Support CONSTANT.
(pragma_getc, pragma_ungetc): Bring back.
(read_line_number): Change in_system_header directly.
(handle_generic_pragma, handle_cp_pragma, yyerror): Move up in file.
(parse_float): Update to C version.
(yylex): Handle '$' under the letter case.
Remove looking_for_typename handling.
Support hex floating point constants.
Follow C's lead for choosing type of integer constants.
Rearrange stuff to match C frontend.
(yyungetc, reinit_parse_for_block, yylex): Support indent_level.
* spew.c (yylex): Clear looking_for_typename if we see a TYPESPEC.
1999-07-23 Mark Mitchell <mark@codesourcery.com> 1999-07-23 Mark Mitchell <mark@codesourcery.com>
* call.c (reference_binding): Tweak. * call.c (reference_binding): Tweak.
......
...@@ -57,6 +57,7 @@ extern void yyprint PROTO((FILE *, int, YYSTYPE)); ...@@ -57,6 +57,7 @@ extern void yyprint PROTO((FILE *, int, YYSTYPE));
static tree get_time_identifier PROTO((const char *)); static tree get_time_identifier PROTO((const char *));
static int check_newline PROTO((void)); static int check_newline PROTO((void));
static int whitespace_cr PROTO((int));
static int skip_white_space PROTO((int)); static int skip_white_space PROTO((int));
static void finish_defarg PROTO((void)); static void finish_defarg PROTO((void));
static int my_get_run_time PROTO((void)); static int my_get_run_time PROTO((void));
...@@ -303,13 +304,13 @@ static int maxtoken; /* Current nominal length of token buffer. */ ...@@ -303,13 +304,13 @@ static int maxtoken; /* Current nominal length of token buffer. */
char *token_buffer; /* Pointer to token buffer. char *token_buffer; /* Pointer to token buffer.
Actual allocated length is maxtoken + 2. */ Actual allocated length is maxtoken + 2. */
static int indent_level = 0; /* Number of { minus number of }. */ static int indent_level; /* Number of { minus number of }. */
#include "hash.h" #include "hash.h"
/* Nonzero tells yylex to ignore \ in string constants. */ /* Nonzero tells yylex to ignore \ in string constants. */
static int ignore_escape_flag = 0; static int ignore_escape_flag;
static tree static tree
get_time_identifier (name) get_time_identifier (name)
...@@ -481,18 +482,7 @@ init_parse (filename) ...@@ -481,18 +482,7 @@ init_parse (filename)
literal_codeset = getenv ("LANG"); literal_codeset = getenv ("LANG");
#endif #endif
#if USE_CPPLIB #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);
cpp_token = CPP_DIRECTIVE;
#else
/* Open input file. */ /* Open input file. */
if (filename == 0 || !strcmp (filename, "-")) if (filename == 0 || !strcmp (filename, "-"))
{ {
...@@ -507,6 +497,20 @@ init_parse (filename) ...@@ -507,6 +497,20 @@ init_parse (filename)
#ifdef IO_BUFFER_SIZE #ifdef IO_BUFFER_SIZE
setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE); setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE), _IOFBF, IO_BUFFER_SIZE);
#endif #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 */ #endif /* !USE_CPPLIB */
/* Initialize the lookahead machinery. */ /* Initialize the lookahead machinery. */
...@@ -686,8 +690,8 @@ init_parse (filename) ...@@ -686,8 +690,8 @@ init_parse (filename)
ridpointers[(int) RID_SIGNED] = get_identifier ("signed"); ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
ridpointers[(int) RID_INLINE] = get_identifier ("inline"); ridpointers[(int) RID_INLINE] = get_identifier ("inline");
ridpointers[(int) RID_CONST] = get_identifier ("const"); ridpointers[(int) RID_CONST] = get_identifier ("const");
ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
ridpointers[(int) RID_RESTRICT] = get_identifier ("__restrict"); ridpointers[(int) RID_RESTRICT] = get_identifier ("__restrict");
ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
ridpointers[(int) RID_AUTO] = get_identifier ("auto"); ridpointers[(int) RID_AUTO] = get_identifier ("auto");
ridpointers[(int) RID_STATIC] = get_identifier ("static"); ridpointers[(int) RID_STATIC] = get_identifier ("static");
ridpointers[(int) RID_EXTERN] = get_identifier ("extern"); ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
...@@ -921,6 +925,7 @@ yyprint (file, yychar, yylval) ...@@ -921,6 +925,7 @@ yyprint (file, yychar, yylval)
if (IDENTIFIER_POINTER (t)) if (IDENTIFIER_POINTER (t))
fprintf (file, " `%s'", IDENTIFIER_POINTER (t)); fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
break; break;
case AGGR: case AGGR:
if (yylval.ttype == class_type_node) if (yylval.ttype == class_type_node)
fprintf (file, " `class'"); fprintf (file, " `class'");
...@@ -935,6 +940,30 @@ yyprint (file, yychar, yylval) ...@@ -935,6 +940,30 @@ yyprint (file, yychar, yylval)
else else
my_friendly_abort (80); my_friendly_abort (80);
break; 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;
} }
} }
...@@ -1435,6 +1464,13 @@ yyungetc (ch, rescan) ...@@ -1435,6 +1464,13 @@ yyungetc (ch, rescan)
/* Unget a character from the input stream. */ /* Unget a character from the input stream. */
if (yychar == YYEMPTY || rescan == 0) if (yychar == YYEMPTY || rescan == 0)
{ {
/* 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); put_back (ch);
} }
else else
...@@ -1530,7 +1566,11 @@ reinit_parse_for_block (pyychar, obstackp) ...@@ -1530,7 +1566,11 @@ reinit_parse_for_block (pyychar, obstackp)
int look_for_lbrac = 0; int look_for_lbrac = 0;
if (pyychar == '{') if (pyychar == '{')
obstack_1grow (obstackp, '{'); {
obstack_1grow (obstackp, '{');
/* We incremented indent_level in yylex; undo that. */
indent_level--;
}
else if (pyychar == '=') else if (pyychar == '=')
look_for_semicolon = 1; look_for_semicolon = 1;
else if (pyychar == ':') else if (pyychar == ':')
...@@ -2117,6 +2157,29 @@ note_list_got_semicolon (declspecs) ...@@ -2117,6 +2157,29 @@ note_list_got_semicolon (declspecs)
clear_anon_tags (); clear_anon_tags ();
} }
/* 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. /* If C is not whitespace, return C.
Otherwise skip whitespace and return first nonwhite char read. */ Otherwise skip whitespace and return first nonwhite char read. */
...@@ -2128,6 +2191,10 @@ skip_white_space (c) ...@@ -2128,6 +2191,10 @@ skip_white_space (c)
{ {
switch (c) 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': case '\n':
if (linemode) if (linemode)
{ {
...@@ -2140,7 +2207,6 @@ skip_white_space (c) ...@@ -2140,7 +2207,6 @@ skip_white_space (c)
case ' ': case ' ':
case '\t': case '\t':
case '\f': case '\f':
case '\r':
case '\v': case '\v':
case '\b': case '\b':
#if USE_CPPLIB #if USE_CPPLIB
...@@ -2153,6 +2219,11 @@ skip_white_space (c) ...@@ -2153,6 +2219,11 @@ skip_white_space (c)
c = getch (); c = getch ();
break; break;
case '\r':
whitespace_cr (c);
c = getch ();
break;
case '\\': case '\\':
c = getch (); c = getch ();
if (c == '\n') if (c == '\n')
...@@ -2192,6 +2263,22 @@ extend_token_buffer (p) ...@@ -2192,6 +2263,22 @@ extend_token_buffer (p)
return token_buffer + offset; return token_buffer + offset;
} }
#if defined HANDLE_PRAGMA
/* Local versions of these macros, that can be passed as function pointers. */
static int
pragma_getc ()
{
return getch ();
}
static void
pragma_ungetc (arg)
int arg;
{
put_back (arg);
}
#endif
static int static int
read_line_number (num) read_line_number (num)
int *num; int *num;
...@@ -2228,7 +2315,6 @@ check_newline () ...@@ -2228,7 +2315,6 @@ check_newline ()
int saw_line; int saw_line;
enum { act_none, act_push, act_pop } action; enum { act_none, act_push, act_pop } action;
int old_lineno, action_number, l; int old_lineno, action_number, l;
int entering_system_header;
int entering_c_header; int entering_c_header;
restart: restart:
...@@ -2288,16 +2374,14 @@ check_newline () ...@@ -2288,16 +2374,14 @@ check_newline ()
if (!strcmp (name, "pragma")) if (!strcmp (name, "pragma"))
{ {
token = real_yylex (); token = real_yylex ();
if (token == IDENTIFIER if (token != IDENTIFIER
&& TREE_CODE (yylval.ttype) == IDENTIFIER_NODE) || 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 /* If this is 1, we handled it; if it's -1, it was one we
0 was it not handled. */ wanted but had something wrong with it. Only if it's
if (handle_cp_pragma (IDENTIFIER_POINTER (yylval.ttype))) 0 was it not handled. */
goto skipline; if (handle_cp_pragma (IDENTIFIER_POINTER (yylval.ttype)))
}
else if (token == END_OF_LINE)
goto skipline; goto skipline;
#ifdef HANDLE_PRAGMA #ifdef HANDLE_PRAGMA
...@@ -2305,7 +2389,7 @@ check_newline () ...@@ -2305,7 +2389,7 @@ check_newline ()
(if both are defined), in order to give the back (if both are defined), in order to give the back
end a chance to override the interpretation of end a chance to override the interpretation of
SYSV style pragmas. */ SYSV style pragmas. */
if (HANDLE_PRAGMA (getch, put_back, if (HANDLE_PRAGMA (pragma_getc, pragma_ungetc,
IDENTIFIER_POINTER (yylval.ttype))) IDENTIFIER_POINTER (yylval.ttype)))
goto skipline; goto skipline;
#endif /* HANDLE_PRAGMA */ #endif /* HANDLE_PRAGMA */
...@@ -2466,12 +2550,15 @@ linenum: ...@@ -2466,12 +2550,15 @@ linenum:
extract_interface_info (); extract_interface_info ();
old_lineno = lineno; old_lineno = lineno;
entering_system_header = 0;
entering_c_header = 0;
action = act_none; action = act_none;
action_number = 0; action_number = 0;
lineno = l; 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)) if (!read_line_number (&action_number))
{ {
/* Update the name in the top element of input_file_stack. */ /* Update the name in the top element of input_file_stack. */
...@@ -2495,7 +2582,7 @@ linenum: ...@@ -2495,7 +2582,7 @@ linenum:
if (action_number == 3) if (action_number == 3)
{ {
/* `3' after file name means this is a system header file. */ /* `3' after file name means this is a system header file. */
entering_system_header = 1; in_system_header = 1;
read_line_number (&action_number); read_line_number (&action_number);
} }
if (action_number == 4) if (action_number == 4)
...@@ -2510,9 +2597,8 @@ linenum: ...@@ -2510,9 +2597,8 @@ linenum:
if (action == act_push) if (action == act_push)
{ {
/* Pushing to a new file. */ /* Pushing to a new file. */
struct file_stack *p; struct file_stack *p
= (struct file_stack *) xmalloc (sizeof (struct file_stack));
p = (struct file_stack *) xmalloc (sizeof (struct file_stack));
input_file_stack->line = old_lineno; input_file_stack->line = old_lineno;
p->next = input_file_stack; p->next = input_file_stack;
p->name = input_filename; p->name = input_filename;
...@@ -2520,7 +2606,6 @@ linenum: ...@@ -2520,7 +2606,6 @@ linenum:
input_file_stack = p; input_file_stack = p;
input_file_stack_tick++; input_file_stack_tick++;
debug_start_source_file (input_filename); debug_start_source_file (input_filename);
in_system_header = entering_system_header;
if (c_header_level) if (c_header_level)
++c_header_level; ++c_header_level;
else if (entering_c_header) else if (entering_c_header)
...@@ -2534,7 +2619,7 @@ linenum: ...@@ -2534,7 +2619,7 @@ linenum:
/* Popping out of a file. */ /* Popping out of a file. */
if (input_file_stack->next) if (input_file_stack->next)
{ {
struct file_stack *p; struct file_stack *p = input_file_stack;
if (c_header_level && --c_header_level == 0) if (c_header_level && --c_header_level == 0)
{ {
...@@ -2542,9 +2627,7 @@ linenum: ...@@ -2542,9 +2627,7 @@ linenum:
warning ("badly nested C headers from preprocessor"); warning ("badly nested C headers from preprocessor");
--pending_lang_change; --pending_lang_change;
} }
in_system_header = entering_system_header;
p = input_file_stack;
if (indent_level != p->indent_level) if (indent_level != p->indent_level)
{ {
warning_with_file_and_line warning_with_file_and_line
...@@ -2561,18 +2644,163 @@ linenum: ...@@ -2561,18 +2644,163 @@ linenum:
else else
error ("#-lines for entering and leaving files don't match"); error ("#-lines for entering and leaving files don't match");
} }
else
in_system_header = entering_system_header; /* 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;
/* skip the rest of this line. */ /* skip the rest of this line. */
skipline: skipline:
linemode = 0; linemode = 0;
end_of_file = 0; end_of_file = 0;
while ((c = getch ()) != EOF && c != '\n'); do
c = getch ();
while (c != '\n' && c != EOF);
return c; return c;
} }
#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)
{
case IDENTIFIER:
case TYPENAME:
case STRING:
case CONSTANT:
handle_pragma_token (token_buffer, yylval.ttype);
break;
case LEFT_RIGHT:
handle_pragma_token ("(", NULL_TREE);
handle_pragma_token (")", NULL_TREE);
break;
case END_OF_LINE:
return handle_pragma_token (NULL_PTR, NULL_TREE);
default:
handle_pragma_token (token_buffer, NULL_TREE);
}
token = real_yylex ();
}
}
#endif /* HANDLE_GENERIC_PRAGMAS */
static int
handle_cp_pragma (pname)
const char *pname;
{
register int token;
if (! strcmp (pname, "vtable"))
{
extern tree pending_vtables;
/* More follows: it must be a string constant (class name). */
token = real_yylex ();
if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
{
error ("invalid #pragma vtable");
return -1;
}
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;
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");
cp_pragma_interface (main_filename);
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);
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");
cp_pragma_implementation (main_filename);
return 1;
}
return 0;
}
void void
do_pending_lang_change () do_pending_lang_change ()
{ {
...@@ -2633,8 +2861,9 @@ readescape (ignore_ptr) ...@@ -2633,8 +2861,9 @@ readescape (ignore_ptr)
; ;
else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node) else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
|| (count > 1 || (count > 1
&& (((unsigned)1 << && (((unsigned)1
(TYPE_PRECISION (integer_type_node) - (count - 1) * 4)) << (TYPE_PRECISION (integer_type_node)
- (count - 1) * 4))
<= firstdig))) <= firstdig)))
pedwarn ("hex escape out of range"); pedwarn ("hex escape out of range");
return code; return code;
...@@ -2705,7 +2934,37 @@ readescape (ignore_ptr) ...@@ -2705,7 +2934,37 @@ readescape (ignore_ptr)
pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c); pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c);
return c; return c;
} }
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);
}
/* Value is 1 (or 2) if we should try to make the next identifier look like /* 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). 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. */ Value is 0 if we treat this name in a default fashion. */
...@@ -3097,15 +3356,17 @@ identifier_typedecl_value (node) ...@@ -3097,15 +3356,17 @@ identifier_typedecl_value (node)
return NULL_TREE; return NULL_TREE;
} }
struct pf_args struct pf_args
{ {
/* Input */ /* Input */
int base;
char * p;
/* I/O */ /* I/O */
char *p;
int c; int c;
/* Output */
int imag; int imag;
tree type; tree type;
/* Output */ int conversion_errno;
REAL_VALUE_TYPE value; REAL_VALUE_TYPE value;
}; };
...@@ -3120,11 +3381,14 @@ parse_float (data) ...@@ -3120,11 +3381,14 @@ parse_float (data)
REAL_VALUE_ATOF may not work any more. */ REAL_VALUE_ATOF may not work any more. */
char *copy = (char *) alloca (args->p - token_buffer + 1); char *copy = (char *) alloca (args->p - token_buffer + 1);
bcopy (token_buffer, copy, 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) while (1)
{ {
int lose = 0; int lose = 0;
/* Read the suffixes to choose a data type. */ /* Read the suffixes to choose a data type. */
switch (args->c) switch (args->c)
{ {
...@@ -3133,13 +3397,13 @@ parse_float (data) ...@@ -3133,13 +3397,13 @@ parse_float (data)
error ("more than one `f' in numeric constant"); error ("more than one `f' in numeric constant");
fflag = 1; fflag = 1;
break; break;
case 'l': case 'L': case 'l': case 'L':
if (lflag) if (lflag)
error ("more than one `l' in numeric constant"); error ("more than one `l' in numeric constant");
lflag = 1; lflag = 1;
break; break;
case 'i': case 'I': case 'i': case 'I':
if (args->imag) if (args->imag)
error ("more than one `i' or `j' in numeric constant"); error ("more than one `i' or `j' in numeric constant");
...@@ -3147,34 +3411,39 @@ parse_float (data) ...@@ -3147,34 +3411,39 @@ parse_float (data)
pedwarn ("ANSI C++ forbids imaginary numeric constants"); pedwarn ("ANSI C++ forbids imaginary numeric constants");
args->imag = 1; args->imag = 1;
break; break;
default: default:
lose = 1; lose = 1;
} }
if (lose) if (lose)
break; break;
if (args->p >= token_buffer + maxtoken - 3) if (args->p >= token_buffer + maxtoken - 3)
args->p = extend_token_buffer (args->p); args->p = extend_token_buffer (args->p);
*(args->p++) = args->c; *(args->p++) = args->c;
*(args->p) = 0; *(args->p) = 0;
args->c = getch (); args->c = getch ();
} }
/* The second argument, machine_mode, of REAL_VALUE_ATOF /* The second argument, machine_mode, of REAL_VALUE_ATOF
tells the desired precision of the binary result tells the desired precision of the binary result
of decimal-to-binary conversion. */ of decimal-to-binary conversion. */
if (fflag) if (fflag)
{ {
if (lflag) if (lflag)
error ("both `f' and `l' in floating constant"); error ("both `f' and `l' in floating constant");
args->type = float_type_node; args->type = float_type_node;
args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type)); 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. /* A diagnostic is required here by some ANSI C testsuites.
This is not pedwarn, become some people don't want This is not pedwarn, because some people don't want
an error for this. */ an error for this. */
if (REAL_VALUE_ISINF (args->value) && pedantic) if (REAL_VALUE_ISINF (args->value) && pedantic)
warning ("floating point number exceeds range of `float'"); warning ("floating point number exceeds range of `float'");
...@@ -3182,13 +3451,23 @@ parse_float (data) ...@@ -3182,13 +3451,23 @@ parse_float (data)
else if (lflag) else if (lflag)
{ {
args->type = long_double_type_node; args->type = long_double_type_node;
args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type)); 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) if (REAL_VALUE_ISINF (args->value) && pedantic)
warning ("floating point number exceeds range of `long double'"); warning ("floating point number exceeds range of `long double'");
} }
else else
{ {
args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type)); 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) if (REAL_VALUE_ISINF (args->value) && pedantic)
warning ("floating point number exceeds range of `double'"); warning ("floating point number exceeds range of `double'");
} }
...@@ -3232,10 +3511,9 @@ int ...@@ -3232,10 +3511,9 @@ int
real_yylex () real_yylex ()
{ {
register int c; register int c;
register char *p;
register int value; register int value;
int wide_flag = 0; int wide_flag = 0;
int dollar_seen = 0;
int i;
c = getch (); c = getch ();
...@@ -3277,8 +3555,8 @@ real_yylex () ...@@ -3277,8 +3555,8 @@ real_yylex ()
switch (c) switch (c)
{ {
case EOF: case EOF:
token_buffer[0] = '\0';
end_of_file = 1; end_of_file = 1;
token_buffer[0] = 0;
if (input_redirected ()) if (input_redirected ())
value = END_OF_SAVED_INPUT; value = END_OF_SAVED_INPUT;
else if (linemode) else if (linemode)
...@@ -3287,14 +3565,6 @@ real_yylex () ...@@ -3287,14 +3565,6 @@ real_yylex ()
value = ENDFILE; value = ENDFILE;
break; break;
case '$':
if (! dollars_in_ident)
error ("`$' in identifier");
else if (pedantic)
pedwarn ("`$' in identifier");
dollar_seen = 1;
goto letter;
case 'L': case 'L':
#if USE_CPPLIB #if USE_CPPLIB
if (cpp_token == CPP_NAME) if (cpp_token == CPP_NAME)
...@@ -3315,7 +3585,7 @@ real_yylex () ...@@ -3315,7 +3585,7 @@ real_yylex ()
} }
token_put_back (c); token_put_back (c);
} }
case 'A': case 'B': case 'C': case 'D': case 'E': case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J': case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'M': case 'N': case 'O': case 'K': case 'M': case 'N': case 'O':
...@@ -3329,181 +3599,164 @@ real_yylex () ...@@ -3329,181 +3599,164 @@ real_yylex ()
case 'u': case 'v': case 'w': case 'x': case 'y': case 'u': case 'v': case 'w': case 'x': case 'y':
case 'z': case 'z':
case '_': case '_':
case '$':
letter: letter:
{
register char *p;
#if USE_CPPLIB #if USE_CPPLIB
if (cpp_token == CPP_NAME) if (cpp_token == CPP_NAME)
{ {
/* Note that one character has already been read from /* Note that one character has already been read from
yy_cur into token_buffer. */ 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) int len = yy_lim - yy_cur + 1;
extend_token_buffer_to (len + 1); if (len >= maxtoken)
memcpy (token_buffer + 1, yy_cur, len); extend_token_buffer_to (len + 1);
p = token_buffer + len; memcpy (token_buffer + 1, yy_cur, len);
yy_cur = yy_lim; p = token_buffer + len;
} yy_cur = yy_lim;
else }
else
#endif #endif
{ {
/* We already installed C as the first char in token_buffer. */ p = token_buffer;
p = token_buffer+1; while (ISALNUM (c) || (c == '_') || c == '$')
c = token_getch (); {
/* Make sure this char really belongs in an identifier. */
while (ISALNUM (c) || (c == '_') || c == '$') if (c == '$')
{ {
if (c == '$') if (! dollars_in_ident)
{ error ("`$' in identifier");
if (! dollars_in_ident) else if (pedantic)
error ("`$' in identifier"); pedwarn ("`$' in identifier");
else if (pedantic) }
pedwarn ("`$' in identifier");
}
if (p >= token_buffer + maxtoken) if (p >= token_buffer + maxtoken)
p = extend_token_buffer (p); p = extend_token_buffer (p);
*p++ = c; *p++ = c;
c = token_getch (); c = token_getch ();
} }
*p = 0; *p = 0;
token_put_back (c); token_put_back (c);
} }
value = IDENTIFIER; value = IDENTIFIER;
yylval.itype = 0; yylval.itype = 0;
/* Try to recognize a keyword. Uses minimum-perfect hash function */ /* Try to recognize a keyword. Uses minimum-perfect hash function */
{ {
register struct resword *ptr; register struct resword *ptr;
if ((ptr = is_reserved_word (token_buffer, p - token_buffer))) if ((ptr = is_reserved_word (token_buffer, p - token_buffer)))
{ {
if (ptr->rid) if (ptr->rid)
{ {
tree old_ttype = ridpointers[(int) ptr->rid]; if (ptr->token == VISSPEC)
{
/* If this provides a type for us, then revert lexical switch (ptr->rid)
state to standard state. */ {
if (TREE_CODE (old_ttype) == IDENTIFIER_NODE case RID_PUBLIC:
&& IDENTIFIER_GLOBAL_VALUE (old_ttype) != 0 yylval.ttype = access_public_node;
&& TREE_CODE (IDENTIFIER_GLOBAL_VALUE (old_ttype)) == TYPE_DECL) break;
looking_for_typename = 0; case RID_PRIVATE:
else if (ptr->token == AGGR || ptr->token == ENUM) yylval.ttype = access_private_node;
looking_for_typename = 2; break;
case RID_PROTECTED:
if (ptr->token == VISSPEC) yylval.ttype = access_protected_node;
{ break;
switch (ptr->rid) default:
{ my_friendly_abort (63);
case RID_PUBLIC: }
yylval.ttype = access_public_node; }
break; else
case RID_PRIVATE: yylval.ttype = ridpointers[(int) ptr->rid];
yylval.ttype = access_private_node; }
break; else switch (ptr->token)
case RID_PROTECTED: {
yylval.ttype = access_protected_node; case EQCOMPARE:
break; yylval.code = NE_EXPR;
default: token_buffer[0] = '!';
my_friendly_abort (63); token_buffer[1] = '=';
} token_buffer[2] = 0;
} break;
else
yylval.ttype = old_ttype;
}
else switch (ptr->token)
{
case EQCOMPARE:
yylval.code = NE_EXPR;
token_buffer[0] = '!';
token_buffer[1] = '=';
token_buffer[2] = 0;
break;
case ASSIGN: case ASSIGN:
if (strcmp ("and_eq", token_buffer) == 0) if (strcmp ("and_eq", token_buffer) == 0)
{ {
yylval.code = BIT_AND_EXPR; yylval.code = BIT_AND_EXPR;
token_buffer[0] = '&'; token_buffer[0] = '&';
} }
else if (strcmp ("or_eq", token_buffer) == 0) else if (strcmp ("or_eq", token_buffer) == 0)
{ {
yylval.code = BIT_IOR_EXPR; yylval.code = BIT_IOR_EXPR;
token_buffer[0] = '|'; token_buffer[0] = '|';
} }
else if (strcmp ("xor_eq", token_buffer) == 0) else if (strcmp ("xor_eq", token_buffer) == 0)
{ {
yylval.code = BIT_XOR_EXPR; yylval.code = BIT_XOR_EXPR;
token_buffer[0] = '^'; token_buffer[0] = '^';
} }
token_buffer[1] = '='; token_buffer[1] = '=';
token_buffer[2] = 0; token_buffer[2] = 0;
break; break;
case '&': case '&':
yylval.code = BIT_AND_EXPR; yylval.code = BIT_AND_EXPR;
token_buffer[0] = '&'; token_buffer[0] = '&';
token_buffer[1] = 0; token_buffer[1] = 0;
break; break;
case '|': case '|':
yylval.code = BIT_IOR_EXPR; yylval.code = BIT_IOR_EXPR;
token_buffer[0] = '|'; token_buffer[0] = '|';
token_buffer[1] = 0; token_buffer[1] = 0;
break; break;
case '^': case '^':
yylval.code = BIT_XOR_EXPR; yylval.code = BIT_XOR_EXPR;
token_buffer[0] = '^'; token_buffer[0] = '^';
token_buffer[1] = 0; token_buffer[1] = 0;
break; break;
} }
value = (int) ptr->token; value = (int) ptr->token;
} }
} }
/* If we did not find a keyword, look for an identifier /* If we did not find a keyword, look for an identifier
(or a typename). */ (or a typename). */
if (value == IDENTIFIER || value == TYPESPEC) if (value == IDENTIFIER || value == TYPESPEC)
GNU_xref_ref (current_function_decl, token_buffer); GNU_xref_ref (current_function_decl, token_buffer);
if (value == IDENTIFIER) if (value == IDENTIFIER)
{ {
register tree tmp = get_identifier (token_buffer); register tree tmp = get_identifier (token_buffer);
#if !defined(VMS) && defined(JOINER) #if !defined(VMS) && defined(JOINER)
/* Make sure that user does not collide with our internal /* Make sure that user does not collide with our internal
naming scheme. */ naming scheme. */
if (JOINER == '$' if (JOINER == '$'
&& dollar_seen && (THIS_NAME_P (tmp)
&& (THIS_NAME_P (tmp) || VPTR_NAME_P (tmp)
|| VPTR_NAME_P (tmp) || DESTRUCTOR_NAME_P (tmp)
|| DESTRUCTOR_NAME_P (tmp) || VTABLE_NAME_P (tmp)
|| VTABLE_NAME_P (tmp) || TEMP_NAME_P (tmp)
|| TEMP_NAME_P (tmp) || ANON_AGGRNAME_P (tmp)
|| ANON_AGGRNAME_P (tmp) || ANON_PARMNAME_P (tmp)))
|| ANON_PARMNAME_P (tmp))) warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy",
warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy", token_buffer);
token_buffer);
#endif #endif
yylval.ttype = tmp; yylval.ttype = tmp;
} }
if (value == NEW && ! global_bindings_p ()) if (value == NEW && ! global_bindings_p ())
{ {
value = NEW; value = NEW;
goto done; goto done;
} }
}
break; break;
case '.': case '.':
...@@ -3537,13 +3790,13 @@ real_yylex () ...@@ -3537,13 +3790,13 @@ real_yylex ()
if (ISDIGIT (c1)) if (ISDIGIT (c1))
{ {
token_put_back (c1); token_put_back (c1);
goto resume_numerical_scan; goto number;
} }
token_put_back (c1); token_put_back (c1);
} }
value = '.'; value = '.';
token_buffer[1] = 0; token_buffer[1] = 0;
goto done; break;
case '0': case '1': case '0': case '1':
/* Optimize for most frequent case. */ /* Optimize for most frequent case. */
...@@ -3559,21 +3812,16 @@ real_yylex () ...@@ -3559,21 +3812,16 @@ real_yylex ()
#endif #endif
if (cond) if (cond)
{ {
/* Terminate string. */ yylval.ttype = (c == '0') ? integer_zero_node : integer_one_node;
if (c == '0')
yylval.ttype = integer_zero_node;
else
yylval.ttype = integer_one_node;
value = CONSTANT; value = CONSTANT;
goto done; break;
} }
/*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': case '5': case '6': case '7': case '8': case '9':
resume_numerical_scan: number:
{ {
register char *p;
int base = 10; int base = 10;
int count = 0; int count = 0;
int largest_digit = 0; int largest_digit = 0;
...@@ -3591,8 +3839,8 @@ real_yylex () ...@@ -3591,8 +3839,8 @@ real_yylex ()
#define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2) #define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2)
unsigned int parts[TOTAL_PARTS]; unsigned int parts[TOTAL_PARTS];
enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS, AFTER_EXPON }
= NOT_FLOAT; floatflag = NOT_FLOAT;
for (count = 0; count < TOTAL_PARTS; count++) for (count = 0; count < TOTAL_PARTS; count++)
parts[count] = 0; parts[count] = 0;
...@@ -3621,19 +3869,19 @@ real_yylex () ...@@ -3621,19 +3869,19 @@ real_yylex ()
/* Read all the digits-and-decimal-points. */ /* Read all the digits-and-decimal-points. */
while (c == '.' while (c == '.'
|| (ISALNUM (c) && (c != 'l') && (c != 'L') || (ISALNUM (c) && c != 'l' && c != 'L'
&& (c != 'u') && (c != 'U') && c != 'u' && c != 'U'
&& c != 'i' && c != 'I' && c != 'j' && c != 'J' && c != 'i' && c != 'I' && c != 'j' && c != 'J'
&& (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F'))))) && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F')))))
{ {
if (c == '.') if (c == '.')
{ {
if (base == 16) if (base == 16 && pedantic)
error ("floating constant may not be in radix 16"); pedwarn ("floating constant may not be in radix 16");
if (floatflag == TOO_MANY_POINTS) if (floatflag == TOO_MANY_POINTS)
/* We have already emitted an error. Don't need another. */ /* 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"); error ("malformed floating constant");
floatflag = TOO_MANY_POINTS; floatflag = TOO_MANY_POINTS;
...@@ -3644,7 +3892,8 @@ real_yylex () ...@@ -3644,7 +3892,8 @@ real_yylex ()
else else
floatflag = AFTER_POINT; floatflag = AFTER_POINT;
base = 10; if (base == 8)
base = 10;
*p++ = c = token_getch (); *p++ = c = token_getch ();
/* Accept '.' as the start of a floating-point number /* Accept '.' as the start of a floating-point number
only when it is followed by a digit. */ only when it is followed by a digit. */
...@@ -3665,12 +3914,17 @@ real_yylex () ...@@ -3665,12 +3914,17 @@ real_yylex ()
if (c == 'e' || c == 'E') if (c == 'e' || c == 'E')
{ {
base = 10; base = 10;
floatflag = AFTER_POINT; floatflag = AFTER_EXPON;
break; /* start of exponent */ break; /* start of exponent */
} }
error ("nondigits in number and not hexadecimal"); error ("nondigits in number and not hexadecimal");
c = 0; c = 0;
} }
else if (base == 16 && (c == 'p' || c == 'P'))
{
floatflag = AFTER_EXPON;
break; /* start of exponent */
}
else if (c >= 'a') else if (c >= 'a')
{ {
c = c - 'a' + 10; c = c - 'a' + 10;
...@@ -3725,15 +3979,15 @@ real_yylex () ...@@ -3725,15 +3979,15 @@ real_yylex ()
if (floatflag != NOT_FLOAT) if (floatflag != NOT_FLOAT)
{ {
tree type = double_type_node; tree type;
int exceeds_double = 0; int imag, conversion_errno;
int imag = 0;
REAL_VALUE_TYPE value; REAL_VALUE_TYPE value;
struct pf_args args; struct pf_args args;
/* Read explicit exponent if any, and put it in tokenbuf. */ /* 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) if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p); p = extend_token_buffer (p);
...@@ -3744,9 +3998,10 @@ real_yylex () ...@@ -3744,9 +3998,10 @@ real_yylex ()
*p++ = c; *p++ = c;
c = token_getch (); c = token_getch ();
} }
/* Exponent is decimal, even if string is a hex float. */
if (! ISDIGIT (c)) if (! ISDIGIT (c))
error ("floating constant exponent has no digits"); error ("floating constant exponent has no digits");
while (ISDIGIT (c)) while (ISDIGIT (c))
{ {
if (p >= token_buffer + maxtoken - 3) if (p >= token_buffer + maxtoken - 3)
p = extend_token_buffer (p); p = extend_token_buffer (p);
...@@ -3754,16 +4009,16 @@ real_yylex () ...@@ -3754,16 +4009,16 @@ real_yylex ()
c = token_getch (); c = token_getch ();
} }
} }
if (base == 16 && floatflag != AFTER_EXPON)
error ("hexadecimal floating constant has no exponent");
*p = 0; *p = 0;
errno = 0;
/* Setup input for parse_float() */ /* Setup input for parse_float() */
args.base = base;
args.p = p; args.p = p;
args.c = c; args.c = c;
args.imag = imag;
args.type = type;
/* Convert string to a double, checking for overflow. */ /* Convert string to a double, checking for overflow. */
if (do_float_handler (parse_float, (PTR) &args)) if (do_float_handler (parse_float, (PTR) &args))
{ {
...@@ -3778,24 +4033,18 @@ real_yylex () ...@@ -3778,24 +4033,18 @@ real_yylex ()
} }
/* Receive output from parse_float() */ /* Receive output from parse_float() */
p = args.p;
c = args.c; c = args.c;
imag = args.imag; imag = args.imag;
type = args.type; type = args.type;
conversion_errno = args.conversion_errno;
#ifdef ERANGE #ifdef ERANGE
if (errno == ERANGE && pedantic) /* ERANGE is also reported for underflow,
{ so test the value to distinguish overflow from that. */
/* ERANGE is also reported for underflow, if (conversion_errno == ERANGE && pedantic
so test the value to distinguish overflow from that. */ && (REAL_VALUES_LESS (dconst1, value)
if (REAL_VALUES_LESS (dconst1, value) || REAL_VALUES_LESS (value, dconstm1)))
|| REAL_VALUES_LESS (value, dconstm1)) warning ("floating point number exceeds range of `double'");
{
pedwarn ("floating point number exceeds range of `%s'",
IDENTIFIER_POINTER (TYPE_IDENTIFIER (type)));
exceeds_double = 1;
}
}
#endif #endif
/* If the result is not a number, assume it must have been /* If the result is not a number, assume it must have been
...@@ -3807,7 +4056,7 @@ real_yylex () ...@@ -3807,7 +4056,7 @@ real_yylex ()
/* Create a node with determined type and value. */ /* Create a node with determined type and value. */
if (imag) if (imag)
yylval.ttype = build_complex (NULL_TREE, yylval.ttype = build_complex (NULL_TREE,
cp_convert (type, integer_zero_node), convert (type, integer_zero_node),
build_real (type, value)); build_real (type, value));
else else
yylval.ttype = build_real (type, value); yylval.ttype = build_real (type, value);
...@@ -3820,7 +4069,7 @@ real_yylex () ...@@ -3820,7 +4069,7 @@ real_yylex ()
int spec_long = 0; int spec_long = 0;
int spec_long_long = 0; int spec_long_long = 0;
int spec_imag = 0; int spec_imag = 0;
int warn; int warn, i;
while (1) while (1)
{ {
...@@ -3867,6 +4116,7 @@ real_yylex () ...@@ -3867,6 +4116,7 @@ real_yylex ()
/* This is simplified by the fact that our constant /* This is simplified by the fact that our constant
is always positive. */ is always positive. */
high = low = 0; high = low = 0;
for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++) for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++)
...@@ -3876,27 +4126,25 @@ real_yylex () ...@@ -3876,27 +4126,25 @@ real_yylex ()
<< (i * HOST_BITS_PER_CHAR)); << (i * HOST_BITS_PER_CHAR));
low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR); low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR);
} }
yylval.ttype = build_int_2 (low, high); yylval.ttype = build_int_2 (low, high);
TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node; TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node;
/* Calculate the ANSI type. */ /* Calculate the ANSI type. */
if (!spec_long && !spec_unsigned if (! spec_long && ! spec_unsigned
&& int_fits_type_p (yylval.ttype, integer_type_node)) && int_fits_type_p (yylval.ttype, integer_type_node))
type = 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)) && int_fits_type_p (yylval.ttype, unsigned_type_node))
/* Nondecimal constants try unsigned even in traditional C. */
type = unsigned_type_node; 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)) && int_fits_type_p (yylval.ttype, long_integer_type_node))
type = 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; type = long_unsigned_type_node;
else if (! spec_unsigned 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, && int_fits_type_p (yylval.ttype,
long_long_integer_type_node)) long_long_integer_type_node))
type = long_long_integer_type_node; type = long_long_integer_type_node;
...@@ -3910,11 +4158,16 @@ real_yylex () ...@@ -3910,11 +4158,16 @@ real_yylex ()
else else
type = widest_unsigned_literal_type_node; type = widest_unsigned_literal_type_node;
if (!int_fits_type_p (yylval.ttype, type) && !warn) if (pedantic && !spec_long_long && !warn
pedwarn ("integer constant is larger than the maximum value for its type"); && (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)) 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) if (spec_imag)
{ {
...@@ -3922,18 +4175,32 @@ real_yylex () ...@@ -3922,18 +4175,32 @@ real_yylex ()
<= TYPE_PRECISION (integer_type_node)) <= TYPE_PRECISION (integer_type_node))
yylval.ttype yylval.ttype
= build_complex (NULL_TREE, integer_zero_node, = build_complex (NULL_TREE, integer_zero_node,
cp_convert (integer_type_node, convert (integer_type_node,
yylval.ttype)); yylval.ttype));
else else
error ("complex integer constant is too wide for `__complex int'"); error ("complex integer constant is too wide for `__complex int'");
} }
else else
TREE_TYPE (yylval.ttype) = type; 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");
} }
token_put_back (c); token_put_back (c);
*p = 0; *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; value = CONSTANT; break;
} }
...@@ -4057,7 +4324,7 @@ real_yylex () ...@@ -4057,7 +4324,7 @@ real_yylex ()
} }
/* Merge character into result; ignore excess 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 (num_chars < max_chars + 1)
{ {
if (width < HOST_BITS_PER_INT) if (width < HOST_BITS_PER_INT)
...@@ -4097,6 +4364,7 @@ real_yylex () ...@@ -4097,6 +4364,7 @@ real_yylex ()
= build_int_2 (result | ~(~(unsigned HOST_WIDE_INT) 0 = build_int_2 (result | ~(~(unsigned HOST_WIDE_INT) 0
>> (HOST_BITS_PER_WIDE_INT - num_bits)), >> (HOST_BITS_PER_WIDE_INT - num_bits)),
-1); -1);
/* In C, a character constant has type 'int'; in C++, 'char'. */
if (chars_seen <= 1) if (chars_seen <= 1)
TREE_TYPE (yylval.ttype) = char_type_node; TREE_TYPE (yylval.ttype) = char_type_node;
else else
...@@ -4115,7 +4383,6 @@ real_yylex () ...@@ -4115,7 +4383,6 @@ real_yylex ()
case '"': case '"':
string_constant: string_constant:
{ {
register char *p;
unsigned width = wide_flag ? WCHAR_TYPE_SIZE unsigned width = wide_flag ? WCHAR_TYPE_SIZE
: TYPE_PRECISION (char_type_node); : TYPE_PRECISION (char_type_node);
#ifdef MULTIBYTE_CHARS #ifdef MULTIBYTE_CHARS
...@@ -4137,7 +4404,7 @@ real_yylex () ...@@ -4137,7 +4404,7 @@ real_yylex ()
goto skipnewline; goto skipnewline;
if (width < HOST_BITS_PER_INT if (width < HOST_BITS_PER_INT
&& (unsigned) c >= ((unsigned)1 << width)) && (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') else if (c == '\n')
{ {
...@@ -4198,7 +4465,7 @@ real_yylex () ...@@ -4198,7 +4465,7 @@ real_yylex ()
for (byte = 0; byte < WCHAR_BYTES; ++byte) for (byte = 0; byte < WCHAR_BYTES; ++byte)
{ {
int value; int value;
if (byte >= (int) sizeof(c)) if (byte >= (int) sizeof (c))
value = 0; value = 0;
else else
value = (c >> (byte * width)) & bytemask; value = (c >> (byte * width)) & bytemask;
...@@ -4218,10 +4485,6 @@ real_yylex () ...@@ -4218,10 +4485,6 @@ real_yylex ()
skipnewline: skipnewline:
c = token_getch (); c = token_getch ();
if (c == EOF) {
error ("Unterminated string");
break;
}
} }
/* Terminate the string value, either with a single byte zero /* Terminate the string value, either with a single byte zero
...@@ -4240,6 +4503,9 @@ real_yylex () ...@@ -4240,6 +4503,9 @@ real_yylex ()
*p++ = 0; *p++ = 0;
} }
if (c == EOF)
error ("Unterminated string constant");
/* We have read the entire constant. /* We have read the entire constant.
Construct a STRING_CST for the result. */ Construct a STRING_CST for the result. */
...@@ -4261,6 +4527,7 @@ real_yylex () ...@@ -4261,6 +4527,7 @@ real_yylex ()
case '-': case '-':
case '&': case '&':
case '|': case '|':
case ':':
case '<': case '<':
case '>': case '>':
case '*': case '*':
...@@ -4337,19 +4604,11 @@ real_yylex () ...@@ -4337,19 +4604,11 @@ real_yylex ()
case '>': case '>':
c = RSHIFT; c = RSHIFT;
goto combine; goto combine;
case ':':
value = SCOPE;
yylval.itype = 1;
goto done;
} }
else if ((c == '-') && (c1 == '>'))
{
c1 = token_getch ();
if (c1 == '*')
value = POINTSAT_STAR;
else
{
token_put_back (c1);
value = POINTSAT;
}
goto done;
}
else if (c1 == '?' && (c == '<' || c == '>')) else if (c1 == '?' && (c == '<' || c == '>'))
{ {
token_buffer[3] = 0; token_buffer[3] = 0;
...@@ -4372,49 +4631,66 @@ real_yylex () ...@@ -4372,49 +4631,66 @@ real_yylex ()
token_buffer); token_buffer);
goto done; goto done;
} }
/* digraphs */ else
else if (c == '<' && c1 == '%') switch (c)
{ value = '{'; goto done; } {
else if (c == '<' && c1 == ':') case '-':
{ value = '['; goto done; } if (c1 == '>')
else if (c == '%' && c1 == '>') {
{ value = '}'; goto done; } c1 = token_getch ();
else if (c == '%' && c1 == ':') if (c1 == '*')
{ value = '#'; goto done; } 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_put_back (c1);
token_buffer[1] = 0; token_buffer[1] = 0;
/* Here the C frontend changes < and > to ARITHCOMPARE. We don't
do that because of templates. */
value = c; value = c;
goto done; break;
} }
case ':':
c = token_getch ();
if (c == ':')
{
token_buffer[1] = ':';
token_buffer[2] = '\0';
value = SCOPE;
yylval.itype = 1;
}
else if (c == '>')
{
value = ']';
goto done;
}
else
{
token_put_back (c);
value = ':';
}
break;
case 0: case 0:
/* Don't make yyparse think this is eof. */ /* Don't make yyparse think this is eof. */
value = 1; value = 1;
break; break;
case '{':
indent_level++;
value = c;
break;
case '}':
indent_level--;
value = c;
break;
default: default:
value = c; value = c;
} }
...@@ -4690,135 +4966,6 @@ compiler_error VPROTO ((const char *msg, ...)) ...@@ -4690,135 +4966,6 @@ compiler_error VPROTO ((const char *msg, ...))
error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf); error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
} }
void
yyerror (string)
const char *string;
{
extern int end_of_file;
char buf[200];
strcpy (buf, string);
/* We can't print string and character constants well
because the token_buffer contains the result of processing escapes. */
if (end_of_file)
strcat (buf, input_redirected ()
? " at end of saved text"
: " at end of input");
else if (token_buffer[0] == 0)
strcat (buf, " at null character");
else if (token_buffer[0] == '"')
strcat (buf, " before string constant");
else if (token_buffer[0] == '\'')
strcat (buf, " before character constant");
else if (!ISGRAPH ((unsigned char)token_buffer[0]))
sprintf (buf + strlen (buf), " before character 0%o",
(unsigned char) token_buffer[0]);
else
strcat (buf, " before `%s'");
error (buf, token_buffer);
}
static int
handle_cp_pragma (pname)
const char *pname;
{
register int token;
if (! strcmp (pname, "vtable"))
{
extern tree pending_vtables;
/* More follows: it must be a string constant (class name). */
token = real_yylex ();
if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
{
error ("invalid #pragma vtable");
return -1;
}
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;
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");
cp_pragma_interface (main_filename);
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);
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");
cp_pragma_implementation (main_filename);
return 1;
}
return 0;
}
/* Return the type-qualifier corresponding to the identifier given by /* Return the type-qualifier corresponding to the identifier given by
RID. */ RID. */
...@@ -4836,45 +4983,3 @@ cp_type_qual_from_rid (rid) ...@@ -4836,45 +4983,3 @@ cp_type_qual_from_rid (rid)
my_friendly_abort (0); my_friendly_abort (0);
return TYPE_UNQUALIFIED; return TYPE_UNQUALIFIED;
} }
#ifdef HANDLE_GENERIC_PRAGMAS
/* Handle a #pragma directive. TOKEN is the type of the word following
the #pragma directive on the line. Process the entire input line and
return non-zero iff the directive successfully parsed. */
/* This function has to be in this file, in order to get at
the token types. */
static int
handle_generic_pragma (token)
register int token;
{
for (;;)
{
switch (token)
{
case IDENTIFIER:
case TYPENAME:
case STRING:
case CONSTANT:
handle_pragma_token (token_buffer, yylval.ttype);
break;
case LEFT_RIGHT:
handle_pragma_token ("(", NULL_TREE);
handle_pragma_token (")", NULL_TREE);
break;
case END_OF_LINE:
return handle_pragma_token (NULL_PTR, NULL_TREE);
default:
handle_pragma_token (token_buffer, NULL_TREE);
}
token = real_yylex ();
}
}
#endif /* HANDLE_GENERIC_PRAGMAS */
...@@ -401,6 +401,9 @@ yylex () ...@@ -401,6 +401,9 @@ yylex ()
break; break;
case TYPESPEC: case TYPESPEC:
/* If this provides a type for us, then revert lexical
state to standard state. */
looking_for_typename = 0;
consume_token (); consume_token ();
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment