OSDN Git Service

* c-common.c (decl_attributes): Only take a single attributes
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl2.c
index 8e3d232..e6d4274 100644 (file)
@@ -1,5 +1,6 @@
 /* Process declarations and variables for C compiler.
-   Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GNU CC.
@@ -31,24 +32,21 @@ Boston, MA 02111-1307, USA.  */
 #include "system.h"
 #include "tree.h"
 #include "rtl.h"
+#include "expr.h"
 #include "flags.h"
 #include "cp-tree.h"
 #include "decl.h"
 #include "lex.h"
 #include "output.h"
 #include "except.h"
-#include "expr.h"
-#include "defaults.h"
 #include "toplev.h"
 #include "dwarf2out.h"
 #include "dwarfout.h"
-#include "splay-tree.h"
 #include "ggc.h"
-
-#if USE_CPPLIB
+#include "timevar.h"
 #include "cpplib.h"
-extern cpp_reader  parse_in;
-#endif
+#include "target.h"
+extern cpp_reader *parse_in;
 
 /* This structure contains information about the initializations
    and/or destructions required for a particular priority level.  */
@@ -61,52 +59,52 @@ typedef struct priority_info_s {
   int destructions_p;
 } *priority_info;
 
-static tree get_sentry PROTO((tree));
-static void mark_vtable_entries PROTO((tree));
-static void grok_function_init PROTO((tree, tree));
-static int finish_vtable_vardecl PROTO((tree *, void *));
-static int prune_vtable_vardecl PROTO((tree *, void *));
-static int is_namespace_ancestor PROTO((tree, tree));
-static void add_using_namespace PROTO((tree, tree, int));
-static tree ambiguous_decl PROTO((tree, tree, tree,int));
-static tree build_anon_union_vars PROTO((tree, tree*, int, int));
-static int acceptable_java_type PROTO((tree));
-static void output_vtable_inherit PROTO((tree));
-static tree start_objects PROTO((int, int));
-static void finish_objects PROTO((int, int, tree));
-static tree merge_functions PROTO((tree, tree));
-static tree decl_namespace PROTO((tree));
-static tree validate_nonmember_using_decl PROTO((tree, tree *, tree *));
-static void do_nonmember_using_decl PROTO((tree, tree, tree, tree,
+static void mark_vtable_entries PARAMS ((tree));
+static void grok_function_init PARAMS ((tree, tree));
+static int finish_vtable_vardecl PARAMS ((tree *, void *));
+static int prune_vtable_vardecl PARAMS ((tree *, void *));
+static int is_namespace_ancestor PARAMS ((tree, tree));
+static void add_using_namespace PARAMS ((tree, tree, int));
+static tree ambiguous_decl PARAMS ((tree, tree, tree,int));
+static tree build_anon_union_vars PARAMS ((tree, tree*, int, int));
+static int acceptable_java_type PARAMS ((tree));
+static void output_vtable_inherit PARAMS ((tree));
+static tree start_objects PARAMS ((int, int));
+static void finish_objects PARAMS ((int, int, tree));
+static tree merge_functions PARAMS ((tree, tree));
+static tree decl_namespace PARAMS ((tree));
+static tree validate_nonmember_using_decl PARAMS ((tree, tree *, tree *));
+static void do_nonmember_using_decl PARAMS ((tree, tree, tree, tree,
                                           tree *, tree *));
-static tree start_static_storage_duration_function PROTO((void));
-static void finish_static_storage_duration_function PROTO((tree));
-static priority_info get_priority_info PROTO((int));
-static void do_static_initialization PROTO((tree, tree));
-static void do_static_destruction PROTO((tree));
-static tree start_static_initialization_or_destruction PROTO((tree, int));
-static void finish_static_initialization_or_destruction PROTO((tree));
-static void generate_ctor_or_dtor_function PROTO((int, int));
+static tree start_static_storage_duration_function PARAMS ((void));
+static void finish_static_storage_duration_function PARAMS ((tree));
+static priority_info get_priority_info PARAMS ((int));
+static void do_static_initialization PARAMS ((tree, tree));
+static void do_static_destruction PARAMS ((tree));
+static tree start_static_initialization_or_destruction PARAMS ((tree, int));
+static void finish_static_initialization_or_destruction PARAMS ((tree));
+static void generate_ctor_or_dtor_function PARAMS ((int, int));
 static int generate_ctor_and_dtor_functions_for_priority
-                                  PROTO((splay_tree_node, void *));
-static tree prune_vars_needing_no_initialization PROTO((tree));
-static void write_out_vars PROTO((tree));
-
-extern int current_class_depth;
-
-/* A list of virtual function tables we must make sure to write out.  */
-tree pending_vtables;
+                                  PARAMS ((splay_tree_node, void *));
+static tree prune_vars_needing_no_initialization PARAMS ((tree));
+static void write_out_vars PARAMS ((tree));
+static void import_export_class        PARAMS ((tree));
+static tree key_method PARAMS ((tree));
+static int compare_options PARAMS ((const PTR, const PTR));
+static tree get_guard_bits PARAMS ((tree));
 
 /* A list of static class variables.  This is needed, because a
    static class variable can be declared inside the class without
    an initializer, and then initialized, staticly, outside the class.  */
 static varray_type pending_statics;
-static size_t pending_statics_used;
+#define pending_statics_used \
+  (pending_statics ? pending_statics->elements_used : 0)
 
 /* A list of functions which were declared inline, but which we
    may need to emit outline anyway.  */
-static varray_type saved_inlines;
-static size_t saved_inlines_used;
+static varray_type deferred_fns;
+#define deferred_fns_used \
+  (deferred_fns ? deferred_fns->elements_used : 0)
 
 /* Same, but not reset.  Local temp variables and global temp variables
    can have the same name.  */
@@ -122,28 +120,15 @@ int at_eof;
 
 /* Functions called along with real static constructors and destructors.  */
 
-tree static_ctors, static_dtors;
+tree static_ctors;
+tree static_dtors;
 
 /* The :: namespace. */
 
 tree global_namespace;
-
-/* The stack for namespaces of current declarations. */
-
-static tree decl_namespace_list;
-
 \f
 /* C (and C++) language-specific option variables.  */
 
-/* Nonzero means allow type mismatches in conditional expressions;
-   just make their values `void'.   */
-
-int flag_cond_mismatch;
-
-/* Nonzero means give `double' the same size as `float'.  */
-
-int flag_short_double;
-
 /* Nonzero means don't recognize the keyword `asm'.  */
 
 int flag_no_asm;
@@ -152,15 +137,6 @@ int flag_no_asm;
 
 int flag_no_gnu_keywords;
 
-/* Nonzero means don't recognize the non-ANSI builtin functions.  */
-
-int flag_no_builtin;
-
-/* Nonzero means don't recognize the non-ANSI builtin functions.
-   -ansi sets this.  */
-
-int flag_no_nonansi_builtin;
-
 /* Nonzero means do some things the same way PCC does.  Only provided so
    the compiler will link.  */
 
@@ -170,8 +146,9 @@ int flag_traditional;
 
 int flag_signed_bitfields = 1;
 
-/* Nonzero means enable obscure ANSI features and disable GNU extensions
-   that might cause ANSI-compliant code to be miscompiled.  */
+/* Nonzero means enable obscure standard features and disable GNU
+   extensions that might cause standard-compliant code to be
+   miscompiled.  */
 
 int flag_ansi;
 
@@ -217,10 +194,7 @@ int warn_ctor_dtor_privacy = 1;
 /* True if we want to implement vtables using "thunks".
    The default is off.  */
 
-#ifndef DEFAULT_VTABLE_THUNKS
-#define DEFAULT_VTABLE_THUNKS 0
-#endif
-int flag_vtable_thunks = DEFAULT_VTABLE_THUNKS;
+int flag_vtable_thunks = 1;
 
 /* Nonzero means generate separate instantiation control files and juggle
    them at link time.  */
@@ -237,11 +211,6 @@ int flag_optional_diags = 1;
 
 int flag_const_strings = 1;
 
-/* If non-NULL, dump the tree structure for the entire translation
-   unit to this file.  */
-
-char *flag_dump_translation_unit = 0;
-
 /* Nonzero means warn about deprecated conversion from string constant to
    `char *'.  */
 
@@ -278,9 +247,9 @@ int warn_sign_compare;
 
 int warn_float_equal = 0;
 
-/* Warn about *printf or *scanf format/argument anomalies.  */
+/* Warn about functions which might be candidates for format attributes.  */
 
-int warn_format;
+int warn_missing_format_attribute;
 
 /* Warn about a subscript that has type char.  */
 
@@ -297,23 +266,25 @@ int warn_parentheses;
 /* Non-zero means warn in function declared in derived class has the
    same name as a virtual in the base class, but fails to match the
    type signature of any virtual function in the base class.  */
+
 int warn_overloaded_virtual;
 
 /* Non-zero means warn when declaring a class that has a non virtual
    destructor, when it really ought to have a virtual one.  */
-int warn_nonvdtor;
 
-/* Non-zero means warn when a function is declared extern and later inline.  */
-int warn_extern_inline;
+int warn_nonvdtor;
 
 /* Non-zero means warn when the compiler will reorder code.  */
+
 int warn_reorder;
 
 /* Non-zero means warn when synthesis behavior differs from Cfront's.  */
+
 int warn_synth;
 
 /* Non-zero means warn when we convert a pointer to member function
    into a pointer to (void or function).  */
+
 int warn_pmf2ptr = 1;
 
 /* Nonzero means warn about violation of some Effective C++ style rules.  */
@@ -353,31 +324,11 @@ int warn_deprecated = 1;
 #endif
 int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
 
-/* Nonzero for -fno-strict-prototype switch: do not consider empty
-   argument prototype to mean function takes no arguments.  */
-
-int flag_strict_prototype = 2;
-int strict_prototype = 1;
-int strict_prototypes_lang_c, strict_prototypes_lang_cplusplus = 1;
-
-/* Nonzero means that labels can be used as first-class objects */
-
-int flag_labels_ok;
-
 /* Nonzero means allow Microsoft extensions without a pedwarn.  */
 
 int flag_ms_extensions;
 
-/* Non-zero means to collect statistics which might be expensive
-   and to print them when we are done.  */
-int flag_detailed_statistics;
-
 /* C++ specific flags.  */   
-/* Zero means that `this' is a *const.  This gives nice behavior in the
-   2.0 world.  1 gives 1.2-compatible behavior.  2 gives Spring behavior.
-   -2 means we're constructing an object and it has fixed type.  */
-
-int flag_this_is_variable;
 
 /* Nonzero means we should attempt to elide constructors when possible.  */
 
@@ -390,11 +341,8 @@ int flag_default_inline = 1;
 
 /* Controls whether compiler generates 'type descriptor' that give
    run-time type information.  */
-int flag_rtti = 1;
 
-/* Nonzero if we wish to output cross-referencing information
-   for the GNU class browser.  */
-extern int flag_gnu_xref;
+int flag_rtti = 1;
 
 /* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
    objects.  */
@@ -414,18 +362,18 @@ int flag_access_control = 1;
 
 /* Nonzero if we want to understand the operator names, i.e. 'bitand'.  */
 
-int flag_operator_names;
+int flag_operator_names = 1;
 
 /* Nonzero if we want to check the return value of new and avoid calling
    constructors if it is a null pointer.  */
 
 int flag_check_new;
 
-/* Nonzero if we want the new ANSI rules for pushing a new scope for `for'
+/* Nonzero if we want the new ISO rules for pushing a new scope for `for'
    initialization variables.
    0: Old rules, set by -fno-for-scope.
-   2: New ANSI rules, set by -ffor-scope.
-   1: Try to implement new ANSI rules, but with backup compatibility
+   2: New ISO rules, set by -ffor-scope.
+   1: Try to implement new ISO rules, but with backup compatibility
    (and warnings).  This is the default, for now.  */
 
 int flag_new_for_scope = 1;
@@ -436,35 +384,27 @@ int flag_new_for_scope = 1;
 
 int flag_weak = 1;
 
-/* Nonzero to enable experimental ABI changes.  */
+/* Nonzero to use __cxa_atexit, rather than atexit, to register
+   destructors for local statics and global objects.  */
 
-int flag_new_abi;
+int flag_use_cxa_atexit;
 
 /* Nonzero to not ignore namespace std. */
 
-int flag_honor_std;
-
-/* Maximum template instantiation depth. Must be at least 17 for ANSI
-   compliance. */
+int flag_honor_std = 1;
 
-int max_tinst_depth = 17;
+/* 0 if we should not perform inlining.
+   1 if we should expand functions calls inline at the tree level.  
+   2 if we should consider *all* functions to be inline 
+   candidates.  */
 
-/* The name-mangling scheme to use.  Must be 1 or greater to support
-   template functions with identical types, but different template
-   arguments.  */
-int name_mangling_version = 2;
+int flag_inline_trees = 0;
 
-/* Nonzero means that guiding declarations are allowed.  */
-int flag_guiding_decls;
+/* Maximum template instantiation depth.  This limit is rather
+   arbitrary, but it exists to limit the time it takes to notice
+   infinite template instantiations.  */
 
-/* Nonzero if wchar_t should be `unsigned short' instead of whatever it
-   would normally be, for use with WINE.  */
-int flag_short_wchar;
-
-/* Nonzero if squashed mangling is to be performed. 
-   This uses the B and K codes to reference previously seen class types 
-   and class qualifiers.       */
-int flag_do_squangling;
+int max_tinst_depth = 50;
 
 /* Nonzero means output .vtable_{entry,inherit} for use in doing vtable gc.  */
 
@@ -475,10 +415,16 @@ int flag_vtable_gc;
 
 int flag_permissive;
 
-/* If this variable is defined to a non-NULL value, it will be called
-   after the file has been completely parsed.  */
+/* Nonzero means to implement standard semantics for exception
+   specifications, calling unexpected if an exception is thrown that
+   doesn't match the specification.  Zero means to treat them as
+   assertions and optimize accordingly, but not check them.  */
+
+int flag_enforce_eh_specs = 1;
+
+/* The variant of the C language being processed.  */
 
-void (*back_end_hook) PROTO((tree));
+c_language_kind c_language = clk_cplusplus;
 
 /* Table of language-dependent -f options.
    STRING is the option name.  VARIABLE is the address of the variable.
@@ -497,7 +443,6 @@ lang_f_options[] =
   {"short-enums", &flag_short_enums, 1},
   {"short-double", &flag_short_double, 1},
   {"short-wchar", &flag_short_wchar, 1},
-  {"cond-mismatch", &flag_cond_mismatch, 1},
   {"asm", &flag_no_asm, 0},
   {"builtin", &flag_no_builtin, 0},
 
@@ -509,16 +454,15 @@ lang_f_options[] =
   {"default-inline", &flag_default_inline, 1},
   {"dollars-in-identifiers", &dollars_in_ident, 1},
   {"elide-constructors", &flag_elide_constructors, 1},
+  {"enforce-eh-specs", &flag_enforce_eh_specs, 1},
   {"external-templates", &flag_external_templates, 1},
   {"for-scope", &flag_new_for_scope, 2},
   {"gnu-keywords", &flag_no_gnu_keywords, 0},
   {"handle-exceptions", &flag_exceptions, 1},
   {"honor-std", &flag_honor_std, 1},
-  {"huge-objects", &flag_huge_objects, 1},
   {"implement-inlines", &flag_implement_inlines, 1},
   {"implicit-inline-templates", &flag_implicit_inline_templates, 1},
   {"implicit-templates", &flag_implicit_templates, 1},
-  {"labels-ok", &flag_labels_ok, 1},
   {"ms-extensions", &flag_ms_extensions, 1},
   {"nonansi-builtins", &flag_no_nonansi_builtin, 0},
   {"operator-names", &flag_operator_names, 1},
@@ -526,37 +470,56 @@ lang_f_options[] =
   {"permissive", &flag_permissive, 1},
   {"repo", &flag_use_repository, 1},
   {"rtti", &flag_rtti, 1},
-  {"squangle", &flag_do_squangling, 1},
   {"stats", &flag_detailed_statistics, 1},
-  {"strict-prototype", &flag_strict_prototype, 1},
   {"vtable-gc", &flag_vtable_gc, 1},
-  {"vtable-thunks", &flag_vtable_thunks, 1},
-  {"weak", &flag_weak, 1},
-  {"xref", &flag_gnu_xref, 1}
+  {"use-cxa-atexit", &flag_use_cxa_atexit, 1},
+  {"weak", &flag_weak, 1}
+};
+
+/* The list of `-f' options that we no longer support.  The `-f'
+   prefix is not given in this table.  The `-fno-' variants are not
+   listed here.  This table must be kept in alphabetical order.  */
+static const char * const unsupported_options[] = {
+  "all-virtual",
+  "cond-mismatch",
+  "enum-int-equiv",
+  "guiding-decls",
+  "huge-objects",
+  "labels-ok",
+  "new-abi",
+  "nonnull-objects",
+  "squangle",
+  "strict-prototype",
+  "this-is-variable",
+  "vtable-thunks",
+  "xref"
 };
 
+/* Compare two option strings, pointed two by P1 and P2, for use with
+   bsearch.  */
+
+static int
+compare_options (p1, p2)
+     const PTR p1;
+     const PTR p2;
+{
+  return strcmp (*((const char *const *) p1), *((const char *const *) p2));
+}
+
 /* Decode the string P as a language-specific option.
    Return the number of strings consumed for a valid option.
    Otherwise return 0.  Should not complain if it does not
    recognise the option.  */
 
 int   
-lang_decode_option (argc, argv)
-     int argc
-#if !USE_CPPLIB
-  ATTRIBUTE_UNUSED
-#endif
-  ;
+cxx_decode_option (argc, argv)
+     int argc;
      char **argv;
-
 {
   int strings_processed;
-  char *p = argv[0];
-#if USE_CPPLIB
-  strings_processed = cpp_handle_option (&parse_in, argc, argv);
-#else
-  strings_processed = 0;
-#endif /* ! USE_CPPLIB */
+  const char *p = argv[0];
+
+  strings_processed = cpp_handle_option (parse_in, argc, argv);
 
   if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
     /* ignore */;
@@ -565,19 +528,37 @@ lang_decode_option (argc, argv)
       /* Some kind of -f option.
         P's value is the option sans `-f'.
         Search for it in the table of options.  */
+      const char *option_value = NULL;
+      const char *positive_option;
       size_t j;
 
       p += 2;
       /* Try special -f options.  */
 
+      /* See if this is one of the options no longer supported.  We
+        used to support these options, so we continue to accept them,
+        with a warning.  */
+      if (strncmp (p, "no-", strlen ("no-")) == 0)
+       positive_option = p + strlen ("no-");
+      else
+       positive_option = p;
+
+      /* If the option is present, issue a warning.  Indicate to our
+        caller that the option was processed successfully.  */
+      if (bsearch (&positive_option, 
+                  unsupported_options, 
+                  (sizeof (unsupported_options) 
+                   / sizeof (unsupported_options[0])),
+                  sizeof (unsupported_options[0]),
+                  compare_options))
+       {
+         warning ("-f%s is no longer supported", p);
+         return 1;
+       }
+
       if (!strcmp (p, "handle-exceptions")
          || !strcmp (p, "no-handle-exceptions"))
        warning ("-fhandle-exceptions has been renamed to -fexceptions (and is now on by default)");
-      else if (!strcmp (p, "all-virtual")
-              || !strcmp (p, "enum-int-equiv")
-              || !strcmp (p, "no-nonnull-objects")
-              || !strcmp (p, "this-is-variable"))
-       warning ("-f%s is no longer supported", p);
       else if (! strcmp (p, "alt-external-templates"))
        {
          flag_external_templates = 1;
@@ -591,44 +572,23 @@ lang_decode_option (argc, argv)
          flag_use_repository = 1;
          flag_implicit_templates = 0;
        }
-      else if (!strcmp (p, "guiding-decls"))
-       {
-         flag_guiding_decls = 1;
-         name_mangling_version = 0;
-       }
-      else if (!strcmp (p, "no-guiding-decls"))
-       flag_guiding_decls = 0;
       else if (!strcmp (p, "external-templates"))
         {
           flag_external_templates = 1;
           cp_deprecated ("-fexternal-templates");
         }
-      else if (!strcmp (p, "new-abi"))
-       {
-         flag_new_abi = 1;
-         flag_do_squangling = 1;
-         flag_honor_std = 1;
-         flag_vtable_thunks = 1;
-       }
-      else if (!strcmp (p, "no-new-abi"))
-       {
-         flag_new_abi = 0;
-         flag_do_squangling = 0;
-         flag_honor_std = 0;
-       }
-      else if (!strncmp (p, "template-depth-", 15))
+      else if ((option_value
+                = skip_leading_substring (p, "template-depth-")))
        max_tinst_depth
-         = read_integral_parameter (p + 15, p - 2, max_tinst_depth);
-      else if (!strncmp (p, "name-mangling-version-", 22))
-       name_mangling_version 
-         = read_integral_parameter (p + 22, p - 2, name_mangling_version);
-      else if (!strncmp (p, "dump-translation-unit-", 22))
+         = read_integral_parameter (option_value, p - 2, max_tinst_depth);
+      else if ((option_value
+                = skip_leading_substring (p, "name-mangling-version-")))
        {
-         if (p[22] == '\0')
-           error ("no file specified with -fdump-translation-unit");
-         else
-           flag_dump_translation_unit = p + 22;
+         warning ("-fname-mangling-version is no longer supported");
+         return 1;
        }
+      else if (dump_switch_p (p))
+       ;
       else 
        {
          int found = 0;
@@ -684,6 +644,11 @@ lang_decode_option (argc, argv)
        warn_pointer_arith = setting;
       else if (!strcmp (p, "missing-prototypes"))
        warn_missing_prototypes = setting;
+      else if (!strcmp (p, "strict-prototypes"))
+       {
+         if (setting == 0)
+           warning ("-Wno-strict-prototypes is not supported in C++");
+       }
       else if (!strcmp (p, "redundant-decls"))
        warn_redundant_decls = setting;
       else if (!strcmp (p, "missing-braces"))
@@ -693,15 +658,25 @@ lang_decode_option (argc, argv)
       else if (!strcmp (p, "float-equal"))
        warn_float_equal = setting;
       else if (!strcmp (p, "format"))
-       warn_format = setting;
+       set_Wformat (setting);
+      else if (!strcmp (p, "format=2"))
+       set_Wformat (2);
+      else if (!strcmp (p, "format-y2k"))
+       warn_format_y2k = setting;
+      else if (!strcmp (p, "format-extra-args"))
+       warn_format_extra_args = setting;
+      else if (!strcmp (p, "format-nonliteral"))
+       warn_format_nonliteral = setting;
+      else if (!strcmp (p, "format-security"))
+       warn_format_security = setting;
+      else if (!strcmp (p, "missing-format-attribute"))
+       warn_missing_format_attribute = setting;
       else if (!strcmp (p, "conversion"))
        warn_conversion = setting;
       else if (!strcmp (p, "parentheses"))
        warn_parentheses = setting;
       else if (!strcmp (p, "non-virtual-dtor"))
        warn_nonvdtor = setting;
-      else if (!strcmp (p, "extern-inline"))
-       warn_extern_inline = setting;
       else if (!strcmp (p, "reorder"))
        warn_reorder = setting;
       else if (!strcmp (p, "synth"))
@@ -737,10 +712,10 @@ lang_decode_option (argc, argv)
       else if (!strcmp (p, "all"))
        {
          warn_return_type = setting;
-         warn_unused = setting;
+         set_Wunused (setting);
          warn_implicit = setting;
          warn_switch = setting;
-         warn_format = setting;
+         set_Wformat (setting);
          warn_parentheses = setting;
          warn_missing_braces = setting;
          warn_sign_compare = setting;
@@ -764,7 +739,7 @@ lang_decode_option (argc, argv)
     }
   else if (!strcmp (p, "-ansi"))
     flag_no_nonansi_builtin = 1, flag_ansi = 1,
-    flag_no_gnu_keywords = 1, flag_operator_names = 1;
+    flag_noniso_default_format_attributes = 0, flag_no_gnu_keywords = 1;
 #ifdef SPEW_DEBUG
   /* Undocumented, only ever used when you're invoking cc1plus by hand, since
      it's probably safe to assume no sane person would ever want to use this
@@ -780,9 +755,11 @@ lang_decode_option (argc, argv)
 \f
 /* Incorporate `const' and `volatile' qualifiers for member functions.
    FUNCTION is a TYPE_DECL or a FUNCTION_DECL.
-   QUALS is a list of qualifiers.  */
+   QUALS is a list of qualifiers.  Returns any explicit
+   top-level qualifiers of the method's this pointer, anything other than
+   TYPE_UNQUALIFIED will be an extension.  */
 
-tree
+int
 grok_method_quals (ctype, function, quals)
      tree ctype, function, quals;
 {
@@ -790,13 +767,16 @@ grok_method_quals (ctype, function, quals)
   tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
   int type_quals = TYPE_UNQUALIFIED;
   int dup_quals = TYPE_UNQUALIFIED;
+  int this_quals = TYPE_UNQUALIFIED;
 
   do
     {
       int tq = cp_type_qual_from_rid (TREE_VALUE (quals));
       
-      if (type_quals & tq)
+      if ((type_quals | this_quals) & tq)
        dup_quals |= tq;
+      else if (tq & TYPE_QUAL_RESTRICT)
+        this_quals |= tq;
       else
        type_quals |= tq;
       quals = TREE_CHAIN (quals);
@@ -817,7 +797,7 @@ grok_method_quals (ctype, function, quals)
     fntype = build_exception_variant (fntype, raises);
 
   TREE_TYPE (function) = fntype;
-  return ctype;
+  return this_quals;
 }
 
 /* Warn when -fexternal-templates is used and #pragma
@@ -834,14 +814,14 @@ warn_if_unknown_interface (decl)
 
   if (flag_alt_external_templates)
     {
-      struct tinst_level *til = tinst_for_decl ();
+      tree til = tinst_for_decl ();
       int sl = lineno;
-      char *sf = input_filename;
+      const char *sf = input_filename;
 
       if (til)
        {
-         lineno = til->line;
-         input_filename = til->file;
+         lineno = TINST_LINE (til);
+         input_filename = TINST_FILE (til);
        }
       cp_warning ("template `%#D' instantiated in file without #pragma interface",
                  decl);
@@ -859,13 +839,12 @@ void
 grok_x_components (specs)
      tree specs;
 {
-  struct pending_inline **p;
   tree t;
 
   specs = strip_attrs (specs);
 
   check_tag_decl (specs);
-  t = groktypename (build_decl_list (specs, NULL_TREE)); 
+  t = groktypename (build_tree_list (specs, NULL_TREE)); 
 
   /* The only case where we need to do anything additional here is an
      anonymous union field, e.g.: `struct S { union { int i; }; };'.  */
@@ -873,14 +852,26 @@ grok_x_components (specs)
     return;
 
   fixup_anonymous_aggr (t);
-  finish_member_declaration (build_lang_decl (FIELD_DECL, NULL_TREE, t)); 
-
-  /* Ignore any inline function definitions in the anonymous union
-     since an anonymous union may not have function members.  */
-  p = &pending_inlines;
-  for (; *p; *p = (*p)->next)
-    if (DECL_CONTEXT ((*p)->fndecl) != t)
-      break;
+  finish_member_declaration (build_decl (FIELD_DECL, NULL_TREE, t)); 
+}
+
+/* Returns a PARM_DECL for a parameter of the indicated TYPE, with the
+   indicated NAME.  */
+
+tree
+build_artificial_parm (name, type)
+     tree name;
+     tree type;
+{
+  tree parm;
+
+  parm = build_decl (PARM_DECL, name, type);
+  DECL_ARTIFICIAL (parm) = 1;
+  /* All our artificial parms are implicitly `const'; they cannot be
+     assigned to.  */
+  TREE_READONLY (parm) = 1;
+  DECL_ARG_TYPE (parm) = type;
+  return parm;
 }
 
 /* Constructors for types with virtual baseclasses need an "in-charge" flag
@@ -891,7 +882,10 @@ grok_x_components (specs)
 
    This function adds the "in-charge" flag to member function FN if
    appropriate.  It is called from grokclassfn and tsubst.
-   FN must be either a constructor or destructor.  */
+   FN must be either a constructor or destructor.
+
+   The in-charge flag follows the 'this' parameter, and is followed by the
+   VTT parm (if any), then the user-written parms.  */
 
 void
 maybe_retrofit_in_chrg (fn)
@@ -899,39 +893,62 @@ maybe_retrofit_in_chrg (fn)
 {
   tree basetype, arg_types, parms, parm, fntype;
 
-  if (DECL_CONSTRUCTOR_P (fn)
-      && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CLASS_CONTEXT (fn))
-      && ! DECL_CONSTRUCTOR_FOR_VBASE_P (fn))
-    /* OK */;
-  else if (! DECL_CONSTRUCTOR_P (fn)
-          && TREE_CHAIN (DECL_ARGUMENTS (fn)) == NULL_TREE)
-    /* OK */;
-  else
+  /* If we've already add the in-charge parameter don't do it again.  */
+  if (DECL_HAS_IN_CHARGE_PARM_P (fn))
     return;
 
-  if (DECL_CONSTRUCTOR_P (fn))
-    DECL_CONSTRUCTOR_FOR_VBASE_P (fn) = 1;
+  /* When processing templates we can't know, in general, whether or
+     not we're going to have virtual baseclasses.  */
+  if (uses_template_parms (fn))
+    return;
 
-  /* First add it to DECL_ARGUMENTS...  */
-  parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
-  /* Mark the artificial `__in_chrg' parameter as "artificial".  */
-  SET_DECL_ARTIFICIAL (parm);
-  DECL_ARG_TYPE (parm) = integer_type_node;
-  TREE_READONLY (parm) = 1;
-  parms = DECL_ARGUMENTS (fn);
-  TREE_CHAIN (parm) = TREE_CHAIN (parms);
-  TREE_CHAIN (parms) = parm;
+  /* We don't need an in-charge parameter for constructors that don't
+     have virtual bases.  */
+  if (DECL_CONSTRUCTOR_P (fn)
+      && !TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+    return;
 
-  /* ...and then to TYPE_ARG_TYPES.  */
   arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
   basetype = TREE_TYPE (TREE_VALUE (arg_types));
-  arg_types = hash_tree_chain (integer_type_node, TREE_CHAIN (arg_types));
+  arg_types = TREE_CHAIN (arg_types);
+
+  parms = TREE_CHAIN (DECL_ARGUMENTS (fn));
+
+  /* If this is a subobject constructor or destructor, our caller will
+     pass us a pointer to our VTT.  */
+  if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+    {
+      parm = build_artificial_parm (vtt_parm_identifier, vtt_parm_type);
+
+      /* First add it to DECL_ARGUMENTS between 'this' and the real args...  */
+      TREE_CHAIN (parm) = parms;
+      parms = parm;
+
+      /* ...and then to TYPE_ARG_TYPES.  */
+      arg_types = hash_tree_chain (vtt_parm_type, arg_types);
+
+      DECL_HAS_VTT_PARM_P (fn) = 1;
+    }
+
+  /* Then add the in-charge parm (before the VTT parm).  */
+  parm = build_artificial_parm (in_charge_identifier, integer_type_node);
+  TREE_CHAIN (parm) = parms;
+  parms = parm;
+  arg_types = hash_tree_chain (integer_type_node, arg_types);
+
+  /* Insert our new parameter(s) into the list.  */
+  TREE_CHAIN (DECL_ARGUMENTS (fn)) = parms;
+
+  /* And rebuild the function type.  */
   fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)),
                                    arg_types);
   if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
     fntype = build_exception_variant (fntype,
                                      TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)));
   TREE_TYPE (fn) = fntype;
