OSDN Git Service

91th Cygnus<->FSF merge
[pf3gnuchains/gcc-fork.git] / gcc / cp / lex.c
index b42be21..befb5a1 100644 (file)
@@ -1,5 +1,5 @@
 /* Separate lexical analyzer for GNU C++.
-   Copyright (C) 1987, 89, 92, 93, 94, 1995 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.
@@ -33,8 +33,8 @@ Boston, MA 02111-1307, 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"
@@ -131,35 +131,35 @@ extern int *token_count;
 \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)
     {
@@ -177,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.  */
 
@@ -254,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;
@@ -301,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
 
@@ -319,7 +336,7 @@ char *cplus_tree_code_type[] = {
 
 int cplus_tree_code_length[] = {
   0,
-#include "tree.def"
+#include "cp-tree.def"
 };
 #undef DEFTREECODE
 
@@ -329,7 +346,7 @@ int cplus_tree_code_length[] = {
 
 char *cplus_tree_code_name[] = {
   "@@dummy",
-#include "tree.def"
+#include "cp-tree.def"
 };
 #undef DEFTREECODE
 \f
@@ -374,12 +391,15 @@ 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 ();
 
@@ -620,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]));
@@ -662,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]));
@@ -672,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] = "-";
@@ -719,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] = "--";
@@ -763,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");
@@ -800,8 +823,6 @@ init_lex ()
       UNSET_RESERVED_WORD ("xor");
       UNSET_RESERVED_WORD ("xor_eq");
     }
-  if (! flag_traditional)
-    UNSET_RESERVED_WORD ("overload");
 
   token_count = init_parse ();
   interface_unknown = 1;
@@ -837,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));
@@ -932,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++)
@@ -946,13 +972,13 @@ 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
@@ -963,6 +989,7 @@ print_parse_statistics ()
 /* 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;
@@ -1005,6 +1032,7 @@ static struct impl_files *impl_file_chain;
 
 /* Helper function to load global variables with interface
    information.  */
+
 void
 extract_interface_info ()
 {
@@ -1026,6 +1054,7 @@ extract_interface_info ()
 
 /* Return nonzero if S is not considered part of an
    INTERFACE/IMPLEMENTATION pair.  Otherwise, return 0.  */
+
 static int
 interface_strcmp (s)
      char *s;
@@ -1064,7 +1093,7 @@ interface_strcmp (s)
   return 1;
 }
 
-void
+static void
 set_typedecl_interface_info (prev, vars)
      tree prev, vars;
 {
@@ -1076,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;
 {
@@ -1085,18 +1114,21 @@ 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 ()
 {
@@ -1161,6 +1193,7 @@ 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;
@@ -1176,12 +1209,11 @@ process_next_inline (t)
   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;
@@ -1315,6 +1347,7 @@ restore_pending_input (p)
 
 /* Return next non-whitespace input character, which may come
    from `finput', or from `nextchar'.  */
+
 static int
 yynextch ()
 {
@@ -1332,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;
@@ -1371,7 +1405,7 @@ store_pending_inline (decl, t)
   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)
@@ -1423,7 +1457,7 @@ reinit_parse_for_method (yychar, decl)
 /* Consume a block -- actually, a method beginning
    with `:' or `{' -- and save it away on the specified obstack.  */
 
-void
+static void
 reinit_parse_for_block (pyychar, obstackp)
      int pyychar;
      struct obstack *obstackp;
@@ -1639,11 +1673,12 @@ cons_up_default_function (type, full_name, kind)
       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];
 
@@ -1664,17 +1699,19 @@ 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);
     
-    fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE,
-                   NULL_TREE, NULL_TREE);
+    fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE);
   }
   
   if (fn == void_type_node)
     return fn;
 
+  if (kind > 2)
+    SET_DECL_ARTIFICIAL (TREE_CHAIN (DECL_ARGUMENTS (fn)));
+
 #if 0
   if (processing_template_defn)
     {
@@ -1683,6 +1720,7 @@ cons_up_default_function (type, full_name, kind)
     }
 #endif
 
+#if 0
   if (CLASSTYPE_INTERFACE_KNOWN (type))
     {
       DECL_INTERFACE_KNOWN (fn) = 1;
@@ -1690,6 +1728,7 @@ cons_up_default_function (type, full_name, kind)
                                     && flag_implement_inlines);
     }
   else
+#endif
     DECL_NOT_REALLY_EXTERN (fn) = 1;
 
   mark_inline_for_output (fn);
@@ -1724,6 +1763,7 @@ cons_up_default_function (type, full_name, kind)
 /* 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;
@@ -1734,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)))
@@ -1856,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;
@@ -1900,251 +1946,30 @@ 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'))
+             token = real_yylex ();
+             if (token == IDENTIFIER
+                 && TREE_CODE (yylval.ttype) == IDENTIFIER_NODE)
                {
-                 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");
+                 /* 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 == 'u'
-                      && getch () == 'n'
-                      && getch () == 'i'
-                      && getch () == 't'
-                      && ((c = getch ()) == ' ' || c == '\t'))
-               {
-                 /* 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;
-                   }
-                 if (nextchar < 0)
-                   nextchar = getch ();
-                 c = nextchar;
-                 if (c != EOF)
-                   warning ("trailing characters ignored");
-               }
-             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
-               {
-                 c = HANDLE_PRAGMA (finput, c);
-               }
+             if (HANDLE_PRAGMA (finput, yylval.ttype))
+               goto skipline;
 #endif
 #endif
-             goto skipline;
            }
+         goto skipline;
        }
       else if (c == 'd')
        {
@@ -2155,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;
            }
        }
@@ -2171,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;
            }
        }
@@ -2203,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)
                {
@@ -2420,15 +2231,7 @@ linenum:
              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 */
