OSDN Git Service

PR c++/8795
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index d269140..d89ec91 100644 (file)
@@ -92,7 +92,6 @@ static void check_for_uninitialized_const_var (tree);
 static hashval_t typename_hash (const void *);
 static int typename_compare (const void *, const void *);
 static void push_binding (tree, tree, struct cp_binding_level*);
-static int add_binding (tree, tree);
 static void pop_binding (tree, tree);
 static tree local_variable_p_walkfn (tree *, int *, void *);
 static tree select_decl (cxx_binding *, int);
@@ -918,42 +917,41 @@ push_binding (tree id, tree decl, cxx_scope* level)
    bound at the same level as some other kind of entity.  It's the
    responsibility of the caller to check that inserting this name is
    valid here.  Returns nonzero if the new binding was successful.  */
-static int
-add_binding (tree id, tree decl)
+
+int
+add_binding (cxx_binding *binding, tree decl)
 {
-  cxx_binding *binding = IDENTIFIER_BINDING (id);
+  tree bval = BINDING_VALUE (binding);
   int ok = 1;
 
   timevar_push (TV_NAME_LOOKUP);
   if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
     /* The new name is the type name.  */
     BINDING_TYPE (binding) = decl;
-  else if (!BINDING_VALUE (binding))
+  else if (!bval)
     /* This situation arises when push_class_level_binding moves an
        inherited type-binding out of the way to make room for a new
        value binding.  */
     BINDING_VALUE (binding) = decl;
-  else if (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
-          && DECL_ARTIFICIAL (BINDING_VALUE (binding)))
+  else if (TREE_CODE (bval) == TYPE_DECL && DECL_ARTIFICIAL (bval))
     {
       /* The old binding was a type name.  It was placed in
         BINDING_VALUE because it was thought, at the point it was
         declared, to be the only entity with such a name.  Move the
         type name into the type slot; it is now hidden by the new
         binding.  */
-      BINDING_TYPE (binding) = BINDING_VALUE (binding);
+      BINDING_TYPE (binding) = bval;
       BINDING_VALUE (binding) = decl;
       INHERITED_VALUE_BINDING_P (binding) = 0;
     }
-  else if (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+  else if (TREE_CODE (bval) == TYPE_DECL
           && TREE_CODE (decl) == TYPE_DECL
-          && DECL_NAME (decl) == DECL_NAME (BINDING_VALUE (binding))
-          && (same_type_p (TREE_TYPE (decl),
-                           TREE_TYPE (BINDING_VALUE (binding)))
+          && DECL_NAME (decl) == DECL_NAME (bval)
+          && (same_type_p (TREE_TYPE (decl), TREE_TYPE (bval))
               /* If either type involves template parameters, we must
                  wait until instantiation.  */
               || uses_template_parms (TREE_TYPE (decl))
-              || uses_template_parms (TREE_TYPE (BINDING_VALUE (binding)))))
+              || uses_template_parms (TREE_TYPE (bval))))
     /* We have two typedef-names, both naming the same type to have
        the same name.  This is OK because of:
 
@@ -964,11 +962,16 @@ add_binding (tree id, tree decl)
         type to which it already refers.  */
     ok = 0;
   /* There can be two block-scope declarations of the same variable,
-     so long as they are `extern' declarations.  */
-  else if (TREE_CODE (decl) == VAR_DECL
-          && TREE_CODE (BINDING_VALUE (binding)) == VAR_DECL
-          && DECL_EXTERNAL (decl)
-          && DECL_EXTERNAL (BINDING_VALUE (binding)))
+     so long as they are `extern' declarations.  However, there cannot
+     be two declarations of the same static data member:
+
+       [class.mem]
+
+       A member shall not be declared twice in the
+       member-specification.  */
+  else if (TREE_CODE (decl) == VAR_DECL && TREE_CODE (bval) == VAR_DECL
+          && DECL_EXTERNAL (decl) && DECL_EXTERNAL (bval)
+          && !DECL_CLASS_SCOPE_P (decl))
     {
       duplicate_decls (decl, BINDING_VALUE (binding));
       ok = 0;
@@ -1037,7 +1040,7 @@ push_local_binding (tree id, tree decl, int flags)
   if (lookup_name_current_level (id))
     {
       /* Supplement the existing binding.  */
-      if (!add_binding (id, decl))
+      if (!add_binding (IDENTIFIER_BINDING (id), decl))
        /* It didn't work.  Something else must be bound at this
           level.  Do not add DECL to the list of things to pop
           later.  */
@@ -1076,7 +1079,7 @@ push_class_binding (tree id, tree decl)
 
   if (binding && BINDING_SCOPE (binding) == class_binding_level)
     /* Supplement the existing binding.  */
-    result = add_binding (id, decl);
+    result = add_binding (IDENTIFIER_BINDING (id), decl);
   else
     /* Create a new binding.  */
     push_binding (id, decl, class_binding_level);
@@ -1168,9 +1171,13 @@ pop_label (tree label, tree old_value)
     {
       if (DECL_INITIAL (label) == NULL_TREE)
        {
+         location_t location;
+
          cp_error_at ("label `%D' used but not defined", label);
+         location.file = input_filename;
+         location.line = 0;
          /* Avoid crashing later.  */
-         define_label (input_filename, 1, DECL_NAME (label));
+         define_label (location, DECL_NAME (label));
        }
       else if (warn_unused_label && !TREE_USED (label))
        cp_warning_at ("label `%D' defined but not used", label);
@@ -1889,8 +1896,7 @@ print_binding_level (struct cp_binding_level* lvl)
 {
   tree t;
   int i = 0, len;
-  fprintf (stderr, " blocks=");
-  fprintf (stderr, HOST_PTR_PRINTF, (void *) lvl->blocks);
+  fprintf (stderr, " blocks=" HOST_PTR_PRINTF, (void *) lvl->blocks);
   if (lvl->tag_transparent)
     fprintf (stderr, " tag-transparent");
   if (lvl->more_cleanups_ok)
@@ -1963,9 +1969,7 @@ print_other_binding_stack (struct cp_binding_level *stack)
   struct cp_binding_level *level;
   for (level = stack; !global_scope_p (level); level = level->level_chain)
     {
-      fprintf (stderr, "binding level ");
-      fprintf (stderr, HOST_PTR_PRINTF, (void *) level);
-      fprintf (stderr, "\n");
+      fprintf (stderr, "binding level " HOST_PTR_PRINTF "\n", (void *) level);
       print_binding_level (level);
     }
 }
@@ -1974,14 +1978,11 @@ void
 print_binding_stack (void)
 {
   struct cp_binding_level *b;
-  fprintf (stderr, "current_binding_level=");
-  fprintf (stderr, HOST_PTR_PRINTF, (void *) current_binding_level);
-  fprintf (stderr, "\nclass_binding_level=");
-  fprintf (stderr, HOST_PTR_PRINTF, (void *) class_binding_level);
-  fprintf (stderr, "\nNAMESPACE_LEVEL (global_namespace)=");
-  fprintf (stderr, HOST_PTR_PRINTF,
+  fprintf (stderr, "current_binding_level=" HOST_PTR_PRINTF
+          "\nclass_binding_level=" HOST_PTR_PRINTF
+          "\nNAMESPACE_LEVEL (global_namespace)=" HOST_PTR_PRINTF "\n",
+          (void *) current_binding_level, (void *) class_binding_level,
            (void *) NAMESPACE_LEVEL (global_namespace));
-  fprintf (stderr, "\n");
   if (class_binding_level)
     {
       for (b = class_binding_level; b; b = b->level_chain)
@@ -2215,7 +2216,7 @@ maybe_push_to_top_level (int pseudo)
   int need_pop;
 
   timevar_push (TV_NAME_LOOKUP);
-  s = (struct saved_scope *) ggc_alloc_cleared (sizeof (struct saved_scope));
+  s = ggc_alloc_cleared (sizeof (struct saved_scope));
 
   b = scope_chain ? current_binding_level : 0;
 
@@ -2308,24 +2309,17 @@ pop_from_top_level (void)
   timevar_pop (TV_NAME_LOOKUP);
 }
 \f
-/* Push a definition of struct, union or enum tag "name".
-   into binding_level "b".   "type" should be the type node,
-   We assume that the tag "name" is not already defined.
-
-   Note that the definition may really be just a forward reference.
-   In that case, the TYPE_SIZE will be a NULL_TREE.
-
-   C++ gratuitously puts all these tags in the name space.  */
-
-/* When setting the IDENTIFIER_TYPE_VALUE field of an identifier ID,
-   record the shadowed value for this binding contour.  TYPE is
-   the type that ID maps to.  */
+/* Push a definition of struct, union or enum tag named ID.  into
+   binding_level B.  DECL is a TYPE_DECL for the type.  We assume that
+   the tag ID is not already defined.  */
 
 static void
 set_identifier_type_value_with_scope (tree id, 
-                                      tree type, 
+                                      tree decl,
                                       struct cp_binding_level* b)
 {
+  tree type;
+
   if (!b->namespace_p)
     {
       /* Shadow the marker, not the real thing, so that the marker
@@ -2333,12 +2327,21 @@ set_identifier_type_value_with_scope (tree id,
       tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
       b->type_shadowed
        = tree_cons (id, old_type_value, b->type_shadowed);
+      type = decl ? TREE_TYPE (decl) : NULL_TREE;
     }
   else
     {
       cxx_binding *binding =
-         binding_for_name (NAMESPACE_LEVEL (current_namespace), id);
-      BINDING_TYPE (binding) = type;
+       binding_for_name (NAMESPACE_LEVEL (current_namespace), id);
+      if (decl)
+       {
+         if (BINDING_VALUE (binding))
+           add_binding (binding, decl);
+         else
+           BINDING_VALUE (binding) = decl;
+       }
+      else
+       abort ();
       /* Store marker instead of real type.  */
       type = global_type_node;
     }
@@ -2348,9 +2351,9 @@ set_identifier_type_value_with_scope (tree id,
 /* As set_identifier_type_value_with_scope, but using current_binding_level.  */
 
 void
-set_identifier_type_value (tree id, tree type)
+set_identifier_type_value (tree id, tree decl)
 {
-  set_identifier_type_value_with_scope (id, type, current_binding_level);
+  set_identifier_type_value_with_scope (id, decl, current_binding_level);
 }
 
 /* Return the type associated with id.  */
@@ -2366,7 +2369,7 @@ identifier_type_value (tree id)
   if (REAL_IDENTIFIER_TYPE_VALUE (id) != global_type_node)
     POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, REAL_IDENTIFIER_TYPE_VALUE (id));
   /* Have to search for it. It must be on the global level, now.
-     Ask lookup_name not to return non-types. */
+     Ask lookup_name not to return non-types.  */
   id = lookup_name_real (id, 2, 1, 0, LOOKUP_COMPLAIN);
   if (id)
     POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_TYPE (id));
@@ -2584,7 +2587,7 @@ pushtag (tree name, tree type, int globalize)
          d = create_implicit_typedef (name, type);
          DECL_CONTEXT (d) = FROB_CONTEXT (context);
          if (! in_class)
-           set_identifier_type_value_with_scope (name, type, b);
+           set_identifier_type_value_with_scope (name, d, b);
 
          d = maybe_process_template_type_declaration (type,
                                                       globalize, b);
@@ -2756,16 +2759,17 @@ decls_match (tree newdecl, tree olddecl)
     }
   else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
     {
-      if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
-                               DECL_TEMPLATE_PARMS (olddecl)))
-       return 0;
-
       if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl))
          != TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)))
        return 0;
 
