OSDN Git Service

* emit-rtl.c (add_insn_before): Fix comment typo.
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index 8dee86a..d0d1ff3 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,
-   2001, 2002, 2003, 2004  Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004,2005  Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -63,12 +63,14 @@ static void push_local_name (tree);
 static tree grok_reference_init (tree, tree, tree, tree *);
 static tree grokfndecl (tree, tree, tree, tree, tree, int,
                        enum overload_flags, cp_cv_quals,
-                       tree, int, int, int, int, int, int, tree);
-static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *, 
+                       tree, int, int, int, int, int, int, tree, 
+                       tree *);
+static tree grokvardecl (tree, tree, const cp_decl_specifier_seq *,
                         int, int, tree);
 static void record_unknown_type (tree, const char *);
-static tree builtin_function_1 (const char *, tree, tree, int,
-                                enum built_in_class, const char *,
+static tree builtin_function_1 (const char *, tree, tree,
+                               enum built_in_function code,
+                                enum built_in_class cl, const char *,
                                tree);
 static tree build_library_fn_1 (tree, enum tree_code, tree);
 static int member_function_or_else (tree, tree, enum overload_flags);
@@ -79,7 +81,8 @@ static hashval_t typename_hash (const void *);
 static int typename_compare (const void *, const void *);
 static tree local_variable_p_walkfn (tree *, int *, void *);
 static tree record_builtin_java_type (const char *, int);
-static const char *tag_name (enum tag_types code);
+static const char *tag_name (enum tag_types);
+static tree lookup_and_check_tag (enum tag_types, tree, tag_scope, bool);
 static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
 static int walk_globals_r (tree, void*);
 static int walk_vtables_r (tree, void*);
@@ -99,7 +102,6 @@ static tree check_initializer (tree, tree, int, tree *);
 static void make_rtl_for_nonlocal_decl (tree, tree, const char *);
 static void save_function_data (tree);
 static void check_function_type (tree, tree);
-static void begin_constructor_body (void);
 static void finish_constructor_body (void);
 static void begin_destructor_body (void);
 static void finish_destructor_body (void);
@@ -110,7 +112,7 @@ static tree start_cleanup_fn (void);
 static void end_cleanup_fn (void);
 static tree cp_make_fname_decl (tree, int);
 static void initialize_predefined_identifiers (void);
-static tree check_special_function_return_type 
+static tree check_special_function_return_type
        (special_function_kind, tree, tree);
 static tree push_cp_library_fn (enum tree_code, tree);
 static tree build_cp_library_fn (tree, enum tree_code, tree);
@@ -119,7 +121,6 @@ static void initialize_local_var (tree, tree);
 static void expand_static_init (tree, tree);
 static tree next_initializable_field (tree);
 static tree reshape_init (tree, tree *);
-static tree build_typename_type (tree, tree, tree);
 
 /* Erroneous argument lists can use this *IFF* they do not modify it.  */
 tree error_mark_list;
@@ -234,7 +235,7 @@ int function_depth;
    with __attribute__((deprecated)).  An object declared as
    __attribute__((deprecated)) suppresses warnings of uses of other
    deprecated items.  */
-   
+
 enum deprecated_states {
   DEPRECATED_NORMAL,
   DEPRECATED_SUPPRESS
@@ -266,8 +267,8 @@ current_tmpl_spec_kind (int n_class_scopes)
   struct cp_binding_level *b;
 
   /* Scan through the template parameter scopes.  */
-  for (b = current_binding_level; 
-       b->kind == sk_template_parms; 
+  for (b = current_binding_level;
+       b->kind == sk_template_parms;
        b = b->level_chain)
     {
       /* If we see a specialization scope inside a parameter scope,
@@ -363,7 +364,7 @@ pop_label (tree label, tree old_value)
        {
          location_t location;
 
-         cp_error_at ("label `%D' used but not defined", label);
+         cp_error_at ("label %qD used but not defined", label);
 #ifdef USE_MAPPED_LOCATION
          location = input_location; /* FIXME want (input_filename, (line)0) */
 #else
@@ -374,7 +375,7 @@ pop_label (tree label, tree old_value)
          define_label (location, DECL_NAME (label));
        }
       else if (warn_unused_label && !TREE_USED (label))
-       cp_warning_at ("label `%D' defined but not used", label);
+       cp_warning_at ("label %qD defined but not used", label);
     }
 
   SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value);
@@ -403,6 +404,43 @@ pop_labels (tree block)
   named_labels = NULL;
 }
 
+/* The following two routines are used to interface to Objective-C++.
+   The binding level is purposely treated as an opaque type.  */
+
+void *
+objc_get_current_scope (void)
+{
+  return current_binding_level;
+}
+
+/* The following routine is used by the NeXT-style SJLJ exceptions;
+   variables get marked 'volatile' so as to not be clobbered by
+   _setjmp()/_longjmp() calls.  All variables in the current scope,
+   as well as parent scopes up to (but not including) ENCLOSING_BLK
+   shall be thusly marked.  */
+
+void
+objc_mark_locals_volatile (void *enclosing_blk)
+{
+  struct cp_binding_level *scope;
+
+  for (scope = current_binding_level;
+       scope && scope != enclosing_blk && scope->kind == sk_block;
+       scope = scope->level_chain)
+    {
+      tree decl;
+
+      for (decl = scope->names; decl; decl = TREE_CHAIN (decl))
+        {
+         if (TREE_CODE (decl) == VAR_DECL)
+           {
+              DECL_REGISTER (decl) = 0;
+              TREE_THIS_VOLATILE (decl) = 1;
+           }
+        }
+    }
+}
+
 /* Exit a binding level.
    Pop the level off, and restore the state of the identifier-decl mappings
    that were in effect when this level was entered.
@@ -438,20 +476,19 @@ poplevel (int keep, int reverse, int functionbody)
 
   block = NULL_TREE;
 
-  my_friendly_assert (current_binding_level->kind != sk_class, 19990916);
+  gcc_assert (current_binding_level->kind != sk_class);
 
   real_functionbody = (current_binding_level->kind == sk_cleanup
                       ? ((functionbody = 0), tmp) : functionbody);
   subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
 
-  my_friendly_assert (VEC_length(cp_class_binding, 
-                                current_binding_level->class_shadowed) == 0,
-                     19990414);
+  gcc_assert (!VEC_length(cp_class_binding,
+                         current_binding_level->class_shadowed));
 
   /* We used to use KEEP == 2 to indicate that the new block should go
      at the beginning of the list of blocks at this binding level,
      rather than the end.  This hack is no longer used.  */
-  my_friendly_assert (keep == 0 || keep == 1, 0);
+  gcc_assert (keep == 0 || keep == 1);
 
   if (current_binding_level->keep)
     keep = 1;
@@ -502,14 +539,6 @@ poplevel (int keep, int reverse, int functionbody)
   else
     decls = current_binding_level->names;
 
-  /* When not in function-at-a-time mode, expand_end_bindings will
-     warn about unused variables.  But, in function-at-a-time mode
-     expand_end_bindings is not passed the list of variables in the
-     current scope, and therefore no warning is emitted.  So, we
-     explicitly warn here.  */
-  if (!processing_template_decl)
-    warn_about_unused_variables (getdecls ());
-
   /* If there were any declarations or structure tags in that level,
      or if this level is a function body,
      create a BLOCK to record them for the life of this function.  */
@@ -534,6 +563,16 @@ poplevel (int keep, int reverse, int functionbody)
   leaving_for_scope
     = current_binding_level->kind == sk_for && flag_new_for_scope == 1;
 
+  /* Before we remove the declarations first check for unused variables.  */
+  if (warn_unused_variable
+      && !processing_template_decl)
+    for (decl = getdecls (); decl; decl = TREE_CHAIN (decl))
+      if (TREE_CODE (decl) == VAR_DECL
+         && ! TREE_USED (decl)
+         && ! DECL_IN_SYSTEM_HEADER (decl)
+         && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
+       warning ("%Junused variable %qD", decl, decl);
+
   /* Remove declarations for all the DECLs in this level.  */
   for (link = decls; link; link = TREE_CHAIN (link))
     {
@@ -595,22 +634,26 @@ poplevel (int keep, int reverse, int functionbody)
 
              /* Although we don't pop the cxx_binding, we do clear
                 its SCOPE since the scope is going away now.  */
-             IDENTIFIER_BINDING (name)->scope 
+             IDENTIFIER_BINDING (name)->scope
                = current_binding_level->level_chain;
            }
        }
       else
        {
+         tree name;
+         
          /* Remove the binding.  */
          decl = link;
+
          if (TREE_CODE (decl) == TREE_LIST)
            decl = TREE_VALUE (decl);
-         if (DECL_P (decl))
-           pop_binding (DECL_NAME (decl), decl);
-         else if (TREE_CODE (decl) == OVERLOAD)
-           pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl);
-         else
-           abort ();
+         name = decl;
+         
+         if (TREE_CODE (name) == OVERLOAD)
+           name = OVL_FUNCTION (name);
+
+         gcc_assert (DECL_P (name));
+         pop_binding (DECL_NAME (name), decl);
        }
     }
 
@@ -787,9 +830,9 @@ walk_vtables_r (tree namespace, void* data)
    returns a nonzero value, return a nonzero value.  */
 bool
 walk_vtables (walk_globals_pred p, walk_globals_fn f, void *data)
-{    
+{
   struct walk_globals_data wgd;
-  wgd.p = p;    
+  wgd.p = p;
   wgd.f = f;
   wgd.data = data;
 
@@ -803,7 +846,7 @@ static int
 walk_namespaces_r (tree namespace, walk_namespaces_fn f, void* data)
 {
   int result = 0;
-  tree current = NAMESPACE_LEVEL (namespace)->namespaces;     
+  tree current = NAMESPACE_LEVEL (namespace)->namespaces;
 
   result |= (*f) (namespace, data);
 
@@ -1091,8 +1134,8 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl)
     return;
 
   name = DECL_ASSEMBLER_NAME (newdecl);
-  pedwarn ("`%D' was declared `extern' and later `static'", newdecl);
-  cp_pedwarn_at ("previous declaration of `%D'", olddecl);
+  pedwarn ("%qD was declared %<extern%> and later %<static%>", newdecl);
+  cp_pedwarn_at ("previous declaration of %qD", olddecl);
 }
 
 /* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
@@ -1140,17 +1183,17 @@ duplicate_decls (tree newdecl, tree olddecl)
               && DECL_UNINLINABLE (olddecl)
               && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
        {
-         warning ("%Jfunction '%D' redeclared as inline", newdecl, newdecl);
-         warning ("%Jprevious declaration of '%D' with attribute noinline",
+         warning ("%Jfunction %qD redeclared as inline", newdecl, newdecl);
+         warning ("%Jprevious declaration of %qD with attribute noinline",
                    olddecl, olddecl);
        }
       else if (DECL_DECLARED_INLINE_P (olddecl)
               && DECL_UNINLINABLE (newdecl)
               && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
        {
-         warning ("%Jfunction '%D' redeclared with attribute noinline",
+         warning ("%Jfunction %qD redeclared with attribute noinline",
                   newdecl, newdecl);
-         warning ("%Jprevious declaration of '%D' was inline",
+         warning ("%Jprevious declaration of %qD was inline",
                   olddecl, olddecl);
        }
     }
@@ -1171,22 +1214,22 @@ duplicate_decls (tree newdecl, tree olddecl)
          if (! TREE_PUBLIC (newdecl))
            {
              if (warn_shadow)
-               warning ("shadowing %s function `%#D'",
-                           DECL_BUILT_IN (olddecl) ? "built-in" : "library",
-                           olddecl);
+                warning ("shadowing %s function %q#D",
+                         DECL_BUILT_IN (olddecl) ? "built-in" : "library",
+                         olddecl);
              /* Discard the old built-in function.  */
              return NULL_TREE;
            }
          /* If the built-in is not ansi, then programs can override
             it even globally without an error.  */
          else if (! DECL_BUILT_IN (olddecl))
-           warning ("library function `%#D' redeclared as non-function `%#D'",
-                       olddecl, newdecl);
+           warning ("library function %q#D redeclared as non-function %q#D",
+                     olddecl, newdecl);
          else
            {
-             error ("declaration of `%#D'", newdecl);
-             error ("conflicts with built-in declaration `%#D'",
-                       olddecl);
+             error ("declaration of %q#D", newdecl);
+             error ("conflicts with built-in declaration %q#D",
+                     olddecl);
            }
          return NULL_TREE;
        }
@@ -1237,14 +1280,14 @@ duplicate_decls (tree newdecl, tree olddecl)
 
              if (TREE_PUBLIC (newdecl))
                {
-                 warning ("new declaration `%#D'", newdecl);
-                 warning ("ambiguates built-in declaration `%#D'",
-                             olddecl);
+                 warning ("new declaration %q#D", newdecl);
+                 warning ("ambiguates built-in declaration %q#D",
+                           olddecl);
                }
              else if (warn_shadow)
-               warning ("shadowing %s function `%#D'",
-                           DECL_BUILT_IN (olddecl) ? "built-in" : "library",
-                           olddecl);
+               warning ("shadowing %s function %q#D",
+                         DECL_BUILT_IN (olddecl) ? "built-in" : "library",
+                         olddecl);
            }
          else
            /* Discard the old built-in function.  */
@@ -1309,10 +1352,10 @@ duplicate_decls (tree newdecl, tree olddecl)
              && DECL_FUNCTION_TEMPLATE_P (newdecl)))
        return NULL_TREE;
 
-      error ("`%#D' redeclared as different kind of symbol", newdecl);
+      error ("%q#D redeclared as different kind of symbol", newdecl);
       if (TREE_CODE (olddecl) == TREE_LIST)
        olddecl = TREE_VALUE (olddecl);
-      cp_error_at ("previous declaration of `%#D'", olddecl);
+      cp_error_at ("previous declaration of %q#D", olddecl);
 
       return error_mark_node;
     }
@@ -1331,8 +1374,8 @@ duplicate_decls (tree newdecl, tree olddecl)
          if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL
              || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
            {
-             error ("declaration of template `%#D'", newdecl);
-             cp_error_at ("conflicts with previous declaration `%#D'",
+             error ("declaration of template %q#D", newdecl);
+             cp_error_at ("conflicts with previous declaration %q#D",
                           olddecl);
            }
          else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
@@ -1346,8 +1389,8 @@ duplicate_decls (tree newdecl, tree olddecl)
                   && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
                                   TREE_TYPE (TREE_TYPE (olddecl))))
            {
-             error ("new declaration `%#D'", newdecl);
-             cp_error_at ("ambiguates old declaration `%#D'", olddecl);
+             error ("new declaration %q#D", newdecl);
+             cp_error_at ("ambiguates old declaration %q#D", olddecl);
            }
          return NULL_TREE;
        }
@@ -1355,25 +1398,25 @@ duplicate_decls (tree newdecl, tree olddecl)
        {
          if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl))
            {
-             error ("declaration of C function `%#D' conflicts with",
-                       newdecl);
-             cp_error_at ("previous declaration `%#D' here", olddecl);
+             error ("declaration of C function %q#D conflicts with",
+                     newdecl);
+             cp_error_at ("previous declaration %q#D here", olddecl);
            }
          else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
                              TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
            {
-             error ("new declaration `%#D'", newdecl);
-             cp_error_at ("ambiguates old declaration `%#D'", olddecl);
+             error ("new declaration %q#D", newdecl);
+             cp_error_at ("ambiguates old declaration %q#D", olddecl);
            }
          else
            return NULL_TREE;
        }
       else
        {
-         error ("conflicting declaration '%#D'", newdecl);
-         cp_error_at ("'%D' has a previous declaration as `%#D'",
+         error ("conflicting declaration %q#D", newdecl);
+         cp_error_at ("%qD has a previous declaration as %q#D",
                        olddecl, olddecl);
-          return NULL_TREE;
+          return error_mark_node;
        }
     }
   else if (TREE_CODE (newdecl) == FUNCTION_DECL
@@ -1402,19 +1445,32 @@ duplicate_decls (tree newdecl, tree olddecl)
     /* One of the declarations is a template instantiation, and the
        other is not a template at all.  That's OK.  */
     return NULL_TREE;
-  else if (TREE_CODE (newdecl) == NAMESPACE_DECL
-           && DECL_NAMESPACE_ALIAS (newdecl)
-           && DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))
-    /* In [namespace.alias] we have:
-
-        In a declarative region, a namespace-alias-definition can be
-        used to redefine a namespace-alias declared in that declarative
-        region to refer only to the namespace to which it already
-        refers.  
-
-      Therefore, if we encounter a second alias directive for the same
-      alias, we can just ignore the second directive.  */
-    return olddecl;
+  else if (TREE_CODE (newdecl) == NAMESPACE_DECL)
+    {
+      /* In [namespace.alias] we have:
+        
+           In a declarative region, a namespace-alias-definition can be
+          used to redefine a namespace-alias declared in that declarative
+          region to refer only to the namespace to which it already
+          refers.
+          
+        Therefore, if we encounter a second alias directive for the same
+        alias, we can just ignore the second directive.  */
+      if (DECL_NAMESPACE_ALIAS (newdecl)
+         && (DECL_NAMESPACE_ALIAS (newdecl) 
+             == DECL_NAMESPACE_ALIAS (olddecl)))
+       return olddecl;
+      /* [namespace.alias]
+
+         A namespace-name or namespace-alias shall not be declared as
+        the name of any other entity in the same declarative region.
+        A namespace-name defined at global scope shall not be
+        declared as the name of any other entity in any global scope
+        of the program.  */
+      error ("declaration of namespace %qD conflicts with", newdecl);
+      cp_error_at ("previous declaration of namespace %qD here", olddecl);
+      return error_mark_node;
+    }
   else
     {
       const char *errmsg = redeclaration_error_message (newdecl, olddecl);
@@ -1424,8 +1480,8 @@ duplicate_decls (tree newdecl, tree olddecl)
          if (DECL_NAME (olddecl) != NULL_TREE)
            cp_error_at ((DECL_INITIAL (olddecl)
                          && namespace_bindings_p ())
-                        ? "`%#D' previously defined here"
-                        : "`%#D' previously declared here", olddecl);
+                        ? "%q#D previously defined here"
+                        : "%q#D previously declared here", olddecl);
          return error_mark_node;
        }
       else if (TREE_CODE (olddecl) == FUNCTION_DECL
@@ -1434,7 +1490,7 @@ duplicate_decls (tree newdecl, tree olddecl)
               && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE)
        {
          /* Prototype decl follows defn w/o prototype.  */
-         cp_warning_at ("prototype for `%#D'", newdecl);
+         cp_warning_at ("prototype for %q#D", newdecl);
          warning ("%Jfollows non-prototype definition here", olddecl);
        }
       else if (TREE_CODE (olddecl) == FUNCTION_DECL
@@ -1447,10 +1503,10 @@ duplicate_decls (tree newdecl, tree olddecl)
            SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
          else
            {
-             cp_error_at ("previous declaration of `%#D' with %L linkage",
+             cp_error_at ("previous declaration of %q#D with %qL linkage",
                           olddecl, DECL_LANGUAGE (olddecl));
-             error ("conflicts with new declaration with %L linkage",
-                       DECL_LANGUAGE (newdecl));
+             error ("conflicts with new declaration with %qL linkage",
+                     DECL_LANGUAGE (newdecl));
            }
        }
 
@@ -1472,25 +1528,25 @@ duplicate_decls (tree newdecl, tree olddecl)
                if (1 == simple_cst_equal (TREE_PURPOSE (t1),
                                           TREE_PURPOSE (t2)))
                  {
-                   pedwarn ("default argument given for parameter %d of `%#D'",
+                   pedwarn ("default argument given for parameter %d of %q#D",
                             i, newdecl);
-                   cp_pedwarn_at ("after previous specification in `%#D'",
+                   cp_pedwarn_at ("after previous specification in %q#D",
                                   olddecl);
                  }
                else
                  {
-                   error ("default argument given for parameter %d of `%#D'",
-                             i, newdecl);
-                   cp_error_at ("after previous specification in `%#D'",
+                   error ("default argument given for parameter %d of %q#D",
+                           i, newdecl);
+                   cp_error_at ("after previous specification in %q#D",
                                 olddecl);
                  }
              }
 
-         if (DECL_DECLARED_INLINE_P (newdecl) 
+         if (DECL_DECLARED_INLINE_P (newdecl)
              && ! DECL_DECLARED_INLINE_P (olddecl)
              && TREE_ADDRESSABLE (olddecl) && warn_inline)
            {
-             warning ("`%#D' was used before it was declared inline", newdecl);
+             warning ("%q#D was used before it was declared inline", newdecl);
              warning ("%Jprevious non-inline declaration here", olddecl);
            }
        }
@@ -1527,7 +1583,6 @@ duplicate_decls (tree newdecl, tree olddecl)
       DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
       DECL_PURE_VIRTUAL_P (newdecl) |= DECL_PURE_VIRTUAL_P (olddecl);
       DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
-      DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
       DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
       if (DECL_OVERLOADED_OPERATOR_P (olddecl) != ERROR_MARK)
        SET_OVERLOADED_OPERATOR_CODE
@@ -1544,8 +1599,8 @@ duplicate_decls (tree newdecl, tree olddecl)
          /* Don't warn about friends, let add_friend take care of it.  */
          && ! (DECL_FRIEND_P (newdecl) || DECL_FRIEND_P (olddecl)))
        {
-         warning ("redundant redeclaration of `%D' in same scope", newdecl);
-         cp_warning_at ("previous declaration of `%D'", olddecl);
+         warning ("redundant redeclaration of %qD in same scope", newdecl);
+         cp_warning_at ("previous declaration of %qD", olddecl);
        }
     }
 
@@ -1580,7 +1635,7 @@ duplicate_decls (tree newdecl, tree olddecl)
       if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE
          && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE)
        {
-         DECL_SOURCE_LOCATION (olddecl) 
+         DECL_SOURCE_LOCATION (olddecl)
            = DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
            = DECL_SOURCE_LOCATION (newdecl);
          if (DECL_FUNCTION_TEMPLATE_P (newdecl))
@@ -1590,7 +1645,7 @@ duplicate_decls (tree newdecl, tree olddecl)
 
       if (DECL_FUNCTION_TEMPLATE_P (newdecl))
        {
-         DECL_INLINE (DECL_TEMPLATE_RESULT (olddecl)) 
+         DECL_INLINE (DECL_TEMPLATE_RESULT (olddecl))
            |= DECL_INLINE (DECL_TEMPLATE_RESULT (newdecl));
          DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (olddecl))
            |= DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (newdecl));
@@ -1638,9 +1693,9 @@ duplicate_decls (tree newdecl, tree olddecl)
              && !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)),
                                     TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1))
            {
-             error ("declaration of `%F' throws different exceptions",
-                       newdecl);
-             cp_error_at ("than previous declaration `%F'", olddecl);
+             error ("declaration of %qF throws different exceptions",
+                     newdecl);
+             cp_error_at ("than previous declaration %qF", olddecl);
            }
        }
       TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
@@ -1664,6 +1719,12 @@ duplicate_decls (tree newdecl, tree olddecl)
        TREE_READONLY (olddecl) = 1;
       if (TREE_THIS_VOLATILE (newdecl))
        TREE_THIS_VOLATILE (olddecl) = 1;
+      if (TREE_NOTHROW (newdecl))
+       TREE_NOTHROW (olddecl) = 1;
+
+      /* Merge deprecatedness.  */
+      if (TREE_DEPRECATED (newdecl))
+       TREE_DEPRECATED (olddecl) = 1;
 
       /* Merge the initialization information.  */
       if (DECL_INITIAL (newdecl) == NULL_TREE
@@ -1700,7 +1761,7 @@ duplicate_decls (tree newdecl, tree olddecl)
          /* Keep the old RTL.  */
          COPY_DECL_RTL (olddecl, newdecl);
        }
-      else if (TREE_CODE (newdecl) == VAR_DECL 
+      else if (TREE_CODE (newdecl) == VAR_DECL
               && (DECL_SIZE (olddecl) || !DECL_SIZE (newdecl)))
        {
          /* Keep the old RTL.  We cannot keep the old RTL if the old
@@ -1745,9 +1806,10 @@ duplicate_decls (tree newdecl, tree olddecl)
       /* Don't really know how much of the language-specific
         values we should copy from old to new.  */
       DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
-      DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 = 
+      DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 =
        DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2;
       DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
+      DECL_REPO_AVAILABLE_P (newdecl) = DECL_REPO_AVAILABLE_P (olddecl);
       DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
       DECL_INITIALIZED_IN_CLASS_P (newdecl)
         |= DECL_INITIALIZED_IN_CLASS_P (olddecl);
@@ -1775,8 +1837,7 @@ duplicate_decls (tree newdecl, tree olddecl)
          /* If newdecl is not a specialization, then it is not a
             template-related function at all.  And that means that we
             should have exited above, returning 0.  */
-         my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl),
-                             0);
+         gcc_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl));
 
          if (TREE_USED (olddecl))
            /* From [temp.expl.spec]:
@@ -1787,7 +1848,7 @@ duplicate_decls (tree newdecl, tree olddecl)
               that specialization that would cause an implicit
               instantiation to take place, in every translation unit in
               which such a use occurs.  */
-           error ("explicit specialization of %D after first use",
+           error ("explicit specialization of %qD after first use",
                      olddecl);
 
          SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
@@ -1802,7 +1863,7 @@ duplicate_decls (tree newdecl, tree olddecl)
 
          DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
 
-         /* If either decl says `inline', this fn is inline, unless 
+         /* If either decl says `inline', this fn is inline, unless
             its definition was passed already.  */
          if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
            DECL_INLINE (olddecl) = 1;
@@ -1861,17 +1922,29 @@ duplicate_decls (tree newdecl, tree olddecl)
   DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
   COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
 
-  /* If either declaration has a nondefault visibility, use it.  */
-  if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT)
+  /* Warn about conflicting visibility specifications.  */
+  if (DECL_VISIBILITY_SPECIFIED (olddecl) 
+      && DECL_VISIBILITY_SPECIFIED (newdecl)
+      && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
+    {
+      warning ("%J%qD: visibility attribute ignored because it",
+              newdecl, newdecl);
+      warning ("%Jconflicts with previous declaration here", olddecl);
+    }
+  /* Choose the declaration which specified visibility.  */
+  if (DECL_VISIBILITY_SPECIFIED (olddecl))
     {
-      if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT
-         && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
-       {
-         warning ("%J'%D': visibility attribute ignored because it",
-                  newdecl, newdecl);
-         warning ("%Jconflicts with previous declaration here", olddecl);
-       }
       DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
+      DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
+    }
+
+  /* The DECL_LANG_SPECIFIC information in OLDDECL will be replaced
+     with that from NEWDECL below.  */
+  if (DECL_LANG_SPECIFIC (olddecl))
+    {
+      gcc_assert (DECL_LANG_SPECIFIC (olddecl) 
+                 != DECL_LANG_SPECIFIC (newdecl));
+      ggc_free (DECL_LANG_SPECIFIC (olddecl));
     }
 
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -1906,8 +1979,8 @@ duplicate_decls (tree newdecl, tree olddecl)
           olddecl, and not newdecl, is on the list of
           instantiations so that if we try to do the instantiation
           again we won't get the clobbered declaration.  */
-       reregister_specialization (newdecl, 
-                                  DECL_TI_TEMPLATE (newdecl), 
+       reregister_specialization (newdecl,
+                                  DECL_TI_TEMPLATE (newdecl),
                                   olddecl);
     }
   else
@@ -1929,11 +2002,16 @@ duplicate_decls (tree newdecl, tree olddecl)
   /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
     so that encode_section_info has a chance to look at the new decl
     flags and attributes.  */
-  if (DECL_RTL_SET_P (olddecl) 
+  if (DECL_RTL_SET_P (olddecl)
       && (TREE_CODE (olddecl) == FUNCTION_DECL
          || (TREE_CODE (olddecl) == VAR_DECL
              && TREE_STATIC (olddecl))))
-    make_decl_rtl (olddecl, NULL);
+    make_decl_rtl (olddecl);
+
+  /* The NEWDECL will no longer be needed.  Because every out-of-class
+     declaration of a member results in a call to duplicate_decls,
+     freeing these nodes represents in a significant savings.  */
+  ggc_free (newdecl);
 
   return olddecl;
 }
@@ -1955,7 +2033,7 @@ redeclaration_error_message (tree newdecl, tree olddecl)
       if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
        return 0;
       else
-       return "redefinition of `%#D'";
+       return "redefinition of %q#D";
     }
   else if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
@@ -1969,7 +2047,7 @@ redeclaration_error_message (tree newdecl, tree olddecl)
         a redeclaration - this is a conflict with a used function.  */
       if (DECL_NAMESPACE_SCOPE_P (olddecl)
          && DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl))
-       return "`%D' conflicts with used function";
+       return "%qD conflicts with used function";
 
       /* We'll complain about linkage mismatches in
          warn_extern_redeclared_static.  */
@@ -1979,9 +2057,9 @@ redeclaration_error_message (tree newdecl, tree olddecl)
          && DECL_INITIAL (newdecl) != NULL_TREE)
        {
          if (DECL_NAME (olddecl) == NULL_TREE)
-           return "`%#D' not declared in class";
+           return "%q#D not declared in class";
          else
-           return "redefinition of `%#D'";
+           return "redefinition of %q#D";
        }
       return 0;
     }
