OSDN Git Service

* decl.c (decls_match): Allow a redeclaration of a builtin to
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index a948c30..2760ea5 100644 (file)
@@ -37,7 +37,6 @@ Boston, MA 02111-1307, USA.  */
 #include "decl.h"
 #include "lex.h"
 #include <signal.h>
-#include "obstack.h"
 #include "defaults.h"
 #include "output.h"
 #include "except.h"
@@ -46,11 +45,6 @@ Boston, MA 02111-1307, USA.  */
 #include "defaults.h"
 #include "ggc.h"
 
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
-extern struct obstack permanent_obstack;
-
 extern int current_class_depth;
 
 extern tree static_ctors, static_dtors;
@@ -113,7 +107,6 @@ static void declare_namespace_level PARAMS ((void));
 static void signal_catch PARAMS ((int)) ATTRIBUTE_NORETURN;
 static void storedecls PARAMS ((tree));
 static void require_complete_types_for_parms PARAMS ((tree));
-static void push_overloaded_decl_1 PARAMS ((tree));
 static int ambi_op_p PARAMS ((tree));
 static int unary_op_p PARAMS ((tree));
 static tree store_bindings PARAMS ((tree, tree));
@@ -133,6 +126,7 @@ static void set_identifier_type_value_with_scope
        PARAMS ((tree, tree, struct binding_level *));
 static void record_builtin_type PARAMS ((enum rid, const char *, tree));
 static void record_unknown_type PARAMS ((tree, const char *));
+static tree build_library_fn_1                 PARAMS ((tree, tree));
 static int member_function_or_else PARAMS ((tree, tree, enum overload_flags));
 static void bad_specifiers PARAMS ((tree, const char *, int, int, int, int,
                                  int));
@@ -182,6 +176,10 @@ static tree get_atexit_node PARAMS ((void));
 static tree get_dso_handle_node PARAMS ((void));
 static tree start_cleanup_fn PARAMS ((void));
 static void end_cleanup_fn PARAMS ((void));
+static tree cp_make_fname_decl PARAMS ((tree, const char *, int));
+static void initialize_predefined_identifiers PARAMS ((void));
+static tree check_special_function_return_type 
+  PARAMS ((special_function_kind, tree, tree, tree));
 
 #if defined (DEBUG_CP_BINDING_LEVELS)
 static void indent PARAMS ((void));
@@ -210,7 +208,7 @@ tree error_mark_list;
        tree __tp_desc_type_node;
 #endif
         tree ti_desc_type_node;
-       tree bltn_desc_type_node, ptr_desc_type_node, ref_desc_type_node;
+       tree bltn_desc_type_node, ptr_desc_type_node;
        tree ary_desc_type_node, func_desc_type_node, enum_desc_type_node;
        tree class_desc_type_node, si_class_desc_type_node, vmi_class_desc_type_node;
        tree ptmd_desc_type_node;
@@ -222,7 +220,6 @@ tree error_mark_list;
        tree __ptmf_desc_array_type, __ptmd_desc_array_type;
 #endif
 
-       tree class_star_type_node;
        tree class_type_node, record_type_node, union_type_node, enum_type_node;
        tree unknown_type_node;
 
@@ -231,9 +228,10 @@ tree error_mark_list;
        tree vtbl_type_node;
        tree vtbl_ptr_type_node;
 
-   Nnamespace std
+   Namespaces,
 
        tree std_node;
+       tree abi_node;
 
    A FUNCTION_DECL which can call `abort'.  Not necessarily the
    one that the user will declare, but sufficient to be called
@@ -314,10 +312,6 @@ static tree current_function_parm_tags;
 
 #define named_labels cp_function_chain->x_named_labels
 
-/* The FUNCTION_DECL for the function currently being compiled,
-   or 0 if between functions.  */
-tree current_function_decl;
-
 /* Set to 0 at beginning of a function definition, and whenever
    a label (case or named) is defined.  Set to value of expression
    returned from function when that value can be transformed into
@@ -342,10 +336,6 @@ extern int flag_no_builtin;
 
 extern int flag_no_nonansi_builtin;
 
-/* Nonzero if we want to support huge (> 2^(sizeof(short)*8-1) bytes)
-   objects.  */
-extern int flag_huge_objects;
-
 /* Nonzero if we want to conserve space in the .o files.  We do this
    by putting uninitialized data and runtime initialized data into
    .common instead of .data at the expense of not flagging multiple
@@ -454,19 +444,18 @@ struct binding_level
     tree incomplete;
 
     /* List of VAR_DECLS saved from a previous for statement.
-       These would be dead in ANSI-conforming code, but might
+       These would be dead in ISO-conforming code, but might
        be referenced in ARM-era code.  These are stored in a
        TREE_LIST; the TREE_VALUE is the actual declaration.  */
     tree dead_vars_from_for;
 
     /* 1 for the level that holds the parameters of a function.
-       2 for the level that holds a class declaration.
-       3 for levels that hold parameter declarations.  */
-    unsigned parm_flag : 4;
+       2 for the level that holds a class declaration.  */
+    unsigned parm_flag : 2;
 
     /* 1 means make a BLOCK for this level regardless of all else.
        2 for temporary binding contours created by the compiler.  */
-    unsigned keep : 3;
+    unsigned keep : 2;
 
     /* Nonzero if this level "doesn't exist" for tags.  */
     unsigned tag_transparent : 1;
@@ -476,22 +465,27 @@ struct binding_level
     unsigned more_cleanups_ok : 1;
     unsigned have_cleanups : 1;
 
-    /* Nonzero if this level is for storing the decls for template
+    /* Nonzero if this scope is for storing the decls for template
        parameters and generic decls; these decls will be discarded and
        replaced with a TEMPLATE_DECL.  */
-    unsigned pseudo_global : 1;
+    unsigned template_parms_p : 1;
+
+    /* Nonzero if this scope corresponds to the `<>' in a 
+       `template <>' clause.  Whenever this flag is set,
+       TEMPLATE_PARMS_P will be set as well.  */
+    unsigned template_spec_p : 1;
 
     /* This is set for a namespace binding level.  */
     unsigned namespace_p : 1;
 
     /* True if this level is that of a for-statement where we need to
-       worry about ambiguous (ARM or ANSI) scope rules.  */
+       worry about ambiguous (ARM or ISO) scope rules.  */
     unsigned is_for_scope : 1;
 
     /* True if this level corresponds to an EH region, as for a try block.  */
     unsigned eh_region : 1;
 
-    /* One bit left for this word.  */
+    /* Four bits left for this word.  */
 
 #if defined(DEBUG_CP_BINDING_LEVELS)
     /* Binding depth at which this level began.  */
@@ -708,15 +702,15 @@ innermost_nonclass_level ()
 /* Nonzero if we are currently in a toplevel binding level.  This
    means either the global binding level or a namespace in a toplevel
    binding level.  Since there are no non-toplevel namespace levels,
-   this really means any namespace or pseudo-global level.  We also
-   include a class whose context is toplevel.  */
+   this really means any namespace or template parameter level.  We
+   also include a class whose context is toplevel.  */
 
 int
 toplevel_bindings_p ()
 {
   struct binding_level *b = innermost_nonclass_level ();
 
-  return b->namespace_p || b->pseudo_global;
+  return b->namespace_p || b->template_parms_p;
 }
 
 /* Nonzero if this is a namespace scope, or if we are defining a class
@@ -754,22 +748,108 @@ kept_level_p ()
              && !current_binding_level->tag_transparent));
 }
 
-void
-declare_pseudo_global_level ()
-{
-  current_binding_level->pseudo_global = 1;
-}
-
 static void
 declare_namespace_level ()
 {
   current_binding_level->namespace_p = 1;
 }
 
+/* Returns non-zero if this scope was created to store template
+   parameters.  */
+
 int
-pseudo_global_level_p ()
+template_parm_scope_p ()
 {
-  return current_binding_level->pseudo_global;
+  return current_binding_level->template_parms_p;
+}
+
+/* Returns the kind of template specialization we are currently
+   processing, given that it's declaration contained N_CLASS_SCOPES
+   explicit scope qualifications.  */
+
+tmpl_spec_kind
+current_tmpl_spec_kind (n_class_scopes)
+     int n_class_scopes;
+{
+  int n_template_parm_scopes = 0;
+  int seen_specialization_p = 0;
+  int innermost_specialization_p = 0;
+  struct binding_level *b;
+
+  /* Scan through the template parameter scopes.  */
+  for (b = current_binding_level; b->template_parms_p; b = b->level_chain)
+    {
+      /* If we see a specialization scope inside a parameter scope,
+        then something is wrong.  That corresponds to a declaration
+        like:
+
+           template <class T> template <> ...
+
+        which is always illegal since [temp.expl.spec] forbids the
+        specialization of a class member template if the enclosing
+        class templates are not explicitly specialized as well.  */
+      if (b->template_spec_p)
+       {
+         if (n_template_parm_scopes == 0)
+           innermost_specialization_p = 1;
+         else
+           seen_specialization_p = 1;
+       }
+      else if (seen_specialization_p == 1)
+       return tsk_invalid_member_spec;
+
+      ++n_template_parm_scopes;
+    }
+
+  /* Handle explicit instantiations.  */
+  if (processing_explicit_instantiation)
+    {
+      if (n_template_parm_scopes != 0)
+       /* We've seen a template parameter list during an explicit
+          instantiation.  For example:
+
+            template <class T> template void f(int);
+
+          This is erroneous.  */
+       return tsk_invalid_expl_inst;
+      else
+       return tsk_expl_inst;
+    }
+
+  if (n_template_parm_scopes < n_class_scopes)
+    /* We've not seen enough template headers to match all the
+       specialized classes present.  For example:
+
+         template <class T> void R<T>::S<T>::f(int);
+
+       This is illegal; there needs to be one set of template
+       parameters for each class.  */
+    return tsk_insufficient_parms;
+  else if (n_template_parm_scopes == n_class_scopes)
+    /* We're processing a non-template declaration (even though it may
+       be a member of a template class.)  For example:
+
+         template <class T> void S<T>::f(int);
+
+       The `class T' maches the `S<T>', leaving no template headers
+       corresponding to the `f'.  */
+    return tsk_none;
+  else if (n_template_parm_scopes > n_class_scopes + 1)
+    /* We've got too many template headers.  For example:
+
+         template <> template <class T> void f (T);
+
+       There need to be more enclosing classes.  */
+    return tsk_excessive_parms;
+  else
+    /* This must be a template.  It's of the form:
+
+         template <class T> template <class U> void S<T>::f(U);
+
+       This is a specialization if the innermost level was a
+       specialization; otherwise it's just a definition of the
+       template.  */
+    return innermost_specialization_p ? tsk_expl_spec : tsk_template;
 }
 
 void
@@ -810,6 +890,38 @@ pushlevel (tag_transparent)
   keep_next_level_flag = 0;
 }
 
+/* Enter a new scope.  The KIND indicates what kind of scope is being
+   created.  */
+
+void
+begin_scope (sk)
+     scope_kind sk;
+{
+  pushlevel (0);
+
+  switch (sk)
+    {
+    case sk_template_spec:
+      current_binding_level->template_spec_p = 1;
+      /* Fall through.  */
+
+    case sk_template_parms:
+      current_binding_level->template_parms_p = 1;
+      break;
+
+    default:
+      my_friendly_abort (20000309);
+    }
+}
+
+/* Exit the current scope.  */
+
+void
+finish_scope ()
+{
+  poplevel (0, 0, 0);
+}
+
 void
 note_level_for_for ()
 {
@@ -1009,8 +1121,7 @@ push_class_binding (id, decl)
            context = CP_DECL_CONTEXT (OVL_CURRENT (decl));
          else
            {
-             my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd',
-                                 0);
+             my_friendly_assert (DECL_P (decl), 0);
              context = CP_DECL_CONTEXT (decl);
            }
 
@@ -1334,7 +1445,7 @@ poplevel (keep, reverse, functionbody)
          decl = link;
          if (TREE_CODE (decl) == TREE_LIST)
            decl = TREE_VALUE (decl);
-         if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
+         if (DECL_P (decl))
            pop_binding (DECL_NAME (decl), decl);
          else if (TREE_CODE (decl) == OVERLOAD)
            pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl);
@@ -1646,9 +1757,8 @@ vtype_decl_p (t, data)
      void *data ATTRIBUTE_UNUSED;
 {
   return (TREE_CODE (t) == TYPE_DECL
-         && TREE_TYPE (t) != error_mark_node
-         && TYPE_LANG_SPECIFIC (TREE_TYPE (t))
-         && CLASSTYPE_VSIZE (TREE_TYPE (t)));
+         && TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
+         && TYPE_POLYMORPHIC_P (TREE_TYPE (t)));
 }
 
 /* Return the declarations that are members of the namespace NS.  */
@@ -1789,7 +1899,18 @@ wrapup_globals_for_namespace (namespace, data)
      Put them into VEC from back to front, then take out from front.  */
 
   for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
-    vec[len - i - 1] = decl;
+    {
+      /* Pretend we've output an unused static variable.  This ensures
+         that the toplevel __FUNCTION__ etc won't be emitted, unless
+         needed. */
+      if (TREE_CODE (decl) == VAR_DECL && DECL_ARTIFICIAL (decl)
+         && !TREE_PUBLIC (decl) && !TREE_USED (decl))
+       {
+         TREE_ASM_WRITTEN (decl) = 1;
+         DECL_IGNORED_P (decl) = 1;
+       }
+      vec[len - i - 1] = decl;
+    }
 
   if (last_time)
     {
@@ -2374,7 +2495,7 @@ maybe_push_to_top_level (pseudo)
         inserted into namespace level, finish_file wouldn't find them
         when doing pending instantiations. Therefore, don't stop at
         namespace level, but continue until :: .  */
-      if (b == global_binding_level || (pseudo && b->pseudo_global))
+      if (b == global_binding_level || (pseudo && b->template_parms_p))
        break;
 
       old_bindings = store_bindings (b->names, old_bindings);
@@ -2583,7 +2704,7 @@ maybe_process_template_type_declaration (type, globalize, b)
             friend case, push_template_decl will already have put the
             friend into global scope, if appropriate.  */
          if (TREE_CODE (type) != ENUMERAL_TYPE
-             && !globalize && b->pseudo_global
+             && !globalize && b->template_parms_p
              && b->level_chain->parm_flag == 2)
            {
              finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
@@ -2592,7 +2713,7 @@ maybe_process_template_type_declaration (type, globalize, b)
                 binding level, but is instead the pseudo-global level.  */
              b->level_chain->tags =
                tree_cons (name, type, b->level_chain->tags);
-             if (TYPE_SIZE (current_class_type) == NULL_TREE)
+             if (!COMPLETE_TYPE_P (current_class_type))
                CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
            }
        }
@@ -2658,8 +2779,7 @@ pushtag (name, type, globalize)
 
              if (! globalize)
                context = cs;
-             else if (cs != NULL_TREE
-                      && TREE_CODE_CLASS (TREE_CODE (cs)) == 't')
+             else if (cs != NULL_TREE && TYPE_P (cs))
                /* When declaring a friend class of a local class, we want
                   to inject the newly named class into the scope
                   containing the local class, not the namespace scope.  */
@@ -2668,7 +2788,7 @@ pushtag (name, type, globalize)
          if (!context)
            context = current_namespace;
 
-         if ((b->pseudo_global && b->level_chain->parm_flag == 2)
+         if ((b->template_parms_p && b->level_chain->parm_flag == 2)
              || b->parm_flag == 2)
            in_class = 1;
 
@@ -2708,7 +2828,7 @@ pushtag (name, type, globalize)
         }
       if (b->parm_flag == 2)
        {
-         if (TYPE_SIZE (current_class_type) == NULL_TREE)
+         if (!COMPLETE_TYPE_P (current_class_type))
            CLASSTYPE_TAGS (current_class_type) = b->tags;
        }
     }
@@ -2811,32 +2931,13 @@ decls_match (newdecl, olddecl)
                && DECL_LANGUAGE (olddecl) == lang_c))
        return 0;
 
-      /* When we parse a static member function definition,
-        we put together a FUNCTION_DECL which thinks its type
-        is METHOD_TYPE.  Change that to FUNCTION_TYPE, and
-        proceed.  */
-      if (TREE_CODE (f1) == METHOD_TYPE && DECL_STATIC_FUNCTION_P (olddecl))
-       revert_static_member_fn (&newdecl, &f1, &p1);
-      else if (TREE_CODE (f2) == METHOD_TYPE
-              && DECL_STATIC_FUNCTION_P (newdecl))
-       revert_static_member_fn (&olddecl, &f2, &p2);
-
-      /* Here we must take care of the case where new default
-        parameters are specified.  Also, warn if an old
-        declaration becomes ambiguous because default
-        parameters may cause the two to be ambiguous.  */
       if (TREE_CODE (f1) != TREE_CODE (f2))
-       {
-         if (TREE_CODE (f1) == OFFSET_TYPE)
-           cp_compiler_error ("`%D' redeclared as member function", newdecl);
-         else
-           cp_compiler_error ("`%D' redeclared as non-member function", newdecl);
-         return 0;
-       }
+        return 0;
 
       if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
        {
-         if (! strict_prototypes_lang_c && DECL_LANGUAGE (olddecl) == lang_c
+         if ((! strict_prototypes_lang_c || DECL_BUILT_IN (olddecl))
+             && DECL_LANGUAGE (olddecl) == lang_c
              && p2 == NULL_TREE)
            {
              types_match = self_promoting_args_p (p1);
@@ -3528,8 +3629,6 @@ duplicate_decls (newdecl, olddecl)
          if (DECL_ARGUMENTS (olddecl))
            DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
        }
-      if (DECL_LANG_SPECIFIC (olddecl))
-       DECL_MAIN_VARIANT (newdecl) = DECL_MAIN_VARIANT (olddecl);
     }
 
   if (TREE_CODE (newdecl) == NAMESPACE_DECL)
@@ -3944,12 +4043,12 @@ pushdecl (x)
          if (oldlocal)
            {
              tree d = oldlocal;
+
              while (oldlocal
                     && TREE_CODE (oldlocal) == VAR_DECL
                     && DECL_DEAD_FOR_LOCAL (oldlocal))
-               {
-                 oldlocal = DECL_SHADOWED_FOR_VAR (oldlocal);
-               }
+               oldlocal = DECL_SHADOWED_FOR_VAR (oldlocal);
+
              if (oldlocal == NULL_TREE)
                oldlocal = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (d));
            }
