OSDN Git Service

91th Cygnus<->FSF merge
[pf3gnuchains/gcc-fork.git] / gcc / cp / lex.c
index 895f269..befb5a1 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
@@ -16,7 +16,8 @@ GNU General Public License for more details.
 
 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++.  */
@@ -32,10 +33,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #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>
@@ -45,12 +47,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #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 ();
@@ -66,20 +67,11 @@ extern char *get_directive_line (); /* In c-common.c */
 
 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;
 
@@ -134,48 +126,40 @@ static tree get_time_identifier ();
 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)
     {
@@ -193,9 +177,26 @@ make_reference_declarator (type_quals, 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.  */
 
@@ -270,7 +271,7 @@ char *token_buffer;         /* Pointer to token buffer.
 
 #include "hash.h"
 \f
-int check_newline ();
+static int check_newline ();
 
 /* Nonzero tells yylex to ignore \ in string constants.  */
 static int ignore_escape_flag = 0;
@@ -317,13 +318,13 @@ my_get_run_time ()
 \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
 
@@ -335,7 +336,7 @@ char *cplus_tree_code_type[] = {
 
 int cplus_tree_code_length[] = {
   0,
-#include "tree.def"
+#include "cp-tree.def"
 };
 #undef DEFTREECODE
 
@@ -345,7 +346,7 @@ int cplus_tree_code_length[] = {
 
 char *cplus_tree_code_name[] = {
   "@@dummy",
-#include "tree.def"
+#include "cp-tree.def"
 };
 #undef DEFTREECODE
 \f
@@ -358,10 +359,8 @@ lang_init ()
   /* 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
@@ -392,12 +391,17 @@ init_filename_times ()
 /* 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.    */
+
+#if 0
 void
 reinit_lang_specific ()
 {
   init_filename_times ();
   reinit_search_statistics ();
 }
+#endif
+
+int *init_parse ();
 
 void
 init_lex ()
@@ -571,9 +575,6 @@ 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.  */
@@ -639,7 +640,7 @@ init_lex ()
   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]));
@@ -681,7 +682,7 @@ init_lex ()
   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]));
@@ -691,17 +692,20 @@ init_lex ()
   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] = "-";
@@ -738,9 +742,9 @@ init_lex ()
   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] = "--";
@@ -782,7 +786,7 @@ init_lex ()
 
 #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");
@@ -790,7 +794,7 @@ init_lex ()
     }
 #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");
