OSDN Git Service

PR c++/19878
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index a4856a9..cea13b8 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.
@@ -61,9 +61,6 @@ static int ambi_op_p (enum tree_code);
 static int unary_op_p (enum tree_code);
 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 *,
                         int, int, tree);
 static void record_unknown_type (tree, const char *);
@@ -80,10 +77,9 @@ 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*);
 static tree make_label_decl (tree, int);
 static void use_label (tree);
 static void check_previous_goto_1 (tree, struct cp_binding_level *, tree,
@@ -119,7 +115,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;
@@ -363,7 +358,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 +369,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 +398,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 +470,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;
@@ -534,7 +565,7 @@ poplevel (int keep, int reverse, int functionbody)
          && ! TREE_USED (decl)
          && ! DECL_IN_SYSTEM_HEADER (decl)
          && DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
-       warning ("%Junused variable '%D'", decl, decl);
+       warning ("%Junused variable %qD", decl, decl);
 
   /* Remove declarations for all the DECLs in this level.  */
   for (link = decls; link; link = TREE_CHAIN (link))
@@ -603,18 +634,20 @@ poplevel (int keep, int reverse, int functionbody)
        }
       else
        {
+         tree name;
+         
          /* Remove the binding.  */
          decl = link;
 
          if (TREE_CODE (decl) == TREE_LIST)
            decl = TREE_VALUE (decl);
+         name = decl;
+         
+         if (TREE_CODE (name) == OVERLOAD)
+           name = OVL_FUNCTION (name);
 
-         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 ();
+         gcc_assert (DECL_P (name));
+         pop_binding (DECL_NAME (name), decl);
        }
     }
 
@@ -707,29 +740,6 @@ poplevel (int keep, int reverse, int functionbody)
   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
 }
 
-/* Delete the node BLOCK from the current binding level.
-   This is used for the block inside a stmt expr ({...})
-   so that the block can be reinserted where appropriate.  */
-
-void
-delete_block (tree block)
-{
-  tree t;
-  if (current_binding_level->blocks == block)
-    current_binding_level->blocks = TREE_CHAIN (block);
-  for (t = current_binding_level->blocks; t;)
-    {
-      if (TREE_CHAIN (t) == block)
-       TREE_CHAIN (t) = TREE_CHAIN (block);
-      else
-       t = TREE_CHAIN (t);
-    }
-  TREE_CHAIN (block) = NULL_TREE;
-  /* Clear TREE_USED which is always set by poplevel.
-     The flag is set again if insert_block is called.  */
-  TREE_USED (block) = 0;
-}
-
 /* Insert BLOCK at the end of the list of subblocks of the
    current binding level.  This is used when a BIND_EXPR is expanded,
    to handle the BLOCK node inside the BIND_EXPR.  */
@@ -742,64 +752,6 @@ insert_block (tree block)
     = chainon (current_binding_level->blocks, block);
 }
 
-/* Returns nonzero if T is a virtual function table.  */
-
-int
-vtable_decl_p (tree t, void* data ATTRIBUTE_UNUSED )
-{
-  return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));
-}
-
-/* Returns nonzero if T is a TYPE_DECL for a type with virtual
-   functions.  */
-
-int
-vtype_decl_p (tree t, void *data ATTRIBUTE_UNUSED )
-{
-  return (TREE_CODE (t) == TYPE_DECL
-         && TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
-         && TYPE_POLYMORPHIC_P (TREE_TYPE (t)));
-}
-
-struct walk_globals_data {
-  walk_globals_pred p;
-  walk_globals_fn f;
-  void *data;
-};
-
-/* Walk the vtable declarations in NAMESPACE.  Whenever one is found
-   for which P returns nonzero, call F with its address.  If any call
-   to F returns a nonzero value, return a nonzero value.  */
-
-static int
-walk_vtables_r (tree namespace, void* data)
-{
-  struct walk_globals_data* wgd = (struct walk_globals_data *) data;
-  walk_globals_fn f = wgd->f;
-  void *d = wgd->data;
-  tree decl = NAMESPACE_LEVEL (namespace)->vtables;
-  int result = 0;
-
-  for (; decl ; decl = TREE_CHAIN (decl))
-    result |= (*f) (&decl, d);
-
-  return result;
-}
-
-/* Walk the vtable declarations.  Whenever one is found for which P
-   returns nonzero, call F with its address.  If any call to F
-   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.f = f;
-  wgd.data = data;
-
-  return walk_namespaces (walk_vtables_r, &wgd);
-}
-
 /* Walk all the namespaces contained NAMESPACE, including NAMESPACE
    itself, calling F for each.  The DATA is passed to F as well.  */
 
@@ -826,53 +778,6 @@ walk_namespaces (walk_namespaces_fn f, void* data)
   return walk_namespaces_r (global_namespace, f, data);
 }
 
