summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp/lex.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp/lex.c')
-rw-r--r--contrib/gcc/cp/lex.c1182
1 files changed, 687 insertions, 495 deletions
diff --git a/contrib/gcc/cp/lex.c b/contrib/gcc/cp/lex.c
index 57639ad..d9f2262 100644
--- a/contrib/gcc/cp/lex.c
+++ b/contrib/gcc/cp/lex.c
@@ -1,5 +1,5 @@
/* 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.
@@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
-#include <setjmp.h>
#include "input.h"
#include "tree.h"
#include "lex.h"
@@ -39,14 +38,8 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "output.h"
-/* MULTIBYTE_CHARS support only works for native compilers.
- ??? Ideally what we want is to model widechar support after
- the current floating point support. */
-#ifdef CROSS_COMPILE
-#undef MULTIBYTE_CHARS
-#endif
-
#ifdef MULTIBYTE_CHARS
+#include "mbchar.h"
#include <locale.h>
#endif
@@ -61,28 +54,26 @@ extern struct obstack permanent_obstack;
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 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 int set_typedecl_interface_info PROTO((tree *, void *));
static void feed_defarg PROTO((tree, tree));
-static int set_vardecl_interface_info PROTO((tree, tree));
+static int set_vardecl_interface_info PROTO((tree *, void *));
static void store_pending_inline PROTO((tree, struct pending_inline *));
static void reinit_parse_for_expr PROTO((struct obstack *));
static int *init_cpp_parse PROTO((void));
-static int handle_cp_pragma PROTO((char *));
-#ifdef HANDLE_SYSV_PRAGMA
-static int handle_sysv_pragma PROTO((int));
+static int handle_cp_pragma PROTO((const char *));
+#ifdef HANDLE_GENERIC_PRAGMAS
+static int handle_generic_pragma PROTO((int));
#endif
#ifdef GATHER_STATISTICS
#ifdef REDUCE_LENGTH
@@ -90,12 +81,16 @@ static int reduce_cmp PROTO((int *, int *));
static int token_cmp PROTO((int *, int *));
#endif
#endif
+static void begin_definition_of_inclass_inline PROTO((struct pending_inline*));
+static void parse_float PROTO((PTR));
+static int is_global PROTO((tree));
+static void init_filename_times PROTO((void));
/* Given a file name X, return the nondirectory portion.
Keep in mind that X can be computed more than once. */
char *
file_name_nondirectory (x)
- char *x;
+ const char *x;
{
char *tmp = (char *) rindex (x, '/');
if (DIR_SEPARATOR != '/' && ! tmp)
@@ -103,7 +98,7 @@ file_name_nondirectory (x)
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
@@ -319,7 +314,7 @@ static int ignore_escape_flag = 0;
static tree
get_time_identifier (name)
- char *name;
+ const char *name;
{
tree time_identifier;
int len = strlen (name);
@@ -328,12 +323,13 @@ get_time_identifier (name)
bcopy (name, buf+5, len);
buf[len+5] = '\0';
time_identifier = get_identifier (buf);
- if (IDENTIFIER_LOCAL_VALUE (time_identifier) == NULL_TREE)
+ if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE)
{
push_obstacks_nochange ();
end_temporary_allocation ();
- IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0);
- IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1);
+ TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0);
+ TIME_IDENTIFIER_FILEINFO (time_identifier)
+ = build_int_2 (0, 1);
SET_IDENTIFIER_GLOBAL_VALUE (time_identifier, filename_times);
filename_times = time_identifier;
pop_obstacks ();
@@ -383,7 +379,7 @@ int cplus_tree_code_length[] = {
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"
};
@@ -394,6 +390,12 @@ char *cplus_tree_code_name[] = {
void
lang_init_options ()
{
+#if USE_CPPLIB
+ cpp_reader_init (&parse_in);
+ parse_in.opts = &parse_options;
+ cpp_options_init (&parse_options);
+#endif
+
/* Default exceptions on. */
flag_exceptions = 1;
}
@@ -401,11 +403,14 @@ lang_init_options ()
void
lang_init ()
{
-#if ! USE_CPPLIB
/* 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);
@@ -424,7 +429,7 @@ lang_identify ()
return "cplusplus";
}
-void
+static void
init_filename_times ()
{
this_filename_time = get_time_identifier ("<top level>");
@@ -432,7 +437,8 @@ init_filename_times ()
{
header_time = 0;
body_time = my_get_run_time ();
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time)) = body_time;
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
+ = body_time;
}
}
@@ -474,13 +480,22 @@ init_parse (filename)
int i;
-#if USE_CPPLIB
- yy_cur = "\n";
- yy_lim = yy_cur + 1;
+#ifdef MULTIBYTE_CHARS
+ /* Change to the native locale for multibyte conversions. */
+ setlocale (LC_CTYPE, "");
+ 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
/* Open input file. */
if (filename == 0 || !strcmp (filename, "-"))
@@ -635,7 +650,7 @@ init_parse (filename)
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,
@@ -664,67 +679,28 @@ init_parse (filename)
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");
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;
@@ -742,37 +718,26 @@ init_parse (filename)
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");
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
+ set up. Therefore, we don't set the type of these nodes until
+ init_decl_processing. */
null_node = build_int_2 (0, 0);
ridpointers[RID_NULL] = null_node;
@@ -1123,7 +1088,7 @@ extract_interface_info ()
}
if (!fileinfo)
fileinfo = get_time_identifier (input_filename);
- fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo);
+ fileinfo = TIME_IDENTIFIER_FILEINFO (fileinfo);
interface_only = TREE_INT_CST_LOW (fileinfo);
interface_unknown = TREE_INT_CST_HIGH (fileinfo);
}
@@ -1133,15 +1098,15 @@ extract_interface_info ()
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)
@@ -1169,37 +1134,71 @@ interface_strcmp (s)
return 1;
}
-static void
-set_typedecl_interface_info (prev, vars)
- tree prev, vars;
+static int
+set_typedecl_interface_info (t, data)
+ tree *t;
+ void *data ATTRIBUTE_UNUSED;
{
- tree id = get_time_identifier (DECL_SOURCE_FILE (vars));
- tree fileinfo = IDENTIFIER_CLASS_VALUE (id);
- tree type = TREE_TYPE (vars);
+ tree id = get_time_identifier (DECL_SOURCE_FILE (*t));
+ tree fileinfo = TIME_IDENTIFIER_FILEINFO (id);
+ tree type = TREE_TYPE (*t);
CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
- = interface_strcmp (file_name_nondirectory (DECL_SOURCE_FILE (vars)));
+ = interface_strcmp (file_name_nondirectory (DECL_SOURCE_FILE (*t)));
+ return 0;
}
static int
-set_vardecl_interface_info (prev, vars)
- tree prev, vars;
+set_vardecl_interface_info (t, data)
+ tree *t;
+ void *data ATTRIBUTE_UNUSED;
{
- tree type = DECL_CONTEXT (vars);
+ tree type = DECL_CONTEXT (*t);
if (CLASSTYPE_INTERFACE_KNOWN (type))
{
if (CLASSTYPE_INTERFACE_ONLY (type))
- set_typedecl_interface_info (prev, TYPE_MAIN_DECL (type));
+ set_typedecl_interface_info (&TYPE_MAIN_DECL (type), data);
else
CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
- DECL_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type);
- TREE_PUBLIC (vars) = 1;
+ DECL_EXTERNAL (*t) = CLASSTYPE_INTERFACE_ONLY (type);
+ TREE_PUBLIC (*t) = 1;
return 1;
}
return 0;
}
+/* Set up the state required to correctly handle the definition of the
+ inline function whose preparsed state has been saved in PI. */
+
+static void
+begin_definition_of_inclass_inline (pi)
+ struct pending_inline* pi;
+{
+ tree context;
+
+ if (!pi->fndecl)
+ return;
+
+ /* If this is an inline function in a local class, we must make sure
+ that we save all pertinent information about the function
+ surrounding the local class. */
+ context = hack_decl_function_context (pi->fndecl);
+ if (context)
+ push_cp_function_context (context);
+
+ feed_input (pi->buf, pi->len);
+ lineno = pi->lineno;
+ input_filename = pi->filename;
+ yychar = PRE_PARSED_FUNCTION_DECL;
+ yylval.ttype = build_tree_list ((tree) pi, pi->fndecl);
+ /* Pass back a handle to the rest of the inline functions, so that they
+ can be processed later. */
+ DECL_PENDING_INLINE_INFO (pi->fndecl) = 0;
+ interface_unknown = pi->interface == 1;
+ interface_only = pi->interface == 0;
+}
+
/* Called from the top level: if there are any pending inlines to
do, set up to process them now. This function sets up the first function
to be parsed; after it has been, the rule for fndef in parse.y will
@@ -1209,7 +1208,6 @@ void
do_pending_inlines ()
{
struct pending_inline *t;
- tree context;
/* Oops, we're still dealing with the last batch. */
if (yychar == PRE_PARSED_FUNCTION_DECL)
@@ -1236,32 +1234,7 @@ do_pending_inlines ()
return;
/* Now start processing the first inline function. */
- context = hack_decl_function_context (t->fndecl);
- if (context)
- push_cp_function_context (context);
- maybe_begin_member_template_processing (t->fndecl);
- if (t->len > 0)
- {
- feed_input (t->buf, t->len);
- lineno = t->lineno;
-#if 0
- if (input_filename != t->filename)
- {
- input_filename = t->filename;
- /* Get interface/implementation back in sync. */
- extract_interface_info ();
- }
-#else
- input_filename = t->filename;
- interface_unknown = t->interface == 1;
- interface_only = t->interface == 0;
-#endif
- yychar = PRE_PARSED_FUNCTION_DECL;
- }
- /* Pass back a handle on the rest of the inline functions, so that they
- can be processed later. */
- yylval.ttype = build_tree_list ((tree) t, t->fndecl);
- DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
+ begin_definition_of_inclass_inline (t);
}
static int nextchar = -1;
@@ -1277,7 +1250,6 @@ process_next_inline (t)
tree context;
struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
context = hack_decl_function_context (i->fndecl);
- maybe_end_member_template_processing (i->fndecl);
if (context)
pop_cp_function_context (context);
i = i->next;
@@ -1295,24 +1267,8 @@ process_next_inline (t)
}
yychar = YYEMPTY;
end_input ();
- if (i && i->fndecl != NULL_TREE)
- {
- context = hack_decl_function_context (i->fndecl);
- if (context)
- push_cp_function_context (context);
- maybe_begin_member_template_processing (i->fndecl);
- feed_input (i->buf, i->len);
- lineno = i->lineno;
- input_filename = i->filename;
- yychar = PRE_PARSED_FUNCTION_DECL;
- yylval.ttype = build_tree_list ((tree) i, i->fndecl);
- DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
- }
if (i)
- {
- interface_unknown = i->interface == 1;
- interface_only = i->interface == 0;
- }
+ begin_definition_of_inclass_inline (i);
else
extract_interface_info ();
}
@@ -1538,10 +1494,12 @@ reinit_parse_for_block (pyychar, obstackp)
else if (pyychar == ':')
{
obstack_1grow (obstackp, pyychar);
+ /* Add a space so we don't get confused by ': ::A(20)'. */
+ obstack_1grow (obstackp, ' ');
look_for_lbrac = 1;
blev = 0;
}
- else if (pyychar == RETURN)
+ else if (pyychar == RETURN_KEYWORD)
{
obstack_grow (obstackp, "return", 6);
look_for_lbrac = 1;
@@ -1928,12 +1886,12 @@ do_pending_defargs ()
if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
{
- maybe_end_member_template_processing (defarg_fn);
+ maybe_end_member_template_processing ();
check_default_args (defarg_fn);
}
poplevel (0, 0, 0);
- pop_nested_class (1);
+ pop_nested_class ();
}
}
@@ -1977,7 +1935,7 @@ cons_up_default_function (type, full_name, kind)
break;
case 3:
- type = build_type_variant (type, 1, 0);
+ type = build_qualified_type (type, TYPE_QUAL_CONST);
/* Fall through... */
case 4:
/* According to ARM $12.8, the default copy ctor will be declared, but
@@ -1995,7 +1953,7 @@ cons_up_default_function (type, full_name, kind)
declspecs = build_decl_list (NULL_TREE, type);
if (kind == 5)
- type = build_type_variant (type, 1, 0);
+ type = build_qualified_type (type, TYPE_QUAL_CONST);
name = ansi_opname [(int) MODIFY_EXPR];
@@ -2113,7 +2071,7 @@ note_got_semicolon (type)
{
if (TREE_CODE_CLASS (TREE_CODE (type)) != 't')
my_friendly_abort (60);
- if (IS_AGGR_TYPE (type))
+ if (CLASS_TYPE_P (type))
CLASSTYPE_GOT_SEMICOLON (type) = 1;
}
@@ -2182,7 +2140,7 @@ skip_white_space (c)
static char *
extend_token_buffer (p)
- char *p;
+ const char *p;
{
int offset = p - token_buffer;
@@ -2208,6 +2166,32 @@ get_last_nonwhite_on_line ()
return c;
}
+#if defined HANDLE_PRAGMA
+/* Local versions of these macros, that can be passed as function pointers. */
+static int
+pragma_getc ()
+{
+ int c;
+
+ if (nextchar != EOF)
+ {
+ c = nextchar;
+ nextchar = EOF;
+ }
+ else
+ c = getch ();
+
+ return c;
+}
+
+static void
+pragma_ungetc (arg)
+ int arg;
+{
+ yyungetc (arg, 0);
+}
+#endif /* HANDLE_PRAGMA */
+
/* At the beginning of a line, increment the line number
and process any #-directive on this line.
If the line is a #-directive, read the entire line and return a newline.
@@ -2215,13 +2199,12 @@ get_last_nonwhite_on_line ()
int linemode;
-static int handle_cp_pragma PROTO((char *));
-
static int
check_newline ()
{
register int c;
register int token;
+ int saw_line = 0;
/* Read first nonwhite char on the line. Do this before incrementing the
line number, in case we're at the end of saved text. */
@@ -2251,7 +2234,7 @@ check_newline ()
it and ignore it; otherwise, ignore the line, with an error
if the word isn't `pragma'. */
- if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
+ if (ISALPHA (c))
{
if (c == 'p')
{
@@ -2274,21 +2257,29 @@ check_newline ()
else if (token == END_OF_LINE)
goto skipline;
-#ifdef HANDLE_SYSV_PRAGMA
- if (handle_sysv_pragma (token))
- goto skipline;
-#else
#ifdef HANDLE_PRAGMA
-#if USE_CPPLIB
- /* TODO: ??? */
- goto skipline;
-#else
- if (HANDLE_PRAGMA (finput, yylval.ttype))
- goto skipline;
-#endif /* !USE_CPPLIB */
-#endif
-#endif
+ /* We invoke HANDLE_PRAGMA before HANDLE_GENERIC_PRAGMAS
+ (if both are defined), in order to give the back
+ end a chance to override the interpretation of
+ SYSV style pragmas. */
+ if (HANDLE_PRAGMA (pragma_getc, pragma_ungetc,
+ IDENTIFIER_POINTER (yylval.ttype)))
+ goto skipline;
+#endif /* HANDLE_PRAGMA */
+
+#ifdef HANDLE_GENERIC_PRAGMAS
+ if (handle_generic_pragma (token))
+ goto skipline;
+#endif /* HANDLE_GENERIC_PRAGMAS */
+
+ /* Issue a warning message if we have been asked to do so.
+ Ignoring unknown pragmas in system header file unless
+ an explcit -Wunknown-pragmas has been given. */
+ if (warn_unknown_pragmas > 1
+ || (warn_unknown_pragmas && ! in_system_header))
+ warning ("ignoring pragma: %s", token_buffer);
}
+
goto skipline;
}
else if (c == 'd')
@@ -2322,7 +2313,10 @@ check_newline ()
&& getch () == 'n'
&& getch () == 'e'
&& ((c = getch ()) == ' ' || c == '\t'))
- goto linenum;
+ {
+ saw_line = 1;
+ goto linenum;
+ }
}
else if (c == 'i')
{
@@ -2419,9 +2413,16 @@ linenum:
/* More follows: it must be a string constant (filename). */
- /* Read the string constant, but don't treat \ as special. */
- ignore_escape_flag = 1;
+ if (saw_line)
+ {
+ /* Don't treat \ as special if we are processing #line 1 "...".
+ If you want it to be treated specially, use # 1 "...". */
+ ignore_escape_flag = 1;
+ }
+
+ /* Read the string constant. */
token = real_yylex ();
+
ignore_escape_flag = 0;
if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
@@ -2438,7 +2439,7 @@ linenum:
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 (IDENTIFIER_LOCAL_VALUE (this_filename_time))
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
+= this_time - body_time;
this_filename_time = time_identifier;
body_time = this_time;
@@ -2463,7 +2464,14 @@ linenum:
main_input_filename = input_filename;
if (write_virtuals == 3)
- walk_vtables (set_typedecl_interface_info, set_vardecl_interface_info);
+ {
+ walk_globals (vtable_decl_p,
+ set_vardecl_interface_info,
+ /*data=*/0);
+ walk_globals (vtype_decl_p,
+ set_typedecl_interface_info,
+ /*data=*/0);
+ }
}
extract_interface_info ();
@@ -2662,7 +2670,8 @@ readescape (ignore_ptr)
;
else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
|| (count > 1
- && ((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;
@@ -2727,7 +2736,7 @@ readescape (ignore_ptr)
pedwarn ("unknown escape sequence `\\%c'", c);
return c;
}
- if (c >= 040 && c < 0177)
+ if (ISGRAPH (c))
pedwarn ("unknown escape sequence `\\%c'", c);
else
pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c);
@@ -2746,6 +2755,7 @@ int
identifier_type (decl)
tree decl;
{
+ tree t;
if (TREE_CODE (decl) == TEMPLATE_DECL)
{
if (TREE_CODE (DECL_RESULT (decl)) == TYPE_DECL)
@@ -2755,7 +2765,10 @@ identifier_type (decl)
}
if (looking_for_template && really_overloaded_fn (decl))
{
- tree t;
+ /* See through a baselink. */
+ if (TREE_CODE (decl) == TREE_LIST)
+ decl = TREE_VALUE (decl);
+
for (t = decl; t != NULL_TREE; t = OVL_CHAIN (t))
if (DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (t)))
return PFUNCNAME;
@@ -2764,10 +2777,20 @@ identifier_type (decl)
return NSNAME;
if (TREE_CODE (decl) != TYPE_DECL)
return IDENTIFIER;
- if (((got_scope && TREE_TYPE (decl) == got_scope)
- || TREE_TYPE (decl) == current_class_type)
- && DECL_ARTIFICIAL (decl))
+ if (DECL_ARTIFICIAL (decl) && TREE_TYPE (decl) == current_class_type)
return SELFNAME;
+
+ /* A constructor declarator for a template type will get here as an
+ implicit typename, a TYPENAME_TYPE with a type. */
+ t = got_scope;
+ if (t && TREE_CODE (t) == TYPENAME_TYPE)
+ t = TREE_TYPE (t);
+ decl = TREE_TYPE (decl);
+ if (TREE_CODE (decl) == TYPENAME_TYPE)
+ decl = TREE_TYPE (decl);
+ if (t && t == decl)
+ return SELFNAME;
+
return TYPENAME;
}
@@ -2801,6 +2824,9 @@ is_global (d)
while (1)
switch (TREE_CODE (d))
{
+ case ERROR_MARK:
+ return 1;
+
case OVERLOAD: d = OVL_FUNCTION (d); continue;
case TREE_LIST: d = TREE_VALUE (d); continue;
default:
@@ -2843,12 +2869,19 @@ do_identifier (token, parsing, args)
|| TREE_CODE (field) == CONST_DECL
|| TREE_CODE (field) == TEMPLATE_DECL)
id = field;
+ else if (TREE_CODE (field) == TYPE_DECL
+ && DECL_ARTIFICIAL (field)
+ && IMPLICIT_TYPENAME_P (TREE_TYPE (field)))
+ /* When we did name-lookup before, we will have eschewed
+ implicit typenames in favor of global bindings. Therefore,
+ if lookup_field returns an implicit typename, but ID is not
+ an implicit typename, then we should skip this one, too. */
+ ;
else if (TREE_CODE (field) != FIELD_DECL)
my_friendly_abort (61);
else
{
- cp_error ("invalid use of member `%D' from base class `%T'", field,
- DECL_FIELD_CONTEXT (field));
+ cp_error ("invalid use of member `%D'", field);
id = error_mark_node;
return id;
}
@@ -2857,44 +2890,41 @@ do_identifier (token, parsing, args)
/* Do Koenig lookup if appropriate (inside templates we build lookup
expressions instead). */
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);
- }
+ /* 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, NULL_TREE);
+ return build_min_nt (LOOKUP_EXPR, token);
else if (IDENTIFIER_OPNAME_P (token))
{
if (token != ansi_opname[ERROR_MARK])
cp_error ("`%D' not defined", token);
id = error_mark_node;
}
- else if (in_call)
+ else if (in_call && ! flag_strict_prototype)
{
id = implicitly_declare (token);
}
@@ -2968,37 +2998,39 @@ do_identifier (token, parsing, args)
/* 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'. */
- }
- if (! processing_template_decl
- || (DECL_INITIAL (id)
- && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_PARM_INDEX))
+ enforce_access (DECL_REAL_CONTEXT(id), id);
+ if (!processing_template_decl || DECL_TEMPLATE_PARM_P (id))
id = DECL_INITIAL (id);
}
else
id = hack_identifier (id, token);
- if (current_template_parms)
- {
- if (is_overloaded_fn (id))
- {
- tree t = build_min (LOOKUP_EXPR, unknown_type_node,
- token, get_first_fn (id));
- if (id != IDENTIFIER_NAMESPACE_VALUE (token))
- TREE_OPERAND (t, 1) = error_mark_node;
- id = t;
- }
- else if (! TREE_PERMANENT (id) || TREE_CODE (id) == PARM_DECL
- || TREE_CODE (id) == USING_DECL)
- id = build_min (LOOKUP_EXPR, TREE_TYPE (id), token, error_mark_node);
- /* else just use the decl */
- }
+ /* We must look up dependent names when the template is
+ instantiated, not while parsing it. For now, we don't
+ distinguish between dependent and independent names. So, for
+ example, we look up all overloaded functions at
+ instantiation-time, even though in some cases we should just use
+ the DECL we have here. We also use LOOKUP_EXPRs to find things
+ like local variables, rather than creating TEMPLATE_DECLs for the
+ local variables and then finding matching instantiations. */
+ if (current_template_parms
+ && (is_overloaded_fn (id)
+ /* If it's not going to be around at instantiation time, we
+ look it up then. This is a hack, and should go when we
+ really get dependent/independent name lookup right. */
+ || !TREE_PERMANENT (id)
+ /* Some local VAR_DECLs (such as those for local variables
+ in member functions of local classes) are built on the
+ permanent obstack. */
+ || (TREE_CODE (id) == VAR_DECL
+ && CP_DECL_CONTEXT (id)
+ && TREE_CODE (CP_DECL_CONTEXT (id)) == FUNCTION_DECL)
+ || TREE_CODE (id) == PARM_DECL
+ || TREE_CODE (id) == RESULT_DECL
+ || TREE_CODE (id) == USING_DECL))
+ id = build_min_nt (LOOKUP_EXPR, token);
return id;
}
@@ -3027,17 +3059,17 @@ do_scoped_id (token, parsing)
{
if (processing_template_decl)
{
- id = build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
+ id = build_min_nt (LOOKUP_EXPR, token);
LOOKUP_EXPR_GLOBAL (id) = 1;
return id;
}
- if (parsing && (yychar == '(' || yychar == LEFT_RIGHT))
+ if (parsing && (yychar == '(' || yychar == LEFT_RIGHT)
+ && ! flag_strict_prototype)
id = implicitly_declare (token);
else
{
if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node)
- error ("undeclared variable `%s' (first use here)",
- IDENTIFIER_POINTER (token));
+ cp_error ("`::%D' undeclared (first use here)", token);
id = error_mark_node;
/* Prevent repeated error messages. */
SET_IDENTIFIER_NAMESPACE_VALUE (token, error_mark_node);
@@ -3064,9 +3096,9 @@ do_scoped_id (token, parsing)
{
if (is_overloaded_fn (id))
{
- id = build_min (LOOKUP_EXPR, unknown_type_node,
- token, get_first_fn (id));
+ id = build_min_nt (LOOKUP_EXPR, token);
LOOKUP_EXPR_GLOBAL (id) = 1;
+ return id;
}
/* else just use the decl */
}
@@ -3081,16 +3113,20 @@ identifier_typedecl_value (node)
type = IDENTIFIER_TYPE_VALUE (node);
if (type == NULL_TREE)
return NULL_TREE;
-#define do(X) \
- { \
- t = (X); \
- if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) \
- return t; \
- }
- do (IDENTIFIER_LOCAL_VALUE (node));
- do (IDENTIFIER_CLASS_VALUE (node));
- do (IDENTIFIER_NAMESPACE_VALUE (node));
-#undef do
+
+ if (IDENTIFIER_BINDING (node))
+ {
+ t = IDENTIFIER_VALUE (node);
+ if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
+ return t;
+ }
+ if (IDENTIFIER_NAMESPACE_VALUE (node))
+ {
+ t = IDENTIFIER_NAMESPACE_VALUE (node);
+ if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
+ return t;
+ }
+
/* Will this one ever happen? */
if (TYPE_MAIN_DECL (type))
return TYPE_MAIN_DECL (type);
@@ -3100,6 +3136,103 @@ identifier_typedecl_value (node)
return NULL_TREE;
}
+struct pf_args
+{
+ /* Input */
+ /* I/O */
+ char *p;
+ int c;
+ int imag;
+ tree type;
+ /* Output */
+ REAL_VALUE_TYPE value;
+};
+
+static void
+parse_float (data)
+ PTR data;
+{
+ struct pf_args * args = (struct pf_args *) data;
+ int fflag = 0, lflag = 0;
+ /* Copy token_buffer now, while it has just the number
+ and not the suffixes; once we add `f' or `i',
+ REAL_VALUE_ATOF may not work any more. */
+ char *copy = (char *) alloca (args->p - token_buffer + 1);
+ bcopy (token_buffer, copy, args->p - token_buffer + 1);
+
+ while (1)
+ {
+ int lose = 0;
+
+ /* Read the suffixes to choose a data type. */
+ switch (args->c)
+ {
+ case 'f': case 'F':
+ if (fflag)
+ error ("more than one `f' in numeric constant");
+ fflag = 1;
+ break;
+
+ case 'l': case 'L':
+ if (lflag)
+ error ("more than one `l' in numeric constant");
+ lflag = 1;
+ break;
+
+ case 'i': case 'I':
+ if (args->imag)
+ error ("more than one `i' or `j' in numeric constant");
+ else if (pedantic)
+ pedwarn ("ANSI C++ forbids imaginary numeric constants");
+ args->imag = 1;
+ break;
+
+ default:
+ lose = 1;
+ }
+
+ if (lose)
+ break;
+
+ if (args->p >= token_buffer + maxtoken - 3)
+ args->p = extend_token_buffer (args->p);
+ *(args->p++) = args->c;
+ *(args->p) = 0;
+ args->c = getch ();
+ }
+
+ /* The second argument, machine_mode, of REAL_VALUE_ATOF
+ tells the desired precision of the binary result
+ of decimal-to-binary conversion. */
+
+ if (fflag)
+ {
+ if (lflag)
+ error ("both `f' and `l' in floating constant");
+
+ args->type = float_type_node;
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ /* A diagnostic is required here by some ANSI C testsuites.
+ This is not pedwarn, become some people don't want
+ an error for this. */
+ if (REAL_VALUE_ISINF (args->value) && pedantic)
+ warning ("floating point number exceeds range of `float'");
+ }
+ else if (lflag)
+ {
+ args->type = long_double_type_node;
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ if (REAL_VALUE_ISINF (args->value) && pedantic)
+ warning ("floating point number exceeds range of `long double'");
+ }
+ else
+ {
+ args->value = REAL_VALUE_ATOF (copy, TYPE_MODE (args->type));
+ if (REAL_VALUE_ISINF (args->value) && pedantic)
+ warning ("floating point number exceeds range of `double'");
+ }
+}
+
int
real_yylex ()
{
@@ -3635,7 +3768,7 @@ real_yylex ()
int exceeds_double = 0;
int imag = 0;
REAL_VALUE_TYPE value;
- jmp_buf handler;
+ struct pf_args args;
/* Read explicit exponent if any, and put it in tokenbuf. */
@@ -3664,97 +3797,31 @@ real_yylex ()
*p = 0;
errno = 0;
+ /* Setup input for parse_float() */
+ args.p = p;
+ args.c = c;
+ args.imag = imag;
+ args.type = type;
+
/* Convert string to a double, checking for overflow. */
- if (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;
-
- default:
- lose = 1;
- }
-
- 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);
+ /* We got an exception from parse_float() */
+ error ("floating constant out of range");
+ value = dconst0;
}
+
+ /* Receive output from parse_float() */
+ p = args.p;
+ c = args.c;
+ imag = args.imag;
+ type = args.type;
+
#ifdef ERANGE
if (errno == ERANGE && pedantic)
{
@@ -3808,7 +3875,7 @@ real_yylex ()
{
if (spec_long_long)
error ("three `l's in integer constant");
- else if (pedantic)
+ else if (pedantic && ! in_system_header && warn_long_long)
pedwarn ("ANSI C++ forbids long long integer constants");
spec_long_long = 1;
}
@@ -3922,30 +3989,27 @@ real_yylex ()
{
register int result = 0;
register int num_chars = 0;
+ int chars_seen = 0;
unsigned width = TYPE_PRECISION (char_type_node);
int max_chars;
-
- if (wide_flag)
- {
- width = WCHAR_TYPE_SIZE;
#ifdef MULTIBYTE_CHARS
- max_chars = MB_CUR_MAX;
-#else
- max_chars = 1;
+ int longest_char = local_mb_cur_max ();
+ (void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
#endif
- }
- else
- max_chars = TYPE_PRECISION (integer_type_node) / width;
+
+ max_chars = TYPE_PRECISION (integer_type_node) / width;
+ if (wide_flag)
+ width = WCHAR_TYPE_SIZE;
while (1)
{
tryagain:
-
c = getch ();
if (c == '\'' || c == EOF)
break;
+ ++chars_seen;
if (c == '\\')
{
int ignore = 0;
@@ -3953,8 +4017,8 @@ real_yylex ()
if (ignore)
goto tryagain;
if (width < HOST_BITS_PER_INT
- && (unsigned) c >= (1 << width))
- warning ("escape sequence out of range for character");
+ && (unsigned) c >= ((unsigned)1 << width))
+ pedwarn ("escape sequence out of range for character");
#ifdef MAP_CHARACTER
if (ISPRINT (c))
c = MAP_CHARACTER (c);
@@ -3963,21 +4027,79 @@ real_yylex ()
else if (c == '\n')
{
if (pedantic)
- pedwarn ("ANSI C++ forbids newline in character constant");
+ pedwarn ("ANSI C forbids newline in character constant");
lineno++;
}
-#ifdef MAP_CHARACTER
else
- c = MAP_CHARACTER (c);
+ {
+#ifdef MULTIBYTE_CHARS
+ wchar_t wc;
+ int i;
+ int char_len = -1;
+ for (i = 1; i <= longest_char; ++i)
+ {
+ if (i > maxtoken - 4)
+ extend_token_buffer (token_buffer);
+
+ token_buffer[i] = c;
+ char_len = local_mbtowc (& wc,
+ token_buffer + 1,
+ i);
+ if (char_len != -1)
+ break;
+ c = getch ();
+ }
+ if (char_len > 1)
+ {
+ /* mbtowc sometimes needs an extra char before accepting */
+ if (char_len < i)
+ put_back (c);
+ if (! wide_flag)
+ {
+ /* Merge character into result; ignore excess chars. */
+ for (i = 1; i <= char_len; ++i)
+ {
+ if (i > max_chars)
+ break;
+ if (width < HOST_BITS_PER_INT)
+ result = (result << width)
+ | (token_buffer[i]
+ & ((1 << width) - 1));
+ else
+ result = token_buffer[i];
+ }
+ num_chars += char_len;
+ goto tryagain;
+ }
+ c = wc;
+ }
+ else
+ {
+ if (char_len == -1)
+ warning ("Ignoring invalid multibyte character");
+ if (wide_flag)
+ c = wc;
+#ifdef MAP_CHARACTER
+ else
+ c = MAP_CHARACTER (c);
#endif
+ }
+#else /* ! MULTIBYTE_CHARS */
+#ifdef MAP_CHARACTER
+ c = MAP_CHARACTER (c);
+#endif
+#endif /* ! MULTIBYTE_CHARS */
+ }
- num_chars++;
- if (num_chars > maxtoken - 4)
- extend_token_buffer (token_buffer);
-
- token_buffer[num_chars] = c;
+ if (wide_flag)
+ {
+ if (chars_seen == 1) /* only keep the first one */
+ result = c;
+ goto tryagain;
+ }
/* Merge character into result; ignore excess chars. */
+ num_chars++;
if (num_chars < max_chars + 1)
{
if (width < HOST_BITS_PER_INT)
@@ -3987,19 +4109,16 @@ real_yylex ()
}
}
- token_buffer[num_chars + 1] = '\'';
- token_buffer[num_chars + 2] = 0;
-
if (c != '\'')
error ("malformatted character constant");
- else if (num_chars == 0)
+ else if (chars_seen == 0)
error ("empty character constant");
else if (num_chars > max_chars)
{
num_chars = max_chars;
error ("character constant too long");
}
- else if (num_chars != 1 && warn_multichar)
+ else if (chars_seen != 1 && warn_multichar)
warning ("multi-character character constant");
/* If char type is signed, sign-extend the constant. */
@@ -4012,37 +4131,21 @@ real_yylex ()
else if (TREE_UNSIGNED (char_type_node)
|| ((result >> (num_bits - 1)) & 1) == 0)
yylval.ttype
- = 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)),
0);
else
yylval.ttype
- = 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)),
-1);
- if (num_chars<=1)
+ if (chars_seen <= 1)
TREE_TYPE (yylval.ttype) = char_type_node;
else
TREE_TYPE (yylval.ttype) = integer_type_node;
}
else
{
-#ifdef MULTIBYTE_CHARS
- /* Set the initial shift state and convert the next sequence. */
- result = 0;
- /* In all locales L'\0' is zero and mbtowc will return zero,
- so don't use it. */
- if (num_chars > 1
- || (num_chars == 1 && token_buffer[1] != '\0'))
- {
- wchar_t wc;
- (void) mbtowc (NULL, NULL, 0);
- if (mbtowc (& wc, token_buffer + 1, num_chars) == num_chars)
- result = wc;
- else
- warning ("Ignoring invalid multibyte character");
- }
-#endif
yylval.ttype = build_int_2 (result, 0);
TREE_TYPE (yylval.ttype) = wchar_type_node;
}
@@ -4055,6 +4158,12 @@ real_yylex ()
string_constant:
{
register char *p;
+ unsigned width = wide_flag ? WCHAR_TYPE_SIZE
+ : TYPE_PRECISION (char_type_node);
+#ifdef MULTIBYTE_CHARS
+ int longest_char = local_mb_cur_max ();
+ (void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
+#endif
c = getch ();
p = token_buffer + 1;
@@ -4068,9 +4177,8 @@ real_yylex ()
c = readescape (&ignore);
if (ignore)
goto skipnewline;
- if (!wide_flag
- && TYPE_PRECISION (char_type_node) < HOST_BITS_PER_INT
- && c >= ((unsigned) 1 << TYPE_PRECISION (char_type_node)))
+ if (width < HOST_BITS_PER_INT
+ && (unsigned) c >= ((unsigned)1 << width))
warning ("escape sequence out of range for character");
}
else if (c == '\n')
@@ -4079,10 +4187,72 @@ real_yylex ()
pedwarn ("ANSI C++ forbids newline in string constant");
lineno++;
}
+ else
+ {
+#ifdef MULTIBYTE_CHARS
+ wchar_t wc;
+ int i;
+ int char_len = -1;
+ for (i = 0; i < longest_char; ++i)
+ {
+ if (p + i >= token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ p[i] = c;
- if (p == token_buffer + maxtoken)
- p = extend_token_buffer (p);
- *p++ = c;
+ char_len = local_mbtowc (& wc, p, i + 1);
+ if (char_len != -1)
+ break;
+ c = getch ();
+ }
+ if (char_len == -1)
+ warning ("Ignoring invalid multibyte character");
+ else
+ {
+ /* mbtowc sometimes needs an extra char before accepting */
+ if (char_len <= i)
+ put_back (c);
+ if (! wide_flag)
+ {
+ p += (i + 1);
+ c = getch ();
+ continue;
+ }
+ c = wc;
+ }
+#endif /* MULTIBYTE_CHARS */
+ }
+
+ /* Add this single character into the buffer either as a wchar_t
+ or as a single byte. */
+ if (wide_flag)
+ {
+ unsigned width = TYPE_PRECISION (char_type_node);
+ unsigned bytemask = (1 << width) - 1;
+ int byte;
+
+ if (p + WCHAR_BYTES > token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+
+ for (byte = 0; byte < WCHAR_BYTES; ++byte)
+ {
+ int value;
+ if (byte >= (int) sizeof(c))
+ value = 0;
+ else
+ value = (c >> (byte * width)) & bytemask;
+ if (BYTES_BIG_ENDIAN)
+ p[WCHAR_BYTES - byte - 1] = value;
+ else
+ p[byte] = value;
+ }
+ p += WCHAR_BYTES;
+ }
+ else
+ {
+ if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ *p++ = c;
+ }
skipnewline:
c = getch ();
@@ -4091,56 +4261,36 @@ real_yylex ()
break;
}
}
- *p = 0;
-
- /* We have read the entire constant.
- Construct a STRING_CST for the result. */
+ /* Terminate the string value, either with a single byte zero
+ or with a wide zero. */
if (wide_flag)
{
- /* If this is a L"..." wide-string, convert the multibyte string
- to a wide character string. */
- char *widep = (char *) alloca ((p - token_buffer) * WCHAR_BYTES);
- int len;
-
-#ifdef MULTIBYTE_CHARS
- len = mbstowcs ((wchar_t *) widep, token_buffer + 1, p - token_buffer);
- if (len < 0 || len >= (p - token_buffer))
- {
- warning ("Ignoring invalid multibyte string");
- len = 0;
- }
- bzero (widep + (len * WCHAR_BYTES), WCHAR_BYTES);
-#else
- {
- char *wp, *cp;
-
- wp = widep + (BYTES_BIG_ENDIAN ? WCHAR_BYTES - 1 : 0);
- bzero (widep, (p - token_buffer) * WCHAR_BYTES);
- for (cp = token_buffer + 1; cp < p; cp++)
- *wp = *cp, wp += WCHAR_BYTES;
- len = p - token_buffer - 1;
- }
-#endif
- if (processing_template_decl)
- push_obstacks (&permanent_obstack, &permanent_obstack);
- yylval.ttype = build_string ((len + 1) * WCHAR_BYTES, widep);
- if (processing_template_decl)
- pop_obstacks ();
- TREE_TYPE (yylval.ttype) = wchar_array_type_node;
+ if (p + WCHAR_BYTES > token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ bzero (p, WCHAR_BYTES);
+ p += WCHAR_BYTES;
}
else
{
- if (processing_template_decl)
- push_obstacks (&permanent_obstack, &permanent_obstack);
- yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
- if (processing_template_decl)
- pop_obstacks ();
- TREE_TYPE (yylval.ttype) = char_array_type_node;
+ if (p >= token_buffer + maxtoken)
+ p = extend_token_buffer (p);
+ *p++ = 0;
}
- *p++ = '"';
- *p = 0;
+ /* We have read the entire constant.
+ Construct a STRING_CST for the result. */
+
+ if (processing_template_decl)
+ push_obstacks (&permanent_obstack, &permanent_obstack);
+ yylval.ttype = build_string (p - (token_buffer + 1), token_buffer + 1);
+ if (processing_template_decl)
+ pop_obstacks ();
+
+ if (wide_flag)
+ TREE_TYPE (yylval.ttype) = wchar_array_type_node;
+ else
+ TREE_TYPE (yylval.ttype) = char_array_type_node;
value = STRING; break;
}
@@ -4392,6 +4542,17 @@ 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;
@@ -4440,8 +4601,6 @@ build_lang_decl (code, name, type)
tree_node_counts[(int)lang_decl] += 1;
tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl);
#endif
-
- return t;
}
tree
@@ -4503,39 +4662,49 @@ make_lang_type (code)
{
extern struct obstack *current_obstack, *saveable_obstack;
register tree t = make_node (code);
- struct obstack *obstack = current_obstack;
- register int i = sizeof (struct lang_type) / sizeof (int);
- register int *pi;
/* Set up some flags that give proper default behavior. */
- IS_AGGR_TYPE (t) = 1;
+ if (IS_AGGR_TYPE_CODE (code))
+ {
+ struct obstack *obstack = current_obstack;
+ struct lang_type *pi;
- if (! TREE_PERMANENT (t))
- obstack = saveable_obstack;
- else
- my_friendly_assert (obstack == &permanent_obstack, 236);
+ SET_IS_AGGR_TYPE (t, 1);
- pi = (int *) obstack_alloc (obstack, sizeof (struct lang_type));
- while (i > 0)
- pi[--i] = 0;
+ if (! TREE_PERMANENT (t))
+ obstack = saveable_obstack;
+ else
+ my_friendly_assert (obstack == &permanent_obstack, 236);
+
+ pi = (struct lang_type *) obstack_alloc (obstack, sizeof (struct lang_type));
+ bzero ((char *) pi, (int) sizeof (struct lang_type));
- TYPE_LANG_SPECIFIC (t) = (struct lang_type *) 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,
- NULL_TREE);
- CLASSTYPE_BINFO_AS_LIST (t) = build_tree_list (NULL_TREE, TYPE_BINFO (t));
+ TYPE_LANG_SPECIFIC (t) = pi;
+ SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
+ CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
- /* Make sure this is laid out, for ease of use later.
- In the presence of parse errors, the normal was of assuring
- this might not ever get executed, so we lay it out *immediately*. */
- build_pointer_type (t);
+ /* Make sure this is laid out, for ease of use later. In the
+ presence of parse errors, the normal was of assuring this
+ might not ever get executed, so we lay it out *immediately*. */
+ build_pointer_type (t);
#ifdef GATHER_STATISTICS
- tree_node_counts[(int)lang_type] += 1;
- tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
+ tree_node_counts[(int)lang_type] += 1;
+ tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
#endif
+ }
+ else
+ /* We use TYPE_ALIAS_SET for the CLASSTYPE_MARKED bits. But,
+ TYPE_ALIAS_SET is initialized to -1 by default, so we must
+ 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;
}
@@ -4545,7 +4714,7 @@ dump_time_statistics ()
{
register tree prev = 0, decl, next;
int this_time = my_get_run_time ();
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
+= this_time - body_time;
fprintf (stderr, "\n******\n");
@@ -4564,22 +4733,31 @@ dump_time_statistics ()
for (decl = prev; decl; decl = IDENTIFIER_GLOBAL_VALUE (decl))
print_time (IDENTIFIER_POINTER (decl),
- TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (decl)));
+ TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (decl)));
}
void
-compiler_error (s, v, v2)
- char *s;
- HOST_WIDE_INT v, v2; /* @@also used as pointer */
+compiler_error VPROTO ((const char *msg, ...))
{
+#ifndef ANSI_PROTOTYPES
+ const char *msg;
+#endif
char buf[1024];
- sprintf (buf, s, v, v2);
+ va_list ap;
+
+ VA_START (ap, msg);
+
+#ifndef ANSI_PROTOTYPES
+ msg = va_arg (ap, const char *);
+#endif
+
+ vsprintf (buf, msg, ap);
error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
}
void
yyerror (string)
- char *string;
+ const char *string;
{
extern int end_of_file;
char buf[200];
@@ -4598,7 +4776,7 @@ yyerror (string)
strcat (buf, " before string constant");
else if (token_buffer[0] == '\'')
strcat (buf, " before character constant");
- else if (token_buffer[0] < 040 || (unsigned char) token_buffer[0] >= 0177)
+ else if (!ISGRAPH ((unsigned char)token_buffer[0]))
sprintf (buf + strlen (buf), " before character 0%o",
(unsigned char) token_buffer[0]);
else
@@ -4609,7 +4787,7 @@ yyerror (string)
static int
handle_cp_pragma (pname)
- char *pname;
+ const char *pname;
{
register int token;
@@ -4655,7 +4833,8 @@ handle_cp_pragma (pname)
}
else if (! strcmp (pname, "interface"))
{
- tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
+ tree fileinfo
+ = TIME_IDENTIFIER_FILEINFO (get_time_identifier (input_filename));
char *main_filename = input_filename;
main_filename = file_name_nondirectory (main_filename);
@@ -4677,7 +4856,6 @@ handle_cp_pragma (pname)
if (token != END_OF_LINE)
warning ("garbage after `#pragma interface' ignored");
-#ifndef NO_LINKAGE_HEURISTICS
write_virtuals = 3;
if (impl_file_chain == 0)
@@ -4690,7 +4868,7 @@ handle_cp_pragma (pname)
#ifdef AUTO_IMPLEMENT
filename = file_name_nondirectory (main_input_filename);
fi = get_time_identifier (filename);
- fi = IDENTIFIER_CLASS_VALUE (fi);
+ fi = TIME_IDENTIFIER_FILEINFO (fi);
TREE_INT_CST_LOW (fi) = 0;
TREE_INT_CST_HIGH (fi) = 1;
/* Get default. */
@@ -4701,16 +4879,21 @@ handle_cp_pragma (pname)
}
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;
-#endif /* NO_LINKAGE_HEURISTICS */
return 1;
}
else if (! strcmp (pname, "implementation"))
{
- tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
+ 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);
@@ -4730,7 +4913,6 @@ handle_cp_pragma (pname)
if (token != END_OF_LINE)
warning ("garbage after `#pragma implementation' ignored");
-#ifndef NO_LINKAGE_HEURISTICS
if (write_virtuals == 3)
{
struct impl_files *ifiles = impl_file_chain;
@@ -4775,25 +4957,43 @@ handle_cp_pragma (pname)
#endif
TREE_INT_CST_LOW (fileinfo) = interface_only;
TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
-#endif /* NO_LINKAGE_HEURISTICS */
return 1;
}
return 0;
}
+
+/* Return the type-qualifier corresponding to the identifier given by
+ RID. */
+
+int
+cp_type_qual_from_rid (rid)
+ tree rid;
+{
+ if (rid == ridpointers[(int) RID_CONST])
+ return TYPE_QUAL_CONST;
+ else if (rid == ridpointers[(int) RID_VOLATILE])
+ return TYPE_QUAL_VOLATILE;
+ else if (rid == ridpointers[(int) RID_RESTRICT])
+ return TYPE_QUAL_RESTRICT;
+
+ my_friendly_abort (0);
+ return TYPE_UNQUALIFIED;
+}
+
-#ifdef HANDLE_SYSV_PRAGMA
+#ifdef HANDLE_GENERIC_PRAGMAS
-/* Handle a #pragma directive. INPUT is the current input stream,
- and C is a character to reread. Processes the entire input line
- and returns a character for the caller to reread: either \n or EOF. */
+/* 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_sysv_pragma (token)
+handle_generic_pragma (token)
register int token;
{
for (;;)
@@ -4802,32 +5002,24 @@ handle_sysv_pragma (token)
{
case IDENTIFIER:
case TYPENAME:
- case STRING:
- case CONSTANT:
- handle_pragma_token ("ignored", yylval.ttype);
- break;
- case '(':
- handle_pragma_token ("(", NULL_TREE);
- break;
- case ')':
- handle_pragma_token (")", NULL_TREE);
- break;
- case ',':
- handle_pragma_token (",", NULL_TREE);
- break;
- case '=':
- handle_pragma_token ("=", NULL_TREE);
+ 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 (NULL_PTR, NULL_TREE);
- return 1;
+ handle_pragma_token (token_buffer, NULL_TREE);
}
+
token = real_yylex ();
}
}
-#endif /* HANDLE_SYSV_PRAGMA */
+#endif /* HANDLE_GENERIC_PRAGMAS */
OpenPOWER on IntegriCloud