@@ -4034,7 +4133,7 @@ pushdecl (x)
       /* Keep count of variables in this level with incomplete type.  */
       if (TREE_CODE (x) == VAR_DECL
          && TREE_TYPE (x) != error_mark_node
-         && ((TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
+         && ((!COMPLETE_TYPE_P (TREE_TYPE (x))
               && PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE))
              /* RTTI TD entries are created while defining the type_info.  */
              || (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
@@ -4208,29 +4307,6 @@ maybe_push_decl (decl)
     return pushdecl (decl);
 }
 
-#if 0
-/* This function is used to push the mangled decls for nested types into
-   the appropriate scope.  Previously pushdecl_top_level was used, but that
-   is incorrect for members of local classes.  */
-
-void
-pushdecl_nonclass_level (x)
-     tree x;
-{
-  struct binding_level *b = current_binding_level;
-
-  my_friendly_assert (b->parm_flag != 2, 180);
-
-#if 0
-  /* Get out of template binding levels */
-  while (b->pseudo_global)
-    b = b->level_chain;
-#endif
-
-  pushdecl_with_scope (x, b);
-}
-#endif
-
 /* Make the declaration(s) of X appear in CLASS scope
    under the name NAME.  */
 
@@ -4368,8 +4444,8 @@ push_using_directive (used)
    want to be referenced by that name.  It is then up to the users of
    that name to decide what to do with that list.
 
-   DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT
-   slot.  It is dealt with the same way.
+   DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its
+   DECL_TEMPLATE_RESULT.  It is dealt with the same way.
 
    FLAGS is a bitwise-or of the following values:
      PUSH_LOCAL: Bind DECL in the current scope, rather than at
@@ -4510,7 +4586,7 @@ implicitly_declare (functionid)
   DECL_EXTERNAL (decl) = 1;
   TREE_PUBLIC (decl) = 1;
 
-  /* ANSI standard says implicit declarations are in the innermost block.
+  /* ISO standard says implicit declarations are in the innermost block.
      So we record the decl in the standard fashion.  */
   pushdecl (decl);
   rest_of_decl_compilation (decl, NULL_PTR, 0, 0);
@@ -4581,8 +4657,8 @@ redeclaration_error_message (newdecl, olddecl)
           && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl))
           && DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)))
          || (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL
-             && TYPE_SIZE (TREE_TYPE (newdecl))
-             && TYPE_SIZE (TREE_TYPE (olddecl))))
+             && COMPLETE_TYPE_P (TREE_TYPE (newdecl))
+             && COMPLETE_TYPE_P (TREE_TYPE (olddecl))))
        return "redefinition of `%#D'";
       return 0;
     }