+
+  /* Now we've got the in-charge parameter.  */
+  DECL_HAS_IN_CHARGE_PARM_P (fn) = 1;
 }
 
 /* Classes overload their constituent function names automatically.
@@ -961,9 +978,11 @@ grokclassfn (ctype, function, flags, quals)
      tree quals;
 {
   tree fn_name = DECL_NAME (function);
-  tree arg_types;
-  tree parm;
-  tree qualtype;
+  int this_quals = TYPE_UNQUALIFIED;
+
+  /* Even within an `extern "C"' block, members get C++ linkage.  See
+     [dcl.link] for details.  */
+  SET_DECL_LANGUAGE (function, lang_cplusplus);
 
   if (fn_name == NULL_TREE)
     {
@@ -973,48 +992,45 @@ grokclassfn (ctype, function, flags, quals)
     }
 
   if (quals)
-    qualtype = grok_method_quals (ctype, function, quals);
-  else
-    qualtype = ctype;
+    this_quals = grok_method_quals (ctype, function, quals);
 
-  arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
   if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
     {
       /* Must add the class instance variable up front.  */
       /* Right now we just make this a pointer.  But later
         we may wish to make it special.  */
-      tree type = TREE_VALUE (arg_types);
+      tree type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (function)));
+      tree qual_type;
+      tree parm;
+
+      /* The `this' parameter is implicitly `const'; it cannot be
+        assigned to.  */
+      this_quals |= TYPE_QUAL_CONST;
+      qual_type = cp_build_qualified_type (type, this_quals);
+      parm = build_artificial_parm (this_identifier, qual_type);
+      c_apply_type_quals_to_decl (this_quals, parm);
 