@@ -1993,12 +2071,12 @@ redeclaration_error_message (tree newdecl, tree olddecl)
        {
          if (COMPLETE_TYPE_P (TREE_TYPE (newdecl))
              && COMPLETE_TYPE_P (TREE_TYPE (olddecl)))
-           return "redefinition of `%#D'";
+           return "redefinition of %q#D";
          return NULL;
        }
 
       if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != FUNCTION_DECL
-         || (DECL_TEMPLATE_RESULT (newdecl) 
+         || (DECL_TEMPLATE_RESULT (newdecl)
              == DECL_TEMPLATE_RESULT (olddecl)))
        return NULL;
 
@@ -2009,7 +2087,7 @@ redeclaration_error_message (tree newdecl, tree olddecl)
       if (DECL_TEMPLATE_INFO (ot))
        ot = DECL_TEMPLATE_RESULT (template_for_substitution (ot));
       if (DECL_INITIAL (nt) && DECL_INITIAL (ot))
-       return "redefinition of `%#D'";
+       return "redefinition of %q#D";
 
       return NULL;
     }
@@ -2020,7 +2098,7 @@ redeclaration_error_message (tree newdecl, tree olddecl)
       if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
        return 0;
       /* Reject two definitions.  */
-      return "redefinition of `%#D'";
+      return "redefinition of %q#D";
     }
   else
     {
@@ -2028,7 +2106,7 @@ redeclaration_error_message (tree newdecl, tree olddecl)
       /* Reject two definitions, and reject a definition
         together with an external reference.  */
       if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
-       return "redeclaration of `%#D'";
+       return "redeclaration of %q#D";
       return 0;
     }
 }
@@ -2069,7 +2147,7 @@ use_label (tree decl)
       || named_label_uses->label_decl != decl)
     {
       struct named_label_use_list *new_ent;
-      new_ent = ggc_alloc (sizeof (struct named_label_use_list));
+      new_ent = GGC_NEW (struct named_label_use_list);
       new_ent->label_decl = decl;
       new_ent->names_in_scope = current_binding_level->names;
       new_ent->binding_level = current_binding_level;
@@ -2093,7 +2171,7 @@ lookup_label (tree id)
   /* You can't use labels at global scope.  */
   if (current_function_decl == NULL_TREE)
     {
-      error ("label `%E' referenced outside of any function", id);
+      error ("label %qE referenced outside of any function", id);
       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
     }
 
@@ -2105,7 +2183,7 @@ lookup_label (tree id)
   /* Record this label on the list of labels used in this function.
      We do this before calling make_label_decl so that we get the
      IDENTIFIER_LABEL_VALUE before the new label is declared.  */
-  ent = ggc_alloc_cleared (sizeof (struct named_label_list));
+  ent = GGC_CNEW (struct named_label_list);
   ent->old_value = IDENTIFIER_LABEL_VALUE (id);
   ent->next = named_labels;
   named_labels = ent;
@@ -2189,7 +2267,7 @@ check_previous_goto_1 (tree decl,
          if (! identified)
            {
              if (decl)
-               pedwarn ("jump to label `%D'", decl);
+               pedwarn ("jump to label %qD", decl);
              else
                pedwarn ("jump to case label");
 
@@ -2199,10 +2277,10 @@ check_previous_goto_1 (tree decl,
            }
 
          if (problem > 1)
-           cp_error_at ("  crosses initialization of `%#D'",
+           cp_error_at ("  crosses initialization of %q#D",
                         new_decls);
          else
-           cp_pedwarn_at ("  enters scope of non-POD `%#D'",
+           cp_pedwarn_at ("  enters scope of non-POD %q#D",
                           new_decls);
        }
 
@@ -2213,7 +2291,7 @@ check_previous_goto_1 (tree decl,
          if (! identified)
            {
              if (decl)
-               pedwarn ("jump to label `%D'", decl);
+               pedwarn ("jump to label %qD", decl);
              else
                pedwarn ("jump to case label");
 
@@ -2301,7 +2379,7 @@ check_goto (tree decl)
   if ((lab->in_try_scope || lab->in_catch_scope || lab->bad_decls)
       && !identified)
     {
-      cp_pedwarn_at ("jump to label `%D'", decl);
+      cp_pedwarn_at ("jump to label %qD", decl);
       pedwarn ("  from here");
       identified = 1;
     }
@@ -2315,9 +2393,9 @@ check_goto (tree decl)
        /* Can't skip init of __exception_info.  */
        error ("%J  enters catch block", b);
       else if (u > 1)
-       cp_error_at ("  skips initialization of `%#D'", b);
+       cp_error_at ("  skips initialization of %q#D", b);
       else
-       cp_pedwarn_at ("  enters scope of non-POD `%#D'", b);
+       cp_pedwarn_at ("  enters scope of non-POD %q#D", b);
     }
 
   if (lab->in_try_scope)
@@ -2343,8 +2421,8 @@ define_label (location_t location, tree name)
 
   /* After labels, make any new cleanups in the function go into their
      own new (temporary) binding contour.  */
-  for (p = current_binding_level; 
-       p->kind != sk_function_parms; 
+  for (p = current_binding_level;
+       p->kind != sk_function_parms;
        p = p->level_chain)
     p->more_cleanups_ok = 0;
 
@@ -2352,7 +2430,7 @@ define_label (location_t location, tree name)
     pedwarn ("label named wchar_t");
 
   if (DECL_INITIAL (decl) != NULL_TREE)
-    error ("duplicate label `%D'", decl);
+    error ("duplicate label %qD", decl);
   else
     {
       /* Mark label as having been defined.  */
@@ -2367,8 +2445,7 @@ define_label (location_t location, tree name)
       check_previous_gotos (decl);
     }
 
-  timevar_pop (TV_NAME_LOOKUP);
-  return decl;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
 }
 
 struct cp_switch
@@ -2451,8 +2528,8 @@ finish_case_label (tree low_value, tree high_value)
 
   /* After labels, make any new cleanups in the function go into their
      own new (temporary) binding contour.  */
-  for (p = current_binding_level; 
-       p->kind != sk_function_parms; 
+  for (p = current_binding_level;
+       p->kind != sk_function_parms;
        p = p->level_chain)
     p->more_cleanups_ok = 0;
 
@@ -2473,83 +2550,101 @@ typename_hash (const void* k)
   return hash;
 }
 
+typedef struct typename_info {
+  tree scope;
+  tree name;
+  tree template_id;
+  bool enum_p;
+  bool class_p;
+} typename_info;
+
 /* Compare two TYPENAME_TYPEs.  K1 and K2 are really of type `tree'.  */
 
 static int
 typename_compare (const void * k1, const void * k2)
 {
   tree t1;
-  tree t2;
-  tree d1;
-  tree d2;
+  const typename_info *t2;
 
   t1 = (tree) k1;
-  t2 = (tree) k2;
-  d1 = TYPE_NAME (t1);
-  d2 = TYPE_NAME (t2);
+  t2 = (const typename_info *) k2;
 
-  return (DECL_NAME (d1) == DECL_NAME (d2)
-         && TYPE_CONTEXT (t1) == TYPE_CONTEXT (t2)
-         && ((TREE_TYPE (t1) != NULL_TREE)
-             == (TREE_TYPE (t2) != NULL_TREE))
-         && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
-         && TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2));
+  return (DECL_NAME (TYPE_NAME (t1)) == t2->name
+         && TYPE_CONTEXT (t1) == t2->scope
+         && TYPENAME_TYPE_FULLNAME (t1) == t2->template_id
+         && TYPENAME_IS_ENUM_P (t1) == t2->enum_p
+         && TYPENAME_IS_CLASS_P (t1) == t2->class_p);
 }
 
 /* Build a TYPENAME_TYPE.  If the type is `typename T::t', CONTEXT is
-   the type of `T', NAME is the IDENTIFIER_NODE for `t'.  If BASE_TYPE
-   is non-NULL, this type is being created by the implicit typename
-   extension, and BASE_TYPE is a type named `t' in some base class of
-   `T' which depends on template parameters.
-
+   the type of `T', NAME is the IDENTIFIER_NODE for `t'.
    Returns the new TYPENAME_TYPE.  */
 
 static GTY ((param_is (union tree_node))) htab_t typename_htab;
 
 static tree
-build_typename_type (tree context, tree name, tree fullname)
+build_typename_type (tree context, tree name, tree fullname,
+                    enum tag_types tag_type)
 {
   tree t;
   tree d;
+  typename_info ti;
   void **e;
+  hashval_t hash;
 
   if (typename_htab == NULL)
-    {
-      typename_htab = htab_create_ggc (61, &typename_hash, 
-                                      &typename_compare, NULL);
-    }
-
-  /* Build the TYPENAME_TYPE.  */
-  t = make_aggr_type (TYPENAME_TYPE);
-  TYPE_CONTEXT (t) = FROB_CONTEXT (context);
-  TYPENAME_TYPE_FULLNAME (t) = fullname;
-
-  /* Build the corresponding TYPE_DECL.  */
-  d = build_decl (TYPE_DECL, name, t);
-  TYPE_NAME (TREE_TYPE (d)) = d;
-  TYPE_STUB_DECL (TREE_TYPE (d)) = d;
-  DECL_CONTEXT (d) = FROB_CONTEXT (context);
-  DECL_ARTIFICIAL (d) = 1;
+    typename_htab = htab_create_ggc (61, &typename_hash,
+                                    &typename_compare, NULL);
+
+  ti.scope = FROB_CONTEXT (context); 
+  ti.name = name;
+  ti.template_id = fullname;
+  ti.enum_p = tag_type == enum_type;
+  ti.class_p = (tag_type == class_type
+               || tag_type == record_type
+               || tag_type == union_type);
+  hash =  (htab_hash_pointer (ti.scope)
+          ^ htab_hash_pointer (ti.name));
 
   /* See if we already have this type.  */
-  e = htab_find_slot (typename_htab, t, INSERT);
+  e = htab_find_slot_with_hash (typename_htab, &ti, hash, INSERT);
   if (*e)
     t = (tree) *e;
   else
-    *e = t;
+    {
+      /* Build the TYPENAME_TYPE.  */
+      t = make_aggr_type (TYPENAME_TYPE);
+      TYPE_CONTEXT (t) = ti.scope;
+      TYPENAME_TYPE_FULLNAME (t) = ti.template_id;
+      TYPENAME_IS_ENUM_P (t) = ti.enum_p;
+      TYPENAME_IS_CLASS_P (t) = ti.class_p;
+      
+      /* Build the corresponding TYPE_DECL.  */
+      d = build_decl (TYPE_DECL, name, t);
+      TYPE_NAME (TREE_TYPE (d)) = d;
+      TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+      DECL_CONTEXT (d) = FROB_CONTEXT (context);
+      DECL_ARTIFICIAL (d) = 1;
 
+      /* Store it in the hash table.  */
+      *e = t;
+    }
+      
   return t;
 }
 
-/* Resolve `typename CONTEXT::NAME'.  Returns an appropriate type,
-   unless an error occurs, in which case error_mark_node is returned.
-   If we locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is
-   set, we return that, rather than the _TYPE it corresponds to, in
-   other cases we look through the type decl.  If TF_ERROR is set,
-   complain about errors, otherwise be quiet.  */
+/* Resolve `typename CONTEXT::NAME'.  TAG_TYPE indicates the tag
+   provided to name the type.  Returns an appropriate type, unless an
+   error occurs, in which case error_mark_node is returned.  If we
+   locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is set, we
+   return that, rather than the _TYPE it corresponds to, in other
+   cases we look through the type decl.  If TF_ERROR is set, complain
+   about errors, otherwise be quiet.  */
 
 tree
-make_typename_type (tree context, tree name, tsubst_flags_t complain)
+make_typename_type (tree context, tree name, enum tag_types tag_type,
+                   tsubst_flags_t complain)
 {
   tree fullname;
 
@@ -2583,20 +2678,11 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
     }
   if (TREE_CODE (name) == TEMPLATE_DECL)
     {
-      error ("`%D' used without template parameters", name);
-      return error_mark_node;
-    }
-  my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 20030802);
-  
-  if (TREE_CODE (context) == NAMESPACE_DECL)
-    {
-      /* We can get here from typename_sub0 in the explicit_template_type
-        expansion.  Just fail.  */
-      if (complain & tf_error)
-       error ("no class template named `%#T' in `%#T'",
-                 name, context);
+      error ("%qD used without template parameters", name);
       return error_mark_node;
     }
+  gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
+  gcc_assert (TYPE_P (context));
 
   if (!dependent_type_p (context)
       || currently_open_class (context))
@@ -2609,8 +2695,8 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
          if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
            {
              if (complain & tf_error)
-               error ("no class template named `%#T' in `%#T'",
-                         name, context);
+               error ("no class template named %q#T in %q#T",
+                       name, context);
              return error_mark_node;
            }
 
@@ -2630,7 +2716,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
          if (!IS_AGGR_TYPE (context))
            {
              if (complain & tf_error)
-               error ("no type named `%#T' in `%#T'", name, context);
+               error ("no type named %q#T in %q#T", name, context);
              return error_mark_node;
            }
 
@@ -2640,7 +2726,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
              if (TREE_CODE (t) != TYPE_DECL)
                {
                  if (complain & tf_error)
-                   error ("no type named `%#T' in `%#T'", name, context);
+                   error ("no type named %q#T in %q#T", name, context);
                  return error_mark_node;
                }
 
@@ -2649,7 +2735,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
 
              if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
                t = TREE_TYPE (t);
-             
+
              return t;
            }
        }
@@ -2660,21 +2746,25 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
   if (!dependent_type_p (context))
     {
       if (complain & tf_error)
-       error ("no type named `%#T' in `%#T'", name, context);
+       error ("no type named %q#T in %q#T", name, context);
       return error_mark_node;
     }
 
-  return build_typename_type (context, name, fullname);
+  return build_typename_type (context, name, fullname, tag_type);
 }
 
-/* Resolve `CONTEXT::template NAME'.  Returns an appropriate type,
-   unless an error occurs, in which case error_mark_node is returned.
-   If we locate a TYPE_DECL, we return that, rather than the _TYPE it
-   corresponds to.  If COMPLAIN zero, don't complain about any errors
-   that occur.  */
+/* Resolve `CONTEXT::template NAME'.  Returns a TEMPLATE_DECL if the name
+   can be resolved or an UNBOUND_CLASS_TEMPLATE, unless an error occurs, 
+   in which case error_mark_node is returned.
+
+   If PARM_LIST is non-NULL, also make sure that the template parameter
+   list of TEMPLATE_DECL matches.
+
+   If COMPLAIN zero, don't complain about any errors that occur.  */
 
 tree
-make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
+make_unbound_class_template (tree context, tree name, tree parm_list,
+                            tsubst_flags_t complain)
 {
   tree t;
   tree d;
@@ -2683,8 +2773,7 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
     name = TYPE_IDENTIFIER (name);
   else if (DECL_P (name))
     name = DECL_NAME (name);
-  if (TREE_CODE (name) != IDENTIFIER_NODE)
-    abort ();
+  gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
 
   if (!dependent_type_p (context)
       || currently_open_class (context))
@@ -2697,10 +2786,21 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
       if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
        {
          if (complain & tf_error)
-           error ("no class template named `%#T' in `%#T'", name, context);
+           error ("no class template named %q#T in %q#T", name, context);
          return error_mark_node;
        }
-      
+
+      if (parm_list
+         && !comp_template_parms (DECL_TEMPLATE_PARMS (tmpl), parm_list))
+       {
+         if (complain & tf_error)
+           {
+             error ("template parameters do not match template");
+             cp_error_at ("%qD declared here", tmpl);
+           }
+         return error_mark_node;
+       }
+
       if (complain & tf_error)
        perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
 
@@ -2718,6 +2818,7 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
   TYPE_STUB_DECL (TREE_TYPE (d)) = d;
   DECL_CONTEXT (d) = FROB_CONTEXT (context);
   DECL_ARTIFICIAL (d) = 1;
+  DECL_TEMPLATE_PARMS (d) = parm_list;
 
   return t;
 }
@@ -2730,8 +2831,8 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
    type.  TYPE is the _TYPE node for the builtin type.  */
 
 void
-record_builtin_type (enum rid rid_index, 
-                     const char* name, 
+record_builtin_type (enum rid rid_index,
+                     const char* name,
                      tree type)
 {
   tree rname = NULL_TREE, tname = NULL_TREE;
@@ -2844,13 +2945,15 @@ initialize_predefined_identifiers (void)
     { "C++", &lang_name_cplusplus, 0 },
     { "C", &lang_name_c, 0 },
     { "Java", &lang_name_java, 0 },
-    { CTOR_NAME, &ctor_identifier, 1 },
-    { "__base_ctor", &base_ctor_identifier, 1 },
-    { "__comp_ctor", &complete_ctor_identifier, 1 },
-    { DTOR_NAME, &dtor_identifier, 1 },
-    { "__comp_dtor", &complete_dtor_identifier, 1 },
-    { "__base_dtor", &base_dtor_identifier, 1 },
-    { "__deleting_dtor", &deleting_dtor_identifier, 1 },
+    /* Some of these names have a trailing space so that it is
+       impossible for them to conflict with names written by users.  */
+    { "__ct ", &ctor_identifier, 1 },
+    { "__base_ctor ", &base_ctor_identifier, 1 },
+    { "__comp_ctor ", &complete_ctor_identifier, 1 },
+    { "__dt ", &dtor_identifier, 1 },
+    { "__comp_dtor ", &complete_dtor_identifier, 1 },
+    { "__base_dtor ", &base_dtor_identifier, 1 },
+    { "__deleting_dtor ", &deleting_dtor_identifier, 1 },
     { IN_CHARGE_NAME, &in_charge_identifier, 0 },
     { "nelts", &nelts_identifier, 0 },
     { THIS_NAME, &this_identifier, 0 },
@@ -2882,7 +2985,7 @@ cxx_init_decl_processing (void)
   tree void_ftype;
   tree void_ftype_ptr;
 
-  build_common_tree_nodes (flag_signed_char);
+  build_common_tree_nodes (flag_signed_char, false);
 
   /* Create all the identifiers we need.  */
   initialize_predefined_identifiers ();
@@ -2893,7 +2996,7 @@ cxx_init_decl_processing (void)
   current_function_decl = NULL_TREE;
   current_binding_level = NULL;
   /* Enter the global namespace.  */
-  my_friendly_assert (global_namespace == NULL_TREE, 375);
+  gcc_assert (global_namespace == NULL_TREE);
   global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name,
                                       void_type_node);
   begin_scope (sk_namespace, global_namespace);
@@ -2909,10 +3012,7 @@ cxx_init_decl_processing (void)
       flag_no_inline = 1;
     }
   if (flag_inline_functions)
-    {
-      flag_inline_trees = 2;
-      flag_inline_functions = 0;
-    }
+    flag_inline_trees = 2;
 
   /* Force minimum function alignment if using the least significant
      bit of function pointers to store the virtual bit.  */
@@ -2942,10 +3042,8 @@ cxx_init_decl_processing (void)
   java_char_type_node = record_builtin_java_type ("__java_char", -16);
   java_boolean_type_node = record_builtin_java_type ("__java_boolean", -1);
 
-  integer_two_node = build_int_2 (2, 0);
-  TREE_TYPE (integer_two_node) = integer_type_node;
-  integer_three_node = build_int_2 (3, 0);
-  TREE_TYPE (integer_three_node) = integer_type_node;
+  integer_two_node = build_int_cst (NULL_TREE, 2);
+  integer_three_node = build_int_cst (NULL_TREE, 3);
 
   record_builtin_type (RID_BOOL, "bool", boolean_type_node);
   truthvalue_type_node = boolean_type_node;
@@ -2965,7 +3063,7 @@ cxx_init_decl_processing (void)
   void_ftype = build_function_type (void_type_node, void_list_node);
   void_ftype_ptr = build_function_type (void_type_node,
                                        tree_cons (NULL_TREE,
-                                                  ptr_type_node, 
+                                                  ptr_type_node,
                                                   void_list_node));
   void_ftype_ptr
     = build_exception_variant (void_ftype_ptr, empty_except_spec);
@@ -3025,13 +3123,13 @@ cxx_init_decl_processing (void)
     bad_alloc_id = get_identifier ("bad_alloc");
     bad_alloc_type_node = make_aggr_type (RECORD_TYPE);
     TYPE_CONTEXT (bad_alloc_type_node) = current_namespace;
-    bad_alloc_decl 
+    bad_alloc_decl
       = create_implicit_typedef (bad_alloc_id, bad_alloc_type_node);
     DECL_CONTEXT (bad_alloc_decl) = current_namespace;
     TYPE_STUB_DECL (bad_alloc_type_node) = bad_alloc_decl;
     pop_namespace ();
-    ptr_ftype_sizetype 
+
+    ptr_ftype_sizetype
       = build_function_type (ptr_type_node,
                             tree_cons (NULL_TREE,
                                        size_type_node,
@@ -3085,17 +3183,17 @@ cp_fname_init (const char* name, tree *type_p)
       domain = build_index_type (size_int (length));
       init = build_string (length + 1, name);
     }
-  
+
   type = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
   type = build_cplus_array_type (type, domain);
 
   *type_p = type;
-  
+
   if (init)
     TREE_TYPE (init) = type;
   else
     init = error_mark_node;
-  
+
   return init;
 }
 
@@ -3120,12 +3218,12 @@ cp_make_fname_decl (tree id, int type_dep)
   /* As we're using pushdecl_with_scope, we must set the context.  */
   DECL_CONTEXT (decl) = current_function_decl;
   DECL_PRETTY_FUNCTION_P (decl) = type_dep;
-      
+
   TREE_STATIC (decl) = 1;
   TREE_READONLY (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
   DECL_INITIAL (decl) = init;
-  
+
   TREE_USED (decl) = 1;
 
   if (current_function_decl)
@@ -3138,7 +3236,7 @@ cp_make_fname_decl (tree id, int type_dep)
     }
   else
     pushdecl_top_level_and_finish (decl, init);
-      
+
   return decl;
 }
 
@@ -3158,7 +3256,7 @@ static tree
 builtin_function_1 (const char* name,
                     tree type,
                     tree context,
-                    int code,
+                   enum built_in_function code,
                     enum built_in_class class,
                     const char* libname,
                     tree attrs)
@@ -3210,7 +3308,7 @@ tree
 builtin_function (const char* name,
                   tree type,
                   int code,
-                  enum built_in_class class,
+                  enum built_in_class cl,
                   const char* libname,
                   tree attrs)
 {
@@ -3219,12 +3317,12 @@ builtin_function (const char* name,
   if (name[0] != '_')
     {
       push_namespace (std_identifier);
-      builtin_function_1 (name, type, std_node, code, class, libname, attrs);
+      builtin_function_1 (name, type, std_node, code, cl, libname, attrs);
       pop_namespace ();
     }
 
   return builtin_function_1 (name, type, NULL_TREE, code,
-                            class, libname, attrs);
+                            cl, libname, attrs);
 }
 
 /* Generate a FUNCTION_DECL with the typical flags for a runtime library
@@ -3240,6 +3338,10 @@ build_library_fn_1 (tree name, enum tree_code operator_code, tree type)
   TREE_NOTHROW (fn) = 1;
   SET_OVERLOADED_OPERATOR_CODE (fn, operator_code);
   SET_DECL_LANGUAGE (fn, lang_c);
+  /* Runtime library routines are, by definition, available in an
+     external shared object.  */
+  DECL_VISIBILITY (fn) = VISIBILITY_DEFAULT;
+  DECL_VISIBILITY_SPECIFIED (fn) = 1;
   return fn;
 }
 
