/* Separate lexical analyzer for GNU C++.
Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
/* This file is the lexical analyzer for GNU C++. */
-/* Cause the `yydebug' variable to be defined. */
-#define YYDEBUG 1
-
#include "config.h"
#include "system.h"
#include "input.h"
#include "tree.h"
#include "cp-tree.h"
#include "cpplib.h"
-#include "c-lex.h"
#include "lex.h"
#include "parse.h"
#include "flags.h"
static int interface_strcmp PARAMS ((const char *));
static int *init_cpp_parse PARAMS ((void));
-static void init_reswords PARAMS ((void));
static void init_cp_pragma PARAMS ((void));
static tree parse_strconst_pragma PARAMS ((const char *, int));
static void handle_pragma_unit PARAMS ((cpp_reader *));
static void handle_pragma_interface PARAMS ((cpp_reader *));
static void handle_pragma_implementation PARAMS ((cpp_reader *));
-static void cxx_init PARAMS ((void));
-static void cxx_finish PARAMS ((void));
-static void cxx_init_options PARAMS ((void));
-static void cxx_post_options PARAMS ((void));
+static void handle_pragma_java_exceptions PARAMS ((cpp_reader *));
#ifdef GATHER_STATISTICS
#ifdef REDUCE_LENGTH
#endif
static int is_global PARAMS ((tree));
static void init_operators PARAMS ((void));
+static void copy_lang_type PARAMS ((tree));
/* A constraint that can be tested at compile time. */
#ifdef __STDC__
#include "cpplib.h"
-/* Pending language change.
- Positive is push count, negative is pop count. */
-int pending_lang_change = 0;
-
extern int yychar; /* the lookahead symbol */
extern YYSTYPE yylval; /* the semantic value of the */
/* lookahead symbol */
if (target && TREE_CODE (target) == IDENTIFIER_NODE
&& ANON_AGGRNAME_P (target))
error ("type name expected before `*'");
- target = build_parse_node (INDIRECT_REF, target);
+ target = build_nt (INDIRECT_REF, target);
TREE_TYPE (target) = cv_qualifiers;
return target;
}
if (TREE_CODE (target) == IDENTIFIER_NODE && ANON_AGGRNAME_P (target))
error ("type name expected before `&'");
}
- target = build_parse_node (ADDR_EXPR, target);
+ target = build_nt (ADDR_EXPR, target);
TREE_TYPE (target) = cv_qualifiers;
return target;
}
make_call_declarator (target, parms, cv_qualifiers, exception_specification)
tree target, parms, cv_qualifiers, exception_specification;
{
- target = build_parse_node (CALL_EXPR, target,
- tree_cons (parms, cv_qualifiers, NULL_TREE),
- /* The third operand is really RTL. We
- shouldn't put anything there. */
- NULL_TREE);
+ target = build_nt (CALL_EXPR, target,
+ tree_cons (parms, cv_qualifiers, NULL_TREE),
+ /* The third operand is really RTL. We
+ shouldn't put anything there. */
+ NULL_TREE);
CALL_DECLARATOR_EXCEPTION_SPEC (target) = exception_specification;
return target;
}
int interface_unknown; /* whether or not we know this class
to behave according to #pragma interface. */
-/* Tree code classes. */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
-
-static char cplus_tree_code_type[] = {
- 'x',
-#include "cp-tree.def"
-};
-#undef DEFTREECODE
-
-/* Table indexed by tree code giving number of expression
- operands beyond the fixed part of the node structure.
- Not used for types or decls. */
-
-#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
-
-static int cplus_tree_code_length[] = {
- 0,
-#include "cp-tree.def"
-};
-#undef DEFTREECODE
-
-/* Names of tree components.
- Used for printing out the tree and error messages. */
-#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
-
-static const char *cplus_tree_code_name[] = {
- "@@dummy",
-#include "cp-tree.def"
-};
-#undef DEFTREECODE
\f
-/* Each front end provides its own hooks, for toplev.c. */
-struct lang_hooks lang_hooks = {cxx_init,
- cxx_finish,
- cxx_init_options,
- cxx_decode_option,
- cxx_post_options};
-
-/* Post-switch processing. */
-static void
-cxx_post_options ()
-{
- cpp_post_options (parse_in);
-}
-
-static void
+/* Initialization before switch parsing. */
+void
cxx_init_options ()
{
- parse_in = cpp_create_reader (CLK_GNUCXX);
+ c_common_init_options (clk_cplusplus);
/* Default exceptions on. */
flag_exceptions = 1;
- /* Mark as "unspecified". */
- flag_bounds_check = -1;
/* By default wrap lines at 80 characters. Is getenv ("COLUMNS")
preferable? */
- diagnostic_message_length_per_line = 80;
+ diagnostic_line_cutoff (global_dc) = 80;
/* By default, emit location information once for every
diagnostic message. */
- set_message_prefixing_rule (DIAGNOSTICS_SHOW_PREFIX_ONCE);
-}
-
-static void
-cxx_init ()
-{
- c_common_lang_init ();
-
- if (flag_gnu_xref) GNU_xref_begin (input_filename);
- init_repo (input_filename);
+ diagnostic_prefixing_rule (global_dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
}
-static void
+void
cxx_finish ()
{
- if (flag_gnu_xref) GNU_xref_end (errorcount+sorrycount);
-}
-
-const char *
-lang_identify ()
-{
- return "cplusplus";
+ c_common_finish ();
}
static int *
/* Initialize data structures that keep track of operator names. */
-#define DEF_OPERATOR(NAME, C, NM, OM, AR, AP) \
+#define DEF_OPERATOR(NAME, C, M, AR, AP) \
CONSTRAINT (C, sizeof "operator " + sizeof NAME <= 256);
#include "operators.def"
#undef DEF_OPERATOR
char buffer[256];
struct operator_name_info_t *oni;
-#define DEF_OPERATOR(NAME, CODE, NEW_MANGLING, OLD_MANGLING, ARITY, ASSN_P) \
+#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, ASSN_P) \
sprintf (buffer, ISALPHA (NAME[0]) ? "operator %s" : "operator%s", NAME); \
identifier = get_identifier (buffer); \
IDENTIFIER_OPNAME_P (identifier) = 1; \
: &operator_name_info[(int) CODE]); \
oni->identifier = identifier; \
oni->name = NAME; \
- oni->mangled_name = flag_new_abi ? NEW_MANGLING : OLD_MANGLING;
+ oni->mangled_name = MANGLING;
#include "operators.def"
#undef DEF_OPERATOR
/* The reserved keyword table. */
struct resword
{
- const char *word;
- ENUM_BITFIELD(rid) rid : 16;
- unsigned int disable : 16;
+ const char *const word;
+ const ENUM_BITFIELD(rid) rid : 16;
+ const unsigned int disable : 16;
};
/* Disable mask. Keywords are disabled if (reswords[i].disable & mask) is
static const struct resword reswords[] =
{
{ "_Complex", RID_COMPLEX, 0 },
+ { "__FUNCTION__", RID_FUNCTION_NAME, 0 },
+ { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
{ "__alignof", RID_ALIGNOF, 0 },
{ "__alignof__", RID_ALIGNOF, 0 },
{ "__asm", RID_ASM, 0 },
{ "__const", RID_CONST, 0 },
{ "__const__", RID_CONST, 0 },
{ "__extension__", RID_EXTENSION, 0 },
+ { "__func__", RID_C99_FUNCTION_NAME, 0 },
{ "__imag", RID_IMAGPART, 0 },
{ "__imag__", RID_IMAGPART, 0 },
{ "__inline", RID_INLINE, 0 },
{ "__restrict__", RID_RESTRICT, 0 },
{ "__signed", RID_SIGNED, 0 },
{ "__signed__", RID_SIGNED, 0 },
+ { "__thread", RID_THREAD, 0 },
{ "__typeof", RID_TYPEOF, 0 },
{ "__typeof__", RID_TYPEOF, 0 },
{ "__volatile", RID_VOLATILE, 0 },
{ "xor_eq", RID_XOR_EQ, D_OPNAME },
};
-#define N_reswords (sizeof reswords / sizeof (struct resword))
/* Table mapping from RID_* constants to yacc token numbers.
Unfortunately we have to have entries for all the keywords in all
/* RID_BOUNDED */ 0,
/* RID_UNBOUNDED */ 0,
/* RID_COMPLEX */ TYPESPEC,
+ /* RID_THREAD */ SCSPEC,
/* C++ */
/* RID_FRIEND */ SCSPEC,
/* RID_PTRBASE */ 0,
/* RID_PTREXTENT */ 0,
/* RID_PTRVALUE */ 0,
+ /* RID_CHOOSE_EXPR */ 0,
+ /* RID_TYPES_COMPATIBLE_P */ 0,
+
+ /* RID_FUNCTION_NAME */ VAR_FUNC_NAME,
+ /* RID_PRETTY_FUNCTION_NAME */ VAR_FUNC_NAME,
+ /* RID_c99_FUNCTION_NAME */ VAR_FUNC_NAME,
/* C++ */
/* RID_BOOL */ TYPESPEC,
/* RID_AT_IMPLEMENTATION */ 0
};
-static void
+void
init_reswords ()
{
unsigned int i;
all the trees it points to are permanently interned in the
get_identifier hash anyway. */
ridpointers = (tree *) xcalloc ((int) RID_MAX, sizeof (tree));
- for (i = 0; i < N_reswords; i++)
+ for (i = 0; i < ARRAY_SIZE (reswords); i++)
{
id = get_identifier (reswords[i].word);
C_RID_CODE (id) = reswords[i].rid;
cpp_register_pragma (parse_in, 0, "implementation",
handle_pragma_implementation);
- cpp_register_pragma_space (parse_in, "GCC");
cpp_register_pragma (parse_in, "GCC", "interface", handle_pragma_interface);
cpp_register_pragma (parse_in, "GCC", "implementation",
handle_pragma_implementation);
+ cpp_register_pragma (parse_in, "GCC", "java_exceptions",
+ handle_pragma_java_exceptions);
}
+/* Initialize the C++ front end. This function is very sensitive to
+ the exact order that things are done here. It would be nice if the
+ initialization done by this routine were moved to its subroutines,
+ and the ordering dependencies clarified and reduced. */
const char *
-init_parse (filename)
+cxx_init (filename)
const char *filename;
{
- /* Make identifier nodes long enough for the language-specific slots. */
- set_identifier_size (sizeof (struct lang_identifier));
- decl_printable_name = lang_printable_name;
-
input_filename = "<internal>";
init_reswords ();
- init_pragma ();
- init_cp_pragma ();
init_spew ();
init_tree ();
- init_cplus_expand ();
init_cp_semantics ();
-
- add_c_tree_codes ();
-
- memcpy (tree_code_type + (int) LAST_C_TREE_CODE,
- cplus_tree_code_type,
- (int)LAST_CPLUS_TREE_CODE - (int)LAST_C_TREE_CODE);
- memcpy (tree_code_length + (int) LAST_C_TREE_CODE,
- cplus_tree_code_length,
- (LAST_CPLUS_TREE_CODE - (int)LAST_C_TREE_CODE) * sizeof (int));
- memcpy (tree_code_name + (int) LAST_C_TREE_CODE,
- cplus_tree_code_name,
- (LAST_CPLUS_TREE_CODE - (int)LAST_C_TREE_CODE) * sizeof (char *));
-
init_operators ();
init_method ();
init_error ();
TREE_TYPE (enum_type_node) = enum_type_node;
ridpointers[(int) RID_ENUM] = enum_type_node;
- /* Create the built-in __null node. Note that we can't yet call for
- type_for_size here because integer_type_node and so forth are not
- set up. Therefore, we don't set the type of these nodes until
- init_decl_processing. */
+ cxx_init_decl_processing ();
+
+ /* Create the built-in __null node. */
null_node = build_int_2 (0, 0);
+ TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
ridpointers[RID_NULL] = null_node;
token_count = init_cpp_parse ();
interface_unknown = 1;
- return init_c_lex (filename);
-}
+ filename = c_common_init (filename);
+ if (filename == NULL)
+ return NULL;
-void
-finish_parse ()
-{
- cpp_finish (parse_in);
- errorcount += parse_in->errors;
+ init_cp_pragma ();
+
+ init_repo (filename);
+
+ return filename;
}
\f
inline void
else if (yylval.ttype == enum_type_node)
fprintf (file, " `enum'");
else
- my_friendly_abort (80);
+ abort ();
break;
case CONSTANT:
int *token_count;
#if 0
-#define REDUCE_LENGTH (sizeof (yyr2) / sizeof (yyr2[0]))
-#define TOKEN_LENGTH (256 + sizeof (yytname) / sizeof (yytname[0]))
+#define REDUCE_LENGTH ARRAY_SIZE (yyr2)
+#define TOKEN_LENGTH (256 + ARRAY_SIZE (yytname))
#endif
#ifdef GATHER_STATISTICS
#endif
}
-/* Sets the value of the 'yydebug' variable to VALUE.
- This is a function so we don't have to have YYDEBUG defined
- in order to build the compiler. */
-
-void
-set_yydebug (value)
- int value;
-{
-#if YYDEBUG != 0
- extern int yydebug;
- yydebug = value;
-#else
- warning ("YYDEBUG not defined.");
-#endif
-}
-
/* Helper function to load global variables with interface
information. */
interface_only = finfo->interface_only;
interface_unknown = finfo->interface_unknown;
-
- /* This happens to be a convenient place to put this. */
- if (flag_gnu_xref) GNU_xref_file (input_filename);
}
/* Return nonzero if S is not considered part of an
&& yychar != SELFNAME)
|| yychar == 0 /* EOF */)
{
- if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
+ if (TYPE_ANONYMOUS_P (type))
error ("semicolon missing after %s declaration",
TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct");
else
- cp_error ("semicolon missing after declaration of `%T'", type);
+ error ("semicolon missing after declaration of `%T'", type);
shadow_tag (build_tree_list (0, type));
}
/* Could probably also hack cases where class { ... } f (); appears. */
tree type;
{
if (!TYPE_P (type))
- my_friendly_abort (60);
+ abort ();
if (CLASS_TYPE_P (type))
CLASSTYPE_GOT_SEMICOLON (type) = 1;
}
for (link = declspecs; link; link = TREE_CHAIN (link))
{
tree type = TREE_VALUE (link);
- if (TYPE_P (type))
+ if (type && TYPE_P (type))
note_got_semicolon (type);
}
clear_anon_tags ();
handle_pragma_vtable (dfile)
cpp_reader *dfile ATTRIBUTE_UNUSED;
{
- tree vtbl = parse_strconst_pragma ("vtable", 0);
-
- if (vtbl && vtbl != (tree)-1)
- pending_vtables = tree_cons (NULL_TREE,
- get_identifier (TREE_STRING_POINTER (vtbl)),
- pending_vtables);
+ parse_strconst_pragma ("vtable", 0);
+ sorry ("#pragma vtable no longer supported");
}
static void
if (fname == (tree)-1)
return;
else if (fname == 0)
- main_filename = file_name_nondirectory (input_filename);
+ main_filename = lbasename (input_filename);
else
main_filename = TREE_STRING_POINTER (fname);
main_filename = main_input_filename;
else
main_filename = input_filename;
- main_filename = file_name_nondirectory (main_filename);
+ main_filename = lbasename (main_filename);
}
else
{
}
}
+/* Indicate that this file uses Java-personality exception handling. */
+static void
+handle_pragma_java_exceptions (dfile)
+ cpp_reader *dfile ATTRIBUTE_UNUSED;
+{
+ tree x;
+ if (c_lex (&x) != CPP_EOF)
+ warning ("junk at end of #pragma GCC java_exceptions");
+
+ choose_personality_routine (lang_java);
+}
+
void
do_pending_lang_change ()
{
else
id = lastiddecl;
+ if (lexing && id && TREE_DEPRECATED (id))
+ warn_deprecated_use (id);
+
/* Do Koenig lookup if appropriate (inside templates we build lookup
expressions instead).
{
if (current_template_parms)
return build_min_nt (LOOKUP_EXPR, token);
+ else if (IDENTIFIER_TYPENAME_P (token))
+ /* A templated conversion operator might exist. */
+ return token;
else if (IDENTIFIER_OPNAME_P (token))
{
if (token != ansi_opname (ERROR_MARK))
- cp_error ("`%D' not defined", token);
+ error ("`%D' not defined", token);
id = error_mark_node;
}
else if (current_function_decl == 0)
{
- cp_error ("`%D' was not declared in this scope", token);
+ error ("`%D' was not declared in this scope", token);
id = error_mark_node;
}
else
{
static int undeclared_variable_notice;
- cp_error ("`%D' undeclared (first use this function)", token);
+ error ("`%D' undeclared (first use this function)", token);
if (! undeclared_variable_notice)
{
id = IDENTIFIER_GLOBAL_VALUE (token);
if (parsing && yychar == YYEMPTY)
yychar = yylex ();
- if (! id)
+ if (!id || (TREE_CODE (id) == FUNCTION_DECL
+ && DECL_ANTICIPATED (id)))
{
if (processing_template_decl)
{
return id;
}
if (IDENTIFIER_NAMESPACE_VALUE (token) != error_mark_node)
- cp_error ("`::%D' undeclared (first use here)", token);
+ error ("`::%D' undeclared (first use here)", token);
id = error_mark_node;
/* Prevent repeated error messages. */
SET_IDENTIFIER_NAMESPACE_VALUE (token, error_mark_node);
ld = (struct lang_decl *) ggc_alloc_cleared (size);
+ ld->decl_flags.can_be_full = CAN_HAVE_FULL_LANG_DECL_P (t) ? 1 : 0;
+ ld->decl_flags.u1sel = TREE_CODE (t) == NAMESPACE_DECL ? 1 : 0;
+ ld->decl_flags.u2sel = 0;
+ if (ld->decl_flags.can_be_full)
+ ld->u.f.u3sel = TREE_CODE (t) == FUNCTION_DECL ? 1 : 0;
+
DECL_LANG_SPECIFIC (t) = ld;
if (current_lang_name == lang_name_cplusplus)
- DECL_LANGUAGE (t) = lang_cplusplus;
+ SET_DECL_LANGUAGE (t, lang_cplusplus);
else if (current_lang_name == lang_name_c)
- DECL_LANGUAGE (t) = lang_c;
+ SET_DECL_LANGUAGE (t, lang_c);
else if (current_lang_name == lang_name_java)
- DECL_LANGUAGE (t) = lang_java;
- else my_friendly_abort (64);
+ SET_DECL_LANGUAGE (t, lang_java);
+ else abort ();
#ifdef GATHER_STATISTICS
tree_node_counts[(int)lang_decl] += 1;
}
void
-copy_lang_decl (node)
+cxx_dup_lang_specific_decl (node)
tree node;
{
int size;
ld = (struct lang_decl *) ggc_alloc (size);
memcpy (ld, DECL_LANG_SPECIFIC (node), size);
DECL_LANG_SPECIFIC (node) = ld;
+
+#ifdef GATHER_STATISTICS
+ tree_node_counts[(int)lang_decl] += 1;
+ tree_node_sizes[(int)lang_decl] += size;
+#endif
}
/* Copy DECL, including any language-specific parts. */
tree copy;
copy = copy_node (decl);
- copy_lang_decl (copy);
+ cxx_dup_lang_specific_decl (copy);
+ return copy;
+}
+
+/* Replace the shared language-specific parts of NODE with a new copy. */
+
+static void
+copy_lang_type (node)
+ tree node;
+{
+ int size;
+ struct lang_type *lt;
+
+ if (! TYPE_LANG_SPECIFIC (node))
+ return;
+
+ if (TYPE_LANG_SPECIFIC (node)->u.h.is_lang_type_class)
+ size = sizeof (struct lang_type);
+ else
+ size = sizeof (struct lang_type_ptrmem);
+ lt = (struct lang_type *) ggc_alloc (size);
+ memcpy (lt, TYPE_LANG_SPECIFIC (node), size);
+ TYPE_LANG_SPECIFIC (node) = lt;
+
+#ifdef GATHER_STATISTICS
+ tree_node_counts[(int)lang_type] += 1;
+ tree_node_sizes[(int)lang_type] += size;
+#endif
+}
+
+/* Copy TYPE, including any language-specific parts. */
+
+tree
+copy_type (type)
+ tree type;
+{
+ tree copy;
+
+ copy = copy_node (type);
+ copy_lang_type (copy);
return copy;
}
tree
-cp_make_lang_type (code)
+cxx_make_type (code)
enum tree_code code;
{
register tree t = make_node (code);
- /* Set up some flags that give proper default behavior. */
- if (IS_AGGR_TYPE_CODE (code))
+ /* Create lang_type structure. */
+ if (IS_AGGR_TYPE_CODE (code)
+ || code == BOUND_TEMPLATE_TEMPLATE_PARM)
{
struct lang_type *pi;
ggc_alloc_cleared (sizeof (struct lang_type)));
TYPE_LANG_SPECIFIC (t) = pi;
+ pi->u.c.h.is_lang_type_class = 1;
+
+#ifdef GATHER_STATISTICS
+ tree_node_counts[(int)lang_type] += 1;
+ tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
+#endif
+ }
+
+ /* Set up some flags that give proper default behavior. */
+ if (IS_AGGR_TYPE_CODE (code))
+ {
SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, interface_unknown);
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
presence of parse errors, the normal was of assuring this
might not ever get executed, so we lay it out *immediately*. */
build_pointer_type (t);
-
-#ifdef GATHER_STATISTICS
- tree_node_counts[(int)lang_type] += 1;
- tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
-#endif
}
else
/* We use TYPE_ALIAS_SET for the CLASSTYPE_MARKED bits. But,
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)
+ if (IS_AGGR_TYPE_CODE (code) || code == TEMPLATE_TYPE_PARM
+ || code == BOUND_TEMPLATE_TEMPLATE_PARM
+ || code == TYPENAME_TYPE)
TYPE_BINFO (t) = make_binfo (size_zero_node, t, NULL_TREE, NULL_TREE);
return t;
make_aggr_type (code)
enum tree_code code;
{
- tree t = cp_make_lang_type (code);
+ tree t = cxx_make_type (code);
if (IS_AGGR_TYPE_CODE (code))
SET_IS_AGGR_TYPE (t, 1);
void
compiler_error VPARAMS ((const char *msg, ...))
{
-#ifndef ANSI_PROTOTYPES
- const char *msg;
-#endif
char buf[1024];
- va_list ap;
- VA_START (ap, msg);
-
-#ifndef ANSI_PROTOTYPES
- msg = va_arg (ap, const char *);
-#endif
+ VA_OPEN (ap, msg);
+ VA_FIXEDARG (ap, const char *, msg);
vsprintf (buf, msg, ap);
- va_end (ap);
+ VA_CLOSE (ap);
+
error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
}
else if (rid == ridpointers[(int) RID_RESTRICT])
return TYPE_QUAL_RESTRICT;
- my_friendly_abort (0);
+ abort ();
return TYPE_UNQUALIFIED;
}