@@ -808,15 +812,17 @@ init_lex ()
     {
       /* 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;
@@ -852,6 +858,11 @@ yyprint (file, yychar, yylval)
     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));
@@ -873,16 +884,22 @@ yyprint (file, yychar, yylval)
     }
 }
 
+#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;
@@ -890,10 +907,12 @@ init_parse ()
   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;
@@ -915,11 +934,13 @@ token_cmp (p, q)
   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;
@@ -937,13 +958,13 @@ print_parse_statistics ()
   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++)
@@ -951,22 +972,24 @@ print_parse_statistics ()
   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;
@@ -1009,6 +1032,7 @@ static struct impl_files *impl_file_chain;
 
 /* Helper function to load global variables with interface
    information.  */
+
 void
 extract_interface_info ()
 {
@@ -1025,12 +1049,12 @@ 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;
@@ -1069,7 +1093,7 @@ interface_strcmp (s)
   return 1;
 }
 
-void
+static void
 set_typedecl_interface_info (prev, vars)
      tree prev, vars;
 {
@@ -1081,7 +1105,7 @@ set_typedecl_interface_info (prev, vars)
     = interface_strcmp (FILE_NAME_NONDIRECTORY (DECL_SOURCE_FILE (vars)));
 }
 
-void
+static int
 set_vardecl_interface_info (prev, vars)
      tree prev, vars;
 {
@@ -1090,22 +1114,26 @@ set_vardecl_interface_info (prev, vars)
   if (CLASSTYPE_INTERFACE_KNOWN (type))
     {
       if (CLASSTYPE_INTERFACE_ONLY (type))
-       set_typedecl_interface_info (prev, TYPE_NAME (type));
+       set_typedecl_interface_info (prev, TYPE_MAIN_DECL (type));
       else
        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)
@@ -1114,7 +1142,7 @@ do_pending_inlines ()
   /* 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;
 
@@ -1125,33 +1153,6 @@ do_pending_inlines ()
        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;
   }
 
@@ -1159,10 +1160,9 @@ do_pending_inlines ()
     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);
@@ -1184,13 +1184,6 @@ do_pending_inlines ()
   /* 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;
 }
 
@@ -1200,27 +1193,27 @@ static int nextchar = -1;
 /* 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;
@@ -1230,22 +1223,14 @@ process_next_inline (t)
   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)
@@ -1362,6 +1347,7 @@ restore_pending_input (p)
 
 /* Return next non-whitespace input character, which may come
    from `finput', or from `nextchar'.  */
+
 static int
 yynextch ()
 {
@@ -1379,6 +1365,7 @@ 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;
@@ -1403,102 +1390,22 @@ yyungetc (ch, rescan)
 /* 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 ();
+static void reinit_parse_for_block PROTO((int, struct obstack *));
 
 void
 reinit_parse_for_method (yychar, decl)
@@ -1509,7 +1416,7 @@ reinit_parse_for_method (yychar, decl)
   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;
@@ -1538,24 +1445,22 @@ reinit_parse_for_method (yychar, decl)
       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 (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;
+static void
+reinit_parse_for_block (pyychar, obstackp)
+     int pyychar;
      struct obstack *obstackp;
-     int is_template;
 {
   register int c = 0;
   int blev = 1;
@@ -1565,23 +1470,33 @@ reinit_parse_for_block (yychar, obstackp, is_template)
   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_1grow (obstackp, yychar);
+      obstack_grow (obstackp, "return", 6);
       look_for_lbrac = 1;
       blev = 0;
     }
+  else if (pyychar == TRY)
+    {
+      obstack_grow (obstackp, "try", 3);
+      look_for_lbrac = 1;
+      blev = 0;
+    }
+  else
+    {
+      yyerror ("parse error in method specification");
+      obstack_1grow (obstackp, '{');
+    }
 
   if (nextchar != EOF)
     {
@@ -1633,7 +1548,26 @@ reinit_parse_for_block (yychar, obstackp, is_template)
            {
              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 == '\\')
            {
@@ -1657,9 +1591,7 @@ reinit_parse_for_block (yychar, obstackp, is_template)
            {
              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;
@@ -1705,13 +1637,10 @@ cons_up_default_function (type, full_name, kind)
      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);
 
   switch (kind)
@@ -1728,7 +1657,6 @@ cons_up_default_function (type, full_name, kind)
     case 2:
       /* Default constructor.  */
       args = void_list_node;
-      complex = TYPE_NEEDS_CONSTRUCTING (type);
       break;
 
     case 3:
@@ -1742,15 +1670,15 @@ cons_up_default_function (type, full_name, kind)
                        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:
-      type = build_type_variant (type, 1, 0);
-      /* Fall through...  */
     case 6:
       retref = 1;
-      declspecs = build_decl_list (NULL_TREE, full_name);
+      declspecs = build_decl_list (NULL_TREE, type);
+
+      if (kind == 5)
+       type = build_type_variant (type, 1, 0);
 
       name = ansi_opname [(int) MODIFY_EXPR];
 
@@ -1759,7 +1687,6 @@ cons_up_default_function (type, full_name, kind)
                        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:
@@ -1772,7 +1699,7 @@ cons_up_default_function (type, full_name, kind)
   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);
     
@@ -1782,36 +1709,29 @@ cons_up_default_function (type, full_name, kind)
   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
 #if 0
-      || ! flag_no_inline
-      || complex
-#endif
-      || ! DECL_EXTERNAL (fn))
+  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;
@@ -1840,357 +1760,10 @@ cons_up_default_function (type, full_name, kind)
   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;
@@ -2201,7 +1774,8 @@ check_for_missing_semicolon (type)
   if ((yychar > 255
        && yychar != SCSPEC
        && yychar != IDENTIFIER
-       && yychar != TYPENAME)
+       && yychar != TYPENAME
+       && yychar != SELFNAME)
       || end_of_file)
     {
       if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
@@ -2323,7 +1897,12 @@ get_last_nonwhite_on_line ()
 
 int linemode;
 
-int
+#ifdef HANDLE_SYSV_PRAGMA
+static int handle_sysv_pragma ();
+#endif
+static int handle_cp_pragma ();
+
+static int
 check_newline ()
 {
   register int c;
@@ -2367,250 +1946,26 @@ 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
            }
@@ -2625,11 +1980,7 @@ check_newline ()
              && getch () == 'e'
              && ((c = getch ()) == ' ' || c == '\t'))
            {
-#ifdef DWARF_DEBUGGING_INFO
-             if ((debug_info_level == DINFO_LEVEL_VERBOSE)
-                 && (write_symbols == DWARF_DEBUG))
-               dwarfout_define (lineno, get_directive_line (finput));
-#endif /* DWARF_DEBUGGING_INFO */
+             debug_define (lineno, get_directive_line (finput));
              goto skipline;
            }
        }