-      parm = build_decl (PARM_DECL, this_identifier, type);
-      /* Mark the artificial `this' parameter as "artificial".  */
-      SET_DECL_ARTIFICIAL (parm);
-      DECL_ARG_TYPE (parm) = type;
       /* We can make this a register, so long as we don't
         accidentally complain if someone tries to take its address.  */
       DECL_REGISTER (parm) = 1;
-      TREE_READONLY (parm) = 1;
       TREE_CHAIN (parm) = last_function_parms;
       last_function_parms = parm;
     }
 
   DECL_ARGUMENTS (function) = last_function_parms;
-  /* First approximations.  */
   DECL_CONTEXT (function) = ctype;
-  DECL_CLASS_CONTEXT (function) = ctype;
+
+  if (flags == DTOR_FLAG)
+    DECL_DESTRUCTOR_P (function) = 1;
 
   if (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function))
-    {
-      maybe_retrofit_in_chrg (function);
-      arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
-    }
+    maybe_retrofit_in_chrg (function);
 
   if (flags == DTOR_FLAG)
     {
-      DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype);
+      DECL_DESTRUCTOR_P (function) = 1;
       TYPE_HAS_DESTRUCTOR (ctype) = 1;
     }
-  else
-    set_mangled_name_for_decl (function);
 }
 
 /* Work on the expr used by alignof (this is only called by the parser).  */
@@ -1167,7 +1183,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
 
   if (doing_vec == 2)
     {
-      maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node);
+      maxindex = cp_build_binary_op (MINUS_EXPR, size, integer_one_node);
       pedwarn ("anachronistic use of array size in vector delete");
     }
 
@@ -1178,14 +1194,17 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
   /* You can't delete functions.  */
   if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
     {
-      error ("cannot delete a function");
+      error ("cannot delete a function.  Only pointer-to-objects are valid arguments to `delete'");
       return error_mark_node;
     }
 
   /* Deleting ptr to void is undefined behaviour [expr.delete/3].  */
   if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
-    cp_warning ("`%T' is not a pointer-to-object type", type);
-  
+    {
+      cp_warning ("deleting `%T' is undefined", type);
+      doing_vec = 0;
+    }
+
   /* An array can't have been allocated by new, so complain.  */
   if (TREE_CODE (t) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL
@@ -1197,8 +1216,8 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
     return build1 (NOP_EXPR, void_type_node, t);
 
   if (doing_vec)
-    return build_vec_delete (t, maxindex, integer_one_node,
-                            integer_zero_node, use_global_delete);
+    return build_vec_delete (t, maxindex, sfk_deleting_destructor,
+                            use_global_delete);
   else
     {
       if (IS_AGGR_TYPE (TREE_TYPE (type))
@@ -1212,7 +1231,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
            return error_mark_node;
        }
 
-      return build_delete (type, t, integer_three_node,
+      return build_delete (type, t, sfk_deleting_destructor,
                           LOOKUP_NORMAL, use_global_delete);
     }
 }
@@ -1237,7 +1256,7 @@ check_member_template (tmpl)
        /* 14.5.2.2 [temp.mem]
           
           A local class shall not have member templates. */
-       cp_error ("declaration of member template `%#D' in local class",
+       cp_error ("invalid declaration of member template `%#D' in local class",
                  decl);
       
       if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
@@ -1267,7 +1286,7 @@ acceptable_java_type (type)
 {
   if (TREE_CODE (type) == VOID_TYPE || TYPE_FOR_JAVA (type))
     return 1;
-  if (TREE_CODE (type) == POINTER_TYPE)
+  if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)
     {
       type = TREE_TYPE (type);
       if (TREE_CODE (type) == RECORD_TYPE)
@@ -1338,6 +1357,8 @@ check_classfn (ctype, function)
   tree *end = 0;
   
   if (DECL_USE_TEMPLATE (function)
+      && !(TREE_CODE (function) == TEMPLATE_DECL
+          && DECL_TEMPLATE_SPECIALIZATION (function))
       && is_member_template (DECL_TI_TEMPLATE (function)))
     /* Since this is a specialization of a member template,
        we're not going to find the declaration in the class.
@@ -1361,7 +1382,7 @@ check_classfn (ctype, function)
          && DECL_CONSTRUCTOR_P (function))
        goto got_it;
       if (*++methods && fn_name == DECL_NAME (OVL_CURRENT (*methods))
-         && DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)))
+         && DECL_DESTRUCTOR_P (function))
        goto got_it;
 
       while (++methods != end && *methods)
@@ -1374,22 +1395,6 @@ check_classfn (ctype, function)
                   fndecls = OVL_NEXT (fndecls))
                {
                  fndecl = OVL_CURRENT (fndecls);
-                 /* The DECL_ASSEMBLER_NAME for a TEMPLATE_DECL, or
-                    for a for member function of a template class, is
-                    not mangled, so the check below does not work
-                    correctly in that case.  Since mangled destructor
-                    names do not include the type of the arguments,
-                    we can't use this short-cut for them, either.
-                    (It's not legal to declare arguments for a
-                    destructor, but some people try.)  */
-                 if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function))
-                     && (DECL_ASSEMBLER_NAME (function)
-                         != DECL_NAME (function))
-                     && (DECL_ASSEMBLER_NAME (fndecl)
-                         != DECL_NAME (fndecl))
-                     && (DECL_ASSEMBLER_NAME (function) 
-                         == DECL_ASSEMBLER_NAME (fndecl)))
-                   return fndecl;
 
                  /* We cannot simply call decls_match because this
                     doesn't work for static member functions that are 
@@ -1435,7 +1440,7 @@ check_classfn (ctype, function)
   else
     {
       methods = 0;
-      if (TYPE_SIZE (ctype) == 0)
+      if (!COMPLETE_TYPE_P (ctype))
         incomplete_type_error (function, ctype);
       else
         cp_error ("no `%#D' member function declared in class `%T'",
@@ -1446,8 +1451,8 @@ check_classfn (ctype, function)
      spurious errors (unless the CTYPE is not yet defined, in which
      case we'll only confuse ourselves when the function is declared
      properly within the class.  */
-  if (TYPE_SIZE (ctype))
-    add_method (ctype, methods, function);
+  if (COMPLETE_TYPE_P (ctype))
+    add_method (ctype, function, /*error_p=*/1);
   return NULL_TREE;
 }
 
@@ -1463,44 +1468,36 @@ finish_static_data_member_decl (decl, init, asmspec_tree, flags)
      tree asmspec_tree;
      int flags;
 {
-  const char *asmspec = 0;
-
-  if (asmspec_tree)
-    asmspec = TREE_STRING_POINTER (asmspec_tree);
-
   my_friendly_assert (TREE_PUBLIC (decl), 0);
 
+  DECL_CONTEXT (decl) = current_class_type;
+
   /* We cannot call pushdecl here, because that would fill in the
-     decl of our TREE_CHAIN.  Instead, we modify cp_finish_decl to do
+     TREE_CHAIN of our decl.  Instead, we modify cp_finish_decl to do
      the right thing, namely, to put this decl out straight away.  */
   /* current_class_type can be NULL_TREE in case of error.  */
-  if (!asmspec && current_class_type)
-    {
-      DECL_INITIAL (decl) = error_mark_node;
-      DECL_ASSEMBLER_NAME (decl)
-       = build_static_name (current_class_type, DECL_NAME (decl));
-    }
+  if (!asmspec_tree && current_class_type)
+    DECL_INITIAL (decl) = error_mark_node;
+
   if (! processing_template_decl)
     {
       if (!pending_statics)
        VARRAY_TREE_INIT (pending_statics, 32, "pending_statics");
-       
-      if (pending_statics_used == pending_statics->num_elements)
-       VARRAY_GROW (pending_statics, 
-                    2 * pending_statics->num_elements);
-      VARRAY_TREE (pending_statics, pending_statics_used) = decl;
-      ++pending_statics_used;
+      VARRAY_PUSH_TREE (pending_statics, decl);
     }
 
   /* Static consts need not be initialized in the class definition.  */
   if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
     {
-      static int explanation = 0;
+      static int explained = 0;
          
       error ("initializer invalid for static member with constructor");
-      if (explanation++ == 0)
-       error ("(you really want to initialize it separately)");
-      init = 0;
+      if (!explained)
+        {
+         error ("(an out of class initialization is required)");
+         explained = 1;
+       }
+      init = NULL_TREE;
     }
   /* Force the compiler to know when an uninitialized static const
      member is being used.  */
@@ -1508,23 +1505,19 @@ finish_static_data_member_decl (decl, init, asmspec_tree, flags)
     TREE_USED (decl) = 1;
   DECL_INITIAL (decl) = init;
   DECL_IN_AGGR_P (decl) = 1;
-  DECL_CONTEXT (decl) = current_class_type;
-  DECL_CLASS_CONTEXT (decl) = current_class_type;
 
   cp_finish_decl (decl, init, asmspec_tree, flags);
 }
 
 /* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
-   of a structure component, returning a FIELD_DECL node.
+   of a structure component, returning a _DECL node.
    QUALS is a list of type qualifiers for this decl (such as for declaring
    const member functions).
 
    This is done during the parsing of the struct declaration.
-   The FIELD_DECL nodes are chained together and the lot of them
+   The _DECL nodes are chained together and the lot of them
    are ultimately passed to `build_struct' to make the RECORD_TYPE node.
 
-   C++:
-
    If class A defines that certain functions in class B are friends, then
    the way I have set things up, it is B who is interested in permission
    granted by A.  However, it is in A's context that these declarations
@@ -1550,7 +1543,23 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
          || TREE_CODE (TREE_OPERAND (declarator, 0)) == SCOPE_REF)
       && parmlist_is_exprlist (CALL_DECLARATOR_PARMS (declarator)))
     {
-      init = TREE_OPERAND (declarator, 1);
+      /* It's invalid to try to initialize a data member using a
+        functional notation, e.g.:
+        
+            struct S {
+             static int i (3);
+           };
+           
+        Explain that to the user.  */
+      static int explained;
+
+      cp_error ("invalid data member initialization");
+      if (!explained)
+       {
+         cp_error ("(use `=' to initialize static data members)");
+         explained = 1;
+       }
+
       declarator = TREE_OPERAND (declarator, 0);
       flags = 0;
     }
@@ -1577,6 +1586,8 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
   if (! value || value == error_mark_node)
     /* friend or constructor went bad.  */
     return value;
+  if (TREE_TYPE (value) == error_mark_node)
+    return error_mark_node;  
 
   /* Pass friendly classes back.  */
   if (TREE_CODE (value) == VOID_TYPE)
