OSDN Git Service

* c-common.c (decl_attributes): Only take a single attributes
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl2.c
index 30bf232..e6d4274 100644 (file)
@@ -1,6 +1,6 @@
 /* Process declarations and variables for C compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000 Free Software Foundation, Inc.
+   1999, 2000, 2001 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GNU CC.
@@ -32,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 "ggc.h"
 #include "timevar.h"
-
-#if USE_CPPLIB
 #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.  */
@@ -62,7 +59,6 @@ typedef struct priority_info_s {
   int destructions_p;
 } *priority_info;
 
-static tree get_sentry PARAMS ((tree));
 static void mark_vtable_entries PARAMS ((tree));
 static void grok_function_init PARAMS ((tree, tree));
 static int finish_vtable_vardecl PARAMS ((tree *, void *));
@@ -94,11 +90,8 @@ 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));
-
-extern int current_class_depth;
-
-/* A list of virtual function tables we must make sure to write out.  */
-tree pending_vtables;
+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
@@ -127,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;
@@ -157,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.  */
 
@@ -223,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.  */
@@ -243,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 *'.  */
 
@@ -284,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.  */
 
@@ -303,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.  */
@@ -359,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.  */
 
@@ -396,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.  */
@@ -442,10 +384,6 @@ int flag_new_for_scope = 1;
 
 int flag_weak = 1;
 
-/* Nonzero to enable experimental ABI changes.  */
-
-int flag_new_abi;
-
 /* Nonzero to use __cxa_atexit, rather than atexit, to register
    destructors for local statics and global objects.  */
 
@@ -453,34 +391,20 @@ int flag_use_cxa_atexit;
 
 /* Nonzero to not ignore namespace std. */
 
-int flag_honor_std = ENABLE_STD_NAMESPACE;
+int flag_honor_std = 1;
 
-/* Nonzero if we should expand functions calls inline at the tree
-   level, rather than at the RTL level.  */
+/* 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.  */
 
 int flag_inline_trees = 0;
 
-/* Maximum template instantiation depth. Must be at least 17 for ISO
-   compliance. */
-
-int max_tinst_depth = 17;
-
-/* 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;
-
-/* Nonzero means that guiding declarations are allowed.  */
-int flag_guiding_decls;
-
-/* Nonzero if wchar_t should be `unsigned short' instead of whatever it
-   would normally be, for use with WINE.  */
-int flag_short_wchar;
+/* 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 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.  */
 
@@ -498,10 +422,9 @@ int flag_permissive;
 
 int flag_enforce_eh_specs = 1;
 
-/* If this variable is defined to a non-NULL value, it will be called
-   after the file has been completely parsed.  */
+/* The variant of the C language being processed.  */
 
-void (*back_end_hook) PARAMS ((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.
@@ -520,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},
 
@@ -538,11 +460,9 @@ lang_f_options[] =
   {"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},
@@ -550,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},
-  {"use-cxa-atexit", &flag_use_cxa_atexit, 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 */;
@@ -589,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;
@@ -615,46 +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_vtable_thunks = 1;
-       }
-      else if (!strcmp (p, "no-new-abi"))
-       {
-         flag_new_abi = 0;
-         flag_do_squangling = 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, "message-length=", 15))
-       set_message_length
-         (read_integral_parameter (p + 15, p - 2,
-                                   /* default line-wrap length */ 72));
-      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;
@@ -710,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"))
@@ -719,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"))
@@ -763,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;
@@ -790,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_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
@@ -865,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);
@@ -890,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; }; };'.  */
@@ -904,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
@@ -922,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)
@@ -934,26 +897,49 @@ maybe_retrofit_in_chrg (fn)
   if (DECL_HAS_IN_CHARGE_PARM_P (fn))
     return;
 
+  /* 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;
+
   /* 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;
 
-  /* 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;
-
-  /* ...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)))
@@ -994,6 +980,10 @@ grokclassfn (ctype, function, flags, quals)
   tree fn_name = DECL_NAME (function);
   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)
     {
       error ("name missing for member function");
@@ -1017,12 +1007,9 @@ grokclassfn (ctype, function, flags, quals)
         assigned to.  */
       this_quals |= TYPE_QUAL_CONST;
       qual_type = cp_build_qualified_type (type, this_quals);
