OSDN Git Service

In include:
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl2.c
index 07f2d54..417348c 100644 (file)
@@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA.  */
 #include "dwarf2out.h"
 #include "dwarfout.h"
 #include "ggc.h"
+#include "timevar.h"
 
 #if USE_CPPLIB
 #include "cpplib.h"
@@ -61,7 +62,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 *));
@@ -93,6 +93,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));
+static int compare_options PARAMS ((const PTR, const PTR));
+static tree get_guard_bits PARAMS ((tree));
 
 extern int current_class_depth;
 
@@ -245,7 +247,7 @@ 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;
+const char *flag_dump_translation_unit = 0;
 
 /* Nonzero means warn about deprecated conversion from string constant to
    `char *'.  */
@@ -358,13 +360,6 @@ 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;
@@ -469,9 +464,6 @@ int max_tinst_depth = 17;
    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;
@@ -502,6 +494,10 @@ int flag_enforce_eh_specs = 1;
 
 void (*back_end_hook) PARAMS ((tree));
 
+/* The variant of the C language being processed.  */
+
+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.
    ON_VALUE is the value to store in VARIABLE
@@ -551,7 +547,6 @@ lang_f_options[] =
   {"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},
@@ -559,6 +554,29 @@ lang_f_options[] =
   {"xref", &flag_gnu_xref, 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",
+  "enum-int-equiv",
+  "guiding-decls",
+  "nonnull-objects",
+  "this-is-variable",
+  "strict-prototype",
+};
+
+/* 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
@@ -574,7 +592,7 @@ lang_decode_option (argc, argv)
      char **argv;
 {
   int strings_processed;
-  char *p = argv[0];
+  const char *p = argv[0];
 #if USE_CPPLIB
   strings_processed = cpp_handle_option (&parse_in, argc, argv);
 #else
@@ -588,19 +606,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;
@@ -614,13 +650,6 @@ 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;
@@ -637,22 +666,21 @@ lang_decode_option (argc, argv)
          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))
+         = read_integral_parameter (option_value, p - 2, max_tinst_depth);
+      else if ((option_value
+                = skip_leading_substring (p, "name-mangling-version-")))
        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, name_mangling_version);
+      else if ((option_value
+                = skip_leading_substring (p, "dump-translation-unit-")))
        {
          if (p[22] == '\0')
            error ("no file specified with -fdump-translation-unit");
          else
-           flag_dump_translation_unit = p + 22;
+           flag_dump_translation_unit = option_value;
        }
       else 
        {
@@ -709,6 +737,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"))
@@ -762,7 +795,7 @@ 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;
@@ -789,7 +822,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
@@ -864,14 +897,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);
@@ -903,7 +936,7 @@ grok_x_components (specs)
     return;
 
   fixup_anonymous_aggr (t);
-  finish_member_declaration (build_lang_decl (FIELD_DECL, NULL_TREE, t)); 
+  finish_member_declaration (build_decl (FIELD_DECL, NULL_TREE, t)); 
 
   /* Ignore any inline function definitions in the anonymous union
      since an anonymous union may not have function members.  */
@@ -913,6 +946,22 @@ grok_x_components (specs)
       break;
 }
 
+/* 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;
+  DECL_ARG_TYPE (parm) = type;
+  return parm;
+}
+
 /* Constructors for types with virtual baseclasses need an "in-charge" flag
    saying whether this constructor is responsible for initialization of
    virtual baseclasses or not.  All destructors also need this "in-charge"
@@ -929,24 +978,23 @@ maybe_retrofit_in_chrg (fn)
 {
   tree basetype, arg_types, parms, parm, fntype;
 
-  if (DECL_CONSTRUCTOR_P (fn)
-      && TYPE_USES_VIRTUAL_BASECLASSES (DECL_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;
+
+  /* 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;
 
-  if (DECL_CONSTRUCTOR_P (fn))
-    DECL_CONSTRUCTOR_FOR_VBASE_P (fn) = 1;
+  /* 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;
+  parm = build_artificial_parm (in_charge_identifier, integer_type_node);
   TREE_READONLY (parm) = 1;
   parms = DECL_ARGUMENTS (fn);
   TREE_CHAIN (parm) = TREE_CHAIN (parms);
@@ -962,6 +1010,21 @@ maybe_retrofit_in_chrg (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;
+
+  /* If this is a subobject constructor or destructor, our caller will
+     pass us a pointer to our VTT.  */
+  if (flag_new_abi && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+    {
+      DECL_VTT_PARM (fn) = build_artificial_parm (vtt_parm_identifier, 
+                                                 vtt_parm_type);
+      DECL_CONTEXT (DECL_VTT_PARM (fn)) = fn;
+      DECL_USE_VTT_PARM (fn) = build_artificial_parm (NULL_TREE,
+                                                     boolean_type_node);
+      DECL_CONTEXT (DECL_USE_VTT_PARM (fn)) = fn;
+    }
 }
 
 /* Classes overload their constituent function names automatically.
@@ -993,6 +1056,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.  */
+  DECL_LANGUAGE (function) = lang_cplusplus;
+
   if (fn_name == NULL_TREE)
     {
       error ("name missing for member function");
@@ -1016,12 +1083,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;
@@ -1037,7 +1101,13 @@ grokclassfn (ctype, function, flags, quals)
 
   if (flags == DTOR_FLAG)
     {
-      DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype);
+      DECL_DESTRUCTOR_P (function) = 1;
+
+      if (flag_new_abi) 
+       set_mangled_name_for_decl (function);
+      else
+       DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype);
+
       TYPE_HAS_DESTRUCTOR (ctype) = 1;
     }
   else