@@ -4854,7 +4930,7 @@ void
 push_switch ()
 {
   struct cp_switch *p
-    = (struct cp_switch *) oballoc (sizeof (struct cp_switch));
+    = (struct cp_switch *) xmalloc (sizeof (struct cp_switch));
   p->level = current_binding_level;
   p->next = switch_stack;
   switch_stack = p;
@@ -4863,7 +4939,11 @@ push_switch ()
 void
 pop_switch ()
 {
+  struct cp_switch *cs;
+  
+  cs = switch_stack;
   switch_stack = switch_stack->next;
+  free (cs);
 }
 
 /* Note that we've seen a definition of a case label, and complain if this
@@ -4982,9 +5062,9 @@ lookup_tag (form, name, binding_level, thislevel_only)
      int thislevel_only;
 {
   register struct binding_level *level;
-  /* Non-zero if, we should look past a pseudo-global level, even if
-     THISLEVEL_ONLY.  */
-  int allow_pseudo_global = 1;
+  /* Non-zero if, we should look past a template parameter level, even
+     if THISLEVEL_ONLY.  */
+  int allow_template_parms_p = 1;
 
   for (level = binding_level; level; level = level->level_chain)
     {
@@ -5003,11 +5083,11 @@ lookup_tag (form, name, binding_level, thislevel_only)
          {
            tree old = binding_for_name (name, tail);
 
-           /* If we just skipped past a pseudo global level, even
-              though THISLEVEL_ONLY, and we find a template class
-              declaration, then we use the _TYPE node for the
+           /* If we just skipped past a template parameter level,
+              even though THISLEVEL_ONLY, and we find a template
+              class declaration, then we use the _TYPE node for the
               template.  See the example below.  */
-           if (thislevel_only && !allow_pseudo_global
+           if (thislevel_only && !allow_template_parms_p
                && old && BINDING_VALUE (old)
                && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (old)))
              old = TREE_TYPE (BINDING_VALUE (old));
@@ -5050,7 +5130,7 @@ lookup_tag (form, name, binding_level, thislevel_only)
          }
       if (thislevel_only && ! level->tag_transparent)
        {
-         if (level->pseudo_global && allow_pseudo_global)
+         if (level->template_parms_p && allow_template_parms_p)
            {
              /* We must deal with cases like this:
 
@@ -5063,7 +5143,7 @@ lookup_tag (form, name, binding_level, thislevel_only)
                 template parameters, rather than the (surrounding)
                 namespace level.  Thus, we keep going one more level,
                 even though THISLEVEL_ONLY is non-zero.  */
-             allow_pseudo_global = 0;
+             allow_template_parms_p = 0;
              continue;
            }
          else
@@ -5142,7 +5222,7 @@ lookup_namespace_name (namespace, name)
       name = TREE_OPERAND (name, 0);
       if (TREE_CODE (name) == OVERLOAD)
        name = DECL_NAME (OVL_CURRENT (name));
-      else if (TREE_CODE_CLASS (TREE_CODE (name)) == 'd')
+      else if (DECL_P (name))
        name = DECL_NAME (name);
     }
 
@@ -5292,7 +5372,7 @@ make_typename_type (context, name, complain)
 {
   tree fullname;
 
-  if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
+  if (TYPE_P (name))
     {
       if (!(TYPE_LANG_SPECIFIC (name)
            && (CLASSTYPE_IS_TEMPLATE (name)
@@ -5953,24 +6033,57 @@ record_unknown_type (type, name)
   TYPE_MODE (type) = TYPE_MODE (void_type_node);
 }
 
-/* Push overloaded decl, in global scope, with one argument so it
-   can be used as a callback from define_function.  */
+/* An string for which we should create an IDENTIFIER_NODE at
+   startup.  */
 
-static void
-push_overloaded_decl_1 (x)
-     tree x;
+typedef struct predefined_identifier
 {
-  pushdecl (x);
-}
+  /* The name of the identifier.  */
+  const char *name;
+  /* The place where the IDENTIFIER_NODE should be stored.  */
+  tree *node;
+  /* Non-zero if this is the name of a constructor or destructor.  */
+  int ctor_or_dtor_p;
+} predefined_identifier;
 
-inline tree
-auto_function (name, type)
-     tree name, type;
-{
-  return define_function
-    (IDENTIFIER_POINTER (name), type, push_overloaded_decl_1,
-     IDENTIFIER_POINTER (build_decl_overload (name, TYPE_ARG_TYPES (type),
-                                             0)));
+/* Create all the predefined identifiers.  */
+
+static void
+initialize_predefined_identifiers () 
+{
+  struct predefined_identifier *pid;
+
+  /* A table of identifiers to create at startup.  */
+  static predefined_identifier predefined_identifiers[] = {
+    { "C++", &lang_name_cplusplus, 0 },
+    { "C", &lang_name_c, 0 },
+    { "Java", &lang_name_java, 0 },
+    { CTOR_NAME, &ctor_identifier, 1 },
+    { "__base_ctor", &base_ctor_identifier, 1 },
+    { "__comp_ctor", &complete_ctor_identifier, 1 },
+    { DTOR_NAME, &dtor_identifier, 1 },
+    { "__comp_dtor", &complete_dtor_identifier, 1 },
+    { "__base_dtor", &base_dtor_identifier, 1 },
+    { "__deleting_dtor", &deleting_dtor_identifier, 1 },
+    { VTABLE_DELTA2_NAME, &delta2_identifier, 0 },
+    { VTABLE_DELTA_NAME, &delta_identifier, 0 },
+    { IN_CHARGE_NAME, &in_charge_identifier, 0 },
+    { VTABLE_INDEX_NAME, &index_identifier, 0 },
+    { "nelts", &nelts_identifier, 0 },
+    { THIS_NAME, &this_identifier, 0 },
+    { VTABLE_PFN_NAME, &pfn_identifier, 0 },
+    { "__pfn_or_delta2", &pfn_or_delta2_identifier, 0 },
+    { "_vptr", &vptr_identifier, 0 },
+    { "__cp_push_exception", &cp_push_exception_identifier, 0 },
+    { NULL, NULL, 0 }
+  };
+
+  for (pid = predefined_identifiers; pid->name; ++pid)
+    {
+      *pid->node = get_identifier (pid->name);
+      if (pid->ctor_or_dtor_p)
+       IDENTIFIER_CTOR_OR_DTOR_P (*pid->node) = 1;
+    }
 }
 
 /* Create the predefined scalar types of C,
@@ -5990,10 +6103,8 @@ init_decl_processing ()
   if (flag_new_abi && !flag_vtable_thunks)
     fatal ("the new ABI requires vtable thunks");
 
-  /* Have to make these distinct before we try using them.  */
-  lang_name_cplusplus = get_identifier ("C++");
-  lang_name_c = get_identifier ("C");
-  lang_name_java = get_identifier ("Java");
+  /* Create all the identifiers we need.  */
+  initialize_predefined_identifiers ();
 
   /* Let the back-end now how to save and restore language-specific
      per-function globals.  */
@@ -6065,16 +6176,6 @@ init_decl_processing ()
   NAMESPACE_LEVEL (global_namespace) = global_binding_level;
   declare_namespace_level ();
 
-  this_identifier = get_identifier (THIS_NAME);
-  in_charge_identifier = get_identifier (IN_CHARGE_NAME);
-  ctor_identifier = get_identifier (CTOR_NAME);
-  dtor_identifier = get_identifier (DTOR_NAME);
-  pfn_identifier = get_identifier (VTABLE_PFN_NAME);
-  index_identifier = get_identifier (VTABLE_INDEX_NAME);
-  delta_identifier = get_identifier (VTABLE_DELTA_NAME);
-  delta2_identifier = get_identifier (VTABLE_DELTA2_NAME);
-  pfn_or_delta2_identifier = get_identifier ("__pfn_or_delta2");
-
   /* Define `int' and `char' first so that dbx will output them first.  */
   record_builtin_type (RID_INT, NULL_PTR, integer_type_node);
   record_builtin_type (RID_CHAR, "char", char_type_node);
@@ -6159,7 +6260,8 @@ init_decl_processing ()
   boolean_true_node = build_int_2 (1, 0);
   TREE_TYPE (boolean_true_node) = boolean_type_node;
 
-  signed_size_zero_node = build_int_2 (0, 0);  record_builtin_type (RID_FLOAT, NULL_PTR, float_type_node);
+  signed_size_zero_node = build_int_2 (0, 0);
+  record_builtin_type (RID_FLOAT, NULL_PTR, float_type_node);
   record_builtin_type (RID_DOUBLE, NULL_PTR, double_type_node);
   record_builtin_type (RID_MAX, "long double", long_double_type_node);
 
@@ -6193,9 +6295,7 @@ init_decl_processing ()
 
   /* Make a type to be the domain of a few array types
      whose domains don't really matter.
-     200 is small enough that it always fits in size_t
-     and large enough that it can hold most function names for the
-     initializations of __FUNCTION__ and __PRETTY_FUNCTION__.  */
+     200 is small enough that it always fits in size_t.  */
   array_domain_type = build_index_type (build_int_2 (200, 0));
 
   /* Make a type for arrays of characters.
@@ -6207,15 +6307,18 @@ init_decl_processing ()
   int_array_type_node
     = build_array_type (integer_type_node, array_domain_type);
 
-  /* This is just some anonymous class type.  Nobody should ever
-     need to look inside this envelope.  */
-  class_star_type_node = build_pointer_type (make_aggr_type (RECORD_TYPE));
-
-  if (flag_huge_objects)
+  if (flag_new_abi)
+    delta_type_node = ptrdiff_type_node;
+  else if (flag_huge_objects)
     delta_type_node = long_integer_type_node;
   else
     delta_type_node = short_integer_type_node;
 
+  if (flag_new_abi)
+    vtable_index_type = ptrdiff_type_node;
+  else
+    vtable_index_type = delta_type_node;
+
   default_function_type
     = build_function_type (integer_type_node, NULL_TREE);
 
@@ -6317,6 +6420,13 @@ init_decl_processing ()
                         get_identifier (flag_honor_std ? "fake std":"std"),
                         void_type_node);
   pushdecl (std_node);
+  
+  if (flag_new_abi)
+    {
+      push_namespace (get_identifier ("__cxxabiv1"));
+      abi_node = current_namespace;
+      pop_namespace ();
+    }
 
   global_type_node = make_node (LANG_TYPE);
   record_unknown_type (global_type_node, "global type");
@@ -6335,15 +6445,15 @@ init_decl_processing ()
     newtype = build_exception_variant
       (ptr_ftype_sizetype, add_exception_specifier (NULL_TREE, bad_alloc_type_node, -1));
     deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);
-    auto_function (ansi_opname[(int) NEW_EXPR], newtype);
-    auto_function (ansi_opname[(int) VEC_NEW_EXPR], newtype);
-    global_delete_fndecl = auto_function (ansi_opname[(int) DELETE_EXPR],
-                                         deltype);
-    auto_function (ansi_opname[(int) VEC_DELETE_EXPR], deltype);
+    push_cp_library_fn (ansi_opname[(int) NEW_EXPR], newtype);
+    push_cp_library_fn (ansi_opname[(int) VEC_NEW_EXPR], newtype);
+    global_delete_fndecl = push_cp_library_fn (ansi_opname[(int) DELETE_EXPR],
+                                              deltype);
+    push_cp_library_fn (ansi_opname[(int) VEC_DELETE_EXPR], deltype);
   }
 
   abort_fndecl
-    = define_function ("__pure_virtual", void_ftype, 0, 0);
+    = build_library_fn_ptr ("__pure_virtual", void_ftype);
 
   /* Perform other language dependent initializations.  */
   init_class_processing ();
@@ -6362,6 +6472,7 @@ init_decl_processing ()
     flag_weak = 0;
 
   /* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__.  */
+  make_fname_decl = cp_make_fname_decl;
   declare_function_name ();
 
   /* Prepare to check format strings against argument lists.  */
@@ -6412,6 +6523,59 @@ init_decl_processing ()
   ggc_add_tree_root (&static_aggregates, 1);
 }
 
+/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
+   decl, NAME is the initialization string and TYPE_DEP indicates whether
+   NAME depended on the type of the function. We make use of that to detect
+   __PRETTY_FUNCTION__ inside a template fn.  Because we build a tree for
+   the function before emitting any of it, we don't need to treat the
+   VAR_DECL specially. We can decide whether to emit it later, if it was
+   used.  */
+
+static tree
+cp_make_fname_decl (id, name, type_dep)
+     tree id;
+     const char *name;
+     int type_dep;
+{
+  tree decl, type, init;
+  size_t length = strlen (name);
+  tree domain = NULL_TREE;
+  
+  if (!processing_template_decl)
+    type_dep = 0;
+  if (!type_dep)
+    domain = build_index_type (build_int_2 (length, 0));
+
+  type =  build_cplus_array_type
+          (build_qualified_type (char_type_node, TYPE_QUAL_CONST),
+          domain);
+
+  decl = build_lang_decl (VAR_DECL, id, type);
+  TREE_STATIC (decl) = 1;
+  TREE_READONLY (decl) = 1;
+  DECL_SOURCE_LINE (decl) = 0;
+  DECL_ARTIFICIAL (decl) = 1;
+  DECL_IN_SYSTEM_HEADER (decl) = 1;
+  pushdecl (decl);
+  if (processing_template_decl)
+    decl = push_template_decl (decl);
+  if (type_dep)
+    {
+      init = build (FUNCTION_NAME, type);
+      DECL_PRETTY_FUNCTION_P (decl) = 1;
+    }
+  else
+    {
+      init = build_string (length + 1, name);
+      TREE_TYPE (init) = type;
+    }
+  DECL_INITIAL (decl) = init;
+  cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
+  
+  /* We will have to make sure we only emit this, if it is actually used. */
+  return decl;
+}
+
 /* Function to print any language-specific context for an error message.  */
 
 static void
@@ -6422,56 +6586,154 @@ lang_print_error_function (file)
   maybe_print_template_context ();
 }
 
-/* Make a definition for a builtin function named NAME and whose data type
+/* Entry point for the benefit of c_common_nodes_and_builtins.
+
+   Make a definition for a builtin function named NAME and whose data type
    is TYPE.  TYPE should be a function type with argument types.
 
-   If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME,
+   CLASS and CODE tell later passes how to compile calls to this function.
+   See tree.h for possible values.
+
+   If LIBNAME is nonzero, use that for DECL_ASSEMBLER_NAME,
    the name to be called if we can't opencode the function.  */
 
 tree
-define_function (name, type, pfn, library_name)
+builtin_function (name, type, code, class, libname)
      const char *name;
      tree type;
-     void (*pfn) PARAMS ((tree));
-     const char *library_name;
+     int code;
+     enum built_in_class class;
+     const char *libname;
 {
-  tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type);
-  DECL_EXTERNAL (decl) = 1;
-  TREE_PUBLIC (decl) = 1;
-  DECL_ARTIFICIAL (decl) = 1;
+  tree decl = build_library_fn_1 (get_identifier (name), type);
+  DECL_BUILT_IN_CLASS (decl) = class;
+  DECL_FUNCTION_CODE (decl) = code;
 
   my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 392);
-  DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
 
   /* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME,
      we cannot change DECL_ASSEMBLER_NAME until we have installed this
      function in the namespace.  */
-  if (pfn) (*pfn) (decl);
-  if (library_name)
-    DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
+  pushdecl (decl);
+  if (libname)
+    DECL_ASSEMBLER_NAME (decl) = get_identifier (libname);
   make_function_rtl (decl);
   return decl;
 }
 
+/* Generate a FUNCTION_DECL with the typical flags for a runtime library
+   function.  Not called directly.  */
 
-/* Wrapper around define_function, for the benefit of
-   c_common_nodes_and_builtins.
-   FUNCTION_CODE tells later passes how to compile calls to this function.
-   See tree.h for its possible values.  */
+static tree
+build_library_fn_1 (name, type)
+     tree name;
+     tree type;
+{
+  tree fn = build_lang_decl (FUNCTION_DECL, name, type);
+  DECL_EXTERNAL (fn) = 1;
+  TREE_PUBLIC (fn) = 1;
+  DECL_ARTIFICIAL (fn) = 1;
+  TREE_NOTHROW (fn) = 1;
+  return fn;
+}
+
+/* Returns the _DECL for a library function with C linkage.
+   We assume that such functions never throw; if this is incorrect,
+   callers should unset TREE_NOTHROW.  */
 
 tree
-builtin_function (name, type, code, class, libname)
+build_library_fn (name, type)
+     tree name;
+     tree type;
+{
+  tree fn = build_library_fn_1 (name, type);
+  make_function_rtl (fn);
+  return fn;
+}
+
+/* Returns the _DECL for a library function with C++ linkage.  */
+
+tree
+build_cp_library_fn (name, type)
+     tree name;
+     tree type;
+{
+  tree fn = build_library_fn_1 (name, type);
+  TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type);
+  set_mangled_name_for_decl (fn);
+  make_function_rtl (fn);
+  return fn;
+}
+
+/* Like build_library_fn, but takes a C string instead of an
+   IDENTIFIER_NODE.  */
+
+tree
+build_library_fn_ptr (name, type)
      const char *name;
      tree type;
-     int code;
-     enum built_in_class class;
-     const char *libname;
 {
-  tree decl = define_function (name, type, (void (*) PARAMS ((tree)))pushdecl,
-                              libname);
-  DECL_BUILT_IN_CLASS (decl) = class;
-  DECL_FUNCTION_CODE (decl) = code;
-  return decl;
+  return build_library_fn (get_identifier (name), type);
+}
+
+/* Like build_cp_library_fn, but takes a C string instead of an
+   IDENTIFIER_NODE.  */
+
+tree
+build_cp_library_fn_ptr (name, type)
+     const char *name;
+     tree type;
+{
+  return build_cp_library_fn (get_identifier (name), type);
+}
+
+/* Like build_library_fn, but also pushes the function so that we will
+   be able to find it via IDENTIFIER_GLOBAL_VALUE.  */
+
+tree
+push_library_fn (name, type)
+     tree name, type;
+{
+  tree fn = build_library_fn (name, type);
+  pushdecl_top_level (fn);
+  return fn;
+}
+
+/* Like build_cp_library_fn, but also pushes the function so that it
+   will be found by normal lookup.  */
+
+tree
+push_cp_library_fn (name, type)
+     tree name;
+     tree type;
+{
+  tree fn = build_cp_library_fn (name, type);
+  pushdecl (fn);
+  return fn;
+}
+
+/* Like push_library_fn, but takes a TREE_LIST of parm types rather than
+   a FUNCTION_TYPE.  */
+
+tree
+push_void_library_fn (name, parmtypes)
+     tree name, parmtypes;
+{
+  tree type = build_function_type (void_type_node, parmtypes);
+  return push_library_fn (name, type);
+}
+
+/* Like push_library_fn, but also note that this function throws
+   and does not return.  Used for __throw_foo and the like.  */
+
+tree
+push_throw_library_fn (name, type)
+     tree name, type;
+{
+  tree fn = push_library_fn (name, type);
+  TREE_THIS_VOLATILE (fn) = 1;
+  TREE_NOTHROW (fn) = 0;
+  return fn;
 }
 \f
 /* When we call finish_struct for an anonymous union, we create
@@ -6509,8 +6771,7 @@ fixup_anonymous_aggr (t)
        q = &TREE_CHAIN (*q);
     }
 
-  /* ANSI C++ June 5 1992 WP 9.5.3.  Anonymous unions may not have
-     function members.  */
+  /* ISO C++ 9.5.3.  Anonymous unions may not have function members.  */
   if (TYPE_METHODS (t))
     error ("an anonymous union cannot have function members");
 }