+      if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
+                               DECL_TEMPLATE_PARMS (olddecl)))
+       return 0;
+
       if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
-       types_match = 1;
+       types_match = same_type_p (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl)),
+                                  TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl)));
       else
        types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
                                   DECL_TEMPLATE_RESULT (newdecl));
@@ -3127,7 +3131,8 @@ duplicate_decls (tree newdecl, tree olddecl)
        {
          /* Prototype decl follows defn w/o prototype.  */
          cp_warning_at ("prototype for `%#D'", newdecl);
-         cp_warning_at ("follows non-prototype definition here", olddecl);
+         warning ("%Hfollows non-prototype definition here",
+                  &DECL_SOURCE_LOCATION (olddecl));
        }
       else if (TREE_CODE (olddecl) == FUNCTION_DECL
               && DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
@@ -3184,8 +3189,8 @@ duplicate_decls (tree newdecl, tree olddecl)
            {
              warning ("`%#D' was used before it was declared inline",
                          newdecl);
-             cp_warning_at ("previous non-inline declaration here",
-                            olddecl);
+             warning ("%Hprevious non-inline declaration here",
+                      &DECL_SOURCE_LOCATION (olddecl));
            }
        }
     }
@@ -3300,6 +3305,8 @@ duplicate_decls (tree newdecl, tree olddecl)
        {
          DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
          DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
+         DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
+           |= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
        }
 
       /* Do this after calling `merge_types' so that default
@@ -3524,7 +3531,7 @@ duplicate_decls (tree newdecl, tree olddecl)
              SET_DECL_RTL (newdecl, DECL_RTL (olddecl));
            }
          else
-           DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
+           DECL_ESTIMATED_INSNS (newdecl) = DECL_ESTIMATED_INSNS (olddecl);
 
          DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
          /* Don't clear out the arguments if we're redefining a function.  */
@@ -3552,36 +3559,30 @@ duplicate_decls (tree newdecl, tree olddecl)
              function_size - sizeof (struct tree_common));
 
       if (DECL_TEMPLATE_INSTANTIATION (newdecl))