@@ -3383,13 +3485,16 @@ fixup_anonymous_aggr (tree t)
            if (CLASS_TYPE_P (type))
              {
                if (TYPE_NEEDS_CONSTRUCTING (type))
-                 cp_error_at ("member %#D' with constructor not allowed in anonymous aggregate",
+                 cp_error_at ("member %q#D with constructor not allowed "
+                               "in anonymous aggregate",
                               field);
                if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
-                 cp_error_at ("member %#D' with destructor not allowed in anonymous aggregate",
+                 cp_error_at ("member %q#D with destructor not allowed "
+                               "in anonymous aggregate",
                               field);
                if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
-                 cp_error_at ("member %#D' with copy assignment operator not allowed in anonymous aggregate",
+                 cp_error_at ("member %q#D with copy assignment operator "
+                               "not allowed in anonymous aggregate",
                               field);
              }
          }
@@ -3423,8 +3528,9 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
       return NULL_TREE;
     }
 
-  if (TYPE_P (declspecs->type)
-      && ((TREE_CODE (declspecs->type) != TYPENAME_TYPE 
+  if (declspecs->type
+      && TYPE_P (declspecs->type)
+      && ((TREE_CODE (declspecs->type) != TYPENAME_TYPE
           && IS_AGGR_TYPE (declspecs->type))
          || TREE_CODE (declspecs->type) == ENUMERAL_TYPE))
     declared_type = declspecs->type;
@@ -3460,7 +3566,7 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
       /* Anonymous unions are objects, so they can have specifiers.  */;
       SET_ANON_AGGR_TYPE_P (declared_type);
 
-      if (TREE_CODE (declared_type) != UNION_TYPE && pedantic 
+      if (TREE_CODE (declared_type) != UNION_TYPE && pedantic
          && !in_system_header)
        pedwarn ("ISO C++ prohibits anonymous structs");
     }
@@ -3469,15 +3575,15 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
     {
       if (declspecs->specs[(int)ds_inline]
          || declspecs->specs[(int)ds_virtual])
-       error ("`%s' can only be specified for functions", 
-              declspecs->specs[(int)ds_inline] 
+       error ("%qs can only be specified for functions",
+              declspecs->specs[(int)ds_inline]
               ? "inline" : "virtual");
       else if (saw_friend
-              && (!current_class_type 
+              && (!current_class_type
                   || current_scope () != current_class_type))
-       error ("`friend' can only be specified inside a class");
+       error ("%<friend%> can only be specified inside a class");
       else if (declspecs->specs[(int)ds_explicit])
-       error ("`explicit' can only be specified for constructors");
+       error ("%<explicit%> can only be specified for constructors");
       else if (declspecs->storage_class)
        error ("a storage class can only be specified for objects "
               "and functions");
@@ -3501,7 +3607,7 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
    Otherwise, it is an error.
 
    C++: may have to grok the declspecs to learn about static,
-   complain for anonymous unions.  
+   complain for anonymous unions.
 
    Returns the TYPE declared -- or NULL_TREE if none.  */
 
@@ -3513,6 +3619,15 @@ shadow_tag (cp_decl_specifier_seq *declspecs)
   if (!t)
     return NULL_TREE;
 
+  if (declspecs->attributes)
+    {
+      cp_warning_at ("attribute ignored in declaration of %q#T", t);
+      cp_warning_at ("attribute for %q#T must follow the %qs keyword",
+                    t,
+                    class_key_or_enum_as_string (t));
+
+    }
+
   maybe_process_partial_specialization (t);
 
   /* This is where the variables in an anonymous union are
@@ -3526,7 +3641,7 @@ shadow_tag (cp_decl_specifier_seq *declspecs)
 
       if (TYPE_FIELDS (t))
        {
-         tree decl = grokdeclarator (/*declarator=*/NULL, 
+         tree decl = grokdeclarator (/*declarator=*/NULL,
                                      declspecs, NORMAL, 0, NULL);
          finish_anon_union (decl);
        }
@@ -3538,7 +3653,7 @@ shadow_tag (cp_decl_specifier_seq *declspecs)
 /* Decode a "typename", such as "int **", returning a ..._TYPE node.  */
 
 tree
-groktypename (cp_decl_specifier_seq *type_specifiers, 
+groktypename (cp_decl_specifier_seq *type_specifiers,
              const cp_declarator *declarator)
 {
   tree attrs;
@@ -3567,16 +3682,19 @@ groktypename (cp_decl_specifier_seq *type_specifiers,
    grokfield and not through here.  */
 
 tree
-start_decl (const cp_declarator *declarator, 
+start_decl (const cp_declarator *declarator,
            cp_decl_specifier_seq *declspecs,
-            int initialized, 
-            tree attributes, 
-            tree prefix_attributes)
+            int initialized,
+            tree attributes,
+            tree prefix_attributes, 
+           bool *pop_scope_p)
 {
   tree decl;
   tree type, tem;
   tree context;
 
+  *pop_scope_p = false;
   /* This should only be done once on the top most decl.  */
   if (have_extern_spec)
     {
@@ -3597,23 +3715,18 @@ start_decl (const cp_declarator *declarator,
   deprecated_state = DEPRECATED_NORMAL;
 
   if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
-    return NULL_TREE;
+    return error_mark_node;
 
   type = TREE_TYPE (decl);
 
   if (type == error_mark_node)
-    return NULL_TREE;
+    return error_mark_node;
 
   context = DECL_CONTEXT (decl);
 
-  if (initialized && context && TREE_CODE (context) == NAMESPACE_DECL
-      && context != current_namespace && TREE_CODE (decl) == VAR_DECL)
-    {
-      /* When parsing the initializer, lookup should use the object's
-        namespace.  */
-      push_decl_namespace (context);
-    }
-
+  if (context)
+    *pop_scope_p = push_scope (context);
+  
   /* We are only interested in class contexts, later.  */
   if (context && TREE_CODE (context) == NAMESPACE_DECL)
     context = NULL_TREE;
@@ -3625,12 +3738,12 @@ start_decl (const cp_declarator *declarator,
     switch (TREE_CODE (decl))
       {
       case TYPE_DECL:
-       error ("typedef `%D' is initialized (use __typeof__ instead)", decl);
+       error ("typedef %qD is initialized (use __typeof__ instead)", decl);
        initialized = 0;
        break;
 
       case FUNCTION_DECL:
-       error ("function `%#D' is initialized like a variable", decl);
+       error ("function %q#D is initialized like a variable", decl);
        initialized = 0;
        break;
 
@@ -3642,8 +3755,8 @@ start_decl (const cp_declarator *declarator,
     {
       if (! toplevel_bindings_p ()
          && DECL_EXTERNAL (decl))
-       warning ("declaration of `%#D' has `extern' and is initialized",
-                   decl);
+       warning ("declaration of %q#D has %<extern%> and is initialized",
+                 decl);
       DECL_EXTERNAL (decl) = 0;
       if (toplevel_bindings_p ())
        TREE_STATIC (decl) = 1;
@@ -3665,34 +3778,38 @@ start_decl (const cp_declarator *declarator,
       && DECL_DECLARED_INLINE_P (decl)
       && DECL_UNINLINABLE (decl)
       && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
-    warning ("%Jinline function '%D' given attribute noinline", decl, decl);
+    warning ("%Jinline function %qD given attribute noinline", decl, decl);
 
   if (context && COMPLETE_TYPE_P (complete_type (context)))
     {
-      push_nested_class (context);
-
       if (TREE_CODE (decl) == VAR_DECL)
        {
          tree field = lookup_field (context, DECL_NAME (decl), 0, false);
          if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
-           error ("`%#D' is not a static member of `%#T'", decl, context);
+           error ("%q#D is not a static member of %q#T", decl, context);
          else
            {
              if (DECL_CONTEXT (field) != context)
                {
                  if (!same_type_p (DECL_CONTEXT (field), context))
-                   pedwarn ("ISO C++ does not permit `%T::%D' to be defined as `%T::%D'",
+                   pedwarn ("ISO C++ does not permit %<%T::%D%> "
+                             "to be defined as %<%T::%D%>",
                             DECL_CONTEXT (field), DECL_NAME (decl),
                             context, DECL_NAME (decl));
                  DECL_CONTEXT (decl) = DECL_CONTEXT (field);
                }
+             if (processing_specialization
+                 && template_class_depth (context) == 0
+                 && CLASSTYPE_TEMPLATE_SPECIALIZATION (context))
+               error ("template header not allowed in member definition "
+                      "of explicitly specialized class");
              /* Static data member are tricky; an in-class initialization
                 still doesn't provide a definition, so the in-class
                 declaration will have DECL_EXTERNAL set, but will have an
                 initialization.  Thus, duplicate_decls won't warn
                 about this situation, and so we check here.  */
              if (DECL_INITIAL (decl) && DECL_INITIAL (field))
-               error ("duplicate initialization of %D", decl);
+               error ("duplicate initialization of %qD", decl);
              if (duplicate_decls (decl, field))
                decl = field;
            }
@@ -3725,8 +3842,8 @@ start_decl (const cp_declarator *declarator,
        }
 
       if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
-       pedwarn ("declaration of `%#D' outside of class is not definition",
-                   decl);
+       pedwarn ("declaration of %q#D outside of class is not definition",
+                 decl);
     }
 
   /* Enter this declaration into the symbol table.  */
@@ -3774,15 +3891,14 @@ start_decl_1 (tree decl)
        ;                       /* A complete type is ok.  */
       else if (TREE_CODE (type) != ARRAY_TYPE)
        {
-         error ("variable `%#D' has initializer but incomplete type",
-                   decl);
+         error ("variable %q#D has initializer but incomplete type", decl);
          initialized = 0;
          type = TREE_TYPE (decl) = error_mark_node;
        }
       else if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
        {
          if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
-           error ("elements of array `%#D' have incomplete type", decl);
+           error ("elements of array %q#D have incomplete type", decl);
          /* else we already gave an error in start_decl.  */
          initialized = 0;
        }
@@ -3798,7 +3914,7 @@ start_decl_1 (tree decl)
       if ((! processing_template_decl || ! uses_template_parms (type))
          && !COMPLETE_TYPE_P (complete_type (type)))
        {
-         error ("aggregate `%#D' has incomplete type and cannot be defined",
+         error ("aggregate %q#D has incomplete type and cannot be defined",
                 decl);
          /* Change the type so that assemble_variable will give
             DECL an rtl we can live with: (mem (const_int 0)).  */
@@ -3848,22 +3964,20 @@ grok_reference_init (tree decl, tree type, tree init, tree *cleanup)
       if ((DECL_LANG_SPECIFIC (decl) == 0
           || DECL_IN_AGGR_P (decl) == 0)
          && ! DECL_THIS_EXTERN (decl))
-       error ("`%D' declared as reference but not initialized", decl);
+       error ("%qD declared as reference but not initialized", decl);
       return NULL_TREE;
     }
 
   if (TREE_CODE (init) == CONSTRUCTOR)
     {
-      error ("ISO C++ forbids use of initializer list to initialize reference `%D'", decl);
+      error ("ISO C++ forbids use of initializer list to "
+             "initialize reference %qD", decl);
       return NULL_TREE;
     }
 
   if (TREE_CODE (init) == TREE_LIST)
     init = build_x_compound_expr_from_list (init, "initializer");
 
-  if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE)
-    init = convert_from_reference (init);
-
   if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
       && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
     /* Note: default conversion is only called in very special cases.  */
@@ -3882,7 +3996,7 @@ grok_reference_init (tree decl, tree type, tree init, tree *cleanup)
     return NULL_TREE;
   else if (tmp == NULL_TREE)
     {
-      error ("cannot initialize `%T' from `%T'", type, TREE_TYPE (init));
+      error ("cannot initialize %qT from %qT", type, TREE_TYPE (init));
       return NULL_TREE;
     }
 
@@ -3914,12 +4028,12 @@ maybe_deduce_size_from_array_init (tree decl, tree init)
       int failure = complete_array_type (type, initializer, do_default);
 
       if (failure == 1)
-       error ("initializer fails to determine size of `%D'", decl);
+       error ("initializer fails to determine size of %qD", decl);
 
       if (failure == 2)
        {
          if (do_default)
-           error ("array size missing in `%D'", decl);
+           error ("array size missing in %qD", decl);
          /* If a `static' var's size isn't known, make it extern as
             well as static, so it does not get allocated.  If it's not
             `static', then don't mark it extern; finish_incomplete_decl
@@ -3931,7 +4045,7 @@ maybe_deduce_size_from_array_init (tree decl, tree init)
       if (pedantic && TYPE_DOMAIN (type) != NULL_TREE
          && tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
                              integer_zero_node))
-       error ("zero-size array `%D'", decl);
+       error ("zero-size array %qD", decl);
 
       layout_decl (decl, 0);
     }
@@ -3955,10 +4069,10 @@ layout_var_decl (tree decl)
      `extern X x' for some incomplete type `X'.)  */
   if (!DECL_EXTERNAL (decl))
     complete_type (type);
-  if (!DECL_SIZE (decl) 
+  if (!DECL_SIZE (decl)
       && TREE_TYPE (decl) != error_mark_node
       && (COMPLETE_TYPE_P (type)
-         || (TREE_CODE (type) == ARRAY_TYPE 
+         || (TREE_CODE (type) == ARRAY_TYPE
              && !TYPE_DOMAIN (type)
              && COMPLETE_TYPE_P (TREE_TYPE (type)))))
     layout_decl (decl, 0);
@@ -3968,7 +4082,7 @@ layout_var_decl (tree decl)
       /* An automatic variable with an incomplete type: that is an error.
         Don't talk about array types here, since we took care of that
         message in grokdeclarator.  */
-      error ("storage size of `%D' isn't known", decl);
+      error ("storage size of %qD isn't known", decl);
       TREE_TYPE (decl) = error_mark_node;
     }
 #if 0
@@ -3990,7 +4104,7 @@ layout_var_decl (tree decl)
       if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
        constant_expression_warning (DECL_SIZE (decl));
       else
-       error ("storage size of `%D' isn't constant", decl);
+       error ("storage size of %qD isn't constant", decl);
     }
 
   if (TREE_STATIC (decl)
@@ -4015,7 +4129,7 @@ maybe_commonize_var (tree decl)
       && DECL_FUNCTION_SCOPE_P (decl)
       /* Unfortunately, import_export_decl has not always been called
         before the function is processed, so we cannot simply check
-        DECL_COMDAT.  */ 
+        DECL_COMDAT.  */
       && (DECL_COMDAT (DECL_CONTEXT (decl))
          || ((DECL_DECLARED_INLINE_P (DECL_CONTEXT (decl))
               || DECL_TEMPLATE_INSTANTIATION (DECL_CONTEXT (decl)))
@@ -4045,8 +4159,11 @@ maybe_commonize_var (tree decl)
                 be merged.  */
              TREE_PUBLIC (decl) = 0;
              DECL_COMMON (decl) = 0;
-             cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
-             warning ("%J  you can work around this by removing the initializer",
+             cp_warning_at ("sorry: semantics of inline function static "
+                             "data %q#D are wrong (you'll wind up "
+                             "with multiple copies)", decl);
+             warning ("%J  you can work around this by removing "
+                       "the initializer",
                       decl);
            }
        }
@@ -4072,7 +4189,7 @@ check_for_uninitialized_const_var (tree decl)
       && CP_TYPE_CONST_P (type)
       && !TYPE_NEEDS_CONSTRUCTING (type)
       && !DECL_INITIAL (decl))
-    error ("uninitialized const `%D'", decl);
+    error ("uninitialized const %qD", decl);
 }
 
 /* FIELD is a FIELD_DECL or NULL.  In the former case, the value
@@ -4092,13 +4209,76 @@ next_initializable_field (tree field)
   return field;
 }
 
+/* Subroutine of reshape_init. Reshape the constructor for an array. INITP
+   is the pointer to the old constructor list (to the CONSTRUCTOR_ELTS of
+   the CONSTRUCTOR we are processing), while NEW_INIT is the CONSTRUCTOR we
+   are building.
+   ELT_TYPE is the element type of the array. MAX_INDEX is an INTEGER_CST
+   representing the size of the array minus one (the maximum index), or
+   NULL_TREE if the array was declared without specifying the size.  */
+
+static bool
+reshape_init_array (tree elt_type, tree max_index,
+                   tree *initp, tree new_init)
+{
+  bool sized_array_p = (max_index != NULL_TREE);
+  HOST_WIDE_INT max_index_cst = 0;
+  HOST_WIDE_INT index;
+
+  if (sized_array_p)
+    /* HWI is either 32bit or 64bit, so it must be enough to represent the
+       array size.  */
+    max_index_cst = tree_low_cst (max_index, 1);
+
+  /* Loop until there are no more initializers.  */
+  for (index = 0;
+       *initp && (!sized_array_p || index <= max_index_cst);
+       ++index)
+    {
+      tree element_init;
+      tree designated_index;
+
+      element_init = reshape_init (elt_type, initp);
+      if (element_init == error_mark_node)
+       return false;
+      TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
+      CONSTRUCTOR_ELTS (new_init) = element_init;
+      designated_index = TREE_PURPOSE (element_init);
+      if (designated_index)
+      {
+         /* Handle array designated initializers (GNU extension).  */
+         if (TREE_CODE (designated_index) == IDENTIFIER_NODE)
+           {
+             error ("name %qD used in a GNU-style designated "
+                     "initializer for an array", designated_index);
+             TREE_PURPOSE (element_init) = NULL_TREE;
+           }
+         else
+           {
+             gcc_assert (TREE_CODE (designated_index) == INTEGER_CST);
+             if (sized_array_p
+                 && tree_int_cst_lt (max_index, designated_index))
+               {
+                 error ("Designated initializer %qE larger than array "
+                        "size", designated_index);
+                 TREE_PURPOSE (element_init) = NULL_TREE;
+               }
+             else
+               index = tree_low_cst (designated_index, 1);
+           }
+       }
+    }
+
+  return true;
+}
+
 /* Undo the brace-elision allowed by [dcl.init.aggr] in a
    brace-enclosed aggregate initializer.
 
    *INITP is one of a list of initializers describing a brace-enclosed
    initializer for an entity of the indicated aggregate TYPE.  It may
    not presently match the shape of the TYPE; for example:
-   
+
      struct S { int a; int b; };
      struct S a[] = { 1, 2, 3, 4 };
 
@@ -4120,7 +4300,7 @@ reshape_init (tree type, tree *initp)
   old_init_value = (TREE_CODE (*initp) == TREE_LIST
                    ? TREE_VALUE (*initp) : old_init);
 
-  my_friendly_assert (old_init_value, 20030723);
+  gcc_assert (old_init_value);
 
   /* If the initializer is brace-enclosed, pull initializers from the
      enclosed elements.  Advance past the brace-enclosed initializer
@@ -4150,14 +4330,14 @@ reshape_init (tree type, tree *initp)
           brace-enclosed initializer.  */
        if (brace_enclosed_p)
          {
-           error ("brace-enclosed initializer used to initialize `%T'",
+           error ("brace-enclosed initializer used to initialize %qT",
                   type);
            if (TREE_CODE (old_init) == TREE_LIST)
              TREE_VALUE (old_init) = error_mark_node;
            else
              old_init = error_mark_node;
          }
-       
+
        return old_init;
       }
 
@@ -4195,7 +4375,7 @@ reshape_init (tree type, tree *initp)
     }
   else
     {
-      /* Build a CONSTRUCTOR to hold the contents of the aggregate.  */  
+      /* Build a CONSTRUCTOR to hold the contents of the aggregate.  */
       new_init = build_constructor (NULL_TREE, NULL_TREE);
 
       if (CLASS_TYPE_P (type))
@@ -4207,14 +4387,13 @@ reshape_init (tree type, tree *initp)
          if (!field)
            {
              /* [dcl.init.aggr]
-             
+
                 An initializer for an aggregate member that is an
                 empty class shall have the form of an empty
                 initializer-list {}.  */
              if (!brace_enclosed_p)
                {
-                 error ("initializer for `%T' must be brace-enclosed",
-                        type);
+                 error ("initializer for %qT must be brace-enclosed", type);
                  return error_mark_node;
                }
            }
@@ -4234,7 +4413,7 @@ reshape_init (tree type, tree *initp)
                      field = lookup_field_1 (type, TREE_PURPOSE (*initp),
                                              /*want_type=*/false);
                      if (!field || TREE_CODE (field) != FIELD_DECL)
-                       error ("`%T' has no non-static data member named `%D'",
+                       error ("%qT has no non-static data member named %qD",
                               type, TREE_PURPOSE (*initp));
                    }
                  if (!field)
@@ -4245,7 +4424,7 @@ reshape_init (tree type, tree *initp)
                    return error_mark_node;
                  TREE_CHAIN (field_init) = CONSTRUCTOR_ELTS (new_init);
                  CONSTRUCTOR_ELTS (new_init) = field_init;
-                 /* [dcl.init.aggr] 
+                 /* [dcl.init.aggr]
 
                     When a union  is  initialized with a brace-enclosed
                     initializer, the braces shall only contain an
@@ -4259,55 +4438,31 @@ reshape_init (tree type, tree *initp)
       else if (TREE_CODE (type) == ARRAY_TYPE
               || TREE_CODE (type) == VECTOR_TYPE)
        {
-         tree index;
-         tree max_index;
-
-         /* If the bound of the array is known, take no more initializers
-            than are allowed.  */
-         max_index = NULL_TREE;
-         if (TREE_CODE (type) == ARRAY_TYPE)
-           {
-             if (TYPE_DOMAIN (type))
-               max_index = array_type_nelts (type);
-           }
-         else
-           {
-             /* For a vector, the representation type is a struct
-                containing a single member which is an array of the
-                appropriate size.  */
-             tree rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type);
-             if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype))))
-               max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS (rtype)));
-           }
+           /* If the bound of the array is known, take no more initializers
+             than are allowed.  */
+           tree max_index = NULL_TREE;
+           if (TREE_CODE (type) == ARRAY_TYPE)
+             {
+               if (TYPE_DOMAIN (type))
+                 max_index = array_type_nelts (type);
+             }
+           else
+             {
+               /* For a vector, the representation type is a struct
+                 containing a single member which is an array of the
+                 appropriate size.  */
+               tree rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type);
+               if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype))))
+                 max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS
+                                                          (rtype)));
+             }
 
-         /* Loop through the array elements, gathering initializers.  */
-         for (index = size_zero_node;
-              *initp && (!max_index || !tree_int_cst_lt (max_index, index));
-              index = size_binop (PLUS_EXPR, index, size_one_node))
-           {
-             tree element_init;
-
-             element_init = reshape_init (TREE_TYPE (type), initp);
-             if (element_init == error_mark_node)
-               return error_mark_node;
-             TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
-             CONSTRUCTOR_ELTS (new_init) = element_init;
-             if (TREE_PURPOSE (element_init))
-               {
-                 tree next_index = TREE_PURPOSE (element_init);
-                 if (TREE_CODE (next_index) == IDENTIFIER_NODE)
-                   {
-                     error ("name `%D' used in a GNU-style designated "
-                            "initializer for an array", next_index);
-                     TREE_PURPOSE (element_init) = NULL_TREE;
-                   }
-                 else
-                   index = next_index;
-               }
-           }
+         if (!reshape_init_array (TREE_TYPE (type), max_index,
+                                  initp, new_init))
+           return error_mark_node;
        }
       else
-       abort ();
+       gcc_unreachable ();
 
       /* The initializers were placed in reverse order in the
         CONSTRUCTOR.  */
@@ -4320,7 +4475,7 @@ reshape_init (tree type, tree *initp)
   /* If this was a brace-enclosed initializer and all of the
      initializers were not used up, there is a problem.  */
   if (brace_enclosed_p && *initp)
-    error ("too many initializers for `%T'", type);
+    error ("too many initializers for %qT", type);
 
   return new_init;
 }
@@ -4355,39 +4510,39 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
   if (type == error_mark_node)
     /* We will have already complained.  */
     init = NULL_TREE;
-  else if (init && COMPLETE_TYPE_P (type) 
+  else if (init && COMPLETE_TYPE_P (type)
           && !TREE_CONSTANT (TYPE_SIZE (type)))
     {
-      error ("variable-sized object `%D' may not be initialized", decl);
+      error ("variable-sized object %qD may not be initialized", decl);
       init = NULL_TREE;
     }
   else if (TREE_CODE (type) == ARRAY_TYPE
           && !COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
     {
-      error ("elements of array `%#D' have incomplete type", decl);
+      error ("elements of array %q#D have incomplete type", decl);
       init = NULL_TREE;
     }
   else if (TREE_CODE (type) != ARRAY_TYPE && !COMPLETE_TYPE_P (type))
     {
-      error ("`%D' has incomplete type", decl);
+      error ("%qD has incomplete type", decl);
       TREE_TYPE (decl) = error_mark_node;
       init = NULL_TREE;
     }
 
   if (TREE_CODE (decl) == CONST_DECL)
     {
-      my_friendly_assert (TREE_CODE (decl) != REFERENCE_TYPE, 148);
+      gcc_assert (TREE_CODE (decl) != REFERENCE_TYPE);
 
       DECL_INITIAL (decl) = init;
 
-      my_friendly_assert (init != NULL_TREE, 149);
+      gcc_assert (init != NULL_TREE);
       init = NULL_TREE;
     }
   else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
     init = grok_reference_init (decl, type, init, cleanup);
   else if (init)
     {
-      if (TREE_CODE (init) == CONSTRUCTOR 
+      if (TREE_CODE (init) == CONSTRUCTOR
          && BRACE_ENCLOSED_INITIALIZER_P (init))
        {
          /* [dcl.init] paragraph 13,
@@ -4395,7 +4550,7 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
             T x = { a };
             is equivalent to
             T x = a;
-            
+
             reshape_init will complain about the extra braces,
             and doesn't do anything useful in the case where TYPE is
             scalar, so just don't call it.  */
@@ -4423,7 +4578,8 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
            {
              if (TYPE_NON_AGGREGATE_CLASS (type))
                {
-                 error ("`%D' must be initialized by constructor, not by `{...}'",
+                 error ("%qD must be initialized by constructor, "
+                         "not by %<{...}%>",
                         decl);
                  init = error_mark_node;
                }
@@ -4454,6 +4610,12 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
          if (TREE_CODE (init) != TREE_VEC)
            {
              init_code = store_init_value (decl, init);
+             if (pedantic && TREE_CODE (type) == ARRAY_TYPE
+                 && DECL_INITIAL (decl)
+                 && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
+                 && PAREN_STRING_LITERAL_P (DECL_INITIAL (decl)))
+               warning ("array %qD initialized by parenthesized string literal %qE",
+                        decl, DECL_INITIAL (decl));
              init = NULL;
            }
        }
@@ -4467,10 +4629,9 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
       tree core_type = strip_array_types (type);
 
       if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
-       error ("structure `%D' with uninitialized const members", decl);
+       error ("structure %qD with uninitialized const members", decl);
       if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
-       error ("structure `%D' with uninitialized reference members",
-              decl);
+       error ("structure %qD with uninitialized reference members", decl);
 
       check_for_uninitialized_const_var (decl);
     }
@@ -4478,7 +4639,7 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
     check_for_uninitialized_const_var (decl);
 
   if (init && init != error_mark_node)
-    init_code = build (INIT_EXPR, type, decl, init);
+    init_code = build2 (INIT_EXPR, type, decl, init);
 
   return init_code;
 }
@@ -4491,10 +4652,30 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
   int toplev = toplevel_bindings_p ();
   int defer_p;
 
+  /* Set the DECL_ASSEMBLER_NAME for the object.  */
+  if (asmspec)
+    {
+      /* The `register' keyword, when used together with an
+        asm-specification, indicates that the variable should be
+        placed in a particular register.  */
+      if (TREE_CODE (decl) == VAR_DECL && DECL_REGISTER (decl))
+       {
+         change_decl_assembler_name (decl, get_identifier (asmspec));
+         DECL_HARD_REGISTER (decl) = 1;
+       }
+      else
+       {
+         if (TREE_CODE (decl) == FUNCTION_DECL
+             && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
+           set_builtin_user_assembler_name (decl, asmspec);
+         set_user_assembler_name (decl, asmspec);
+       }
+    }
+
   /* Handle non-variables up front.  */
   if (TREE_CODE (decl) != VAR_DECL)
     {
-      rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
+      rest_of_decl_compilation (decl, toplev, at_eof);
       return;
     }
 
@@ -4502,22 +4683,11 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
      member.  */
   if (DECL_LANG_SPECIFIC (decl) && DECL_IN_AGGR_P (decl))
     {
-      my_friendly_assert (TREE_STATIC (decl), 19990828);
+      gcc_assert (TREE_STATIC (decl));
       /* An in-class declaration of a static data member should be
         external; it is only a declaration, and not a definition.  */
       if (init == NULL_TREE)
-       my_friendly_assert (DECL_EXTERNAL (decl), 20000723);
-    }
-
-  /* Set the DECL_ASSEMBLER_NAME for the variable.  */
-  if (asmspec)
-    {
-      change_decl_assembler_name (decl, get_identifier (asmspec));
-      /* The `register' keyword, when used together with an
-        asm-specification, indicates that the variable should be
-        placed in a particular register.  */
-      if (DECL_REGISTER (decl))
-       DECL_HARD_REGISTER (decl) = 1;
+       gcc_assert (DECL_EXTERNAL (decl));
     }
 
   /* We don't create any RTL for local variables.  */
@@ -4540,28 +4710,23 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
     {
       /* Fool with the linkage of static consts according to #pragma
         interface.  */
-      if (!interface_unknown && !TREE_PUBLIC (decl))
+      struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename));
+      if (!finfo->interface_unknown && !TREE_PUBLIC (decl))
        {
          TREE_PUBLIC (decl) = 1;
-         DECL_EXTERNAL (decl) = interface_only;
+         DECL_EXTERNAL (decl) = finfo->interface_only;
        }
 
       defer_p = 1;
     }
   /* Likewise for template instantiations.  */
-  else if (DECL_COMDAT (decl))
+  else if (DECL_LANG_SPECIFIC (decl)
+          && DECL_IMPLICIT_INSTANTIATION (decl))
     defer_p = 1;
 
-  /* If we're deferring the variable, we only need to make RTL if
-     there's an ASMSPEC.  Otherwise, we'll lazily create it later when
-     we need it.  (There's no way to lazily create RTL for things that
-     have assembly specs because the information about the specifier
-     isn't stored in the tree, yet)  */
-  if (defer_p && asmspec)
-    make_decl_rtl (decl, asmspec);
   /* If we're not deferring, go ahead and assemble the variable.  */
-  else if (!defer_p)
-    rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
+  if (!defer_p)
+    rest_of_decl_compilation (decl, toplev, at_eof);
 }
 
 /* Generate code to initialize DECL (a local variable).  */
@@ -4572,10 +4737,9 @@ initialize_local_var (tree decl, tree init)
   tree type = TREE_TYPE (decl);
   tree cleanup;
 
-  my_friendly_assert (TREE_CODE (decl) == VAR_DECL
-                     || TREE_CODE (decl) == RESULT_DECL, 
-                     20021010);
-  my_friendly_assert (!TREE_STATIC (decl), 20021010);
+  gcc_assert (TREE_CODE (decl) == VAR_DECL
+             || TREE_CODE (decl) == RESULT_DECL);
+  gcc_assert (!TREE_STATIC (decl));
 
   if (DECL_SIZE (decl) == NULL_TREE)
     {
@@ -4596,7 +4760,7 @@ initialize_local_var (tree decl, tree init)
        {
          int saved_stmts_are_full_exprs_p;
 
-         my_friendly_assert (building_stmt_tree (), 20000906);
+         gcc_assert (building_stmt_tree ());
          saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
          current_stmt_tree ()->stmts_are_full_exprs_p = 1;
          finish_expr_stmt (init);
@@ -4625,6 +4789,22 @@ initialize_local_var (tree decl, tree init)
     finish_decl_cleanup (decl, cleanup);
 }
 
+/* DECL is a VAR_DECL for a compiler-generated variable with static
+   storage duration (like a virtual table) whose initializer is a
+   compile-time constant.  Initialize the variable and provide it to
+   the back end.  */
+
+void
+initialize_artificial_var (tree decl, tree init)
+{
+  DECL_INITIAL (decl) = build_constructor (NULL_TREE, init);
+  DECL_INITIALIZED_P (decl) = 1;
+  determine_visibility (decl);
+  layout_var_decl (decl);
+  maybe_commonize_var (decl);
+  make_rtl_for_nonlocal_decl (decl, init, /*asmspec=*/NULL);
+}
+
 /* Finish processing of a declaration;
    install its line number and initial value.
    If the length of an array type is not known before,
@@ -4644,6 +4824,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
   tree cleanup;
   const char *asmspec = NULL;
   int was_readonly = 0;
+  bool var_definition_p = false;
 
   if (decl == error_mark_node)
     return;
@@ -4654,7 +4835,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
       return;
     }
 
-  my_friendly_assert (TREE_CODE (decl) != RESULT_DECL, 20030619);
+  gcc_assert (TREE_CODE (decl) != RESULT_DECL);
 
   /* Assume no cleanup is required.  */
   cleanup = NULL_TREE;
@@ -4662,13 +4843,12 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
   /* If a name was specified, get the string.  */
   if (global_scope_p (current_binding_level))
     asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
-  if (asmspec_tree) 
+  if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
 
   if (init && TREE_CODE (init) == NAMESPACE_DECL)
     {
-      error ("cannot initialize `%D' to namespace `%D'",
-               decl, init);
+      error ("cannot initialize %qD to namespace %qD", decl, init);
       init = NULL_TREE;
     }
 
@@ -4678,20 +4858,10 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
       && (DECL_INITIAL (decl) || init))
     DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
 
-  if (TREE_CODE (decl) == VAR_DECL
-      && DECL_CONTEXT (decl)
-      && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL
-      && DECL_CONTEXT (decl) != current_namespace
-      && init)
-    {
-      /* Leave the namespace of the object.  */
-      pop_decl_namespace ();
-    }
-
   type = TREE_TYPE (decl);
 
   if (type == error_mark_node)
-    goto finish_end0;
+    goto finish_end;
 
   if (TYPE_HAS_MUTABLE_P (type))
     TREE_READONLY (decl) = 0;
@@ -4708,11 +4878,12 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
          && !DECL_PRETTY_FUNCTION_P (decl)
          && !dependent_type_p (TREE_TYPE (decl)))
        maybe_deduce_size_from_array_init (decl, init);
-      goto finish_end0;
+      
+      goto finish_end;
     }
 
   /* Parameters are handled by store_parm_decls, not cp_finish_decl.  */
-  my_friendly_assert (TREE_CODE (decl) != PARM_DECL, 19990828);
+  gcc_assert (TREE_CODE (decl) != PARM_DECL);
 
   /* Take care of TYPE_DECLs up front.  */
   if (TREE_CODE (decl) == TYPE_DECL)
@@ -4721,7 +4892,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
          && IS_AGGR_TYPE (type) && DECL_NAME (decl))
        {
          if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
-           warning ("shadowing previous type declaration of `%#D'", decl);
+           warning ("shadowing previous type declaration of %q#D", decl);
          set_identifier_type_value (DECL_NAME (decl), decl);
        }
 
@@ -4732,15 +4903,15 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
          && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
        TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
 
-      rest_of_decl_compilation (decl, NULL,
-                               DECL_CONTEXT (decl) == NULL_TREE, at_eof);
+      rest_of_decl_compilation (decl, DECL_CONTEXT (decl) == NULL_TREE,
+                               at_eof);
       goto finish_end;
     }
 
   if (TREE_CODE (decl) != FUNCTION_DECL)
     ttype = target_type (type);
 
-  
+
   /* Currently, GNU C++ puts constants in text space, making them
      impossible to initialize.  In the future, one would hope for
      an operating system which understood the difference between
@@ -4748,7 +4919,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
   if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl))
     {
       was_readonly = 1;
-      if (TYPE_NEEDS_CONSTRUCTING (type) 
+      if (TYPE_NEEDS_CONSTRUCTING (type)
          || TREE_CODE (type) == REFERENCE_TYPE)
        TREE_READONLY (decl) = 0;
     }
@@ -4758,7 +4929,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
       /* Only PODs can have thread-local storage.  Other types may require
         various kinds of non-trivial initialization.  */
       if (DECL_THREAD_LOCAL (decl) && !pod_type_p (TREE_TYPE (decl)))
-       error ("`%D' cannot be thread-local because it has non-POD type `%T'",
+       error ("%qD cannot be thread-local because it has non-POD type %qT",
               decl, TREE_TYPE (decl));
       /* Convert the initializer to the type of DECL, if we have not
         already initialized DECL.  */
@@ -4773,18 +4944,18 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
          /* Thread-local storage cannot be dynamically initialized.  */
          if (DECL_THREAD_LOCAL (decl) && init)
            {
-             error ("`%D' is thread-local and so cannot be dynamically "
+             error ("%qD is thread-local and so cannot be dynamically "
                     "initialized", decl);
              init = NULL_TREE;
            }
          /* Handle:
-            
+
             [dcl.init]
-            
+
             The memory occupied by any object of static storage
             duration is zero-initialized at program startup before
             any other initialization takes place.
-            
+
             We cannot create an appropriate initializer until after
             the type of DECL is finalized.  If DECL_INITIAL is set,
             then the DECL is statically initialized, and any
@@ -4796,6 +4967,14 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
          /* Remember that the initialization for this variable has
             taken place.  */
          DECL_INITIALIZED_P (decl) = 1;
+         /* This declaration is the definition of this variable,
+            unless we are initializing a static data member within
+            the class specifier.  */
+         if (!DECL_EXTERNAL (decl))
+           var_definition_p = true;
+         /* The variable is being defined, so determine its
+            visibility.  */
+         determine_visibility (decl);
        }
       /* If the variable has an array type, lay out the type, even if
         there is no initializer.  It is valid to index through the
@@ -4833,7 +5012,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
       else
        abstract_virtuals_error (decl, type);
 
-      if (TREE_CODE (decl) == FUNCTION_DECL 
+      if (TREE_CODE (decl) == FUNCTION_DECL
          || TREE_TYPE (decl) == error_mark_node)
        /* No initialization required.  */
        ;
@@ -4858,30 +5037,18 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
              else if (!TREE_STATIC (decl))
                initialize_local_var (decl, init);
            }
-
-         if (TREE_STATIC (decl))
-           expand_static_init (decl, init);
-       }
-    finish_end0:
-
-      /* Undo call to `pushclass' that was done in `start_decl'
-        due to initialization of qualified member variable.
-        I.e., Foo::x = 10;  */
-      {
-       tree context = CP_DECL_CONTEXT (decl);
-       if (context
-           && TYPE_P (context)
-           && (TREE_CODE (decl) == VAR_DECL
-               /* We also have a pushclass done that we need to undo here
-                  if we're at top level and declare a method.  */
-               || TREE_CODE (decl) == FUNCTION_DECL)
-           /* If size hasn't been set, we're still defining it,
-              and therefore inside the class body; don't pop
-              the binding level..  */
-           && COMPLETE_TYPE_P (context)
-           && context == current_class_type)
-         pop_nested_class ();
-      }
+         
+         /* If a variable is defined, and then a subsequent
+            definition with external linkage is encountered, we will
+            get here twice for the same variable.  We want to avoid
+            calling expand_static_init more than once.  For variables
+            that are not static data members, we can call
+            expand_static_init only when we actually process the
+            initializer.  It is not legal to redeclare a static data
+            member, so this issue does not arise in that case.  */
+         if (var_definition_p && TREE_STATIC (decl))
+           expand_static_init (decl, init); 
+       } 
     }
 
   /* If a CLEANUP_STMT was created to destroy a temporary bound to a
@@ -4924,7 +5091,11 @@ declare_global_var (tree name, tree type)
   TREE_PUBLIC (decl) = 1;
   DECL_EXTERNAL (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
-  pushdecl (decl);
+  /* If the user has explicitly declared this variable (perhaps
+     because the code we are compiling is part of a low-level runtime
+     library), then it is possible that our declaration will be merged
+     with theirs by pushdecl.  */
+  decl = pushdecl (decl);
   cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0);
   pop_from_top_level ();
 
