aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/lex.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/lex.c')
-rw-r--r--gcc/cp/lex.c637
1 files changed, 358 insertions, 279 deletions
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 77ea80eb745..5cccdbe2292 100644
--- a/gcc/cp/lex.c
+++ b/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 "function.h"
@@ -56,18 +55,16 @@ 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 void feed_defarg PROTO((tree, tree));
@@ -75,7 +72,7 @@ static int set_vardecl_interface_info PROTO((tree, tree));
static void store_pending_inline PROTO((tree, struct pending_inline *));
static void reinit_parse_for_expr PROTO((struct obstack *));
static int *init_cpp_parse PROTO((void));
-static int handle_cp_pragma PROTO((char *));
+static int handle_cp_pragma PROTO((const char *));
#ifdef HANDLE_GENERIC_PRAGMAS
static int handle_generic_pragma PROTO((int));
#endif
@@ -85,12 +82,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)
@@ -98,7 +99,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
@@ -314,7 +315,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);
@@ -323,12 +324,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 ();
@@ -378,7 +380,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"
};
@@ -389,6 +391,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;
}
@@ -396,11 +404,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);
@@ -426,7 +437,7 @@ lang_identify ()
return "cplusplus";
}
-void
+static void
init_filename_times ()
{
this_filename_time = get_time_identifier ("<top level>");
@@ -434,7 +445,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;
}
}
@@ -483,12 +495,15 @@ init_parse (filename)
#endif
#if USE_CPPLIB
- yy_cur = "\n";
- yy_lim = yy_cur + 1;
-
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, "-"))
@@ -643,7 +658,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,
@@ -710,6 +725,9 @@ init_parse (filename)
ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOLATILE],
build_tree_list (NULL_TREE, ridpointers[(int) RID_VOLATILE]));
+ ridpointers[(int) RID_RESTRICT] = get_identifier ("__restrict");
+ SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_RESTRICT],
+ build_tree_list (NULL_TREE, ridpointers[(int) RID_RESTRICT]));
ridpointers[(int) RID_AUTO] = get_identifier ("auto");
SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_AUTO],
build_tree_list (NULL_TREE, ridpointers[(int) RID_AUTO]));
@@ -1138,7 +1156,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);
}
@@ -1148,15 +1166,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)
@@ -1189,7 +1207,7 @@ set_typedecl_interface_info (prev, vars)
tree prev ATTRIBUTE_UNUSED, vars;
{
tree id = get_time_identifier (DECL_SOURCE_FILE (vars));
- tree fileinfo = IDENTIFIER_CLASS_VALUE (id);
+ tree fileinfo = TIME_IDENTIFIER_FILEINFO (id);
tree type = TREE_TYPE (vars);
CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
@@ -1215,6 +1233,37 @@ set_vardecl_interface_info (prev, vars)
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
@@ -1224,7 +1273,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)
@@ -1251,32 +1299,7 @@ do_pending_inlines ()
return;
/* Now start processing the first inline function. */
- context = hack_decl_function_context (t->fndecl);
- if (context)
- push_function_context_to (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;
@@ -1292,7 +1315,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 ();
if (context)
pop_function_context_from (context);
i = i->next;
@@ -1310,24 +1332,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_function_context_to (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 ();
}
@@ -1553,6 +1559,8 @@ 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;
}
@@ -1991,7 +1999,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
@@ -2009,7 +2017,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];
@@ -2127,7 +2135,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;
}
@@ -2196,7 +2204,7 @@ skip_white_space (c)
static char *
extend_token_buffer (p)
- char *p;
+ const char *p;
{
int offset = p - token_buffer;
@@ -2255,13 +2263,12 @@ pragma_ungetc (arg)
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. */
@@ -2291,7 +2298,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')
{
@@ -2370,7 +2377,10 @@ check_newline ()
&& getch () == 'n'
&& getch () == 'e'
&& ((c = getch ()) == ' ' || c == '\t'))
- goto linenum;
+ {
+ saw_line = 1;
+ goto linenum;
+ }
}
else if (c == 'i')
{
@@ -2467,9 +2477,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)
@@ -2486,7 +2503,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;
@@ -2776,7 +2793,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);
@@ -2805,6 +2822,10 @@ identifier_type (decl)
}
if (looking_for_template && really_overloaded_fn (decl))
{
+ /* 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;
@@ -2909,8 +2930,7 @@ do_identifier (token, parsing, args)
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;
}
@@ -2919,11 +2939,9 @@ 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] */
@@ -2936,18 +2954,19 @@ do_identifier (token, parsing, args)
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;
- }
+ if (id == error_mark_node)
+ {
+ /* lookup_name quietly returns error_mark_node if we're parsing,
+ as we don't want to complain about an identifier that ends up
+ being used as a declarator. So we call it again to get the error
+ message. */
+ id = lookup_name (token, 0);
+ return error_mark_node;
+ }
+
+ if (!id)
+ {
if (current_template_parms)
return build_min_nt (LOOKUP_EXPR, token);
else if (IDENTIFIER_OPNAME_P (token))
@@ -3030,24 +3049,10 @@ 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
- /* Really, if we're processing a template, we just want to
- resolve template parameters, and not enumeration
- constants. But, they're hard to tell apart. (Note that
- a non-type template parameter may have enumeration type.)
- Fortunately, there's no harm in resolving *global*
- enumeration constants, since they can't depend on
- template parameters. */
- || (TREE_CODE (CP_DECL_CONTEXT (id)) == NAMESPACE_DECL
- && 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
@@ -3074,6 +3079,7 @@ do_identifier (token, parsing, args)
&& 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);
@@ -3158,16 +3164,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);
@@ -3177,6 +3187,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 ()
{
@@ -3712,7 +3819,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. */
@@ -3741,97 +3848,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)
{
@@ -4221,15 +4262,13 @@ real_yylex ()
/* mbtowc sometimes needs an extra char before accepting */
if (char_len <= i)
put_back (c);
- if (wide_flag)
+ if (! wide_flag)
{
- *(wchar_t *)p = wc;
- p += sizeof (wc);
+ p += (i + 1);
+ c = getch ();
+ continue;
}
- else
- p += (i + 1);
- c = getch ();
- continue;
+ c = wc;
}
#endif /* MULTIBYTE_CHARS */
}
@@ -4554,6 +4593,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;
@@ -4602,8 +4652,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
@@ -4665,38 +4713,46 @@ 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);
- CLASSTYPE_BINFO_AS_LIST (t) = build_tree_list (NULL_TREE, TYPE_BINFO (t));
+ TYPE_LANG_SPECIFIC (t) = pi;
+ CLASSTYPE_AS_LIST (t) = build_expr_list (NULL_TREE, t);
+ SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
+ CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
+ TYPE_BINFO (t) = make_binfo (integer_zero_node, t, NULL_TREE, NULL_TREE);
+ CLASSTYPE_BINFO_AS_LIST (t)
+ = build_tree_list (NULL_TREE, TYPE_BINFO (t));
- /* Make sure this is laid out, for ease of use later.
- In the presence of parse errors, the normal was of assuring
- this 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;
return t;
}
@@ -4706,7 +4762,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");
@@ -4725,22 +4781,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];
@@ -4759,7 +4824,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
@@ -4770,7 +4835,7 @@ yyerror (string)
static int
handle_cp_pragma (pname)
- char *pname;
+ const char *pname;
{
register int token;
@@ -4816,7 +4881,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);
@@ -4838,7 +4904,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)
@@ -4851,7 +4916,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. */
@@ -4862,16 +4927,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);
@@ -4891,7 +4961,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;
@@ -4936,13 +5005,31 @@ 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_GENERIC_PRAGMAS
@@ -4963,29 +5050,21 @@ handle_generic_pragma (token)
{
case IDENTIFIER:
case TYPENAME:
- case STRING:
- case CONSTANT:
- handle_pragma_token (IDENTIFIER_POINTER(yylval.ttype), 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:
- default:
return handle_pragma_token (NULL_PTR, NULL_TREE);
+
+ default:
+ handle_pragma_token (token_buffer, NULL);
}
token = real_yylex ();