@@ -1593,15 +1604,10 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
     {
       DECL_NONLOCAL (value) = 1;
       DECL_CONTEXT (value) = current_class_type;
-      DECL_CLASS_CONTEXT (value) = current_class_type;
-
-      /* Now that we've updated the context, we need to remangle the
-        name for this TYPE_DECL.  */
-      DECL_ASSEMBLER_NAME (value) = DECL_NAME (value);
-      if (!uses_template_parms (value))
-       DECL_ASSEMBLER_NAME (value) =
-         get_identifier (build_overload_name (TREE_TYPE (value), 1, 1));
 
+      if (CLASS_TYPE_P (TREE_TYPE (value)))
+        CLASSTYPE_GOT_SEMICOLON (TREE_TYPE (value)) = 1;
+      
       if (processing_template_decl)
        value = push_template_decl (value);
 
@@ -1659,8 +1665,7 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
                 static, since references are initialized with the address.  */
              if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE
                  || (TREE_STATIC (init) == 0
-                     && (TREE_CODE_CLASS (TREE_CODE (init)) != 'd'
-                         || DECL_EXTERNAL (init) == 0)))
+                     && (!DECL_P (init) || DECL_EXTERNAL (init) == 0)))
                {
                  error ("field initializer is not constant");
                  init = error_mark_node;
@@ -1686,15 +1691,10 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
   if (TREE_CODE (value) == FIELD_DECL)
     {
       if (asmspec)
-       {
-         /* This must override the asm specifier which was placed
-            by grokclassfn.  Lay this out fresh.  */
-         DECL_RTL (value) = NULL_RTX;
-         DECL_ASSEMBLER_NAME (value) = get_identifier (asmspec);
-       }
+       cp_error ("`asm' specifiers are not permitted on non-static data members");
       if (DECL_INITIAL (value) == error_mark_node)
        init = error_mark_node;
-      cp_finish_decl (value, init, asmspec_tree, flags);
+      cp_finish_decl (value, init, NULL_TREE, flags);
       DECL_INITIAL (value) = init;
       DECL_IN_AGGR_P (value) = 1;
       return value;
@@ -1705,8 +1705,8 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
        {
          /* This must override the asm specifier which was placed
             by grokclassfn.  Lay this out fresh.  */
-         DECL_RTL (value) = NULL_RTX;
-         DECL_ASSEMBLER_NAME (value) = get_identifier (asmspec);
+         SET_DECL_RTL (value, NULL_RTX);
+         SET_DECL_ASSEMBLER_NAME (value, get_identifier (asmspec));
        }
       cp_finish_decl (value, init, asmspec_tree, flags);
 
@@ -1787,7 +1787,7 @@ grokoptypename (declspecs, declarator)
      tree declspecs, declarator;
 {
   tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE);
-  return build_typename_overload (t);
+  return mangle_conv_op_name_for_type (t);
 }
 
 /* When a function is declared with an initializer,
@@ -1858,27 +1858,10 @@ grok_function_init (decl, init)
 
   if (TREE_CODE (type) == FUNCTION_TYPE)
     cp_error ("initializer specified for non-member function `%D'", decl);
-#if 0
-  /* We'll check for this in finish_struct_1.  */
-  else if (DECL_VINDEX (decl) == NULL_TREE)
-    cp_error ("initializer specified for non-virtual method `%D'", decl);
-#endif
   else if (integer_zerop (init))
     {
-#if 0
-      /* Mark this function as being "defined".  */
-      DECL_INITIAL (decl) = error_mark_node;
-      /* pure virtual destructors must be defined.  */
-      /* pure virtual needs to be defined (as abort) only when put in 
-        vtbl. For wellformed call, it should be itself. pr4737 */
-      if (!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)))
-       {
-         /* Give this node rtl from `abort'.  */
-         DECL_RTL (decl) = DECL_RTL (abort_fndecl);
-       }
-#endif
-      DECL_ABSTRACT_VIRTUAL_P (decl) = 1;
-      if (DECL_NAME (decl) == ansi_opname [(int) MODIFY_EXPR])
+      DECL_PURE_VIRTUAL_P (decl) = 1;
+      if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
        {
          tree parmtype
            = TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl))));
@@ -1901,7 +1884,7 @@ cplus_decl_attributes (decl, attributes, prefix_attributes)
   if (TREE_CODE (decl) == TEMPLATE_DECL)
     decl = DECL_TEMPLATE_RESULT (decl);
 
-  decl_attributes (decl, attributes, prefix_attributes);
+  decl_attributes (decl, chainon (attributes, prefix_attributes));
 
   if (TREE_CODE (decl) == TYPE_DECL)
     SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (decl), TREE_TYPE (decl));
@@ -1918,7 +1901,7 @@ constructor_name_full (thing)
      tree thing;
 {
   if (TREE_CODE (thing) == TEMPLATE_TYPE_PARM
-      || TREE_CODE (thing) == TEMPLATE_TEMPLATE_PARM
+      || TREE_CODE (thing) == BOUND_TEMPLATE_TEMPLATE_PARM
       || TREE_CODE (thing) == TYPENAME_TYPE)
     thing = TYPE_NAME (thing);
   else if (IS_AGGR_TYPE_CODE (TREE_CODE (thing)))
@@ -1954,55 +1937,42 @@ constructor_name (thing)
   return t;
 }
 \f
-/* Record the existence of an addressable inline function.  */
+/* Defer the compilation of the FN until the end of compilation.  */
 
 void
-mark_inline_for_output (decl)
-     tree decl;
+defer_fn (fn)
+     tree fn;
 {
-  decl = DECL_MAIN_VARIANT (decl);
-  if (DECL_SAVED_INLINE (decl))
+  if (DECL_DEFERRED_FN (fn))
     return;
-  DECL_SAVED_INLINE (decl) = 1;
-  if (!saved_inlines)
-    VARRAY_TREE_INIT (saved_inlines, 32, "saved_inlines");
-  
-  if (saved_inlines_used == saved_inlines->num_elements)
-    VARRAY_GROW (saved_inlines, 
-                2 * saved_inlines->num_elements);
-  VARRAY_TREE (saved_inlines, saved_inlines_used) = decl;
-  ++saved_inlines_used;
+  DECL_DEFERRED_FN (fn) = 1;
+  if (!deferred_fns)
+    VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
+
+  VARRAY_PUSH_TREE (deferred_fns, fn);
 }
 
 /* Hand off a unique name which can be used for variable we don't really
    want to know about anyway, for example, the anonymous variables which
    are needed to make references work.  Declare this thing so we can use it.
-   The variable created will be of type TYPE.
-
-   STATICP is nonzero if this variable should be static.  */
+   The variable created will be of type TYPE, and will have internal
+   linkage.  */
 
 tree
-get_temp_name (type, staticp)
+get_temp_name (type)
      tree type;
-     int staticp;
 {
   char buf[sizeof (AUTO_TEMP_FORMAT) + 20];
   tree decl;
   int toplev = toplevel_bindings_p ();
 
-  if (toplev || staticp)
-    {
-      sprintf (buf, AUTO_TEMP_FORMAT, global_temp_name_counter++);
-      decl = pushdecl_top_level (build_decl (VAR_DECL, get_identifier (buf), type));
-    }
-  else
-    {
-      sprintf (buf, AUTO_TEMP_FORMAT, temp_name_counter++);
-      decl = pushdecl (build_decl (VAR_DECL, get_identifier (buf), type));
-    }
-  TREE_USED (decl) = 1;
-  TREE_STATIC (decl) = staticp;
+  sprintf (buf, AUTO_TEMP_FORMAT, global_temp_name_counter++);
+  decl = build_decl (VAR_DECL, get_identifier (buf), type);
   DECL_ARTIFICIAL (decl) = 1;
+  TREE_USED (decl) = 1;
+  TREE_STATIC (decl) = 1;
+  
+  decl = pushdecl_top_level (decl);
 
   /* If this is a local variable, then lay out its rtl now.
      Otherwise, callers of this function are responsible for dealing
@@ -2079,12 +2049,17 @@ build_anon_union_vars (anon_decl, elems, static_p, external_p)
          DECL_INITIAL (decl) = NULL_TREE;
        }
 
-      /* Only write out one anon union element--choose the one that
-        can hold them all.  */
+      /* Only write out one anon union element--choose the largest
+        one.  We used to try to find one the same size as the union,
+        but that fails if the ABI forces us to align the union more
+        strictly.  */
       if (main_decl == NULL_TREE
-         && simple_cst_equal (DECL_SIZE (decl),
-                              DECL_SIZE (anon_decl)) == 1)
-       main_decl = decl;
+         || tree_int_cst_lt (DECL_SIZE (main_decl), DECL_SIZE (decl)))
+       {
+         if (main_decl)
+           TREE_ASM_WRITTEN (main_decl) = 1;
+         main_decl = decl;
+       }
       else 
        /* ??? This causes there to be no debug info written out
           about this decl.  */
@@ -2105,12 +2080,9 @@ build_anon_union_vars (anon_decl, elems, static_p, external_p)
   return main_decl;
 }
 
-/* Finish off the processing of a UNION_TYPE structure.
-   If there are static members, then all members are
-   static, and must be laid out together.  If the
-   union is an anonymous union, we arrange for that
-   as well.  PUBLIC_P is nonzero if this union is
-   not declared static.  */
+/* Finish off the processing of a UNION_TYPE structure.  If the union is an
+   anonymous union, then all members must be laid out together.  PUBLIC_P
+   is nonzero if this union is not declared static.  */
 
 void
 finish_anon_union (anon_union_decl)
@@ -2122,12 +2094,15 @@ finish_anon_union (anon_union_decl)
   int static_p = TREE_STATIC (anon_union_decl);
   int external_p = DECL_EXTERNAL (anon_union_decl);
 
+  /* The VAR_DECL's context is the same as the TYPE's context. */
+  DECL_CONTEXT (anon_union_decl) = DECL_CONTEXT (TYPE_NAME (type));
+  
   if (TYPE_FIELDS (type) == NULL_TREE)
     return;
 
   if (public_p)
     {
-      error ("global anonymous unions must be declared static");
+      error ("namespace-scope anonymous aggregates must be static");
       return;
     }
 
@@ -2137,14 +2112,14 @@ finish_anon_union (anon_union_decl)
 
   if (main_decl == NULL_TREE)
     {
-      warning ("anonymous union with no members");
+      warning ("anonymous aggregate with no members");
       return;
     }
 
   if (static_p)
     {
-      make_decl_rtl (main_decl, 0, toplevel_bindings_p ());
-      DECL_RTL (anon_union_decl) = DECL_RTL (main_decl);
+      make_decl_rtl (main_decl, 0);
+      COPY_DECL_RTL (main_decl, anon_union_decl);
       expand_anon_union_decl (anon_union_decl, 
                              NULL_TREE,
                              DECL_ANON_UNION_ELEMS (anon_union_decl));
@@ -2178,8 +2153,8 @@ finish_builtin_type (type, name, fields, len, align_type)
       TREE_CHAIN (fields[i]) = fields[i+1];
     }
   DECL_FIELD_CONTEXT (fields[i]) = type;
-  DECL_CLASS_CONTEXT (fields[i]) = type;
   TYPE_ALIGN (type) = TYPE_ALIGN (align_type);
+  TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (align_type);
   layout_type (type);
 #if 0 /* not yet, should get fixed properly later */
   TYPE_NAME (type) = make_type_decl (get_identifier (name), type);
@@ -2198,23 +2173,34 @@ tree
 coerce_new_type (type)
      tree type;
 {
-  int e1 = 0, e2 = 0;
-
-  if (TREE_CODE (type) == METHOD_TYPE)
-    type = build_function_type (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type)));
-  if (! same_type_p (TREE_TYPE (type), ptr_type_node))
-    e1 = 1, error ("`operator new' must return type `void *'");
-
-  /* Technically the type must be `size_t', but we may not know
-     what that is.  */
-  if (TYPE_ARG_TYPES (type) == NULL_TREE)
-    e1 = 1, error ("`operator new' takes type `size_t' parameter");
-  else if (! same_type_p (TREE_VALUE (TYPE_ARG_TYPES (type)), sizetype))
-    e2 = 1, error ("`operator new' takes type `size_t' as first parameter");
-  if (e2)
-    type = build_function_type (ptr_type_node, tree_cons (NULL_TREE, sizetype, TREE_CHAIN (TYPE_ARG_TYPES (type))));
-  else if (e1)
-    type = build_function_type (ptr_type_node, TYPE_ARG_TYPES (type));
+  int e = 0;
+  tree args = TYPE_ARG_TYPES (type);
+
+  my_friendly_assert (TREE_CODE (type) == FUNCTION_TYPE, 20001107);
+  
+  if (!same_type_p (TREE_TYPE (type), ptr_type_node))
+    e = 1, cp_error ("`operator new' must return type `%T'", ptr_type_node);
+
+  if (!args || args == void_list_node
+      || !same_type_p (TREE_VALUE (args), c_size_type_node))
+    {
+      e = 2;
+      if (args && args != void_list_node)
+        args = TREE_CHAIN (args);
+      cp_error ("`operator new' takes type `size_t' (`%T') as first parameter", c_size_type_node);
+    }
+  switch (e)
+  {
+    case 2:
+      args = tree_cons (NULL_TREE, c_size_type_node, args);
+      /* FALLTHROUGH */
+    case 1:
+      type = build_exception_variant
+              (build_function_type (ptr_type_node, args),
+               TYPE_RAISES_EXCEPTIONS (type));
+      /* FALLTHROUGH */
+    default:;
+  }
   return type;
 }
 
@@ -2222,63 +2208,34 @@ tree
 coerce_delete_type (type)
      tree type;
 {
-  int e1 = 0, e2 = 0;
-#if 0
-  e3 = 0;
-#endif
-  tree arg_types = TYPE_ARG_TYPES (type);
-
-  if (TREE_CODE (type) == METHOD_TYPE)
-    {
-      type = build_function_type (TREE_TYPE (type), TREE_CHAIN (arg_types));
-      arg_types = TREE_CHAIN (arg_types);
-    }
-
-  if (TREE_TYPE (type) != void_type_node)
-    e1 = 1, error ("`operator delete' must return type `void'");
-
-  if (arg_types == NULL_TREE
-      || ! same_type_p (TREE_VALUE (arg_types), ptr_type_node))
-    e2 = 1, error ("`operator delete' takes type `void *' as first parameter");
+  int e = 0;
+  tree args = TYPE_ARG_TYPES (type);
+  
+  my_friendly_assert (TREE_CODE (type) == FUNCTION_TYPE, 20001107);
 
-#if 0
-  if (arg_types
-      && TREE_CHAIN (arg_types)
-      && TREE_CHAIN (arg_types) != void_list_node)
-    {
-      /* Again, technically this argument must be `size_t', but again
-        we may not know what that is.  */
-      tree t2 = TREE_VALUE (TREE_CHAIN (arg_types));
-      if (! same_type_p (t2, sizetype))
-       e3 = 1, error ("second argument to `operator delete' must be of type `size_t'");
-      else if (TREE_CHAIN (TREE_CHAIN (arg_types)) != void_list_node)
-       {
-         e3 = 1;
-         if (TREE_CHAIN (TREE_CHAIN (arg_types)))
-           error ("too many arguments in declaration of `operator delete'");
-         else
-           error ("`...' invalid in specification of `operator delete'");
-       }
-    }
+  if (!same_type_p (TREE_TYPE (type), void_type_node))
+    e = 1, cp_error ("`operator delete' must return type `%T'", void_type_node);
 
-  if (e3)
-    arg_types = tree_cons (NULL_TREE, ptr_type_node,
-                          build_tree_list (NULL_TREE, sizetype));
-  else if (e3 |= e2)
+  if (!args || args == void_list_node
+      || !same_type_p (TREE_VALUE (args), ptr_type_node))
     {
-      if (arg_types == NULL_TREE)
-       arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
-      else
-       arg_types = tree_cons (NULL_TREE, ptr_type_node, TREE_CHAIN (arg_types));
+      e = 2;
+      if (args && args != void_list_node)
+        args = TREE_CHAIN (args);
+      cp_error ("`operator delete' takes type `%T' as first parameter", ptr_type_node);
     }
-  else e3 |= e1;
-#endif
-
-  if (e2)
-    arg_types = tree_cons (NULL_TREE, ptr_type_node,
-                          arg_types ? TREE_CHAIN (arg_types): NULL_TREE);
-  if (e2 || e1)
-    type = build_function_type (void_type_node, arg_types);
+  switch (e)
+  {
+    case 2:
+      args = tree_cons (NULL_TREE, ptr_type_node, args);
+      /* FALLTHROUGH */
+    case 1:
+      type = build_exception_variant
+              (build_function_type (void_type_node, args),
+               TYPE_RAISES_EXCEPTIONS (type));
+      /* FALLTHROUGH */
+    default:;
+  }
 
   return type;
 }