-       {
-         /* If newdecl is a template instantiation, it is possible that
-            the following sequence of events has occurred:
-
-            o A friend function was declared in a class template.  The
-            class template was instantiated.
-
-            o The instantiation of the friend declaration was
-            recorded on the instantiation list, and is newdecl.
+       /* If newdecl is a template instantiation, it is possible that
+          the following sequence of events has occurred:
 
-            o Later, however, instantiate_class_template called pushdecl
-            on the newdecl to perform name injection.  But, pushdecl in
-            turn called duplicate_decls when it discovered that another
-            declaration of a global function with the same name already
-            existed.
+          o A friend function was declared in a class template.  The
+          class template was instantiated.
 
-            o Here, in duplicate_decls, we decided to clobber newdecl.
+          o The instantiation of the friend declaration was
+          recorded on the instantiation list, and is newdecl.
 
-            If we're going to do that, we'd better make sure that
-            olddecl, and not newdecl, is on the list of
-            instantiations so that if we try to do the instantiation
-            again we won't get the clobbered declaration.  */
+          o Later, however, instantiate_class_template called pushdecl
+          on the newdecl to perform name injection.  But, pushdecl in
+          turn called duplicate_decls when it discovered that another
+          declaration of a global function with the same name already
+          existed.
 
-         tree tmpl = DECL_TI_TEMPLATE (newdecl);
-         tree decls = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
+          o Here, in duplicate_decls, we decided to clobber newdecl.
 
-         for (; decls; decls = TREE_CHAIN (decls))
-           if (TREE_VALUE (decls) == newdecl)
-             TREE_VALUE (decls) = olddecl;
-       }
+          If we're going to do that, we'd better make sure that
+          olddecl, and not newdecl, is on the list of
+          instantiations so that if we try to do the instantiation
+          again we won't get the clobbered declaration.  */
+       reregister_specialization (newdecl, 
+                                  DECL_TI_TEMPLATE (newdecl), 
+                                  olddecl);
     }
   else
     {
@@ -3744,7 +3745,7 @@ pushdecl (tree x)
          else if (TREE_CODE (t) == PARM_DECL)
            {
              if (DECL_CONTEXT (t) == NULL_TREE)
-               /* This is probaby caused by too many errors, but calling
+               /* This is probably caused by too many errors, but calling
                   abort will say that if errors have occurred.  */
                abort ();
 
@@ -3852,9 +3853,7 @@ pushdecl (tree x)
          if (type != error_mark_node
              && TYPE_NAME (type)
              && TYPE_IDENTIFIER (type))
-            set_identifier_type_value_with_scope (DECL_NAME (x), type,
-                                                 current_binding_level);
-
+            set_identifier_type_value (DECL_NAME (x), x);
        }
 
       /* Multiple external decls of the same identifier ought to match.
@@ -3877,7 +3876,7 @@ pushdecl (tree x)
              && TREE_CODE (decl) == TREE_CODE (x)
              && !same_type_p (TREE_TYPE (x), TREE_TYPE (decl)))
            {
-             pedwarn ("type mismatch with previous external decl", x);
+             pedwarn ("type mismatch with previous external decl of `%#D'", x);
              cp_pedwarn_at ("previous external decl of `%#D'", decl);
            }
        }
@@ -3944,15 +3943,13 @@ pushdecl (tree x)
 
          /* If this is a TYPE_DECL, push it into the type value slot.  */
          if (TREE_CODE (x) == TYPE_DECL)
-           set_identifier_type_value_with_scope (name, TREE_TYPE (x),
-                                                 current_binding_level);
+           set_identifier_type_value (name, x);
 
          /* Clear out any TYPE_DECL shadowed by a namespace so that
             we won't think this is a type.  The C struct hack doesn't
             go through namespaces.  */
          if (TREE_CODE (x) == NAMESPACE_DECL)
-           set_identifier_type_value_with_scope (name, NULL_TREE,
-                                                 current_binding_level);
+           set_identifier_type_value (name, NULL_TREE);
 
          if (oldlocal)
            {
@@ -4133,7 +4130,7 @@ pushdecl_namespace_level (tree x)
         {
           /* @@ This shouldn't be needed.  My test case "zstring.cc" trips
              up here if this is changed to an assertion.  --KR  */
-         SET_IDENTIFIER_TYPE_VALUE (name, newval);
+         SET_IDENTIFIER_TYPE_VALUE (name, x);
        }
       else
         {
@@ -4143,24 +4140,47 @@ pushdecl_namespace_level (tree x)
   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
 }
 
-/* Like pushdecl, only it places X in the global scope if appropriate.  */
+/* Like pushdecl, only it places X in the global scope if appropriate.
+   Calls cp_finish_decl to register the variable, initializing it with
+   *INIT, if INIT is non-NULL.  */
 
-tree
-pushdecl_top_level (tree x)
+static tree
+pushdecl_top_level_1 (tree x, tree *init)
 {
   timevar_push (TV_NAME_LOOKUP);
   push_to_top_level ();
   x = pushdecl_namespace_level (x);
+  if (init)
+    cp_finish_decl (x, *init, NULL_TREE, 0);
   pop_from_top_level ();
   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
 }
 
+/* Like pushdecl, only it places X in the global scope if appropriate.  */
+
+tree
+pushdecl_top_level (tree x)
+{
+  return pushdecl_top_level_1 (x, NULL);
+}
+
+/* Like pushdecl, only it places X in the global scope if
+   appropriate.  Calls cp_finish_decl to register the variable,
+   initializing it with INIT.  */
+
+tree
+pushdecl_top_level_and_finish (tree x, tree init)
+{
+  return pushdecl_top_level_1 (x, &init);
+}
+
 /* Make the declaration of X appear in CLASS scope.  */
 
-void
+bool
 pushdecl_class_level (tree x)
 {
   tree name;
+  bool is_valid = true;
 
   timevar_push (TV_NAME_LOOKUP);
   /* Get the name of X.  */
@@ -4171,9 +4191,9 @@ pushdecl_class_level (tree x)
 
   if (name)
     {
-      push_class_level_binding (name, x);
+      is_valid = push_class_level_binding (name, x);
       if (TREE_CODE (x) == TYPE_DECL)
-       set_identifier_type_value (name, TREE_TYPE (x));
+       set_identifier_type_value (name, x);
     }
   else if (ANON_AGGR_TYPE_P (TREE_TYPE (x)))
     {
@@ -4183,9 +4203,17 @@ pushdecl_class_level (tree x)
       tree f;
 
       for (f = TYPE_FIELDS (TREE_TYPE (x)); f; f = TREE_CHAIN (f))
-       pushdecl_class_level (f);
+       {
+         location_t save_location = input_location;
+         input_location = DECL_SOURCE_LOCATION (f);
+         if (!pushdecl_class_level (f))
+           is_valid = false;
+         input_location = save_location;
+       }
     }
   timevar_pop (TV_NAME_LOOKUP);
+
+  return is_valid;
 }
 
 /* Enter DECL into the symbol table, if that's appropriate.  Returns
@@ -4217,21 +4245,19 @@ maybe_push_decl (tree decl)
     return pushdecl (decl);
 }
 
-/* Make the declaration(s) of X appear in CLASS scope
-   under the name NAME.  */
+/* Make the declaration(s) of X appear in CLASS scope under the name
+   NAME.  Returns true if the binding is valid.  */
 
-void
+bool
 push_class_level_binding (tree name, tree x)
 {
   cxx_binding *binding;
+
   timevar_push (TV_NAME_LOOKUP);
   /* The class_binding_level will be NULL if x is a template
      parameter name in a member template.  */
   if (!class_binding_level)
-    {
-      timevar_pop (TV_NAME_LOOKUP);
-      return;
-    }
+    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
 
   /* Make sure that this new member does not have the same name
      as a template parameter.  */
@@ -4242,48 +4268,54 @@ push_class_level_binding (tree name, tree x)
      class, then we will need to restore IDENTIFIER_CLASS_VALUE when
      we leave this class.  Record the shadowed declaration here.  */
   binding = IDENTIFIER_BINDING (name);
-  if (binding
-      && ((TREE_CODE (x) == OVERLOAD
-          && BINDING_VALUE (binding)
-          && is_overloaded_fn (BINDING_VALUE (binding)))
-         || INHERITED_VALUE_BINDING_P (binding)))
+  if (binding && BINDING_VALUE (binding))
     {
-      tree shadow;
-      tree old_decl;
+      tree bval = BINDING_VALUE (binding);
+      tree old_decl = NULL_TREE;
 
-      /* If the old binding was from a base class, and was for a tag
-        name, slide it over to make room for the new binding.  The
-        old binding is still visible if explicitly qualified with a
-        class-key.  */
-      if (INHERITED_VALUE_BINDING_P (binding)
-         && BINDING_VALUE (binding)
-         && TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
-         && DECL_ARTIFICIAL (BINDING_VALUE (binding))
-         && !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
-       {
-         old_decl = BINDING_TYPE (binding);
-         BINDING_TYPE (binding) = BINDING_VALUE (binding);
-         BINDING_VALUE (binding) = NULL_TREE;
-         INHERITED_VALUE_BINDING_P (binding) = 0;
+      if (INHERITED_VALUE_BINDING_P (binding))
+       {
+         /* If the old binding was from a base class, and was for a
+            tag name, slide it over to make room for the new binding.
+            The old binding is still visible if explicitly qualified
+            with a class-key.  */
+         if (TREE_CODE (bval) == TYPE_DECL && DECL_ARTIFICIAL (bval)
+             && !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
+           {
+             BINDING_TYPE (binding) = bval;
+             BINDING_VALUE (binding) = NULL_TREE;
+             INHERITED_VALUE_BINDING_P (binding) = 0;
+           }
+         old_decl = bval;
+       }
+      else if (TREE_CODE (x) == OVERLOAD && is_overloaded_fn (bval))
+       old_decl = bval;
+      else if (TREE_CODE (x) == USING_DECL && TREE_CODE (bval) == USING_DECL)
+       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
+      else if (TREE_CODE (x) == USING_DECL && is_overloaded_fn (bval))
+       old_decl = bval;
+      else if (TREE_CODE (bval) == USING_DECL && is_overloaded_fn (x))
+       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
+      
+      if (old_decl)
+       {
+         tree shadow;
+         
+         /* Find the previous binding of name on the class-shadowed
+             list, and update it.  */
+         for (shadow = class_binding_level->class_shadowed;
+              shadow;
+              shadow = TREE_CHAIN (shadow))
+           if (TREE_PURPOSE (shadow) == name
+               && TREE_TYPE (shadow) == old_decl)
+             {
+               BINDING_VALUE (binding) = x;
+               INHERITED_VALUE_BINDING_P (binding) = 0;
+               TREE_TYPE (shadow) = x;
+               IDENTIFIER_CLASS_VALUE (name) = x;
+               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
+             }
        }
-      else
-       old_decl = BINDING_VALUE (binding);
-
-      /* Find the previous binding of name on the class-shadowed
-         list, and update it.  */
-      for (shadow = class_binding_level->class_shadowed;
-          shadow;
-          shadow = TREE_CHAIN (shadow))
-       if (TREE_PURPOSE (shadow) == name
-           && TREE_TYPE (shadow) == old_decl)
-         {
-           BINDING_VALUE (binding) = x;
-           INHERITED_VALUE_BINDING_P (binding) = 0;
-           TREE_TYPE (shadow) = x;
-           IDENTIFIER_CLASS_VALUE (name) = x;
-           timevar_pop (TV_NAME_LOOKUP);
-           return;
-         }
     }
 
   /* If we didn't replace an existing binding, put the binding on the
@@ -4296,8 +4328,10 @@ push_class_level_binding (tree name, tree x)
       /* Record the value we are binding NAME to so that we can know
         what to pop later.  */
       TREE_TYPE (class_binding_level->class_shadowed) = x;
+      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
     }
-  timevar_pop (TV_NAME_LOOKUP);
+
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false);
 }
 
 /* Insert another USING_DECL into the current binding level, returning
@@ -4638,8 +4672,7 @@ use_label (tree decl)
       || named_label_uses->label_decl != decl)
     {
       struct named_label_use_list *new_ent;
-      new_ent = ((struct named_label_use_list *)
-                ggc_alloc (sizeof (struct named_label_use_list)));
+      new_ent = ggc_alloc (sizeof (struct named_label_use_list));
       new_ent->label_decl = decl;
       new_ent->names_in_scope = current_binding_level->names;
       new_ent->binding_level = current_binding_level;
@@ -4676,8 +4709,7 @@ lookup_label (tree id)
   /* Record this label on the list of labels used in this function.
      We do this before calling make_label_decl so that we get the
      IDENTIFIER_LABEL_VALUE before the new label is declared.  */
-  ent = ((struct named_label_list *)
-        ggc_alloc_cleared (sizeof (struct named_label_list)));
+  ent = ggc_alloc_cleared (sizeof (struct named_label_list));
   ent->old_value = IDENTIFIER_LABEL_VALUE (id);
   ent->next = named_labels;
   named_labels = ent;
@@ -4885,7 +4917,7 @@ check_goto (tree decl)
 
       if (u > 1 && DECL_ARTIFICIAL (b))
        /* Can't skip init of __exception_info.  */
-       cp_error_at ("  enters catch block", b);
+       error ("%H  enters catch block", &DECL_SOURCE_LOCATION (b));
       else if (u > 1)
        cp_error_at ("  skips initialization of `%#D'", b);
       else
@@ -4903,7 +4935,7 @@ check_goto (tree decl)
    Otherwise return 0.  */
 
 tree
-define_label (const char* filename, int line, tree name)
+define_label (location_t location, tree name)
 {
   tree decl = lookup_label (name);
   struct named_label_list *ent;
@@ -4932,8 +4964,7 @@ define_label (const char* filename, int line, tree name)
       /* Mark label as having been defined.  */
       DECL_INITIAL (decl) = error_mark_node;
       /* Say where in the source.  */
-      DECL_SOURCE_FILE (decl) = filename;
-      DECL_SOURCE_LINE (decl) = line;
+      DECL_SOURCE_LOCATION (decl) = location;
       if (ent)
        {
          ent->names_in_scope = current_binding_level->names;
@@ -4973,8 +5004,7 @@ static struct cp_switch *switch_stack;
 void
 push_switch (tree switch_stmt)
 {
-  struct cp_switch *p
-    = (struct cp_switch *) xmalloc (sizeof (struct cp_switch));
+  struct cp_switch *p = xmalloc (sizeof (struct cp_switch));
   p->level = current_binding_level;
   p->next = switch_stack;
   p->switch_stmt = switch_stmt;
@@ -5159,9 +5189,9 @@ lookup_tag (enum tree_code form, tree name,
            if (thislevel_only && !allow_template_parms_p
                && binding && BINDING_VALUE (binding)
                && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (binding)))
-             old = TREE_TYPE (BINDING_VALUE (binding));
+             old = BINDING_VALUE (binding);
            else if (binding)
-             old = BINDING_TYPE (binding);
+             old = select_decl (binding, LOOKUP_PREFER_TYPES);
             else
               old = NULL_TREE;
 
@@ -5170,6 +5200,7 @@ lookup_tag (enum tree_code form, tree name,
                /* We've found something at this binding level.  If it is
                   a typedef, extract the tag it refers to.  Lookup fails
                   if the typedef doesn't refer to a taggable type.  */
+               old = TREE_TYPE (old);
                old = follow_tag_typedef (old);
                if (!old)
                  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
@@ -5379,12 +5410,12 @@ typename_compare (const void * k1, const void * k2)
 
 static GTY ((param_is (union tree_node))) htab_t typename_htab;
 
-tree
+static tree
 build_typename_type (tree context, tree name, tree fullname)
 {
   tree t;
   tree d;
-  PTR *e;
+  void **e;
 
   if (typename_htab == NULL)
     {
@@ -5459,9 +5490,8 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
       error ("`%D' used without template parameters", name);
       return error_mark_node;
     }
-  if (TREE_CODE (name) != IDENTIFIER_NODE)
-    abort ();
-
+  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
@@ -5489,13 +5519,13 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
            }
 
          if (complain & tf_error)
-           perform_or_defer_access_check (context, tmpl);
+           perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
 
          return lookup_template_class (tmpl,
                                        TREE_OPERAND (fullname, 1),
                                        NULL_TREE, context,
                                        /*entering_scope=*/0,
-                                       tf_error | tf_warning);
+                                       tf_error | tf_warning | tf_user);
        }
       else
        {
@@ -5519,7 +5549,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
                }
 
              if (complain & tf_error)
-               perform_or_defer_access_check (context, t);
+               perform_or_defer_access_check (TYPE_BINFO (context), t);
 
              if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
                t = TREE_TYPE (t);
@@ -5576,7 +5606,7 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
        }
       
       if (complain & tf_error)
-       perform_or_defer_access_check (context, tmpl);
+       perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
 
       return tmpl;
     }
@@ -5613,12 +5643,11 @@ select_decl (cxx_binding *binding, int flags)
       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
     }
 
-  /* If we could have a type and
-     we have nothing or we need a type and have none.  */
-  if (BINDING_TYPE (binding)
-      && (!val || ((flags & LOOKUP_PREFER_TYPES)
-                   && TREE_CODE (val) != TYPE_DECL)))
-    val = TYPE_STUB_DECL (BINDING_TYPE (binding));
+  /* If looking for a type, or if there is no non-type binding, select
+     the value binding.  */
+  if (BINDING_TYPE (binding) 
+      && (!val || (flags & LOOKUP_PREFER_TYPES)))
+    val = BINDING_TYPE (binding);
   /* Don't return non-types if we really prefer types.  */
   else if (val && LOOKUP_TYPES_ONLY (flags)  && TREE_CODE (val) != TYPE_DECL
           && (TREE_CODE (val) != TEMPLATE_DECL
@@ -5721,7 +5750,8 @@ qualify_lookup (tree val, int flags)
     return val;
   if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL)
     return val;
-  if ((flags & LOOKUP_PREFER_TYPES) && TREE_CODE (val) == TYPE_DECL)
+  if ((flags & LOOKUP_PREFER_TYPES)
+      && (TREE_CODE (val) == TYPE_DECL || TREE_CODE (val) == TEMPLATE_DECL))
     return val;
   if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
     return NULL_TREE;
@@ -5733,11 +5763,15 @@ qualify_lookup (tree val, int flags)
    bindings.  
 
    Returns a DECL (or OVERLOAD, or BASELINK) representing the
-   declaration found.  */
+   declaration found.  If no suitable declaration can be found,
+   ERROR_MARK_NODE is returned.  Iif COMPLAIN is true and SCOPE is
+   neither a class-type nor a namespace a diagnostic is issued.  */
 
 tree
-lookup_qualified_name (tree scope, tree name, bool is_type_p, int flags)
+lookup_qualified_name (tree scope, tree name, bool is_type_p, bool complain)
 {
+  int flags = 0;
+
   if (TREE_CODE (scope) == NAMESPACE_DECL)
     {
       cxx_binding binding;
@@ -5746,12 +5780,19 @@ lookup_qualified_name (tree scope, tree name, bool is_type_p, int flags)
       flags |= LOOKUP_COMPLAIN;
       if (is_type_p)
        flags |= LOOKUP_PREFER_TYPES;
-      if (!qualified_lookup_using_namespace (name, scope, &binding, flags))
-       return NULL_TREE;
-      return select_decl (&binding, flags);
+      if (qualified_lookup_using_namespace (name, scope, &binding, 
+                                           flags))
+       return select_decl (&binding, flags);
     }
-  else
-    return lookup_member (scope, name, 0, is_type_p);
+  else if (is_aggr_type (scope, complain))
+    {
+      tree t;
+      t = lookup_member (scope, name, 0, is_type_p);
+      if (t)
+       return t;
+    }
+
+  return error_mark_node;
 }
 
 /* Check to see whether or not DECL is a variable that would have been
@@ -6001,9 +6042,9 @@ lookup_type_current_level (tree name)
 
 \f
 /* Push the declarations of builtin types into the namespace.
-   RID_INDEX is the index of the builtin type
-   in the array RID_POINTERS.  NAME is the name used when looking
-   up the builtin type.  TYPE is the _TYPE node for the builtin type.  */
+   RID_INDEX is the index of the builtin type in the array
+   RID_POINTERS.  NAME is the name used when looking up the builtin
+   type.  TYPE is the _TYPE node for the builtin type.  */
 
 void
 record_builtin_type (enum rid rid_index, 
@@ -6018,27 +6059,30 @@ record_builtin_type (enum rid rid_index,
   if (name)
     tname = get_identifier (name);
 
+  /* The calls to SET_IDENTIFIER_GLOBAL_VALUE below should be
+     eliminated.  Built-in types should not be looked up name; their
+     names are keywords that the parser can recognize.  However, there
+     is code in c-common.c that uses identifier_global_value to look
+     up built-in types by name.  */
   if (tname)
     {
-      tdecl = pushdecl (build_decl (TYPE_DECL, tname, type));
-      set_identifier_type_value (tname, NULL_TREE);
-      if ((int) rid_index < (int) RID_MAX)
-       /* Built-in types live in the global namespace.  */
+      tdecl = build_decl (TYPE_DECL, tname, type);
+      DECL_ARTIFICIAL (tdecl) = 1;
+      if (tname)
        SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl);
     }
-  if (rname != NULL_TREE)
+  if (rname)
     {
-      if (tname != NULL_TREE)
+      if (!tdecl)
        {
-         set_identifier_type_value (rname, NULL_TREE);
-         SET_IDENTIFIER_GLOBAL_VALUE (rname, tdecl);
-       }
-      else
-       {
-         tdecl = pushdecl (build_decl (TYPE_DECL, rname, type));
-         set_identifier_type_value (rname, NULL_TREE);
+         tdecl = build_decl (TYPE_DECL, rname, type);
+         DECL_ARTIFICIAL (tdecl) = 1;
        }
+      SET_IDENTIFIER_GLOBAL_VALUE (rname, tdecl);
     }
+
+  if (!TYPE_NAME (type))
+    TYPE_NAME (type) = tdecl;
 }
 
 /* Record one of the standard Java types.
@@ -6174,7 +6218,7 @@ cxx_init_decl_processing (void)
   current_lang_name = NULL_TREE;
 
   /* Adjust various flags based on command-line settings.  */
-  if (! flag_permissive && ! pedantic)
+  if (!flag_permissive)
     flag_pedantic_errors = 1;
   if (!flag_no_inline)
     {
@@ -6222,16 +6266,10 @@ cxx_init_decl_processing (void)
   integer_three_node = build_int_2 (3, 0);
   TREE_TYPE (integer_three_node) = integer_type_node;
 
-  boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
-  TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
-  TYPE_MAX_VALUE (boolean_type_node) = build_int_2 (1, 0);
-  TREE_TYPE (TYPE_MAX_VALUE (boolean_type_node)) = boolean_type_node;
-  TYPE_PRECISION (boolean_type_node) = 1;
   record_builtin_type (RID_BOOL, "bool", boolean_type_node);
-  boolean_false_node = build_int_2 (0, 0);
-  TREE_TYPE (boolean_false_node) = boolean_type_node;
-  boolean_true_node = build_int_2 (1, 0);
-  TREE_TYPE (boolean_true_node) = boolean_type_node;
+  truthvalue_type_node = boolean_type_node;
+  truthvalue_false_node = boolean_false_node;
+  truthvalue_true_node = boolean_true_node;
 
   empty_except_spec = build_tree_list (NULL_TREE, NULL_TREE);
 
@@ -6296,14 +6334,22 @@ cxx_init_decl_processing (void)
   current_lang_name = lang_name_cplusplus;
 
   {
-    tree bad_alloc_type_node, newtype, deltype;
+    tree bad_alloc_id;
+    tree bad_alloc_type_node;
+    tree bad_alloc_decl;
+    tree newtype, deltype;
     tree ptr_ftype_sizetype;
 
     push_namespace (std_identifier);
-    bad_alloc_type_node 
-      = xref_tag (class_type, get_identifier ("bad_alloc"), 
-                 /*attributes=*/NULL_TREE, 1);
+    bad_alloc_id = get_identifier ("bad_alloc");
+    bad_alloc_type_node = make_aggr_type (RECORD_TYPE);
+    TYPE_CONTEXT (bad_alloc_type_node) = current_namespace;
+    bad_alloc_decl 
+      = create_implicit_typedef (bad_alloc_id, bad_alloc_type_node);
+    DECL_CONTEXT (bad_alloc_decl) = current_namespace;
+    TYPE_STUB_DECL (bad_alloc_type_node) = bad_alloc_decl;
     pop_namespace ();
     ptr_ftype_sizetype 
       = build_function_type (ptr_type_node,
                             tree_cons (NULL_TREE,
@@ -6466,7 +6512,7 @@ builtin_function_1 (const char* name,
 
 /* Entry point for the benefit of c_common_nodes_and_builtins.
 
-   Make a defintion for a builtin function named NAME and whose data type
+   Make a definition for a builtin function named NAME and whose data type
    is TYPE.  TYPE should be a function type with argument types.  This
    function places the anticipated declaration in the global namespace
    and additionally in the std namespace if appropriate.
@@ -6603,19 +6649,6 @@ push_throw_library_fn (tree name, tree type)
   TREE_NOTHROW (fn) = 0;
   return fn;
 }
-
-/* Apply default attributes to a function, if a system function with default
-   attributes.  */
-
-void
-cxx_insert_default_attributes (tree decl)
-{
-  if (!DECL_EXTERN_C_FUNCTION_P (decl))
-    return;
-  if (!TREE_PUBLIC (decl))
-    return;
-  c_common_insert_default_attributes (decl);
-}
 \f
 /* When we call finish_struct for an anonymous union, we create
    default copy constructors and such.  But, an anonymous union
@@ -6653,7 +6686,8 @@ fixup_anonymous_aggr (tree t)
 
   /* ISO C++ 9.5.3.  Anonymous unions may not have function members.  */
   if (TYPE_METHODS (t))
-    cp_error_at ("an anonymous union cannot have function members", t);
+    error ("%Han anonymous union cannot have function members",
+          &DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (t)));
 
   /* Anonymous aggregates cannot have fields with ctors, dtors or complex
      assignment operators (because they cannot have these methods themselves).
@@ -7165,17 +7199,15 @@ grok_reference_init (tree decl, tree type, tree init)
     }
 
   if (TREE_CODE (init) == TREE_LIST)
-    init = build_compound_expr (init);
+    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.  */
-      init = default_conversion (init);
-    }
+    /* Note: default conversion is only called in very special cases.  */
+    init = decay_conversion (init);
 
   /* Convert INIT to the reference type TYPE.  This may involve the
      creation of a temporary, whose lifetime must be the same as that
@@ -7259,7 +7291,7 @@ layout_var_decl (tree decl)
   /* If we haven't already layed out this declaration, do so now.
      Note that we must not call complete type for an external object
      because it's type might involve templates that we are not
-     supposed to isntantiate yet.  (And it's perfectly valid to say
+     supposed to instantiate yet.  (And it's perfectly valid to say
      `extern X x' for some incomplete type `X'.)  */
   if (!DECL_EXTERNAL (decl))
     complete_type (type);
@@ -7354,7 +7386,8 @@ maybe_commonize_var (tree decl)
              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);
-             cp_warning_at ("  you can work around this by removing the initializer", decl);
+             warning ("%H  you can work around this by removing the initializer",
+                      &DECL_SOURCE_LOCATION (decl));
            }
        }
     }
@@ -7427,13 +7460,7 @@ reshape_init (tree type, tree *initp)
   old_init_value = (TREE_CODE (*initp) == TREE_LIST
                    ? TREE_VALUE (*initp) : old_init);
 
-  /* For some parse errors, OLD_INIT_VALUE may be NULL.  */
-  if (!old_init_value)
-    {
-      my_friendly_assert (TREE_CODE (old_init) == TREE_LIST, 20021202);
-      TREE_VALUE (old_init) = error_mark_node;
-      return old_init;
-    }
+  my_friendly_assert (old_init_value, 20030723);
 
   /* If the initializer is brace-enclosed, pull initializers from the
      enclosed elements.  Advance past the brace-enclosed initializer
@@ -7903,6 +7930,7 @@ static void
 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, 
@@ -7952,17 +7980,9 @@ initialize_local_var (tree decl, tree init)
     }
 
   /* Generate a cleanup, if necessary.  */
-  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
-    {
-      tree cleanup;
-
-      /* Compute the cleanup.  */
-      cleanup = cxx_maybe_build_cleanup (decl);
-      
-      /* Record the cleanup required for this declaration.  */
-      if (DECL_SIZE (decl) && cleanup)
-       finish_decl_cleanup (decl, cleanup);
-    }
+  cleanup = cxx_maybe_build_cleanup (decl);
+  if (DECL_SIZE (decl) && cleanup)
+    finish_decl_cleanup (decl, cleanup);
 }
 
 /* Finish processing of a declaration;
@@ -7991,6 +8011,8 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
       return;
     }
 
+  my_friendly_assert (TREE_CODE (decl) != RESULT_DECL, 20030619);
+
   /* If a name was specified, get the string.  */
   if (global_scope_p (current_binding_level))
     asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
@@ -8023,7 +8045,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
   type = TREE_TYPE (decl);
 
   if (type == error_mark_node)
-    return;
+    goto finish_end0;
 
   if (TYPE_HAS_MUTABLE_P (type))
     TREE_READONLY (decl) = 0;
@@ -8031,8 +8053,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
   if (processing_template_decl)
     {
       /* Add this declaration to the statement-tree.  */
-      if (at_function_scope_p ()
-         && TREE_CODE (decl) != RESULT_DECL)
+      if (at_function_scope_p ())
        add_decl_stmt (decl);
 
       if (init && DECL_INITIAL (decl))
@@ -8051,8 +8072,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
        {
          if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
            warning ("shadowing previous type declaration of `%#D'", decl);
-         set_identifier_type_value (DECL_NAME (decl), type);
-         CLASSTYPE_GOT_SEMICOLON (type) = 1;
+         set_identifier_type_value (DECL_NAME (decl), decl);
        }
 
       /* If we have installed this as the canonical typedef for this
@@ -8071,7 +8091,8 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
     ttype = target_type (type);
 
   if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl)
-      && TYPE_NEEDS_CONSTRUCTING (type))
+      && (TYPE_NEEDS_CONSTRUCTING (type) 
+         || TREE_CODE (type) == REFERENCE_TYPE))
     {
       /* Currently, GNU C++ puts constants in text space, making them
         impossible to initialize.  In the future, one would hope for
@@ -8089,8 +8110,6 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
       SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
       make_decl_rtl (decl, asmspec);
     }
-  else if (TREE_CODE (decl) == RESULT_DECL)
-    init = check_initializer (decl, init, flags);
   else if (TREE_CODE (decl) == VAR_DECL)
     {
       /* Only PODs can have thread-local storage.  Other types may require
@@ -8146,9 +8165,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
   /* Add this declaration to the statement-tree.  This needs to happen
      after the call to check_initializer so that the DECL_STMT for a
      reference temp is added before the DECL_STMT for the reference itself.  */
-  if (building_stmt_tree ()
-      && at_function_scope_p ()
-      && TREE_CODE (decl) != RESULT_DECL)
+  if (at_function_scope_p ())
     add_decl_stmt (decl);
 
   if (TREE_CODE (decl) == VAR_DECL)
@@ -8157,8 +8174,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
   /* Output the assembler code and/or RTL code for variables and functions,
      unless the type is an undefined structure or union.
      If not, it will get done when the type is completed.  */
-  if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL
-      || TREE_CODE (decl) == RESULT_DECL)
+  if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
     {
       if (TREE_CODE (decl) == VAR_DECL)
        maybe_commonize_var (decl);
@@ -8230,6 +8246,10 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
 
   if (was_readonly)
     TREE_READONLY (decl) = 1;
+
+  /* If this was marked 'used', be sure it will be output.  */
+  if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
+    mark_referenced (DECL_ASSEMBLER_NAME (decl));
 }
 
 /* This is here for a midend callback from c-common.c */
@@ -8324,7 +8344,7 @@ get_atexit_node (void)
   atexit_fndecl = build_library_fn_ptr (name, fn_type);
   mark_used (atexit_fndecl);
   pop_lang_context ();
-  atexit_node = default_conversion (atexit_fndecl);
+  atexit_node = decay_conversion (atexit_fndecl);
 
   return atexit_node;
 }