@@ -5019,8 +5190,6 @@ static GTY(()) int start_cleanup_cnt;
 static tree
 start_cleanup_fn (void)
 {
-  int old_interface_only = interface_only;
-  int old_interface_unknown = interface_unknown;
   char name[32];
   tree parmtypes;
   tree fntype;
@@ -5031,9 +5200,6 @@ start_cleanup_fn (void)
   /* No need to mangle this.  */
   push_lang_context (lang_name_c);
 
-  interface_only = 0;
-  interface_unknown = 1;
-
   /* Build the parameter-types.  */
   parmtypes = void_list_node;
   /* Functions passed to __cxa_atexit take an additional parameter.
@@ -5073,9 +5239,6 @@ start_cleanup_fn (void)
   pushdecl (fndecl);
   start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED);
 
-  interface_unknown = old_interface_unknown;
-  interface_only = old_interface_only;
-
   pop_lang_context ();
 
   return current_function_decl;
@@ -5094,7 +5257,7 @@ end_cleanup_fn (void)
 /* Generate code to handle the destruction of DECL, an object with
    static storage duration.  */
 
-void
+tree
 register_dtor_fn (tree decl)
 {
   tree cleanup;
@@ -5103,7 +5266,7 @@ register_dtor_fn (tree decl)
   tree fcall;
 
   if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
-    return;
+    return void_zero_node;
 
   /* Call build_cleanup before we enter the anonymous function so that
      any access checks will be done relative to the current scope,
@@ -5117,7 +5280,7 @@ register_dtor_fn (tree decl)
      to the original function, rather than the anonymous one.  That
      will make the back-end think that nested functions are in use,
      which causes confusion.  */
-  
+
   push_deferring_access_checks (dk_no_check);
   fcall = build_cleanup (decl);
   pop_deferring_access_checks ();
@@ -5134,7 +5297,7 @@ register_dtor_fn (tree decl)
   cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
   if (flag_use_cxa_atexit)
     {
-      args = tree_cons (NULL_TREE, 
+      args = tree_cons (NULL_TREE,
                        build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0),
                        NULL_TREE);
       args = tree_cons (NULL_TREE, null_pointer_node, args);
@@ -5142,7 +5305,7 @@ register_dtor_fn (tree decl)
     }
   else
     args = tree_cons (NULL_TREE, cleanup, NULL_TREE);
-  finish_expr_stmt (build_function_call (get_atexit_node (), args));
+  return build_function_call (get_atexit_node (), args);
 }
 
 /* DECL is a VAR_DECL with static storage duration.  INIT, if present,
@@ -5152,82 +5315,136 @@ register_dtor_fn (tree decl)
 static void
 expand_static_init (tree decl, tree init)
 {
-  my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20021010);
-  my_friendly_assert (TREE_STATIC (decl), 20021010);
+  gcc_assert (TREE_CODE (decl) == VAR_DECL);
+  gcc_assert (TREE_STATIC (decl));
 
   /* Some variables require no initialization.  */
-  if (!init 
+  if (!init
       && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
       && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
     return;
 
-  if (! toplevel_bindings_p ())
+  if (DECL_FUNCTION_SCOPE_P (decl))
     {
       /* Emit code to perform this initialization but once.  */
-      tree if_stmt;
-      tree then_clause;
-      tree assignment;
-      tree guard;
-      tree guard_init;
+      tree if_stmt = NULL_TREE, inner_if_stmt = NULL_TREE;
+      tree then_clause = NULL_TREE, inner_then_clause = NULL_TREE;
+      tree guard, guard_addr, guard_addr_list;
+      tree acquire_fn, release_fn, abort_fn;
+      tree flag, begin;
 
       /* Emit code to perform this initialization but once.  This code
         looks like:
 
-           static int guard = 0;
-           if (!guard) {
-             // Do initialization.
-            guard = 1;
-            // Register variable for destruction at end of program.
+           static <type> guard;
+           if (!guard.first_byte) {
+            if (__cxa_guard_acquire (&guard)) {
+              bool flag = false;
+              try {
+                // Do initialization.
+                flag = true; __cxa_guard_release (&guard);
+                // Register variable for destruction at end of program.
+              } catch {
+                if (!flag) __cxa_guard_abort (&guard);
+              }
           }
 
-        Note that the `temp' variable is only set to 1 *after* the
+        Note that the `flag' variable is only set to 1 *after* the
         initialization is complete.  This ensures that an exception,
         thrown during the construction, will cause the variable to
         reinitialized when we pass through this code again, as per:
 
           [stmt.dcl]
 
-          If the initialization exits by throwing an exception, the
+          If the initialization exits by throwing an exception, the  
           initialization is not complete, so it will be tried again
           the next time control enters the declaration.
 
-         In theory, this process should be thread-safe, too; multiple
-        threads should not be able to initialize the variable more
-        than once.  We don't yet attempt to ensure thread-safety.  */
+         This process should be thread-safe, too; multiple threads
+        should not be able to initialize the variable more than
+        once.  */
 
       /* Create the guard variable.  */
       guard = get_guard (decl);
 
-      /* Begin the conditional initialization.  */
-      if_stmt = begin_if_stmt ();
-      finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
-      then_clause = begin_compound_stmt (0);
-
-      /* Do the initialization itself.  */
-      assignment = init ? init : NULL_TREE;
-
-      /* Once the assignment is complete, set TEMP to 1.  Since the
-        construction of the static object is complete at this point,
-        we want to make sure TEMP is set to 1 even if a temporary
-        constructed during the initialization throws an exception
-        when it is destroyed.  So, we combine the initialization and
-        the assignment to TEMP into a single expression, ensuring
-        that when we call finish_expr_stmt the cleanups will not be
-        run until after TEMP is set to 1.  */
-      guard_init = set_guard (guard);
-      if (assignment)
-       assignment = build_compound_expr (assignment, guard_init);
+      /* This optimization isn't safe on targets with relaxed memory
+        consistency.  On such targets we force synchronization in
+        __cxa_guard_acquire.  */
+      if (!targetm.relaxed_ordering || !flag_threadsafe_statics)
+       {
+         /* Begin the conditional initialization.  */
+         if_stmt = begin_if_stmt ();
+         finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
+         then_clause = begin_compound_stmt (BCS_NO_SCOPE);
+       }
+
+      if (flag_threadsafe_statics)
+       {
+         guard_addr = build_address (guard);
+         guard_addr_list = build_tree_list (NULL_TREE, guard_addr);
+
+         acquire_fn = get_identifier ("__cxa_guard_acquire");
+         release_fn = get_identifier ("__cxa_guard_release");
+         abort_fn = get_identifier ("__cxa_guard_abort");
+         if (!get_global_value_if_present (acquire_fn, &acquire_fn))
+           {
+             tree argtypes = tree_cons (NULL_TREE, TREE_TYPE (guard_addr),
+                                        void_list_node);
+             tree vfntype = build_function_type (void_type_node, argtypes);
+             acquire_fn = push_library_fn
+               (acquire_fn, build_function_type (integer_type_node, argtypes));
+             release_fn = push_library_fn (release_fn, vfntype);
+             abort_fn = push_library_fn (abort_fn, vfntype);
+           }
+         else
+           {
+             release_fn = identifier_global_value (release_fn);
+             abort_fn = identifier_global_value (abort_fn);
+           }
+
+         inner_if_stmt = begin_if_stmt ();
+         finish_if_stmt_cond (build_call (acquire_fn, guard_addr_list),
+                              inner_if_stmt);
+
+         inner_then_clause = begin_compound_stmt (BCS_NO_SCOPE);
+         begin = get_target_expr (boolean_false_node);
+         flag = TARGET_EXPR_SLOT (begin);
+
+         TARGET_EXPR_CLEANUP (begin)
+           = build (COND_EXPR, void_type_node, flag,
+                    void_zero_node,
+                    build_call (abort_fn, guard_addr_list));
+         CLEANUP_EH_ONLY (begin) = 1;
+
+         /* Do the initialization itself.  */
+         init = add_stmt_to_compound (begin, init);
+         init = add_stmt_to_compound
+           (init, build (MODIFY_EXPR, void_type_node, flag, boolean_true_node));
+         init = add_stmt_to_compound
+           (init, build_call (release_fn, guard_addr_list));
+       }
       else
-       assignment = guard_init;
-      finish_expr_stmt (assignment);
+       init = add_stmt_to_compound (init, set_guard (guard));
 
       /* Use atexit to register a function for destroying this static
         variable.  */
-      register_dtor_fn (decl);
+      init = add_stmt_to_compound (init, register_dtor_fn (decl));
 
-      finish_compound_stmt (then_clause);
-      finish_then_clause (if_stmt);
-      finish_if_stmt (if_stmt);
+      finish_expr_stmt (init);
+
+      if (flag_threadsafe_statics)
+       {
+         finish_compound_stmt (inner_then_clause);
+         finish_then_clause (inner_if_stmt);
+         finish_if_stmt (inner_if_stmt);
+       }
+
+      if (!targetm.relaxed_ordering || !flag_threadsafe_statics)
+       {
+         finish_compound_stmt (then_clause);
+         finish_then_clause (if_stmt);
+         finish_if_stmt (if_stmt);
+       }
     }
   else
     static_aggregates = tree_cons (init, decl, static_aggregates);
@@ -5262,8 +5479,9 @@ complete_array_type (tree type, tree initial_value, int do_default)
        {
          int eltsize
            = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
-         maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value)
-                                  / eltsize) - 1, 0);
+         maxindex = build_int_cst (NULL_TREE,
+                                   (TREE_STRING_LENGTH (initial_value)
+                                    / eltsize) - 1);
        }
       else if (TREE_CODE (initial_value) == CONSTRUCTOR)
        {
@@ -5277,7 +5495,6 @@ complete_array_type (tree type, tree initial_value, int do_default)
              else
                maxindex = size_binop (PLUS_EXPR, maxindex, ssize_int (1));
            }
-         maxindex = copy_node (maxindex);
        }
       else
        {
@@ -5288,14 +5505,14 @@ complete_array_type (tree type, tree initial_value, int do_default)
            initial_value = NULL_TREE;
 
          /* Prevent further error messages.  */
-         maxindex = build_int_2 (0, 0);
+         maxindex = build_int_cst (NULL_TREE, 0);
        }
     }
 
   if (!maxindex)
     {
       if (do_default)
-       maxindex = build_int_2 (0, 0);
+       maxindex = build_int_cst (NULL_TREE, 0);
       value = 2;
     }
 
@@ -5308,8 +5525,6 @@ complete_array_type (tree type, tree initial_value, int do_default)
       domain = build_index_type (maxindex);
       TYPE_DOMAIN (type) = domain;
 
-      if (! TREE_TYPE (maxindex))
-       TREE_TYPE (maxindex) = domain;
       if (initial_value)
         itype = TREE_TYPE (initial_value);
       else
@@ -5326,7 +5541,7 @@ complete_array_type (tree type, tree initial_value, int do_default)
       TYPE_NEEDS_CONSTRUCTING (type)
        = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
       TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
-       = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));      
+       = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));
     }
 
   /* Lay out the type now that we can get the real answer.  */
@@ -5346,11 +5561,9 @@ member_function_or_else (tree ctype, tree cur_type, enum overload_flags flags)
   if (ctype && ctype != cur_type)
     {
       if (flags == DTOR_FLAG)
-       error ("destructor for alien class `%T' cannot be a member",
-                 ctype);
+       error ("destructor for alien class %qT cannot be a member", ctype);
       else
-       error ("constructor for alien class `%T' cannot be a member",
-                 ctype);
+       error ("constructor for alien class %qT cannot be a member", ctype);
       return 0;
     }
   return 1;
@@ -5371,20 +5584,21 @@ bad_specifiers (tree object,
                 int raises)
 {
   if (virtualp)
-    error ("`%D' declared as a `virtual' %s", object, type);
+    error ("%qD declared as a %<virtual%> %s", object, type);
   if (inlinep)
-    error ("`%D' declared as an `inline' %s", object, type);
+    error ("%qD declared as an %<inline%> %s", object, type);
   if (quals)
-    error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration",
-             object, type);
+    error ("%<const%> and %<volatile%> function specifiers on "
+           "%qD invalid in %s declaration",
+           object, type);
   if (friendp)
-    cp_error_at ("`%D' declared as a friend", object);
+    cp_error_at ("%qD declared as a friend", object);
   if (raises
       && (TREE_CODE (object) == TYPE_DECL
          || (!TYPE_PTRFN_P (TREE_TYPE (object))
              && !TYPE_REFFN_P (TREE_TYPE (object))
              && !TYPE_PTRMEMFUNC_P (TREE_TYPE (object)))))
-    cp_error_at ("`%D' declared with an exception specification", object);
+    cp_error_at ("%qD declared with an exception specification", object);
 }
 
 /* CTYPE is class type, or null if non-class.
@@ -5404,7 +5618,7 @@ bad_specifiers (tree object,
    applicable error messages.  */
 
 static tree