@@ -1194,7 +1264,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");
     }
 
@@ -1211,8 +1281,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
@@ -1224,7 +1297,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))
@@ -1238,7 +1312,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);
     }
 }
@@ -1389,7 +1463,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)
@@ -1410,7 +1484,7 @@ check_classfn (ctype, function)
                     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))
+                 if (!DECL_DESTRUCTOR_P (function)
                      && (DECL_ASSEMBLER_NAME (function)
                          != DECL_NAME (function))
                      && (DECL_ASSEMBLER_NAME (fndecl)
@@ -1475,7 +1549,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;
 }
 
@@ -1498,6 +1572,8 @@ finish_static_data_member_decl (decl, init, asmspec_tree, flags)
 
   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
      the right thing, namely, to put this decl out straight away.  */
@@ -1505,8 +1581,11 @@ finish_static_data_member_decl (decl, init, asmspec_tree, flags)
   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 (flag_new_abi)
+       DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl);
+      else
+       DECL_ASSEMBLER_NAME (decl) 
+         = build_static_name (current_class_type, DECL_NAME (decl));
     }
   if (! processing_template_decl)
     {
@@ -1531,22 +1610,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
@@ -1572,7 +1648,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_p;
+
+      cp_error ("invalid data member initiailization");
+      if (!explained_p)
+       {
+         cp_error ("use `=' to initialize static data members");
+         explained_p = 1;
+       }
+
       declarator = TREE_OPERAND (declarator, 0);
       flags = 0;
     }
@@ -1618,12 +1710,20 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
       DECL_NONLOCAL (value) = 1;
       DECL_CONTEXT (value) = current_class_type;
 
+      if (CLASS_TYPE_P (TREE_TYPE (value)))
+        CLASSTYPE_GOT_SEMICOLON (TREE_TYPE (value)) = 1;
+      
       /* 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 (!uses_template_parms (value)) 
+       {
+         if (flag_new_abi)
+           DECL_ASSEMBLER_NAME (value) = mangle_type (TREE_TYPE (value));
+         else
+           DECL_ASSEMBLER_NAME (value) =
+             get_identifier (build_overload_name (TREE_TYPE (value), 1, 1));
+       }
 
       if (processing_template_decl)
        value = push_template_decl (value);
@@ -1809,7 +1909,10 @@ grokoptypename (declspecs, declarator)
      tree declspecs, declarator;
 {
   tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE);
-  return build_typename_overload (t);
+  if (flag_new_abi)
+    return mangle_conv_op_name_for_type (t);
+  else
+    return build_typename_overload (t);
 }
 
 /* When a function is declared with an initializer,
@@ -1893,14 +1996,14 @@ grok_function_init (decl, init)
       /* 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)))
+      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))));
@@ -1994,32 +2097,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
@@ -2096,12 +2191,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.  */
@@ -2144,7 +2244,7 @@ finish_anon_union (anon_union_decl)
 
   if (public_p)
     {
-      error ("global anonymous unions must be declared static");
+      error ("namespace-scope anonymous aggregates must be static");
       return;
     }
 
@@ -2154,7 +2254,7 @@ finish_anon_union (anon_union_decl)
 
   if (main_decl == NULL_TREE)
     {
-      warning ("anonymous union with no members");
+      warning ("anonymous aggregate with no members");
       return;
     }
 
@@ -2196,6 +2296,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);
@@ -2320,11 +2421,12 @@ mark_vtable_entries (decl)
 
       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, THUNK_GENERATE_WITH_VTABLE_P (fn));
       mark_used (fn);
     }
 }
@@ -2405,6 +2507,7 @@ key_method (type)
   tree method;
 
   if (TYPE_FOR_JAVA (type)
+      || CLASSTYPE_TEMPLATE_INSTANTIATION (type)
       || CLASSTYPE_INTERFACE_KNOWN (type))
     return NULL_TREE;
 