-/* Walk the global declarations in NAMESPACE.  Whenever one is found
-   for which P returns nonzero, call F with its address.  If any call
-   to F returns a nonzero value, return a nonzero value.  */
-
-static int
-walk_globals_r (tree namespace, void* data)
-{
-  struct walk_globals_data* wgd = (struct walk_globals_data *) data;
-  walk_globals_pred p = wgd->p;
-  walk_globals_fn f = wgd->f;
-  void *d = wgd->data;
-  tree *t;
-  int result = 0;
-
-  t = &NAMESPACE_LEVEL (namespace)->names;
-
-  while (*t)
-    {
-      tree glbl = *t;
-
-      if ((*p) (glbl, d))
-       result |= (*f) (t, d);
-
-      /* If F changed *T, then *T still points at the next item to
-        examine.  */
-      if (*t == glbl)
-       t = &TREE_CHAIN (*t);
-    }
-
-  return result;
-}
-
-/* Walk the global declarations.  Whenever one is found for which P
-   returns true, call F with its address.  If any call to F
-   returns true, return true.  */
-
-bool
-walk_globals (walk_globals_pred p, walk_globals_fn f, void *data)
-{
-  struct walk_globals_data wgd;
-  wgd.p = p;
-  wgd.f = f;
-  wgd.data = data;
-
-  return walk_namespaces (walk_globals_r, &wgd);
-}
-
 /* Call wrapup_globals_declarations for the globals in NAMESPACE.  If
    DATA is non-NULL, this is the last time we will call
    wrapup_global_declarations for this NAMESPACE.  */
@@ -1095,8 +1000,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.
@@ -1144,17 +1049,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);
        }
     }
@@ -1175,22 +1080,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;
        }
@@ -1241,14 +1146,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.  */
@@ -1313,10 +1218,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;
     }
@@ -1335,8 +1240,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
@@ -1350,8 +1255,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;
        }
@@ -1359,25 +1264,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
@@ -1426,10 +1331,10 @@ duplicate_decls (tree newdecl, tree olddecl)
          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 glogal scope
+        declared as the name of any other entity in any global scope
         of the program.  */
-      error ("declaration of `namespace %D' conflicts with", newdecl);
-      cp_error_at ("previous declaration of `namespace %D' here", olddecl);
+      error ("declaration of namespace %qD conflicts with", newdecl);
+      cp_error_at ("previous declaration of namespace %qD here", olddecl);
       return error_mark_node;
     }
   else
@@ -1441,8 +1346,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
@@ -1451,7 +1356,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
@@ -1464,10 +1369,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));
            }
        }
 
@@ -1489,16 +1394,16 @@ 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);
                  }
              }
@@ -1507,7 +1412,7 @@ duplicate_decls (tree newdecl, tree olddecl)
              && ! 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);
            }
        }
@@ -1544,7 +1449,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
@@ -1561,8 +1465,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);
        }
     }
 
@@ -1655,9 +1559,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;
@@ -1681,6 +1585,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
@@ -1759,6 +1669,13 @@ duplicate_decls (tree newdecl, tree olddecl)
       DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
       DECL_TEMPLATE_INSTANTIATED (newdecl)
        |= DECL_TEMPLATE_INSTANTIATED (olddecl);
+      /* If the OLDDECL is an implicit instantiation, then the NEWDECL
+        must be too.  But, it may not yet be marked as such if the
+        caller has created NEWDECL, but has not yet figured out that
+        it is a redeclaration.  */
+      if (DECL_IMPLICIT_INSTANTIATION (olddecl)
+         && !DECL_USE_TEMPLATE (newdecl))
+       SET_DECL_IMPLICIT_INSTANTIATION (newdecl);
       /* 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);
@@ -1793,8 +1710,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]:
@@ -1805,7 +1721,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);
@@ -1884,7 +1800,7 @@ duplicate_decls (tree newdecl, tree olddecl)
       && DECL_VISIBILITY_SPECIFIED (newdecl)
       && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
     {
-      warning ("%J'%D': visibility attribute ignored because it",
+      warning ("%J%qD: visibility attribute ignored because it",
               newdecl, newdecl);
       warning ("%Jconflicts with previous declaration here", olddecl);
     }
@@ -1895,6 +1811,15 @@ duplicate_decls (tree newdecl, tree 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)
     {
       int function_size;
@@ -1956,6 +1881,11 @@ duplicate_decls (tree newdecl, tree olddecl)
              && TREE_STATIC (olddecl))))
     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;
 }
 \f
@@ -1976,21 +1906,22 @@ 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)
     {
       /* If this is a pure function, its olddecl will actually be
         the original initialization to `0' (which we force to call
         abort()).  Don't complain about redefinition in this case.  */
-      if (DECL_LANG_SPECIFIC (olddecl) && DECL_PURE_VIRTUAL_P (olddecl))
+      if (DECL_LANG_SPECIFIC (olddecl) && DECL_PURE_VIRTUAL_P (olddecl)
+         && DECL_INITIAL (olddecl) == NULL_TREE)
        return 0;
 
       /* If both functions come from different namespaces, this is not
         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.  */
@@ -2000,9 +1931,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;
     }
@@ -2014,7 +1945,7 @@ 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;
        }
 
@@ -2030,7 +1961,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;
     }
@@ -2041,7 +1972,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
     {
@@ -2049,7 +1980,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;
     }
 }
@@ -2114,7 +2045,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);
     }
 
@@ -2210,7 +2141,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");
 
@@ -2220,10 +2151,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);
        }
 
@@ -2234,7 +2165,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");
 
@@ -2322,7 +2253,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;
     }
@@ -2336,9 +2267,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)
@@ -2373,7 +2304,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.  */
@@ -2388,8 +2319,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
@@ -2461,7 +2391,7 @@ finish_case_label (tree low_value, tree high_value)
     }
 
   /* Find the condition on which this switch statement depends.  */
-  cond = SWITCH_COND (switch_stack->switch_stmt);
+  cond = SWITCH_STMT_COND (switch_stack->switch_stmt);
   if (cond && TREE_CODE (cond) == TREE_LIST)
     cond = TREE_VALUE (cond);
 