@@ -8347,10 +8367,11 @@ get_dso_handle_node (void)
 /* Begin a new function with internal linkage whose job will be simply
    to destroy some particular variable.  */
 
+static GTY(()) int start_cleanup_cnt;
+
 static tree
 start_cleanup_fn (void)
 {
-  static int counter = 0;
   int old_interface_only = interface_only;
   int old_interface_unknown = interface_unknown;
   char name[32];
@@ -8377,7 +8398,7 @@ start_cleanup_fn (void)
   /* Build the function type itself.  */
   fntype = build_function_type (void_type_node, parmtypes);
   /* Build the name of the function.  */
-  sprintf (name, "__tcf_%d", counter++);
+  sprintf (name, "__tcf_%d", start_cleanup_cnt++);
   /* Build the function declaration.  */
   fndecl = build_lang_decl (FUNCTION_DECL, get_identifier (name), fntype);
   /* It's a function with internal linkage, generated by the
@@ -8416,7 +8437,7 @@ start_cleanup_fn (void)
 static void
 end_cleanup_fn (void)
 {
-  expand_body (finish_function (0));
+  expand_or_defer_fn (finish_function (0));
 
   pop_from_top_level ();
 }
@@ -8453,13 +8474,14 @@ register_dtor_fn (tree decl)
   pop_deferring_access_checks ();
 
   /* Create the body of the anonymous function.  */
-  compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
+  compound_stmt = begin_compound_stmt (/*has_no_scope=*/false);
   finish_expr_stmt (fcall);
-  finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
+  finish_compound_stmt (compound_stmt);
   end_cleanup_fn ();
 
   /* Call atexit with the cleanup function.  */
   cxx_mark_addressable (cleanup);
+  mark_used (cleanup);
   cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
   if (flag_use_cxa_atexit)
     {
@@ -8481,8 +8503,6 @@ register_dtor_fn (tree decl)
 static void
 expand_static_init (tree decl, tree init)
 {
-  tree oldstatic;
-
   my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20021010);
   my_friendly_assert (TREE_STATIC (decl), 20021010);
 
@@ -8492,14 +8512,7 @@ expand_static_init (tree decl, tree init)
       && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
     return;
 
-  oldstatic = value_member (decl, static_aggregates);
-
-  if (oldstatic)
-    {
-      if (TREE_PURPOSE (oldstatic) && init != NULL_TREE)
-       error ("multiple initializations given for `%D'", decl);
-    }
-  else if (! toplevel_bindings_p ())
+  if (! toplevel_bindings_p ())
     {
       /* Emit code to perform this initialization but once.  */
       tree if_stmt;
@@ -8539,7 +8552,7 @@ expand_static_init (tree decl, tree init)
       /* Begin the conditional initialization.  */
       if_stmt = begin_if_stmt ();
       finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
-      then_clause = begin_compound_stmt (/*has_no_scope=*/0);
+      then_clause = begin_compound_stmt (/*has_no_scope=*/false);
 
       /* Do the initialization itself.  */
       assignment = init ? init : NULL_TREE;
@@ -8554,12 +8567,7 @@ expand_static_init (tree decl, tree init)
         run until after TEMP is set to 1.  */
       guard_init = set_guard (guard);
       if (assignment)
-       {
-         assignment = tree_cons (NULL_TREE, assignment,
-                                 build_tree_list (NULL_TREE,
-                                                  guard_init));
-         assignment = build_compound_expr (assignment);
-       }
+       assignment = build_compound_expr (assignment, guard_init);
       else
        assignment = guard_init;
       finish_expr_stmt (assignment);
@@ -8568,7 +8576,7 @@ expand_static_init (tree decl, tree init)
         variable.  */
       register_dtor_fn (decl);
 
-      finish_compound_stmt (/*has_no_scope=*/0, then_clause);
+      finish_compound_stmt (then_clause);
       finish_then_clause (if_stmt);
       finish_if_stmt ();
     }
@@ -8874,19 +8882,14 @@ grokfndecl (tree ctype,
       DECL_NOT_REALLY_EXTERN (decl) = 1;
     }
 
-  DID_INLINE_FUNC (decl) = 0;
   /* If the declaration was declared inline, mark it as such.  */
   if (inlinep)
     DECL_DECLARED_INLINE_P (decl) = 1;
   /* We inline functions that are explicitly declared inline, or, when
      the user explicitly asks us to, all functions.  */
-  if (DECL_DECLARED_INLINE_P (decl))
+  if (DECL_DECLARED_INLINE_P (decl)
+      || (flag_inline_trees == 2 && !DECL_INLINE (decl) && funcdef_flag))
     DECL_INLINE (decl) = 1;
-  if (flag_inline_trees == 2 && !DECL_INLINE (decl))
-    {
-      DID_INLINE_FUNC (decl) = 1;
-      DECL_INLINE (decl) = 1;
-    }
 
   DECL_EXTERNAL (decl) = 1;
   if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
@@ -8897,7 +8900,7 @@ grokfndecl (tree ctype,
     }
 
   if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
-    grok_op_properties (decl, friendp);
+    grok_op_properties (decl, friendp, /*complain=*/true);
 
   if (ctype && decl_function_context (decl))
     DECL_NO_STATIC_CHAIN (decl) = 1;
@@ -8947,7 +8950,6 @@ grokfndecl (tree ctype,
               fns = TREE_OPERAND (fns, 1);
             }
          my_friendly_assert (TREE_CODE (fns) == IDENTIFIER_NODE
-                             || TREE_CODE (fns) == LOOKUP_EXPR
                              || TREE_CODE (fns) == OVERLOAD, 20001120);
          DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
 
@@ -9240,9 +9242,6 @@ build_ptrmemfunc_type (tree type)
      later.  */
   TYPE_SET_PTRMEMFUNC_TYPE (type, t);
 
-  /* Seems to be wanted.  */
-  CLASSTYPE_GOT_SEMICOLON (t) = 1;
-
   return t;
 }
 
@@ -9251,7 +9250,26 @@ build_ptrmemfunc_type (tree type)
 tree
 build_ptrmem_type (tree class_type, tree member_type)
 {
-  return build_pointer_type (build_offset_type (class_type, member_type));
+  if (TREE_CODE (member_type) == METHOD_TYPE)
+    {
+      tree arg_types;
+
+      arg_types = TYPE_ARG_TYPES (member_type);
+      class_type = (cp_build_qualified_type 
+                   (class_type,
+                    cp_type_quals (TREE_TYPE (TREE_VALUE (arg_types)))));
+      member_type 
+       = build_method_type_directly (class_type, 
+                                     TREE_TYPE (member_type),
+                                     TREE_CHAIN (arg_types));
+      return build_ptrmemfunc_type (build_pointer_type (member_type));
+    }
+  else
+    {
+      my_friendly_assert (TREE_CODE (member_type) != FUNCTION_TYPE,
+                         20030716);
+      return build_offset_type (class_type, member_type);
+    }
 }
 
 /* DECL is a VAR_DECL defined in-class, whose TYPE is also given.
@@ -9488,10 +9506,6 @@ create_array_type_for_decl (tree name, tree type, tree size)
       error_msg = "array of references";
       break;
 
-    case OFFSET_TYPE:
-      error_msg = "array of data members";
-      break;
-
     case METHOD_TYPE:
       error_msg = "array of function members";
       break;
@@ -9769,9 +9783,6 @@ grokdeclarator (tree declarator,
              {
                tree fns = TREE_OPERAND (decl, 0);
 
-               if (TREE_CODE (fns) == LOOKUP_EXPR)
-                 fns = TREE_OPERAND (fns, 0);
-
                dname = fns;
                if (TREE_CODE (dname) == COMPONENT_REF)
                  dname = TREE_OPERAND (dname, 1);
@@ -9880,16 +9891,19 @@ grokdeclarator (tree declarator,
              decl = *next;
              if (ctype)
                {
-                 if (TREE_CODE (decl) == IDENTIFIER_NODE
-                     && constructor_name_p (decl, ctype))
+                 tree name = decl;
+
+                 if (TREE_CODE (name) == BIT_NOT_EXPR)
+                   name = TREE_OPERAND (name, 0);
+
+                 if (!constructor_name_p (decl, ctype))
+                   ;
+                 else if (decl == name)
                    {
                      sfk = sfk_constructor;
                      ctor_return_type = ctype;
                    }
-                 else if (TREE_CODE (decl) == BIT_NOT_EXPR
-                          && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE
-                          && constructor_name_p (TREE_OPERAND (decl, 0),
-                                                 ctype))
+                 else
                    {
                      sfk = sfk_destructor;
                      ctor_return_type = ctype;
@@ -10579,15 +10593,7 @@ grokdeclarator (tree declarator,
 
        case ARRAY_REF:
          {
-           register tree size;
-
-           size = TREE_OPERAND (declarator, 1);
-
-           /* VC++ spells a zero-sized array with [].  */
-           if (size == NULL_TREE && decl_context == FIELD && ! staticp
-               && ! RIDBIT_SETP (RID_TYPEDEF, specbits))
-             size = integer_zero_node;
-
+           tree size = TREE_OPERAND (declarator, 1);
            declarator = TREE_OPERAND (declarator, 0);
 
            type = create_array_type_for_decl (dname, type, size);
@@ -10745,9 +10751,6 @@ grokdeclarator (tree declarator,
 
            declarator = TREE_OPERAND (declarator, 0);
 
-           /* FIXME: This is where default args should be fully
-              processed.  */
-
            arg_types = grokparms (inner_parms);
 
            if (declarator && flags == DTOR_FLAG)
@@ -10930,7 +10933,9 @@ grokdeclarator (tree declarator,
                else if (TREE_CODE (type) == FUNCTION_TYPE)
                  {
                    if (current_class_type == NULL_TREE || friendp)
-                     type = build_cplus_method_type (ctype, TREE_TYPE (type),
+                     type 
+                       = build_method_type_directly (ctype, 
+                                                     TREE_TYPE (type),
                                                      TYPE_ARG_TYPES (type));
                    else
                      {
@@ -10972,8 +10977,9 @@ grokdeclarator (tree declarator,
                  /* In this case, we will deal with it later.  */
                  ;
                else if (TREE_CODE (type) == FUNCTION_TYPE)
-                 type = build_cplus_method_type (ctype, TREE_TYPE (type),
-                                                 TYPE_ARG_TYPES (type));
+                 type = build_method_type_directly (ctype, 
+                                                    TREE_TYPE (type),
+                                                    TYPE_ARG_TYPES (type));
              }
          }
          break;
@@ -11109,8 +11115,8 @@ grokdeclarator (tree declarator,
        {
          decl = build_decl (TYPE_DECL, declarator, type);
          if (in_namespace || ctype)
-           cp_error_at ("typedef name may not be a nested-name-specifier",
-                        decl);
+           error ("%Htypedef name may not be a nested-name-specifier",
+                  &DECL_SOURCE_LOCATION (decl));
          if (!current_function_decl)
            DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
        }
@@ -11156,7 +11162,8 @@ grokdeclarator (tree declarator,
          if (ctype == NULL_TREE)
            {
              if (TREE_CODE (type) != METHOD_TYPE)
-               cp_error_at ("invalid type qualifier for non-member function type", decl);
+               error ("%Hinvalid type qualifier for non-member function type",
+                      &DECL_SOURCE_LOCATION (decl));
              else
                ctype = TYPE_METHOD_BASETYPE (type);
            }
@@ -11248,7 +11255,8 @@ grokdeclarator (tree declarator,
            {
              /* A friendly class?  */
              if (current_class_type)
-               make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type));
+               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);
@@ -11325,8 +11333,6 @@ grokdeclarator (tree declarator,
        }
       else if (TREE_CODE (type) == FUNCTION_TYPE)
        type = build_pointer_type (type);
-      else if (TREE_CODE (type) == OFFSET_TYPE)
-       type = build_pointer_type (type);
     }
 
   {
@@ -11341,6 +11347,14 @@ grokdeclarator (tree declarator,
       }
     else if (decl_context == FIELD)
       {
+       /* The C99 flexible array extension.  */
+       if (!staticp && TREE_CODE (type) == ARRAY_TYPE
+           && TYPE_DOMAIN (type) == NULL_TREE)
+         {
+           tree itype = compute_array_index_type (dname, integer_zero_node);
+           type = build_cplus_array_type (TREE_TYPE (type), itype);
+         }
+
        if (type == error_mark_node)
          {
            /* Happens when declaring arrays of sizes which
@@ -11401,8 +11415,9 @@ grokdeclarator (tree declarator,
                      }
                  }
                else if (staticp < 2)
-                 type = build_cplus_method_type (ctype, TREE_TYPE (type),
-                                                 TYPE_ARG_TYPES (type));
+                 type = build_method_type_directly (ctype, 
+                                                    TREE_TYPE (type),
+                                                    TYPE_ARG_TYPES (type));
              }
 
            /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node.  */
@@ -11456,7 +11471,10 @@ grokdeclarator (tree declarator,
               members of other classes.  */
            /* All method decls are public, so tell grokfndecl to set
               TREE_PUBLIC, also.  */
-           decl = grokfndecl (ctype, type, declarator, declarator,
+           decl = grokfndecl (ctype, type,
+                              TREE_CODE (declarator) != TEMPLATE_ID_EXPR
+                              ? declarator : dname,
+                              declarator,
                               virtualp, flags, quals, raises,
                               friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
                               template_count, in_namespace);
@@ -11501,30 +11519,24 @@ grokdeclarator (tree declarator,
            /* Friends are treated specially.  */
            if (ctype == current_class_type)
              warning ("member functions are implicitly friends of their class");
-           else
-             {
-               tree t = NULL_TREE;
-               if (decl && DECL_NAME (decl))
-                 {
-                   if (template_class_depth (current_class_type) == 0)
-                     {
-                       decl
-                         = check_explicit_specialization
-                         (declarator, decl,
-                          template_count, 2 * (funcdef_flag != 0) + 4);
-                       if (decl == error_mark_node)
-                         return error_mark_node;
-                     }
-                   
-                   t = do_friend (ctype, declarator, decl,
-                                  last_function_parms, *attrlist,
-                                  flags, quals, funcdef_flag);
-                 }
-               if (t && funcdef_flag)
-                 return t;
-  
-               return void_type_node;
-             }
+           else if (decl && DECL_NAME (decl))
+             {
+               if (template_class_depth (current_class_type) == 0)
+                 {
+                   decl = check_explicit_specialization
+                     (declarator, decl, template_count,
+                      2 * (funcdef_flag != 0) + 4);
+                   if (decl == error_mark_node)
+                     return error_mark_node;
+                 }
+               
+               decl = do_friend (ctype, declarator, decl,
+                                 last_function_parms, *attrlist,
+                                 flags, quals, funcdef_flag);
+               return decl;
+             }
+           else
+             return void_type_node;
          }
 
        /* Structure field.  It may not be a function, except for C++ */
@@ -11597,7 +11609,8 @@ grokdeclarator (tree declarator,
                            inlinep, friendp, raises != NULL_TREE);
          }
       }
-    else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
+    else if (TREE_CODE (type) == FUNCTION_TYPE
+            || TREE_CODE (type) == METHOD_TYPE)
       {
        tree original_name;
        int publicp = 0;
@@ -11640,8 +11653,9 @@ grokdeclarator (tree declarator,
              }
          }
        else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2)
-         type = build_cplus_method_type (ctype, TREE_TYPE (type),
-                                         TYPE_ARG_TYPES (type));
+         type = build_method_type_directly (ctype, 
+                                            TREE_TYPE (type),
+                                            TYPE_ARG_TYPES (type));
 
        /* Record presence of `static'.  */
        publicp = (ctype != NULL_TREE
@@ -11952,19 +11966,13 @@ grokparms (tree first_parm)
        {
          /* Top-level qualifiers on the parameters are
             ignored for function types.  */
-         type = TYPE_MAIN_VARIANT (type);
+         type = cp_build_qualified_type (type, 0);
          if (TREE_CODE (type) == METHOD_TYPE)
            {
              error ("parameter `%D' invalidly declared method type", decl);
              type = build_pointer_type (type);
              TREE_TYPE (decl) = type;
            }
-         else if (TREE_CODE (type) == OFFSET_TYPE)
-           {
-             error ("parameter `%D' invalidly declared offset type", decl);
-             type = build_pointer_type (type);
-             TREE_TYPE (decl) = type;
-           }
          else if (abstract_virtuals_error (decl, type))
            any_error = 1;  /* Seems like a good idea.  */
          else if (POINTER_TYPE_P (type))
@@ -12177,10 +12185,12 @@ unary_op_p (enum tree_code code)
          || code == TYPE_EXPR);
 }
 
-/* Do a little sanity-checking on how they declared their operator.  */
+/* DECL is a declaration for an overloaded operator.  Returns true if
+   the declaration is valid; false otherwise.  If COMPLAIN is true,
+   errors are issued for invalid declarations.  */
 
-void
-grok_op_properties (tree decl, int friendp)
+bool
+grok_op_properties (tree decl, int friendp, bool complain)
 {
   tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
   tree argtype;
@@ -12188,6 +12198,10 @@ grok_op_properties (tree decl, int friendp)
   tree name = DECL_NAME (decl);
   enum tree_code operator_code;
   int arity;
+  bool ok;
+
+  /* Assume that the declaration is valid.  */
+  ok = true;
 
   /* Count the number of arguments.  */
   for (argtype = argtypes, arity = 0;
@@ -12229,19 +12243,6 @@ grok_op_properties (tree decl, int friendp)
     {
       switch (operator_code)
        {
-       case CALL_EXPR:
-         TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
-         break;
-
-       case ARRAY_REF:
-         TYPE_OVERLOADS_ARRAY_REF (current_class_type) = 1;
-         break;
-
-       case COMPONENT_REF:
-       case MEMBER_REF:
-         TYPE_OVERLOADS_ARROW (current_class_type) = 1;
-         break;
-
        case NEW_EXPR:
          TYPE_HAS_NEW_OPERATOR (current_class_type) = 1;
          break;
@@ -12294,35 +12295,38 @@ grok_op_properties (tree decl, int friendp)
            error ("`%D' must be a nonstatic member function", decl);
          else
            {
-             tree p = argtypes;
+             tree p;
 
              if (DECL_STATIC_FUNCTION_P (decl))
                error ("`%D' must be either a non-static member function or a non-member function", decl);
 
-             if (p)
-               for (; TREE_CODE (TREE_VALUE (p)) != VOID_TYPE ; p = TREE_CHAIN (p))
-                 {
-                   tree arg = TREE_VALUE (p);
-                   if (TREE_CODE (arg) == REFERENCE_TYPE)
-                     arg = TREE_TYPE (arg);
-
-                   /* This lets bad template code slip through.  */
-                   if (IS_AGGR_TYPE (arg)
-                       || TREE_CODE (arg) == ENUMERAL_TYPE
-                       || TREE_CODE (arg) == TEMPLATE_TYPE_PARM
-                       || TREE_CODE (arg) == BOUND_TEMPLATE_TEMPLATE_PARM)
-                     goto foundaggr;
-                 }
-             error
-               ("`%D' must have an argument of class or enumerated type",
-                decl);
-           foundaggr:
-             ;
+             for (p = argtypes; p && p != void_list_node; p = TREE_CHAIN (p))
+               {
+                 tree arg = non_reference (TREE_VALUE (p));
+                 /* IS_AGGR_TYPE, rather than CLASS_TYPE_P, is used
+                    because these checks are performed even on
+                    template functions.  */
+                 if (IS_AGGR_TYPE (arg) || TREE_CODE (arg) == ENUMERAL_TYPE)
+                   break;
+               }
+
+             if (!p || p == void_list_node)
+               {
+                 if (!complain)
+                   return false;
+
+                 error ("`%D' must have an argument of class or "
+                        "enumerated type",
+                        decl);
+                 ok = false;
+               }
            }
        }
 
+      /* There are no restrictions on the arguments to an overloaded
+        "operator ()".  */
       if (operator_code == CALL_EXPR)
-       return;                 /* No restrictions on args.  */
+       return ok;
 
       if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
        {
@@ -12345,7 +12349,7 @@ grok_op_properties (tree decl, int friendp)
                       && DERIVED_FROM_P (t, current_class_type))
                what = "a base class";
 
-             if (what)
+             if (what && warn_conversion)
                warning ("conversion to %s%s will never use a type conversion operator",
                         ref ? "a reference to " : "", what);
            }
@@ -12505,6 +12509,8 @@ grok_op_properties (tree decl, int friendp)
           }
 
     }
+
+  return ok;
 }
 \f
 static const char *
@@ -12526,57 +12532,110 @@ tag_name (enum tag_types code)
 }
 
 /* Name lookup in an elaborated-type-specifier (after the keyword
-   indicated by TAG_CODE) has found TYPE.  If the
+   indicated by TAG_CODE) has found the TYPE_DECL DECL.  If the
    elaborated-type-specifier is invalid, issue a diagnostic and return
-   error_mark_node; otherwise, return TYPE itself.  */
+   error_mark_node; otherwise, return the *_TYPE to which it referred.
+   If ALLOW_TEMPLATE_P is true, TYPE may be a class template.  */
 
-static tree
+tree
 check_elaborated_type_specifier (enum tag_types tag_code,
-                                tree type)
+                                tree decl,
+                                bool allow_template_p)
 {
-  tree t;
+  tree type;
 
-  t = follow_tag_typedef (type);
+  /* In the case of:
 
-  /* [dcl.type.elab] If the identifier resolves to a typedef-name or a
-     template type-parameter, the elaborated-type-specifier is
-     ill-formed.  */
-  if (!t)
+       struct S { struct S *p; };
+
+     name lookup will find the TYPE_DECL for the implicit "S::S"
+     typedef.  Adjust for that here.  */
+  if (DECL_SELF_REFERENCE_P (decl))
+    decl = TYPE_NAME (TREE_TYPE (decl));
+
+  type = TREE_TYPE (decl);
+
+  /*   [dcl.type.elab] 
+
+       If the identifier resolves to a typedef-name or a template
+       type-parameter, the elaborated-type-specifier is ill-formed.
+
+     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'",
-            TYPE_NAME (type), tag_name (tag_code));
-      t = error_mark_node;
+      error ("using typedef-name `%D' after `%s'", decl, tag_name (tag_code));
+      return IS_AGGR_TYPE (type) ? type : error_mark_node;
     }
-  else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+    
+  if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
     {
       error ("using template type parameter `%T' after `%s'",
             type, tag_name (tag_code));
-      t = error_mark_node;
+      return error_mark_node;
     }
+  else if (TREE_CODE (type) != RECORD_TYPE
+          && TREE_CODE (type) != UNION_TYPE
+          && tag_code != enum_type)
+    {
+      error ("`%T' referred to as `%s'", type, tag_name (tag_code));
+      return error_mark_node;
+    }
+  else if (TREE_CODE (type) != ENUMERAL_TYPE
+          && tag_code == enum_type)
+    {
+      error ("`%T' referred to as enum", type);
+      return error_mark_node;
+    }
+  else if (!allow_template_p
+          && TREE_CODE (type) == RECORD_TYPE
+          && CLASSTYPE_IS_TEMPLATE (type))
+    {
+      /* If a class template appears as elaborated type specifier
+        without a template header such as:
 
-  return t;
+          template <class T> class C {};
+          void f(class C);             // No template header here
+
+        then the required template argument is missing.  */
+
+      error ("template argument required for `%s %T'",
+            tag_name (tag_code),
+            DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)));
+      return error_mark_node;
+    }
+
+  return type;
 }
 
-/* Get the struct, enum or union (CODE says which) with tag NAME.
+/* 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.
 
-   C++: If a class derivation is given, process it here, and report
-   an error if multiple derivation declarations are not identical.
+   If a declaration is given, process it here, and report an error if
+   multiple declarations are not identical.  ATTRIBUTE is the attribute
+   appeared in this declaration.
 
-   If this is a definition, come in through xref_tag and only look in
+   GLOBALIZE is false when this is also a definition.  Only look in
    the current frame for the name (since C++ allows new names in any
-   scope.)  */
+   scope.)
+
+   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, tree attributes, 
-         bool globalize)
+         bool globalize, bool template_header_p)
 {
   enum tree_code code;
-  register tree ref, t;
+  register 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);
+
   switch (tag_code)
     {
     case record_type:
@@ -12593,93 +12652,50 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
       abort ();
     }
 