-      parm = build_decl (PARM_DECL, this_identifier, qual_type);
+      parm = build_artificial_parm (this_identifier, qual_type);
       c_apply_type_quals_to_decl (this_quals, parm);
 
-      /* 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;
@@ -1033,17 +1020,17 @@ grokclassfn (ctype, function, flags, quals)
   DECL_ARGUMENTS (function) = last_function_parms;
   DECL_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);
 
   if (flags == DTOR_FLAG)
     {
       DECL_DESTRUCTOR_P (function) = 1;
-      DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype);
       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).  */
@@ -1196,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");
     }
 
@@ -1213,8 +1200,11 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
 
   /* 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
@@ -1226,7 +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, use_global_delete);
+    return build_vec_delete (t, maxindex, sfk_deleting_destructor,
+                            use_global_delete);
   else
     {
       if (IS_AGGR_TYPE (TREE_TYPE (type))
@@ -1240,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);
     }
 }
@@ -1295,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)
@@ -1404,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 (!DECL_DESTRUCTOR_P (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 
@@ -1477,7 +1452,7 @@ check_classfn (ctype, function)
      case we'll only confuse ourselves when the function is declared
      properly within the class.  */
   if (COMPLETE_TYPE_P (ctype))
-    add_method (ctype, methods, function);
+    add_method (ctype, function, /*error_p=*/1);
   return NULL_TREE;
 }
 
@@ -1493,23 +1468,17 @@ 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)
@@ -1520,12 +1489,15 @@ finish_static_data_member_decl (decl, init, asmspec_tree, flags)
   /* 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.  */
@@ -1533,22 +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;
 
   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
@@ -1582,13 +1551,13 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
            };
            
         Explain that to the user.  */
-      static int explained_p;
+      static int explained;
 
-      cp_error ("invalid data member initiailization");
-      if (!explained_p)
+      cp_error ("invalid data member initialization");
+      if (!explained)
        {
-         cp_error ("use `=' to initialize static data members");
-         explained_p = 1;
+         cp_error ("(use `=' to initialize static data members)");
+         explained = 1;
        }
 
       declarator = TREE_OPERAND (declarator, 0);
@@ -1636,13 +1605,9 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
       DECL_NONLOCAL (value) = 1;
       DECL_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);
 
@@ -1726,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;
@@ -1745,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);
 
@@ -1827,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,
@@ -1898,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 member function `%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 (!DECL_DESTRUCTOR_P (decl)))
-       {
-         /* Give this node rtl from `abort'.  */
-         DECL_RTL (decl) = DECL_RTL (abort_fndecl);
-       }
-#endif
       DECL_PURE_VIRTUAL_P (decl) = 1;
-      if (DECL_NAME (decl) == ansi_opname [(int) MODIFY_EXPR])
+      if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
        {
          tree parmtype
            = TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl))));
@@ -1941,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));
@@ -1958,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)))
@@ -2012,32 +1955,24 @@ defer_fn (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
@@ -2114,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.  */
@@ -2140,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)
@@ -2157,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;
     }
 
@@ -2172,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));
@@ -2214,6 +2154,7 @@ finish_builtin_type (type, name, fields, len, align_type)
     }
   DECL_FIELD_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);
@@ -2232,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;
 }
 
@@ -2256,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;
 }
@@ -2333,16 +2256,17 @@ mark_vtable_entries (decl)
 
       if (TREE_CODE (fnaddr) != ADDR_EXPR)
        /* This entry is an offset: a virtual base class offset, a
-          virtual call offset, and RTTI offset, etc.  */
+          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);
     }
 }