@@ -2494,83 +2424,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;
 
@@ -2604,20 +2552,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))
@@ -2630,8 +2569,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;
            }
 
@@ -2651,7 +2590,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;
            }
 
@@ -2661,7 +2600,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;
                }
 
@@ -2681,21 +2620,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;
@@ -2704,8 +2647,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))
@@ -2718,7 +2660,18 @@ 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;
        }
 
@@ -2739,6 +2692,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;
 }
@@ -2865,13 +2819,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 },
@@ -2903,7 +2859,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 ();
@@ -2914,7 +2870,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);
@@ -2930,10 +2886,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.  */
@@ -2963,8 +2916,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_cst (NULL_TREE, 2, 0);
-  integer_three_node = build_int_cst (NULL_TREE, 3, 0);
+  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;
@@ -3406,13 +3359,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);
              }
          }
@@ -3446,7 +3402,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs)
       return NULL_TREE;
     }
 
-  if (TYPE_P (declspecs->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))
@@ -3492,15 +3449,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",
+       error ("%qs can only be specified for functions",
               declspecs->specs[(int)ds_inline]
               ? "inline" : "virtual");
       else if (saw_friend
               && (!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");
@@ -3536,6 +3493,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
@@ -3595,12 +3561,14 @@ start_decl (const cp_declarator *declarator,
             int initialized,
             tree attributes,
             tree prefix_attributes, 
-           bool *pop_scope_p)
+           tree *pushed_scope_p)
 {
   tree decl;
   tree type, tem;
   tree context;
 
+  *pushed_scope_p = NULL_TREE;
   /* This should only be done once on the top most decl.  */
   if (have_extern_spec)
     {
@@ -3621,23 +3589,23 @@ 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 (context)
-    *pop_scope_p = push_scope (context);
-  else
-    *pop_scope_p = false;
+    {
+      *pushed_scope_p = push_scope (context);
   
-  /* We are only interested in class contexts, later.  */
-  if (context && TREE_CODE (context) == NAMESPACE_DECL)
-    context = NULL_TREE;
+      /* We are only interested in class contexts, later.  */
+      if (TREE_CODE (context) == NAMESPACE_DECL)
+       context = NULL_TREE;
+    }
 
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?
@@ -3646,12 +3614,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;
 
@@ -3663,8 +3631,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;
@@ -3686,7 +3654,7 @@ 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)))
     {
@@ -3694,24 +3662,30 @@ start_decl (const cp_declarator *declarator,
        {
          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;
            }
@@ -3732,7 +3706,12 @@ start_decl (const cp_declarator *declarator,
       if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
          || CLASSTYPE_TEMPLATE_INSTANTIATION (context))
        {
-         SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+         /* Do not mark DECL as an explicit specialization if it was
+            not already marked as an instantiation; a declaration
+            should never be marked as a specialization unless we know
+            what template is being specialized.  */ 
+         if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
+           SET_DECL_TEMPLATE_SPECIALIZATION (decl);
          /* [temp.expl.spec] An explicit specialization of a static data
             member of a template is a definition if the declaration
             includes an initializer; otherwise, it is a declaration.
@@ -3744,8 +3723,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.  */
@@ -3793,15 +3772,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;
        }
@@ -3817,7 +3795,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)).  */
@@ -3867,22 +3845,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.  */
@@ -3901,7 +3877,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;
     }
 
@@ -3933,12 +3909,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
@@ -3950,7 +3926,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);
     }
@@ -3987,7 +3963,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
@@ -4009,7 +3985,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)
@@ -4064,8 +4040,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);
            }
        }
@@ -4091,7 +4070,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
@@ -4111,6 +4090,69 @@ 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.
 
@@ -4139,7 +4181,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
@@ -4169,7 +4211,7 @@ 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;
@@ -4232,8 +4274,7 @@ reshape_init (tree type, tree *initp)
                 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;
                }
            }
@@ -4253,7 +4294,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)
@@ -4278,55 +4319,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)));
-           }
-
-         /* 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;
+           /* 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)));
+             }
 
-             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.  */
@@ -4336,10 +4353,15 @@ reshape_init (tree type, tree *initp)
        new_init = build_tree_list (TREE_PURPOSE (old_init), new_init);
     }
 
-  /* 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);
+  /* If there are more initializers than necessary, issue a
+     diagnostic.  */  
+  if (*initp)
+    {
+      if (brace_enclosed_p)
+       error ("too many initializers for %qT", type);
+      else if (warn_missing_braces)
+       warning ("missing braces around initializer");
+    }
 
   return new_init;
 }
@@ -4377,29 +4399,29 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
   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)
@@ -4442,7 +4464,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;
                }
@@ -4473,6 +4496,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;
            }
        }
@@ -4486,10 +4515,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);
     }
@@ -4522,7 +4550,12 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
          DECL_HARD_REGISTER (decl) = 1;
        }
       else
-       set_user_assembler_name (decl, asmspec);
+       {
+         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.  */
@@ -4536,11 +4569,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);
+       gcc_assert (DECL_EXTERNAL (decl));
     }
 
   /* We don't create any RTL for local variables.  */
@@ -4563,10 +4596,11 @@ 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;
@@ -4589,10 +4623,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)
     {
@@ -4613,7 +4646,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);
@@ -4642,6 +4675,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,
@@ -4661,6 +4710,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;
@@ -4671,7 +4721,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;
@@ -4684,8 +4734,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
 
   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;
     }
 
@@ -4700,9 +4749,6 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
   if (type == error_mark_node)
     goto finish_end;
 