+             debug_start_source_file (input_filename);
              in_system_header = entering_system_header;
              if (c_header_level)
                ++c_header_level;
@@ -2457,15 +2260,7 @@ linenum:
                  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)
-                   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");
@@ -2485,6 +2280,7 @@ linenum:
  skipline:
   linemode = 0;
   end_of_file = 0;
+  nextchar = -1;
   while ((c = getch ()) != EOF && c != '\n');
   return c;
 }
@@ -2523,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;
@@ -2603,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':
@@ -2644,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
@@ -2675,6 +2446,10 @@ identifier_type (decl)
     return NSNAME;
   if (TREE_CODE (decl) != TYPE_DECL)
     return IDENTIFIER;
+  if (((got_scope && TREE_TYPE (decl) == got_scope)
+       || TREE_TYPE (decl) == current_class_type)
+      && DECL_ARTIFICIAL (decl))
+    return SELFNAME;
   return TYPENAME;
 }
 
@@ -2683,7 +2458,7 @@ see_typename ()
 {
   looking_for_typename = 1;
   if (yychar < 0)
-    if ((yychar = yylex()) < 0) yychar = 0;
+    if ((yychar = yylex ()) < 0) yychar = 0;
   looking_for_typename = 0;
   if (yychar == IDENTIFIER)
     {
@@ -2742,9 +2517,14 @@ do_identifier (token, parsing)
 
   /* 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)
@@ -2763,7 +2543,7 @@ do_identifier (token, parsing)
       else if (IDENTIFIER_OPNAME_P (token))
        {
          if (token != ansi_opname[ERROR_MARK])
-           cp_error ("operator %O not defined", token);
+           cp_error ("`%D' not defined", token);
          id = error_mark_node;
        }
       else if (parsing && (yychar == '(' || yychar == LEFT_RIGHT))
@@ -2848,7 +2628,7 @@ do_identifier (token, parsing)
            cp_error ("enum `%D' is private", id);
          /* protected is OK, since it's an enum of `this'.  */
        }
-      if (! current_template_parms
+      if (! processing_template_decl
          || (DECL_INITIAL (id)
              && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_CONST_PARM))
        id = DECL_INITIAL (id);
@@ -2885,7 +2665,7 @@ do_scoped_id (token, parsing)
     yychar = yylex ();
   if (! id)
     {
-      if (current_template_parms)
+      if (processing_template_decl)
        {
          id = build_min_nt (LOOKUP_EXPR, token, NULL_TREE);
          LOOKUP_EXPR_GLOBAL (id) = 1;
@@ -2910,7 +2690,7 @@ do_scoped_id (token, parsing)
       else if (TREE_CODE (id) != TREE_LIST)
        mark_used (id);
     }
-  if (TREE_CODE (id) == CONST_DECL && ! current_template_parms)
+  if (TREE_CODE (id) == CONST_DECL && ! processing_template_decl)
     {
       /* XXX CHS - should we set TREE_USED of the constant? */
       id = DECL_INITIAL (id);
@@ -2920,7 +2700,7 @@ do_scoped_id (token, parsing)
       TREE_CONSTANT (id) = 1;
     }
 
-  if (current_template_parms)
+  if (processing_template_decl)
     {
       if (is_overloaded_fn (id))
        {
@@ -2952,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 ()
 {
@@ -3238,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;
            }
@@ -3246,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);
 
@@ -3298,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;
              }
          }
@@ -3362,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:
@@ -3567,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)
@@ -3602,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))
@@ -3725,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)
@@ -3818,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.  */
@@ -3838,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
              {
@@ -3858,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;
@@ -3949,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.  */
@@ -4037,7 +3706,7 @@ real_yylex ()
          skipnewline:
            c = getch ();
            if (c == EOF) {
-               error("Unterminated string");
+               error ("Unterminated string");
                break;
            }
          }
@@ -4078,19 +3747,19 @@ real_yylex ()
              len = p - token_buffer - 1;
            }
 #endif
-           if (current_template_parms)
+           if (processing_template_decl)
              push_obstacks (&permanent_obstack, &permanent_obstack);
            yylval.ttype = build_string ((len + 1) * WCHAR_BYTES, widep);
-           if (current_template_parms)
+           if (processing_template_decl)
              pop_obstacks ();
            TREE_TYPE (yylval.ttype) = wchar_array_type_node;
          }
        else
          {
-           if (current_template_parms)
+           if (processing_template_decl)
              push_obstacks (&permanent_obstack, &permanent_obstack);
            yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
-           if (current_template_parms)
+           if (processing_template_decl)
              pop_obstacks ();
            TREE_TYPE (yylval.ttype) = char_array_type_node;
          }
@@ -4309,6 +3978,30 @@ is_rid (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,
+  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[];
 #endif
@@ -4352,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);
@@ -4383,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;
@@ -4480,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;
@@ -4549,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)
@@ -4606,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,
@@ -4615,11 +4416,14 @@ 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:
@@ -4644,14 +4448,11 @@ handle_sysv_pragma ()
          handle_pragma_token (")", NULL_TREE);
          break;
        case END_OF_LINE:
-         handle_pragma_token (NULL_PTR, NULL_TREE);
-         return;
        default:
          handle_pragma_token (NULL_PTR, NULL_TREE);
-         while (yylex () != END_OF_LINE)
-           /* continue */;
-         return;
+         return 1;
        }
+      token = real_yylex ();
     }
 }
 #endif /* HANDLE_SYSV_PRAGMA */