-  /* If a cross reference is requested, look up the type
-     already defined for this tag and return it.  */
-  if (TYPE_P (name))
-    {
-      t = name;
-      name = TYPE_IDENTIFIER (t);
-    }
-  else
-    t = IDENTIFIER_TYPE_VALUE (name);
-
-  /* Warn about 'friend struct Inherited;' doing the wrong thing.  */
-  if (t && globalize && TREE_CODE (t) == TYPENAME_TYPE)
-    {
-      static int explained;
-      tree shadowed;
-
-      warning ("`%s %T' declares a new type at namespace scope",
-                 tag_name (tag_code), name);
-      if (!explained++)
-       warning ("  names from dependent base classes are not visible to unqualified name lookup - to refer to the inherited type, say `%s %T::%T'",
-                   tag_name (tag_code),
-                   constructor_name (current_class_type),
-                   TYPE_IDENTIFIER (t));
-
-      /* We need to remove the class scope binding for the
-         TYPENAME_TYPE as otherwise poplevel_class gets confused.  */
-      for (shadowed = b->class_shadowed;
-          shadowed;
-          shadowed = TREE_CHAIN (shadowed))
-       if (TREE_TYPE (shadowed) == TYPE_NAME (t))
-         {
-           TREE_PURPOSE (shadowed) = NULL_TREE;
-           break;
-         }
-    }
-
-  if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM
-      && TREE_CODE (t) != BOUND_TEMPLATE_TEMPLATE_PARM)
-    t = NULL_TREE;
-
   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.  */