-  if (TYPE_HAS_MUTABLE_P (type))
-    TREE_READONLY (decl) = 0;
-
   if (processing_template_decl)
     {
       /* Add this declaration to the statement-tree.  */
@@ -4715,11 +4761,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_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)
@@ -4728,7 +4775,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);
        }
 
@@ -4748,16 +4795,13 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
     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
-     initialization and the running of a program.  */
-  if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl))
+  /* A reference will be modified here, as it is initialized.  */
+  if (! DECL_EXTERNAL (decl) 
+      && TREE_READONLY (decl)
+      && TREE_CODE (type) == REFERENCE_TYPE)
     {
       was_readonly = 1;
-      if (TYPE_NEEDS_CONSTRUCTING (type)
-         || TREE_CODE (type) == REFERENCE_TYPE)
-       TREE_READONLY (decl) = 0;
+      TREE_READONLY (decl) = 0;
     }
 
   if (TREE_CODE (decl) == VAR_DECL)
@@ -4765,7 +4809,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.  */
@@ -4780,7 +4824,7 @@ 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;
            }
@@ -4803,6 +4847,11 @@ 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);
@@ -4868,10 +4917,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);
-       }
+         
+         /* 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
@@ -4914,7 +4971,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 ();
 
@@ -5009,8 +5070,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;
@@ -5021,9 +5080,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.
@@ -5063,9 +5119,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;
@@ -5084,7 +5137,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;
@@ -5093,7 +5146,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,
@@ -5132,7 +5185,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,
@@ -5142,8 +5195,8 @@ 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
@@ -5151,73 +5204,127 @@ expand_static_init (tree decl, tree init)
       && 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);
@@ -5254,7 +5361,7 @@ complete_array_type (tree type, tree initial_value, int do_default)
            = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
          maxindex = build_int_cst (NULL_TREE,
                                    (TREE_STRING_LENGTH (initial_value)
-                                    / eltsize) - 1, 0);
+                                    / eltsize) - 1);
        }
       else if (TREE_CODE (initial_value) == CONSTRUCTOR)
        {
@@ -5278,14 +5385,14 @@ complete_array_type (tree type, tree initial_value, int do_default)
            initial_value = NULL_TREE;
 
          /* Prevent further error messages.  */
-         maxindex = build_int_cst (NULL_TREE, 0, 0);
+         maxindex = build_int_cst (NULL_TREE, 0);
        }
     }
 
   if (!maxindex)
     {
       if (do_default)
-       maxindex = build_int_cst (NULL_TREE, 0, 0);
+       maxindex = build_int_cst (NULL_TREE, 0);
       value = 2;
     }
 
@@ -5334,11 +5441,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;
@@ -5359,20 +5464,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.
@@ -5388,6 +5494,8 @@ bad_specifiers (tree object,
    CHECK is 1 if we must find this method in CTYPE, 0 if we should
    not look, and -1 if we should not call `grokclassfn' at all.
 
+   SFK is the kind of special function (if any) for the new function.
+
    Returns `NULL_TREE' if something goes wrong, after issuing
    applicable error messages.  */
 
@@ -5405,9 +5513,11 @@ grokfndecl (tree ctype,
             int friendp,
             int publicp,
             int inlinep,
+           special_function_kind sfk,
             int funcdef_flag,
             int template_count,
-            tree in_namespace)
+            tree in_namespace,
+           tree* attrlist)
 {
   tree decl;
   int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
@@ -5454,14 +5564,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;
     }
@@ -5489,17 +5602,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);
        }
     }
 
@@ -5522,7 +5634,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;
     }
@@ -5546,7 +5658,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
        {
@@ -5556,8 +5668,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;
            }
 
@@ -5573,25 +5686,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;
            }
        }
@@ -5609,14 +5724,13 @@ grokfndecl (tree ctype,
   if (check < 0)
     return decl;
 
-  if (flags == NO_SPECIAL && ctype && constructor_name_p (declarator, ctype))
-    DECL_CONSTRUCTOR_P (decl) = 1;
-
-  /* Function gets the ugly name, field gets the nice one.  This call
-     may change the type of the function (because of default
-     parameters)!  */
   if (ctype != NULL_TREE)
-    grokclassfn (ctype, decl, flags, quals);
+    {
+      if (sfk == sfk_constructor)
+       DECL_CONSTRUCTOR_P (decl) = 1;
+
+      grokclassfn (ctype, decl, flags, quals);
+    }
 
   decl = check_explicit_specialization (orig_declarator, decl,
                                        template_count,
@@ -5625,6 +5739,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)
@@ -5635,7 +5755,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
@@ -5650,12 +5770,12 @@ 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)
        {
          tree ok;
-         bool pop_p;
+         tree pushed_scope;
 
          /* Since we've smashed OLD_DECL to its
             DECL_TEMPLATE_RESULT, we must do the same to DECL.  */
@@ -5664,13 +5784,13 @@ grokfndecl (tree ctype,
 
          /* Attempt to merge the declarations.  This can fail, in
             the case of some invalid specialization declarations.  */
-         pop_p = push_scope (ctype);
+         pushed_scope = push_scope (ctype);
          ok = duplicate_decls (decl, old_decl);
-         if (pop_p)
-           pop_scope (ctype);
+         if (pushed_scope)
+           pop_scope (pushed_scope);
          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;
            }
@@ -5704,7 +5824,7 @@ set_linkage_for_static_data_member (tree decl)
   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 ordinarly namespace-scope variables.  */
+     with ordinary namespace-scope variables.  */
   if (!processing_template_decl)
     DECL_INTERFACE_KNOWN (decl) = 1;
 }
