/* Separate lexical analyzer for GNU C++.
- Copyright (C) 1987, 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* This file is the lexical analyzer for GNU C++. */
#include "input.h"
#include "tree.h"
#include "lex.h"
-#include "parse.h"
#include "cp-tree.h"
+#include "parse.h"
#include "flags.h"
#include "obstack.h"
+#include "c-pragma.h"
#ifdef MULTIBYTE_CHARS
#include <stdlib.h>
#ifndef errno
extern int errno; /* needed for VAX. */
#endif
-extern jmp_buf toplevel;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
-extern struct obstack *expression_obstack, permanent_obstack;
+extern struct obstack permanent_obstack;
extern struct obstack *current_obstack, *saveable_obstack;
extern double atof ();
extern char *index ();
extern char *rindex ();
-
-void extract_interface_info ();
void yyerror ();
/* This obstack is needed to hold text. It is not safe to use
TOKEN_BUFFER because `check_newline' calls `yylex'. */
struct obstack inline_text_obstack;
-static char *inline_text_firstobj;
-
-/* This obstack is used to hold information about methods to be
- synthesized. It should go away when synthesized methods are handled
- properly (i.e. only when needed). */
-struct obstack synth_obstack;
-static char *synth_firstobj;
int end_of_file;
static tree filename_times;
static tree this_filename_time;
-/* For implementing #pragma unit. */
-tree current_unit_name;
-tree current_unit_language;
-
/* Array for holding counts of the numbers of tokens seen. */
extern int *token_count;
-
-/* Textual definition used for default functions. */
-static void default_copy_constructor_body ();
-static void default_assign_ref_body ();
\f
/* Return something to represent absolute declarators containing a *.
TARGET is the absolute declarator that the * contains.
- TYPE_QUALS is a list of modifiers such as const or volatile
+ CV_QUALIFIERS is a list of modifiers such as const or volatile
to apply to the pointer type, represented as identifiers.
We return an INDIRECT_REF whose "contents" are TARGET
and whose type is the modifier list. */
tree
-make_pointer_declarator (type_quals, target)
- tree type_quals, target;
+make_pointer_declarator (cv_qualifiers, target)
+ tree cv_qualifiers, target;
{
if (target && TREE_CODE (target) == IDENTIFIER_NODE
&& ANON_AGGRNAME_P (target))
error ("type name expected before `*'");
target = build_parse_node (INDIRECT_REF, target);
- TREE_TYPE (target) = type_quals;
+ TREE_TYPE (target) = cv_qualifiers;
return target;
}
/* Return something to represent absolute declarators containing a &.
TARGET is the absolute declarator that the & contains.
- TYPE_QUALS is a list of modifiers such as const or volatile
+ CV_QUALIFIERS is a list of modifiers such as const or volatile
to apply to the reference type, represented as identifiers.
We return an ADDR_EXPR whose "contents" are TARGET
and whose type is the modifier list. */
tree
-make_reference_declarator (type_quals, target)
- tree type_quals, target;
+make_reference_declarator (cv_qualifiers, target)
+ tree cv_qualifiers, target;
{
if (target)
{
error ("type name expected before `&'");
}
target = build_parse_node (ADDR_EXPR, target);
- TREE_TYPE (target) = type_quals;
+ TREE_TYPE (target) = cv_qualifiers;
+ return target;
+}
+
+tree
+make_call_declarator (target, parms, cv_qualifiers, exception_specification)
+ tree target, parms, cv_qualifiers, exception_specification;
+{
+ target = build_parse_node (CALL_EXPR, target, parms, cv_qualifiers);
+ TREE_TYPE (target) = exception_specification;
return target;
}
+
+void
+set_quals_and_spec (call_declarator, cv_qualifiers, exception_specification)
+ tree call_declarator, cv_qualifiers, exception_specification;
+{
+ TREE_OPERAND (call_declarator, 2) = cv_qualifiers;
+ TREE_TYPE (call_declarator) = exception_specification;
+}
\f
/* Build names and nodes for overloaded operators. */
\f
/* Table indexed by tree code giving a string containing a character
classifying the tree code. Possibilities are
- t, d, s, c, r, <, 1 and 2. See cp/tree.def for details. */
+ t, d, s, c, r, <, 1 and 2. See cp/cp-tree.def for details. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
char *cplus_tree_code_type[] = {
"x",
-#include "tree.def"
+#include "cp-tree.def"
};
#undef DEFTREECODE
int cplus_tree_code_length[] = {
0,
-#include "tree.def"
+#include "cp-tree.def"
};
#undef DEFTREECODE
char *cplus_tree_code_name[] = {
"@@dummy",
-#include "tree.def"
+#include "cp-tree.def"
};
#undef DEFTREECODE
\f
/* With luck, we discover the real source file's name from that
and put it in input_filename. */
put_back (check_newline ());
-
- if (flag_cadillac)
- cadillac_start ();
if (flag_gnu_xref) GNU_xref_begin (input_filename);
+ init_repo (input_filename);
}
void
/* Change by Bryan Boreham, Kewill, Thu Jul 27 09:46:05 1989.
Stuck this hack in to get the files open correctly; this is called
in place of init_lex if we are an unexec'd binary. */
+
void
reinit_lang_specific ()
{
reinit_search_statistics ();
}
+int *init_parse ();
+
void
init_lex ()
{
init_method ();
init_error ();
gcc_obstack_init (&inline_text_obstack);
- inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
- gcc_obstack_init (&synth_obstack);
- synth_firstobj = (char *) obstack_alloc (&synth_obstack, 0);
/* Start it at 0, because check_newline is called at the very beginning
and will increment it to 1. */
SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_REGISTER],
build_tree_list (NULL_TREE, ridpointers[(int) RID_REGISTER]));
- /* C++ extensions. These are probably not correctly named. */
+ /* 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]));
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++. */
+ /* 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]));
TREE_TYPE (signature_type_node) = signature_type_node;
ridpointers[(int) RID_SIGNATURE] = signature_type_node;
+ null_node = build_int_2 (0, 0);
+ ridpointers[RID_NULL] = null_node;
+
opname_tab[(int) COMPONENT_REF] = "->";
opname_tab[(int) MEMBER_REF] = "->*";
opname_tab[(int) METHOD_CALL_EXPR] = "->()";
- opname_tab[(int) INDIRECT_REF] = "(unary *)";
+ opname_tab[(int) INDIRECT_REF] = "*";
opname_tab[(int) ARRAY_REF] = "[]";
opname_tab[(int) MODIFY_EXPR] = "=";
opname_tab[(int) NEW_EXPR] = "new";
opname_tab[(int) DELETE_EXPR] = "delete";
opname_tab[(int) VEC_NEW_EXPR] = "new []";
opname_tab[(int) VEC_DELETE_EXPR] = "delete []";
- opname_tab[(int) COND_EXPR] = "... ? ... : ...";
+ opname_tab[(int) COND_EXPR] = "?:";
opname_tab[(int) CALL_EXPR] = "()";
opname_tab[(int) PLUS_EXPR] = "+";
opname_tab[(int) MINUS_EXPR] = "-";
opname_tab[(int) EQ_EXPR] = "==";
opname_tab[(int) NE_EXPR] = "!=";
opname_tab[(int) IN_EXPR] = "in";
- opname_tab[(int) RANGE_EXPR] = "..";
- opname_tab[(int) CONVERT_EXPR] = "(unary +)";
- opname_tab[(int) ADDR_EXPR] = "(unary &)";
+ opname_tab[(int) RANGE_EXPR] = "...";
+ opname_tab[(int) CONVERT_EXPR] = "+";
+ opname_tab[(int) ADDR_EXPR] = "&";
opname_tab[(int) PREDECREMENT_EXPR] = "--";
opname_tab[(int) PREINCREMENT_EXPR] = "++";
opname_tab[(int) POSTDECREMENT_EXPR] = "--";
#if 0
/* let's parse things, and if they use it, then give them an error. */
- if (!flag_handle_exceptions)
+ if (!flag_exceptions)
{
UNSET_RESERVED_WORD ("throw");
UNSET_RESERVED_WORD ("try");
}
#endif
- if (! (flag_gc || flag_rtti) || flag_no_gnu_keywords)
+ if (!flag_rtti || flag_no_gnu_keywords)
{
UNSET_RESERVED_WORD ("classof");
UNSET_RESERVED_WORD ("headof");
{
/* These are new ANSI keywords that may break code. */
UNSET_RESERVED_WORD ("and");
+ UNSET_RESERVED_WORD ("and_eq");
UNSET_RESERVED_WORD ("bitand");
UNSET_RESERVED_WORD ("bitor");
UNSET_RESERVED_WORD ("compl");
UNSET_RESERVED_WORD ("not");
+ UNSET_RESERVED_WORD ("not_eq");
UNSET_RESERVED_WORD ("or");
+ UNSET_RESERVED_WORD ("or_eq");
UNSET_RESERVED_WORD ("xor");
+ UNSET_RESERVED_WORD ("xor_eq");
}
- if (! flag_traditional)
- UNSET_RESERVED_WORD ("overload");
token_count = init_parse ();
interface_unknown = 1;
case SCSPEC:
case PRE_PARSED_CLASS_DECL:
t = yylval.ttype;
+ if (TREE_CODE (t) == TYPE_DECL)
+ {
+ fprintf (file, " `%s'", DECL_NAME (t));
+ break;
+ }
my_friendly_assert (TREE_CODE (t) == IDENTIFIER_NODE, 224);
if (IDENTIFIER_POINTER (t))
fprintf (file, " `%s'", IDENTIFIER_POINTER (t));
}
}
+#if defined(GATHER_STATISTICS) && defined(REDUCE_LENGTH)
static int *reduce_count;
+#endif
+
int *token_count;
+#if 0
#define REDUCE_LENGTH (sizeof (yyr2) / sizeof (yyr2[0]))
#define TOKEN_LENGTH (256 + sizeof (yytname) / sizeof (yytname[0]))
+#endif
int *
init_parse ()
{
#ifdef GATHER_STATISTICS
+#ifdef REDUCE_LENGTH
reduce_count = (int *)malloc (sizeof (int) * (REDUCE_LENGTH + 1));
bzero (reduce_count, sizeof (int) * (REDUCE_LENGTH + 1));
reduce_count += 1;
bzero (token_count, sizeof (int) * (TOKEN_LENGTH + 1));
token_count += 1;
#endif
+#endif
return token_count;
}
#ifdef GATHER_STATISTICS
+#ifdef REDUCE_LENGTH
void
yyhook (yyn)
int yyn;
return token_count[*q] - token_count[*p];
}
#endif
+#endif
void
print_parse_statistics ()
{
#ifdef GATHER_STATISTICS
+#ifdef REDUCE_LENGTH
#if YYDEBUG != 0
int i;
int maxlen = REDUCE_LENGTH;
qsort (sorted, TOKEN_LENGTH, sizeof (int), token_cmp);
for (i = 0; i < TOKEN_LENGTH; i++)
{
- int index = sorted[i];
- if (token_count[index] == 0)
+ int idx = sorted[i];
+ if (token_count[idx] == 0)
break;
- if (token_count[index] < token_count[-1])
+ if (token_count[idx] < token_count[-1])
break;
fprintf (stderr, "token %d, `%s', count = %d\n",
- index, yytname[YYTRANSLATE (index)], token_count[index]);
+ idx, yytname[YYTRANSLATE (idx)], token_count[idx]);
}
fprintf (stderr, "\n");
for (i = 0; i < REDUCE_LENGTH; i++)
qsort (sorted, REDUCE_LENGTH, sizeof (int), reduce_cmp);
for (i = 0; i < REDUCE_LENGTH; i++)
{
- int index = sorted[i];
- if (reduce_count[index] == 0)
+ int idx = sorted[i];
+ if (reduce_count[idx] == 0)
break;
- if (reduce_count[index] < reduce_count[-1])
+ if (reduce_count[idx] < reduce_count[-1])
break;
fprintf (stderr, "rule %d, line %d, count = %d\n",
- index, yyrline[index], reduce_count[index]);
+ idx, yyrline[idx], reduce_count[idx]);
}
fprintf (stderr, "\n");
#endif
#endif
+#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;
/* Helper function to load global variables with interface
information. */
+
void
extract_interface_info ()
{
fileinfo = get_time_identifier (input_filename);
fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo);
interface_only = TREE_INT_CST_LOW (fileinfo);
- if (!processing_template_defn || flag_external_templates)
- interface_unknown = TREE_INT_CST_HIGH (fileinfo);
+ interface_unknown = TREE_INT_CST_HIGH (fileinfo);
}
/* Return nonzero if S is not considered part of an
INTERFACE/IMPLEMENTATION pair. Otherwise, return 0. */
+
static int
interface_strcmp (s)
char *s;
= interface_strcmp (FILE_NAME_NONDIRECTORY (DECL_SOURCE_FILE (vars)));
}
-void
+int
set_vardecl_interface_info (prev, vars)
tree prev, vars;
{
CLASSTYPE_VTABLE_NEEDS_WRITING (type) = 1;
DECL_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type);
TREE_PUBLIC (vars) = 1;
+ return 1;
}
+ return 0;
}
\f
/* 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
call process_next_inline to start working on the next one. */
+
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)
/* Reverse the pending inline functions, since
they were cons'd instead of appended. */
{
- struct pending_inline *prev = 0, *tail, *bottom = 0;
+ struct pending_inline *prev = 0, *tail;
t = pending_inlines;
pending_inlines = 0;
t->deja_vu = 1;
prev = t;
}
-
- /* This kludge should go away when synthesized methods are handled
- properly, i.e. only when needed. */
- for (t = prev; t; t = t->next)
- {
- if (t->lineno <= 0)
- {
- tree f = t->fndecl;
- DECL_PENDING_INLINE_INFO (f) = 0;
- interface_unknown = t->interface == 1;
- interface_only = t->interface == 0;
- synthesize_method (f);
- if (tail)
- tail->next = t->next;
- else
- prev = t->next;
- if (! bottom)
- bottom = t;
- }
- else
- tail = t;
- }
- if (bottom)
- {
- obstack_free (&synth_obstack, bottom);
- extract_interface_info ();
- }
t = prev;
}
return;
/* Now start processing the first inline function. */
- my_friendly_assert ((t->parm_vec == NULL_TREE) == (t->bindings == NULL_TREE),
- 226);
- if (t->parm_vec)
- push_template_decls (t->parm_vec, t->bindings, 0);
+ context = hack_decl_function_context (t->fndecl);
+ if (context)
+ push_cp_function_context (context);
if (t->len > 0)
{
feed_input (t->buf, t->len, t->can_free ? &inline_text_obstack : 0);
/* 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);
-#if 0
- if (flag_default_inline && t->fndecl
- /* If we're working from a template, don't change
- the `inline' state. */
- && t->parm_vec == NULL_TREE)
- DECL_INLINE (t->fndecl) = 1;
-#endif
DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
}
/* Called from the fndecl rule in the parser when the function just parsed
was declared using a PRE_PARSED_FUNCTION_DECL (i.e. came from
do_pending_inlines). */
+
void
process_next_inline (t)
tree t;
{
+ tree context;
struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
- my_friendly_assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE),
- 227);
- if (i->parm_vec)
- pop_template_decls (i->parm_vec, i->bindings, 0);
+ context = hack_decl_function_context (i->fndecl);
+ if (context)
+ pop_cp_function_context (context);
i = i->next;
if (yychar == YYEMPTY)
yychar = yylex ();
if (yychar != END_OF_SAVED_INPUT)
{
error ("parse error at end of saved function text");
+
/* restore_pending_input will abort unless yychar is either
- * END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
- * hosed, feed back YYEMPTY.
- * We also need to discard nextchar, since that may have gotten
- * set as well.
- */
+ END_OF_SAVED_INPUT or YYEMPTY; since we already know we're
+ hosed, feed back YYEMPTY. We also need to discard nextchar,
+ since that may have gotten set as well. */
nextchar = -1;
}
yychar = YYEMPTY;
to_be_restored = 0;
if (i && i->fndecl != NULL_TREE)
{
- my_friendly_assert ((i->parm_vec == NULL_TREE) == (i->bindings == NULL_TREE),
- 228);
- if (i->parm_vec)
- push_template_decls (i->parm_vec, i->bindings, 0);
+ context = hack_decl_function_context (i->fndecl);
+ if (context)
+ push_cp_function_context (context);
feed_input (i->buf, i->len, i->can_free ? &inline_text_obstack : 0);
lineno = i->lineno;
input_filename = i->filename;
yychar = PRE_PARSED_FUNCTION_DECL;
yylval.ttype = build_tree_list ((tree) i, i->fndecl);
-#if 0
- if (flag_default_inline
- /* If we're working from a template, don't change
- the `inline' state. */
- && i->parm_vec == NULL_TREE)
- DECL_INLINE (i->fndecl) = 1;
-#endif
DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
}
if (i)
/* Return next non-whitespace input character, which may come
from `finput', or from `nextchar'. */
+
static int
yynextch ()
{
/* Unget character CH from the input stream.
If RESCAN is non-zero, then we want to `see' this
character as the next input token. */
+
void
yyungetc (ch, rescan)
int ch;
/* This function stores away the text for an inline function that should
be processed later. It decides how much later, and may need to move
the info between obstacks; therefore, the caller should not refer to
- the T parameter after calling this function.
-
- This function also stores the list of template-parameter bindings that
- will be needed for expanding the template, if any. */
+ the T parameter after calling this function. */
static void
store_pending_inline (decl, t)
tree decl;
struct pending_inline *t;
{
- extern int processing_template_defn;
- int delay_to_eof = 0;
- struct pending_inline **inlines;
-
t->fndecl = decl;
- /* Default: compile right away, and no extra bindings are needed. */
- t->parm_vec = t->bindings = 0;
- if (processing_template_defn)
- {
- tree type = current_class_type;
- /* Assumption: In this (possibly) nested class sequence, only
- one name will have template parms. */
- while (type && TREE_CODE_CLASS (TREE_CODE (type)) == 't')
- {
- tree decl = TYPE_NAME (type);
- tree tmpl = IDENTIFIER_TEMPLATE (DECL_NAME (decl));
- if (tmpl)
- {
- t->parm_vec = DECL_TEMPLATE_INFO (TREE_PURPOSE (tmpl))->parm_vec;
- t->bindings = TREE_VALUE (tmpl);
- }
- type = DECL_CONTEXT (decl);
- }
- if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
- || TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
- {
- if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
- my_friendly_assert (TYPE_MAX_VALUE (TREE_TYPE (decl)) == current_class_type,
- 233);
-
- /* Inline functions can be compiled immediately. Other functions
- will be output separately, so if we're in interface-only mode,
- punt them now, or output them now if we're doing implementations
- and we know no overrides will exist. Otherwise, we delay until
- end-of-file, to see if the definition is really required. */
- if (DECL_INLINE (decl))
- /* delay_to_eof == 0 */;
- else if (current_class_type && !interface_unknown)
- {
- if (interface_only)
- {
-#if 0
- print_node_brief (stderr, "\ndiscarding text for ", decl, 0);
-#endif
- if (t->can_free)
- obstack_free (&inline_text_obstack, t->buf);
- DECL_PENDING_INLINE_INFO (decl) = 0;
- return;
- }
- }
- /* Don't delay the processing of virtual functions. */
- else if (DECL_VINDEX (decl) == NULL_TREE)
- delay_to_eof = 1;
- }
- else
- my_friendly_abort (58);
- }
-
- if (delay_to_eof)
- {
- extern struct pending_inline *pending_template_expansions;
-
- if (t->can_free)
- {
- char *free_to = t->buf;
- t->buf = (char *) obstack_copy (&permanent_obstack, t->buf,
- t->len + 1);
- t = (struct pending_inline *) obstack_copy (&permanent_obstack,
- (char *)t, sizeof (*t));
- obstack_free (&inline_text_obstack, free_to);
- }
- inlines = &pending_template_expansions;
- t->can_free = 0;
- }
- else
- {
- inlines = &pending_inlines;
- DECL_PENDING_INLINE_INFO (decl) = t;
- }
+ DECL_PENDING_INLINE_INFO (decl) = t;
/* Because we use obstacks, we must process these in precise order. */
- t->next = *inlines;
- *inlines = t;
+ t->next = pending_inlines;
+ pending_inlines = t;
}
void reinit_parse_for_block ();
int starting_lineno = lineno;
char *starting_filename = input_filename;
- reinit_parse_for_block (yychar, &inline_text_obstack, 0);
+ reinit_parse_for_block (yychar, &inline_text_obstack);
len = obstack_object_size (&inline_text_obstack);
current_base_init_list = NULL_TREE;
t->len = len;
t->can_free = 1;
t->deja_vu = 0;
+#if 0
if (interface_unknown && processing_template_defn && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl))
- warn_if_unknown_interface ();
+ warn_if_unknown_interface (decl);
+#endif
t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
store_pending_inline (decl, t);
}
}
-/* Consume a block -- actually, a method or template definition beginning
- with `:' or `{' -- and save it away on the specified obstack.
+/* Consume a block -- actually, a method beginning
+ with `:' or `{' -- and save it away on the specified obstack. */
- Argument IS_TEMPLATE indicates which set of error messages should be
- output if something goes wrong. This should really be cleaned up somehow,
- without loss of clarity. */
void
-reinit_parse_for_block (yychar, obstackp, is_template)
- int yychar;
+reinit_parse_for_block (pyychar, obstackp)
+ int pyychar;
struct obstack *obstackp;
- int is_template;
{
register int c = 0;
int blev = 1;
int look_for_semicolon = 0;
int look_for_lbrac = 0;
- if (yychar == '{')
+ if (pyychar == '{')
obstack_1grow (obstackp, '{');
- else if (yychar == '=')
+ else if (pyychar == '=')
look_for_semicolon = 1;
- else if (yychar != ':' && (yychar != RETURN || is_template))
+ else if (pyychar == ':')
{
- yyerror (is_template
- ? "parse error in template specification"
- : "parse error in method specification");
- obstack_1grow (obstackp, '{');
+ obstack_1grow (obstackp, pyychar);
+ look_for_lbrac = 1;
+ blev = 0;
}
- else
+ else if (pyychar == RETURN)
+ {
+ obstack_grow (obstackp, "return", 6);
+ look_for_lbrac = 1;
+ blev = 0;
+ }
+ else if (pyychar == TRY)
{
- obstack_1grow (obstackp, yychar);
+ obstack_grow (obstackp, "try", 3);
look_for_lbrac = 1;
blev = 0;
}
+ else
+ {
+ yyerror ("parse error in method specification");
+ obstack_1grow (obstackp, '{');
+ }
if (nextchar != EOF)
{
{
blev--;
if (blev == 0 && !look_for_semicolon)
- goto done;
+ {
+ if (pyychar == TRY)
+ {
+ if (peekyylex () == CATCH)
+ {
+ yylex ();
+ obstack_grow (obstackp, " catch ", 7);
+ look_for_lbrac = 1;
+ }
+ else
+ {
+ yychar = '{';
+ goto done;
+ }
+ }
+ else
+ {
+ goto done;
+ }
+ }
}
else if (c == '\\')
{
{
if (look_for_lbrac)
{
- error (is_template
- ? "template body missing"
- : "function body for constructor missing");
+ error ("function body for constructor missing");
obstack_1grow (obstackp, '{');
obstack_1grow (obstackp, '}');
len += 2;
When KIND == 6, build default operator = (X&). */
tree
-cons_up_default_function (type, name, kind)
- tree type, name;
+cons_up_default_function (type, full_name, kind)
+ tree type, full_name;
int kind;
{
extern tree void_list_node;
- char *func_buf = NULL;
- int func_len = 0;
tree declspecs = NULL_TREE;
tree fn, args;
tree argtype;
int retref = 0;
- int complex = 0;
+ tree name = constructor_name (full_name);
- name = constructor_name (name);
switch (kind)
{
/* Destructors. */
case 2:
/* Default constructor. */
args = void_list_node;
- complex = TYPE_NEEDS_CONSTRUCTING (type);
break;
case 3:
build_tree_list (hash_tree_chain (argtype, NULL_TREE),
get_identifier ("_ctor_arg")),
void_list_node);
- complex = TYPE_HAS_COMPLEX_INIT_REF (type);
break;
case 5:
/* Fall through... */
case 6:
retref = 1;
- declspecs = build_decl_list (NULL_TREE, name);
+ declspecs = build_decl_list (NULL_TREE, type);
name = ansi_opname [(int) MODIFY_EXPR];
build_tree_list (hash_tree_chain (argtype, NULL_TREE),
get_identifier ("_ctor_arg")),
void_list_node);
- complex = TYPE_HAS_COMPLEX_ASSIGN_REF (type);
break;
default:
TREE_PARMLIST (args) = 1;
{
- tree declarator = build_parse_node (CALL_EXPR, name, args, NULL_TREE);
+ tree declarator = make_call_declarator (name, args, NULL_TREE, NULL_TREE);
if (retref)
declarator = build_parse_node (ADDR_EXPR, declarator);
if (fn == void_type_node)
return fn;
- if (processing_template_defn)
- SET_DECL_IMPLICIT_INSTANTIATION (fn);
+ if (kind > 2)
+ SET_DECL_ARTIFICIAL (TREE_CHAIN (DECL_ARGUMENTS (fn)));
- if (CLASSTYPE_INTERFACE_KNOWN (type))
+#if 0
+ if (processing_template_defn)
{
- DECL_INTERFACE_KNOWN (fn) = 1;
- DECL_EXTERNAL (fn) = (CLASSTYPE_INTERFACE_ONLY (type)
- || ! flag_implement_inlines);
- TREE_STATIC (fn) = ! DECL_EXTERNAL (fn);
+ SET_DECL_IMPLICIT_INSTANTIATION (fn);
+ repo_template_used (fn);
}
+#endif
- /* When on-the-fly synthesis works properly, remove the second and third
- conditions here. */
- if (flag_keep_inline_functions
- || ! flag_no_inline
- || complex
- || ! DECL_EXTERNAL (fn))
+#if 0
+ if (CLASSTYPE_INTERFACE_KNOWN (type))
{
- struct pending_inline *t;
- t = (struct pending_inline *)
- obstack_alloc (&synth_obstack, sizeof (struct pending_inline));
- t->lineno = -kind;
- t->can_free = 0;
- t->interface = (interface_unknown ? 1 : (interface_only ? 0 : 2));
- store_pending_inline (fn, t);
+ DECL_INTERFACE_KNOWN (fn) = 1;
+ DECL_NOT_REALLY_EXTERN (fn) = (!CLASSTYPE_INTERFACE_ONLY (type)
+ && flag_implement_inlines);
}
else
- mark_inline_for_output (fn);
+#endif
+ DECL_NOT_REALLY_EXTERN (fn) = 1;
+
+ mark_inline_for_output (fn);
#ifdef DEBUG_DEFAULT_FUNCTIONS
{ char *fn_type = NULL;
return fn;
}
-#if 0
-/* Used by default_copy_constructor_body. For the anonymous union
- in TYPE, return the member that is at least as large as the rest
- of the members, so we can copy it. */
-static tree
-largest_union_member (type)
- tree type;
-{
- tree f, type_size = TYPE_SIZE (type);
-
- for (f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f))
- if (simple_cst_equal (DECL_SIZE (f), type_size))
- return f;
-
- /* We should always find one. */
- my_friendly_abort (323);
- return NULL_TREE;
-}
-
-/* Construct the body of a default assignment operator.
- Mostly copied directly from default_copy_constructor_body. */
-static void
-default_assign_ref_body (bufp, lenp, type, fields)
- char **bufp;
- int *lenp;
- tree type, fields;
-{
- static struct obstack body;
- static int inited = FALSE;
- int n_bases = CLASSTYPE_N_BASECLASSES (type);
- char *tbuf;
- int tgot, tneed;
-
- if (!inited)
- {
- obstack_init (&body);
- inited = TRUE;
- }
- body.next_free = body.object_base;
-
- obstack_1grow (&body, '{');
-
- /* Small buffer for sprintf(). */
-
- tgot = 100;
- tbuf = (char *) alloca (tgot);
-
- /* If we don't need a real op=, just do a bitwise copy. */
- if (! TYPE_HAS_COMPLEX_ASSIGN_REF (type))
- {
- tbuf = "{__builtin_memcpy(this,&_ctor_arg,sizeof(_ctor_arg));return *this;}";
- *lenp = strlen (tbuf);
- *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1);
- strcpy (*bufp, tbuf);
- return;
- }
-
- if (TREE_CODE (type) == UNION_TYPE)
- {
- if (fields)
- {
- tree main = fields;
- char * s;
- tree f;
-
- for (f = TREE_CHAIN (fields); f; f = TREE_CHAIN (f))
- if (tree_int_cst_lt (TYPE_SIZE (TREE_TYPE (main)),
- TYPE_SIZE (TREE_TYPE (f))))
- main = f;
-
- s = IDENTIFIER_POINTER (DECL_NAME (main));
-
- tneed = (2 * strlen (s)) + 28;
- if (tgot < tneed)
- {
- tgot = tneed;
- tbuf = (char *) alloca (tgot);
- }
-
- sprintf (tbuf, "{%s=_ctor_arg.%s;return *this;}", s, s);
- }
- else
- tbuf = "{}";
-
- *lenp = strlen (tbuf);
- *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1);
- strcpy (*bufp, tbuf);
- return;
- }
-
- /* Construct base classes...
- FIXME: Does not deal with multiple inheritance and virtual bases
- correctly. See g++.old-deja/g++.jason/opeq5.C for a testcase.
- We need to do wacky things if everything between us and the virtual
- base (by all paths) has a "complex" op=. */
-
- if (n_bases)
- {
- tree bases = TYPE_BINFO_BASETYPES (type);
- int i = 0;
-
- for (i = 0; i < n_bases; i++)
- {
- tree binfo = TREE_VEC_ELT (bases, i);
- tree btype, name;
- char *s;
-
- btype = BINFO_TYPE (binfo);
- name = TYPE_NESTED_NAME (btype);
- s = IDENTIFIER_POINTER (name);
-
- tneed = (2 * strlen (s)) + 42;
- if (tgot < tneed)
- {
- tgot = tneed;
- tbuf = (char *) alloca (tgot);
- }
-
- sprintf (tbuf, "%s::operator=((%s%s ::%s&)_ctor_arg);", s,
- TYPE_READONLY (type) ? "const " : "",
- CLASSTYPE_DECLARED_CLASS (btype) ? "class" : "struct",
- s);
- obstack_grow (&body, tbuf, strlen (tbuf));
- }
- }
-
- /* Construct fields. */
-
- if (fields)
- {
- tree f;
-
- for (f = fields; f; f = TREE_CHAIN (f))
- {
- if (TREE_CODE (f) == FIELD_DECL && ! DECL_VIRTUAL_P (f))
- {
- char *s;
- tree x;
- tree t = TREE_TYPE (f);
-
- if (DECL_NAME (f))
- x = f;
- else if (t != NULL_TREE
- && TREE_CODE (t) == UNION_TYPE
- && ((TREE_CODE (TYPE_NAME (t)) == IDENTIFIER_NODE
- && ANON_AGGRNAME_P (TYPE_NAME (t)))
- || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))))
- && TYPE_FIELDS (t) != NULL_TREE)
- x = largest_union_member (t);
- else
- continue;
-
- s = IDENTIFIER_POINTER (DECL_NAME (x));
- tneed = (2 * strlen (s)) + 13;
- if (tgot < tneed)
- {
- tgot = tneed;
- tbuf = (char *) alloca (tgot);
- }
-
- sprintf (tbuf, "%s=_ctor_arg.%s;", s, s);
- obstack_grow (&body, tbuf, strlen (tbuf));
- }
- }
- }
-
- obstack_grow (&body, "return *this;}", 15);
-
- *lenp = obstack_object_size (&body) - 1;
- *bufp = obstack_alloc (&inline_text_obstack, *lenp);
-
- strcpy (*bufp, body.object_base);
-}
-
-/* Construct the body of a default copy constructor. */
-static void
-default_copy_constructor_body (bufp, lenp, type, fields)
- char **bufp;
- int *lenp;
- tree type, fields;
-{
- static struct obstack prologue;
- static int inited = FALSE;
- int n_bases = CLASSTYPE_N_BASECLASSES (type);
- char sep = ':';
- char *tbuf;
- int tgot, tneed;
-
- /* Create a buffer to call base class constructors and construct members
- (fields). */
-
- if (!inited)
- {
- obstack_init (&prologue);
- inited = TRUE;
- }
- prologue.next_free = prologue.object_base;
-
- /* If we don't need a real copy ctor, just do a bitwise copy. */
- if (! TYPE_HAS_COMPLEX_INIT_REF (type))
- {
- tbuf = "{__builtin_memcpy(this,&_ctor_arg,sizeof(_ctor_arg));}";
- *lenp = strlen (tbuf);
- *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1);
- strcpy (*bufp, tbuf);
- return;
- }
-
- /* Small buffer for sprintf(). */
-
- tgot = 100;
- tbuf = (char *) alloca (tgot);
-
- if (TREE_CODE (type) == UNION_TYPE)
- {
- if (fields)
- {
- tree main = fields;
- char * s;
- tree f;
-
- for (f = TREE_CHAIN (fields); f; f = TREE_CHAIN (f))
- if (tree_int_cst_lt (TYPE_SIZE (TREE_TYPE (main)),
- TYPE_SIZE (TREE_TYPE (f))))
- main = f;
-
- s = IDENTIFIER_POINTER (DECL_NAME (main));
- tneed = (2 * strlen (s)) + 16;
- if (tgot < tneed)
- {
- tgot = tneed;
- tbuf = (char *) alloca (tgot);
- }
-
- sprintf (tbuf, ":%s(_ctor_arg.%s){}", s, s);
- }
- else
- tbuf = "{}";
-
- *lenp = strlen (tbuf);
- *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1);
- strcpy (*bufp, tbuf);
- return;
- }
-
- /* Construct base classes... */
-
- if (n_bases)
- {
- /* Note that CLASSTYPE_VBASECLASSES isn't set yet... */
- tree v = get_vbase_types (type);
- tree bases = TYPE_BINFO_BASETYPES (type);
- int i = 0;
-
- for (;;)
- {
- tree binfo, btype, name;
- char *s;
-
- if (v)
- {
- binfo = v;
- v = TREE_CHAIN (v);
- }
- else if (i < n_bases)
- {
- binfo = TREE_VEC_ELT (bases, i++);
- if (TREE_VIA_VIRTUAL (binfo))
- continue;
- }
- else
- break;
-
- btype = BINFO_TYPE (binfo);
- name = TYPE_NESTED_NAME (btype);
- s = IDENTIFIER_POINTER (name);
-
- tneed = (2 * strlen (s)) + 39;
- if (tgot < tneed)
- {
- tgot = tneed;
- tbuf = (char *) alloca (tgot);
- }
-
- sprintf (tbuf, "%c%s((%s%s ::%s&)_ctor_arg)", sep, s,
- TYPE_READONLY (type) ? "const " : "",
- CLASSTYPE_DECLARED_CLASS (btype) ? "class" : "struct",
- s);
- sep = ',';
- obstack_grow (&prologue, tbuf, strlen (tbuf));
- }
- }
-
- /* Construct fields. */
-
- if (fields)
- {
- tree f;
-
- for (f = fields; f; f = TREE_CHAIN (f))
- {
- if (TREE_CODE (f) == FIELD_DECL && ! DECL_VIRTUAL_P (f))
- {
- char *s;
- tree x;
- tree t = TREE_TYPE (f);
-
- if (DECL_NAME (f))
- x = f;
- else if (t != NULL_TREE
- && TREE_CODE (t) == UNION_TYPE
- && ((TREE_CODE (TYPE_NAME (t)) == IDENTIFIER_NODE
- && ANON_AGGRNAME_P (TYPE_NAME (t)))
- || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
- && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))))
- && TYPE_FIELDS (t) != NULL_TREE)
- x = largest_union_member (t);
- else
- continue;
-
- s = IDENTIFIER_POINTER (DECL_NAME (x));
- tneed = (2 * strlen (s)) + 30;
- if (tgot < tneed)
- {
- tgot = tneed;
- tbuf = (char *) alloca (tgot);
- }
-
- sprintf (tbuf, "%c%s(_ctor_arg.%s)", sep, s, s);
- sep = ',';
- obstack_grow (&prologue, tbuf, strlen (tbuf));
- }
- }
- }
-
- /* Concatenate constructor body to prologue. */
-
- *lenp = obstack_object_size (&prologue) + 2;
- *bufp = obstack_alloc (&inline_text_obstack, *lenp + 1);
-
- obstack_1grow (&prologue, '\0');
-
- strcpy (*bufp, prologue.object_base);
- strcat (*bufp, "{}");
-}
-#endif
-
/* Heuristic to tell whether the user is missing a semicolon
after a struct or enum declaration. Emit an error message
if we know the user has blown it. */
+
void
check_for_missing_semicolon (type)
tree type;
if ((yychar > 255
&& yychar != SCSPEC
&& yychar != IDENTIFIER
- && yychar != TYPENAME)
+ && yychar != TYPENAME
+ && yychar != SELFNAME)
|| end_of_file)
{
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
int linemode;
+int handle_cp_pragma ();
+
int
check_newline ()
{
&& getch () == 'm'
&& getch () == 'a')
{
- /* Read first nonwhite char after the `#pragma'. */
-
- do
- c = getch ();
- while (c == ' ' || c == '\t');
-
- if (c == 'v'
- && getch () == 't'
- && getch () == 'a'
- && getch () == 'b'
- && getch () == 'l'
- && getch () == 'e'
- && ((c = getch ()) == ' ' || c == '\t'))
- {
- extern tree pending_vtables;
-
- /* More follows: it must be a string constant (class name). */
- token = real_yylex ();
- if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid #pragma vtable");
- goto skipline;
- }
- if (write_virtuals != 2)
- {
- warning ("use `+e2' option to enable #pragma vtable");
- goto skipline;
- }
- pending_vtables = perm_tree_cons (NULL_TREE, get_identifier (TREE_STRING_POINTER (yylval.ttype)), pending_vtables);
- if (nextchar < 0)
- nextchar = getch ();
- c = nextchar;
- if (c != EOF)
- warning ("trailing characters ignored");
- }
- else if (c == 'u'
- && getch () == 'n'
- && getch () == 'i'
- && getch () == 't'
- && ((c = getch ()) == ' ' || c == '\t'))
+ token = real_yylex ();
+ if (token == IDENTIFIER
+ && TREE_CODE (yylval.ttype) == IDENTIFIER_NODE)
{
- /* More follows: it must be a string constant (unit name). */
- token = real_yylex ();
- if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid #pragma unit");
- goto skipline;
- }
- current_unit_name = get_identifier (TREE_STRING_POINTER (yylval.ttype));
- current_unit_language = current_lang_name;
- if (nextchar < 0)
- nextchar = getch ();
- c = nextchar;
- if (c != EOF)
- warning ("trailing characters ignored");
+ /* If this is 1, we handled it; if it's -1, it was one we
+ wanted but had something wrong with it. Only if it's
+ 0 was it not handled. */
+ if (handle_cp_pragma (IDENTIFIER_POINTER (yylval.ttype)))
+ goto skipline;
}
- else if (c == 'i')
- {
- tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
- c = getch ();
-
- if (c == 'n'
- && getch () == 't'
- && getch () == 'e'
- && getch () == 'r'
- && getch () == 'f'
- && getch () == 'a'
- && getch () == 'c'
- && getch () == 'e'
- && ((c = getch ()) == ' ' || c == '\t' || c == EOF))
- {
- int warned_already = 0;
- char *main_filename = input_filename;
-
- main_filename = FILE_NAME_NONDIRECTORY (main_filename);
- while (c == ' ' || c == '\t')
- c = getch ();
- if (c != EOF)
- {
- put_back (c);
- token = real_yylex ();
- if (token != STRING
- || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid `#pragma interface'");
- goto skipline;
- }
- main_filename = TREE_STRING_POINTER (yylval.ttype);
- c = getch();
- put_back (c);
- }
-
- while (c == ' ' || c == '\t')
- c = getch ();
-
- while (c != EOF)
- {
- if (!warned_already && extra_warnings
- && c != ' ' && c != '\t')
- {
- warning ("garbage after `#pragma interface' ignored");
- warned_already = 1;
- }
- c = getch ();
- }
-
- write_virtuals = 3;
-
- if (impl_file_chain == 0)
- {
- /* If this is zero at this point, then we are
- auto-implementing. */
- if (main_input_filename == 0)
- main_input_filename = input_filename;
-
-#ifdef AUTO_IMPLEMENT
- filename = FILE_NAME_NONDIRECTORY (main_input_filename);
- fi = get_time_identifier (filename);
- fi = IDENTIFIER_CLASS_VALUE (fi);
- TREE_INT_CST_LOW (fi) = 0;
- TREE_INT_CST_HIGH (fi) = 1;
- /* Get default. */
- impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
- impl_file_chain->filename = filename;
- impl_file_chain->next = 0;
-#endif
- }
-
- interface_only = interface_strcmp (main_filename);
- interface_unknown = 0;
- TREE_INT_CST_LOW (fileinfo) = interface_only;
- TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
- }
- else if (c == 'm'
- && getch () == 'p'
- && getch () == 'l'
- && getch () == 'e'
- && getch () == 'm'
- && getch () == 'e'
- && getch () == 'n'
- && getch () == 't'
- && getch () == 'a'
- && getch () == 't'
- && getch () == 'i'
- && getch () == 'o'
- && getch () == 'n'
- && ((c = getch ()) == ' ' || c == '\t' || c == EOF))
- {
- int warned_already = 0;
- char *main_filename = main_input_filename ? main_input_filename : input_filename;
-
- main_filename = FILE_NAME_NONDIRECTORY (main_filename);
- while (c == ' ' || c == '\t')
- c = getch ();
- if (c != EOF)
- {
- put_back (c);
- token = real_yylex ();
- if (token != STRING
- || TREE_CODE (yylval.ttype) != STRING_CST)
- {
- error ("invalid `#pragma implementation'");
- goto skipline;
- }
- main_filename = TREE_STRING_POINTER (yylval.ttype);
- c = getch();
- put_back (c);
- }
-
- while (c == ' ' || c == '\t')
- c = getch ();
-
- while (c != EOF)
- {
- if (!warned_already && extra_warnings
- && c != ' ' && c != '\t')
- {
- warning ("garbage after `#pragma implementation' ignored");
- warned_already = 1;
- }
- c = getch ();
- }
+ else if (token == END_OF_LINE)
+ goto skipline;
- if (write_virtuals == 3)
- {
- struct impl_files *ifiles = impl_file_chain;
- while (ifiles)
- {
- if (! strcmp (ifiles->filename, main_filename))
- break;
- ifiles = ifiles->next;
- }
- if (ifiles == 0)
- {
- ifiles = (struct impl_files*) permalloc (sizeof (struct impl_files));
- ifiles->filename = main_filename;
- ifiles->next = impl_file_chain;
- impl_file_chain = ifiles;
- }
- }
- else if ((main_input_filename != 0
- && ! strcmp (main_input_filename, input_filename))
- || ! strcmp (input_filename, main_filename))
- {
- write_virtuals = 3;
- if (impl_file_chain == 0)
- {
- impl_file_chain = (struct impl_files*) permalloc (sizeof (struct impl_files));
- impl_file_chain->filename = main_filename;
- impl_file_chain->next = 0;
- }
- }
- else
- error ("`#pragma implementation' can only appear at top-level");
- interface_only = 0;
-#if 1
- /* We make this non-zero so that we infer decl linkage
- in the impl file only for variables first declared
- in the interface file. */
- interface_unknown = 1;
-#else
- /* We make this zero so that templates in the impl
- file will be emitted properly. */
- interface_unknown = 0;
-#endif
- TREE_INT_CST_LOW (fileinfo) = interface_only;
- TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
- }
- }
#ifdef HANDLE_SYSV_PRAGMA
- else
- {
- put_back (c);
- handle_sysv_pragma ();
- }
+ if (handle_sysv_pragma (finput, token))
+ goto skipline;
#else
#ifdef HANDLE_PRAGMA
- /* FIXME: This will break if we're doing any of the C++ input
- tricks. */
- else
- {
- ungetc (c, finput);
- HANDLE_PRAGMA (finput);
- }
+ if (HANDLE_PRAGMA (finput, yylval.ttype))
+ goto skipline;
#endif
#endif
}
/* Here we have just seen `#ident '.
A string constant should follow. */
- while (c == ' ' || c == '\t')
- c = getch ();
-
- /* If no argument, ignore the line. */
- if (c == EOF)
- goto skipline;
-
- put_back (c);
token = real_yylex ();
+ if (token == END_OF_LINE)
+ goto skipline;
if (token != STRING
|| TREE_CODE (yylval.ttype) != STRING_CST)
{
body_time = this_time;
}
- if (flag_cadillac)
- cadillac_note_source ();
-
input_filename
= (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
extract_interface_info ();
c = get_last_nonwhite_on_line ();
- if (c != EOF)
+ if (c == EOF)
+ {
+ /* Update the name in the top element of input_file_stack. */
+ if (input_file_stack)
+ input_file_stack->name = input_filename;
+ }
+ else
{
put_back (c);
}
}
- /* Do the actions implied by the preceeding numbers. */
+ /* Do the actions implied by the preceding numbers. */
if (action == act_push)
{
p->name = input_filename;
input_file_stack = p;
input_file_stack_tick++;
+#ifdef DBX_DEBUGGING_INFO
+ if (write_symbols == DBX_DEBUG)
+ dbxout_start_new_source_file (input_filename);
+#endif
#ifdef DWARF_DEBUGGING_INFO
if (debug_info_level == DINFO_LEVEL_VERBOSE
&& write_symbols == DWARF_DEBUG)
dwarfout_start_new_source_file (input_filename);
#endif /* DWARF_DEBUGGING_INFO */
- if (flag_cadillac)
- cadillac_push_source ();
in_system_header = entering_system_header;
if (c_header_level)
++c_header_level;
warning ("badly nested C headers from preprocessor");
--pending_lang_change;
}
- if (flag_cadillac)
- cadillac_pop_source ();
in_system_header = entering_system_header;
p = input_file_stack;
input_file_stack = p->next;
free (p);
input_file_stack_tick++;
+#ifdef DBX_DEBUGGING_INFO
+ if (write_symbols == DBX_DEBUG)
+ dbxout_resume_previous_source_file ();
+#endif
#ifdef DWARF_DEBUGGING_INFO
if (debug_info_level == DINFO_LEVEL_VERBOSE
&& write_symbols == DWARF_DEBUG)
error ("#-lines for entering and leaving files don't match");
}
else
- {
- in_system_header = entering_system_header;
- if (flag_cadillac)
- cadillac_switch_source (-1);
- }
+ in_system_header = entering_system_header;
}
/* If NEXTCHAR is not end of line, we don't care what it is. */
skipline:
linemode = 0;
end_of_file = 0;
+ nextchar = -1;
while ((c = getch ()) != EOF && c != '\n');
return c;
}
switch (c)
{
case 'x':
- if (warn_traditional)
- warning ("the meaning of `\\x' varies with -traditional");
-
- if (flag_traditional)
- return c;
-
code = 0;
count = 0;
nonnull = 0;
return TARGET_BS;
case 'a':
- if (warn_traditional)
- warning ("the meaning of `\\a' varies with -traditional");
-
- if (flag_traditional)
- return c;
return TARGET_BELL;
case 'v':
Value is 0 if we treat this name in a default fashion. */
int looking_for_typename = 0;
-#if 0
-/* NO LONGER USED: Value is -1 if we must not see a type name. */
-void
-dont_see_typename ()
-{
- looking_for_typename = -1;
- if (yychar == TYPENAME || yychar == PTYPENAME)
- {
- yychar = IDENTIFIER;
- lastiddecl = 0;
- }
-}
-#endif
-
#ifdef __GNUC__
extern __inline int identifier_type ();
__inline
identifier_type (decl)
tree decl;
{
- if (TREE_CODE (decl) == TEMPLATE_DECL
- && DECL_TEMPLATE_IS_CLASS (decl))
- return PTYPENAME;
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ {
+ if (TREE_CODE (DECL_RESULT (decl)) == TYPE_DECL)
+ return PTYPENAME;
+ }
+ if (TREE_CODE (decl) == NAMESPACE_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))
+ return SELFNAME;
return TYPENAME;
}
void
see_typename ()
{
+ looking_for_typename = 1;
+ if (yychar < 0)
+ if ((yychar = yylex ()) < 0) yychar = 0;
looking_for_typename = 0;
if (yychar == IDENTIFIER)
{
}
tree
-do_identifier (token)
+do_identifier (token, parsing)
register tree token;
+ int parsing;
{
- register tree id = lastiddecl;
+ register tree id;
- if (yychar == YYEMPTY)
+ if (! parsing || IDENTIFIER_OPNAME_P (token))
+ id = lookup_name (token, 0);
+ else
+ id = lastiddecl;
+
+ if (parsing && yychar == YYEMPTY)
yychar = yylex ();
/* Scope class declarations before global
declarations. */
if (id == IDENTIFIER_GLOBAL_VALUE (token)
&& current_class_type != 0
- && TYPE_SIZE (current_class_type) == 0
- && TREE_CODE (current_class_type) != UNINSTANTIATED_P_TYPE)
+ && TYPE_SIZE (current_class_type) == 0)
{
/* Could be from one of the base classes. */
tree field = lookup_field (current_class_type, token, 1, 0);
/* Remember that this name has been used in the class definition, as per
[class.scope0] */
- if (id && current_class_type
+ if (id && current_class_type && parsing
&& TYPE_BEING_DEFINED (current_class_type)
&& ! IDENTIFIER_CLASS_VALUE (token))
pushdecl_class_level (id);
if (id && id != error_mark_node && TREE_TYPE (id) == error_mark_node)
return id;
}
- if (yychar == '(' || yychar == LEFT_RIGHT)
+
+ if (current_template_parms)
+ return build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
+ else if (IDENTIFIER_OPNAME_P (token))
+ {
+ if (token != ansi_opname[ERROR_MARK])
+ cp_error ("`%D' not defined", token);
+ id = error_mark_node;
+ }
+ else if (parsing && (yychar == '(' || yychar == LEFT_RIGHT))
{
id = implicitly_declare (token);
}
SET_IDENTIFIER_ERROR_LOCUS (token, current_function_decl);
}
}
+
+ if (TREE_CODE (id) == VAR_DECL && DECL_DEAD_FOR_LOCAL (id))
+ {
+ tree shadowed = DECL_SHADOWED_FOR_VAR (id);
+ while (shadowed != NULL_TREE && TREE_CODE (shadowed) == VAR_DECL
+ && DECL_DEAD_FOR_LOCAL (shadowed))
+ shadowed = DECL_SHADOWED_FOR_VAR (shadowed);
+ if (!shadowed)
+ shadowed = IDENTIFIER_GLOBAL_VALUE (DECL_NAME (id));
+ if (shadowed)
+ {
+ if (!DECL_ERROR_REPORTED (id))
+ {
+ warning ("name lookup of `%s' changed",
+ IDENTIFIER_POINTER (token));
+ cp_warning_at (" matches this `%D' under current ANSI rules",
+ shadowed);
+ cp_warning_at (" matches this `%D' under old rules", id);
+ DECL_ERROR_REPORTED (id) = 1;
+ }
+ id = shadowed;
+ }
+ else if (!DECL_ERROR_REPORTED (id))
+ {
+ static char msg[]
+ = "name lookup of `%s' changed for new ANSI `for' scoping";
+ DECL_ERROR_REPORTED (id) = 1;
+ if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (id)))
+ {
+ error (msg, IDENTIFIER_POINTER (token));
+ cp_error_at (" cannot use obsolete binding at `%D' because it has a destructor", id);
+ id = error_mark_node;
+ }
+ else
+ {
+ pedwarn (msg, IDENTIFIER_POINTER (token));
+ cp_pedwarn_at (" using obsolete binding at `%D'", id);
+ }
+ }
+ }
/* TREE_USED is set in `hack_identifier'. */
if (TREE_CODE (id) == CONST_DECL)
{
if (IDENTIFIER_CLASS_VALUE (token) == id)
{
/* Check access. */
- enum access_type access
- = compute_access (TYPE_BINFO (current_class_type), id);
- if (access == access_private)
+ 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'. */
}
- id = DECL_INITIAL (id);
+ if (! processing_template_decl
+ || (DECL_INITIAL (id)
+ && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_CONST_PARM))
+ 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_GLOBAL_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 */
+ }
+
+ return id;
+}
+
+tree
+do_scoped_id (token, parsing)
+ tree token;
+ int parsing;
+{
+ tree id = IDENTIFIER_GLOBAL_VALUE (token);
+ if (parsing && yychar == YYEMPTY)
+ yychar = yylex ();
+ if (! id)
+ {
+ if (processing_template_decl)
+ {
+ id = build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
+ LOOKUP_EXPR_GLOBAL (id) = 1;
+ return id;
+ }
+ if (parsing && yychar == '(' || yychar == LEFT_RIGHT)
+ id = implicitly_declare (token);
+ else
+ {
+ if (IDENTIFIER_GLOBAL_VALUE (token) != error_mark_node)
+ error ("undeclared variable `%s' (first use here)",
+ IDENTIFIER_POINTER (token));
+ id = error_mark_node;
+ /* Prevent repeated error messages. */
+ IDENTIFIER_GLOBAL_VALUE (token) = error_mark_node;
+ }
}
else
- id = hack_identifier (id, token, yychar);
+ {
+ if (TREE_CODE (id) == ADDR_EXPR)
+ mark_used (TREE_OPERAND (id, 0));
+ else if (TREE_CODE (id) != TREE_LIST)
+ mark_used (id);
+ }
+ if (TREE_CODE (id) == CONST_DECL && ! processing_template_decl)
+ {
+ /* XXX CHS - should we set TREE_USED of the constant? */
+ id = DECL_INITIAL (id);
+ /* This is to prevent an enum whose value is 0
+ from being considered a null pointer constant. */
+ id = build1 (NOP_EXPR, TREE_TYPE (id), id);
+ TREE_CONSTANT (id) = 1;
+ }
+
+ if (processing_template_decl)
+ {
+ if (is_overloaded_fn (id))
+ {
+ id = build_min (LOOKUP_EXPR, unknown_type_node,
+ token, get_first_fn (id));
+ LOOKUP_EXPR_GLOBAL (id) = 1;
+ }
+ /* else just use the decl */
+ }
return id;
}
return NULL_TREE;
}
-struct try_type
-{
- tree *node_var;
- char unsigned_flag;
- char long_flag;
- char long_long_flag;
-};
-
-struct try_type type_sequence[] =
-{
- { &integer_type_node, 0, 0, 0},
- { &unsigned_type_node, 1, 0, 0},
- { &long_integer_type_node, 0, 1, 0},
- { &long_unsigned_type_node, 1, 1, 0},
- { &long_long_integer_type_node, 0, 1, 1},
- { &long_long_unsigned_type_node, 1, 1, 1}
-};
-
int
real_yylex ()
{
value = END_OF_SAVED_INPUT;
else if (linemode)
value = END_OF_LINE;
- else if (do_pending_expansions ())
- /* this will set yychar for us */
- return yychar;
else
value = ENDFILE;
break;
*p++ = c;
c = getc (finput);
}
+
+ if (linemode && c == '\n')
+ {
+ put_back (c);
+ c = EOF;
+ }
}
else
{
switch (ptr->rid)
{
case RID_PUBLIC:
- yylval.itype = access_public;
+ yylval.ttype = access_public_node;
break;
case RID_PRIVATE:
- yylval.itype = access_private;
+ yylval.ttype = access_private_node;
break;
case RID_PROTECTED:
- yylval.itype = access_protected;
+ yylval.ttype = access_protected_node;
break;
default:
my_friendly_abort (63);
token_buffer[0] = '^';
token_buffer[1] = 0;
}
+ else if (ptr->token == NAMESPACE)
+ {
+ static int warned;
+ if (! warned)
+ warning ("namespaces are mostly broken in this version of g++");
+
+ warned = 1;
+ }
value = (int) ptr->token;
}
|| strcmp ("try", token_buffer) == 0)
{
static int did_warn = 0;
- if (! did_warn && ! flag_handle_exceptions)
+ if (! did_warn && ! flag_exceptions)
{
pedwarn ("`catch', `throw', and `try' are all C++ reserved words");
did_warn = 1;
&& DECL_INITIAL (tmp) != NULL_TREE
&& TREE_CODE (DECL_INITIAL (tmp)) == STRING_CST)
{
- yylval.ttype = DECL_INITIAL (tmp);
+ tree stringval = DECL_INITIAL (tmp);
+
+ /* Copy the string value so that we won't clobber anything
+ if we put something in the TREE_CHAIN of this one. */
+ yylval.ttype = build_string (TREE_STRING_LENGTH (stringval),
+ TREE_STRING_POINTER (stringval));
value = STRING;
}
}
}
put_back (c1);
}
- /* fall through... */
+ /* fall through... */
case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
resume_numerical_scan:
set_float_handler (handler);
/* The second argument, machine_mode, of REAL_VALUE_ATOF
tells the desired precision of the binary result of
- decimal-to-binary conversion. */
+ decimal-to-binary conversion. */
/* Read the suffixes to choose a data type. */
switch (c)
yylval.ttype = build_int_2 (low, high);
TREE_TYPE (yylval.ttype) = long_long_unsigned_type_node;
-#if 0
- /* Find the first allowable type that the value fits in. */
- type = 0;
- for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
- i++)
- if (!(spec_long && !type_sequence[i].long_flag)
- && !(spec_long_long && !type_sequence[i].long_long_flag)
- && !(spec_unsigned && !type_sequence[i].unsigned_flag)
- /* A hex or octal constant traditionally is unsigned. */
- && !(base != 10 && flag_traditional
- && !type_sequence[i].unsigned_flag)
- /* A decimal constant can't be unsigned int
- unless explicitly specified. */
- && !(base == 10 && !spec_unsigned
- && *type_sequence[i].node_var == unsigned_type_node))
- if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
- {
- type = *type_sequence[i].node_var;
- break;
- }
- if (flag_traditional && type == long_unsigned_type_node
- && !spec_unsigned)
- type = long_integer_type_node;
-
- if (type == 0)
- {
- type = long_long_integer_type_node;
- warning ("integer constant out of range");
- }
-
- /* Warn about some cases where the type of a given constant
- changes from traditional C to ANSI C. */
- if (warn_traditional)
- {
- tree other_type = 0;
-
- /* This computation is the same as the previous one
- except that flag_traditional is used backwards. */
- for (i = 0; i < sizeof (type_sequence) / sizeof (type_sequence[0]);
- i++)
- if (!(spec_long && !type_sequence[i].long_flag)
- && !(spec_long_long && !type_sequence[i].long_long_flag)
- && !(spec_unsigned && !type_sequence[i].unsigned_flag)
- /* A hex or octal constant traditionally is unsigned. */
- && !(base != 10 && !flag_traditional
- && !type_sequence[i].unsigned_flag)
- /* A decimal constant can't be unsigned int
- unless explicitly specified. */
- && !(base == 10 && !spec_unsigned
- && *type_sequence[i].node_var == unsigned_type_node))
- if (int_fits_type_p (yylval.ttype, *type_sequence[i].node_var))
- {
- other_type = *type_sequence[i].node_var;
- break;
- }
- if (!flag_traditional && type == long_unsigned_type_node
- && !spec_unsigned)
- type = long_integer_type_node;
-
- if (other_type != 0 && other_type != type)
- {
- if (flag_traditional)
- warning ("type of integer constant would be different without -traditional");
- else
- warning ("type of integer constant would be different with -traditional");
- }
- }
-
-#else /* 1 */
if (!spec_long && !spec_unsigned
- && !(flag_traditional && base != 10)
&& int_fits_type_p (yylval.ttype, integer_type_node))
{
-#if 0
- if (warn_traditional && base != 10)
- warning ("small nondecimal constant becomes signed in ANSI C++");
-#endif
type = integer_type_node;
}
else if (!spec_long && (base != 10 || spec_unsigned)
else if (! spec_long_long
&& int_fits_type_p (yylval.ttype,
long_unsigned_type_node))
- {
-#if 0
- if (warn_traditional && !spec_unsigned)
- warning ("large integer constant becomes unsigned in ANSI C++");
-#endif
- if (flag_traditional && !spec_unsigned)
- type = long_integer_type_node;
- else
- type = long_unsigned_type_node;
- }
+ type = long_unsigned_type_node;
else if (! spec_unsigned
/* Verify value does not overflow into sign bit. */
else if (int_fits_type_p (yylval.ttype,
long_long_unsigned_type_node))
- {
-#if 0
- if (warn_traditional && !spec_unsigned)
- warning ("large nondecimal constant is unsigned in ANSI C++");
-#endif
-
- if (flag_traditional && !spec_unsigned)
- type = long_long_integer_type_node;
- else
- type = long_long_unsigned_type_node;
- }
+ type = long_long_unsigned_type_node;
else
{
if (base == 10 && ! spec_unsigned && TREE_UNSIGNED (type))
warning ("decimal integer constant is so large that it is unsigned");
}
-#endif
TREE_TYPE (yylval.ttype) = type;
*p = 0;
num_chars = max_chars;
error ("character constant too long");
}
- else if (num_chars != 1 && ! flag_traditional)
+ else if (num_chars != 1)
warning ("multi-character character constant");
/* If char type is signed, sign-extend the constant. */
skipnewline:
c = getch ();
if (c == EOF) {
- error("Unterminated string");
+ error ("Unterminated string");
break;
}
}
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;
}
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;
}
{ value = '}'; goto done; }
else if (c == '%' && c1 == ':')
{ value = '#'; goto done; }
- else if (c == ':' && c1 == '>')
- { value = ']'; goto done; }
nextchar = c1;
token_buffer[1] = 0;
value = SCOPE;
yylval.itype = 1;
}
+ else if (c == '>')
+ {
+ value = ']';
+ goto done;
+ }
else
{
nextchar = c;
done:
/* yylloc.last_line = lineno; */
#ifdef GATHER_STATISTICS
+#ifdef REDUCE_LENGTH
token_count[value] += 1;
#endif
+#endif
return value;
}
+int
+is_rid (t)
+ tree t;
+{
+ return !!is_reserved_word (IDENTIFIER_POINTER (t), IDENTIFIER_LENGTH (t));
+}
+
+#ifdef GATHER_STATISTICS
+/* The original for tree_node_kind is in the toplevel tree.c; changes there
+ need to be brought into here, unless this were actually put into a header
+ instead. */
+/* Statistics-gathering stuff. */
typedef enum
{
- d_kind, t_kind, s_kind, r_kind, e_kind, c_kind,
- id_kind, op_id_kind, perm_list_kind, temp_list_kind,
- vec_kind, x_kind, lang_decl, lang_type, all_kinds
+ d_kind,
+ t_kind,
+ b_kind,
+ s_kind,
+ r_kind,
+ e_kind,
+ c_kind,
+ id_kind,
+ op_id_kind,
+ perm_list_kind,
+ temp_list_kind,
+ vec_kind,
+ x_kind,
+ lang_decl,
+ lang_type,
+ all_kinds
} tree_node_kind;
+
extern int tree_node_counts[];
extern int tree_node_sizes[];
-extern char *tree_node_kind_names[];
+#endif
/* Place to save freed lang_decls which were allocated on the
permanent_obstack. @@ Not currently used. */
== TREE_PERMANENT (t), 234);
DECL_MAIN_VARIANT (t) = t;
if (current_lang_name == lang_name_cplusplus)
- {
- DECL_LANGUAGE (t) = lang_cplusplus;
-#if 0
-#ifndef NO_AUTO_OVERLOAD
- if (code == FUNCTION_DECL && name != 0
- && ! (IDENTIFIER_LENGTH (name) == 4
- && IDENTIFIER_POINTER (name)[0] == 'm'
- && strcmp (IDENTIFIER_POINTER (name), "main") == 0)
- && ! (IDENTIFIER_LENGTH (name) > 10
- && IDENTIFIER_POINTER (name)[0] == '_'
- && IDENTIFIER_POINTER (name)[1] == '_'
- && strncmp (IDENTIFIER_POINTER (name)+2, "builtin_", 8) == 0))
- TREE_OVERLOADED (name) = 1;
-#endif
-#endif
- }
+ DECL_LANGUAGE (t) = lang_cplusplus;
else if (current_lang_name == lang_name_c)
DECL_LANGUAGE (t) = lang_c;
else my_friendly_abort (64);
#endif
#ifdef GATHER_STATISTICS
tree_node_counts[(int)lang_decl] += 1;
- tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
+ tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl);
#endif
return t;
int size;
int *pi;
+ if (! DECL_LANG_SPECIFIC (node))
+ return;
+
if (TREE_CODE (node) == FIELD_DECL)
size = sizeof (struct lang_decl_flags);
else
#ifdef GATHER_STATISTICS
tree_node_counts[(int)lang_type] += 1;
- tree_node_sizes[(int)lang_type] += sizeof(struct lang_type);
+ tree_node_sizes[(int)lang_type] += sizeof (struct lang_type);
#endif
return t;
#ifdef GATHER_STATISTICS
tree_node_counts[(int)lang_decl] += 1;
- tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
+ tree_node_sizes[(int)lang_decl] += sizeof (struct lang_decl);
#endif
}
sprintf (buf, s, v, v2);
error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
}
-
-void
-compiler_error_with_decl (decl, s)
- tree decl;
- char *s;
-{
- char *name;
- count_error (0);
-
- report_error_function (0);
-
- if (TREE_CODE (decl) == PARM_DECL)
- fprintf (stderr, "%s:%d: ",
- DECL_SOURCE_FILE (DECL_CONTEXT (decl)),
- DECL_SOURCE_LINE (DECL_CONTEXT (decl)));
- else
- fprintf (stderr, "%s:%d: ",
- DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
-
- name = lang_printable_name (decl);
- if (name)
- fprintf (stderr, s, name);
- else
- fprintf (stderr, s, "((anonymous))");
- fprintf (stderr, " (compiler error)\n");
-}
\f
void
yyerror (string)
error (buf, token_buffer);
}
\f
+int
+handle_cp_pragma (pname)
+ char *pname;
+{
+ register int token;
+
+ if (! strcmp (pname, "vtable"))
+ {
+ extern tree pending_vtables;
+
+ /* More follows: it must be a string constant (class name). */
+ token = real_yylex ();
+ if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
+ {
+ error ("invalid #pragma vtable");
+ return -1;
+ }
+
+ if (write_virtuals != 2)
+ {
+ warning ("use `+e2' option to enable #pragma vtable");
+ return -1;
+ }
+ pending_vtables
+ = perm_tree_cons (NULL_TREE,
+ get_identifier (TREE_STRING_POINTER (yylval.ttype)),
+ pending_vtables);
+ token = real_yylex ();
+ if (token != END_OF_LINE)
+ warning ("trailing characters ignored");
+ return 1;
+ }
+ else if (! strcmp (pname, "unit"))
+ {
+ /* More follows: it must be a string constant (unit name). */
+ token = real_yylex ();
+ if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
+ {
+ error ("invalid #pragma unit");
+ return -1;
+ }
+ token = real_yylex ();
+ if (token != END_OF_LINE)
+ warning ("trailing characters ignored");
+ return 1;
+ }
+ else if (! strcmp (pname, "interface"))
+ {
+ tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
+ int warned_already = 0;
+ char *main_filename = input_filename;
+
+ main_filename = FILE_NAME_NONDIRECTORY (main_filename);
+
+ token = real_yylex ();
+
+ if (token != END_OF_LINE)
+ {
+ if (token != STRING
+ || TREE_CODE (yylval.ttype) != STRING_CST)
+ {
+ error ("invalid `#pragma interface'");
+ return -1;
+ }
+ main_filename = TREE_STRING_POINTER (yylval.ttype);
+ }
+
+ while (token != END_OF_LINE)
+ {
+ if (!warned_already && extra_warnings)
+ {
+ warning ("garbage after `#pragma interface' ignored");
+ warned_already = 1;
+ }
+ token = real_yylex ();
+ }
+
+#ifndef NO_LINKAGE_HEURISTICS
+ write_virtuals = 3;
+
+ if (impl_file_chain == 0)
+ {
+ /* If this is zero at this point, then we are
+ auto-implementing. */
+ if (main_input_filename == 0)
+ main_input_filename = input_filename;
+
+#ifdef AUTO_IMPLEMENT
+ filename = FILE_NAME_NONDIRECTORY (main_input_filename);
+ fi = get_time_identifier (filename);
+ fi = IDENTIFIER_CLASS_VALUE (fi);
+ TREE_INT_CST_LOW (fi) = 0;
+ TREE_INT_CST_HIGH (fi) = 1;
+ /* Get default. */
+ impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
+ impl_file_chain->filename = filename;
+ impl_file_chain->next = 0;
+#endif
+ }
+
+ interface_only = interface_strcmp (main_filename);
+ interface_unknown = 0;
+ 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));
+ int warned_already = 0;
+ char *main_filename = main_input_filename ? main_input_filename : input_filename;
+
+ main_filename = FILE_NAME_NONDIRECTORY (main_filename);
+ token = real_yylex ();
+ if (token != END_OF_LINE)
+ {
+ if (token != STRING
+ || TREE_CODE (yylval.ttype) != STRING_CST)
+ {
+ error ("invalid `#pragma implementation'");
+ return -1;
+ }
+ main_filename = TREE_STRING_POINTER (yylval.ttype);
+ }
+
+ while (token != END_OF_LINE)
+ {
+ if (!warned_already && extra_warnings)
+ {
+ warning ("garbage after `#pragma implementation' ignored");
+ warned_already = 1;
+ }
+ token = real_yylex ();
+ }
+
+#ifndef NO_LINKAGE_HEURISTICS
+ if (write_virtuals == 3)
+ {
+ struct impl_files *ifiles = impl_file_chain;
+ while (ifiles)
+ {
+ if (! strcmp (ifiles->filename, main_filename))
+ break;
+ ifiles = ifiles->next;
+ }
+ if (ifiles == 0)
+ {
+ ifiles = (struct impl_files*) permalloc (sizeof (struct impl_files));
+ ifiles->filename = main_filename;
+ ifiles->next = impl_file_chain;
+ impl_file_chain = ifiles;
+ }
+ }
+ else if ((main_input_filename != 0
+ && ! strcmp (main_input_filename, input_filename))
+ || ! strcmp (input_filename, main_filename))
+ {
+ write_virtuals = 3;
+ if (impl_file_chain == 0)
+ {
+ impl_file_chain = (struct impl_files*) permalloc (sizeof (struct impl_files));
+ impl_file_chain->filename = main_filename;
+ impl_file_chain->next = 0;
+ }
+ }
+ else
+ error ("`#pragma implementation' can only appear at top-level");
+ interface_only = 0;
+#if 1
+ /* We make this non-zero so that we infer decl linkage
+ in the impl file only for variables first declared
+ in the interface file. */
+ interface_unknown = 1;
+#else
+ /* We make this zero so that templates in the impl
+ file will be emitted properly. */
+ interface_unknown = 0;
+#endif
+ TREE_INT_CST_LOW (fileinfo) = interface_only;
+ TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
+#endif /* NO_LINKAGE_HEURISTICS */
+
+ return 1;
+ }
+
+ return 0;
+}
+\f
#ifdef HANDLE_SYSV_PRAGMA
/* Handle a #pragma directive. INPUT is the current input stream,
/* This function has to be in this file, in order to get at
the token types. */
-handle_sysv_pragma ()
+int
+handle_sysv_pragma (finput, token)
+ FILE *finput;
+ register int token;
{
for (;;)
{
- switch (yylex ())
+ switch (token)
{
case IDENTIFIER:
case TYPENAME:
case STRING:
case CONSTANT:
- handle_pragma_token (token_buffer, yylval.ttype);
+ 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);
+ break;
+ case LEFT_RIGHT:
+ handle_pragma_token ("(", NULL_TREE);
+ handle_pragma_token (")", NULL_TREE);
break;
case END_OF_LINE:
- handle_pragma_token (0, 0);
- return;
default:
- handle_pragma_token (token_buffer, 0);
+ handle_pragma_token (NULL_PTR, NULL_TREE);
+ return 1;
}
+ token = real_yylex ();
}
}
#endif /* HANDLE_SYSV_PRAGMA */