-      ref = lookup_tag (code, name, b, 1);
+      t = lookup_tag (code, name, b, 1);
     }
   else
     {
-      if (t)
-       {
-         ref = check_elaborated_type_specifier (tag_code, t);
-         if (ref == error_mark_node)
-           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
-       }
-      else
-       ref = lookup_tag (code, name, b, 0);
+      tree decl = lookup_name (name, 1);
 
-      if (! ref)
+      if (decl && DECL_CLASS_TEMPLATE_P (decl))
+       decl = DECL_TEMPLATE_RESULT (decl);
+
+      if (decl && TREE_CODE (decl) == TYPE_DECL)
        {
-         /* Try finding it as a type declaration.  If that wins,
-            use it.  */
-         ref = lookup_name (name, 1);
+         /* 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.
 
-         if (ref != NULL_TREE
-             && processing_template_decl
-             && DECL_CLASS_TEMPLATE_P (ref)
-             && template_class_depth (current_class_type) == 0)
-           /* Since GLOBALIZE is true, we're declaring a global
-              template, so we want this type.  */
-           ref = DECL_TEMPLATE_RESULT (ref);
+            For example:
 
-         if (ref && TREE_CODE (ref) == TYPE_DECL)
-           {
-             ref = check_elaborated_type_specifier (tag_code, 
-                                                    TREE_TYPE (ref));
-             if (ref == error_mark_node)
-               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
-             if (ref && TREE_CODE (ref) != code)
-               ref = NULL_TREE;
-           }
-         else
-           ref = NULL_TREE;
+              template <class T> class C {
+                class C *c1;           // DECL_SELF_REFERENCE_P is true
+                class D;
+              };
+              template <class U> class C; // template_header_p is true
+              template <class T> class C<T>::D {
+                class C *c2;           // DECL_SELF_REFERENCE_P is true
+              };  */
+
+         t = check_elaborated_type_specifier (tag_code,
+                                              decl,
+                                              template_header_p
+                                              | DECL_SELF_REFERENCE_P (decl));
+         if (t == error_mark_node)
+           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
        }
+      else
+       t = NULL_TREE;
 
-      if (ref && current_class_type
+      if (t && current_class_type
          && template_class_depth (current_class_type)
-         && PROCESSING_REAL_TEMPLATE_DECL_P ())
+         && template_header_p)
        {
          /* Since GLOBALIZE is nonzero, we are not looking at a
             definition of this tag.  Since, in addition, we are currently
@@ -12717,12 +12733,12 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
              accomplish this by making sure that the new type we
              create to represent this declaration has the right
              TYPE_CONTEXT.  */
-         context = TYPE_CONTEXT (ref);
-         ref = NULL_TREE;
+         context = TYPE_CONTEXT (t);
+         t = NULL_TREE;
        }
     }
 