@@ -5724,11 +5844,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
@@ -5736,11 +5858,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
@@ -5757,8 +5875,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;
 
@@ -5806,29 +5924,34 @@ grokvardecl (tree type,
         declare an entity with linkage.
 
         Only check this for public decls for now.  */
-      tree t = no_linkage_check (TREE_TYPE (decl),
-                                /*relaxed_p=*/false);
+      tree t = no_linkage_check (TREE_TYPE (decl), /*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
                {
-                 pedwarn ("non-local variable `%#D' uses anonymous type",
+                 /* DRs 132, 319 and 389 seem to indicate types with
+                    no linkage can only be used to declare extern "C"
+                    entities.  Since it's not always an error in the
+                    ISO C++ 90 Standard, we only issue a warning.  */
+                 warning ("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_warning_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);
+           warning ("non-local variable %q#D uses local type %qT", decl, t);
        }
     }
+  else
+    DECL_INTERFACE_KNOWN (decl) = 1;
 
   return decl;
 }
@@ -5920,8 +6043,7 @@ build_ptrmem_type (tree class_type, tree 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);
     }
 }
@@ -5942,7 +6064,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
@@ -5951,10 +6074,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;
 }
@@ -5973,9 +6098,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);
     }
@@ -5993,7 +6118,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)
@@ -6011,7 +6136,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;
@@ -6021,7 +6146,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");
        }
@@ -6030,15 +6155,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");
     }
@@ -6048,12 +6173,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);
@@ -6084,11 +6217,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;
 }
@@ -6137,7 +6269,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);
 
@@ -6151,10 +6283,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;
     }
@@ -6200,7 +6334,7 @@ check_special_function_return_type (special_function_kind sfk,
       if (type)
        error ("return type specification for destructor invalid");
       /* We can't use the proper return type here because we run into
-        problems with abiguous bases and covariant returns.
+        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))
@@ -6211,20 +6345,44 @@ check_special_function_return_type (special_function_kind sfk,
 
     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.
@@ -6321,6 +6479,7 @@ grokdeclarator (const cp_declarator *declarator,
   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];
@@ -6358,40 +6517,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,
                                                     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);
@@ -6401,9 +6547,22 @@ grokdeclarator (const cp_declarator *declarator,
              {
              case BIT_NOT_EXPR:
                {
-                 tree type = TREE_OPERAND (decl, 0);
-                 type = constructor_name (type);
-                 name = IDENTIFIER_POINTER (type);
+                 tree type;
+
+                 if (innermost_code != cdk_function)
+                   {
+                     error ("declaration of %qD as non-function", decl);
+                     return error_mark_node;
+                   }
+                 else if (!qualifying_scope 
+                          && !(current_class_type && at_class_scope_p ()))
+                   {
+                     error ("declaration of %qD as non-member", decl);
+                     return error_mark_node;
+                   }
+                 
+                 type = TREE_OPERAND (decl, 0);
+                 name = IDENTIFIER_POINTER (constructor_name (type));
                }
                break;
 
@@ -6416,8 +6575,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));
                    }
                }
@@ -6429,7 +6587,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);
                  }
@@ -6437,7 +6595,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;
@@ -6454,7 +6612,7 @@ grokdeclarator (const cp_declarator *declarator,
                break;
 
              default:
-               abort ();
+               gcc_unreachable ();
              }
            break;
 
@@ -6468,7 +6626,7 @@ grokdeclarator (const cp_declarator *declarator,
            break;
 
          default:
-           abort ();
+           gcc_unreachable ();
          }
        }
       if (id_declarator->kind == cdk_id)
@@ -6485,8 +6643,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
@@ -6518,11 +6676,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)
@@ -6556,9 +6717,9 @@ grokdeclarator (const cp_declarator *declarator,
       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;
        }
@@ -6580,7 +6741,7 @@ grokdeclarator (const cp_declarator *declarator,
            "__complex",
            "__thread"
          };
-         error ("duplicate `%s'", decl_spec_names[(int)ds]);
+         error ("duplicate %qs", decl_spec_names[(int)ds]);
        }
     }
 
@@ -6613,14 +6774,14 @@ 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;
     }
@@ -6645,23 +6806,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;
@@ -6726,7 +6887,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
@@ -6755,9 +6916,23 @@ 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);
 
+  if (TREE_CODE (type) == FUNCTION_TYPE 
+      && type_quals != TYPE_UNQUALIFIED)
+    {
+      /* This was an error in C++98 (cv-qualifiers cannot be added to
+         a function type), but DR 295 makes the code well-formed by
+         dropping the extra qualifiers. */
+      if (pedantic)
+        {
+          tree bad_type = build_qualified_type (type, type_quals);
+          pedwarn ("ignoring %qV qualifiers added to function type %qT",
+                   bad_type, type);
+        }
+      type_quals = TYPE_UNQUALIFIED;
+    }
   type_quals |= cp_type_quals (type);
   type = cp_build_qualified_type_real
     (type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl)
@@ -6776,15 +6951,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;
     }
 
@@ -6816,14 +6990,14 @@ 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 != 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
@@ -6854,9 +7028,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))
                    {
@@ -6866,14 +7040,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");
            }
@@ -6892,24 +7066,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;
     }