@@ -2297,17 +2254,19 @@ mark_vtable_entries (decl)
       fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries) 
                : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
 
-      if (TREE_CODE (fnaddr) == NOP_EXPR)
-       /* RTTI offset.  */
+      if (TREE_CODE (fnaddr) != ADDR_EXPR)
+       /* This entry is an offset: a virtual base class offset, a
+          virtual call offset, an RTTI offset, etc.  */
        continue;
 
       fn = TREE_OPERAND (fnaddr, 0);
       TREE_ADDRESSABLE (fn) = 1;
-      if (TREE_CODE (fn) == THUNK_DECL && DECL_EXTERNAL (fn))
-       {
-         DECL_EXTERNAL (fn) = 0;
-         emit_thunk (fn);
-       }
+      /* When we don't have vcall offsets, we output thunks whenever
+        we output the vtables that contain them.  With vcall offsets,
+        we know all the thunks we'll need when we emit a virtual
+        function, so we emit the thunks there instead.  */
+      if (DECL_THUNK_P (fn)) 
+       use_thunk (fn, /*emit_p=*/0);
       mark_used (fn);
     }
 }
@@ -2321,9 +2280,24 @@ comdat_linkage (decl)
 {
   if (flag_weak)
     make_decl_one_only (decl);
-  else if (TREE_CODE (decl) == FUNCTION_DECL || DECL_VIRTUAL_P (decl))
-    /* We can just emit functions and vtables statically; it doesn't really
-       matter if we have multiple copies.  */
+  else if (TREE_CODE (decl) == FUNCTION_DECL 
+          || (TREE_CODE (decl) == VAR_DECL && DECL_ARTIFICIAL (decl)))
+    /* We can just emit function and compiler-generated variables
+       statically; having multiple copies is (for the most part) only
+       a waste of space.  
+
+       There are two correctness issues, however: the address of a
+       template instantiation with external linkage should be the
+       same, independent of what translation unit asks for the
+       address, and this will not hold when we emit multiple copies of
+       the function.  However, there's little else we can do.  
+
+       Also, by default, the typeinfo implementation for the new ABI
+       assumes that there will be only one copy of the string used as
+       the name for each type.  Therefore, if weak symbols are
+       unavailable, the run-time library should perform a more
+       conservative check; it should perform a string comparison,
+       rather than an address comparison.  */
     TREE_PUBLIC (decl) = 0;
   else
     {
@@ -2348,9 +2322,6 @@ comdat_linkage (decl)
 
   if (DECL_LANG_SPECIFIC (decl))
     DECL_COMDAT (decl) = 1;
-
-  if (TREE_CODE (decl) == FUNCTION_DECL)
-    DECL_DEFER_OUTPUT (decl) = 1;
 }
 
 /* For win32 we also want to put explicit instantiations in
@@ -2367,7 +2338,7 @@ maybe_make_one_only (decl)
      after a weak one is an error.  Also, not making explicit
      instantiations one_only means that we can end up with two copies of
      some template instantiations. */
-  if (! supports_one_only ())
+  if (! flag_weak)
     return;
 
   /* We can't set DECL_COMDAT on functions, or finish_file will think
@@ -2381,6 +2352,35 @@ maybe_make_one_only (decl)
     DECL_COMDAT (decl) = 1;
 }
 
+/* Returns the virtual function with which the vtable for TYPE is
+   emitted, or NULL_TREE if that heuristic is not applicable to TYPE.  */
+
+static tree
+key_method (type)
+     tree type;
+{
+  tree method;
+
+  if (TYPE_FOR_JAVA (type)
+      || CLASSTYPE_TEMPLATE_INSTANTIATION (type)
+      || CLASSTYPE_INTERFACE_KNOWN (type))
+    return NULL_TREE;
+
+  for (method = TYPE_METHODS (type); method != NULL_TREE;
+       method = TREE_CHAIN (method))
+    if (DECL_VINDEX (method) != NULL_TREE
+       && ! DECL_DECLARED_INLINE_P (method)
+       && (! DECL_PURE_VIRTUAL_P (method)
+#if 0
+           /* This would be nice, but we didn't think of it in time.  */
+           || DECL_DESTRUCTOR_P (method)
+#endif
+           ))
+      return method;
+
+  return NULL_TREE;
+}
+
 /* Set TREE_PUBLIC and/or DECL_EXTERN on the vtable DECL,
    based on TYPE and other static flags.
 
@@ -2404,7 +2404,7 @@ import_export_vtable (decl, type, final)
   else if (CLASSTYPE_INTERFACE_KNOWN (type))
     {
       TREE_PUBLIC (decl) = 1;
-      DECL_EXTERNAL (decl) = ! CLASSTYPE_VTABLE_NEEDS_WRITING (type);
+      DECL_EXTERNAL (decl) = CLASSTYPE_INTERFACE_ONLY (type);
       DECL_INTERFACE_KNOWN (decl) = 1;
     }
   else
@@ -2412,21 +2412,8 @@ import_export_vtable (decl, type, final)
       /* We can only wait to decide if we have real non-inline virtual
         functions in our class, or if we come from a template.  */
 
-      int found = CLASSTYPE_TEMPLATE_INSTANTIATION (type);
-
-      if (! found && ! final)
-       {
-         tree method;
-         for (method = TYPE_METHODS (type); method != NULL_TREE;
-              method = TREE_CHAIN (method))
-           if (DECL_VINDEX (method) != NULL_TREE
-               && ! DECL_THIS_INLINE (method)
-               && ! DECL_ABSTRACT_VIRTUAL_P (method))
-             {
-               found = 1;
-               break;
-             }
-       }
+      int found = (CLASSTYPE_TEMPLATE_INSTANTIATION (type)
+                  || key_method (type));
 
       if (final || ! found)
        {
@@ -2444,13 +2431,20 @@ import_export_vtable (decl, type, final)
 /* Determine whether or not we want to specifically import or export CTYPE,
    using various heuristics.  */
 
-void
+static void
 import_export_class (ctype)
      tree ctype;
 {
   /* -1 for imported, 1 for exported.  */
   int import_export = 0;
 
+  /* It only makes sense to call this function at EOF.  The reason is
+     that this function looks at whether or not the first non-inline
+     non-abstract virtual member function has been defined in this
+     translation unit.  But, we can't possibly know that until we've
+     seen the entire translation unit.  */
+  my_friendly_assert (at_eof, 20000226);
+
   if (CLASSTYPE_INTERFACE_KNOWN (ctype))
     return;
 
@@ -2462,13 +2456,18 @@ import_export_class (ctype)
   if (CLASSTYPE_INTERFACE_ONLY (ctype))
     return;
 
-#ifdef VALID_MACHINE_TYPE_ATTRIBUTE
-  /* FIXME this should really use some sort of target-independent macro.  */
-  if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype)))
+  if ((*targetm.valid_type_attribute) (ctype,
+                                      TYPE_ATTRIBUTES (ctype),
+                                      get_identifier ("dllimport"),
+                                      NULL_TREE)
+      && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype)))
     import_export = -1;
-  else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
+  else if ((*targetm.valid_type_attribute) (ctype,
+                                           TYPE_ATTRIBUTES (ctype),
+                                           get_identifier ("dllexport"),
+                                           NULL_TREE)
+          && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
     import_export = 1;
-#endif
 
   /* If we got -fno-implicit-templates, we import template classes that
      weren't explicitly instantiated.  */
@@ -2478,23 +2477,13 @@ import_export_class (ctype)
     import_export = -1;
 
   /* Base our import/export status on that of the first non-inline,
-     non-abstract virtual function, if any.  */
+     non-pure virtual function, if any.  */
   if (import_export == 0
-      && TYPE_VIRTUAL_P (ctype)
-      && ! CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
+      && TYPE_POLYMORPHIC_P (ctype))
     {
-      tree method;
-      for (method = TYPE_METHODS (ctype); method != NULL_TREE;
-          method = TREE_CHAIN (method))
-       {
-         if (DECL_VINDEX (method) != NULL_TREE
-             && !DECL_THIS_INLINE (method)
-             && !DECL_ABSTRACT_VIRTUAL_P (method))
-           {
-             import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1);
-             break;
-           }
-       }
+      tree method = key_method (ctype);
+      if (method)
+       import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1);
     }
 
 #ifdef MULTIPLE_SYMBOL_SPACES
@@ -2505,7 +2494,6 @@ import_export_class (ctype)
   if (import_export)
     {
       SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
-      CLASSTYPE_VTABLE_NEEDS_WRITING (ctype) = (import_export > 0);
       CLASSTYPE_INTERFACE_ONLY (ctype) = (import_export < 0);
     }
 }
@@ -2528,7 +2516,7 @@ output_vtable_inherit (vars)
     op[1] = const0_rtx;
   else if (parent)
     {
-      parent = TYPE_BINFO_VTABLE (BINFO_TYPE (parent));
+      parent = get_vtbl_decl_for_binfo (TYPE_BINFO (BINFO_TYPE (parent)));
       op[1] = XEXP (DECL_RTL (parent), 0);  /* strip the mem ref  */
     }
   else
@@ -2548,11 +2536,13 @@ finish_vtable_vardecl (t, data)
   import_export_vtable (vars, ctype, 1);
 
   if (! DECL_EXTERNAL (vars)
-      && (DECL_INTERFACE_KNOWN (vars) 
-         || DECL_NEEDED_P (vars)
-         || (hack_decl_function_context (vars) && TREE_USED (vars)))
+      && DECL_NEEDED_P (vars)
       && ! TREE_ASM_WRITTEN (vars))
     {
+      if (TREE_TYPE (vars) == void_type_node)
+        /* It is a dummy vtable made by get_vtable_decl. Ignore it.  */
+        return 0;
+      
       /* Write it out.  */
       mark_vtable_entries (vars);
       if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
@@ -2588,7 +2578,7 @@ finish_vtable_vardecl (t, data)
       if (flag_weak)
        comdat_linkage (vars);
 
-      rest_of_decl_compilation (vars, NULL_PTR, 1, 1);
+      rest_of_decl_compilation (vars, NULL, 1, 1);
 
       if (flag_vtable_gc)
        output_vtable_inherit (vars);
@@ -2598,13 +2588,19 @@ finish_vtable_vardecl (t, data)
       if (flag_syntax_only)
        TREE_ASM_WRITTEN (vars) = 1;
 
+      /* Since we're writing out the vtable here, also write the debug 
+        info.  */
+      note_debug_info_needed (ctype);
+
       return 1;
     }
-  else if (!DECL_NEEDED_P (vars))
-    /* We don't know what to do with this one yet.  */
-    return 0;
 
-  *t = TREE_CHAIN (vars);
+  /* If the references to this class' vtables were optimized away, still
+     emit the appropriate debugging information.  See dfs_debug_mark.  */
+  if (DECL_COMDAT (vars)
+      && CLASSTYPE_DEBUG_REQUESTED (ctype))
+    note_debug_info_needed (ctype);
+
   return 0;
 }
 
@@ -2634,7 +2630,8 @@ import_export_decl (decl)
       if ((DECL_IMPLICIT_INSTANTIATION (decl)
           || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
          && (flag_implicit_templates
-             || (flag_implicit_inline_templates && DECL_THIS_INLINE (decl))))
+             || (flag_implicit_inline_templates 
+                 && DECL_DECLARED_INLINE_P (decl))))
        {
          if (!TREE_PUBLIC (decl))
            /* Templates are allowed to have internal linkage.  See 
@@ -2648,28 +2645,29 @@ import_export_decl (decl)
     }
   else if (DECL_FUNCTION_MEMBER_P (decl))
     {
-      tree ctype = DECL_CLASS_CONTEXT (decl);
-      import_export_class (ctype);
-      if (CLASSTYPE_INTERFACE_KNOWN (ctype)
-         && (flag_new_abi
-             ? (! DECL_THIS_INLINE (decl))
-             : (! DECL_ARTIFICIAL (decl) || DECL_VINDEX (decl))))
+      if (!DECL_DECLARED_INLINE_P (decl))
        {
-         DECL_NOT_REALLY_EXTERN (decl)
-           = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
-                || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines
-                    && !DECL_VINDEX (decl)));
-
-         /* Always make artificials weak.  */
-         if (DECL_ARTIFICIAL (decl) && flag_weak)
-           comdat_linkage (decl);
-         else
-           maybe_make_one_only (decl);
+         tree ctype = DECL_CONTEXT (decl);
+         import_export_class (ctype);
+         if (CLASSTYPE_INTERFACE_KNOWN (ctype))
+           {
+             DECL_NOT_REALLY_EXTERN (decl)
+               = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
+                    || (DECL_DECLARED_INLINE_P (decl) 
+                        && ! flag_implement_inlines
+                        && !DECL_VINDEX (decl)));
+
+             /* Always make artificials weak.  */
+             if (DECL_ARTIFICIAL (decl) && flag_weak)
+               comdat_linkage (decl);
+             else
+               maybe_make_one_only (decl);
+           }
        }
       else
        comdat_linkage (decl);
     }