-grokfndecl (tree ctype, 
+grokfndecl (tree ctype,
             tree type,
             tree declarator,
            tree parms,
@@ -5413,13 +5627,14 @@ grokfndecl (tree ctype,
             enum overload_flags flags,
            cp_cv_quals quals,
             tree raises,
-            int check, 
-            int friendp, 
-            int publicp, 
-            int inlinep, 
-            int funcdef_flag, 
+            int check,
+            int friendp,
+            int publicp,
+            int inlinep,
+            int funcdef_flag,
             int template_count,
-            tree in_namespace)
+            tree in_namespace,
+           tree* attrlist)
 {
   tree decl;
   int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
@@ -5466,14 +5681,17 @@ grokfndecl (tree ctype,
   if (ctype == NULL_TREE && DECL_MAIN_P (decl))
     {
       if (processing_template_decl)
-       error ("cannot declare `::main' to be a template");
+       error ("cannot declare %<::main%> to be a template");
       if (inlinep)
-       error ("cannot declare `::main' to be inline");
+       error ("cannot declare %<::main%> to be inline");
       if (!publicp)
-       error ("cannot declare `::main' to be static");
+       error ("cannot declare %<::main%> to be static");
       if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
                        integer_type_node))
-       error ("`main' must return `int'");
+       {
+         error ("%<::main%> must return %<int%>");
+         TREE_TYPE (TREE_TYPE (decl)) = integer_type_node;
+       }
       inlinep = 0;
       publicp = 1;
     }
@@ -5491,7 +5709,8 @@ grokfndecl (tree ctype,
         declare an entity with linkage.
 
         Only check this for public decls for now.  See core 319, 389.  */
-      t = no_linkage_check (TREE_TYPE (decl));
+      t = no_linkage_check (TREE_TYPE (decl),
+                           /*relaxed_p=*/false);
       if (t)
        {
          if (TYPE_ANONYMOUS_P (t))
@@ -5500,17 +5719,16 @@ grokfndecl (tree ctype,
                /* Allow this; it's pretty common in C.  */;
              else
                {
-                 pedwarn ("non-local function `%#D' uses anonymous type",
+                 pedwarn ("non-local function %q#D uses anonymous type",
                              decl);
                  if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
-                   cp_pedwarn_at ("\
-`%#D' does not refer to the unqualified type, so it is not used for linkage",
-                               TYPE_NAME (t));
+                   cp_pedwarn_at ("%q#D does not refer to the unqualified "
+                                   "type, so it is not used for linkage",
+                                   TYPE_NAME (t));
                }
            }
          else
-           pedwarn ("non-local function `%#D' uses local type `%T'",
-                       decl, t);
+           pedwarn ("non-local function %q#D uses local type %qT", decl, t);
        }
     }
 
@@ -5533,7 +5751,7 @@ grokfndecl (tree ctype,
   DECL_EXTERNAL (decl) = 1;
   if (quals && TREE_CODE (type) == FUNCTION_TYPE)
     {
-      error ("%smember function `%D' cannot have cv-qualifier",
+      error ("%smember function %qD cannot have cv-qualifier",
             (ctype ? "static " : "non-"), decl);
       quals = TYPE_UNQUALIFIED;
     }
@@ -5557,7 +5775,7 @@ grokfndecl (tree ctype,
     {
       if (funcdef_flag)
        error
-         ("defining explicit specialization `%D' in friend declaration",
+         ("defining explicit specialization %qD in friend declaration",
           orig_declarator);
       else
        {
@@ -5567,8 +5785,9 @@ grokfndecl (tree ctype,
          if (PROCESSING_REAL_TEMPLATE_DECL_P ())
            {
              /* Something like `template <class T> friend void f<T>()'.  */
-             error ("invalid use of template-id `%D' in declaration of primary template",
-                       orig_declarator);
+             error ("invalid use of template-id %qD in declaration "
+                     "of primary template",
+                     orig_declarator);
              return NULL_TREE;
            }
 
@@ -5584,25 +5803,27 @@ grokfndecl (tree ctype,
                  (see template_id in parse.y). If the current class contains
                  such a name, we'll get a COMPONENT_REF here. Undo that.  */
 
-              my_friendly_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
-                                  == current_class_type, 20001120);
+              gcc_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
+                         == current_class_type);
               fns = TREE_OPERAND (fns, 1);
             }
-         my_friendly_assert (TREE_CODE (fns) == IDENTIFIER_NODE
-                             || TREE_CODE (fns) == OVERLOAD, 20001120);
+         gcc_assert (TREE_CODE (fns) == IDENTIFIER_NODE
+                     || TREE_CODE (fns) == OVERLOAD);
          DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
 
          if (has_default_arg)
            {
-             error ("default arguments are not allowed in declaration of friend template specialization `%D'",
-                       decl);
+             error ("default arguments are not allowed in declaration "
+                     "of friend template specialization %qD",
+                     decl);
              return NULL_TREE;
            }
 
          if (inlinep)
            {
-             error ("`inline' is not allowed in declaration of friend template specialization `%D'",
-                       decl);
+             error ("%<inline%> is not allowed in declaration of friend "
+                     "template specialization %qD",
+                     decl);
              return NULL_TREE;
            }
        }
@@ -5636,6 +5857,12 @@ grokfndecl (tree ctype,
   if (decl == error_mark_node)
     return NULL_TREE;
 
+  if (attrlist)
+    {
+      cplus_decl_attributes (&decl, *attrlist, 0);
+      *attrlist = NULL_TREE;
+    }
+
   if (ctype != NULL_TREE
       && (! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
       && check)
@@ -5646,7 +5873,7 @@ grokfndecl (tree ctype,
                                (processing_template_decl
                                 > template_class_depth (ctype))
                                ? current_template_parms
-                               : NULL_TREE);
+                               : NULL_TREE); 
 
       if (old_decl && TREE_CODE (old_decl) == TEMPLATE_DECL)
        /* Because grokfndecl is always supposed to return a
@@ -5661,7 +5888,7 @@ grokfndecl (tree ctype,
           XXX Isn't this done in start_function, too?  */
        revert_static_member_fn (decl);
       if (old_decl && DECL_ARTIFICIAL (old_decl))
-       error ("definition of implicitly-declared `%D'", old_decl);
+       error ("definition of implicitly-declared %qD", old_decl);
 
       if (old_decl)
        {
@@ -5681,7 +5908,7 @@ grokfndecl (tree ctype,
            pop_scope (ctype);
          if (!ok)
            {
-             error ("no `%#D' member function declared in class `%T'",
+             error ("no %q#D member function declared in class %qT",
                     decl, ctype);
              return NULL_TREE;
            }
@@ -5701,7 +5928,26 @@ grokfndecl (tree ctype,
   return decl;
 }
 
-/* Create a VAR_DECL named NAME with the indicated TYPE.  
+/* DECL is a VAR_DECL for a static data member.  Set flags to reflect
+   the linkage that DECL will receive in the object file.  */
+
+static void
+set_linkage_for_static_data_member (tree decl)
+{
+  /* A static data member always has static storage duration and
+     external linkage.  Note that static data members are forbidden in
+     local classes -- the only situation in which a class has
+     non-external linkage.  */
+  TREE_PUBLIC (decl) = 1;
+  TREE_STATIC (decl) = 1;
+  /* For non-template classes, static data members are always put
+     out in exactly those files where they are defined, just as
+     with ordinary namespace-scope variables.  */
+  if (!processing_template_decl)
+    DECL_INTERFACE_KNOWN (decl) = 1;
+}
+
+/* Create a VAR_DECL named NAME with the indicated TYPE.
 
    If SCOPE is non-NULL, it is the class type or namespace containing
    the variable.  If SCOPE is NULL, the variable should is created in
@@ -5716,11 +5962,13 @@ grokvardecl (tree type,
              tree scope)
 {
   tree decl;
+  tree explicit_scope;
 
-  my_friendly_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE, 
-                     20020808);
+  gcc_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE);
 
-  /* Compute the scope in which to place the variable.  */
+  /* Compute the scope in which to place the variable, but remember
+     whether or not that scope was explicitly specified by the user.   */
+  explicit_scope = scope;
   if (!scope)
     {
       /* An explicit "extern" specifier indicates a namespace-scope
@@ -5728,11 +5976,7 @@ grokvardecl (tree type,
       if (declspecs->storage_class == sc_extern)
        scope = current_namespace;
       else if (!at_function_scope_p ())
-       {
-         scope = current_scope ();
-         if (!scope)
-           scope = current_namespace;
-       }
+       scope = current_scope ();
     }
 
   if (scope
@@ -5741,7 +5985,7 @@ grokvardecl (tree type,
          (TREE_CODE (scope) == NAMESPACE_DECL && processing_template_decl)
          /* Similarly for namespace-scope variables with language linkage
             other than C++.  */
-         || (TREE_CODE (scope) == NAMESPACE_DECL 
+         || (TREE_CODE (scope) == NAMESPACE_DECL
              && current_lang_name != lang_name_cplusplus)
          /* Similarly for static data members.  */
          || TYPE_P (scope)))
@@ -5749,8 +5993,8 @@ grokvardecl (tree type,
   else
     decl = build_decl (VAR_DECL, name, type);
 
-  if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
-    set_decl_namespace (decl, scope, 0);
+  if (explicit_scope && TREE_CODE (explicit_scope) == NAMESPACE_DECL)
+    set_decl_namespace (decl, explicit_scope, 0);
   else
     DECL_CONTEXT (decl) = scope;
 
@@ -5760,12 +6004,10 @@ grokvardecl (tree type,
       DECL_EXTERNAL (decl) = !initialized;
     }
 
-  /* In class context, static means one per class,
-     public access, and static storage.  */
   if (DECL_CLASS_SCOPE_P (decl))
     {
-      TREE_PUBLIC (decl) = 1;
-      TREE_STATIC (decl) = 1;
+      set_linkage_for_static_data_member (decl);
+      /* This function is only called with out-of-class definitions.  */
       DECL_EXTERNAL (decl) = 0;
     }
   /* At top level, either `static' or no s.c. makes a definition
@@ -5800,26 +6042,38 @@ grokvardecl (tree type,
         declare an entity with linkage.
 
         Only check this for public decls for now.  */
-      tree t = no_linkage_check (TREE_TYPE (decl));
+      tree t1 = TREE_TYPE (decl);
+      tree t = no_linkage_check (t1, /*relaxed_p=*/false);
       if (t)
        {
          if (TYPE_ANONYMOUS_P (t))
            {
              if (DECL_EXTERN_C_P (decl))
-               /* Allow this; it's pretty common in C.  */;
+               /* Allow this; it's pretty common in C.  */
+                 ;
+             else if (same_type_ignoring_top_level_qualifiers_p(t1, t))
+               /* This is something like "enum { a = 3 } x;", which is
+                  well formed.  The enum doesn't have "a name with no
+                  linkage", because it has no name.  See closed CWG issue
+                  132.
+
+                  Note that while this construct is well formed in C++03
+                  it is likely to become ill formed in C++0x.  See open
+                  CWG issue 389 and related issues.  */
+               ;
              else
                {
-                 pedwarn ("non-local variable `%#D' uses anonymous type",
+                 /* It's a typedef referring to an anonymous type.  */
+                 pedwarn ("non-local variable %q#D uses anonymous type",
                           decl);
                  if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
-                   cp_pedwarn_at ("\
-`%#D' does not refer to the unqualified type, so it is not used for linkage",
+                   cp_pedwarn_at ("%q#D does not refer to the unqualified "
+                                   "type, so it is not used for linkage",
                                   TYPE_NAME (t));
                }
            }
          else
-           pedwarn ("non-local variable `%#D' uses local type `%T'",
-                       decl, t);
+           pedwarn ("non-local variable %q#D uses local type %qT", decl, t);
        }
     }
 
@@ -5854,7 +6108,7 @@ build_ptrmemfunc_type (tree type)
 
   t = make_aggr_type (RECORD_TYPE);
   xref_basetypes (t, NULL_TREE);
-  
+
   /* Let the front-end know this is a pointer to member function...  */
   TYPE_PTRMEMFUNC_FLAG (t) = 1;
   /* ... and not really an aggregate.  */
@@ -5862,11 +6116,11 @@ build_ptrmemfunc_type (tree type)
 
   field = build_decl (FIELD_DECL, pfn_identifier, type);
   fields = field;
-  
+
   field = build_decl (FIELD_DECL, delta_identifier, delta_type_node);
   TREE_CHAIN (field) = fields;
   fields = field;
-  
+
   finish_builtin_struct (t, "__ptrmemfunc_type", fields, ptr_type_node);
 
   /* Zap out the name so that the back-end will give us the debugging
@@ -5902,19 +6156,18 @@ build_ptrmem_type (tree class_type, tree member_type)
       tree arg_types;
 
       arg_types = TYPE_ARG_TYPES (member_type);
-      class_type = (cp_build_qualified_type 
+      class_type = (cp_build_qualified_type
                    (class_type,
                     cp_type_quals (TREE_TYPE (TREE_VALUE (arg_types)))));
-      member_type 
-       = build_method_type_directly (class_type, 
+      member_type
+       = build_method_type_directly (class_type,
                                      TREE_TYPE (member_type),
                                      TREE_CHAIN (arg_types));
       return build_ptrmemfunc_type (build_pointer_type (member_type));
     }
   else
     {
-      my_friendly_assert (TREE_CODE (member_type) != FUNCTION_TYPE,
-                         20030716);
+      gcc_assert (TREE_CODE (member_type) != FUNCTION_TYPE);
       return build_offset_type (class_type, member_type);
     }
 }
@@ -5935,7 +6188,8 @@ check_static_variable_definition (tree decl, tree type)
      required.  */
   if (!ARITHMETIC_TYPE_P (type) && TREE_CODE (type) != ENUMERAL_TYPE)
     {
-      error ("invalid in-class initialization of static data member of non-integral type `%T'",
+      error ("invalid in-class initialization of static data member "
+             "of non-integral type %qT",
             type);
       /* If we just return the declaration, crashes will sometimes
         occur.  We therefore return void_type_node, as if this were a
@@ -5944,10 +6198,12 @@ check_static_variable_definition (tree decl, tree type)
       return 1;
     }
   else if (!CP_TYPE_CONST_P (type))
-    error ("ISO C++ forbids in-class initialization of non-const static member `%D'",
-             decl);
+    error ("ISO C++ forbids in-class initialization of non-const "
+           "static member %qD",
+           decl);
   else if (pedantic && !INTEGRAL_TYPE_P (type))
-    pedwarn ("ISO C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
+    pedwarn ("ISO C++ forbids initialization of member constant "
+             "%qD of non-integral type %qT", decl, type);
 
   return 0;
 }
@@ -5966,9 +6222,9 @@ compute_array_index_type (tree name, tree size)
   if (!dependent_type_p (type) && !INTEGRAL_TYPE_P (type))
     {
       if (name)
-       error ("size of array `%D' has non-integral type `%T'", name, type);
+       error ("size of array %qD has non-integral type %qT", name, type);
       else
-       error ("size of array has non-integral type `%T'", type);
+       error ("size of array has non-integral type %qT", type);
       size = integer_one_node;
       type = TREE_TYPE (size);
     }
@@ -5986,7 +6242,7 @@ compute_array_index_type (tree name, tree size)
   STRIP_TYPE_NOPS (size);
 
   /* It might be a const variable or enumeration constant.  */
-  size = decl_constant_value (size);
+  size = integral_constant_value (size);
 
   /* Normally, the array-bound will be a constant.  */
   if (TREE_CODE (size) == INTEGER_CST)
@@ -6004,7 +6260,7 @@ compute_array_index_type (tree name, tree size)
       if (INT_CST_LT (size, integer_zero_node))
        {
          if (name)
-           error ("size of array `%D' is negative", name);
+           error ("size of array %qD is negative", name);
          else
            error ("size of array is negative");
          size = integer_one_node;
@@ -6014,7 +6270,7 @@ compute_array_index_type (tree name, tree size)
       else if (integer_zerop (size) && pedantic && !in_system_header)
        {
          if (name)
-           pedwarn ("ISO C++ forbids zero-size array `%D'", name);
+           pedwarn ("ISO C++ forbids zero-size array %qD", name);
          else
            pedwarn ("ISO C++ forbids zero-size array");
        }
@@ -6023,15 +6279,15 @@ compute_array_index_type (tree name, tree size)
     {
       /* `(int) &fn' is not a valid array bound.  */
       if (name)
-       error ("size of array `%D' is not an integral constant-expression",
-                 name);
+       error ("size of array %qD is not an integral constant-expression",
+               name);
       else
        error ("size of array is not an integral constant-expression");
     }
   else if (pedantic)
     {
       if (name)
-       pedwarn ("ISO C++ forbids variable-size array `%D'", name);
+       pedwarn ("ISO C++ forbids variable-size array %qD", name);
       else
        pedwarn ("ISO C++ forbids variable-size array");
     }
@@ -6041,12 +6297,20 @@ compute_array_index_type (tree name, tree size)
     itype = build_min (MINUS_EXPR, sizetype, size, integer_one_node);
   else
     {
+      HOST_WIDE_INT saved_processing_template_decl;
+
       /* Compute the index of the largest element in the array.  It is
-        one less than the number of elements in the array.  */
-      itype
-       = fold (cp_build_binary_op (MINUS_EXPR,
-                                   cp_convert (ssizetype, size),
-                                   cp_convert (ssizetype, integer_one_node)));
+        one less than the number of elements in the array.  We save
+        and restore PROCESSING_TEMPLATE_DECL so that computations in
+        cp_build_binary_op will be appropriately folded.  */
+      saved_processing_template_decl = processing_template_decl;
+      processing_template_decl = 0;
+      itype = cp_build_binary_op (MINUS_EXPR,
+                                 cp_convert (ssizetype, size),
+                                 cp_convert (ssizetype, integer_one_node));
+      itype = fold (itype);
+      processing_template_decl = saved_processing_template_decl;
+
       if (!TREE_CONSTANT (itype))
        /* A variable sized array.  */
        itype = variable_size (itype);
@@ -6077,11 +6341,10 @@ get_scope_of_declarator (const cp_declarator *declarator)
   /* If the declarator-id is a SCOPE_REF, the scope in which the
      declaration occurs is the first operand.  */
   if (declarator
-      && declarator->u.id.name
-      && TREE_CODE (declarator->u.id.name) == SCOPE_REF)
-    return TREE_OPERAND (declarator->u.id.name, 0);
+      && declarator->u.id.qualifying_scope)
+    return declarator->u.id.qualifying_scope;
 
-  /* Otherwise, the declarator is not a quablified name; the entity will
+  /* Otherwise, the declarator is not a qualified name; the entity will
      be declared in the current scope.  */
   return NULL_TREE;
 }
@@ -6130,7 +6393,7 @@ create_array_type_for_decl (tree name, tree type, tree size)
   if (error_msg)
     {
       if (name)
-       error ("declaration of `%D' as %s", name, error_msg);
+       error ("declaration of %qD as %s", name, error_msg);
       else
        error ("creating %s", error_msg);
 
@@ -6144,10 +6407,12 @@ create_array_type_for_decl (tree name, tree type, tree size)
   if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
     {
       if (name)
-       error ("declaration of `%D' as multidimensional array must have bounds for all dimensions except the first",
-                 name);
+       error ("declaration of %qD as multidimensional array must "
+               "have bounds for all dimensions except the first",
+               name);
       else
-       error ("multidimensional array must have bounds for all dimensions except the first");
+       error ("multidimensional array must have bounds for all "
+               "dimensions except the first");
 
       return error_mark_node;
     }
@@ -6167,7 +6432,8 @@ create_array_type_for_decl (tree name, tree type, tree size)
 /* Check that it's OK to declare a function with the indicated TYPE.
    SFK indicates the kind of special function (if any) that this
    function is.  OPTYPE is the type given in a conversion operator
-   declaration.  Returns the actual return type of the function; that
+   declaration, or the class type for a constructor/destructor.
+   Returns the actual return type of the function; that
    may be different than TYPE if an error occurs, or for certain
    special functions.  */
 
@@ -6182,31 +6448,65 @@ check_special_function_return_type (special_function_kind sfk,
       if (type)
        error ("return type specification for constructor invalid");
 
-      type = void_type_node;
+      if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (optype))
+       type = build_pointer_type (optype);
+      else
+       type = void_type_node;
       break;
 
     case sfk_destructor:
       if (type)
        error ("return type specification for destructor invalid");
-      type = void_type_node;
+      /* We can't use the proper return type here because we run into
+        problems with ambiguous bases and covariant returns.
+        Java classes are left unchanged because (void *) isn't a valid
+        Java type, and we don't want to change the Java ABI.  */
+      if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (optype))
+       type = build_pointer_type (void_type_node);
+      else
+       type = void_type_node;
       break;
 
     case sfk_conversion:
       if (type && !same_type_p (type, optype))
-       error ("operator `%T' declared to return `%T'", optype, type);
+       error ("operator %qT declared to return %qT", optype, type);
       else if (type)
-       pedwarn ("return type specified for `operator %T'",  optype);
+       pedwarn ("return type specified for %<operator %T%>",  optype);
       type = optype;
       break;
 
     default:
-      abort ();
-      break;
+      gcc_unreachable ();
     }
 
   return type;
 }
 
+/* A variable or data member (whose unqualified name is IDENTIFIER)
+   has been declared with the indicated TYPE.  If the TYPE is not
+   acceptable, issue an error message and return a type to use for
+   error-recovery purposes.  */
+
+tree
+check_var_type (tree identifier, tree type)
+{
+  if (VOID_TYPE_P (type))
+    {
+      if (!identifier)
+       error ("unnamed variable or field declared void");
+      else if (TREE_CODE (identifier) == IDENTIFIER_NODE)
+       {
+         gcc_assert (!IDENTIFIER_OPNAME_P (identifier));
+         error ("variable or field %qE declared void", identifier);
+       }
+      else
+       error ("variable or field declared void");
+      type = integer_type_node;
+    }
+  
+  return type;
+}
+
 /* Given declspecs and a declarator (abstract or otherwise), determine
    the name and type of the object declared and construct a DECL node
    for it.
@@ -6261,7 +6561,7 @@ grokdeclarator (const cp_declarator *declarator,
   int explicit_char = 0;
   int defaulted_int = 0;
   tree dependant_name = NULL_TREE;
-  
+
   tree typedef_decl = NULL_TREE;
   const char *name = NULL;
   tree typedef_type = NULL_TREE;
@@ -6298,11 +6598,12 @@ grokdeclarator (const cp_declarator *declarator,
   /* The NAMESPACE_DECL for the namespace in which this entity is
      located.  If an unqualified name is used to declare the entity,
      this value will be NULL_TREE, even if the entity is located at
-     namespace scope.  */ 
+     namespace scope.  */
   tree in_namespace = NULL_TREE;
   cp_decl_spec ds;
   cp_storage_class storage_class;
   bool unsigned_p, signed_p, short_p, long_p, thread_p;
+  bool type_was_error_mark_node = false;
 
   signed_p = declspecs->specs[(int)ds_signed];
   unsigned_p = declspecs->specs[(int)ds_unsigned];
@@ -6319,8 +6620,8 @@ grokdeclarator (const cp_declarator *declarator,
 
   /* Look inside a declarator for the name being declared
      and get it as a string, for an error message.  */
-  for (id_declarator = declarator; 
-       id_declarator; 
+  for (id_declarator = declarator;
+       id_declarator;
        id_declarator = id_declarator->declarator)
     {
       if (id_declarator->kind != cdk_id)
@@ -6340,40 +6641,27 @@ grokdeclarator (const cp_declarator *declarator,
 
        case cdk_id:
          {
-           tree decl = id_declarator->u.id.name;
+           tree qualifying_scope = id_declarator->u.id.qualifying_scope;
+           tree decl = id_declarator->u.id.unqualified_name;
            if (!decl)
              break;
-           if (TREE_CODE (decl) == SCOPE_REF)
+           if (qualifying_scope)
              {
-               tree qualifying_scope = TREE_OPERAND (decl, 0);
-;
-               /* It is valid to write:
-
-                  class C { void f(); };
-                  typedef C D;
-                  void D::f();
-
-                The standard is not clear about whether `typedef const C D' is
-                legal; as of 2002-09-15 the committee is considering
-                that question.  EDG 3.0 allows that syntax.
-                Therefore, we do as well.  */
-               if (qualifying_scope && TYPE_P (qualifying_scope))
+               if (TYPE_P (qualifying_scope))
                  {
-                   ctype = TYPE_MAIN_VARIANT (qualifying_scope); 
+                   ctype = qualifying_scope;
                    if (innermost_code != cdk_function
                        && current_class_type
-                       && !UNIQUELY_DERIVED_FROM_P (ctype, 
+                       && !UNIQUELY_DERIVED_FROM_P (ctype,
                                                     current_class_type))
                      {
-                       error ("type `%T' is not derived from type `%T'",
+                       error ("type %qT is not derived from type %qT",
                               ctype, current_class_type);
-                       ctype = NULL_TREE;
+                       return error_mark_node;
                      }
-                   TREE_OPERAND (decl, 0) = ctype; 
                  }
                else if (TREE_CODE (qualifying_scope) == NAMESPACE_DECL)
                  in_namespace = qualifying_scope;
-               decl = TREE_OPERAND (decl, 1);
              }
            if (TREE_CODE (decl) == BASELINK)
              decl = BASELINK_FUNCTIONS (decl);
@@ -6398,8 +6686,7 @@ grokdeclarator (const cp_declarator *declarator,
                    dname = TREE_OPERAND (dname, 1);
                  if (TREE_CODE (dname) != IDENTIFIER_NODE)
                    {
-                     my_friendly_assert (is_overloaded_fn (dname),
-                                         19990331);
+                     gcc_assert (is_overloaded_fn (dname));
                      dname = DECL_NAME (get_first_fn (dname));
                    }
                }
@@ -6411,7 +6698,7 @@ grokdeclarator (const cp_declarator *declarator,
 
                if (C_IS_RESERVED_WORD (dname))
                  {
-                   error ("declarator-id missing; using reserved word `%D'",
+                   error ("declarator-id missing; using reserved word %qD",
                           dname);
                    name = IDENTIFIER_POINTER (dname);
                  }
@@ -6419,7 +6706,7 @@ grokdeclarator (const cp_declarator *declarator,
                  name = IDENTIFIER_POINTER (dname);
                else
                  {
-                   my_friendly_assert (flags == NO_SPECIAL, 154);
+                   gcc_assert (flags == NO_SPECIAL);
                    flags = TYPENAME_FLAG;
                    ctor_return_type = TREE_TYPE (dname);
                    sfk = sfk_conversion;
@@ -6436,7 +6723,7 @@ grokdeclarator (const cp_declarator *declarator,
                break;
 
              default:
-               abort ();
+               gcc_unreachable ();
              }
            break;
 
@@ -6450,7 +6737,7 @@ grokdeclarator (const cp_declarator *declarator,
            break;
 
          default:
-           abort ();
+           gcc_unreachable ();
          }
        }
       if (id_declarator->kind == cdk_id)
@@ -6467,8 +6754,8 @@ grokdeclarator (const cp_declarator *declarator,
       && innermost_code != cdk_function
       && ! (ctype && !declspecs->any_specifiers_p))
     {
-      error ("declaration of `%D' as non-function", dname);
-      return void_type_node;
+      error ("declaration of %qD as non-function", dname);
+      return error_mark_node;
     }
 
   /* Anything declared one level down from the top level
@@ -6500,11 +6787,14 @@ grokdeclarator (const cp_declarator *declarator,
   /* If there were multiple types specified in the decl-specifier-seq,
      issue an error message.  */
   if (declspecs->multiple_types_p)
-    error ("two or more data types in declaration of `%s'", name);
+    error ("two or more data types in declaration of %qs", name);
   /* Extract the basic type from the decl-specifier-seq.  */
   type = declspecs->type;
   if (type == error_mark_node)
-    type = NULL_TREE;
+    {
+      type = NULL_TREE;
+      type_was_error_mark_node = true;
+    }
   /* If the entire declaration is itself tagged as deprecated then
      suppress reports of deprecated items.  */
   if (type && TREE_DEPRECATED (type)
@@ -6528,22 +6818,22 @@ grokdeclarator (const cp_declarator *declarator,
   explicit_char = declspecs->explicit_char_p;
 
   /* Check for repeated decl-specifiers.  */
-  for (ds = ds_first; ds != ds_last; ++ds) 
+  for (ds = ds_first; ds != ds_last; ++ds)
     {
       unsigned count = declspecs->specs[(int)ds];
       if (count < 2)
        continue;
-      /* The "long" specifier is a special case because of 
+      /* The "long" specifier is a special case because of
         "long long".  */
       if (ds == ds_long)
        {
          if (count > 2)
-           error ("`long long long' is too long for GCC");
+           error ("%<long long long%> is too long for GCC");
          else if (pedantic && !in_system_header && warn_long_long)
-           pedwarn ("ISO C++ does not support `long long'");
+           pedwarn ("ISO C++ does not support %<long long%>");
          else
            longlong = 1;
-       } 
+       }
       else if (declspecs->specs[(int)ds] > 1)
        {
          static const char *const decl_spec_names[] = {
@@ -6562,7 +6852,7 @@ grokdeclarator (const cp_declarator *declarator,
            "__complex",
            "__thread"
          };
-         error ("duplicate `%s'", decl_spec_names[(int)ds]);
+         error ("duplicate %qs", decl_spec_names[(int)ds]);
        }
     }
 
@@ -6574,6 +6864,9 @@ grokdeclarator (const cp_declarator *declarator,
   typedef_type = type;
 
 
+  if (sfk != sfk_conversion)
+    ctor_return_type = ctype;
+
   if (sfk != sfk_none)
     type = check_special_function_return_type (sfk, type,
                                               ctor_return_type);
@@ -6592,18 +6885,18 @@ grokdeclarator (const cp_declarator *declarator,
                 && in_namespace == NULL_TREE
                 && current_namespace == global_namespace);
 
-      if (in_system_header || flag_ms_extensions)
+      if (type_was_error_mark_node)
+       /* We've already issued an error, don't complain more.  */;
+      else if (in_system_header || flag_ms_extensions)
        /* Allow it, sigh.  */;
       else if (pedantic || ! is_main)
-       pedwarn ("ISO C++ forbids declaration of `%s' with no type",
-                   name);
+       pedwarn ("ISO C++ forbids declaration of %qs with no type", name);
       else if (warn_return_type)
-       warning ("ISO C++ forbids declaration of `%s' with no type",
-                   name);
+       warning ("ISO C++ forbids declaration of %qs with no type", name);
 
       type = integer_type_node;
     }
-  
+
   ctype = NULL_TREE;
 
   /* Now process the modifiers that were specified
@@ -6624,23 +6917,23 @@ grokdeclarator (const cp_declarator *declarator,
       int ok = 0;
 
       if (TREE_CODE (type) == REAL_TYPE)
-       error ("short, signed or unsigned invalid for `%s'", name);
+       error ("short, signed or unsigned invalid for %qs", name);
       else if (TREE_CODE (type) != INTEGER_TYPE)
-       error ("long, short, signed or unsigned invalid for `%s'", name);
+       error ("long, short, signed or unsigned invalid for %qs", name);
       else if (long_p && short_p)
-       error ("long and short specified together for `%s'", name);
+       error ("long and short specified together for %qs", name);
       else if ((long_p || short_p) && explicit_char)
-       error ("long or short specified with char for `%s'", name);
+       error ("long or short specified with char for %qs", name);
       else if ((long_p|| short_p) && TREE_CODE (type) == REAL_TYPE)
-       error ("long or short specified with floating type for `%s'", name);
+       error ("long or short specified with floating type for %qs", name);
       else if (signed_p && unsigned_p)
-       error ("signed and unsigned given together for `%s'", name);
+       error ("signed and unsigned given together for %qs", name);
       else
        {
          ok = 1;
          if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
            {
-             pedwarn ("long, short, signed or unsigned used invalidly for `%s'",
+             pedwarn ("long, short, signed or unsigned used invalidly for %qs",
                       name);
              if (flag_pedantic_errors)
                ok = 0;
@@ -6705,7 +6998,7 @@ grokdeclarator (const cp_declarator *declarator,
   if (declspecs->specs[(int)ds_complex])
     {
       if (TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
-       error ("complex invalid for `%s'", name);
+       error ("complex invalid for %qs", name);
       /* If we just have "complex", it is equivalent to
         "complex double", but if any modifiers at all are specified it is
         the complex form of TYPE.  E.g, "complex short" is
@@ -6734,8 +7027,8 @@ grokdeclarator (const cp_declarator *declarator,
   if (declspecs->specs[(int)ds_restrict])
     type_quals |= TYPE_QUAL_RESTRICT;
   if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
-    error ("qualifiers are not allowed on declaration of `operator %T'",
-             ctor_return_type);
+    error ("qualifiers are not allowed on declaration of %<operator %T%>",
+           ctor_return_type);
 
   type_quals |= cp_type_quals (type);
   type = cp_build_qualified_type_real
@@ -6743,7 +7036,7 @@ grokdeclarator (const cp_declarator *declarator,
                         ? tf_ignore_bad_quals : 0) | tf_error | tf_warning));
   /* We might have ignored or rejected some of the qualifiers.  */
   type_quals = cp_type_quals (type);
-  
+
   staticp = 0;
   inlinep = !! declspecs->specs[(int)ds_inline];
   virtualp = !! declspecs->specs[(int)ds_virtual];
@@ -6755,15 +7048,14 @@ grokdeclarator (const cp_declarator *declarator,
 
   if (virtualp && staticp == 2)
     {
-      error ("member `%D' cannot be declared both virtual and static",
-               dname);
+      error ("member %qD cannot be declared both virtual and static", dname);
       staticp = 0;
     }
   friendp = !! declspecs->specs[(int)ds_friend];
 
   if (dependant_name && !friendp)
     {
-      error ("`%T::%D' is not a valid declarator", ctype, dependant_name);
+      error ("%<%T::%D%> is not a valid declarator", ctype, dependant_name);
       return void_type_node;
     }
 
@@ -6795,17 +7087,17 @@ grokdeclarator (const cp_declarator *declarator,
   /* Warn about storage classes that are invalid for certain
      kinds of declarations (parameters, typenames, etc.).  */
   if (declspecs->multiple_storage_classes_p)
-    error ("multiple storage classes in declaration of `%s'", name);
+    error ("multiple storage classes in declaration of %qs", name);
   else if (thread_p
-          && ((storage_class 
+          && ((storage_class
                && storage_class != sc_extern
                && storage_class != sc_static)
               || declspecs->specs[(int)ds_typedef]))
     {
-      error ("multiple storage classes in declaration of `%s'", name);
+      error ("multiple storage classes in declaration of %qs", name);
       thread_p = false;
     }
-  else if (decl_context != NORMAL 
+  else if (decl_context != NORMAL
           && ((storage_class != sc_none
                && storage_class != sc_mutable)
               || thread_p))
@@ -6833,9 +7125,9 @@ grokdeclarator (const cp_declarator *declarator,
                {
                  /* Avoid trying to get an operand off an identifier node.  */
                  if (declarator->kind != cdk_id)
-                   tmp = declarator->declarator->u.id.name;
+                   tmp = declarator->declarator->u.id.unqualified_name;
                  else
-                   tmp = declarator->u.id.name;
+                   tmp = declarator->u.id.unqualified_name;
                  op = IDENTIFIER_OPNAME_P (tmp);
                  if (IDENTIFIER_TYPENAME_P (tmp))
                    {
@@ -6845,14 +7137,14 @@ grokdeclarator (const cp_declarator *declarator,
                        name = "<invalid operator>";
                    }
                }
-             error ("storage class specified for %s `%s'",
+             error ("storage class specified for %s %qs",
                     op ? "member operator" : "field",
                     name);
            }
          else
            {
              if (decl_context == PARM || decl_context == CATCHPARM)
-               error ("storage class specified for parameter `%s'", name);
+               error ("storage class specified for parameter %qs", name);
              else
                error ("storage class specified for typename");
            }
@@ -6863,7 +7155,7 @@ grokdeclarator (const cp_declarator *declarator,
            storage_class = sc_none;
        }
     }
-  else if (storage_class == sc_extern && initialized 
+  else if (storage_class == sc_extern && initialized
           && !funcdef_flag)
     {
       if (toplevel_bindings_p ())
@@ -6871,24 +7163,24 @@ grokdeclarator (const cp_declarator *declarator,
          /* It's common practice (and completely valid) to have a const
             be initialized and declared extern.  */
          if (!(type_quals & TYPE_QUAL_CONST))
-           warning ("`%s' initialized and declared `extern'", name);
+           warning ("%qs initialized and declared %<extern%>", name);
        }
       else
-       error ("`%s' has both `extern' and initializer", name);
+       error ("%qs has both %<extern%> and initializer", name);
     }
   else if (storage_class == sc_extern && funcdef_flag
           && ! toplevel_bindings_p ())
-    error ("nested function `%s' declared `extern'", name);
+    error ("nested function %qs declared %<extern%>", name);
   else if (toplevel_bindings_p ())
     {
       if (storage_class == sc_auto)
-       error ("top-level declaration of `%s' specifies `auto'", name);
+       error ("top-level declaration of %qs specifies %<auto%>", name);
     }
   else if (thread_p
           && storage_class != sc_extern
           && storage_class != sc_static)
     {
-      error ("function-scope `%s' implicitly auto and declared `__thread'",
+      error ("function-scope %qs implicitly auto and declared %<__thread%>",
             name);
       thread_p = false;
     }
@@ -6900,35 +7192,33 @@ grokdeclarator (const cp_declarator *declarator,
     unqualified_id = NULL_TREE;
   else
     {
-      unqualified_id = id_declarator->u.id.name;
-      if (TREE_CODE (unqualified_id) == SCOPE_REF)
-       unqualified_id = TREE_OPERAND (unqualified_id, 1);
+      unqualified_id = id_declarator->u.id.unqualified_name;
       if (TREE_CODE (unqualified_id) == BASELINK)
        unqualified_id = BASELINK_FUNCTIONS (unqualified_id);
       switch (TREE_CODE (unqualified_id))
        {
        case BIT_NOT_EXPR:
-         unqualified_id 
+         unqualified_id
            = constructor_name (TREE_OPERAND (unqualified_id, 0));
          break;
-         
+
        case TYPE_DECL:
-         unqualified_id 
+         unqualified_id
            = constructor_name (TREE_TYPE (unqualified_id));
          break;
 
        case IDENTIFIER_NODE:
        case TEMPLATE_ID_EXPR:
          break;
-       
+
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
   /* Determine the type of the entity declared by recurring on the
      declarator.  */
-  for (; 
+  for (;
        declarator && declarator->kind != cdk_id;
        declarator = declarator->declarator)
     {
@@ -6944,7 +7234,7 @@ grokdeclarator (const cp_declarator *declarator,
       if (attrs)
        {
          int attr_flags;
-         
+
          attr_flags = 0;
          if (declarator == NULL || declarator->kind == cdk_id)
            attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
@@ -6960,15 +7250,8 @@ grokdeclarator (const cp_declarator *declarator,
       switch (declarator->kind)
        {
        case cdk_array:
-         type = create_array_type_for_decl (dname, type, 
+         type = create_array_type_for_decl (dname, type,
                                             declarator->u.array.bounds);
-         if (inner_declarator
-             && (inner_declarator->kind == cdk_pointer
-                 || inner_declarator->kind == cdk_reference
-                 || inner_declarator->kind == cdk_ptrmem))
-           /* We can never complete an array type which is the
-              target of a pointer, so go ahead and lay it out.  */
-           layout_type (type);
          break;
 
        case cdk_function:
@@ -6987,12 +7270,12 @@ grokdeclarator (const cp_declarator *declarator,
 
            if (TREE_CODE (type) == FUNCTION_TYPE)
              {
-               error ("`%s' declared as function returning a function", name);
+               error ("%qs declared as function returning a function", name);
                type = integer_type_node;
              }
            if (TREE_CODE (type) == ARRAY_TYPE)
              {
-               error ("`%s' declared as function returning an array", name);
+               error ("%qs declared as function returning an array", name);
                type = integer_type_node;
              }
 
@@ -7079,7 +7362,7 @@ grokdeclarator (const cp_declarator *declarator,
            else if (friendp)
              {
                if (initialized)
-                 error ("can't initialize friend function `%s'", name);
+                 error ("can't initialize friend function %qs", name);
                if (virtualp)
                  {
                    /* Cannot be both friend and virtual.  */
@@ -7089,11 +7372,12 @@ grokdeclarator (const cp_declarator *declarator,
                if (decl_context == NORMAL)
                  error ("friend declaration not in class definition");
                if (current_function_decl && funcdef_flag)
-                 error ("can't define friend function `%s' in a local class definition",
-                           name);
+                 error ("can't define friend function %qs in a local "
+                         "class definition",
+                         name);
              }
 
-           arg_types = grokparms (declarator->u.function.parameters, 
+           arg_types = grokparms (declarator->u.function.parameters,
                                   &parms);
 
            if (inner_declarator
@@ -7105,7 +7389,7 @@ grokdeclarator (const cp_declarator *declarator,
                arg_types = void_list_node;
                parms = NULL_TREE;
              }
-           
+
            type = build_function_type (type, arg_types);
          }
          break;
@@ -7119,16 +7403,16 @@ grokdeclarator (const cp_declarator *declarator,
          if (TREE_CODE (type) == REFERENCE_TYPE)
            {
              error (declarator->kind == cdk_reference
-                    ? "cannot declare reference to `%#T'"
-                    : "cannot declare pointer to `%#T'", type);
+                    ? "cannot declare reference to %q#T"
+                    : "cannot declare pointer to %q#T", type);
              type = TREE_TYPE (type);
            }
          else if (VOID_TYPE_P (type))
            {
              if (declarator->kind == cdk_reference)
-               error ("cannot declare reference to `%#T'", type);
+               error ("cannot declare reference to %q#T", type);
              else if (declarator->kind == cdk_ptrmem)
-               error ("cannot declare pointer to `%#T' member", type);
+               error ("cannot declare pointer to %q#T member", type);
            }
 
          /* We now know that the TYPE_QUALS don't apply to the decl,
@@ -7140,7 +7424,7 @@ grokdeclarator (const cp_declarator *declarator,
                  || (quals && TREE_CODE (type) == METHOD_TYPE)))
            {
              tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
-             grok_method_quals (declarator->u.pointer.class_type, 
+             grok_method_quals (declarator->u.pointer.class_type,
                                 dummy, quals);
              type = TREE_TYPE (dummy);
              quals = TYPE_UNQUALIFIED;
@@ -7154,8 +7438,19 @@ grokdeclarator (const cp_declarator *declarator,
          else if (TREE_CODE (type) == METHOD_TYPE)
            type = build_ptrmemfunc_type (build_pointer_type (type));
          else if (declarator->kind == cdk_ptrmem)
-           type = build_ptrmem_type (declarator->u.pointer.class_type, 
-                                     type);
+           {
+             /* We might have parsed a namespace as the class type.  */
+             if (TREE_CODE (declarator->u.pointer.class_type)
+                 == NAMESPACE_DECL)
+               {
+                 error ("%qD is a namespace",
+                        declarator->u.pointer.class_type);
+                 type = build_pointer_type (type);
+               }
+             else
+               type = build_ptrmem_type (declarator->u.pointer.class_type,
+                                         type);
+           }
          else
            type = build_pointer_type (type);
 
@@ -7164,8 +7459,8 @@ grokdeclarator (const cp_declarator *declarator,
 
          if (declarator->u.pointer.qualifiers)
            {
-             type 
-               = cp_build_qualified_type (type, 
+             type
+               = cp_build_qualified_type (type,
                                           declarator->u.pointer.qualifiers);
              type_quals = cp_type_quals (type);
            }
@@ -7176,33 +7471,29 @@ grokdeclarator (const cp_declarator *declarator,
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
-  
+
   if (unqualified_id && TREE_CODE (unqualified_id) == TEMPLATE_ID_EXPR
       && TREE_CODE (type) != FUNCTION_TYPE
       && TREE_CODE (type) != METHOD_TYPE)
     {
-      error ("template-id `%D' used as a declarator", 
+      error ("template-id %qD used as a declarator",
             unqualified_id);
       unqualified_id = dname;
     }
 
   /* If DECLARATOR is non-NULL, we know it is a cdk_id declarator;
      otherwise, we would not have exited the loop above.  */
-  if (declarator 
-      && TREE_CODE (declarator->u.id.name) == SCOPE_REF
-      /* If the qualifying scope was invalid, it will have been set to
-        NULL_TREE above.  */
-      && TREE_OPERAND (declarator->u.id.name, 0)
-      && TYPE_P (TREE_OPERAND (declarator->u.id.name, 0)))
+  if (declarator
+      && declarator->u.id.qualifying_scope
+      && TYPE_P (declarator->u.id.qualifying_scope))
     {
       tree t;
 
-      ctype = TREE_OPERAND (declarator->u.id.name, 0);
-      if (TYPE_P (ctype))
-       ctype = TYPE_MAIN_VARIANT (ctype);
+      ctype = declarator->u.id.qualifying_scope;
+      ctype = TYPE_MAIN_VARIANT (ctype);
       t = ctype;
       while (t != NULL_TREE && CLASS_TYPE_P (t))
        {
@@ -7235,12 +7526,12 @@ grokdeclarator (const cp_declarator *declarator,
             Is this ill-formed?  */
 
          if (pedantic)
-           pedwarn ("extra qualification `%T::' on member `%s' ignored",
+           pedwarn ("extra qualification %<%T::%> on member %qs ignored",
                        ctype, name);
        }
       else if (TREE_CODE (type) == FUNCTION_TYPE)
        {
-         tree sname = TREE_OPERAND (declarator->u.id.name, 1);
+         tree sname = declarator->u.id.unqualified_name;
 
          if (TREE_CODE (sname) == IDENTIFIER_NODE
              && NEW_DELETE_OPNAME_P (sname))
@@ -7248,13 +7539,13 @@ grokdeclarator (const cp_declarator *declarator,
               are always static functions.  */
            ;
          else if (current_class_type == NULL_TREE || friendp)
-           type 
-             = build_method_type_directly (ctype, 
+           type
+             = build_method_type_directly (ctype,
                                            TREE_TYPE (type),
                                            TYPE_ARG_TYPES (type));
          else
            {
-             error ("cannot declare member function `%T::%s' within `%T'",
+             error ("cannot declare member function %<%T::%s%> within %<%T%>",
                     ctype, name, current_class_type);
              return error_mark_node;
            }
@@ -7269,7 +7560,7 @@ grokdeclarator (const cp_declarator *declarator,
 
          if (current_class_type)
            {
-             error ("cannot declare member `%T::%s' within `%T'",
+             error ("cannot declare member %<%T::%s%> within %qT",
                     ctype, name, current_class_type);
              return void_type_node;
            }
@@ -7297,20 +7588,20 @@ grokdeclarator (const cp_declarator *declarator,
       && COMPLETE_TYPE_P (type)
       && TREE_OVERFLOW (TYPE_SIZE (type)))
     {
-      error ("size of array `%s' is too large", name);
+      error ("size of array %qs is too large", name);
       /* If we proceed with the array type as it is, we'll eventually
         crash in tree_low_cst().  */
       type = error_mark_node;
     }
 
   if ((decl_context == FIELD || decl_context == PARM)
-      && !processing_template_decl 
+      && !processing_template_decl
       && variably_modified_type_p (type, NULL_TREE))
     {
       if (decl_context == FIELD)
-       error ("data member may not have variably modified type `%T'", type);
+       error ("data member may not have variably modified type %qT", type);
       else
-       error ("parameter may not have variably modified type `%T'", type);
+       error ("parameter may not have variably modified type %qT", type);
       type = error_mark_node;
     }
 
@@ -7318,7 +7609,7 @@ grokdeclarator (const cp_declarator *declarator,
     {
       /* [dcl.fct.spec] The explicit specifier shall only be used in
          declarations of constructors within a class definition.  */
-      error ("only declarations of constructors can be `explicit'");
+      error ("only declarations of constructors can be %<explicit%>");
       explicitp = 0;
     }
 
@@ -7326,28 +7617,28 @@ grokdeclarator (const cp_declarator *declarator,
     {
       if (decl_context != FIELD || friendp)
         {
-         error ("non-member `%s' cannot be declared `mutable'", name);
+         error ("non-member %qs cannot be declared %<mutable%>", name);
          storage_class = sc_none;
         }
       else if (decl_context == TYPENAME || declspecs->specs[(int)ds_typedef])
        {
-         error ("non-object member `%s' cannot be declared `mutable'", name);
+         error ("non-object member %qs cannot be declared %<mutable%>", name);
          storage_class = sc_none;
        }
       else if (TREE_CODE (type) == FUNCTION_TYPE
                || TREE_CODE (type) == METHOD_TYPE)
         {
-         error ("function `%s' cannot be declared `mutable'", name);
+         error ("function %qs cannot be declared %<mutable%>", name);
          storage_class = sc_none;
         }
       else if (staticp)
        {
-         error ("static `%s' cannot be declared `mutable'", name);
+         error ("static %qs cannot be declared %<mutable%>", name);
          storage_class = sc_none;
        }
       else if (type_quals & TYPE_QUAL_CONST)
        {
-         error ("const `%s' cannot be declared `mutable'", name);
+         error ("const %qs cannot be declared %<mutable%>", name);
          storage_class = sc_none;
        }
     }
@@ -7365,7 +7656,8 @@ grokdeclarator (const cp_declarator *declarator,
       if (decl_context == FIELD)
        {
          if (constructor_name_p (unqualified_id, current_class_type))
-           pedwarn ("ISO C++ forbids nested type `%D' with same name as enclosing class",
+           pedwarn ("ISO C++ forbids nested type %qD with same name "
+                     "as enclosing class",
                     unqualified_id);
          decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
        }
@@ -7376,8 +7668,16 @@ grokdeclarator (const cp_declarator *declarator,
            error ("%Jtypedef name may not be a nested-name-specifier", decl);
          if (!current_function_decl)
            DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
+         else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (current_function_decl)
+                  || (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P 
+                      (current_function_decl)))
+           /* The TYPE_DECL is "abstract" because there will be
+              clones of this constructor/destructor, and there will
+              be copies of this TYPE_DECL generated in those
+              clones.  */
+           DECL_ABSTRACT (decl) = 1;
        }
-      
+
       /* If the user declares "typedef struct {...} foo" then the
         struct will have an anonymous name.  Fill that name in now.
         Nothing can refer to it, so nothing needs know about the name
@@ -7395,7 +7695,6 @@ grokdeclarator (const cp_declarator *declarator,
          tree t;
 
          /* Replace the anonymous name with the real name everywhere.  */
-         lookup_tag_reverse (type, unqualified_id);
          for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
            if (TYPE_NAME (t) == oldname)
              TYPE_NAME (t) = decl;
@@ -7432,7 +7731,7 @@ grokdeclarator (const cp_declarator *declarator,
          || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
        C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
 
-      bad_specifiers (decl, "type", virtualp, quals != TYPE_UNQUALIFIED, 
+      bad_specifiers (decl, "type", virtualp, quals != TYPE_UNQUALIFIED,
                      inlinep, friendp, raises != NULL_TREE);
 
       return decl;
@@ -7450,7 +7749,7 @@ grokdeclarator (const cp_declarator *declarator,
 
   /* Detect where we're using a typedef of function type to declare a
      function. PARMS will not be set, so we must create it now.  */
-  
+
   if (type == typedef_type && TREE_CODE (type) == FUNCTION_TYPE)
     {
       tree decls = NULL_TREE;
@@ -7463,7 +7762,7 @@ grokdeclarator (const cp_declarator *declarator,
          TREE_CHAIN (decl) = decls;
          decls = decl;
        }
-      
+
       parms = nreverse (decls);
     }
 
@@ -7487,7 +7786,7 @@ grokdeclarator (const cp_declarator *declarator,
            }
          if (inlinep)
            {
-             error ("`inline' specified for friend class declaration");
+             error ("%<inline%> specified for friend class declaration");
              inlinep = 0;
            }
 
@@ -7498,11 +7797,11 @@ grokdeclarator (const cp_declarator *declarator,
                pedwarn ("template parameters cannot be friends");
              else if (TREE_CODE (type) == TYPENAME_TYPE)
                pedwarn ("friend declaration requires class-key, "
-                        "i.e. `friend class %T::%D'",
+                        "i.e. %<friend class %T::%D%>",
                         TYPE_CONTEXT (type), TYPENAME_TYPE_FULLNAME (type));
              else
                pedwarn ("friend declaration requires class-key, "
-                        "i.e. `friend %#T'",
+                        "i.e. %<friend %#T%>",
                         type);
            }
 
@@ -7514,8 +7813,8 @@ grokdeclarator (const cp_declarator *declarator,
                make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type),
                                   /*complain=*/true);
              else
-               error ("trying to make class `%T' a friend of global scope",
-                         type);
+               error ("trying to make class %qT a friend of global scope",
+                       type);
 
              type = void_type_node;
            }
@@ -7544,38 +7843,32 @@ grokdeclarator (const cp_declarator *declarator,
           && TREE_CODE (type) != UNION_TYPE
           && ! bitfield)
     {
-      error ("abstract declarator `%T' used as declaration", type);
-      unqualified_id = make_anon_name ();
+      error ("abstract declarator %qT used as declaration", type);
+      return error_mark_node;
     }
 
-  /* `void' at top level (not within pointer)
-     is allowed only in typedefs or type names.
-     We don't complain about parms either, but that is because
-     a better error message can be made later.  */
-
-  if (TREE_CODE (type) == VOID_TYPE && decl_context != PARM)
+  /* Only functions may be declared using an operator-function-id.  */
+  if (unqualified_id
+      && IDENTIFIER_OPNAME_P (unqualified_id)
+      && TREE_CODE (type) != FUNCTION_TYPE
+      && TREE_CODE (type) != METHOD_TYPE)
     {
-      if (! unqualified_id)
-       error ("unnamed variable or field declared void");
-      else if (TREE_CODE (unqualified_id) == IDENTIFIER_NODE)
-       {
-         if (IDENTIFIER_OPNAME_P (unqualified_id))
-           abort ();
-         else
-           error ("variable or field `%s' declared void", name);
-       }
-      else
-       error ("variable or field declared void");
-      type = integer_type_node;
+      error ("declaration of %qD as non-function", unqualified_id);
+      return error_mark_node;
     }
 
+  /* We don't check parameter types here because we can emit a better
+     error message later.  */
+  if (decl_context != PARM)
+    type = check_var_type (unqualified_id, type);
+
   /* Now create the decl, which may be a VAR_DECL, a PARM_DECL
      or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE.  */
 
   if (decl_context == PARM || decl_context == CATCHPARM)
     {
       if (ctype || in_namespace)
-       error ("cannot use `::' in parameter declaration");
+       error ("cannot use %<::%> in parameter declaration");
 
       /* A parameter declared as an array of T is really a pointer to T.
         One declared as a function is really a pointer to a function.
@@ -7620,7 +7913,7 @@ grokdeclarator (const cp_declarator *declarator,
        else if (in_namespace && !friendp)
          {
            /* Something like struct S { int N::j; };  */
-           error ("invalid use of `::'");
+           error ("invalid use of %<::%>");
            decl = NULL_TREE;
          }
        else if (TREE_CODE (type) == FUNCTION_TYPE)
@@ -7632,7 +7925,7 @@ grokdeclarator (const cp_declarator *declarator,
               typedefs.  */
            if (friendp && unqualified_id == ridpointers[(int) RID_SIGNED])
              {
-               error ("function `%D' cannot be declared friend",
+               error ("function %qD cannot be declared friend",
                       unqualified_id);
                friendp = 0;
              }
@@ -7644,7 +7937,7 @@ grokdeclarator (const cp_declarator *declarator,
 
                if (ctype == NULL_TREE)
                  {
-                   error ("can't make `%D' into a method -- not in a class",
+                   error ("can't make %qD into a method -- not in a class",
                           unqualified_id);
                    return void_type_node;
                  }
@@ -7653,7 +7946,7 @@ grokdeclarator (const cp_declarator *declarator,
                   ARM 9.5 */
                if (virtualp && TREE_CODE (ctype) == UNION_TYPE)
                  {
-                   error ("function `%D' declared virtual inside a union",
+                   error ("function %qD declared virtual inside a union",
                           unqualified_id);
                    return void_type_node;
                  }
@@ -7662,13 +7955,14 @@ grokdeclarator (const cp_declarator *declarator,
                  {
                    if (virtualp)
                      {
-                       error ("`%D' cannot be declared virtual, since it is always static",
+                       error ("%qD cannot be declared virtual, since it "
+                               "is always static",
                               unqualified_id);
                        virtualp = 0;
                      }
                  }
                else if (staticp < 2)
-                 type = build_method_type_directly (ctype, 
+                 type = build_method_type_directly (ctype,
                                                     TREE_TYPE (type),
                                                     TYPE_ARG_TYPES (type));
              }
@@ -7685,7 +7979,7 @@ grokdeclarator (const cp_declarator *declarator,
                               unqualified_id,
                               virtualp, flags, quals, raises,
                               friendp ? -1 : 0, friendp, publicp, inlinep,
-                              funcdef_flag, template_count, in_namespace);
+                              funcdef_flag, template_count, in_namespace, attrlist);
            if (decl == NULL_TREE)
              return decl;
 #if 0
@@ -7732,7 +8026,7 @@ grokdeclarator (const cp_declarator *declarator,
                               unqualified_id,
                               virtualp, flags, quals, raises,
                               friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
-                              template_count, in_namespace);
+                              template_count, in_namespace, attrlist);
            if (decl == NULL_TREE)
              return NULL_TREE;
          }
@@ -7741,9 +8035,9 @@ grokdeclarator (const cp_declarator *declarator,
                 && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
          {
            if (unqualified_id)
-             error ("field `%D' has incomplete type", unqualified_id);
+             error ("field %qD has incomplete type", unqualified_id);
            else
-             error ("name `%T' has incomplete type", type);
+             error ("name %qT has incomplete type", type);
 
            /* If we're instantiating a template, tell them which
               instantiation made the field's type be incomplete.  */
@@ -7752,8 +8046,8 @@ grokdeclarator (const cp_declarator *declarator,
                && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type))
                && declspecs->type
                && declspecs->type == type)
-             error ("  in instantiation of template `%T'",
-                       current_class_type);
+             error ("  in instantiation of template %qT",
+                     current_class_type);
 
            type = error_mark_node;
            decl = NULL_TREE;
@@ -7762,7 +8056,7 @@ grokdeclarator (const cp_declarator *declarator,
          {
            if (friendp)
              {
-               error ("`%E' is neither function nor member function; "
+               error ("%qE is neither function nor member function; "
                        "cannot be declared friend", unqualified_id);
                friendp = 0;
              }
@@ -7784,7 +8078,7 @@ grokdeclarator (const cp_declarator *declarator,
                    if (decl == error_mark_node)
                      return error_mark_node;
                  }
-               
+
                decl = do_friend (ctype, unqualified_id, decl,
                                  *attrlist, flags, quals, funcdef_flag);
                return decl;
@@ -7813,9 +8107,9 @@ grokdeclarator (const cp_declarator *declarator,
                       the rest of the compiler does not correctly
                       handle the initialization unless the member is
                       static so we make it static below.  */
-                   pedwarn ("ISO C++ forbids initialization of member `%D'",
+                   pedwarn ("ISO C++ forbids initialization of member %qD",
                             unqualified_id);
-                   pedwarn ("making `%D' static", unqualified_id);
+                   pedwarn ("making %qD static", unqualified_id);
                    staticp = 1;
                  }
 
@@ -7837,9 +8131,11 @@ grokdeclarator (const cp_declarator *declarator,
                /* C++ allows static class members.  All other work
                   for this is done by grokfield.  */
                decl = build_lang_decl (VAR_DECL, unqualified_id, type);
-               TREE_STATIC (decl) = 1;
-               /* In class context, 'static' means public access.  */
-               TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = 1;
+               set_linkage_for_static_data_member (decl);
+               /* Even if there is an in-class initialization, DECL
+                  is considered undefined until an out-of-class
+                  definition is provided.  */
+               DECL_EXTERNAL (decl) = 1;
              }
            else
              {
@@ -7871,11 +8167,11 @@ grokdeclarator (const cp_declarator *declarator,
          original_name = unqualified_id;
 
        if (storage_class == sc_auto)
-         error ("storage class `auto' invalid for function `%s'", name);
+         error ("storage class %<auto%> invalid for function %qs", name);
        else if (storage_class == sc_register)
-         error ("storage class `register' invalid for function `%s'", name);
+         error ("storage class %<register%> invalid for function %qs", name);
        else if (thread_p)
-         error ("storage class `__thread' invalid for function `%s'", name);
+         error ("storage class %<__thread%> invalid for function %qs", name);
 
        /* Function declaration not at top level.
           Storage classes other than `extern' are not allowed
@@ -7886,22 +8182,24 @@ grokdeclarator (const cp_declarator *declarator,
            && pedantic)
          {
            if (storage_class == sc_static)
-             pedwarn ("`static' specified invalid for function `%s' declared out of global scope", name);
+             pedwarn ("%<static%> specified invalid for function %qs "
+                       "declared out of global scope", name);
            else
-             pedwarn ("`inline' specifier invalid for function `%s' declared out of global scope", name);
+             pedwarn ("%<inline%> specifier invalid for function %qs "
+                       "declared out of global scope", name);
          }
 
        if (ctype == NULL_TREE)
          {
            if (virtualp)
              {
-               error ("virtual non-class function `%s'", name);
+               error ("virtual non-class function %qs", name);
                virtualp = 0;
              }
          }
        else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
                 && !NEW_DELETE_OPNAME_P (original_name))
-         type = build_method_type_directly (ctype, 
+         type = build_method_type_directly (ctype,
                                             TREE_TYPE (type),
                                             TYPE_ARG_TYPES (type));
 
@@ -7914,7 +8212,7 @@ grokdeclarator (const cp_declarator *declarator,
                           virtualp, flags, quals, raises,
                           1, friendp,
                           publicp, inlinep, funcdef_flag,
-                          template_count, in_namespace);
+                          template_count, in_namespace, attrlist);
        if (decl == NULL_TREE)
          return NULL_TREE;
 
@@ -7926,7 +8224,8 @@ grokdeclarator (const cp_declarator *declarator,
               declaring main to be static.  */
            if (TREE_CODE (type) == METHOD_TYPE)
              {
-               pedwarn ("cannot declare member function `%D' to have static linkage", decl);
+               pedwarn ("cannot declare member function %qD to have "
+                         "static linkage", decl);
                invalid_static = 1;
              }
            else if (current_function_decl)
@@ -7948,7 +8247,7 @@ grokdeclarator (const cp_declarator *declarator,
        /* It's a variable.  */
 
        /* An uninitialized decl with `extern' is a reference.  */
-       decl = grokvardecl (type, unqualified_id, 
+       decl = grokvardecl (type, unqualified_id,
                            declspecs,
                            initialized,
                            (type_quals & TYPE_QUAL_CONST) != 0,
@@ -7961,19 +8260,21 @@ grokdeclarator (const cp_declarator *declarator,
            DECL_CONTEXT (decl) = ctype;
            if (staticp == 1)
              {
-                pedwarn ("`static' may not be used when defining (as opposed to declaring) a static data member");
+                pedwarn ("%<static%> may not be used when defining "
+                         "(as opposed to declaring) a static data member");
                staticp = 0;
                storage_class = sc_none;
              }
            if (storage_class == sc_register && TREE_STATIC (decl))
              {
-               error ("static member `%D' declared `register'", decl);
+               error ("static member %qD declared %<register%>", decl);
                storage_class = sc_none;
              }
            if (storage_class == sc_extern && pedantic)
              {
-               pedwarn ("cannot explicitly declare member `%#D' to have extern linkage",
-                           decl);
+               pedwarn ("cannot explicitly declare member %q#D to have "
+                         "extern linkage",
+                         decl);
                storage_class = sc_none;
              }
          }
@@ -8008,6 +8309,8 @@ require_complete_types_for_parms (tree parms)
 {
   for (; parms; parms = TREE_CHAIN (parms))
     {
+      if (dependent_type_p (TREE_TYPE (parms)))
+       continue;
       if (VOID_TYPE_P (TREE_TYPE (parms)))
         /* grokparms will have already issued an error.  */
         TREE_TYPE (parms) = error_mark_node;
@@ -8112,11 +8415,11 @@ check_default_argument (tree decl, tree arg)
       || !can_convert_arg (decl_type, TREE_TYPE (arg), arg))
     {
       if (decl)
-       error ("default argument for `%#D' has type `%T'",
-                 decl, TREE_TYPE (arg));
+       error ("default argument for %q#D has type %qT",
+               decl, TREE_TYPE (arg));
       else
-       error ("default argument for parameter of type `%T' has type `%T'",
-                 decl_type, TREE_TYPE (arg));
+       error ("default argument for parameter of type %qT has type %qT",
+               decl_type, TREE_TYPE (arg));
 
       return error_mark_node;
     }
@@ -8132,8 +8435,7 @@ check_default_argument (tree decl, tree arg)
                                      NULL);
   if (var)
     {
-      error ("default argument `%E' uses local variable `%D'",
-               arg, var);
+      error ("default argument %qE uses local variable %qD", arg, var);
       return error_mark_node;
     }
 
@@ -8201,7 +8503,7 @@ grokparms (cp_parameter_declarator *first_parm, tree *parms)
          type = cp_build_qualified_type (type, 0);
          if (TREE_CODE (type) == METHOD_TYPE)
            {
-             error ("parameter `%D' invalidly declared method type", decl);
+             error ("parameter %qD invalidly declared method type", decl);
              type = build_pointer_type (type);
              TREE_TYPE (decl) = type;
            }
@@ -8225,8 +8527,9 @@ grokparms (cp_parameter_declarator *first_parm, tree *parms)
                  t = TREE_TYPE (t);
                }
              if (TREE_CODE (t) == ARRAY_TYPE)
-               error ("parameter `%D' includes %s to array of unknown bound `%T'",
-                         decl, ptr ? "pointer" : "reference", t);
+               error ("parameter %qD includes %s to array of unknown "
+                       "bound %qT",
+                       decl, ptr ? "pointer" : "reference", t);
            }
 
          if (!any_error && init)
@@ -8273,16 +8576,17 @@ copy_fn_p (tree d)
   tree args;
   tree arg_type;
   int result = 1;
-  
-  my_friendly_assert (DECL_FUNCTION_MEMBER_P (d), 20011208);
 
-  if (DECL_TEMPLATE_INFO (d) && is_member_template (DECL_TI_TEMPLATE (d)))
+  gcc_assert (DECL_FUNCTION_MEMBER_P (d));
+
+  if (DECL_TEMPLATE_INFO (d) 
+      && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (d)))
     /* Instantiations of template member functions are never copy
        functions.  Note that member functions of templated classes are
        represented as template functions internally, and we must
        accept those as copy functions.  */
     return 0;
-    
+
   args = FUNCTION_FIRST_USER_PARMTYPE (d);
   if (!args)
     return 0;
@@ -8302,7 +8606,7 @@ copy_fn_p (tree d)
     }
   else
     return 0;
-  
+
   args = TREE_CHAIN (args);
 
   if (args && args != void_list_node && !TREE_PURPOSE (args))
@@ -8321,11 +8625,11 @@ void grok_special_member_properties (tree decl)
   else if (DECL_CONSTRUCTOR_P (decl))
     {
       int ctor = copy_fn_p (decl);
-      
+
       if (ctor > 0)
        {
          /* [class.copy]
-             
+
             A non-template constructor for class X is a copy
             constructor if its first parameter is of type X&, const
             X&, volatile X& or const volatile X&, and either there
@@ -8341,13 +8645,13 @@ void grok_special_member_properties (tree decl)
   else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
     {
       /* [class.copy]
-         
+
         A non-template assignment operator for class X is a copy
         assignment operator if its parameter is of type X, X&, const
         X&, volatile X& or const volatile X&.  */
-      
+
       int assop = copy_fn_p (decl);
-      
+
       if (assop)
        {
          TYPE_HAS_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
@@ -8368,12 +8672,12 @@ grok_ctor_properties (tree ctype, tree decl)
   if (ctor_parm < 0)
     {
       /* [class.copy]
-         
+
         A declaration of a constructor for a class X is ill-formed if
         its first parameter is of type (optionally cv-qualified) X
         and either there are no other parameters or else all other
         parameters have default arguments.
-         
+
         We *don't* complain about member template instantiations that
         have this form, though; they can occur as we try to decide
         what constructor to use during overload resolution.  Since
@@ -8382,11 +8686,11 @@ grok_ctor_properties (tree ctype, tree decl)
         or implicitly defined), there's no need to worry about their
         existence.  Theoretically, they should never even be
         instantiated, but that's hard to forestall.  */
-      error ("invalid constructor; you probably meant `%T (const %T&)'",
+      error ("invalid constructor; you probably meant %<%T (const %T&)%>",
                ctype, ctype);
       return 0;
     }
-  
+
   return 1;
 }
 
@@ -8462,10 +8766,10 @@ grok_op_properties (tree decl, int friendp, bool complain)
 #include "operators.def"
 #undef DEF_OPERATOR
 
-       abort ();
+       gcc_unreachable ();
       }
     while (0);
-  my_friendly_assert (operator_code != LAST_CPLUS_TREE_CODE, 20000526);
+  gcc_assert (operator_code != LAST_CPLUS_TREE_CODE);
   SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
 
   if (! friendp)
@@ -8506,9 +8810,9 @@ grok_op_properties (tree decl, int friendp, bool complain)
       if (DECL_NAMESPACE_SCOPE_P (decl))
        {
          if (CP_DECL_CONTEXT (decl) != global_namespace)
-           error ("`%D' may not be declared within a namespace", decl);
+           error ("%qD may not be declared within a namespace", decl);
          else if (!TREE_PUBLIC (decl))
-           error ("`%D' may not be declared as static", decl);
+           error ("%qD may not be declared as static", decl);
        }
     }
 
@@ -8528,13 +8832,14 @@ grok_op_properties (tree decl, int friendp, bool complain)
              || operator_code == COMPONENT_REF
              || operator_code == ARRAY_REF
              || operator_code == NOP_EXPR)
-           error ("`%D' must be a nonstatic member function", decl);
+           error ("%qD must be a nonstatic member function", decl);
          else
            {
              tree p;
 
              if (DECL_STATIC_FUNCTION_P (decl))
-               error ("`%D' must be either a non-static member function or a non-member function", decl);
+               error ("%qD must be either a non-static member "
+                       "function or a non-member function", decl);
 
              for (p = argtypes; p && p != void_list_node; p = TREE_CHAIN (p))
                {
@@ -8551,7 +8856,7 @@ grok_op_properties (tree decl, int friendp, bool complain)
                  if (!complain)
                    return false;
 
-                 error ("`%D' must have an argument of class or "
+                 error ("%qD must have an argument of class or "
                         "enumerated type",
                         decl);
                  ok = false;
@@ -8586,7 +8891,8 @@ grok_op_properties (tree decl, int friendp, bool complain)
                what = "a base class";
 
              if (what && warn_conversion)
-               warning ("conversion to %s%s will never use a type conversion operator",
+               warning ("conversion to %s%s will never use a type "
+                         "conversion operator",
                         ref ? "a reference to " : "", what);
            }
        }
@@ -8632,7 +8938,7 @@ grok_op_properties (tree decl, int friendp, bool complain)
                  break;
 
                default:
-                 abort ();
+                 gcc_unreachable ();
                }
 
              SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
@@ -8643,20 +8949,20 @@ grok_op_properties (tree decl, int friendp, bool complain)
                  && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
                {
                  if (methodp)
-                   error ("postfix `%D' must take `int' as its argument",
+                   error ("postfix %qD must take %<int%> as its argument",
                              decl);
                  else
                    error
-                     ("postfix `%D' must take `int' as its second argument",
+                     ("postfix %qD must take %<int%> as its second argument",
                       decl);
                }
            }
          else
            {
              if (methodp)
-               error ("`%D' must take either zero or one argument", decl);
+               error ("%qD must take either zero or one argument", decl);
              else
-               error ("`%D' must take either one or two arguments", decl);
+               error ("%qD must take either one or two arguments", decl);
            }
 
          /* More Effective C++ rule 6.  */
@@ -8677,13 +8983,13 @@ grok_op_properties (tree decl, int friendp, bool complain)
                  if (TREE_CODE (ret) != REFERENCE_TYPE
                      || !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
                                       arg))
-                   warning ("prefix `%D' should return `%T'", decl,
-                               build_reference_type (arg));
+                   warning ("prefix %qD should return %qT", decl,
+                             build_reference_type (arg));
                }
              else
                {
                  if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
-                   warning ("postfix `%D' should return `%T'", decl, arg);
+                   warning ("postfix %qD should return %qT", decl, arg);
                }
            }
        }
@@ -8692,9 +8998,9 @@ grok_op_properties (tree decl, int friendp, bool complain)
          if (arity != 1)
            {
              if (methodp)
-               error ("`%D' must take `void'", decl);
+               error ("%qD must take %<void%>", decl);
              else
-               error ("`%D' must take exactly one argument", decl);
+               error ("%qD must take exactly one argument", decl);
            }
        }
       else /* if (binary_op_p (operator_code)) */
@@ -8702,9 +9008,9 @@ grok_op_properties (tree decl, int friendp, bool complain)
          if (arity != 2)
            {
              if (methodp)
-               error ("`%D' must take exactly one argument", decl);
+               error ("%qD must take exactly one argument", decl);
              else
-               error ("`%D' must take exactly two arguments", decl);
+               error ("%qD must take exactly two arguments", decl);
            }
 
          /* More Effective C++ rule 7.  */
@@ -8712,8 +9018,8 @@ grok_op_properties (tree decl, int friendp, bool complain)
              && (operator_code == TRUTH_ANDIF_EXPR
                  || operator_code == TRUTH_ORIF_EXPR
                  || operator_code == COMPOUND_EXPR))
-           warning ("user-defined `%D' always evaluates both arguments",
-                       decl);
+           warning ("user-defined %qD always evaluates both arguments",
+                     decl);
        }
 
       /* Effective C++ rule 23.  */
@@ -8726,7 +9032,7 @@ grok_op_properties (tree decl, int friendp, bool complain)
              || operator_code == MULT_EXPR
              || operator_code == TRUNC_MOD_EXPR)
          && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE)
-       warning ("`%D' should return by value", decl);
+       warning ("%qD should return by value", decl);
 
       /* [over.oper]/8 */
       for (; argtypes && argtypes != void_list_node;
@@ -8738,10 +9044,10 @@ grok_op_properties (tree decl, int friendp, bool complain)
                || operator_code == POSTDECREMENT_EXPR)
               {
                 if (pedantic)
-                  pedwarn ("`%D' cannot have default arguments", decl);
+                  pedwarn ("%qD cannot have default arguments", decl);
               }
             else
-              error ("`%D' cannot have default arguments", decl);
+              error ("%qD cannot have default arguments", decl);
           }
 
     }
@@ -8749,6 +9055,8 @@ grok_op_properties (tree decl, int friendp, bool complain)
   return ok;
 }
 \f
+/* Return a string giving the keyword associate with CODE.  */
+
 static const char *
 tag_name (enum tag_types code)
 {
@@ -8759,11 +9067,13 @@ tag_name (enum tag_types code)
     case class_type:
       return "class";
     case union_type:
-      return "union ";
+      return "union";
     case enum_type:
       return "enum";
+    case typename_type:
+      return "typename";
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -8791,7 +9101,15 @@ check_elaborated_type_specifier (enum tag_types tag_code,
 
   type = TREE_TYPE (decl);
 
-  /*   [dcl.type.elab] 
+  /* Check TEMPLATE_TYPE_PARM first because DECL_IMPLICIT_TYPEDEF_P
+     is false for this case as well.  */
+  if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+    {
+      error ("using template type parameter %qT after %qs",
+            type, tag_name (tag_code));
+      return error_mark_node;
+    }
+  /*   [dcl.type.elab]
 
        If the identifier resolves to a typedef-name or a template
        type-parameter, the elaborated-type-specifier is ill-formed.
@@ -8799,29 +9117,28 @@ check_elaborated_type_specifier (enum tag_types tag_code,
      In other words, the only legitimate declaration to use in the
      elaborated type specifier is the implicit typedef created when
      the type is declared.  */
-  if (!DECL_IMPLICIT_TYPEDEF_P (decl))
+  else if (!DECL_IMPLICIT_TYPEDEF_P (decl)
+          && tag_code != typename_type)
     {
-      error ("using typedef-name `%D' after `%s'", decl, tag_name (tag_code));
-      return IS_AGGR_TYPE (type) ? type : error_mark_node;
-    }
-    
-  if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
-    {
-      error ("using template type parameter `%T' after `%s'",
-            type, tag_name (tag_code));
+      error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
+      cp_error_at ("%qD has a previous declaration here", decl);
       return error_mark_node;
     }
   else if (TREE_CODE (type) != RECORD_TYPE
           && TREE_CODE (type) != UNION_TYPE
-          && tag_code != enum_type)
+          && tag_code != enum_type
+          && tag_code != typename_type)
     {
-      error ("`%T' referred to as `%s'", type, tag_name (tag_code));
+      error ("%qT referred to as %qs", type, tag_name (tag_code));
+      cp_error_at ("%qT has a previous declaration here", type);
       return error_mark_node;
     }
   else if (TREE_CODE (type) != ENUMERAL_TYPE
-          && tag_code == enum_type)
+          && tag_code == enum_type
+          && tag_code != typename_type)
     {
-      error ("`%T' referred to as enum", type);
+      error ("%qT referred to as enum", type);
+      cp_error_at ("%qT has a previous declaration here", type);
       return error_mark_node;
     }
   else if (!allow_template_p
@@ -8836,7 +9153,7 @@ check_elaborated_type_specifier (enum tag_types tag_code,
 
         then the required template argument is missing.  */
 
-      error ("template argument required for `%s %T'",
+      error ("template argument required for %<%s %T%>",
             tag_name (tag_code),
             DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)));
       return error_mark_node;
@@ -8845,31 +9162,91 @@ check_elaborated_type_specifier (enum tag_types tag_code,
   return type;
 }
 
+/* Lookup NAME in elaborate type specifier in scope according to
+   SCOPE and issue diagnostics if necessary.
+   Return *_TYPE node upon success, NULL_TREE when the NAME is not
+   found, and ERROR_MARK_NODE for type error.  */
+
+static tree
+lookup_and_check_tag (enum tag_types tag_code, tree name,
+                     tag_scope scope, bool template_header_p)
+{
+  tree t;
+  tree decl;
+  if (scope == ts_global)
+    decl = lookup_name (name, 2);
+  else
+    decl = lookup_type_scope (name, scope);
+
+  if (decl && DECL_CLASS_TEMPLATE_P (decl))
+    decl = DECL_TEMPLATE_RESULT (decl);
+
+  if (decl && TREE_CODE (decl) == TYPE_DECL)
+    {
+      /* Look for invalid nested type:
+          class C {
+            class C {};
+          };  */
+      if (scope == ts_current && DECL_SELF_REFERENCE_P (decl))
+       {
+         error ("%qD has the same name as the class in which it is "
+                "declared",
+                decl);
+         return error_mark_node;
+       }
+
+      /* Two cases we need to consider when deciding if a class
+        template is allowed as an elaborated type specifier:
+        1. It is a self reference to its own class.
+        2. It comes with a template header.
+
+        For example:
+
+          template <class T> class C {
+            class C *c1;               // DECL_SELF_REFERENCE_P is true
+            class D;
+          };
+          template <class U> class C; // template_header_p is true
+          template <class T> class C<T>::D {
+            class C *c2;               // DECL_SELF_REFERENCE_P is true
+          };  */
+
+      t = check_elaborated_type_specifier (tag_code,
+                                          decl,
+                                          template_header_p
+                                          | DECL_SELF_REFERENCE_P (decl));
+      return t;
+    }
+  else
+    return NULL_TREE;
+}
+
 /* Get the struct, enum or union (TAG_CODE says which) with tag NAME.
    Define the tag as a forward-reference if it is not defined.
 
    If a declaration is given, process it here, and report an error if
    multiple declarations are not identical.
 
-   GLOBALIZE is false when this is also a definition.  Only look in
+   SCOPE is TS_CURRENT when this is also a definition.  Only look in
    the current frame for the name (since C++ allows new names in any
-   scope.)
+   scope.)  It is TS_WITHIN_ENCLOSING_NON_CLASS if this is a friend
+   declaration.  Only look beginning from the current scope outward up
+   till the nearest non-class scope.  Otherwise it is TS_GLOBAL.
 
    TEMPLATE_HEADER_P is true when this declaration is preceded by
    a set of template parameters.  */
 
 tree
 xref_tag (enum tag_types tag_code, tree name,
-         bool globalize, bool template_header_p)
+         tag_scope scope, bool template_header_p)
 {
   enum tree_code code;
   tree t;
-  struct cp_binding_level *b = current_binding_level;
   tree context = NULL_TREE;
 
   timevar_push (TV_NAME_LOOKUP);
 
-  my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 0);
+  gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
 
   switch (tag_code)
     {
@@ -8884,93 +9261,62 @@ xref_tag (enum tag_types tag_code, tree name,
       code = ENUMERAL_TYPE;
       break;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
-  if (! globalize)
-    {
-      /* If we know we are defining this tag, only look it up in
-        this scope and don't try to find it as a type.  */
-      t = lookup_tag (code, name, b, 1);
-    }
+  /* In case of anonymous name, xref_tag is only called to
+     make type node and push name.  Name lookup is not required.  */
+  if (ANON_AGGRNAME_P (name))
+    t = NULL_TREE;
   else
-    {
-      tree decl = lookup_name (name, 2);
-
-      if (decl && DECL_CLASS_TEMPLATE_P (decl))
-       decl = DECL_TEMPLATE_RESULT (decl);
-
-      if (decl && TREE_CODE (decl) == TYPE_DECL)
-       {
-         /* Two cases we need to consider when deciding if a class
-            template is allowed as an elaborated type specifier:
-            1. It is a self reference to its own class.
-            2. It comes with a template header.
+    t = lookup_and_check_tag  (tag_code, name,
+                              scope, template_header_p);
 
-            For example:
+  if (t == error_mark_node)
+    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
 
-              template <class T> class C {
-                class C *c1;           // DECL_SELF_REFERENCE_P is true
-                class D;
-              };
-              template <class U> class C; // template_header_p is true
-              template <class T> class C<T>::D {
-                class C *c2;           // DECL_SELF_REFERENCE_P is true
-              };  */
-
-         t = check_elaborated_type_specifier (tag_code,
-                                              decl,
-                                              template_header_p
-                                              | DECL_SELF_REFERENCE_P (decl));
-         if (t == error_mark_node)
-           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
-       }
-      else
-       t = NULL_TREE;
-
-      if (t && current_class_type
-         && template_class_depth (current_class_type)
-         && template_header_p)
-       {
-         /* Since GLOBALIZE is nonzero, we are not looking at a
-            definition of this tag.  Since, in addition, we are currently
-            processing a (member) template declaration of a template
-            class, we must be very careful; consider:
+  if (scope != ts_current && t && current_class_type
+      && template_class_depth (current_class_type)
+      && template_header_p)
+    {
+      /* Since SCOPE is not TS_CURRENT, we are not looking at a
+        definition of this tag.  Since, in addition, we are currently
+        processing a (member) template declaration of a template
+        class, we must be very careful; consider:
 
-              template <class X>
-              struct S1
+          template <class X>
+          struct S1
 
-              template <class U>
-              struct S2
-              { template <class V>
-              friend struct S1; };
+          template <class U>
+          struct S2
+          { template <class V>
+          friend struct S1; };
 
-            Here, the S2::S1 declaration should not be confused with the
-            outer declaration.  In particular, the inner version should
-            have a template parameter of level 2, not level 1.  This
-            would be particularly important if the member declaration
-            were instead:
+        Here, the S2::S1 declaration should not be confused with the
+        outer declaration.  In particular, the inner version should
+        have a template parameter of level 2, not level 1.  This
+        would be particularly important if the member declaration
+        were instead:
 
-              template <class V = U> friend struct S1;
+          template <class V = U> friend struct S1;
 
-            say, when we should tsubst into `U' when instantiating
-            S2.  On the other hand, when presented with:
+        say, when we should tsubst into `U' when instantiating
+        S2.  On the other hand, when presented with:
 
-                template <class T>
-                struct S1 {
-                  template <class U>
-                  struct S2 {};
-                  template <class U>
-                  friend struct S2;
-                };
+          template <class T>
+          struct S1 {
+            template <class U>
+            struct S2 {};
+            template <class U>
+            friend struct S2;
+          };
 
-              we must find the inner binding eventually.  We
-             accomplish this by making sure that the new type we
-             create to represent this declaration has the right
-             TYPE_CONTEXT.  */
-         context = TYPE_CONTEXT (t);
-         t = NULL_TREE;
-       }
+        we must find the inner binding eventually.  We
+        accomplish this by making sure that the new type we
+        create to represent this declaration has the right
+        TYPE_CONTEXT.  */
+      context = TYPE_CONTEXT (t);
+      t = NULL_TREE;
     }
 
   if (! t)
@@ -8981,25 +9327,26 @@ xref_tag (enum tag_types tag_code, tree name,
         the forward-reference will be altered into a real type.  */
       if (code == ENUMERAL_TYPE)
        {
-         error ("use of enum `%#D' without previous declaration", name);
+         error ("use of enum %q#D without previous declaration", name);
          POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
        }
       else
        {
          t = make_aggr_type (code);
          TYPE_CONTEXT (t) = context;
-         pushtag (name, t, globalize);
+         /* pushtag only cares whether SCOPE is zero or not.  */
+         t = pushtag (name, t, scope != ts_current);
        }
     }
   else
     {
-      if (!globalize && processing_template_decl && IS_AGGR_TYPE (t))
+      if (template_header_p && IS_AGGR_TYPE (t))
        redeclare_class_template (t, current_template_parms);
-      else if (!processing_template_decl 
+      else if (!processing_template_decl
               && CLASS_TYPE_P (t)
               && CLASSTYPE_IS_TEMPLATE (t))
        {
-         error ("redeclaration of `%T' as a non-template", t);
+         error ("redeclaration of %qT as a non-template", t);
          t = error_mark_node;
        }
     }
@@ -9008,7 +9355,7 @@ xref_tag (enum tag_types tag_code, tree name,
 }
 
 tree
-xref_tag_from_type (tree old, tree id, int globalize)
+xref_tag_from_type (tree old, tree id, tag_scope scope)
 {
   enum tag_types tag_kind;
 
@@ -9020,7 +9367,7 @@ xref_tag_from_type (tree old, tree id, int globalize)
   if (id == NULL_TREE)
     id = TYPE_IDENTIFIER (old);
 
-  return xref_tag (tag_kind, id, globalize, false);
+  return xref_tag (tag_kind, id, scope, false);
 }
 
 /* Create the binfo hierarchy for REF with (possibly NULL) base list
@@ -9033,8 +9380,8 @@ xref_basetypes (tree ref, tree base_list)
 {
   tree *basep;
   tree binfo, base_binfo;
-  unsigned max_vbases = 0; /* Maxium direct & indirect virtual bases. */
-  unsigned max_bases = 0;  /* Maxium direct bases.  */
+  unsigned max_vbases = 0; /* Maximum direct & indirect virtual bases.  */
+  unsigned max_bases = 0;  /* Maximum direct bases.  */
   int i;
   tree default_access;
   tree igo_prev; /* Track Inheritance Graph Order.  */
@@ -9052,11 +9399,11 @@ xref_basetypes (tree ref, tree base_list)
      instantiated.  This ensures that if we call ourselves recursively
      we do not get confused about which classes are marked and which
      are not.  */
-  basep = &base_list; 
-  while (*basep) 
+  basep = &base_list;
+  while (*basep)
     {
       tree basetype = TREE_VALUE (*basep);
-      
+
       if (!(processing_template_decl && uses_template_parms (basetype))
          && !complete_type_or_else (basetype, NULL))
        /* An incomplete type.  Remove it from the list.  */
@@ -9072,49 +9419,41 @@ xref_basetypes (tree ref, tree base_list)
        }
     }
 
-  SET_CLASSTYPE_MARKED (ref);
+  TYPE_MARKED_P (ref) = 1;
 
   /* The binfo slot should be empty, unless this is an (ill-formed)
      redefinition.  */
-  my_friendly_assert (!TYPE_BINFO (ref) || TYPE_SIZE (ref), 20040706);
-  my_friendly_assert (TYPE_MAIN_VARIANT (ref) == ref, 20040712);
-  
+  gcc_assert (!TYPE_BINFO (ref) || TYPE_SIZE (ref));
+  gcc_assert (TYPE_MAIN_VARIANT (ref) == ref);
+
   binfo = make_tree_binfo (max_bases);
+
   TYPE_BINFO (ref) = binfo;
   BINFO_OFFSET (binfo) = size_zero_node;
   BINFO_TYPE (binfo) = ref;
-  
+
   if (max_bases)
     {
-      BINFO_BASE_ACCESSES (binfo) = make_tree_vec (max_bases);
+      BINFO_BASE_ACCESSES (binfo) = VEC_alloc (tree, max_bases);
       /* An aggregate cannot have baseclasses.  */
       CLASSTYPE_NON_AGGREGATE (ref) = 1;
-      
+
       if (TREE_CODE (ref) == UNION_TYPE)
-       error ("derived union `%T' invalid", ref);
+       error ("derived union %qT invalid", ref);
     }
-      
+
   if (max_bases > 1)
     {
-      TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
-      /* If there is more than one non-empty they cannot be at the
-        same address.  */
-      TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
-      
       if (TYPE_FOR_JAVA (ref))
-       error ("Java class '%T' cannot have multiple bases", ref);
+       error ("Java class %qT cannot have multiple bases", ref);
     }
-  
+
   if (max_vbases)
     {
       CLASSTYPE_VBASECLASSES (ref) = VEC_alloc (tree, max_vbases);
-      TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
-      /* Converting to a virtual base class requires looking up the
-        offset of the virtual base.  */
-      TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
-      
+
       if (TYPE_FOR_JAVA (ref))
-       error ("Java class '%T' cannot have virtual bases", ref);
+       error ("Java class %qT cannot have virtual bases", ref);
     }
 
   for (igo_prev = binfo; base_list; base_list = TREE_CHAIN (base_list))
@@ -9122,10 +9461,10 @@ xref_basetypes (tree ref, tree base_list)
       tree access = TREE_PURPOSE (base_list);
       int via_virtual = TREE_TYPE (base_list) != NULL_TREE;
       tree basetype = TREE_VALUE (base_list);
-      
+
       if (access == access_default_node)
        access = default_access;
-         
+
       if (TREE_CODE (basetype) == TYPE_DECL)
        basetype = TREE_TYPE (basetype);
       if (TREE_CODE (basetype) != RECORD_TYPE
@@ -9133,21 +9472,11 @@ xref_basetypes (tree ref, tree base_list)
          && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
          && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM)
        {
-         error ("base type `%T' fails to be a struct or class type",
+         error ("base type %qT fails to be a struct or class type",
                 basetype);
          continue;
        }
-      
-      if (CLASSTYPE_MARKED (basetype))
-       {
-         if (basetype == ref)
-           error ("recursive type `%T' undefined", basetype);
-         else
-           error ("duplicate base type `%T' invalid", basetype);
-         continue;
-       }
-      SET_CLASSTYPE_MARKED (basetype);
-      
+
       if (TYPE_FOR_JAVA (basetype) && (current_lang_depth () == 0))
        TYPE_FOR_JAVA (ref) = 1;
 
@@ -9155,47 +9484,78 @@ xref_basetypes (tree ref, tree base_list)
       if (CLASS_TYPE_P (basetype) && !dependent_type_p (basetype))
        {
          base_binfo = TYPE_BINFO (basetype);
-         /* The orignal basetype could have been a typedef'd type.  */
+         /* The original basetype could have been a typedef'd type.  */
          basetype = BINFO_TYPE (base_binfo);
-         
+
          /* Inherit flags from the base.  */
          TYPE_HAS_NEW_OPERATOR (ref)
            |= TYPE_HAS_NEW_OPERATOR (basetype);
          TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
            |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
          TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
-         TYPE_USES_MULTIPLE_INHERITANCE (ref)
-           |= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
-         TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
-           |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
          TYPE_HAS_CONVERSION (ref) |= TYPE_HAS_CONVERSION (basetype);
+         CLASSTYPE_DIAMOND_SHAPED_P (ref)
+           |= CLASSTYPE_DIAMOND_SHAPED_P (basetype);
+         CLASSTYPE_REPEATED_BASE_P (ref)
+           |= CLASSTYPE_REPEATED_BASE_P (basetype);
        }
       
+      /* We must do this test after we've seen through a typedef
+        type.  */
+      if (TYPE_MARKED_P (basetype))
+       {
+         if (basetype == ref)
+           error ("recursive type %qT undefined", basetype);
+         else
+           error ("duplicate base type %qT invalid", basetype);
+         continue;
+       }
+      TYPE_MARKED_P (basetype) = 1;
+
       base_binfo = copy_binfo (base_binfo, basetype, ref,
                               &igo_prev, via_virtual);
       if (!BINFO_INHERITANCE_CHAIN (base_binfo))
        BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
 
-      TREE_VEC_ELT (BINFO_BASE_ACCESSES (binfo),
-                   BINFO_N_BASE_BINFOS (binfo)) = access;
       BINFO_BASE_APPEND (binfo, base_binfo);
+      BINFO_BASE_ACCESS_APPEND (binfo, access);
     }
 
-  if (max_bases)
-    /* If any bases were invalid, we will have allocated too many
-       slots.  */
-    TREE_VEC_LENGTH (BINFO_BASE_ACCESSES (binfo))
-      = BINFO_N_BASE_BINFOS (binfo);
-  
+  if (VEC_space (tree, CLASSTYPE_VBASECLASSES (ref), 1))
+    /* If we have space in the vbase vector, we must have shared at
+       least one of them, and are therefore diamond shaped.  */
+    CLASSTYPE_DIAMOND_SHAPED_P (ref) = 1;
+
   /* Unmark all the types.  */
   for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
-    CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (base_binfo));
-  CLEAR_CLASSTYPE_MARKED (ref);
+    TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 0;
+  TYPE_MARKED_P (ref) = 0;
+
+  /* Now see if we have a repeated base type.  */
+  if (!CLASSTYPE_REPEATED_BASE_P (ref))
+    {
+      for (base_binfo = binfo; base_binfo;
+          base_binfo = TREE_CHAIN (base_binfo))
+       {
+         if (TYPE_MARKED_P (BINFO_TYPE (base_binfo)))
+           {
+             CLASSTYPE_REPEATED_BASE_P (ref) = 1;
+             break;
+           }
+         TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 1;
+       }
+      for (base_binfo = binfo; base_binfo;
+          base_binfo = TREE_CHAIN (base_binfo))
+       if (TYPE_MARKED_P (BINFO_TYPE (base_binfo)))
+         TYPE_MARKED_P (BINFO_TYPE (base_binfo)) = 0;
+       else
+         break;
+    }
 }
 
 \f
 /* Begin compiling the definition of an enumeration type.
-   NAME is its name (or null if anonymous).
+   NAME is its name.
    Returns the type object, as yet incomplete.
    Also records info about it so that build_enumerator
    may be used to declare the individual values as they are read.  */
@@ -9203,27 +9563,34 @@ xref_basetypes (tree ref, tree base_list)
 tree
 start_enum (tree name)
 {
-  tree enumtype = NULL_TREE;
-  struct cp_binding_level *b = current_binding_level;
+  tree enumtype;
+
+  gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
 
   /* If this is the real definition for a previous forward reference,
      fill in the contents in the same object that used to be the
      forward reference.  */
 
-  if (name != NULL_TREE)
-    enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1);
+  enumtype = lookup_and_check_tag (enum_type, name,
+                                  /*tag_scope=*/ts_current,
+                                  /*template_header_p=*/false);
 
   if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
     {
-      error ("multiple definition of `%#T'", enumtype);
+      error ("multiple definition of %q#T", enumtype);
       error ("%Jprevious definition here", TYPE_MAIN_DECL (enumtype));
       /* Clear out TYPE_VALUES, and start again.  */
       TYPE_VALUES (enumtype) = NULL_TREE;
     }
   else
     {
+      /* In case of error, make a dummy enum to allow parsing to
+        continue.  */
+      if (enumtype == error_mark_node)
+       name = make_anon_name ();
+
       enumtype = make_node (ENUMERAL_TYPE);
-      pushtag (name, enumtype, 0);
+      enumtype = pushtag (name, enumtype, 0);
     }
 
   return enumtype;
@@ -9243,8 +9610,9 @@ finish_enum (tree enumtype)
   tree maxnode;
   tree t;
   bool unsignedp;
+  bool use_short_enum;
   int lowprec;
-  int highprec; 
+  int highprec;
   int precision;
   integer_type_kind itk;
   tree underlying_type = NULL_TREE;
@@ -9258,8 +9626,8 @@ finish_enum (tree enumtype)
      works.  */
   if (processing_template_decl)
     {
-      for (values = TYPE_VALUES (enumtype); 
-          values; 
+      for (values = TYPE_VALUES (enumtype);
+          values;
           values = TREE_CHAIN (values))
        TREE_TYPE (TREE_VALUE (values)) = enumtype;
       if (at_function_scope_p ())
@@ -9272,8 +9640,8 @@ finish_enum (tree enumtype)
     {
       minnode = maxnode = NULL_TREE;
 
-      for (values = TYPE_VALUES (enumtype); 
-          values; 
+      for (values = TYPE_VALUES (enumtype);
+          values;
           values = TREE_CHAIN (values))
        {
          decl = TREE_VALUE (values);
@@ -9294,16 +9662,6 @@ finish_enum (tree enumtype)
            maxnode = value;
          else if (tree_int_cst_lt (value, minnode))
            minnode = value;
-
-         /* Set the TREE_TYPE for the values as well.  That's so that when
-            we call decl_constant_value we get an entity of the right type
-            (but with the constant value).  But first make a copy so we
-            don't clobber shared INTEGER_CSTs.  */
-         if (TREE_TYPE (value) != enumtype)
-           {
-             value = DECL_INITIAL (decl) = copy_node (value);
-             TREE_TYPE (value) = enumtype;
-           }
        }
     }
   else
@@ -9331,13 +9689,19 @@ finish_enum (tree enumtype)
        enumeration.  It is implementation-defined which integral type is
        used as the underlying type for an enumeration except that the
        underlying type shall not be larger than int unless the value of
-       an enumerator cannot fit in an int or unsigned int.  
+       an enumerator cannot fit in an int or unsigned int.
 
      We use "int" or an "unsigned int" as the underlying type, even if
      a smaller integral type would work, unless the user has
-     explicitly requested that we use the smallest possible type.  */
-  for (itk = (flag_short_enums ? itk_char : itk_int); 
-       itk != itk_none; 
+     explicitly requested that we use the smallest possible type.  The
+     user can request that for all enumerations with a command line
+     flag, or for just one enumeration with an attribute.  */
+
+  use_short_enum = flag_short_enums
+    || lookup_attribute ("packed", TYPE_ATTRIBUTES (enumtype));
+
+  for (itk = (use_short_enum ? itk_char : itk_int);
+       itk != itk_none;
        itk++)
     {
       underlying_type = integer_types[itk];
@@ -9352,12 +9716,12 @@ finish_enum (tree enumtype)
         IF no integral type can represent all the enumerator values, the
         enumeration is ill-formed.  */
       error ("no integral type can represent all of the enumerator values "
-            "for `%T'", enumtype);
+            "for %qT", enumtype);
       precision = TYPE_PRECISION (long_long_integer_type_node);
       underlying_type = integer_types[itk_unsigned_long_long];
     }
 
-  /* Compute the minium and maximum values for the type.  
+  /* Compute the minium and maximum values for the type.
 
      [dcl.enum]
 
@@ -9366,11 +9730,18 @@ finish_enum (tree enumtype)
      underlying type in the range bmin to bmax, where bmin and bmax are,
      respectively, the smallest and largest values of the smallest bit-
      field that can store emin and emax.  */
-  TYPE_PRECISION (enumtype) = precision;
+
+  /* The middle-end currently assumes that types with TYPE_PRECISION
+     narrower than their underlying type are suitably zero or sign
+     extended to fill their mode.  g++ doesn't make these guarantees.
+     Until the middle-end can represent such paradoxical types, we
+     set the TYPE_PRECISION to the width of the underlying type.  */
+  TYPE_PRECISION (enumtype) = TYPE_PRECISION (underlying_type);
+
   set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp);
 
   /* [dcl.enum]
-     
+
      The value of sizeof() applied to an enumeration type, an object
      of an enumeration type, or an enumerator, is the value of sizeof()
      applied to the underlying type.  */
@@ -9388,6 +9759,10 @@ finish_enum (tree enumtype)
       decl = TREE_VALUE (values);
       value = perform_implicit_conversion (underlying_type,
                                           DECL_INITIAL (decl));
+
+      /* Do not clobber shared ints.  */
+      value = copy_node (value);
+      
       TREE_TYPE (value) = enumtype;
       DECL_INITIAL (decl) = value;
       TREE_VALUE (values) = value;
@@ -9432,7 +9807,7 @@ build_enumerator (tree name, tree value, tree enumtype)
       /* Validate and default VALUE.  */
       if (value != NULL_TREE)
        {
-         value = decl_constant_value (value);
+         value = integral_constant_value (value);
 
          if (TREE_CODE (value) == INTEGER_CST)
            {
@@ -9441,7 +9816,7 @@ build_enumerator (tree name, tree value, tree enumtype)
            }
          else
            {
-             error ("enumerator value for `%D' not integer constant", name);
+             error ("enumerator value for %qD not integer constant", name);
              value = NULL_TREE;
            }
        }
@@ -9449,19 +9824,26 @@ build_enumerator (tree name, tree value, tree enumtype)
       /* Default based on previous value.  */
       if (value == NULL_TREE)
        {
-         tree prev_value;
-
          if (TYPE_VALUES (enumtype))
            {
-             /* The next value is the previous value ...  */
+             HOST_WIDE_INT hi;
+             unsigned HOST_WIDE_INT lo;
+             tree prev_value;
+             bool overflowed;
+
+             /* The next value is the previous value plus one.  We can
+                safely assume that the previous value is an INTEGER_CST.
+                add_double doesn't know the type of the target expression,
+                so we must check with int_fits_type_p as well.  */
              prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
-             /* ... plus one.  */
-             value = cp_build_binary_op (PLUS_EXPR,
-                                         prev_value,
-                                         integer_one_node);
-
-             if (tree_int_cst_lt (value, prev_value))
-               error ("overflow in enumeration values at `%D'", name);
+             overflowed = add_double (TREE_INT_CST_LOW (prev_value),
+                                      TREE_INT_CST_HIGH (prev_value),
+                                      1, 0, &lo, &hi);
+             value = build_int_cst_wide (TREE_TYPE (prev_value), lo, hi);
+             overflowed |= !int_fits_type_p (value, TREE_TYPE (prev_value));
+
+             if (overflowed)
+               error ("overflow in enumeration values at %qD", name);
            }
          else
            value = integer_zero_node;
@@ -9473,8 +9855,6 @@ build_enumerator (tree name, tree value, tree enumtype)
 
   /* C++ associates enums with global, function, or class declarations.  */
   context = current_scope ();
-  if (!context)
-    context = current_namespace;
 
   /* Build the actual enumeration constant.  Note that the enumeration
     constants have the type of their initializers until the
@@ -9530,9 +9910,11 @@ check_function_type (tree decl, tree current_function_parms)
   /* In a function definition, arg types must be complete.  */
   require_complete_types_for_parms (current_function_parms);
 
+  if (dependent_type_p (return_type))
+    return;
   if (!COMPLETE_OR_VOID_TYPE_P (return_type))
     {
-      error ("return type `%#T' is incomplete", TREE_TYPE (fntype));
+      error ("return type %q#T is incomplete", TREE_TYPE (fntype));
 
       /* Make it return void instead, but don't change the
         type of the DECL_RESULT, in case we have a named return value.  */
@@ -9583,21 +9965,22 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
   int doing_friend = 0;
   struct cp_binding_level *bl;
   tree current_function_parms;
+  struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename));
 
   /* Sanity check.  */
-  my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);
-  my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
+  gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE);
+  gcc_assert (TREE_CHAIN (void_list_node) == NULL_TREE);
 
   fntype = TREE_TYPE (decl1);
   if (TREE_CODE (fntype) == METHOD_TYPE)
     ctype = TYPE_METHOD_BASETYPE (fntype);
-  
+
   /* ISO C++ 11.4/5.  A friend function defined in a class is in
      the (lexical) scope of the class in which it is defined.  */
   if (!ctype && DECL_FRIEND_P (decl1))
     {
       ctype = DECL_FRIEND_CONTEXT (decl1);
-      
+
       /* CTYPE could be null here if we're dealing with a template;
         for example, `inline friend float foo()' inside a template
         will have no CTYPE set.  */
@@ -9609,7 +9992,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
 
   if (DECL_DECLARED_INLINE_P (decl1)
       && lookup_attribute ("noinline", attrs))
-    warning ("%Jinline function '%D' given attribute noinline", decl1, decl1);
+    warning ("%Jinline function %qD given attribute noinline", decl1, decl1);
 
   if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
     /* This is a constructor, we must ensure that any default args
@@ -9646,7 +10029,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
   if (warn_ecpp
       && DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR
       && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
-    warning ("`operator=' should return a reference to `*this'");
+    warning ("%<operator=%> should return a reference to %<*this%>");
 
   /* Make the init_value nonzero so pushdecl knows this is not tentative.
      error_mark_node is replaced below (in poplevel) with the BLOCK.  */
@@ -9674,8 +10057,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
   /* Make sure the parameter and return types are reasonable.  When
      you declare a function, these types can be incomplete, but they
      must be complete when you define the function.  */
-  if (! processing_template_decl)
-    check_function_type (decl1, current_function_parms);
+  check_function_type (decl1, current_function_parms);
 
   /* Build the return declaration for the function.  */
   restype = TREE_TYPE (fntype);
@@ -9684,10 +10066,14 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
     restype = type_promotes_to (restype);
   if (DECL_RESULT (decl1) == NULL_TREE)
     {
-      DECL_RESULT (decl1)
-       = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
-      c_apply_type_quals_to_decl (cp_type_quals (restype),
-                                 DECL_RESULT (decl1));
+      tree resdecl;
+
+      resdecl = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
+      DECL_ARTIFICIAL (resdecl) = 1;
+      DECL_IGNORED_P (resdecl) = 1;
+      DECL_RESULT (decl1) = resdecl;
+
+      c_apply_type_quals_to_decl (cp_type_quals (restype), resdecl);
     }
 
   /* Initialize RTL machinery.  We cannot do this until
@@ -9718,7 +10104,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
     {
       /* A specialization is not used to guide overload resolution.  */
       if (!DECL_FUNCTION_MEMBER_P (decl1)
-         && !(DECL_USE_TEMPLATE (decl1) && 
+         && !(DECL_USE_TEMPLATE (decl1) &&
               PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl1))))
        {
          tree olddecl = pushdecl (decl1);
@@ -9744,6 +10130,12 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
       fntype = TREE_TYPE (decl1);
     }
 
+  /* Determine the ELF visibility attribute for the function.  We must
+     not do this before calling "pushdecl", as we must allow
+     "duplicate_decls" to merge any attributes appropriately.  */
+  if (!DECL_CLONED_FUNCTION_P (decl1))
+    determine_visibility (decl1);
+
   /* Reset these in case the call to pushdecl changed them.  */
   current_function_decl = decl1;
   cfun->decl = decl1;
@@ -9761,10 +10153,8 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
         between `current_class_type' and `current_class_ptr'.  */
       tree t = DECL_ARGUMENTS (decl1);
 
-      my_friendly_assert (t != NULL_TREE && TREE_CODE (t) == PARM_DECL,
-                         162);
-      my_friendly_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE,
-                         19990811);
+      gcc_assert (t != NULL_TREE && TREE_CODE (t) == PARM_DECL);
+      gcc_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE);
 
       cp_function_chain->x_current_class_ref
        = build_indirect_ref (t, NULL);
@@ -9780,8 +10170,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
        }
       if (DECL_HAS_VTT_PARM_P (decl1))
        {
-         if (DECL_NAME (t) != vtt_parm_identifier)
-           abort ();
+         gcc_assert (DECL_NAME (t) == vtt_parm_identifier);
          current_vtt_parm = t;
        }
     }
@@ -9802,16 +10191,16 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
   /* If this function belongs to an interface, it is public.
      If it belongs to someone else's interface, it is also external.
      This only affects inlines and template instantiations.  */
-  else if (interface_unknown == 0
+  else if (finfo->interface_unknown == 0
           && ! DECL_TEMPLATE_INSTANTIATION (decl1))
     {
-      if (DECL_DECLARED_INLINE_P (decl1) 
+      if (DECL_DECLARED_INLINE_P (decl1)
          || DECL_TEMPLATE_INSTANTIATION (decl1)
          || processing_template_decl)
        {
          DECL_EXTERNAL (decl1)
-           = (interface_only
-              || (DECL_DECLARED_INLINE_P (decl1) 
+           = (finfo->interface_only
+              || (DECL_DECLARED_INLINE_P (decl1)
                   && ! flag_implement_inlines
                   && !DECL_VINDEX (decl1)));
 
@@ -9822,15 +10211,21 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
        DECL_EXTERNAL (decl1) = 0;
       DECL_NOT_REALLY_EXTERN (decl1) = 0;
       DECL_INTERFACE_KNOWN (decl1) = 1;
+      /* If this function is in an interface implemented in this file,
+        make sure that the backend knows to emit this function 
+        here.  */
+      if (!DECL_EXTERNAL (decl1))
+       mark_needed (decl1);
     }
-  else if (interface_unknown && interface_only
+  else if (finfo->interface_unknown && finfo->interface_only
           && ! DECL_TEMPLATE_INSTANTIATION (decl1))
     {
       /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma
-        interface, we will have interface_only set but not
-        interface_known.  In that case, we don't want to use the normal
-        heuristics because someone will supply a #pragma implementation
-        elsewhere, and deducing it here would produce a conflict.  */
+        interface, we will have both finfo->interface_unknown and
+        finfo->interface_only set.  In that case, we don't want to
+        use the normal heuristics because someone will supply a
+        #pragma implementation elsewhere, and deducing it here would
+        produce a conflict.  */
       comdat_linkage (decl1);
       DECL_EXTERNAL (decl1) = 0;
       DECL_INTERFACE_KNOWN (decl1) = 1;
@@ -9842,7 +10237,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
         So clear DECL_EXTERNAL.  */
       DECL_EXTERNAL (decl1) = 0;
 
-      if ((DECL_DECLARED_INLINE_P (decl1) 
+      if ((DECL_DECLARED_INLINE_P (decl1)
           || DECL_TEMPLATE_INSTANTIATION (decl1))
          && ! DECL_INTERFACE_KNOWN (decl1)
          /* Don't try to defer nested functions for now.  */
@@ -9856,14 +10251,16 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
 
   ++function_depth;
 
-  if (DECL_DESTRUCTOR_P (decl1))
+  if (DECL_DESTRUCTOR_P (decl1)
+      || (DECL_CONSTRUCTOR_P (decl1)
+         && targetm.cxx.cdtor_returns_this ()))
     {
-      dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-      DECL_CONTEXT (dtor_label) = current_function_decl;
+      cdtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+      DECL_CONTEXT (cdtor_label) = current_function_decl;
     }
 
   start_fname_decls ();
-  
+
   store_parm_decls (current_function_parms);
 }
 
@@ -9876,7 +10273,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
    yyparse to report a parse error.  */
 
 int
-start_function (cp_decl_specifier_seq *declspecs, 
+start_function (cp_decl_specifier_seq *declspecs,
                const cp_declarator *declarator,
                tree attrs)
 {
@@ -9888,30 +10285,22 @@ start_function (cp_decl_specifier_seq *declspecs,
       /* This should only be done once on the outermost decl.  */
       have_extern_spec = false;
     }
-  
+
   decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
   /* If the declarator is not suitable for a function definition,
      cause a syntax error.  */
   if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
     return 0;
-  
-  cplus_decl_attributes (&decl1, attrs, 0);
-  
+
   /* If #pragma weak was used, mark the decl weak now.  */
   if (global_scope_p (current_binding_level))
     maybe_apply_pragma_weak (decl1);
-  
+
   if (DECL_MAIN_P (decl1))
-    {
-      /* If this doesn't return integer_type, or a typedef to
-        integer_type, complain.  */
-      if (!same_type_p (TREE_TYPE (TREE_TYPE (decl1)), integer_type_node))
-       {
-         if (pedantic || warn_return_type)
-           pedwarn ("return type for `main' changed to `int'");
-         TREE_TYPE (decl1) = default_function_type;
-       }
-    }
+    /* main must return int.  grokfndecl should have corrected it
+       (and issued a diagnostic) if the user got it wrong.  */
+    gcc_assert (same_type_p (TREE_TYPE (TREE_TYPE (decl1)),
+                            integer_type_node));
 
   start_preparsed_function (decl1, attrs, /*flags=*/SF_DEFAULT);
 
@@ -9963,7 +10352,7 @@ store_parm_decls (tree current_function_parms)
                  || TREE_CODE (parm) != VOID_TYPE)
                pushdecl (parm);
              else
-               error ("parameter `%D' declared void", parm);
+               error ("parameter %qD declared void", parm);
            }
          else
            {
@@ -10012,11 +10401,10 @@ save_function_data (tree decl)
 
   /* Save the language-specific per-function data so that we can
      get it back when we really expand this function.  */
-  my_friendly_assert (!DECL_PENDING_INLINE_P (decl),
-                     19990908);
+  gcc_assert (!DECL_PENDING_INLINE_P (decl));
 
   /* Make a copy.  */
-  f = ggc_alloc (sizeof (struct language_function));
+  f = GGC_NEW (struct language_function);
   memcpy (f, cp_function_chain, sizeof (struct language_function));
   DECL_SAVED_FUNCTION_DATA (decl) = f;
 
@@ -10027,22 +10415,27 @@ save_function_data (tree decl)
   f->x_local_names = NULL;
 }
 
-/* Add a note to mark the beginning of the main body of the constructor.
-   This is used to set up the data structures for the cleanup regions for
-   fully-constructed bases and members.  */
 
-static void
-begin_constructor_body (void)
-{
-}
-
-/* Add a note to mark the end of the main body of the constructor.  This is
-   used to end the cleanup regions for fully-constructed bases and
-   members.  */
+/* Set the return value of the constructor (if present).  */
 
 static void
 finish_constructor_body (void)
 {
+  tree val;
+  tree exprstmt;
+
+  if (targetm.cxx.cdtor_returns_this ())
+    {
+      /* Any return from a constructor will end up here.  */
+      add_stmt (build_stmt (LABEL_EXPR, cdtor_label));
+
+      val = DECL_ARGUMENTS (current_function_decl);
+      val = build2 (MODIFY_EXPR, TREE_TYPE (val),
+                   DECL_RESULT (current_function_decl), val);
+      /* Return the address of the object.  */
+      exprstmt = build_stmt (RETURN_EXPR, val);
+      add_stmt (exprstmt);
+    }
 }
 
 /* Do all the processing for the beginning of a destructor; set up the
@@ -10070,7 +10463,7 @@ begin_destructor_body (void)
   if_stmt = begin_if_stmt ();
 
   /* If it is not safe to avoid setting up the vtables, then
-     someone will change the condition to be boolean_true_node.  
+     someone will change the condition to be boolean_true_node.
      (Actually, for now, we do not have code to set the condition
      appropriately, so we just assume that we always need to
      initialize the vtables.)  */
@@ -10102,7 +10495,7 @@ finish_destructor_body (void)
 
   /* Any return from a destructor will end up here; that way all base
      and member cleanups will be run when the function returns.  */
-  add_stmt (build_stmt (LABEL_EXPR, dtor_label));
+  add_stmt (build_stmt (LABEL_EXPR, cdtor_label));
 
   /* In a virtual destructor, we must call delete.  */
   if (DECL_VIRTUAL_P (current_function_decl))
@@ -10117,18 +10510,30 @@ finish_destructor_body (void)
       be looked up in the scope of the destructor's class and if
       found shall be accessible and unambiguous.  */
       exprstmt = build_op_delete_call
-       (DELETE_EXPR, current_class_ptr, virtual_size, 
+       (DELETE_EXPR, current_class_ptr, virtual_size,
         /*global_p=*/false, NULL_TREE);
 
       if_stmt = begin_if_stmt ();
-      finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
-                                 current_in_charge_parm,
-                                 integer_one_node),
+      finish_if_stmt_cond (build2 (BIT_AND_EXPR, integer_type_node,
+                                  current_in_charge_parm,
+                                  integer_one_node),
                           if_stmt);
       finish_expr_stmt (exprstmt);
       finish_then_clause (if_stmt);
       finish_if_stmt (if_stmt);
     }
+
+  if (targetm.cxx.cdtor_returns_this ())
+    {
+      tree val;
+
+      val = DECL_ARGUMENTS (current_function_decl);
+      val = build2 (MODIFY_EXPR, TREE_TYPE (val),
+                   DECL_RESULT (current_function_decl), val);
+      /* Return the address of the object.  */
+      exprstmt = build_stmt (RETURN_EXPR, val);
+      add_stmt (exprstmt);
+    }
 }
 
 /* Do the necessary processing for the beginning of a function body, which
@@ -10154,8 +10559,6 @@ begin_function_body (void)
 
   if (processing_template_decl)
     /* Do nothing now.  */;
-  else if (DECL_CONSTRUCTOR_P (current_function_decl))
-    begin_constructor_body ();
   else if (DECL_DESTRUCTOR_P (current_function_decl))
     begin_destructor_body ();
 
@@ -10183,7 +10586,7 @@ finish_function_body (tree compstmt)
     finish_constructor_body ();
   else if (DECL_DESTRUCTOR_P (current_function_decl))
     finish_destructor_body ();
-}  
+}
 
 /* Finish up a function declaration and compile that function
    all the way to assembler language output.  The free the storage
@@ -10224,20 +10627,27 @@ finish_function (int flags)
       This caused &foo to be of type ptr-to-const-function
       which then got a warning when stored in a ptr-to-function variable.  */
 
-  my_friendly_assert (building_stmt_tree (), 20000911);
-  
+  gcc_assert (building_stmt_tree ());
+
   /* For a cloned function, we've already got all the code we need;
      there's no need to add any extra bits.  */
   if (!DECL_CLONED_FUNCTION_P (fndecl))
     {
       if (DECL_MAIN_P (current_function_decl))
        {
-         /* Make it so that `main' always returns 0 by default.  */
+         tree stmt;
+
+         /* Make it so that `main' always returns 0 by default (or
+            1 for VMS).  */
 #if VMS_TARGET
-         finish_return_stmt (integer_one_node);
+         stmt = finish_return_stmt (integer_one_node);
 #else
-         finish_return_stmt (integer_zero_node);
+         stmt = finish_return_stmt (integer_zero_node);
 #endif
+         /* Hack.  We don't want the middle-end to warn that this
+            return is unreachable, so put the statement on the
+            special line 0.  */
+         annotate_with_file_line (stmt, input_filename, 0);
        }
 
       /* Finish dealing with exception specifiers.  */
@@ -10263,15 +10673,14 @@ finish_function (int flags)
   /* This must come after expand_function_end because cleanups might
      have declarations (from inline functions) that need to go into
      this function's blocks.  */
-  
+
   /* If the current binding level isn't the outermost binding level
      for this function, either there is a bug, or we have experienced
      syntax errors and the statement tree is malformed.  */
   if (current_binding_level->kind != sk_function_parms)
     {
       /* Make sure we have already experienced errors.  */
-      if (errorcount == 0)
-       abort ();
+      gcc_assert (errorcount);
 
       /* Throw away the broken statement tree and extra binding
          levels.  */
@@ -10289,7 +10698,7 @@ finish_function (int flags)
 
   /* Statements should always be full-expressions at the outermost set
      of curly braces for a function.  */
-  my_friendly_assert (stmts_are_full_exprs_p (), 19990831);
+  gcc_assert (stmts_are_full_exprs_p ());
 
   /* Set up the named return value optimization, if we can.  Candidate
      variables are selected in check_return_value.  */
@@ -10340,7 +10749,10 @@ finish_function (int flags)
       && !DECL_NAME (DECL_RESULT (fndecl))
       /* Normally, with -Wreturn-type, flow will complain.  Unless we're an
         inline function, as we might never be compiled separately.  */
-      && (DECL_INLINE (fndecl) || processing_template_decl))
+      && (DECL_INLINE (fndecl) || processing_template_decl)
+      /* Structor return values (if any) are set by the compiler.  */
+      && !DECL_CONSTRUCTOR_P (fndecl)
+      && !DECL_DESTRUCTOR_P (fndecl))
     warning ("no return statement in function returning non-void");
 
   /* Store the end of the function, so that we get good line number
@@ -10350,11 +10762,23 @@ finish_function (int flags)
   /* Genericize before inlining.  */
   if (!processing_template_decl)
     {
+      struct language_function *f = DECL_SAVED_FUNCTION_DATA (fndecl);
       cp_genericize (fndecl);
+      /* Clear out the bits we don't need.  */
+      f->x_current_class_ptr = NULL;
+      f->x_current_class_ref = NULL;
+      f->x_eh_spec_block = NULL;
+      f->x_in_charge_parm = NULL;
+      f->x_vtt_parm = NULL;
+      f->x_return_value = NULL;
+      f->bindings = NULL;
 
       /* Handle attribute((warn_unused_result)).  Relies on gimple input.  */
       c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
     }
+  /* Clear out the bits we don't need.  */
+  local_names = NULL;
+  named_label_uses = NULL;
 
   /* We're leaving the context of this function, so zap cfun.  It's still in
      DECL_STRUCT_FUNCTION, and we'll restore it in tree_rest_of_compilation.  */
@@ -10406,7 +10830,7 @@ finish_function (int flags)
    CHANGES TO CODE IN `grokfield'.  */
 
 tree
-start_method (cp_decl_specifier_seq *declspecs, 
+start_method (cp_decl_specifier_seq *declspecs,
               const cp_declarator *declarator, tree attrlist)
 {
   tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
@@ -10432,7 +10856,7 @@ start_method (cp_decl_specifier_seq *declspecs,
     {
       if (DECL_CONTEXT (fndecl)
          && TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
-       error ("`%D' is already defined in class `%T'", fndecl,
+       error ("%qD is already defined in class %qT", fndecl,
               DECL_CONTEXT (fndecl));
       return void_type_node;
     }
@@ -10509,7 +10933,7 @@ finish_method (tree decl)
     {
       if (DECL_NAME (link) != NULL_TREE)
        pop_binding (DECL_NAME (link), link);
-      my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163);
+      gcc_assert (TREE_CODE (link) != FUNCTION_DECL);
       DECL_CONTEXT (link) = NULL_TREE;
     }
 
@@ -10522,8 +10946,8 @@ finish_method (tree decl)
      for String.cc in libg++.  */
   if (DECL_FRIEND_P (fndecl))
     {
-      CLASSTYPE_INLINE_FRIENDS (current_class_type)
-       = tree_cons (NULL_TREE, fndecl, CLASSTYPE_INLINE_FRIENDS (current_class_type));
+      VEC_safe_push (tree, CLASSTYPE_INLINE_FRIENDS (current_class_type),
+                    fndecl);
       decl = void_type_node;
     }
 
@@ -10537,18 +10961,18 @@ finish_method (tree decl)
 void
 maybe_register_incomplete_var (tree var)
 {
-  my_friendly_assert (TREE_CODE (var) == VAR_DECL, 20020406);
+  gcc_assert (TREE_CODE (var) == VAR_DECL);
 
   /* Keep track of variables with incomplete types.  */
-  if (!processing_template_decl && TREE_TYPE (var) != error_mark_node 
+  if (!processing_template_decl && TREE_TYPE (var) != error_mark_node
       && DECL_EXTERNAL (var))
     {
       tree inner_type = TREE_TYPE (var);
-      
+
       while (TREE_CODE (inner_type) == ARRAY_TYPE)
        inner_type = TREE_TYPE (inner_type);
       inner_type = TYPE_MAIN_VARIANT (inner_type);
-      
+
       if ((!COMPLETE_TYPE_P (inner_type) && CLASS_TYPE_P (inner_type))
          /* RTTI TD entries are created while defining the type_info.  */
          || (TYPE_LANG_SPECIFIC (inner_type)
@@ -10566,8 +10990,8 @@ complete_vars (tree type)
 {
   tree *list = &incomplete_vars;
 
-  my_friendly_assert (CLASS_TYPE_P (type), 20020406);
-  while (*list) 
+  gcc_assert (CLASS_TYPE_P (type));
+  while (*list)
     {
       if (same_type_p (type, TREE_PURPOSE (*list)))
        {
@@ -10598,6 +11022,8 @@ cxx_maybe_build_cleanup (tree decl)
     {
       int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
       tree rval;
+      bool has_vbases = (TREE_CODE (type) == RECORD_TYPE
+                        && CLASSTYPE_VBASECLASSES (type));
 
       if (TREE_CODE (type) == ARRAY_TYPE)
        rval = decl;
@@ -10608,15 +11034,13 @@ cxx_maybe_build_cleanup (tree decl)
        }
 
       /* Optimize for space over speed here.  */
-      if (! TYPE_USES_VIRTUAL_BASECLASSES (type)
-         || flag_expensive_optimizations)
+      if (!has_vbases || flag_expensive_optimizations)
        flags |= LOOKUP_NONVIRTUAL;
 
       rval = build_delete (TREE_TYPE (rval), rval,
                           sfk_complete_destructor, flags, 0);
 
-      if (TYPE_USES_VIRTUAL_BASECLASSES (type)
-         && ! TYPE_HAS_DESTRUCTOR (type))
+      if (has_vbases && !TYPE_HAS_DESTRUCTOR (type))
        rval = build_compound_expr (rval, build_vbase_delete (type, decl));
 
       return rval;
@@ -10643,8 +11067,7 @@ revert_static_member_fn (tree decl)
 
   if (cp_type_quals (TREE_TYPE (TREE_VALUE (args)))
       != TYPE_UNQUALIFIED)
-    error ("static member function `%#D' declared with type qualifiers",
-             decl);
+    error ("static member function %q#D declared with type qualifiers", decl);
 
   args = TREE_CHAIN (args);
   tmp = build_function_type (TREE_TYPE (function), args);
@@ -10663,8 +11086,7 @@ revert_static_member_fn (tree decl)
 void
 cxx_push_function_context (struct function * f)
 {
-  struct language_function *p
-    = ggc_alloc_cleared (sizeof (struct language_function));
+  struct language_function *p = GGC_CNEW (struct language_function);
   f->language = p;
 
   /* Whenever we start a new function, we destroy temporaries in the
@@ -10682,7 +11104,7 @@ cxx_push_function_context (struct function * f)
          *cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn);
 
          /* We don't need the saved data anymore.  Unless this is an inline
-            function; we need the named return value info for 
+            function; we need the named return value info for
             declare_return_variable.  */
          if (! DECL_INLINE (fn))
            DECL_SAVED_FUNCTION_DATA (fn) = NULL;
@@ -10711,6 +11133,7 @@ cp_tree_node_structure (union lang_tree_node * t)
     case IDENTIFIER_NODE:      return TS_CP_IDENTIFIER;
     case OVERLOAD:             return TS_CP_OVERLOAD;
     case TEMPLATE_PARM_INDEX:  return TS_CP_TPI;
+    case TINST_LEVEL:          return TS_CP_TINST_LEVEL;
     case PTRMEM_CST:           return TS_CP_PTRMEM;
     case BASELINK:              return TS_CP_BASELINK;
     default:                   return TS_CP_GENERIC;
@@ -10732,5 +11155,24 @@ cp_missing_noreturn_ok_p (tree decl)
   return DECL_MAIN_P (decl);
 }
 
+/* Return the COMDAT group into which DECL should be placed.  */
+
+const char *
+cxx_comdat_group (tree decl)
+{
+  tree name;
+
+  /* Virtual tables, construction virtual tables, and virtual table
+     tables all go in a single COMDAT group, named after the primary
+     virtual table.  */
+  if (TREE_CODE (decl) == VAR_DECL && DECL_VTABLE_OR_VTT_P (decl))
+    name = DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (DECL_CONTEXT (decl)));
+  /* For all other DECLs, the COMDAT group is the mangled name of the
+     declaration itself.  */
+  else
+    name = DECL_ASSEMBLER_NAME (decl);
+
+  return IDENTIFIER_POINTER (name);
+}
+
 #include "gt-cp-decl.h"
-#include "gtype-cp.h"