-  if (! ref)
+  if (! t)
     {
       /* If no such tag is yet defined, create a forward-reference node
         and record it as the "definition".
@@ -12732,49 +12748,41 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
        {
          error ("use of enum `%#D' without previous declaration", name);
 
-         ref = make_node (ENUMERAL_TYPE);
+         t = make_node (ENUMERAL_TYPE);
 
          /* Give the type a default layout like unsigned int
             to avoid crashing if it does not get defined.  */
-         TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
-         TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
-         TYPE_USER_ALIGN (ref) = 0;
-         TREE_UNSIGNED (ref) = 1;
-         TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
-         TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
-         TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
+         TYPE_MODE (t) = TYPE_MODE (unsigned_type_node);
+         TYPE_ALIGN (t) = TYPE_ALIGN (unsigned_type_node);
+         TYPE_USER_ALIGN (t) = 0;
+         TREE_UNSIGNED (t) = 1;
+         TYPE_PRECISION (t) = TYPE_PRECISION (unsigned_type_node);
+         TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (unsigned_type_node);
+         TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (unsigned_type_node);
 
          /* Enable us to recognize when a type is created in class context.
             To do nested classes correctly, this should probably be cleared
             out when we leave this classes scope.  Currently this in only
             done in `start_enum'.  */
 
-         pushtag (name, ref, globalize);
+         pushtag (name, t, globalize);
        }
       else
        {
-         struct cp_binding_level *old_b = class_binding_level;
-
-         ref = make_aggr_type (code);
-         TYPE_CONTEXT (ref) = context;
-
-#ifdef NONNESTED_CLASSES
-         /* Class types don't nest the way enums do.  */
-         class_binding_level = (struct cp_binding_level *)0;
-#endif
-         pushtag (name, ref, globalize);
-         class_binding_level = old_b;
+         t = make_aggr_type (code);
+         TYPE_CONTEXT (t) = context;
+         pushtag (name, t, globalize);
        }
     }
   else
     {
-      if (!globalize && processing_template_decl && IS_AGGR_TYPE (ref))
-       redeclare_class_template (ref, current_template_parms);
+      if (!globalize && processing_template_decl && IS_AGGR_TYPE (t))
+       redeclare_class_template (t, current_template_parms);
     }
 
-  TYPE_ATTRIBUTES (ref) = attributes;
+  TYPE_ATTRIBUTES (t) = attributes;
 
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ref);
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
 }
 
 tree
@@ -12790,7 +12798,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, /*attributes=*/NULL_TREE, globalize);
+  return xref_tag (tag_kind, id, /*attributes=*/NULL_TREE, globalize, false);
 }
 
 /* REF is a type (named NAME), for which we have just seen some
@@ -12810,6 +12818,9 @@ xref_basetypes (tree ref, tree base_list)
   int i;
   enum tag_types tag_code;
 
+  if (ref == error_mark_node)
+    return;
+
   if (TREE_CODE (ref) == UNION_TYPE)
     {
       error ("derived union `%T' invalid", ref);
@@ -12988,7 +12999,8 @@ start_enum (tree name)
   if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
     {
       error ("multiple definition of `%#T'", enumtype);
-      cp_error_at ("previous definition here", enumtype);
+      error ("%Hprevious definition here",
+            &DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (enumtype)));
       /* Clear out TYPE_VALUES, and start again.  */
       TYPE_VALUES (enumtype) = NULL_TREE;
     }