@@ -2356,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
     {
@@ -2399,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
@@ -2430,8 +2369,13 @@ key_method (type)
   for (method = TYPE_METHODS (type); method != NULL_TREE;
        method = TREE_CHAIN (method))
     if (DECL_VINDEX (method) != NULL_TREE
-       && ! DECL_THIS_INLINE (method)
-       && ! DECL_PURE_VIRTUAL_P (method))
+       && ! 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;
@@ -2460,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
@@ -2512,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.  */
@@ -2545,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);
     }
 }
@@ -2630,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);
@@ -2682,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 
@@ -2696,28 +2645,29 @@ import_export_decl (decl)
     }
   else if (DECL_FUNCTION_MEMBER_P (decl))
     {
-      tree ctype = DECL_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));
 
@@ -2739,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.  */
@@ -2773,33 +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;
 }
 
-static tree
-get_sentry (base)
-     tree base;
+/* Returns the initialization guard variable for the variable DECL,
+   which has static storage duration.  */
+
+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);
+  tree sname;
+  tree guard;
 
-  if (! sentry)
+  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
@@ -2876,8 +2894,8 @@ finish_objects (method_type, initp, body)
   const char *fnname;
   tree fn;
 
-  /* Finish up. */
-  finish_compound_stmt(/*has_no_scope=*/0, body);
+  /* Finish up.  */
+  finish_compound_stmt (/*has_no_scope=*/0, body);
   fn = finish_function (0);
   expand_body (fn);
 
@@ -2908,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
@@ -3104,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;
 
@@ -3150,61 +3169,83 @@ start_static_initialization_or_destruction (decl, initp)
   
   /* 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);
 
-  return sentry_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 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
@@ -3215,7 +3256,7 @@ finish_static_initialization_or_destruction (sentry_if_stmt)
 
 /* 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
@@ -3224,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);
   
@@ -3235,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);
@@ -3252,11 +3289,11 @@ do_static_initialization (decl, init)
     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.  */
 
@@ -3264,7 +3301,7 @@ 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.  */
@@ -3275,10 +3312,10 @@ do_static_destruction (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
@@ -3465,8 +3502,7 @@ finish_file ()
 
   timevar_push (TV_VARCONST);
 
-  if (new_abi_rtti_p ())
-    emit_support_tinfos ();
+  emit_support_tinfos ();
   
   do 
     {
@@ -3486,8 +3522,7 @@ finish_file ()
       
       /* Write out needed type info variables. Writing out one variable
          might cause others to be needed.  */
-      if (new_abi_rtti_p ()
-          && walk_globals (tinfo_decl_p, emit_tinfo_decl, /*data=*/0))
+      if (walk_globals (tinfo_decl_p, emit_tinfo_decl, /*data=*/0))
        reconsider = 1;
 
       /* The list of objects with static storage duration is built up
@@ -3560,19 +3595,12 @@ 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 unnecessarily.  But, we must stop lying
@@ -3678,9 +3706,17 @@ 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)
@@ -3881,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)));
 
@@ -3929,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 
@@ -3964,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
@@ -4100,8 +4150,6 @@ tree
 finish_decl_parsing (decl)
      tree decl;
 {
-  extern int current_class_depth;
-  
   switch (TREE_CODE (decl))
     {
     case IDENTIFIER_NODE:
@@ -4126,41 +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);
-  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
@@ -4392,6 +4413,8 @@ 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 = tree_cons (scope, NULL_TREE, seen);
@@ -4428,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);
@@ -4445,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
@@ -4518,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
@@ -4587,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;
@@ -4603,8 +4631,7 @@ add_function (k, fn)
       cp_error ("  in call to `%D'", k->name);
       return 1;
     }
-  else
-    k->functions = fn;
+
   return 0;
 }
 
@@ -4653,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);
 
@@ -4710,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));
     }
@@ -4740,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;
@@ -4769,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)
@@ -4833,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
@@ -4927,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);
     }
@@ -4951,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);
@@ -5023,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
@@ -5108,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);
 
@@ -5173,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);
@@ -5243,7 +5279,7 @@ mark_used (decl)
      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)
          || (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))))
@@ -5258,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.  */
@@ -5288,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
@@ -5311,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 (&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);
 }