@@ -2641,11 +1992,7 @@ check_newline ()
              && getch () == 'f'
              && ((c = getch ()) == ' ' || c == '\t'))
            {
-#ifdef DWARF_DEBUGGING_INFO
-             if ((debug_info_level == DINFO_LEVEL_VERBOSE)
-                 && (write_symbols == DWARF_DEBUG))
-               dwarfout_undef (lineno, get_directive_line (finput));
-#endif /* DWARF_DEBUGGING_INFO */
+             debug_undef (lineno, get_directive_line (finput));
              goto skipline;
            }
        }
@@ -2673,15 +2020,9 @@ check_newline ()
              /* 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)
                {
@@ -2786,9 +2127,6 @@ linenum:
          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));
@@ -2880,7 +2218,7 @@ linenum:
                }
            }
 
-         /* Do the actions implied by the preceeding numbers.  */
+         /* Do the actions implied by the preceding numbers.  */
 
          if (action == act_push)
            {
@@ -2893,13 +2231,7 @@ linenum:
              p->name = input_filename;
              input_file_stack = p;
              input_file_stack_tick++;
-#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 ();
+             debug_start_source_file (input_filename);
              in_system_header = entering_system_header;
              if (c_header_level)
                ++c_header_level;
@@ -2922,29 +2254,19 @@ linenum:
                        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 DWARF_DEBUGGING_INFO
-                 if (debug_info_level == DINFO_LEVEL_VERBOSE
-                     && write_symbols == DWARF_DEBUG)
-                   dwarfout_resume_previous_source_file (input_file_stack->line);
-#endif /* DWARF_DEBUGGING_INFO */
+                 debug_end_source_file (input_file_stack->line);
                }
              else
                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.  */
@@ -2958,6 +2280,7 @@ linenum:
  skipline:
   linemode = 0;
   end_of_file = 0;
+  nextchar = -1;
   while ((c = getch ()) != EOF && c != '\n');
   return c;
 }
@@ -2996,12 +2319,6 @@ readescape (ignore_ptr)
   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;
@@ -3076,11 +2393,6 @@ readescape (ignore_ptr)
       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':
@@ -3117,20 +2429,6 @@ readescape (ignore_ptr)
    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
@@ -3139,17 +2437,28 @@ int
 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)
     {
@@ -3165,19 +2474,24 @@ see_typename ()
 }
 
 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);
@@ -3203,9 +2517,14 @@ do_identifier (token)
 
   /* 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))
+      && ! IDENTIFIER_CLASS_VALUE (token)
+      /* Avoid breaking if we get called for a default argument that
+        refers to an overloaded method.  Eventually this will not be
+        necessary, since default arguments shouldn't be parsed until
+        after the class is complete.  (jason 3/12/97) */
+      && TREE_CODE (id) != TREE_LIST)
     pushdecl_class_level (id);
     
   if (!id || id == error_mark_node)
@@ -3218,7 +2537,16 @@ do_identifier (token)
          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);
        }
@@ -3249,22 +2577,139 @@ do_identifier (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;
 }
 
@@ -3287,32 +2732,14 @@ identifier_typedecl_value (node)
   do (IDENTIFIER_GLOBAL_VALUE (node));
 #undef do
   /* Will this one ever happen?  */
-  if (TYPE_NAME (type))
-    return TYPE_NAME (type);
+  if (TYPE_MAIN_DECL (type))
+    return TYPE_MAIN_DECL (type);
 
   /* We used to do an internal error of 62 here, but instead we will
      handle the return of a null appropriately in the callers.  */
   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 ()
 {
@@ -3366,9 +2793,6 @@ 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;
@@ -3439,6 +2863,12 @@ real_yylex ()
                *p++ = c;
                c = getc (finput);
              }
+
+           if (linemode && c == '\n')
+             {
+               put_back (c);
+               c = EOF;
+             }
          }
        else
          {
@@ -3510,13 +2940,13 @@ real_yylex ()
                      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);
@@ -3570,6 +3000,14 @@ real_yylex ()
                  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;
            }
@@ -3578,18 +3016,6 @@ real_yylex ()
        /* If we did not find a keyword, look for an identifier
           (or a typename).  */
 
-       if (strcmp ("catch", token_buffer) == 0
-           || strcmp ("throw", token_buffer) == 0
-           || strcmp ("try", token_buffer) == 0)
-         {
-           static int did_warn = 0;
-           if (! did_warn  && ! flag_handle_exceptions)
-             {
-               pedwarn ("`catch', `throw', and `try' are all C++ reserved words");
-               did_warn = 1;
-             }
-         }
-
        if (value == IDENTIFIER || value == TYPESPEC)
          GNU_xref_ref (current_function_decl, token_buffer);
 