@@ -6921,9 +7095,7 @@ 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))
@@ -6943,7 +7115,7 @@ grokdeclarator (const cp_declarator *declarator,
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -6983,13 +7155,6 @@ grokdeclarator (const cp_declarator *declarator,
        case cdk_array:
          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:
@@ -7008,12 +7173,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;
              }
 
@@ -7100,7 +7265,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.  */
@@ -7110,8 +7275,9 @@ 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,
@@ -7128,6 +7294,7 @@ grokdeclarator (const cp_declarator *declarator,
              }
 
            type = build_function_type (type, arg_types);
+            type = cp_build_qualified_type (type, quals);
          }
          break;
 
@@ -7140,16 +7307,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,
@@ -7160,7 +7327,15 @@ grokdeclarator (const cp_declarator *declarator,
              && (TREE_CODE (type) == FUNCTION_TYPE
                  || (quals && TREE_CODE (type) == METHOD_TYPE)))
            {
-             tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
+             tree dummy;
+             
+              /* If the type is a FUNCTION_TYPE, pick up the
+                 qualifiers from that function type. No other
+                 qualifiers may be supplied. */
+              if (TREE_CODE (type) == FUNCTION_TYPE)
+                quals = cp_type_quals (type);
+
+             dummy = build_decl (TYPE_DECL, NULL_TREE, type);
              grok_method_quals (declarator->u.pointer.class_type,
                                 dummy, quals);
              type = TREE_TYPE (dummy);
@@ -7175,8 +7350,22 @@ 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 if (declarator->u.pointer.class_type == error_mark_node)
+               /* We will already have complained.  */
+               type = error_mark_node;
+             else
+               type = build_ptrmem_type (declarator->u.pointer.class_type,
+                                         type);
+           }
          else
            type = build_pointer_type (type);
 
@@ -7197,7 +7386,7 @@ grokdeclarator (const cp_declarator *declarator,
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -7205,7 +7394,7 @@ grokdeclarator (const cp_declarator *declarator,
       && 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;
     }
@@ -7213,17 +7402,13 @@ grokdeclarator (const cp_declarator *declarator,
   /* 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)))
+      && 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))
        {
@@ -7256,12 +7441,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))
@@ -7275,7 +7460,7 @@ grokdeclarator (const cp_declarator *declarator,
                                            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;
            }
@@ -7290,7 +7475,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;
            }
@@ -7318,7 +7503,7 @@ 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;
@@ -7329,9 +7514,9 @@ grokdeclarator (const cp_declarator *declarator,
       && 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;
     }
 
@@ -7339,7 +7524,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;
     }
 
@@ -7347,28 +7532,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;
        }
     }
@@ -7384,20 +7569,29 @@ grokdeclarator (const cp_declarator *declarator,
        TYPE_FOR_JAVA (type) = 1;
 
       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",
-                    unqualified_id);
-         decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
-       }
+       decl = build_lang_decl (TYPE_DECL, unqualified_id, type);
       else
+       decl = build_decl (TYPE_DECL, unqualified_id, type);
+      if (id_declarator && declarator->u.id.qualifying_scope)
+       error ("%Jtypedef name may not be a nested-name-specifier", decl);
+
+      if (decl_context != FIELD)
        {
-         decl = build_decl (TYPE_DECL, unqualified_id, type);
-         if (in_namespace || ctype)
-           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;
+       }
+      else if (constructor_name_p (unqualified_id, current_class_type))
+       pedwarn ("ISO C++ forbids nested type %qD with same name "
+                "as enclosing class",
+                unqualified_id);
 
       /* If the user declares "typedef struct {...} foo" then the
         struct will have an anonymous name.  Fill that name in now.
@@ -7416,7 +7610,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;
@@ -7439,11 +7632,12 @@ grokdeclarator (const cp_declarator *declarator,
        {
          if (ctype == NULL_TREE)
            {
-             if (TREE_CODE (type) != METHOD_TYPE)
-               error ("%Jinvalid type qualifier for non-member function type",
-                      decl);
-             else
+              if (TREE_CODE (type) == METHOD_TYPE)
                ctype = TYPE_METHOD_BASETYPE (type);
+              /* Any qualifiers on a function type typedef have
+                 already been dealt with. */
+              else if (TREE_CODE (type) == FUNCTION_TYPE)
+                quals = TYPE_UNQUALIFIED;
            }
          if (ctype != NULL_TREE)
            grok_method_quals (ctype, decl, quals);
@@ -7486,6 +7680,23 @@ grokdeclarator (const cp_declarator *declarator,
        }
 
       parms = nreverse (decls);
+
+      if (decl_context != TYPENAME)
+        {
+          /* A cv-qualifier-seq shall only be part of the function type
+             for a non-static member function. [8.3.5/4 dcl.fct] */ 
+          if (cp_type_quals (type) != TYPE_UNQUALIFIED
+              && (current_class_type == NULL_TREE || staticp) )
+            {
+              error ("qualified function types cannot be used to declare %s functions",
+                     (staticp? "static member" : "free"));
+              type = TYPE_MAIN_VARIANT (type);
+            }
+          
+          /* The qualifiers on the function type become the qualifiers on
+             the non-static member function. */
+          quals |= cp_type_quals (type);
+        }
     }
 
   /* If this is a type name (such as, in a cast or sizeof),
@@ -7508,7 +7719,7 @@ grokdeclarator (const cp_declarator *declarator,
            }
          if (inlinep)
            {
-             error ("`inline' specified for friend class declaration");
+             error ("%<inline%> specified for friend class declaration");
              inlinep = 0;
            }
 
@@ -7519,11 +7730,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);
            }
 
@@ -7535,8 +7746,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;
            }
@@ -7565,38 +7776,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.
@@ -7641,7 +7846,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)
@@ -7649,15 +7854,6 @@ grokdeclarator (const cp_declarator *declarator,
            int publicp = 0;
            tree function_context;
 
-           /* We catch the others as conflicts with the builtin
-              typedefs.  */
-           if (friendp && unqualified_id == ridpointers[(int) RID_SIGNED])
-             {
-               error ("function `%D' cannot be declared friend",
-                      unqualified_id);
-               friendp = 0;
-             }
-
            if (friendp == 0)
              {
                if (ctype == NULL_TREE)
@@ -7665,7 +7861,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;
                  }