@@ -2511,8 +2614,7 @@ import_export_class (ctype)
   /* Base our import/export status on that of the first non-inline,
      non-pure virtual function, if any.  */
   if (import_export == 0
-      && TYPE_POLYMORPHIC_P (ctype)
-      && ! CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
+      && TYPE_POLYMORPHIC_P (ctype))
     {
       tree method = key_method (ctype);
       if (method)
@@ -2755,34 +2857,117 @@ 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;
+
+  /* For a local variable, under the old ABI, we do not try to get a
+     unique mangled name for the DECL.  */
+  if (!flag_new_abi && !DECL_NAMESPACE_SCOPE_P (decl))
     {
-      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);
+      guard = get_temp_name (integer_type_node);
+      cp_finish_decl (guard, NULL_TREE, NULL_TREE, 0);
+      return guard;
     }
-  return sentry;
+
+  if (!flag_new_abi)
+    /* For struct X foo __attribute__((weak)), there is a counter
+       __snfoo. Since base is already an assembler name, sname should
+       be globally unique */
+    sname = get_id_2 ("__sn", DECL_ASSEMBLER_NAME (decl));
+  else
+    sname = mangle_guard_variable (decl);
+
+  guard = IDENTIFIER_GLOBAL_VALUE (sname);
+  if (! guard)
+    {
+      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.  */
+      if (flag_new_abi)
+       guard_type = long_long_integer_type_node;
+      else
+       guard_type = integer_type_node;
+
+      guard = build_decl (VAR_DECL, sname, guard_type);
+      TREE_PUBLIC (guard) = 1;
+      DECL_ARTIFICIAL (guard) = 1;
+      TREE_STATIC (guard) = 1;
+      TREE_USED (guard) = 1;
+      DECL_COMMON (guard) = 1;
+      pushdecl_top_level (guard);
+      cp_finish_decl (guard, NULL_TREE, NULL_TREE, 0);
+    }
+  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;
+{
+  if (!flag_new_abi)
+    return 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
@@ -2859,8 +3044,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);
 
@@ -3087,9 +3272,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;
 
@@ -3133,61 +3319,80 @@ 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;
+
+      guard = get_guard (decl);
 
-      cond = build_binary_op (TRUTH_ANDIF_EXPR, cond, sentry_cond);
+      /* 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);
+       }
+      /* Under the old ABI, e 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);
+
+  /* Under the new ABI, we have not already set the GUARD, so we must
+     do so now.  */
+  if (guard && initp && flag_new_abi)
+    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
@@ -3198,7 +3403,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
@@ -3207,10 +3412,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,11 +3440,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.  */
 
@@ -3247,7 +3452,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.  */
@@ -3258,10 +3463,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
@@ -3413,8 +3618,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;
@@ -3425,8 +3628,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;
@@ -3450,10 +3651,7 @@ 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);
 
   if (new_abi_rtti_p ())
     emit_support_tinfos ();
@@ -3513,7 +3711,7 @@ finish_file ()
             in reverse order so that the most recently constructed
             variable is the first destroyed.  If we're using
             __cxa_atexit, then we don't need to do this; functions
-            we're registered at initialization time to destroy the
+            were registered at initialization time to destroy the
             local statics.  */
          if (!flag_use_cxa_atexit)
            {
@@ -3565,7 +3763,7 @@ finish_file ()
 
       /* 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 < deferred_fns_used; ++i)
@@ -3676,9 +3874,7 @@ finish_file ()
   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)
     {
@@ -3921,10 +4117,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 
@@ -3956,9 +4159,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
@@ -4118,6 +4328,8 @@ 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;
@@ -4133,12 +4345,8 @@ check_cp_case_value (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 = decl_constant_value (value);
+  STRIP_TYPE_NOPS (value);
   value = fold (value);
 
   if (TREE_CODE (value) != INTEGER_CST
@@ -4388,6 +4596,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);
@@ -4514,7 +4724,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
@@ -4583,10 +4794,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;
@@ -4599,8 +4811,7 @@ add_function (k, fn)
       cp_error ("  in call to `%D'", k->name);
       return 1;
     }
-  else
-    k->functions = fn;
+
   return 0;
 }
 
@@ -4714,7 +4925,7 @@ arg_assoc_class (k, type)
   /* 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));
     }
@@ -4767,6 +4978,8 @@ arg_assoc_type (k, type)
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
       return 0;
+    case TYPENAME_TYPE:
+      return 0;
     case LANG_TYPE:
       if (type == unknown_type_node)
        return 0;
@@ -4829,6 +5042,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
@@ -5228,13 +5444,18 @@ mark_used (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)
          || (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))))
@@ -5252,7 +5473,9 @@ handle_class_head (aggr, scope, id)
   tree decl;
 
   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