@@ -3630,7 +3056,12 @@ real_yylex ()
                && 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;
              }
          }
@@ -3694,7 +3125,7 @@ real_yylex ()
          }
        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:
@@ -3899,7 +3330,7 @@ real_yylex ()
                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)
@@ -3934,7 +3365,7 @@ real_yylex ()
                    ))
              {
                pedwarn ("floating point number exceeds range of `%s'",
-                        IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
+                        IDENTIFIER_POINTER (TYPE_IDENTIFIER (type)));
              }
            /* Note: garbage_chars is -1 if first char is *not* garbage.  */
            while (isalnum (c))
@@ -4057,83 +3488,9 @@ real_yylex ()
            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)
@@ -4150,16 +3507,7 @@ real_yylex ()
            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.  */
@@ -4170,17 +3518,7 @@ real_yylex ()
 
            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
              {
@@ -4190,7 +3528,6 @@ real_yylex ()
                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;
@@ -4281,7 +3618,7 @@ real_yylex ()
            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.  */
@@ -4369,7 +3706,7 @@ real_yylex ()
          skipnewline:
            c = getch ();
            if (c == EOF) {
-               error("Unterminated string");
+               error ("Unterminated string");
                break;
            }
          }
@@ -4410,12 +3747,20 @@ real_yylex ()
              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;
          }
 
@@ -4617,21 +3962,49 @@ real_yylex ()
 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.  */
@@ -4672,22 +4045,7 @@ build_lang_decl (code, name, type)
          == 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);
@@ -4703,7 +4061,7 @@ build_lang_decl (code, name, type)
 #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;
@@ -4750,6 +4108,9 @@ copy_lang_decl (node)
   int size;
   int *pi;
 
+  if (! DECL_LANG_SPECIFIC (node))
+    return;
+
   if (TREE_CODE (node) == FIELD_DECL)
     size = sizeof (struct lang_decl_flags);
   else
@@ -4797,40 +4158,13 @@ make_lang_type (code)
 
 #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;
 }
 
 void
-copy_decl_lang_specific (decl)
-     tree decl;
-{
-  extern struct obstack *current_obstack, *saveable_obstack;
-  register int *old = (int *)DECL_LANG_SPECIFIC (decl);
-  struct obstack *obstack = current_obstack;
-  register int i = sizeof (struct lang_decl) / sizeof (int);
-  register int *pi;
-
-  if (! TREE_PERMANENT (decl))
-    obstack = saveable_obstack;
-  else
-    my_friendly_assert (obstack == &permanent_obstack, 237);
-
-  pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
-  while (i-- > 0)
-    pi[i] = old[i];
-
-  DECL_LANG_SPECIFIC (decl) = (struct lang_decl *) pi;
-
-#ifdef GATHER_STATISTICS
-  tree_node_counts[(int)lang_decl] += 1;
-  tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
-#endif
-}
-
-void
 dump_time_statistics ()
 {
   register tree prev = 0, decl, next;
@@ -4866,32 +4200,6 @@ compiler_error (s, v, v2)
   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)
@@ -4923,6 +4231,182 @@ yyerror (string)
   error (buf, token_buffer);
 }
 \f
+static 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));
+      char *main_filename = input_filename;
+
+      main_filename = FILE_NAME_NONDIRECTORY (main_filename);
+
+      token = real_yylex ();
+      
+      if (token != END_OF_LINE)
+       {
+         if (token != STRING
+             || TREE_CODE (yylval.ttype) != STRING_CST)
+           {
+             error ("invalid `#pragma interface'");
+             return -1;
+           }
+         main_filename = TREE_STRING_POINTER (yylval.ttype);
+         token = real_yylex ();
+       }
+
+      if (token != END_OF_LINE)
+       warning ("garbage after `#pragma interface' ignored");
+
+#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));
+      char *main_filename = main_input_filename ? main_input_filename : input_filename;
+
+      main_filename = FILE_NAME_NONDIRECTORY (main_filename);
+      token = real_yylex ();
+      if (token != END_OF_LINE)
+       {
+         if (token != STRING
+             || TREE_CODE (yylval.ttype) != STRING_CST)
+           {
+             error ("invalid `#pragma implementation'");
+             return -1;
+           }
+         main_filename = TREE_STRING_POINTER (yylval.ttype);
+         token = real_yylex ();
+       }
+
+      if (token != END_OF_LINE)
+       warning ("garbage after `#pragma implementation' ignored");
+
+#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,
@@ -4932,24 +4416,43 @@ yyerror (string)
 /* This function has to be in this file, in order to get at
    the token types.  */
 
-handle_sysv_pragma ()
+static 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 */