@@ -7674,7 +7870,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;
                  }
@@ -7683,7 +7879,8 @@ 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;
                      }
@@ -7694,6 +7891,18 @@ grokdeclarator (const cp_declarator *declarator,
                                                     TYPE_ARG_TYPES (type));
              }
 
+           /* Check that the name used for a destructor makes sense.  */
+           if (sfk == sfk_destructor
+               && !same_type_p (TREE_OPERAND 
+                                (id_declarator->u.id.unqualified_name, 0),
+                                ctype))
+             {
+               error ("declaration of %qD as member of %qT", 
+                      id_declarator->u.id.unqualified_name,
+                      ctype);
+               return error_mark_node;
+             }
+
            /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node.  */
            function_context = (ctype != NULL_TREE) ?
              decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
@@ -7706,7 +7915,8 @@ grokdeclarator (const cp_declarator *declarator,
                               unqualified_id,
                               virtualp, flags, quals, raises,
                               friendp ? -1 : 0, friendp, publicp, inlinep,
-                              funcdef_flag, template_count, in_namespace);
+                              sfk,
+                              funcdef_flag, template_count, in_namespace, attrlist);
            if (decl == NULL_TREE)
              return decl;
 #if 0
@@ -7752,8 +7962,9 @@ grokdeclarator (const cp_declarator *declarator,
                               parms,
                               unqualified_id,
                               virtualp, flags, quals, raises,
-                              friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
-                              template_count, in_namespace);
+                              friendp ? -1 : 0, friendp, 1, 0, sfk,
+                              funcdef_flag, template_count, in_namespace, 
+                              attrlist); 
            if (decl == NULL_TREE)
              return NULL_TREE;
          }
@@ -7762,9 +7973,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.  */
@@ -7773,8 +7984,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;
@@ -7783,7 +7994,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;
              }
@@ -7834,9 +8045,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;
                  }
 
@@ -7894,11 +8105,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
@@ -7909,16 +8120,18 @@ 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;
              }
          }
@@ -7936,8 +8149,8 @@ grokdeclarator (const cp_declarator *declarator,
        decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
                           virtualp, flags, quals, raises,
                           1, friendp,
-                          publicp, inlinep, funcdef_flag,
-                          template_count, in_namespace);
+                          publicp, inlinep, sfk, funcdef_flag,
+                          template_count, in_namespace, attrlist);
        if (decl == NULL_TREE)
          return NULL_TREE;
 
@@ -7949,7 +8162,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)
@@ -7984,19 +8198,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;
              }
          }
@@ -8016,7 +8232,7 @@ grokdeclarator (const cp_declarator *declarator,
        when processing a template; we'll do this for the instantiated
        declaration based on the type of DECL.  */
     if (!processing_template_decl)
-      c_apply_type_quals_to_decl (type_quals, decl);
+      cp_apply_type_quals_to_decl (type_quals, decl);
 
     return decl;
   }
@@ -8031,6 +8247,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;
@@ -8135,11 +8353,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;
     }
@@ -8155,8 +8373,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;
     }
 
@@ -8224,7 +8441,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;
            }
@@ -8248,8 +8465,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)
@@ -8297,9 +8515,10 @@ copy_fn_p (tree d)
   tree arg_type;
   int result = 1;
 
-  my_friendly_assert (DECL_FUNCTION_MEMBER_P (d), 20011208);
+  gcc_assert (DECL_FUNCTION_MEMBER_P (d));
 
-  if (DECL_TEMPLATE_INFO (d) && is_member_template (DECL_TI_TEMPLATE (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
@@ -8405,7 +8624,7 @@ 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;
     }
@@ -8485,10 +8704,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)
@@ -8529,9 +8748,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);
        }
     }
 
@@ -8551,13 +8770,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))
                {
@@ -8574,7 +8794,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;
@@ -8609,7 +8829,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);
            }
        }
@@ -8655,7 +8876,7 @@ grok_op_properties (tree decl, int friendp, bool complain)
                  break;
 
                default:
-                 abort ();
+                 gcc_unreachable ();
                }
 
              SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
@@ -8666,20 +8887,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.  */
@@ -8700,13 +8921,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);
                }
            }
        }
@@ -8715,9 +8936,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)) */
@@ -8725,9 +8946,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.  */
@@ -8735,8 +8956,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.  */
@@ -8749,7 +8970,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;
@@ -8761,10 +8982,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);
           }
 
     }
@@ -8772,6 +8993,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)
 {
@@ -8782,11 +9005,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 ();
     }
 }
 