-  else if (DECL_TINFO_FN_P (decl))
+  else if (tinfo_decl_p (decl, 0))
     {
       tree ctype = TREE_TYPE (DECL_NAME (decl));
 
@@ -2677,7 +2675,7 @@ import_export_decl (decl)
        import_export_class (ctype);
 
       if (IS_AGGR_TYPE (ctype) && CLASSTYPE_INTERFACE_KNOWN (ctype)
-         && TYPE_VIRTUAL_P (ctype)
+         && TYPE_POLYMORPHIC_P (ctype)
          /* If -fno-rtti, we're not necessarily emitting this stuff with
             the class, so go ahead and emit it now.  This can happen
             when a class is used in exception handling.  */
@@ -2691,7 +2689,8 @@ import_export_decl (decl)
        {
          DECL_NOT_REALLY_EXTERN (decl)
            = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
-                || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines
+                || (DECL_DECLARED_INLINE_P (decl) 
+                    && ! flag_implement_inlines
                     && !DECL_VINDEX (decl)));
 
          /* Always make artificials weak.  */
@@ -2725,34 +2724,100 @@ build_cleanup (decl)
       temp = build1 (ADDR_EXPR, build_pointer_type (type), decl);
     }
   temp = build_delete (TREE_TYPE (temp), temp,
-                      integer_two_node,
+                      sfk_complete_destructor,
                       LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
   return temp;
 }
 
-extern int parse_time, varconst_time;
+/* Returns the initialization guard variable for the variable DECL,
+   which has static storage duration.  */
 
-static tree
-get_sentry (base)
-     tree base;
+tree
+get_guard (decl)
+     tree decl;
 {
-  tree sname = get_id_2 ("__sn", base);
-  /* For struct X foo __attribute__((weak)), there is a counter
-     __snfoo. Since base is already an assembler name, sname should
-     be globally unique */
-  tree sentry = IDENTIFIER_GLOBAL_VALUE (sname);
-  if (! sentry)
+  tree sname;
+  tree guard;
+
+  sname = mangle_guard_variable (decl);
+  guard = IDENTIFIER_GLOBAL_VALUE (sname);
+  if (! guard)
     {
-      sentry = build_decl (VAR_DECL, sname, integer_type_node);
-      TREE_PUBLIC (sentry) = 1;
-      DECL_ARTIFICIAL (sentry) = 1;
-      TREE_STATIC (sentry) = 1;
-      TREE_USED (sentry) = 1;
-      DECL_COMMON (sentry) = 1;
-      pushdecl_top_level (sentry);
-      cp_finish_decl (sentry, NULL_TREE, NULL_TREE, 0);
+      tree guard_type;
+
+      /* Under the new ABI, we use a type that is big enough to
+        contain a mutex as well as an integer counter.  */
+      guard_type = long_long_integer_type_node;
+      guard = build_decl (VAR_DECL, sname, guard_type);
+      
+      /* The guard should have the same linkage as what it guards. */
+      TREE_PUBLIC (guard) = TREE_PUBLIC (decl);
+      TREE_STATIC (guard) = TREE_STATIC (decl);
+      DECL_COMMON (guard) = DECL_COMMON (decl);
+      DECL_ONE_ONLY (guard) = DECL_ONE_ONLY (decl);
+      if (TREE_PUBLIC (decl))
+        DECL_WEAK (guard) = DECL_WEAK (decl);
+      
+      DECL_ARTIFICIAL (guard) = 1;
+      TREE_USED (guard) = 1;
+      pushdecl_top_level (guard);
+      cp_finish_decl (guard, NULL_TREE, NULL_TREE, 0);
     }
-  return sentry;
+  return guard;
+}
+
+/* Return those bits of the GUARD variable that should be set when the
+   guarded entity is actually initialized.  */
+
+static tree
+get_guard_bits (guard)
+     tree guard;
+{
+  /* Under the new ABI, we only set the first byte of the guard,
+     in order to leave room for a mutex in the high-order bits.  */
+  guard = build1 (ADDR_EXPR, 
+                 build_pointer_type (TREE_TYPE (guard)),
+                 guard);
+  guard = build1 (NOP_EXPR, 
+                 build_pointer_type (char_type_node), 
+                 guard);
+  guard = build1 (INDIRECT_REF, char_type_node, guard);
+
+  return guard;
+}
+
+/* Return an expression which determines whether or not the GUARD
+   variable has already been initialized.  */
+
+tree
+get_guard_cond (guard)
+     tree guard;
+{
+  tree guard_value;
+
+  /* Check to see if the GUARD is zero.  */
+  guard = get_guard_bits (guard);
+  guard_value = integer_zero_node;
+  if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
+    guard_value = convert (TREE_TYPE (guard), guard_value);
+  return cp_build_binary_op (EQ_EXPR, guard, guard_value);
+}
+
+/* Return an expression which sets the GUARD variable, indicating that
+   the variable being guarded has been initialized.  */
+
+tree
+set_guard (guard)
+     tree guard;
+{
+  tree guard_init;
+
+  /* Set the GUARD to one.  */
+  guard = get_guard_bits (guard);
+  guard_init = integer_one_node;
+  if (!same_type_p (TREE_TYPE (guard_init), TREE_TYPE (guard)))
+    guard_init = convert (TREE_TYPE (guard), guard_init);
+  return build_modify_expr (guard, NOP_EXPR, guard_init);
 }
 
 /* Start the process of running a particular set of global constructors
@@ -2826,12 +2891,12 @@ finish_objects (method_type, initp, body)
      int method_type, initp;
      tree body;
 {
-  char *fnname;
+  const char *fnname;
   tree fn;
 
-  /* Finish up. */
-  finish_compound_stmt(/*has_no_scope=*/0, body);
-  fn = finish_function (lineno, 0);
+  /* Finish up.  */
+  finish_compound_stmt (/*has_no_scope=*/0, body);
+  fn = finish_function (0);
   expand_body (fn);
 
   /* When only doing semantic analysis, and no RTL generation, we
@@ -2861,7 +2926,7 @@ finish_objects (method_type, initp, body)
                  linker sorts in increasing order.  */
               MAX_INIT_PRIORITY - initp);
       named_section (NULL_TREE, buf, 0);
-      assemble_integer (gen_rtx_SYMBOL_REF (Pmode, fnname),
+      assemble_integer (XEXP (DECL_RTL (fn), 0),
                        POINTER_SIZE / BITS_PER_UNIT, 1);
     }
 #endif
@@ -2889,7 +2954,6 @@ static tree ssdf_decl;
 /* All the static storage duration functions created in this
    translation unit.  */
 static varray_type ssdf_decls;
-static size_t ssdf_decls_used;
 
 /* A map from priority levels to information about that priority
    level.  There may be many such levels, so efficient lookup is
@@ -2962,10 +3026,7 @@ start_static_storage_duration_function ()
       get_priority_info (DEFAULT_INIT_PRIORITY);
     }
 
-  if (ssdf_decls_used == ssdf_decls->num_elements)
-    VARRAY_GROW (ssdf_decls, 2 * ssdf_decls_used);
-  VARRAY_TREE (ssdf_decls, ssdf_decls_used) = ssdf_decl;
-  ++ssdf_decls_used;
+  VARRAY_PUSH_TREE (ssdf_decls, ssdf_decl);
 
   /* Create the argument list.  */
   initialize_p_decl = build_decl (PARM_DECL,
@@ -3019,7 +3080,7 @@ finish_static_storage_duration_function (body)
 {
   /* Close out the function.  */
   finish_compound_stmt (/*has_no_scope=*/0, body);
-  expand_body (finish_function (lineno, 0));
+  expand_body (finish_function (0));
 }
 
 /* Return the information about the indicated PRIORITY level.  If no
@@ -3061,9 +3122,10 @@ start_static_initialization_or_destruction (decl, initp)
      tree decl;
      int initp;
 {
-  tree sentry_if_stmt = NULL_TREE;
+  tree guard_if_stmt = NULL_TREE;
   int priority;
   tree cond;
+  tree guard;
   tree init_cond;
   priority_info pi;
 
@@ -3101,78 +3163,100 @@ start_static_initialization_or_destruction (decl, initp)
      which the DECL is a member.  */
   if (member_p (decl))
     {
-      DECL_CLASS_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
+      DECL_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
       DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
     }
   
   /* Conditionalize this initialization on being in the right priority
      and being initializing/finalizing appropriately.  */
-  sentry_if_stmt = begin_if_stmt ();
-  cond = build_binary_op (EQ_EXPR,
-                         priority_decl,
-                         build_int_2 (priority, 0));
+  guard_if_stmt = begin_if_stmt ();
+  cond = cp_build_binary_op (EQ_EXPR,
+                            priority_decl,
+                            build_int_2 (priority, 0));
   init_cond = initp ? integer_one_node : integer_zero_node;
-  init_cond = build_binary_op (EQ_EXPR,
-                              initialize_p_decl,
-                              init_cond);
-  cond = build_binary_op (TRUTH_ANDIF_EXPR, cond, init_cond);
-
-  /* We need a sentry if this is an object with external linkage that
-     might be initialized in more than one place.  */
+  init_cond = cp_build_binary_op (EQ_EXPR,
+                                 initialize_p_decl,
+                                 init_cond);
+  cond = cp_build_binary_op (TRUTH_ANDIF_EXPR, cond, init_cond);
+
+  /* Assume we don't need a guard.  */
+  guard = NULL_TREE;
+  /* We need a guard if this is an object with external linkage that
+     might be initialized in more than one place.  (For example, a
+     static data member of a template, when the data member requires
+     construction.)  */
   if (TREE_PUBLIC (decl) && (DECL_COMMON (decl) 
                             || DECL_ONE_ONLY (decl)
                             || DECL_WEAK (decl)))
     {
-      tree sentry;
-      tree sentry_cond;
-
-      sentry = get_sentry (DECL_ASSEMBLER_NAME (decl));
-
-      /* We do initializations only if the SENTRY is zero, i.e., if we
-        are the first to initialize the variable.  We do destructions
-        only if the SENTRY is one, i.e., if we are the last to
-        destroy the variable.  */
-      if (initp)
-       sentry_cond = build_binary_op (EQ_EXPR,
-                                      build_unary_op (PREINCREMENT_EXPR,
-                                                      sentry,
-                                                      /*noconvert=*/1),
-                                      integer_one_node);
-      else
-       sentry_cond = build_binary_op (EQ_EXPR,
-                                      build_unary_op (PREDECREMENT_EXPR,
-                                                      sentry,
-                                                      /*noconvert=*/1),
-                                      integer_zero_node);
+      tree guard_cond;
 
-      cond = build_binary_op (TRUTH_ANDIF_EXPR, cond, sentry_cond);
+      guard = get_guard (decl);
+
+      /* When using __cxa_atexit, we just check the GUARD as we would
+        for a local static.  */
+      if (flag_use_cxa_atexit)
+       {
+         /* When using __cxa_atexit, we never try to destroy
+            anything from a static destructor.  */
+         my_friendly_assert (initp, 20000629);
+         guard_cond = get_guard_cond (guard);
+       }
+      /* If we don't have __cxa_atexit, then we will be running
+        destructors from .fini sections, or their equivalents.  So,
+        we need to know how many times we've tried to initialize this
+        object.  We do initializations only if the GUARD is zero,
+        i.e., if we are the first to initialize the variable.  We do
+        destructions only if the GUARD is one, i.e., if we are the
+        last to destroy the variable.  */
+      else if (initp)
+       guard_cond 
+         = cp_build_binary_op (EQ_EXPR,
+                               build_unary_op (PREINCREMENT_EXPR,
+                                               guard,
+                                               /*noconvert=*/1),
+                               integer_one_node);
+      else
+       guard_cond 
+         = cp_build_binary_op (EQ_EXPR,
+                               build_unary_op (PREDECREMENT_EXPR,
+                                               guard,
+                                               /*noconvert=*/1),
+                               integer_zero_node);
+
+      cond = cp_build_binary_op (TRUTH_ANDIF_EXPR, cond, guard_cond);
     }
 
-  finish_if_stmt_cond (cond, sentry_if_stmt);
+  finish_if_stmt_cond (cond, guard_if_stmt);
+
+  /* If we're using __cxa_atexit, we have not already set the GUARD,
+     so we must do so now.  */
+  if (guard && initp && flag_use_cxa_atexit)
+    finish_expr_stmt (set_guard (guard));
 
-  return sentry_if_stmt;
+  return guard_if_stmt;
 }
 
 /* We've just finished generating code to do an initialization or
-   finalization.  SENTRY_IF_STMT is the if-statement we used to guard
+   finalization.  GUARD_IF_STMT is the if-statement we used to guard
    the initialization.  */
 
 static void
-finish_static_initialization_or_destruction (sentry_if_stmt)
-     tree sentry_if_stmt;
+finish_static_initialization_or_destruction (guard_if_stmt)
+     tree guard_if_stmt;
 {
-  finish_then_clause (sentry_if_stmt);
+  finish_then_clause (guard_if_stmt);
   finish_if_stmt ();
 
   /* Now that we're done with DECL we don't need to pretend to be a
      member of its class any longer.  */
-  DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE;
+  DECL_CONTEXT (current_function_decl) = NULL_TREE;
   DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
 }
 
 /* Generate code to do the static initialization of DECL.  The
    initialization is INIT.  If DECL may be initialized more than once
-   in different object files, SENTRY is the guard variable to 
+   in different object files, GUARD is the guard variable to 
    check.  PRIORITY is the priority for the initialization.  */
 
 static void