@@ -6525,6 +6786,7 @@ check_tag_decl (declspecs)
      tree declspecs;
 {
   int found_type = 0;
+  int saw_friend = 0;
   tree ob_modifier = NULL_TREE;
   register tree link;
   register tree t = NULL_TREE;
@@ -6533,7 +6795,10 @@ check_tag_decl (declspecs)
     {
       register tree value = TREE_VALUE (link);
 
-      if (TYPE_P (value))
+      if (TYPE_P (value)
+         || (TREE_CODE (value) == IDENTIFIER_NODE
+             && IDENTIFIER_GLOBAL_VALUE (value)
+             && TYPE_P (IDENTIFIER_GLOBAL_VALUE (value))))
        {
          ++found_type;
 
@@ -6548,6 +6813,8 @@ check_tag_decl (declspecs)
          if (current_class_type == NULL_TREE
              || current_scope () != current_class_type)
            ob_modifier = value;
+         else
+           saw_friend = 1;
        }
       else if (value == ridpointers[(int) RID_STATIC]
               || value == ridpointers[(int) RID_EXTERN]
@@ -6564,9 +6831,7 @@ check_tag_decl (declspecs)
   if (found_type > 1)
     error ("multiple types in one declaration");
 
-  /* Inside a class, we might be in a friend or access declaration.
-     Until we have a good way of detecting the latter, don't warn.  */
-  if (t == NULL_TREE && ! current_class_type)
+  if (t == NULL_TREE && ! saw_friend)
     pedwarn ("declaration does not declare anything");
 
   /* Check for an anonymous union.  We're careful
@@ -6667,10 +6932,6 @@ groktypename (typename)
    do go through here.  Structure field declarations are done by
    grokfield and not through here.  */
 
-/* Set this to zero to debug not using the temporary obstack
-   to parse initializers.  */
-int debug_temp_inits = 1;
-
 tree
 start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
      tree declarator, declspecs;
@@ -6776,7 +7037,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   /* Set attributes here so if duplicate decl, will have proper attributes.  */
   cplus_decl_attributes (decl, attributes, prefix_attributes);
 
-  if (context && TYPE_SIZE (complete_type (context)) != NULL_TREE)
+  if (context && COMPLETE_TYPE_P (complete_type (context)))
     {
       push_nested_class (context, 2);
 
@@ -6789,7 +7050,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
            {
              if (DECL_CONTEXT (field) != context)
                {
-                 cp_pedwarn ("ANSI C++ does not permit `%T::%D' to be defined as `%T::%D'",
+                 cp_pedwarn ("ISO C++ does not permit `%T::%D' to be defined as `%T::%D'",
                              DECL_CONTEXT (field), DECL_NAME (decl),
                              context, DECL_NAME (decl));
                  DECL_CONTEXT (decl) = DECL_CONTEXT (field);
@@ -6867,7 +7128,7 @@ start_decl_1 (decl)
   /* If this type of object needs a cleanup, but we're not allowed to
      add any more objects with cleanups to the current scope, create a
      new binding level.  */
-  if (TYPE_NEEDS_DESTRUCTOR (type)
+  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
       && current_binding_level->more_cleanups_ok == 0)
     {
       keep_next_level (2);
@@ -6883,7 +7144,7 @@ start_decl_1 (decl)
     {
       /* Don't allow initializations for incomplete types except for
         arrays which might be completed by the initialization.  */
-      if (TYPE_SIZE (complete_type (type)) != NULL_TREE)
+      if (COMPLETE_TYPE_P (complete_type (type)))
        ;                       /* A complete type is ok.  */
       else if (TREE_CODE (type) != ARRAY_TYPE)
        {
@@ -6892,7 +7153,7 @@ start_decl_1 (decl)
          initialized = 0;
          type = TREE_TYPE (decl) = error_mark_node;
        }
-      else if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
+      else if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
        {
          if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
            cp_error ("elements of array `%#D' have incomplete type", decl);
@@ -6909,7 +7170,7 @@ start_decl_1 (decl)
       && ! DECL_EXTERNAL (decl))
     {
       if ((! processing_template_decl || ! uses_template_parms (type))
-         && TYPE_SIZE (complete_type (type)) == NULL_TREE)
+         && !COMPLETE_TYPE_P (complete_type (type)))
        {
          cp_error ("aggregate `%#D' has incomplete type and cannot be initialized",
                 decl);
@@ -6959,7 +7220,7 @@ grok_reference_init (decl, type, init)
 
   if (TREE_CODE (init) == CONSTRUCTOR)
     {
-      cp_error ("ANSI C++ forbids use of initializer list to initialize reference `%D'", decl);
+      cp_error ("ISO C++ forbids use of initializer list to initialize reference `%D'", decl);
       return;
     }
 
@@ -7110,7 +7371,7 @@ layout_var_decl (decl)
      `extern X x' for some incomplete type `X'.)  */
   if (!DECL_EXTERNAL (decl))
     complete_type (type);
-  if (!DECL_SIZE (decl) && TYPE_SIZE (type))
+  if (!DECL_SIZE (decl) && COMPLETE_TYPE_P (type))
     layout_decl (decl, 0);
 
   if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE)
@@ -7156,7 +7417,7 @@ maybe_commonize_var (decl)
      linkage.  */
   if (TREE_STATIC (decl)
       /* Don't mess with __FUNCTION__.  */
-      && ! TREE_ASM_WRITTEN (decl)
+      && ! DECL_ARTIFICIAL (decl)
       && current_function_decl
       && DECL_CONTEXT (decl) == current_function_decl
       && (DECL_THIS_INLINE (current_function_decl)
@@ -7191,7 +7452,7 @@ maybe_commonize_var (decl)
          if (TREE_PUBLIC (decl))
            DECL_ASSEMBLER_NAME (decl)
              = build_static_name (current_function_decl, DECL_NAME (decl));
-         else if (! DECL_ARTIFICIAL (decl))
+         else
            {
              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);
@@ -7253,18 +7514,18 @@ check_initializer (decl, init)
       if (type == error_mark_node)
        /* We will have already complained.  */
        init = NULL_TREE;
-      else if (TYPE_SIZE (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
+      else if (COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
        {
          cp_error ("variable-sized object `%D' may not be initialized", decl);
          init = NULL_TREE;
        }
       else if (TREE_CODE (type) == ARRAY_TYPE
-              && !TYPE_SIZE (TREE_TYPE (type)))
+              && !COMPLETE_TYPE_P (TREE_TYPE (type)))
        {
          cp_error ("elements of array `%#D' have incomplete type", decl);
          init = NULL_TREE;
        }
-      else if (!TYPE_SIZE (type))
+      else if (!COMPLETE_TYPE_P (type))
        {
          cp_error ("`%D' has incomplete type", decl);
          TREE_TYPE (decl) = error_mark_node;
@@ -7322,7 +7583,7 @@ check_initializer (decl, init)
     }
   else if (DECL_EXTERNAL (decl))
     ;
-  else if (TREE_CODE_CLASS (TREE_CODE (type)) == 't'
+  else if (TYPE_P (type)
           && (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
     {
       tree core_type = strip_array_types (type);
@@ -7338,8 +7599,7 @@ check_initializer (decl, init)
 
       check_for_uninitialized_const_var (decl);
 
-      if (TYPE_SIZE (type) != NULL_TREE
-         && TYPE_NEEDS_CONSTRUCTING (type))
+      if (COMPLETE_TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
        init = obscure_complex_init (decl, NULL_TREE);
 
     }
@@ -7513,7 +7773,7 @@ initialize_local_var (decl, init, flags)
   if (TREE_STATIC (decl))
     {
       if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
-         || TYPE_NEEDS_DESTRUCTOR (type))
+         || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
        expand_static_init (decl, init);
       return;
     }
@@ -7545,7 +7805,7 @@ initialize_local_var (decl, init, flags)
         marked used. (see TREE_USED, above.)  */
       if (TYPE_NEEDS_CONSTRUCTING (type)
          && ! already_used
-         && !TYPE_NEEDS_DESTRUCTOR (type)
+         && TYPE_HAS_TRIVIAL_DESTRUCTOR (type)
          && DECL_NAME (decl))
        TREE_USED (decl) = 0;
       else if (already_used)
@@ -7567,7 +7827,7 @@ destroy_local_var (decl)
     return;
 
   /* And only things with destructors need cleaning up.  */
-  if (!TYPE_NEEDS_DESTRUCTOR (type))
+  if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
     return;
 
   if (TREE_CODE (decl) == VAR_DECL &&
@@ -7621,20 +7881,11 @@ emit_local_var (decl)
    If the length of an array type is not known before,
    it must be determined now, from the initial value, or it is an error.
 
-   For C++, `cp_finish_decl' must be fairly evasive:  it must keep initializers
-   for aggregates that have constructors alive on the permanent obstack,
-   so that the global initializing functions can be written at the end.
-
    INIT0 holds the value of an initializer that should be allowed to escape
    the normal rules.
 
-   FLAGS is LOOKUP_ONLYCONVERTING is the = init syntax was used, else 0
-   if the (init) syntax was used.
-
-   For functions that take default parameters, DECL points to its
-   "maximal" instantiation.  `cp_finish_decl' must then also declared its
-   subsequently lower and lower forms of instantiation, checking for
-   ambiguity as it goes.  This can be sped up later.  */
+   FLAGS is LOOKUP_ONLYCONVERTING if the = init syntax was used, else 0
+   if the (init) syntax was used.  */
 
 void
 cp_finish_decl (decl, init, asmspec_tree, flags)
@@ -7647,7 +7898,6 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
   const char *asmspec = NULL;
   int was_readonly = 0;
 
-  /* If this is 0, then we did not change obstacks.  */
   if (! decl)
     {
       if (init)
@@ -7655,33 +7905,13 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
       return;
     }
 
-  /* Handling __FUNCTION__ and its ilk in a template-function requires
-     some special processing because we are called from
-     language-independent code.  */
-  if (cfun && processing_template_decl
-      && current_function_name_declared == 2)
-    {
-      /* Since we're in a template function, we need to
-        push_template_decl.  The language-independent code in
-        declare_hidden_char_array doesn't know to do this.  */
-      retrofit_lang_decl (decl);
-      decl = push_template_decl (decl);
-
-      if (strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)),
-                 "__PRETTY_FUNCTION__") == 0)
-       {
-         init = build (FUNCTION_NAME, const_string_type_node);
-         DECL_PRETTY_FUNCTION_P (decl) = 1;
-       }
-    }
-
   /* If a name was specified, get the string.  */
   if (asmspec_tree)
       asmspec = TREE_STRING_POINTER (asmspec_tree);
 
   if (init && TREE_CODE (init) == NAMESPACE_DECL)
     {
-      cp_error ("Cannot initialize `%D' to namespace `%D'",
+      cp_error ("cannot initialize `%D' to namespace `%D'",
                decl, init);
       init = NULL_TREE;
     }
@@ -7706,7 +7936,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
 
   if (type == error_mark_node)
     return;
-
+  
   /* Add this declaration to the statement-tree.  */
   if (building_stmt_tree () && at_function_scope_p ())
     add_decl_stmt (decl);
@@ -7747,7 +7977,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
         type, and that type has not been defined yet, delay emitting
         the debug information for it, as we will emit it later.  */
       if (TYPE_MAIN_DECL (TREE_TYPE (decl)) == decl
-         && TYPE_SIZE (TREE_TYPE (decl)) == NULL_TREE)
+         && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
        TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
 
       rest_of_decl_compilation (decl, NULL_PTR,
@@ -7843,7 +8073,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
        {
          /* Cleanups for static variables are handled by `finish_file'.  */
          if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
-             || TYPE_NEEDS_DESTRUCTOR (type))
+             || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
            expand_static_init (decl, init);
        }
     finish_end0:
@@ -7854,7 +8084,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
       {
        tree context = CP_DECL_CONTEXT (decl);
        if (context
-           && TREE_CODE_CLASS (TREE_CODE (context)) == 't'
+           && TYPE_P (context)
            && (TREE_CODE (decl) == VAR_DECL
                /* We also have a pushclass done that we need to undo here
                   if we're at top level and declare a method.  */
@@ -7862,7 +8092,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
            /* If size hasn't been set, we're still defining it,
               and therefore inside the class body; don't pop
               the binding level..  */
-           && TYPE_SIZE (context) != NULL_TREE
+           && COMPLETE_TYPE_P (context)
            && context == current_class_type)
          pop_nested_class ();
       }
@@ -7967,7 +8197,7 @@ get_atexit_node ()
 
   /* Now, build the function declaration.  */
   push_lang_context (lang_name_c);
-  atexit_fndecl = define_function (name, fn_type, /*pfn=*/0, NULL_PTR);
+  atexit_fndecl = build_library_fn_ptr (name, fn_type);
   mark_used (atexit_fndecl);
   pop_lang_context ();
   atexit_node = default_conversion (atexit_fndecl);
@@ -8058,7 +8288,7 @@ end_cleanup_fn ()
 {
   do_poplevel ();
 
-  expand_body (finish_function (lineno, 0));
+  expand_body (finish_function (0));
 
   pop_from_top_level ();
 }
@@ -8077,7 +8307,7 @@ register_dtor_fn (decl)
 
   int saved_flag_access_control;
 
-  if (!TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
+  if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
     return;
 
   /* Call build_cleanup before we enter the anonymous function so that
@@ -8263,13 +8493,14 @@ complete_array_type (type, initial_value, do_default)
       else if (TREE_CODE (initial_value) == CONSTRUCTOR)
        {
          tree elts = CONSTRUCTOR_ELTS (initial_value);
-         maxindex = size_binop (MINUS_EXPR, integer_zero_node, size_one_node);
+
+         maxindex = ssize_int (-1);
          for (; elts; elts = TREE_CHAIN (elts))
            {
              if (TREE_PURPOSE (elts))
                maxindex = TREE_PURPOSE (elts);
              else
-               maxindex = size_binop (PLUS_EXPR, maxindex, size_one_node);
+               maxindex = size_binop (PLUS_EXPR, maxindex, ssize_int (1));
            }
          maxindex = copy_node (maxindex);
        }
@@ -8449,11 +8680,11 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
   if (ctype == NULL_TREE && DECL_MAIN_P (decl))
     {
       if (processing_template_decl)
-       error ("cannot declare `main' to be a template");
+       error ("cannot declare `::main' to be a template");
       if (inlinep)
-       error ("cannot declare `main' to be inline");
+       error ("cannot declare `::main' to be inline");
       else if (! publicp)
-       error ("cannot declare `main' to be static");
+       error ("cannot declare `::main' to be static");
       inlinep = 0;
       publicp = 1;
     }
@@ -8532,7 +8763,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
          if (PROCESSING_REAL_TEMPLATE_DECL_P ())
            {
              /* Something like `template <class T> friend void f<T>()'.  */
-             cp_error ("template-id `%D' in declaration of primary template",
+             cp_error ("invalid use of template-id `%D' in declaration of primary template",
                        orig_declarator);
              return NULL_TREE;
            }
@@ -8576,103 +8807,85 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
        tentative.  error_mark_node is replaced later with the BLOCK.  */
     DECL_INITIAL (decl) = error_mark_node;
 
+  if (TYPE_NOTHROW_P (type) || nothrow_libfn_p (decl))
+    TREE_NOTHROW (decl) = 1;
+
   /* Caller will do the rest of this.  */
   if (check < 0)
     return decl;
 
   if (flags == NO_SPECIAL && ctype && constructor_name (cname) == declarator)
-    {
-      tree tmp;
-      /* Just handle constructors here.  We could do this
-        inside the following if stmt, but I think
-        that the code is more legible by breaking this
-        case out.  See comments below for what each of
-        the following calls is supposed to do.  */
-      DECL_CONSTRUCTOR_P (decl) = 1;
-
-      grokclassfn (ctype, decl, flags, quals);
-
-      decl = check_explicit_specialization (orig_declarator, decl,
-                                           template_count,
-                                           2 * (funcdef_flag != 0) +
-                                           4 * (friendp != 0));
-      if (decl == error_mark_node)
-       return NULL_TREE;
-
-      if ((! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
-         && check)
-       {
-         tmp = check_classfn (ctype, decl);
-
-         if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
-           tmp = DECL_TEMPLATE_RESULT(tmp);
+    DECL_CONSTRUCTOR_P (decl) = 1;
+
+  /* Function gets the ugly name, field gets the nice one.  This call
+     may change the type of the function (because of default
+     parameters)!  */
+  if (ctype != NULL_TREE)
+    grokclassfn (ctype, decl, flags, quals);
+
+  decl = check_explicit_specialization (orig_declarator, decl,
+                                       template_count,
+                                       2 * (funcdef_flag != 0) +
+                                       4 * (friendp != 0));
+  if (decl == error_mark_node)
+    return NULL_TREE;
 
-         if (tmp && DECL_ARTIFICIAL (tmp))
-           cp_error ("definition of implicitly-declared `%D'", tmp);
-         if (tmp && duplicate_decls (decl, tmp))
-           return tmp;
-       }
-      if (! grok_ctor_properties (ctype, decl))
-       return NULL_TREE;
-    }
-  else
+  if (ctype != NULL_TREE
+      && (! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
+      && check)
     {
-      tree tmp;
+      tree old_decl;
 
-      /* Function gets the ugly name, field gets the nice one.
-        This call may change the type of the function (because
-        of default parameters)!  */
-      if (ctype != NULL_TREE)
-       grokclassfn (ctype, decl, flags, quals);
+      old_decl = check_classfn (ctype, decl);
 
-      decl = check_explicit_specialization (orig_declarator, decl,
-                                           template_count,
-                                           2 * (funcdef_flag != 0) +
-                                           4 * (friendp != 0));
-      if (decl == error_mark_node)
-       return NULL_TREE;
+      if (old_decl && TREE_CODE (old_decl) == TEMPLATE_DECL)
+       /* Because grokfndecl is always supposed to return a
+          FUNCTION_DECL, we pull out the DECL_TEMPLATE_RESULT
+          here.  We depend on our callers to figure out that its
+          really a template that's being returned.  */
+       old_decl = DECL_TEMPLATE_RESULT (old_decl);
 
-      if (ctype != NULL_TREE
-         && (! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
-         && check)
+      if (old_decl && DECL_STATIC_FUNCTION_P (old_decl)
+         && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
        {
-         tmp = check_classfn (ctype, decl);
+         /* Remove the `this' parm added by grokclassfn.
+            XXX Isn't this done in start_function, too?  */
+         revert_static_member_fn (decl);
+         last_function_parms = TREE_CHAIN (last_function_parms);
+       }
+      if (old_decl && DECL_ARTIFICIAL (old_decl))
+       cp_error ("definition of implicitly-declared `%D'", old_decl);
 
-         if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
-           tmp = DECL_TEMPLATE_RESULT (tmp);
+      if (old_decl)
+       {
+         /* Since we've smashed OLD_DECL to its
+            DECL_TEMPLATE_RESULT, we must do the same to DECL.  */
+         if (TREE_CODE (decl) == TEMPLATE_DECL)
+           decl = DECL_TEMPLATE_RESULT (decl);
 
-         if (tmp && DECL_STATIC_FUNCTION_P (tmp)
-             && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
-           {
-             /* Remove the `this' parm added by grokclassfn.
-                XXX Isn't this done in start_function, too?  */
-             revert_static_member_fn (&decl, NULL, NULL);
-             last_function_parms = TREE_CHAIN (last_function_parms);
-           }
-         if (tmp && DECL_ARTIFICIAL (tmp))
-           cp_error ("definition of implicitly-declared `%D'", tmp);
-         if (tmp)
-           {
-             /* Attempt to merge the declarations.  This can fail, in
-                the case of some illegal specialization declarations.  */
-             if (!duplicate_decls (decl, tmp))
-               cp_error ("no `%#D' member function declared in class `%T'",
-                         decl, ctype);
-             return tmp;
-           }
+         /* Attempt to merge the declarations.  This can fail, in
+            the case of some illegal specialization declarations.  */
+         if (!duplicate_decls (decl, old_decl))
+           cp_error ("no `%#D' member function declared in class `%T'",
+                     decl, ctype);
+         return old_decl;
        }
+    }
 
-      if (ctype == NULL_TREE || check)
-       return decl;
+  if (DECL_CONSTRUCTOR_P (decl) && !grok_ctor_properties (ctype, decl))
+    return NULL_TREE;
 
-      if (virtualp)
-       {
-         DECL_VIRTUAL_P (decl) = 1;
-         if (DECL_VINDEX (decl) == NULL_TREE)
-           DECL_VINDEX (decl) = error_mark_node;
-         IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
-       }
+  if (ctype == NULL_TREE || check)
+    return decl;
+
+  if (virtualp)
+    {
+      DECL_VIRTUAL_P (decl) = 1;
+      if (DECL_VINDEX (decl) == NULL_TREE)
+       DECL_VINDEX (decl) = error_mark_node;
+      IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
     }
+
   return decl;
 }
 
@@ -8804,27 +9017,36 @@ build_ptrmemfunc_type (type)
     unqualified_variant
       = build_ptrmemfunc_type (TYPE_MAIN_VARIANT (type));
 
-  u = make_aggr_type (UNION_TYPE);
-  SET_IS_AGGR_TYPE (u, 0);
-  fields[0] = build_lang_decl (FIELD_DECL, pfn_identifier, type);
-  fields[1] = build_lang_decl (FIELD_DECL, delta2_identifier,
-                              delta_type_node);
-  finish_builtin_type (u, "__ptrmemfunc_type", fields, 1, ptr_type_node);
-  TYPE_NAME (u) = NULL_TREE;
-
   t = make_aggr_type (RECORD_TYPE);
-
   /* Let the front-end know this is a pointer to member function...  */
   TYPE_PTRMEMFUNC_FLAG (t) = 1;
   /* ... and not really an aggregate.  */
   SET_IS_AGGR_TYPE (t, 0);
 
-  fields[0] = build_lang_decl (FIELD_DECL, delta_identifier,
-                              delta_type_node);
-  fields[1] = build_lang_decl (FIELD_DECL, index_identifier,
-                              delta_type_node);
-  fields[2] = build_lang_decl (FIELD_DECL, pfn_or_delta2_identifier, u);
-  finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node);
+  if (!flag_new_abi)
+    {
+      u = make_aggr_type (UNION_TYPE);
+      SET_IS_AGGR_TYPE (u, 0);
+      fields[0] = build_lang_decl (FIELD_DECL, pfn_identifier, type);
+      fields[1] = build_lang_decl (FIELD_DECL, delta2_identifier,
+                                  delta_type_node);
+      finish_builtin_type (u, "__ptrmemfunc_type", fields, 1, ptr_type_node);
+      TYPE_NAME (u) = NULL_TREE;
+
+      fields[0] = build_lang_decl (FIELD_DECL, delta_identifier,
+                                  delta_type_node);
+      fields[1] = build_lang_decl (FIELD_DECL, index_identifier,
+                                  delta_type_node);
+      fields[2] = build_lang_decl (FIELD_DECL, pfn_or_delta2_identifier, u);
+      finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node);
+    }
+  else
+    {
+      fields[0] = build_lang_decl (FIELD_DECL, pfn_identifier, type);
+      fields[1] = build_lang_decl (FIELD_DECL, delta_identifier,
+                                  delta_type_node);
+      finish_builtin_type (t, "__ptrmemfunc_type", fields, 1, ptr_type_node);
+    }
 
   /* Zap out the name so that the back-end will give us the debugging
      information for this anonymous RECORD_TYPE.  */
@@ -8870,7 +9092,7 @@ check_static_variable_definition (decl, type)
      required.  */
   if (CLASS_TYPE_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
     {
-      cp_error ("in-class initialization of static data member of non-integral type `%T'",
+      cp_error ("invalid in-class initialization of static data member of non-integral type `%T'",
                type);
       /* If we just return the declaration, crashes will sometimes
         occur.  We therefore return void_type_node, as if this was a
@@ -8879,10 +9101,10 @@ check_static_variable_definition (decl, type)
       return 1;
     }
   else if (!CP_TYPE_CONST_P (type))
-    cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
+    cp_error ("ISO C++ forbids in-class initialization of non-const static member `%D'",
              decl);
   else if (pedantic && !INTEGRAL_TYPE_P (type))
-    cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
+    cp_pedwarn ("ISO C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
 
   return 0;
 }
@@ -8966,9 +9188,9 @@ compute_array_index_type (name, size)
       else if (integer_zerop (size) && pedantic && !in_system_header)
        {
          if (name)
-           cp_pedwarn ("ANSI C++ forbids zero-size array `%D'", name);
+           cp_pedwarn ("ISO C++ forbids zero-size array `%D'", name);
          else
-           cp_pedwarn ("ANSI C++ forbids zero-size array");
+           cp_pedwarn ("ISO C++ forbids zero-size array");
        }
     }
 
@@ -8987,10 +9209,10 @@ compute_array_index_type (name, size)
       if (pedantic)
        {
          if (name)
-           cp_pedwarn ("ANSI C++ forbids variable-size array `%D'",
+           cp_pedwarn ("ISO C++ forbids variable-size array `%D'",
                        name);
          else
-           cp_pedwarn ("ANSI C++ forbids variable-size array");
+           cp_pedwarn ("ISO C++ forbids variable-size array");
        }
 
       /* Create a variable-sized array index type.  */
@@ -9073,9 +9295,8 @@ create_array_type_for_decl (name, type, size)
      can be omitted only for the first member of the sequence.  */
   if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
     {
-      cp_error ("declaration of `%D' as multidimensional array",
+      cp_error ("declaration of `%D' as multidimensional array must have bounds for all dimensions except the first",
                name);
-      cp_error ("must have bounds for all dimensions except the first");
 
       return error_mark_node;
     }
@@ -9087,6 +9308,54 @@ create_array_type_for_decl (name, type, size)
   return build_cplus_array_type (type, itype);
 }
 
+/* Check that it's OK to declare a function with the indicated TYPE.
+   SFK indicates the kind of special function (if any) that this
+   function is.  CTYPE is the class of which this function is a
+   member.  OPTYPE is the type given in a conversion operator
+   declaration.  Returns the actual return type of the function; that
+   may be different than TYPE if an error occurs, or for certain
+   special functions.  */
+
+static tree
+check_special_function_return_type (sfk, type, ctype, optype)
+     special_function_kind sfk;
+     tree type;
+     tree ctype;
+     tree optype;
+{
+  switch (sfk)
+    {
+    case sfk_constructor:
+      if (type)
+       cp_error ("return type specification for constructor invalid");
+       
+      /* In the old ABI, we return `this'; in the new ABI we don't
+        bother.  */
+      type = flag_new_abi ? void_type_node : build_pointer_type        (ctype);
+      break;
+
+    case sfk_destructor:
+      if (type)
+       cp_error ("return type specification for destructor invalid");
+      type = void_type_node;
+      break;
+
+    case sfk_conversion:
+      if (type && !same_type_p (type, optype))
+       cp_error ("operator `%T' declared to return `%T'", optype, type);
+      else if (type)
+       cp_pedwarn ("return type specified for `operator %T'",  optype);
+      type = optype;
+      break;
+
+    default:
+      my_friendly_abort (20000408);
+      break;
+    }
+
+  return type;
+}
+
 /* Given declspecs and a declarator,
    determine the name and type of the object declared
    and construct a ..._DECL node for it.
@@ -9147,8 +9416,6 @@ create_array_type_for_decl (name, type, size)
    May return void_type_node if the declarator turned out to be a friend.
    See grokfield for details.  */
 
-enum return_types { return_normal, return_ctor, return_dtor, return_conversion };
-
 tree
 grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
      tree declspecs;
@@ -9187,7 +9454,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
   /* Keep track of what sort of function is being processed
      so that we can warn about default return values, or explicit
      return values which do not match prescribed defaults.  */
-  enum return_types return_type = return_normal;
+  special_function_kind sfk = sfk_none;
 
   tree dname = NULL_TREE;
   tree ctype = current_class_type;
@@ -9237,7 +9504,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
              my_friendly_assert (flags == NO_SPECIAL, 152);
              flags = DTOR_FLAG;
-             return_type = return_dtor;
+             sfk = sfk_destructor;
              if (TREE_CODE (name) == TYPE_DECL)
                TREE_OPERAND (decl, 0) = name = constructor_name (name);
              my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153);
@@ -9307,6 +9574,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
                decl = start_decl (declarator, declspecs, 1,
                                   attributes, prefix_attributes);
+               decl_type_access_control (decl);
                if (decl)
                  {
                    /* Look for __unused__ attribute */
@@ -9335,7 +9603,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                && decl != NULL_TREE && flags != DTOR_FLAG
                && decl == constructor_name (ctype))
              {
-               return_type = return_ctor;
+               sfk = sfk_constructor;
                ctor_return_type = ctype;
              }
            ctype = NULL_TREE;
@@ -9383,7 +9651,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                    my_friendly_assert (flags == NO_SPECIAL, 154);
                    flags = TYPENAME_FLAG;
                    ctor_return_type = TREE_TYPE (dname);
-                   return_type = return_conversion;
+                   sfk = sfk_conversion;
                  }
                name = operator_name_string (dname);
              }
@@ -9447,7 +9715,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                  if (TREE_CODE (decl) == IDENTIFIER_NODE
                      && constructor_name (ctype) == decl)
                    {
-                     return_type = return_ctor;
+                     sfk = sfk_constructor;
                      ctor_return_type = ctype;
                    }
                  else if (TREE_CODE (decl) == BIT_NOT_EXPR
@@ -9455,7 +9723,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                           && (constructor_name (ctype) == TREE_OPERAND (decl, 0)
                               || constructor_name_full (ctype) == TREE_OPERAND (decl, 0)))
                    {
-                     return_type = return_dtor;
+                     sfk = sfk_destructor;
                      ctor_return_type = ctype;
                      flags = DTOR_FLAG;
                      TREE_OPERAND (decl, 0) = constructor_name (ctype);
@@ -9604,7 +9872,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                  if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits))
                    {
                      if (pedantic && ! in_system_header && warn_long_long)
-                       pedwarn ("ANSI C++ does not support `long long'");
+                       pedwarn ("ISO C++ does not support `long long'");
                      if (longlong)
                        error ("`long long long' is too long for GCC");
                      else
@@ -9671,58 +9939,35 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
       defaulted_int = 1;
     }
 
-  if (type == NULL_TREE)
+  if (sfk != sfk_none)
+    type = check_special_function_return_type (sfk, type,
+                                              ctor_return_type,
+                                              ctor_return_type);
+  else if (type == NULL_TREE)
     {
+      int is_main;
+
       explicit_int = -1;
-      if (return_type == return_dtor)
-       type = void_type_node;
-      else if (return_type == return_ctor)
-       type = build_pointer_type (ctor_return_type);
-      else if (return_type == return_conversion)
-       type = ctor_return_type;
-      else
-       {
+
          /* We handle `main' specially here, because 'main () { }' is so
             common.  With no options, it is allowed.  With -Wreturn-type,
             it is a warning.  It is only an error with -pedantic-errors.  */
-         int is_main = (funcdef_flag
-                        && MAIN_NAME_P (dname)
-                        && ctype == NULL_TREE
-                        && in_namespace == NULL_TREE
-                        && current_namespace == global_namespace);
-
-         if (in_system_header || flag_ms_extensions)
-           /* Allow it, sigh.  */;
-         else if (pedantic || ! is_main)
-           cp_pedwarn ("ANSI C++ forbids declaration of `%s' with no type",
-                       name);
-         else if (warn_return_type)
-           cp_warning ("ANSI C++ forbids declaration of `%s' with no type",
-                       name);
+      is_main = (funcdef_flag
+                && MAIN_NAME_P (dname)
+                && ctype == NULL_TREE
+                && in_namespace == NULL_TREE
+                && current_namespace == global_namespace);
+
+      if (in_system_header || flag_ms_extensions)
+       /* Allow it, sigh.  */;
+      else if (pedantic || ! is_main)
+       cp_pedwarn ("ISO C++ forbids declaration of `%s' with no type",
+                   name);
+      else if (warn_return_type)
+       cp_warning ("ISO C++ forbids declaration of `%s' with no type",
+                   name);
 
-         type = integer_type_node;
-       }
-    }
-  else if (return_type == return_dtor)
-    {
-      error ("return type specification for destructor invalid");
-      type = void_type_node;
-    }
-  else if (return_type == return_ctor)
-    {
-      error ("return type specification for constructor invalid");
-      type = build_pointer_type (ctor_return_type);
-    }
-  else if (return_type == return_conversion)
-    {
-      if (!same_type_p (type, ctor_return_type))
-       cp_error ("operator `%T' declared to return `%T'",
-                 ctor_return_type, type);
-      else
-       cp_pedwarn ("return type specified for `operator %T'",
-                   ctor_return_type);
-
-      type = ctor_return_type;
+      type = integer_type_node;
     }
 
   ctype = NULL_TREE;
@@ -9867,7 +10112,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
        type = build_complex_type (type);
     }
 
-  if (return_type == return_conversion
+  if (sfk == sfk_conversion
       && (RIDBIT_SETP (RID_CONST, specbits)
          || RIDBIT_SETP (RID_VOLATILE, specbits)
          || RIDBIT_SETP (RID_RESTRICT, specbits)))
@@ -10164,7 +10409,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                && (friendp == 0 || dname == current_class_name))
              ctype = current_class_type;
 
-           if (ctype && return_type == return_conversion)
+           if (ctype && sfk == sfk_conversion)
              TYPE_HAS_CONVERSION (ctype) = 1;
            if (ctype && constructor_name (ctype) == dname)
              {
@@ -10175,9 +10420,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
                if (flags == DTOR_FLAG)
                  {
-                   /* ANSI C++ June 5 1992 WP 12.4.1.  A destructor may
-                      not be declared const or volatile.  A destructor
-                      may not be static.  */
+                   /* ISO C++ 12.4/2.  A destructor may not be
+                      declared const or volatile.  A destructor may
+                      not be static.  */
                    if (staticp == 2)
                      error ("destructor cannot be static member function");
                    if (quals)
@@ -10198,9 +10443,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                  {
                    if (explicitp == 1)
                      explicitp = 2;
-                   /* ANSI C++ June 5 1992 WP 12.1.2.  A constructor may
-                      not be declared const or volatile.  A constructor may
-                      not be virtual.  A constructor may not be static.  */
+                   /* ISO C++ 12.1.  A constructor may not be
+                      declared const or volatile.  A constructor may
+                      not be virtual.  A constructor may not be
+                      static.  */
                    if (staticp == 2)
                      error ("constructor cannot be static member function");
                    if (virtualp)
@@ -10222,7 +10468,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                      if (RIDBIT_ANY_SET (tmp_bits))
                        error ("return value type specifier for constructor ignored");
                    }
-                   type = build_pointer_type (ctype);
                    if (decl_context == FIELD)
                      {
                        if (! member_function_or_else (ctype,
@@ -10230,7 +10475,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                                                       flags))
                          return void_type_node;
                        TYPE_HAS_CONSTRUCTOR (ctype) = 1;
-                       if (return_type != return_ctor)
+                       if (sfk != sfk_constructor)
                          return NULL_TREE;
                      }
                  }
@@ -10461,9 +10706,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            t = ctype;
            while (t != NULL_TREE && CLASS_TYPE_P (t))
              {
-               if (CLASSTYPE_TEMPLATE_INFO (t) &&
-                   !CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
+               /* You're supposed to have one `template <...>' 
+                  for every template class, but you don't need one
+                  for a full specialization.  For example:
+
+                    template <class T> struct S{};
+                    template <> struct S<int> { void f(); };
+                    void S<int>::f () {}
+
+                  is correct; there shouldn't be a `template <>' for
+                  the definition of `S<int>::f'.  */
+               if (CLASSTYPE_TEMPLATE_INFO (t)
+                   && (CLASSTYPE_TEMPLATE_INSTANTIATION (t)
+                       || uses_template_parms (CLASSTYPE_TI_ARGS (t))))
                  template_count += 1;
+
                t = TYPE_MAIN_DECL (t);
                if (DECL_LANG_SPECIFIC (t))
                  t = DECL_CONTEXT (t);
@@ -10505,7 +10762,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                      }
                  }
                else if (RIDBIT_SETP (RID_TYPEDEF, specbits)
-                        || TYPE_SIZE (complete_type (ctype)) != NULL_TREE)
+                        || COMPLETE_TYPE_P (complete_type (ctype)))
                  {
                    /* Have to move this code elsewhere in this function.
                       this code is used for i.e., typedef int A::M; M *pm;
@@ -10655,7 +10912,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
       if (decl_context == FIELD)
        {
          if (declarator == constructor_name (current_class_type))
-           cp_pedwarn ("ANSI C++ forbids nested type `%D' with same name as enclosing class",
+           cp_pedwarn ("ISO C++ forbids nested type `%D' with same name as enclosing class",
                        declarator);
          decl = build_lang_decl (TYPE_DECL, declarator, type);
        }
@@ -10674,6 +10931,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
         Nothing can refer to it, so nothing needs know about the name
         change.  */
       if (type != error_mark_node
+         && declarator
          && TYPE_NAME (type)
          && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
          && ANON_AGGRNAME_P (TYPE_IDENTIFIER (type))
@@ -10726,7 +10984,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
          if (ctype == NULL_TREE)
            {
              if (TREE_CODE (type) != METHOD_TYPE)
-               cp_error_at ("invalid type qualifier for non-method type", decl);
+               cp_error_at ("invalid type qualifier for non-member function type", decl);
              else
                ctype = TYPE_METHOD_BASETYPE (type);
            }
@@ -10797,14 +11055,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
        }
       else if (quals)
        {
-         tree dummy = build_decl (TYPE_DECL, declarator, type);
          if (ctype == NULL_TREE)
            {
-             my_friendly_assert (TREE_CODE (type) == METHOD_TYPE, 159);
-             ctype = TYPE_METHOD_BASETYPE (type);
+             if (TREE_CODE (type) != METHOD_TYPE)
+               cp_error ("invalid qualifiers on non-member function type");
+             else
+               ctype = TYPE_METHOD_BASETYPE (type);
+           }
+         if (ctype)
+           {
+             tree dummy = build_decl (TYPE_DECL, declarator, type);
+             grok_method_quals (ctype, dummy, quals);
+             type = TREE_TYPE (dummy);
            }
-         grok_method_quals (ctype, dummy, quals);
-         type = TREE_TYPE (dummy);
        }
 
       return type;
@@ -10992,7 +11255,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                  TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)));
 
                /* Skip the `in_chrg' argument too, if present.  */
-               if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (decl)))
+               if (DECL_HAS_IN_CHARGE_PARM_P (decl))
                  arg_types = TREE_CHAIN (arg_types);
 
                if (arg_types == void_list_node
@@ -11017,7 +11280,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
              return NULL_TREE;
          }
        else if (!staticp && ! processing_template_decl
-                && TYPE_SIZE (complete_type (type)) == NULL_TREE
+                && !COMPLETE_TYPE_P (complete_type (type))
                 && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
          {
            if (declarator)
@@ -11042,7 +11305,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
          {
            if (friendp)
              {
-               error ("`%s' is neither function nor method; cannot be declared friend",
+               error ("`%s' is neither function nor member function; cannot be declared friend",
                       IDENTIFIER_POINTER (declarator));
                friendp = 0;
              }
@@ -11100,7 +11363,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                       the rest of the compiler does not correctly
                       handle the initialization unless the member is
                       static so we make it static below.  */
-                   cp_pedwarn ("ANSI C++ forbids initialization of member `%D'",
+                   cp_pedwarn ("ISO C++ forbids initialization of member `%D'",
                                declarator);
                    cp_pedwarn ("making `%D' static", declarator);
                    staticp = 1;
@@ -11125,7 +11388,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                   allow non-static data members here, because C does
                   and /usr/include/netinet/in.h uses that.  */
                && (staticp || ! in_system_header))
-             cp_pedwarn ("ANSI C++ forbids data member `%D' with same name as enclosing class",
+             cp_pedwarn ("ISO C++ forbids data member `%D' with same name as enclosing class",
                          declarator);
 
            if (staticp)
@@ -11337,7 +11600,7 @@ require_complete_types_for_parms (parms)
       if (type == error_mark_node)
        continue;
 
-      if (TYPE_SIZE (type) == NULL_TREE)
+      if (!COMPLETE_TYPE_P (type))
        {
          if (DECL_NAME (parms))
            error ("parameter `%s' has incomplete type",
@@ -11710,8 +11973,7 @@ copy_args_p (d)
     return 0;
 
   t = FUNCTION_ARG_CHAIN (d);
-  if (DECL_CONSTRUCTOR_P (d)
-      && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (d)))
+  if (DECL_CONSTRUCTOR_P (d) && DECL_HAS_IN_CHARGE_PARM_P (d))
     t = TREE_CHAIN (t);
   if (t && TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE
       && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (t)))
@@ -11742,7 +12004,7 @@ grok_ctor_properties (ctype, decl)
      added to any ctor so we can tell if the class has been initialized
      yet.  This could screw things up in this function, so we deliberately
      ignore the leading int if we're in that situation.  */
-  if (TYPE_USES_VIRTUAL_BASECLASSES (ctype))
+  if (DECL_HAS_IN_CHARGE_PARM_P (decl))
     {
       my_friendly_assert (parmtypes
                          && TREE_VALUE (parmtypes) == integer_type_node,
@@ -11863,11 +12125,11 @@ grok_op_properties (decl, virtualp, friendp)
               || name == ansi_opname[(int) MEMBER_REF])
        TYPE_OVERLOADS_ARROW (current_class_type) = 1;
       else if (name == ansi_opname[(int) NEW_EXPR])
-       TYPE_GETS_NEW (current_class_type) |= 1;
+       TYPE_HAS_NEW_OPERATOR (current_class_type) = 1;
       else if (name == ansi_opname[(int) DELETE_EXPR])
        TYPE_GETS_DELETE (current_class_type) |= 1;
       else if (name == ansi_opname[(int) VEC_NEW_EXPR])
-       TYPE_GETS_NEW (current_class_type) |= 2;
+       TYPE_HAS_ARRAY_NEW_OPERATOR (current_class_type) = 1;
       else if (name == ansi_opname[(int) VEC_DELETE_EXPR])
        TYPE_GETS_DELETE (current_class_type) |= 2;
     }
@@ -11878,7 +12140,7 @@ grok_op_properties (decl, virtualp, friendp)
       /* When the compiler encounters the definition of A::operator new, it
         doesn't look at the class declaration to find out if it's static.  */
       if (methodp)
-       revert_static_member_fn (&decl, NULL, NULL);
+       revert_static_member_fn (decl);
 
       /* Take care of function decl if we had syntax errors.  */
       if (argtypes == NULL_TREE)
@@ -11893,7 +12155,7 @@ grok_op_properties (decl, virtualp, friendp)
           || name == ansi_opname[(int) VEC_DELETE_EXPR])
     {
       if (methodp)
-       revert_static_member_fn (&decl, NULL, NULL);
+       revert_static_member_fn (decl);
 
       if (argtypes == NULL_TREE)
        TREE_TYPE (decl)
@@ -11901,14 +12163,7 @@ grok_op_properties (decl, virtualp, friendp)
                                 hash_tree_chain (ptr_type_node,
                                                  void_list_node));
       else
-       {
-         TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
-
-         if (! friendp && name == ansi_opname[(int) VEC_DELETE_EXPR]
-             && (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)))
-                 != void_list_node))
-           TYPE_VEC_DELETE_TAKES_SIZE (current_class_type) = 1;
-       }
+       TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
     }
   else
     {
@@ -11958,20 +12213,21 @@ grok_op_properties (decl, virtualp, friendp)
       if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
        {
          tree t = TREE_TYPE (name);
-         if (TREE_CODE (t) == VOID_TYPE)
-           pedwarn ("void is not a valid type conversion operator");
-         else if (! friendp)
+         if (! friendp)
            {
              int ref = (TREE_CODE (t) == REFERENCE_TYPE);
              const char *what = 0;
+             
              if (ref)
                t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
 
-             if (t == current_class_type)
+             if (TREE_CODE (t) == VOID_TYPE)
+               what = "void";
+             else if (t == current_class_type)
                what = "the same type";
              /* Don't force t to be complete here.  */
              else if (IS_AGGR_TYPE (t)
-                      && TYPE_SIZE (t)
+                      && COMPLETE_TYPE_P (t)
                       && DERIVED_FROM_P (t, current_class_type))
                what = "a base class";
 
@@ -12004,7 +12260,7 @@ grok_op_properties (decl, virtualp, friendp)
       else if (name == ansi_opname[(int) COND_EXPR])
        {
          /* 13.4.0.3 */
-         cp_error ("ANSI C++ prohibits overloading operator ?:");
+         cp_error ("ISO C++ prohibits overloading operator ?:");
        }
       else if (ambi_op_p (name))
        {
@@ -12169,7 +12425,7 @@ xref_tag (code_type_node, name, globalize)
       code_type_node = TREE_VALUE (code_type_node);
     }
 
-  tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
+  tag_code = (enum tag_types) tree_low_cst (code_type_node, 1);
   switch (tag_code)
     {
     case record_type:
@@ -12188,7 +12444,7 @@ xref_tag (code_type_node, name, globalize)
 
   /* If a cross reference is requested, look up the type
      already defined for this tag and return it.  */
-  if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
+  if (TYPE_P (name))
     {
       t = name;
       name = TYPE_IDENTIFIER (t);
@@ -12239,7 +12495,7 @@ xref_tag (code_type_node, name, globalize)
              && template_class_depth (current_class_type) == 0)
            /* Since GLOBALIZE is true, we're declaring a global
               template, so we want this type.  */
-           ref = DECL_RESULT (ref);
+           ref = DECL_TEMPLATE_RESULT (ref);
 
          if (ref && TREE_CODE (ref) == TYPE_DECL
              && TREE_CODE (TREE_TYPE (ref)) == code)
@@ -12344,7 +12600,7 @@ xref_tag (code_type_node, name, globalize)
 
   /* Until the type is defined, tentatively accept whatever
      structure tag the user hands us.  */
-  if (TYPE_SIZE (ref) == NULL_TREE
+  if (!COMPLETE_TYPE_P (ref)
       && ref != current_class_type
       /* Have to check this, in case we have contradictory tag info.  */
       && IS_AGGR_TYPE_CODE (TREE_CODE (ref)))
@@ -12397,7 +12653,7 @@ xref_basetypes (code_type_node, name, ref, binfo)
   tree base;
 
   int i, len;
-  enum tag_types tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
+  enum tag_types tag_code = (enum tag_types) tree_low_cst (code_type_node, 1);
 
   if (tag_code == union_type)
     {
@@ -12454,7 +12710,7 @@ xref_basetypes (code_type_node, name, ref, binfo)
 
       /* This code replaces similar code in layout_basetypes.
          We put the complete_type first for implicit `typename'.  */
-      if (TYPE_SIZE (basetype) == NULL_TREE
+      if (!COMPLETE_TYPE_P (basetype)
          && ! (current_template_parms && uses_template_parms (basetype)))
        {
          cp_error ("base class `%T' has incomplete type", basetype);
@@ -12485,7 +12741,7 @@ xref_basetypes (code_type_node, name, ref, binfo)
             the `accessibility' of that particular inheritance is.)  */
 
          base_binfo
-           = make_binfo (integer_zero_node, basetype,
+           = make_binfo (size_zero_node, basetype,
                          CLASS_TYPE_P (basetype)
                          ? TYPE_BINFO_VTABLE (basetype) : NULL_TREE,
                          CLASS_TYPE_P (basetype)
@@ -12515,7 +12771,10 @@ xref_basetypes (code_type_node, name, ref, binfo)
 
          if (CLASS_TYPE_P (basetype))
            {
-             TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
+             TYPE_HAS_NEW_OPERATOR (ref) 
+               |= TYPE_HAS_NEW_OPERATOR (basetype);
+             TYPE_HAS_ARRAY_NEW_OPERATOR (ref) 
+               |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
              TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
              /* If the base-class uses multiple inheritance, so do we.  */
              TYPE_USES_MULTIPLE_INHERITANCE (ref)
@@ -12778,10 +13037,9 @@ build_enumerator (name, value, enumtype)
              /* The next value is the previous value ... */
              prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
              /* ... plus one.  */
-             value = build_binary_op_nodefault (PLUS_EXPR,
-                                                prev_value,
-                                                integer_one_node,
-                                                PLUS_EXPR);
+             value = build_binary_op (PLUS_EXPR,
+                                      prev_value,
+                                      integer_one_node);
 
              if (tree_int_cst_lt (value, prev_value))
                cp_error ("overflow in enumeration values at `%D'", name);
@@ -12867,11 +13125,12 @@ check_function_type (decl)
      tree decl;
 {
   tree fntype = TREE_TYPE (decl);
+  tree return_type = complete_type (TREE_TYPE (fntype));
 
   /* In a function definition, arg types must be complete.  */
   require_complete_types_for_parms (current_function_parms);
 
-  if (TYPE_SIZE (complete_type (TREE_TYPE (fntype))) == NULL_TREE)
+  if (!COMPLETE_OR_VOID_TYPE_P (return_type))
     {
       cp_error ("return type `%#T' is incomplete", TREE_TYPE (fntype));
 
@@ -12954,9 +13213,8 @@ start_function (declspecs, declarator, attrs, flags)
       if (TREE_CODE (fntype) == METHOD_TYPE)
        ctype = TYPE_METHOD_BASETYPE (fntype);
 
-      /* ANSI C++ June 5 1992 WP 11.4.5.  A friend function defined in a
-        class is in the (lexical) scope of the class in which it is
-        defined.  */
+      /* ISO C++ 11.4/5.  A friend function defined in a class is in
+        the (lexical) scope of the class in which it is defined.  */
       if (!ctype && DECL_FRIEND_P (decl1))
        {
          ctype = DECL_FRIEND_CONTEXT (decl1);
@@ -13017,7 +13275,7 @@ start_function (declspecs, declarator, attrs, flags)
   if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1)
       && TREE_CODE (TREE_TYPE (decl1)) == METHOD_TYPE)
     {
-      revert_static_member_fn (&decl1, NULL, NULL);
+      revert_static_member_fn (decl1);
       last_function_parms = TREE_CHAIN (last_function_parms);
       ctype = NULL_TREE;
     }
@@ -13142,7 +13400,6 @@ start_function (declspecs, declarator, attrs, flags)
          /* And make sure we have enough default args.  */
          check_default_args (decl1);
        }
-      DECL_MAIN_VARIANT (decl1) = decl1;
       fntype = TREE_TYPE (decl1);
     }
 
@@ -13191,13 +13448,7 @@ start_function (declspecs, declarator, attrs, flags)
 
       /* Constructors and destructors need to know whether they're "in
         charge" of initializing virtual base classes.  */
-      if (DECL_DESTRUCTOR_P (decl1))
-       current_in_charge_parm = TREE_CHAIN (t);
-      else if (DECL_CONSTRUCTOR_P (decl1)
-              && TREE_CHAIN (t)
-              && DECL_ARTIFICIAL (TREE_CHAIN (t))
-              && (DECL_NAME (TREE_CHAIN (t))
-                  == in_charge_identifier))
+      if (DECL_HAS_IN_CHARGE_PARM_P (decl1))
        current_in_charge_parm = TREE_CHAIN (t);
     }
 
@@ -13306,7 +13557,12 @@ start_function (declspecs, declarator, attrs, flags)
       dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
       DECL_CONTEXT (dtor_label) = current_function_decl;
     }
-  else if (DECL_CONSTRUCTOR_P (decl1))
+  /* Under the old ABI we return `this' from constructors, so we make
+     ordinary `return' statements in constructors jump to CTOR_LABEL;
+     from there we return `this'.  Under the new ABI, we don't bother
+     with any of this.  By not setting CTOR_LABEL the remainder of the
+     machinery is automatically disabled.  */
+  else if (!flag_new_abi && DECL_CONSTRUCTOR_P (decl1))
     {
       ctor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
       DECL_CONTEXT (ctor_label) = current_function_decl;
@@ -13396,7 +13652,7 @@ store_parm_decls ()
                    cleanups = tree_cons (parm, cleanup, cleanups);
                }
              else if (type != error_mark_node
-                      && TYPE_NEEDS_DESTRUCTOR (type))
+                      && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
                parms_have_cleanups = 1;
            }
          else
@@ -13461,6 +13717,7 @@ store_parm_decls ()
 
   /* Do the starting of the exception specifications, if we have any.  */
   if (flag_exceptions && !processing_template_decl
+      && flag_enforce_eh_specs
       && building_stmt_tree ()
       && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
     current_eh_spec_try_block = expand_start_eh_spec ();
@@ -13537,7 +13794,8 @@ static void
 finish_constructor_body ()
 {
   /* Any return from a constructor will end up here.  */
-  add_tree (build_min_nt (LABEL_STMT, ctor_label));
+  if (ctor_label)
+    add_tree (build_min_nt (LABEL_STMT, ctor_label));
 
   /* Clear CTOR_LABEL so that finish_return_stmt knows to really
      generate the return, rather than a goto to CTOR_LABEL.  */
@@ -13557,9 +13815,9 @@ static void
 finish_destructor_body ()
 {
   tree compound_stmt;
-  tree in_charge;
   tree virtual_size;
   tree exprstmt;
+  tree if_stmt;
 
   /* Create a block to contain all the extra code.  */
   compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
@@ -13577,16 +13835,9 @@ finish_destructor_body ()
      will set the flag again.  */
   TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
 
-  /* These are two cases where we cannot delegate deletion.  */
-  if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)
-      || TYPE_GETS_REG_DELETE (current_class_type))
-    in_charge = integer_zero_node;
-  else
-    in_charge = current_in_charge_parm;
-
   exprstmt = build_delete (current_class_type,
                           current_class_ref,
-                          in_charge,
+                          integer_zero_node,
                           LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
                           0);
 
@@ -13612,15 +13863,15 @@ finish_destructor_body ()
 
          while (vbases)
            {
-             if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
+             if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (vbases)))
                {
                  tree vb = get_vbase
                    (BINFO_TYPE (vbases),
                     TYPE_BINFO (current_class_type));
                  finish_expr_stmt
                    (build_scoped_method_call
-                    (current_class_ref, vb, dtor_identifier,
-                     build_tree_list (NULL_TREE, integer_zero_node)));
+                    (current_class_ref, vb, complete_dtor_identifier,
+                     NULL_TREE));
                }
              vbases = TREE_CHAIN (vbases);
            }
@@ -13643,24 +13894,18 @@ finish_destructor_body ()
      only defines placement deletes we don't do anything here.  So we
      pass LOOKUP_SPECULATIVELY; delete_sanity will complain for us if
      they ever try to delete one of these.  */
-  if (TYPE_GETS_REG_DELETE (current_class_type)
-      || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
-    {
-      tree if_stmt;
-
-      exprstmt = build_op_delete_call
-       (DELETE_EXPR, current_class_ptr, virtual_size,
-        LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
-
-      if_stmt = begin_if_stmt ();
-      finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
-                                 current_in_charge_parm,
-                                 integer_one_node),
-                          if_stmt);
-      finish_expr_stmt (exprstmt);
-      finish_then_clause (if_stmt);
-      finish_if_stmt ();
-    }
+  exprstmt = build_op_delete_call
+    (DELETE_EXPR, current_class_ptr, virtual_size,
+     LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
+
+  if_stmt = begin_if_stmt ();
+  finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
+                             current_in_charge_parm,
+                             integer_one_node),
+                      if_stmt);
+  finish_expr_stmt (exprstmt);
+  finish_then_clause (if_stmt);
+  finish_if_stmt ();
 
   /* Close the block we started above.  */
   finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
@@ -13670,9 +13915,6 @@ finish_destructor_body ()
    all the way to assembler language output.  The free the storage
    for the function definition.
 
-   This is called after parsing the body of the function definition.
-   LINENO is the current line number.
-
    FLAGS is a bitwise or of the following values:
      1 - CALL_POPLEVEL
        An extra call to poplevel (and expand_end_bindings) must be
@@ -13684,8 +13926,7 @@ finish_destructor_body ()
        after the class definition is complete.)  */
 
 tree
-finish_function (lineno, flags)
-     int lineno;
+finish_function (flags)
      int flags;
 {
   register tree fndecl = current_function_decl;
@@ -13696,6 +13937,7 @@ finish_function (lineno, flags)
   int inclass_inline = (flags & 2) != 0;
   int expand_p;
   int nested;
+  int current_line = lineno;
 
   /* When we get some parse errors, we can end up without a
      current_function_decl, so cope.  */
@@ -13716,7 +13958,11 @@ finish_function (lineno, flags)
       store_parm_decls ();
     }
 
-  if (building_stmt_tree ())
+  /* For a cloned function, we've already got all the code we need;
+     there's no need to add any extra bits.  */
+  if (building_stmt_tree () && DECL_CLONED_FUNCTION_P (fndecl))
+    ;
+  else if (building_stmt_tree ())
     {
       if (DECL_CONSTRUCTOR_P (fndecl))
        {
@@ -13738,6 +13984,7 @@ finish_function (lineno, flags)
 
       /* Finish dealing with exception specifiers.  */
       if (flag_exceptions && !processing_template_decl
+         && flag_enforce_eh_specs
          && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
        expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS
                            (TREE_TYPE (current_function_decl)),
@@ -13809,7 +14056,7 @@ finish_function (lineno, flags)
          DECL_CONTEXT (no_return_label) = fndecl;
          DECL_INITIAL (no_return_label) = error_mark_node;
          DECL_SOURCE_FILE (no_return_label) = input_filename;
-         DECL_SOURCE_LINE (no_return_label) = lineno;
+         DECL_SOURCE_LINE (no_return_label) = current_line;
          expand_goto (no_return_label);
        }
 
@@ -13848,7 +14095,7 @@ finish_function (lineno, flags)
       immediate_size_expand = 1;
 
       /* Generate rtl for function exit.  */
-      expand_function_end (input_filename, lineno, 1);
+      expand_function_end (input_filename, current_line, 1);
     }
 
   /* We have to save this value here in case
@@ -13901,21 +14148,10 @@ finish_function (lineno, flags)
     {
       int returns_null;
       int returns_value;
-      int saved_flag_keep_inline_functions =
-       flag_keep_inline_functions;
 
       /* So we can tell if jump_optimize sets it to 1.  */
       can_reach_end = 0;
 
-      if (DECL_CONTEXT (fndecl) != NULL_TREE
-         && decl_function_context (fndecl))
-       /* Trick rest_of_compilation into not deferring output of this
-          function, even if it is inline, since the rtl_obstack for
-          this function is the function_obstack of the enclosing
-          function and will be deallocated when the enclosing
-          function is gone.  See save_tree_status.  */
-       flag_keep_inline_functions = 1;
-
       /* Before we call rest_of_compilation (which will pop the
         CURRENT_FUNCTION), we must save these values.  */
       returns_null = current_function_returns_null;
@@ -13952,8 +14188,6 @@ finish_function (lineno, flags)
       if (function_depth > 1)
        ggc_pop_context ();
 
-      flag_keep_inline_functions = saved_flag_keep_inline_functions;
-
       if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
        {
          /* Set DECL_EXTERNAL so that assemble_external will be called as
@@ -13961,7 +14195,7 @@ finish_function (lineno, flags)
          if (! DECL_EXTERNAL (fndecl))
            DECL_NOT_REALLY_EXTERN (fndecl) = 1;
          DECL_EXTERNAL (fndecl) = 1;
-         mark_inline_for_output (fndecl);
+         defer_fn (fndecl);
        }
 
 #if 0
@@ -14116,12 +14350,6 @@ start_method (declspecs, declarator, attrlist)
   if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
     fndecl = push_template_decl (fndecl);
 
-  /* We read in the parameters on the maybepermanent_obstack,
-     but we won't be getting back to them until after we
-     may have clobbered them.  So the call to preserve_data
-     will keep them safe.  */
-  preserve_data ();
-
   if (! DECL_FRIEND_P (fndecl))
     {
       if (TREE_CHAIN (fndecl))
@@ -14285,17 +14513,14 @@ hack_incomplete_structures (type)
 }
 
 /* If DECL is of a type which needs a cleanup, build that cleanup here.
-   See build_delete for information about AUTO_DELETE.
-
-   Don't build these on the momentary obstack; they must live
-   the life of the binding contour.  */
+   See build_delete for information about AUTO_DELETE.  */
 
 static tree
 maybe_build_cleanup_1 (decl, auto_delete)
      tree decl, auto_delete;
 {
   tree type = TREE_TYPE (decl);
-  if (type != error_mark_node && TYPE_NEEDS_DESTRUCTOR (type))
+  if (type != error_mark_node && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
     {
       int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
       tree rval;
@@ -14326,16 +14551,6 @@ maybe_build_cleanup_1 (decl, auto_delete)
 }
 
 /* If DECL is of a type which needs a cleanup, build that cleanup
-   here.  The cleanup does free the storage with a call to delete.  */
-
-tree
-maybe_build_cleanup_and_delete (decl)
-     tree decl;
-{
-  return maybe_build_cleanup_1 (decl, integer_three_node);
-}
-
-/* If DECL is of a type which needs a cleanup, build that cleanup
    here.  The cleanup does not free the storage with a call a delete.  */
 
 tree
@@ -14357,9 +14572,6 @@ void
 cplus_expand_expr_stmt (exp)
      tree exp;
 {
-  if (stmts_are_full_exprs_p)
-    exp = convert_to_void (exp, "statement");
-
 #if 0
   /* We should do this eventually, but right now this causes regex.o from
      libg++ to miscompile, and tString to core dump.  */
@@ -14384,20 +14596,16 @@ finish_stmt ()
   last_expr_type = NULL_TREE;
 }
 
-/* Change a static member function definition into a FUNCTION_TYPE, instead
-   of the METHOD_TYPE that we create when it's originally parsed.
-
-   WARNING: DO NOT pass &TREE_TYPE (decl) to FN or &TYPE_ARG_TYPES
-   (TREE_TYPE (decl)) to ARGTYPES, as doing so will corrupt the types of
-   other decls.  Either pass the addresses of local variables or NULL.  */
+/* DECL was originally constructed as a non-static member function,
+   but turned out to be static.  Update it accordingly.  */
 
 void
-revert_static_member_fn (decl, fn, argtypes)
-     tree *decl, *fn, *argtypes;
+revert_static_member_fn (decl)
+     tree decl;
 {
   tree tmp;
-  tree function = fn ? *fn : TREE_TYPE (*decl);
-  tree args = argtypes ? *argtypes : TYPE_ARG_TYPES (function);
+  tree function = TREE_TYPE (decl);
+  tree args = TYPE_ARG_TYPES (function);
 
   if (CP_TYPE_QUALS (TREE_TYPE (TREE_VALUE (args)))
       != TYPE_UNQUALIFIED)
@@ -14409,14 +14617,10 @@ revert_static_member_fn (decl, fn, argtypes)
   tmp = build_qualified_type (tmp, CP_TYPE_QUALS (function));
   tmp = build_exception_variant (tmp,
                                 TYPE_RAISES_EXCEPTIONS (function));
-  TREE_TYPE (*decl) = tmp;
-  if (DECL_ARGUMENTS (*decl))
-    DECL_ARGUMENTS (*decl) = TREE_CHAIN (DECL_ARGUMENTS (*decl));
-  DECL_STATIC_FUNCTION_P (*decl) = 1;
-  if (fn)
-    *fn = tmp;
-  if (argtypes)
-    *argtypes = args;
+  TREE_TYPE (decl) = tmp;
+  if (DECL_ARGUMENTS (decl))
+    DECL_ARGUMENTS (decl) = TREE_CHAIN (DECL_ARGUMENTS (decl));
+  DECL_STATIC_FUNCTION_P (decl) = 1;
 }
 
 /* Initialize the variables used during compilation of a C++
@@ -14486,13 +14690,6 @@ mark_cp_function_context (f)
   mark_lang_function (f->language);
 }
 
-int
-in_function_p ()
-{
-  return function_depth != 0;
-}
-
-
 void
 lang_mark_false_label_stack (l)
      struct label_node *l;
@@ -14550,9 +14747,9 @@ lang_mark_tree (t)
            mark_binding_level (&NAMESPACE_LEVEL (t));
          if (CAN_HAVE_FULL_LANG_DECL_P (t))
            {
-             ggc_mark_tree (ld->main_decl_variant);
              ggc_mark_tree (ld->befriending_classes);
              ggc_mark_tree (ld->saved_tree);
+             ggc_mark_tree (ld->cloned_function);
              if (TREE_CODE (t) == TYPE_DECL)
                ggc_mark_tree (ld->u.sorted_fields);
              else if (TREE_CODE (t) == FUNCTION_DECL