@@ -13008,7 +13020,9 @@ start_enum (tree name)
 void
 finish_enum (tree enumtype)
 {
-  tree pair;
+  tree values;
+  tree decl;
+  tree value;
   tree minnode;
   tree maxnode;
   tree t;
@@ -13016,6 +13030,8 @@ finish_enum (tree enumtype)
   int lowprec;
   int highprec; 
   int precision;
+  integer_type_kind itk;
+  tree underlying_type = NULL_TREE;
 
   /* We built up the VALUES in reverse order.  */
   TYPE_VALUES (enumtype) = nreverse (TYPE_VALUES (enumtype));
@@ -13026,21 +13042,25 @@ finish_enum (tree enumtype)
      works.  */
   if (processing_template_decl)
     {
-      for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
-       TREE_TYPE (TREE_VALUE (pair)) = enumtype;
+      for (values = TYPE_VALUES (enumtype); 
+          values; 
+          values = TREE_CHAIN (values))
+       TREE_TYPE (TREE_VALUE (values)) = enumtype;
       if (at_function_scope_p ())
        add_stmt (build_min (TAG_DEFN, enumtype));
       return;
     }
 
+  /* Determine the minimum and maximum values of the enumerators.  */
   if (TYPE_VALUES (enumtype))
     {
       minnode = maxnode = NULL_TREE;
 
-      for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
+      for (values = TYPE_VALUES (enumtype); 
+          values; 
+          values = TREE_CHAIN (values))
        {
-         tree decl = TREE_VALUE (pair);
-         tree value = DECL_INITIAL (decl);
+         decl = TREE_VALUE (values);
 
          /* [dcl.enum]: Following the closing brace of an enum-specifier,
             each enumerator has the type of its enumeration.  Prior to the
@@ -13048,6 +13068,8 @@ finish_enum (tree enumtype)
             initializing value.  */
          TREE_TYPE (decl) = enumtype;
 
+         /* Update the minimum and maximum values, if appropriate.  */
+         value = DECL_INITIAL (decl);
          /* Figure out what the minimum and maximum values of the
             enumerators are.  */
          if (!minnode)
@@ -13066,13 +13088,13 @@ finish_enum (tree enumtype)
              value = DECL_INITIAL (decl) = copy_node (value);
              TREE_TYPE (value) = enumtype;
            }
-
-         /* In addition, transform the TYPE_VALUES list to contain the
-            values, rather than the CONST_DECLs for them.  */
-         TREE_VALUE (pair) = value;
        }
     }
   else
+    /* [dcl.enum]
+
+       If the enumerator-list is empty, the underlying type is as if
+       the enumeration had a single enumerator with value 0.  */
     minnode = maxnode = integer_zero_node;
 
   /* Compute the number of bits require to represent all values of the
@@ -13084,24 +13106,76 @@ finish_enum (tree enumtype)
   highprec = min_precision (maxnode, unsignedp);
   precision = MAX (lowprec, highprec);
 
-  /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'.  */
-  TYPE_SIZE (enumtype) = NULL_TREE;
-  TYPE_PRECISION (enumtype) = precision;
-  if (unsignedp)
-    fixup_unsigned_type (enumtype);
-  else
-    fixup_signed_type (enumtype);
+  /* Determine the underlying type of the enumeration.
 
-  if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node)))
-    /* Use the width of the narrowest normal C type which is wide
-       enough.  */
-    TYPE_PRECISION (enumtype) = TYPE_PRECISION (c_common_type_for_size
-                                               (precision, 1));
-  else
-    TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
+       [dcl.enum]
 
-  TYPE_SIZE (enumtype) = NULL_TREE;
-  layout_type (enumtype);
+       The underlying type of an enumeration is an integral type that
+       can represent all the enumerator values defined in the
+       enumeration.  It is implementation-defined which integral type is
+       used as the underlying type for an enumeration except that the
+       underlying type shall not be larger than int unless the value of
+       an enumerator cannot fit in an int or unsigned int.  
+
+     We use "int" or an "unsigned int" as the underlying type, even if
+     a smaller integral type would work, unless the user has
+     explicitly requested that we use the smallest possible type.  */
+  for (itk = (flag_short_enums ? itk_char : itk_int); 
+       itk != itk_none; 
+       itk++)
+    {
+      underlying_type = integer_types[itk];
+      if (TYPE_PRECISION (underlying_type) >= precision
+         && TREE_UNSIGNED (underlying_type) == unsignedp)
+       break;
+    }
+  if (itk == itk_none)
+    {
+      /* DR 377
+
+        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);
+      precision = TYPE_PRECISION (long_long_integer_type_node);
+      underlying_type = integer_types[itk_unsigned_long_long];
+    }
+
+  /* Compute the minium and maximum values for the type.  
+
+     [dcl.enum]
+
+     For an enumeration where emin is the smallest enumerator and emax
+     is the largest, the values of the enumeration are the values of the
+     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;
+  set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp);
+
+  /* [dcl.enum]
+     
+     The value of sizeof() applied to an enumeration type, an object
+     of an enumeration type, or an enumerator, is the value of sizeof()
+     applied to the underlying type.  */
+  TYPE_SIZE (enumtype) = TYPE_SIZE (underlying_type);
+  TYPE_SIZE_UNIT (enumtype) = TYPE_SIZE_UNIT (underlying_type);
+  TYPE_MODE (enumtype) = TYPE_MODE (underlying_type);
+  TYPE_ALIGN (enumtype) = TYPE_ALIGN (underlying_type);
+  TYPE_USER_ALIGN (enumtype) = TYPE_USER_ALIGN (underlying_type);
+  TREE_UNSIGNED (enumtype) = TREE_UNSIGNED (underlying_type);
+
+  /* Convert each of the enumerators to the type of the underlying
+     type of the enumeration.  */
+  for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
+    {
+      decl = TREE_VALUE (values);
+      value = perform_implicit_conversion (underlying_type,
+                                          DECL_INITIAL (decl));
+      TREE_TYPE (value) = enumtype;
+      DECL_INITIAL (decl) = value;
+      TREE_VALUE (values) = value;
+    }
 
   /* Fix up all variant types of this enum type.  */
   for (t = TYPE_MAIN_VARIANT (enumtype); t; t = TYPE_NEXT_VARIANT (t))
@@ -13146,7 +13220,7 @@ build_enumerator (tree name, tree value, tree enumtype)
 
          if (TREE_CODE (value) == INTEGER_CST)
            {
-             value = default_conversion (value);
+             value = perform_integral_promotions (value);
              constant_expression_warning (value);
            }
          else
@@ -13183,6 +13257,8 @@ 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
@@ -13214,8 +13290,8 @@ build_enumerator (tree name, tree value, tree enumtype)
 
   if (context && context == current_class_type)
     /* In something like `struct S { enum E { i = 7 }; };' we put `i'
-      on the TYPE_FIELDS list for `S'.  (That's so that you can say
-      things like `S::i' later.)  */
+       on the TYPE_FIELDS list for `S'.  (That's so that you can say
+       things like `S::i' later.)  */
     finish_member_declaration (decl);
   else
     pushdecl (decl);
@@ -13246,9 +13322,9 @@ check_function_type (tree decl, tree current_function_parms)
        {
          tree ctype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype)));
          TREE_TYPE (decl)
-           = build_cplus_method_type (ctype,
-                                      void_type_node,
-                                      FUNCTION_ARG_CHAIN (decl));
+           = build_method_type_directly (ctype,
+                                         void_type_node,
+                                         FUNCTION_ARG_CHAIN (decl));
        }
       else
        TREE_TYPE (decl)
@@ -13348,20 +13424,6 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
       fntype = TREE_TYPE (decl1);
 
       restype = TREE_TYPE (fntype);
-      if (CLASS_TYPE_P (restype) && !CLASSTYPE_GOT_SEMICOLON (restype))
-       {
-         error ("semicolon missing after declaration of `%#T'", restype);
-         shadow_tag (build_tree_list (NULL_TREE, restype));
-         CLASSTYPE_GOT_SEMICOLON (restype) = 1;
-         if (TREE_CODE (fntype) == FUNCTION_TYPE)
-           fntype = build_function_type (integer_type_node,
-                                         TYPE_ARG_TYPES (fntype));
-         else
-           fntype = build_cplus_method_type (build_type_variant (TYPE_METHOD_BASETYPE (fntype), TREE_READONLY (decl1), TREE_SIDE_EFFECTS (decl1)),
-                                             integer_type_node,
-                                             TYPE_ARG_TYPES (fntype));
-         TREE_TYPE (decl1) = fntype;
-       }
 
       if (TREE_CODE (fntype) == METHOD_TYPE)
        ctype = TYPE_METHOD_BASETYPE (fntype);
@@ -13475,7 +13537,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
      CFUN set up, and our per-function variables initialized.
      FIXME factor out the non-RTL stuff.  */
   bl = current_binding_level;
-  init_function_start (decl1, input_filename, input_line);
+  init_function_start (decl1);
   current_binding_level = bl;
 
   /* Even though we're inside a function body, we still don't want to
@@ -13489,7 +13551,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
   begin_stmt_tree (&DECL_SAVED_TREE (decl1));
 
   /* Don't double-count statements in templates.  */
-  DECL_NUM_STMTS (decl1) = 0;
+  DECL_ESTIMATED_INSNS (decl1) = 0;
 
   /* Let the user know we're compiling this function.  */
   announce_function (decl1);
@@ -13735,8 +13797,7 @@ save_function_data (tree decl)
                      19990908);
 
   /* Make a copy.  */
-  f = ((struct language_function *)
-       ggc_alloc (sizeof (struct language_function)));
+  f = ggc_alloc (sizeof (struct language_function));
   memcpy (f, cp_function_chain, sizeof (struct language_function));
   DECL_SAVED_FUNCTION_DATA (decl) = f;
 
@@ -13809,14 +13870,14 @@ begin_destructor_body (void)
      initialize the vtables.)  */
   finish_if_stmt_cond (boolean_true_node, if_stmt);
 
-  compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
+  compound_stmt = begin_compound_stmt (/*has_no_scope=*/false);
 
   /* Make all virtual function table pointers in non-virtual base
      classes point to CURRENT_CLASS_TYPE's virtual function
      tables.  */
   initialize_vtbl_ptrs (current_class_ptr);
 
-  finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
+  finish_compound_stmt (compound_stmt);
   finish_then_clause (if_stmt);
   finish_if_stmt ();
 
@@ -13883,7 +13944,7 @@ begin_function_body (void)
        operation of dwarfout.c.  */
     keep_next_level (1);
 
-  stmt = begin_compound_stmt (0);
+  stmt = begin_compound_stmt (/*has_no_scope=*/false);
   COMPOUND_STMT_BODY_BLOCK (stmt) = 1;
 
   if (processing_template_decl)
@@ -13909,7 +13970,7 @@ void
 finish_function_body (tree compstmt)
 {
   /* Close the block.  */
-  finish_compound_stmt (0, compstmt);
+  finish_compound_stmt (compstmt);
 
   if (processing_template_decl)
     /* Do nothing now.  */;
@@ -14180,14 +14241,16 @@ start_method (tree declspecs, tree declarator, tree attrlist)
   check_template_shadow (fndecl);
 
   DECL_DECLARED_INLINE_P (fndecl) = 1;
-
-  DID_INLINE_FUNC (fndecl) = 0;
   if (flag_default_inline)
     DECL_INLINE (fndecl) = 1;
 
   /* We process method specializations in finish_struct_1.  */
   if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
-    fndecl = push_template_decl (fndecl);
+    {
+      fndecl = push_template_decl (fndecl);
+      if (fndecl == error_mark_node)
+       return fndecl;
+    }
 
   if (! DECL_FRIEND_P (fndecl))
     {
@@ -14353,8 +14416,7 @@ cxx_maybe_build_cleanup (tree decl)
 
       if (TYPE_USES_VIRTUAL_BASECLASSES (type)
          && ! TYPE_HAS_DESTRUCTOR (type))
-       rval = build_compound_expr (tree_cons (NULL_TREE, rval,
-                                              build_tree_list (NULL_TREE, build_vbase_delete (type, decl))));
+       rval = build_compound_expr (rval, build_vbase_delete (type, decl));
 
       return rval;
     }
@@ -14405,8 +14467,7 @@ void
 cxx_push_function_context (struct function * f)
 {
   struct language_function *p
-    = ((struct language_function *)
-       ggc_alloc_cleared (sizeof (struct language_function)));
+    = ggc_alloc_cleared (sizeof (struct language_function));
   f->language = p;
 
   /* It takes an explicit call to expand_body to generate RTL for a