@@ -3181,10 +3265,10 @@ do_static_initialization (decl, init)
      tree init;
 {
   tree expr;
-  tree sentry_if_stmt;
+  tree guard_if_stmt;
 
   /* Set up for the initialization.  */
-  sentry_if_stmt
+  guard_if_stmt
     = start_static_initialization_or_destruction (decl,
                                                  /*initp=*/1);
   
@@ -3192,10 +3276,6 @@ do_static_initialization (decl, init)
   if (IS_AGGR_TYPE (TREE_TYPE (decl))
       || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
     expr = build_aggr_init (decl, init, 0);
-  else if (TREE_CODE (init) == TREE_VEC)
-    expr = build_vec_init (decl, TREE_VEC_ELT (init, 0),
-                          TREE_VEC_ELT (init, 1),
-                          TREE_VEC_ELT (init, 2), 0);
   else
     {
       expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
@@ -3203,12 +3283,17 @@ do_static_initialization (decl, init)
     }
   finish_expr_stmt (expr);
 
+  /* If we're using __cxa_atexit, register a a function that calls the
+     destructor for the object.  */
+  if (flag_use_cxa_atexit)
+    register_dtor_fn (decl);
+
   /* Finsh up.  */
-  finish_static_initialization_or_destruction (sentry_if_stmt);
+  finish_static_initialization_or_destruction (guard_if_stmt);
 }
 
 /* Generate code to do the static destruction of DECL.  If DECL may be
-   initialized more than once in different object files, SENTRY is the
+   initialized more than once in different object files, GUARD is the
    guard variable to check.  PRIORITY is the priority for the
    destruction.  */
 
@@ -3216,17 +3301,21 @@ static void
 do_static_destruction (decl)
      tree decl;
 {
-  tree sentry_if_stmt;
+  tree guard_if_stmt;
+
+  /* If we're using __cxa_atexit, then destructors are registered
+     immediately after objects are initialized.  */
+  my_friendly_assert (!flag_use_cxa_atexit, 20000121);
 
   /* If we don't need a destructor, there's nothing to do.  */
-  if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
+  if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
     return;
-    
+
   /* Actually do the destruction.  */
-  sentry_if_stmt = start_static_initialization_or_destruction (decl,
+  guard_if_stmt = start_static_initialization_or_destruction (decl,
                                                               /*initp=*/0);
   finish_expr_stmt (build_cleanup (decl));
-  finish_static_initialization_or_destruction (sentry_if_stmt);
+  finish_static_initialization_or_destruction (guard_if_stmt);
 }
 
 /* VARS is a list of variables with static storage duration which may
@@ -3317,7 +3406,7 @@ generate_ctor_or_dtor_function (constructor_p, priority)
 
   /* Call the static storage duration function with appropriate
      arguments.  */
-  for (i = 0; i < ssdf_decls_used; ++i) 
+  for (i = 0; i < ssdf_decls->elements_used; ++i) 
     {
       arguments = tree_cons (NULL_TREE, build_int_2 (priority, 0), 
                             NULL_TREE);
@@ -3378,8 +3467,6 @@ generate_ctor_and_dtor_functions_for_priority (n, data)
 void
 finish_file ()
 {
-  extern int lineno;
-  int start_time, this_time;
   tree vars;
   int reconsider;
   size_t i;
@@ -3390,8 +3477,6 @@ finish_file ()
   if (! global_bindings_p () || current_class_type || decl_namespace_list)
     return;
 
-  start_time = get_run_time ();
-
   /* Otherwise, GDB can get confused, because in only knows
      about source for LINENO-1 lines.  */
   lineno -= 1;
@@ -3415,11 +3500,10 @@ finish_file ()
      generating the intiailzer for an object may cause templates to be
      instantiated, etc., etc.  */
 
-  this_time = get_run_time ();
-  parse_time -= this_time - start_time;
-  varconst_time += this_time - start_time;
-  start_time = get_run_time ();
+  timevar_push (TV_VARCONST);
 
+  emit_support_tinfos ();
+  
   do 
     {
       reconsider = 0;
@@ -3436,6 +3520,11 @@ finish_file ()
                        /*data=*/0))
        reconsider = 1;
       
+      /* Write out needed type info variables. Writing out one variable
+         might cause others to be needed.  */
+      if (walk_globals (tinfo_decl_p, emit_tinfo_decl, /*data=*/0))
+       reconsider = 1;
+
       /* The list of objects with static storage duration is built up
         in reverse order.  We clear STATIC_AGGREGATES so that any new
         aggregates added during the initialization of these will be
@@ -3467,10 +3556,18 @@ finish_file ()
 
          /* Then, generate code to do all the destructions.  Do these
             in reverse order so that the most recently constructed
-            variable is the first destroyed.  */
-         vars = nreverse (vars);
-         for (v = vars; v; v = TREE_CHAIN (v))
-           do_static_destruction (TREE_VALUE (v));
+            variable is the first destroyed.  If we're using
+            __cxa_atexit, then we don't need to do this; functions
+            were registered at initialization time to destroy the
+            local statics.  */
+         if (!flag_use_cxa_atexit)
+           {
+             vars = nreverse (vars);
+             for (v = vars; v; v = TREE_CHAIN (v))
+               do_static_destruction (TREE_VALUE (v));
+           }
+         else
+           vars = NULL_TREE;
 
          /* Finish up the static storage duration function for this
             round.  */
@@ -3484,9 +3581,9 @@ finish_file ()
       
       /* Go through the various inline functions, and see if any need
         synthesizing.  */
-      for (i = 0; i < saved_inlines_used; ++i)
+      for (i = 0; i < deferred_fns_used; ++i)
        {
-         tree decl = VARRAY_TREE (saved_inlines, i);
+         tree decl = VARRAY_TREE (deferred_fns, i);
          import_export_decl (decl);
          if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
              && TREE_USED (decl)
@@ -3498,37 +3595,60 @@ finish_file ()
                 finish_function doesn't clean things up, and we end
                 up with CURRENT_FUNCTION_DECL set.  */
              push_to_top_level ();
-             if (DECL_TINFO_FN_P (decl))
-               synthesize_tinfo_fn (decl);
-             else
-               synthesize_method (decl);
+             synthesize_method (decl);
              pop_from_top_level ();
              reconsider = 1;
            }
        }
 
-      /* Mark all functions that might deal with exception-handling as
-        referenced.  */
-      mark_all_runtime_matches ();
-
       /* We lie to the back-end, pretending that some functions are
         not defined when they really are.  This keeps these functions
-        from being put out unncessarily.  But, we must stop lying
+        from being put out unnecessarily.  But, we must stop lying
         when the functions are referenced, or if they are not comdat
         since they need to be put out now.  */
-      for (i = 0; i < saved_inlines_used; ++i)
+      for (i = 0; i < deferred_fns_used; ++i)
        {
-         tree decl = VARRAY_TREE (saved_inlines, i);
+         tree decl = VARRAY_TREE (deferred_fns, i);
       
          if (DECL_NOT_REALLY_EXTERN (decl)
              && DECL_INITIAL (decl)
-             && (DECL_NEEDED_P (decl) || !DECL_COMDAT (decl)))
+             && DECL_NEEDED_P (decl))
            DECL_EXTERNAL (decl) = 0;
+
+         /* If we're going to need to write this function out, and
+            there's already a body for it, create RTL for it now.
+            (There might be no body if this is a method we haven't
+            gotten around to synthesizing yet.)  */
+         if (!DECL_EXTERNAL (decl)
+             && DECL_NEEDED_P (decl)
+             && DECL_SAVED_TREE (decl)
+             && !DECL_SAVED_INSNS (decl)
+             && !TREE_ASM_WRITTEN (decl))
+           {
+             int saved_not_really_extern;
+
+             /* When we call finish_function in expand_body, it will
+                try to reset DECL_NOT_REALLY_EXTERN so we save and
+                restore it here.  */
+             saved_not_really_extern = DECL_NOT_REALLY_EXTERN (decl);
+             /* Generate RTL for this function now that we know we
+                need it.  */
+             expand_body (decl);
+             /* Undo the damage done by finish_function.  */
+             DECL_EXTERNAL (decl) = 0;
+             DECL_NOT_REALLY_EXTERN (decl) = saved_not_really_extern;
+             /* If we're compiling -fsyntax-only pretend that this
+                function has been written out so that we don't try to
+                expand it again.  */
+             if (flag_syntax_only)
+               TREE_ASM_WRITTEN (decl) = 1;
+             reconsider = 1;
+           }
        }
 
-      if (saved_inlines_used
-         && wrapup_global_declarations (&VARRAY_TREE (saved_inlines, 0),
-                                        saved_inlines_used))
+      if (deferred_fns_used
+         && wrapup_global_declarations (&VARRAY_TREE (deferred_fns, 0),
+                                        deferred_fns_used))
        reconsider = 1;
       if (walk_namespaces (wrapup_globals_for_namespace, /*data=*/0))
        reconsider = 1;
@@ -3586,17 +3706,23 @@ finish_file ()
 
   /* The entire file is now complete.  If requested, dump everything
      to a file.   */
-  if (flag_dump_translation_unit)
-    dump_node_to_file (global_namespace, flag_dump_translation_unit);
+  {
+    int flags;
+    FILE *stream = dump_begin (TDI_all, &flags);
 
+    if (stream)
+      {
+       dump_node (global_namespace, flags & ~TDF_SLIM, stream);
+       dump_end (TDI_all, stream);
+      }
+  }
+  
   /* If there's some tool that wants to examine the entire translation
      unit, let it do so now.  */
   if (back_end_hook)
     (*back_end_hook) (global_namespace);
 
-  this_time = get_run_time ();
-  parse_time -= this_time - start_time;
-  varconst_time += this_time - start_time;
+  timevar_pop (TV_VARCONST);
 
   if (flag_detailed_statistics)
     {
@@ -3656,7 +3782,7 @@ reparse_absdcl_as_casts (decl, expr)
       decl = TREE_OPERAND (decl, 0);
 
       expr = digest_init (type, expr, (tree *) 0);
-      if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0)
+      if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
        {
          int failure = complete_array_type (type, expr, 1);
          if (failure)
@@ -3791,8 +3917,8 @@ build_expr_from_tree (t)
     case ARRAY_REF:
       if (TREE_OPERAND (t, 0) == NULL_TREE)
        /* new-type-id */
-       return build_parse_node (ARRAY_REF, NULL_TREE,
-                                build_expr_from_tree (TREE_OPERAND (t, 1)));
+       return build_nt (ARRAY_REF, NULL_TREE,
+                        build_expr_from_tree (TREE_OPERAND (t, 1)));
       return grok_array_decl (build_expr_from_tree (TREE_OPERAND (t, 0)),
                              build_expr_from_tree (TREE_OPERAND (t, 1)));
 
@@ -3800,7 +3926,7 @@ build_expr_from_tree (t)
     case ALIGNOF_EXPR:
       {
        tree r = build_expr_from_tree (TREE_OPERAND (t, 0));
-       if (TREE_CODE_CLASS (TREE_CODE (r)) != 't')
+       if (!TYPE_P (r))
          r = TREE_TYPE (r);
        return TREE_CODE (t) == SIZEOF_EXPR ? c_sizeof (r) : c_alignof (r);
       }
@@ -3839,10 +3965,17 @@ build_expr_from_tree (t)
       if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
        {
          tree ref = TREE_OPERAND (t, 0);
+         tree name = TREE_OPERAND (ref, 1);
+         
+         if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+           name = build_nt (TEMPLATE_ID_EXPR,
+                            TREE_OPERAND (name, 0),
+                            build_expr_from_tree (TREE_OPERAND (name, 1)));
+           
          return build_scoped_method_call
            (build_expr_from_tree (TREE_OPERAND (t, 1)),
             build_expr_from_tree (TREE_OPERAND (ref, 0)),
-            TREE_OPERAND (ref, 1),
+            name,
             build_expr_from_tree (TREE_OPERAND (t, 2)));
        }
       else 
@@ -3874,9 +4007,16 @@ build_expr_from_tree (t)
       if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
        {
          tree ref = TREE_OPERAND (t, 0);
+         tree name = TREE_OPERAND (ref, 1);
+         
+         if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+           name = build_nt (TEMPLATE_ID_EXPR,
+                            TREE_OPERAND (name, 0),
+                            build_expr_from_tree (TREE_OPERAND (name, 1)));
+           
          return build_member_call
            (build_expr_from_tree (TREE_OPERAND (ref, 0)),
-            TREE_OPERAND (ref, 1),
+            name,
             build_expr_from_tree (TREE_OPERAND (t, 1)));
        }
       else
@@ -3968,9 +4108,9 @@ build_expr_from_tree (t)
       }
 
     case TYPEID_EXPR:
-      if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 0))) == 't')
+      if (TYPE_P (TREE_OPERAND (t, 0)))
        return get_typeid (TREE_OPERAND (t, 0));
-      return build_x_typeid (build_expr_from_tree (TREE_OPERAND (t, 0)));
+      return build_typeid (build_expr_from_tree (TREE_OPERAND (t, 0)));
 
     case VAR_DECL:
       return convert_from_reference (t);
@@ -3997,7 +4137,7 @@ reparse_decl_as_expr (type, decl)
 {
   decl = build_expr_from_tree (decl);
   if (type)
-    return build_functional_cast (type, build_expr_list (NULL_TREE, decl));
+    return build_functional_cast (type, build_tree_list (NULL_TREE, decl));
   else
     return decl;
 }
@@ -4010,8 +4150,6 @@ tree
 finish_decl_parsing (decl)
      tree decl;
 {
-  extern int current_class_depth;
-  
   switch (TREE_CODE (decl))
     {
     case IDENTIFIER_NODE:
@@ -4036,45 +4174,14 @@ finish_decl_parsing (decl)
       /* For attribute handling.  */
       TREE_VALUE (decl) = finish_decl_parsing (TREE_VALUE (decl));
       return decl;
+    case TEMPLATE_ID_EXPR:
+      return decl;
     default:
       my_friendly_abort (5);
       return NULL_TREE;
     }
 }
 
-tree
-check_cp_case_value (value)
-     tree value;
-{
-  if (value == NULL_TREE)
-    return value;
-
-  /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
-  STRIP_TYPE_NOPS (value);
-
-  if (TREE_READONLY_DECL_P (value))
-    {
-      value = decl_constant_value (value);
-      STRIP_TYPE_NOPS (value);
-    }
-  value = fold (value);
-
-  if (TREE_CODE (value) != INTEGER_CST
-      && value != error_mark_node)
-    {
-      cp_error ("case label `%E' does not reduce to an integer constant",
-               value);
-      value = error_mark_node;
-    }
-  else
-    /* Promote char or short to int.  */
-    value = default_conversion (value);
-
-  constant_expression_warning (value);
-
-  return value;
-}
-
 /* Return 1 if root encloses child. */
 
 static int
@@ -4238,7 +4345,7 @@ ambiguous_decl (name, old, new, flags)
                }
               cp_error_at ("  also declared as `%#D' here", val);
             }
-         return error_mark_node;
+         BINDING_VALUE (old) = error_mark_node;
        }
     }
   /* ... and copy the type. */
@@ -4286,7 +4393,7 @@ lookup_using_namespace (name, val, usings, scope, flags, spacesp)
        /* Resolve ambiguities. */
        val = ambiguous_decl (name, val, val1, flags);
       }
-  return val != error_mark_node;
+  return BINDING_VALUE (val) != error_mark_node;
 }
 
 /* [namespace.qual]
@@ -4306,9 +4413,11 @@ qualified_lookup_using_namespace (name, scope, result, flags)
   /* ... and a list of namespace yet to see. */
   tree todo = NULL_TREE;
   tree usings;