@@ -8814,6 +9039,14 @@ check_elaborated_type_specifier (enum tag_types tag_code,
 
   type = TREE_TYPE (decl);
 
+  /* 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
@@ -8822,29 +9055,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))
-    {
-      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)
+  else if (!DECL_IMPLICIT_TYPEDEF_P (decl)
+          && tag_code != typename_type)
     {
-      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
@@ -8859,7 +9091,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;
@@ -8868,31 +9100,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)
     {
@@ -8907,93 +9199,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.
-
-            For example:
+    t = lookup_and_check_tag  (tag_code, name,
+                              scope, template_header_p);
 
-              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
-              };  */
+  if (t == error_mark_node)
+    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
 
-         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)
@@ -9004,25 +9265,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
               && 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;
        }
     }
@@ -9031,7 +9293,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;
 
@@ -9043,7 +9305,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
@@ -9056,8 +9318,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.  */
@@ -9095,12 +9357,12 @@ 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);
 
@@ -9115,30 +9377,21 @@ xref_basetypes (tree ref, tree base_list)
       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))
@@ -9157,21 +9410,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;
 
@@ -9179,7 +9422,7 @@ 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.  */
@@ -9188,12 +9431,24 @@ xref_basetypes (tree ref, tree base_list)
          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);
@@ -9204,15 +9459,41 @@ xref_basetypes (tree ref, tree base_list)
       BINFO_BASE_ACCESS_APPEND (binfo, access);
     }
 
+  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.  */
@@ -9220,27 +9501,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;
@@ -9260,6 +9548,7 @@ finish_enum (tree enumtype)
   tree maxnode;
   tree t;
   bool unsignedp;
+  bool use_short_enum;
   int lowprec;
   int highprec;
   int precision;
@@ -9311,16 +9600,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
@@ -9352,8 +9631,14 @@ finish_enum (tree enumtype)
 
      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);
+     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++)
     {
@@ -9369,7 +9654,7 @@ 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];
     }
@@ -9383,7 +9668,14 @@ 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]
@@ -9405,6 +9697,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;
@@ -9440,6 +9736,11 @@ build_enumerator (tree name, tree value, tree enumtype)
   tree context;
   tree type;
 
+  /* If the VALUE was erroneous, pretend it wasn't there; that will
+     result in the enum being assigned the next value in sequence.  */
+  if (value == error_mark_node)
+    value = NULL_TREE;
+
   /* Remove no-op casts from the value.  */
   if (value)
     STRIP_TYPE_NOPS (value);
@@ -9449,7 +9750,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)
            {
@@ -9458,7 +9759,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;
            }
        }
@@ -9466,19 +9767,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;
@@ -9490,8 +9798,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
@@ -9547,9 +9853,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.  */
@@ -9600,10 +9908,11 @@ 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)
@@ -9626,7 +9935,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
@@ -9663,7 +9972,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.  */
@@ -9691,8 +10000,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);
@@ -9708,7 +10016,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
       DECL_IGNORED_P (resdecl) = 1;
       DECL_RESULT (decl1) = resdecl;
 
-      c_apply_type_quals_to_decl (cp_type_quals (restype), resdecl);
+      cp_apply_type_quals_to_decl (cp_type_quals (restype), resdecl);
     }
 
   /* Initialize RTL machinery.  We cannot do this until
@@ -9788,10 +10096,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);
@@ -9807,8 +10113,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;
        }
     }
@@ -9829,7 +10134,7 @@ 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)
@@ -9837,7 +10142,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
          || processing_template_decl)
        {
          DECL_EXTERNAL (decl1)
-           = (interface_only
+           = (finfo->interface_only
               || (DECL_DECLARED_INLINE_P (decl1)
                   && ! flag_implement_inlines
                   && !DECL_VINDEX (decl1)));
@@ -9855,14 +10160,15 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
       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;
@@ -9929,23 +10235,15 @@ start_function (cp_decl_specifier_seq *declspecs,
   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);
 
@@ -9997,7 +10295,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
            {
@@ -10046,8 +10344,7 @@ 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_NEW (struct language_function);
@@ -10273,7 +10570,7 @@ 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.  */
@@ -10281,12 +10578,19 @@ finish_function (int flags)
     {
       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.  */
@@ -10319,8 +10623,7 @@ finish_function (int flags)
   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.  */
@@ -10338,7 +10641,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.  */
@@ -10402,11 +10705,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.  */
@@ -10484,7 +10799,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;
     }
@@ -10561,7 +10876,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;
     }
 
@@ -10574,8 +10889,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;
     }
 
@@ -10589,7 +10904,7 @@ 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
@@ -10618,15 +10933,17 @@ complete_vars (tree type)
 {
   tree *list = &incomplete_vars;
 
-  my_friendly_assert (CLASS_TYPE_P (type), 20020406);
+  gcc_assert (CLASS_TYPE_P (type));
   while (*list)
     {
       if (same_type_p (type, TREE_PURPOSE (*list)))
        {
          tree var = TREE_VALUE (*list);
+         tree type = TREE_TYPE (var);
          /* Complete the type of the variable.  The VAR_DECL itself
             will be laid out in expand_expr.  */
-         complete_type (TREE_TYPE (var));
+         complete_type (type);
+         cp_apply_type_quals_to_decl (cp_type_quals (type), var);
          /* Remove this entry from the list.  */
          *list = TREE_CHAIN (*list);
        }
@@ -10650,6 +10967,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;
@@ -10660,17 +10979,12 @@ 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))
-       rval = build_compound_expr (rval, build_vbase_delete (type, decl));
-
       return rval;
     }
   return NULL_TREE;
@@ -10695,8 +11009,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);
@@ -10784,5 +11097,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"