+  /* Look through namespace aliases.  */
+  scope = ORIGINAL_NAMESPACE (scope);
   while (scope && (result != error_mark_node))
     {
-      seen = temp_tree_cons (scope, NULL_TREE, seen);
+      seen = tree_cons (scope, NULL_TREE, seen);
       result = ambiguous_decl (name, result,
                                binding_for_name (name, scope), flags);
       if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
@@ -4318,7 +4427,7 @@ qualified_lookup_using_namespace (name, scope, result, flags)
          /* If this was a real directive, and we have not seen it. */
          if (!TREE_INDIRECT_USING (usings)
              && !purpose_member (TREE_PURPOSE (usings), seen))
-           todo = temp_tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
+           todo = tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
       if (todo)
        {
          scope = TREE_PURPOSE (todo);
@@ -4342,7 +4451,7 @@ set_decl_namespace (decl, scope, friendp)
      int friendp;
 {
   tree old;
-  if (scope == std_node)
+  if (scope == fake_std_node)
     scope = global_namespace;
   /* Get rid of namespace aliases. */
   scope = ORIGINAL_NAMESPACE (scope);
@@ -4359,6 +4468,9 @@ set_decl_namespace (decl, scope, friendp)
       if (!old)
        /* No old declaration at all. */
        goto complain;
+      /* A template can be explicitly specialized in any namespace.  */
+      if (processing_explicit_instantiation)
+       return;
       if (!is_overloaded_fn (decl))
        /* Don't compare non-function decls with decls_match here,
           since it can't check for the correct constness at this
@@ -4390,14 +4502,16 @@ static tree
 decl_namespace (decl)
      tree decl;
 {
+  if (TYPE_P (decl))
+    decl = TYPE_STUB_DECL (decl);
   while (DECL_CONTEXT (decl))
     {
       decl = DECL_CONTEXT (decl);
       if (TREE_CODE (decl) == NAMESPACE_DECL)
        return decl;
-      if (TREE_CODE_CLASS (TREE_CODE (decl)) == 't')
+      if (TYPE_P (decl))
        decl = TYPE_STUB_DECL (decl);
-      my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 390);
+      my_friendly_assert (DECL_P (decl), 390);
     }
 
   return global_namespace;
@@ -4430,7 +4544,8 @@ push_decl_namespace (decl)
 {
   if (TREE_CODE (decl) != NAMESPACE_DECL)
     decl = decl_namespace (decl);
-  decl_namespace_list = tree_cons (decl, NULL_TREE, decl_namespace_list);
+  decl_namespace_list = tree_cons (ORIGINAL_NAMESPACE (decl),
+                                   NULL_TREE, decl_namespace_list);
 }
 
 void
@@ -4475,13 +4590,13 @@ struct arg_lookup
   tree functions;
 };
 
-static int arg_assoc         PROTO((struct arg_lookup*, tree));
-static int arg_assoc_args    PROTO((struct arg_lookup*, tree));
-static int arg_assoc_type    PROTO((struct arg_lookup*, tree));
-static int add_function      PROTO((struct arg_lookup *, tree));
-static int arg_assoc_namespace PROTO((struct arg_lookup *, tree));
-static int arg_assoc_class   PROTO((struct arg_lookup *, tree));
-static int arg_assoc_template_arg PROTO((struct arg_lookup*, tree));
+static int arg_assoc         PARAMS ((struct arg_lookup*, tree));
+static int arg_assoc_args    PARAMS ((struct arg_lookup*, tree));
+static int arg_assoc_type    PARAMS ((struct arg_lookup*, tree));
+static int add_function      PARAMS ((struct arg_lookup *, tree));
+static int arg_assoc_namespace PARAMS ((struct arg_lookup *, tree));
+static int arg_assoc_class   PARAMS ((struct arg_lookup *, tree));
+static int arg_assoc_template_arg PARAMS ((struct arg_lookup*, tree));
 
 /* Add a function to the lookup structure.
    Returns 1 on error.  */
@@ -4499,10 +4614,11 @@ add_function (k, fn)
      case.  */
 
   /* We must find only functions, or exactly one non-function. */
-  if (k->functions && is_overloaded_fn (k->functions)
-      && is_overloaded_fn (fn))
+  if (!k->functions) 
+    k->functions = fn;
+  else if (is_overloaded_fn (k->functions) && is_overloaded_fn (fn))
     k->functions = build_overload (fn, k->functions);
-  else if (k->functions)
+  else
     {
       tree f1 = OVL_CURRENT (k->functions);
       tree f2 = fn;
@@ -4515,8 +4631,7 @@ add_function (k, fn)
       cp_error ("  in call to `%D'", k->name);
       return 1;
     }
-  else
-    k->functions = fn;
+
   return 0;
 }
 
@@ -4565,7 +4680,9 @@ arg_assoc_template_arg (k, arg)
      contribute to the set of associated namespaces.  ]  */
 
   /* Consider first template template arguments.  */
-  if (TREE_CODE (arg) == TEMPLATE_DECL)
+  if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+    return 0;
+  else if (TREE_CODE (arg) == TEMPLATE_DECL)
     {
       tree ctx = CP_DECL_CONTEXT (arg);
 
@@ -4578,7 +4695,7 @@ arg_assoc_template_arg (k, arg)
     }
   /* It's not a template template argument, but it is a type template
      argument.  */
-  else if (TREE_CODE_CLASS (TREE_CODE (arg)) == 't')
+  else if (TYPE_P (arg))
     return arg_assoc_type (k, arg);
   /* It's a non-type template argument.  */
   else
@@ -4622,15 +4739,15 @@ arg_assoc_class (k, type)
           friends = TREE_CHAIN (friends))
        /* Only interested in global functions with potentially hidden
            (i.e. unqualified) declarations. */
-       if (TREE_PURPOSE (list) == error_mark_node && TREE_VALUE (list)
-           && decl_namespace (TREE_VALUE (list)) == context)
-         if (add_function (k, TREE_VALUE (list)))
+       if (TREE_PURPOSE (friends) == error_mark_node && TREE_VALUE (friends)
+           && decl_namespace (TREE_VALUE (friends)) == context)
+         if (add_function (k, TREE_VALUE (friends)))
            return 1;
 
   /* Process template arguments.  */
   if (CLASSTYPE_TEMPLATE_INFO (type))
     {
-      list = innermost_args (CLASSTYPE_TI_ARGS (type));
+      list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
       for (i = 0; i < TREE_VEC_LENGTH (list); ++i) 
         arg_assoc_template_arg (k, TREE_VEC_ELT (list, i));
     }
@@ -4652,6 +4769,7 @@ arg_assoc_type (k, type)
     case INTEGER_TYPE:
     case REAL_TYPE:
     case COMPLEX_TYPE:
+    case VECTOR_TYPE:
     case CHAR_TYPE:
     case BOOLEAN_TYPE:
       return 0;
@@ -4681,7 +4799,9 @@ arg_assoc_type (k, type)
       /* Associate the return type. */
       return arg_assoc_type (k, TREE_TYPE (type));
     case TEMPLATE_TYPE_PARM:
-    case TEMPLATE_TEMPLATE_PARM:
+    case BOUND_TEMPLATE_TEMPLATE_PARM:
+      return 0;
+    case TYPENAME_TYPE:
       return 0;
     case LANG_TYPE:
       if (type == unknown_type_node)
@@ -4716,7 +4836,7 @@ arg_assoc (k, n)
   if (n == error_mark_node)
     return 0;
 
-  if (TREE_CODE_CLASS (TREE_CODE (n)) == 't')
+  if (TYPE_P (n))
     return arg_assoc_type (k, n);
 
   if (! type_unknown_p (n))
@@ -4745,6 +4865,9 @@ arg_assoc (k, n)
       tree ctx;
       tree arg;
 
+      if (TREE_CODE (template) == COMPONENT_REF)
+        template = TREE_OPERAND (template, 1);
+      
       /* First, the template.  There may actually be more than one if
         this is an overloaded function template.  But, in that case,
         we only need the first; all the functions will be in the same
@@ -4789,6 +4912,7 @@ lookup_arg_dependent (name, fns, args)
      tree args;
 {
   struct arg_lookup k;
+  tree fn = NULL_TREE;
 
   k.name = name;
   k.functions = fns;
@@ -4796,7 +4920,9 @@ lookup_arg_dependent (name, fns, args)
 
   /* Note that we've already looked at some namespaces during normal
      unqualified lookup, unless we found a decl in function scope.  */
-  if (fns && DECL_LOCAL_FUNCTION_P (OVL_CURRENT (fns)))
+  if (fns)
+    fn = OVL_CURRENT (fns);
+  if (fn && TREE_CODE (fn) == FUNCTION_DECL && DECL_LOCAL_FUNCTION_P (fn))
     k.namespaces = NULL_TREE;
   else
     unqualified_namespace_lookup (name, 0, &k.namespaces);
@@ -4836,18 +4962,8 @@ validate_nonmember_using_decl (decl, scope, name)
      tree *name;
 {
   if (TREE_CODE (decl) == SCOPE_REF
-      && TREE_OPERAND (decl, 0) == std_node)
+      && TREE_OPERAND (decl, 0) == fake_std_node)
     {
-      if (namespace_bindings_p ()
-         && current_namespace == global_namespace)
-       /* There's no need for a using declaration at all, here,
-          since `std' is the same as `::'.  We can't just pass this
-          on because we'll complain later about declaring something
-          in the same scope as a using declaration with the same
-          name.  We return NULL_TREE which indicates to the caller
-          that there's no need to do any further processing.  */
-       return NULL_TREE;
-
       *scope = global_namespace;
       *name = TREE_OPERAND (decl, 1);
     }
@@ -4860,7 +4976,8 @@ validate_nonmember_using_decl (decl, scope, name)
 
         A using-declaration for a class member shall be a
         member-declaration.  */
-      if (TREE_CODE (*scope) != NAMESPACE_DECL)
+      if (!processing_template_decl
+          && TREE_CODE (*scope) != NAMESPACE_DECL)
        {
          if (TYPE_P (*scope))
            cp_error ("`%T' is not a namespace", *scope);
@@ -4878,7 +4995,7 @@ validate_nonmember_using_decl (decl, scope, name)
     }
   else
     my_friendly_abort (382);
-  if (TREE_CODE_CLASS (TREE_CODE (*name)) == 'd')
+  if (DECL_P (*name))
     *name = DECL_NAME (*name);
   /* Make a USING_DECL. */
   return push_using_decl (*scope, *name);
@@ -4932,20 +5049,21 @@ do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
            {
              tree old_fn = OVL_CURRENT (tmp1);
 
-             if (!OVL_USED (tmp1)
-                 && compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
-                               TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
+              if (new_fn == old_fn)
+                /* The function already exists in the current namespace.  */
+                break;
+             else if (OVL_USED (tmp1))
+               continue; /* this is a using decl */
+             else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
+                                 TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
                {
-                 /* There was already a non-using declaration in
-                    this scope with the same parameter types.  */
-                 cp_error ("`%D' is already declared in this scope",
-                           name);
+                 /* There was already a non-using declaration in
+                    this scope with the same parameter types. If both
+                    are the same extern "C" functions, that's ok.  */
+                  if (!decls_match (new_fn, old_fn))
+                   cp_error ("`%D' is already declared in this scope", name);
                  break;
                }
-             else if (duplicate_decls (new_fn, old_fn))
-               /* We're re-using something we already used 
-                  before.  We don't need to add it again.  */ 
-               break;
            }
 
          /* If we broke out of the loop, there's no reason to add
@@ -5017,6 +5135,10 @@ do_local_using_decl (decl)
   if (decl == NULL_TREE)
     return;
 
+  if (building_stmt_tree ()
+      && at_function_scope_p ())
+    add_decl_stmt (decl);
+
   oldval = lookup_name_current_level (name);
   oldtype = lookup_type_current_level (name);
 
@@ -5055,7 +5177,7 @@ do_class_using_decl (decl)
   tree name, value;
 
   if (TREE_CODE (decl) != SCOPE_REF
-      || TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (decl, 0))) != 't')
+      || !TYPE_P (TREE_OPERAND (decl, 0)))
     {
       cp_error ("using-declaration for non-member at class scope");
       return NULL_TREE;
@@ -5082,20 +5204,25 @@ void
 do_using_directive (namespace)
      tree namespace;
 {
-  if (namespace == std_node)
+  if (namespace == fake_std_node)
     return;
+  if (building_stmt_tree ())
+    add_stmt (build_stmt (USING_STMT, namespace));
+  
   /* using namespace A::B::C; */
   if (TREE_CODE (namespace) == SCOPE_REF)
       namespace = TREE_OPERAND (namespace, 1);
   if (TREE_CODE (namespace) == IDENTIFIER_NODE)
     {
       /* Lookup in lexer did not find a namespace. */
-      cp_error ("namespace `%T' undeclared", namespace);
+      if (!processing_template_decl)
+       cp_error ("namespace `%T' undeclared", namespace);
       return;
     }
   if (TREE_CODE (namespace) != NAMESPACE_DECL)
     {
-      cp_error ("`%T' is not a namespace", namespace);
+      if (!processing_template_decl)
+       cp_error ("`%T' is not a namespace", namespace);
       return;
     }
   namespace = ORIGINAL_NAMESPACE (namespace);
@@ -5135,20 +5262,28 @@ mark_used (decl)
   assemble_external (decl);
 
   /* Is it a synthesized method that needs to be synthesized?  */
-  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CLASS_CONTEXT (decl)
-      && DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
+      && DECL_ARTIFICIAL (decl) 
+      && ! DECL_INITIAL (decl)
       /* Kludge: don't synthesize for default args.  */
       && current_function_decl)
-    synthesize_method (decl);
+    {
+      synthesize_method (decl);
+      /* If we've already synthesized the method we don't need to
+        instantiate it, so we can return right away.  */
+      return;
+    }
 
   /* If this is a function or variable that is an instance of some
      template, we now know that we will need to actually do the
      instantiation. We check that DECL is not an explicit
      instantiation because that is not checked in instantiate_decl.  */
-  if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
+  if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
       && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
-      && !DECL_EXPLICIT_INSTANTIATION (decl))
-    instantiate_decl (decl);
+      && (!DECL_EXPLICIT_INSTANTIATION (decl)
+         || (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))))
+    instantiate_decl (decl, /*defer_ok=*/1);
 }
 
 /* Helper function for named_class_head_sans_basetype nonterminal.  We
@@ -5159,23 +5294,36 @@ tree
 handle_class_head (aggr, scope, id)
      tree aggr, scope, id;
 {
-  tree decl;
+  tree decl = NULL_TREE;
 
   if (TREE_CODE (id) == TYPE_DECL)
-    decl = id;
+    /* We must bash typedefs back to the main decl of the type. Otherwise
+       we become confused about scopes.  */
+    decl = TYPE_MAIN_DECL (TREE_TYPE (id));
   else if (DECL_CLASS_TEMPLATE_P (id))
     decl = DECL_TEMPLATE_RESULT (id);
   else 
     {
-      tree current = current_scope();
+      tree current = current_scope ();
   
       if (current == NULL_TREE)
         current = current_namespace;
-      if (scope == std_node)
+      if (scope == fake_std_node)
         scope = global_namespace;
       if (scope == NULL_TREE)
         scope = global_namespace;
-      if (scope == current)
+
+      if (TYPE_P (scope))
+       {
+         /* According to the suggested resolution of core issue 180,
+            'typename' is assumed after a class-key.  */
+         decl = make_typename_type (scope, id, 1);
+         if (decl != error_mark_node)
+           decl = TYPE_MAIN_DECL (decl);
+         else
+           decl = NULL_TREE;
+       }
+      else if (scope == current)
         {
           /* We've been given AGGR SCOPE::ID, when we're already inside SCOPE.
              Be nice about it.  */
@@ -5189,7 +5337,8 @@ handle_class_head (aggr, scope, id)
        cp_error ("no file-scope type named `%D'", id);
       
       /* Inject it at the current scope.  */
-      decl = TYPE_MAIN_DECL (xref_tag (aggr, id, 1));
+      if (! decl)
+       decl = TYPE_MAIN_DECL (xref_tag (aggr, id, 1));
     }
  
   /* Enter the SCOPE.  If this turns out not to be a definition, the
@@ -5212,12 +5361,10 @@ handle_class_head (aggr, scope, id)
 void
 init_decl2 ()
 {
-  ggc_add_tree_root (&decl_namespace_list, 1);
-  ggc_add_tree_varray_root (&saved_inlines, 1);
+  ggc_add_tree_varray_root (&deferred_fns, 1);
   ggc_add_tree_varray_root (&pending_statics, 1);
   ggc_add_tree_varray_root (&ssdf_decls, 1);
   ggc_add_tree_root (&ssdf_decl, 1);
   ggc_add_tree_root (&priority_decl, 1);
   ggc_add_tree_root (&initialize_p_decl, 1);
-  ggc_add_tree_root (&pending_vtables, 1);
 }