OSDN Git Service

* decl.c (decls_match): Allow a redeclaration of a builtin to
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index 2471090..2760ea5 100644 (file)
@@ -1,5 +1,6 @@
 /* Process declarations and variables for C compiler.
-   Copyright (C) 1988, 92-98, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+   Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GNU CC.
@@ -36,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"
@@ -45,18 +45,13 @@ 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;
 
 extern tree global_namespace;
 
-extern int (*valid_lang_attribute) PROTO ((tree, tree, tree, tree));
+extern int (*valid_lang_attribute) PARAMS ((tree, tree, tree, tree));
 
 /* Use garbage collection.  */
 
@@ -99,91 +94,95 @@ int ggc_p = 1;
 #define WCHAR_TYPE "int"
 #endif
 
-static tree grokparms                          PROTO((tree, int));
-static const char *redeclaration_error_message PROTO((tree, tree));
+static tree grokparms                          PARAMS ((tree, int));
+static const char *redeclaration_error_message PARAMS ((tree, tree));
 
-static void push_binding_level PROTO((struct binding_level *, int,
+static void push_binding_level PARAMS ((struct binding_level *, int,
                                      int));
-static void pop_binding_level PROTO((void));
-static void suspend_binding_level PROTO((void));
-static void resume_binding_level PROTO((struct binding_level *));
-static struct binding_level *make_binding_level PROTO((void));
-static void declare_namespace_level PROTO((void));
-static void signal_catch PROTO((int)) ATTRIBUTE_NORETURN;
-static void storedecls PROTO((tree));
-static void require_complete_types_for_parms PROTO((tree));
-static void push_overloaded_decl_1 PROTO((tree));
-static int ambi_op_p PROTO((tree));
-static int unary_op_p PROTO((tree));
-static tree store_bindings PROTO((tree, tree));
-static tree lookup_tag_reverse PROTO((tree, tree));
-static tree obscure_complex_init PROTO((tree, tree));
-static tree maybe_build_cleanup_1 PROTO((tree, tree));
-static tree lookup_name_real PROTO((tree, int, int, int));
-static void warn_extern_redeclared_static PROTO((tree, tree));
-static void grok_reference_init PROTO((tree, tree, tree));
-static tree grokfndecl PROTO((tree, tree, tree, tree, int,
+static void pop_binding_level PARAMS ((void));
+static void suspend_binding_level PARAMS ((void));
+static void resume_binding_level PARAMS ((struct binding_level *));
+static struct binding_level *make_binding_level PARAMS ((void));
+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 int ambi_op_p PARAMS ((tree));
+static int unary_op_p PARAMS ((tree));
+static tree store_bindings PARAMS ((tree, tree));
+static tree lookup_tag_reverse PARAMS ((tree, tree));
+static tree obscure_complex_init PARAMS ((tree, tree));
+static tree maybe_build_cleanup_1 PARAMS ((tree, tree));
+static tree lookup_name_real PARAMS ((tree, int, int, int));
+static void warn_extern_redeclared_static PARAMS ((tree, tree));
+static void grok_reference_init PARAMS ((tree, tree, tree));
+static tree grokfndecl PARAMS ((tree, tree, tree, tree, int,
                              enum overload_flags, tree,
                              tree, int, int, int, int, int, int, tree));
-static tree grokvardecl PROTO((tree, tree, RID_BIT_TYPE *, int, int, tree));
-static tree lookup_tag PROTO((enum tree_code, tree,
+static tree grokvardecl PARAMS ((tree, tree, RID_BIT_TYPE *, int, int, tree));
+static tree lookup_tag PARAMS ((enum tree_code, tree,
                              struct binding_level *, int));
 static void set_identifier_type_value_with_scope
-       PROTO((tree, tree, struct binding_level *));
-static void record_builtin_type PROTO((enum rid, const char *, tree));
-static void record_unknown_type PROTO((tree, const char *));
-static int member_function_or_else PROTO((tree, tree, const char *));
-static void bad_specifiers PROTO((tree, const char *, int, int, int, int,
+       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));
-static void lang_print_error_function PROTO((const char *));
-static tree maybe_process_template_type_declaration PROTO((tree, int, struct binding_level*));
-static void check_for_uninitialized_const_var PROTO((tree));
-static unsigned long typename_hash PROTO((hash_table_key));
-static boolean typename_compare PROTO((hash_table_key, hash_table_key));
-static void push_binding PROTO((tree, tree, struct binding_level*));
-static int add_binding PROTO((tree, tree));
-static void pop_binding PROTO((tree, tree));
-static tree local_variable_p_walkfn PROTO((tree *, int *, void *));
-static tree find_binding PROTO((tree, tree));
-static tree select_decl PROTO((tree, int));
-static int lookup_flags PROTO((int, int));
-static tree qualify_lookup PROTO((tree, int));
-static tree record_builtin_java_type PROTO((const char *, int));
-static const char *tag_name PROTO((enum tag_types code));
-static void find_class_binding_level PROTO((void));
-static struct binding_level *innermost_nonclass_level PROTO((void));
-static void warn_about_implicit_typename_lookup PROTO((tree, tree));
-static int walk_namespaces_r PROTO((tree, walk_namespaces_fn, void *));
-static int walk_globals_r PROTO((tree, void *));
-static void add_decl_to_level PROTO((tree, struct binding_level *));
-static tree make_label_decl PROTO((tree, int));
-static void pop_label PROTO((tree));
-static void pop_labels PROTO((tree));
-static void maybe_deduce_size_from_array_init PROTO((tree, tree));
-static void layout_var_decl PROTO((tree));
-static void maybe_commonize_var PROTO((tree));
-static tree check_initializer PROTO((tree, tree));
-static void make_rtl_for_nonlocal_decl PROTO((tree, tree, const char *));
-static void push_cp_function_context PROTO((struct function *));
-static void pop_cp_function_context PROTO((struct function *));
-static void mark_binding_level PROTO((void *));
-static void mark_cp_function_context PROTO((struct function *));
-static void mark_saved_scope PROTO((void *));
-static void mark_lang_function PROTO((struct language_function *));
-static void mark_stmt_tree PROTO((struct stmt_tree *));
-static void save_function_data PROTO((tree));
-static void check_function_type PROTO((tree));
-static void destroy_local_var PROTO((tree));
-static void finish_constructor_body PROTO((void));
-static void finish_destructor_body PROTO((void));
-static tree create_array_type_for_decl PROTO((tree, tree, tree));
-static tree get_atexit_node PROTO((void));
-static tree get_dso_handle_node PROTO((void));
-static tree start_cleanup_fn PROTO((void));
-static void end_cleanup_fn PROTO((void));
+static void lang_print_error_function PARAMS ((const char *));
+static tree maybe_process_template_type_declaration PARAMS ((tree, int, struct binding_level*));
+static void check_for_uninitialized_const_var PARAMS ((tree));
+static unsigned long typename_hash PARAMS ((hash_table_key));
+static boolean typename_compare PARAMS ((hash_table_key, hash_table_key));
+static void push_binding PARAMS ((tree, tree, struct binding_level*));
+static int add_binding PARAMS ((tree, tree));
+static void pop_binding PARAMS ((tree, tree));
+static tree local_variable_p_walkfn PARAMS ((tree *, int *, void *));
+static tree find_binding PARAMS ((tree, tree));
+static tree select_decl PARAMS ((tree, int));
+static int lookup_flags PARAMS ((int, int));
+static tree qualify_lookup PARAMS ((tree, int));
+static tree record_builtin_java_type PARAMS ((const char *, int));
+static const char *tag_name PARAMS ((enum tag_types code));
+static void find_class_binding_level PARAMS ((void));
+static struct binding_level *innermost_nonclass_level PARAMS ((void));
+static void warn_about_implicit_typename_lookup PARAMS ((tree, tree));
+static int walk_namespaces_r PARAMS ((tree, walk_namespaces_fn, void *));
+static int walk_globals_r PARAMS ((tree, void *));
+static void add_decl_to_level PARAMS ((tree, struct binding_level *));
+static tree make_label_decl PARAMS ((tree, int));
+static void pop_label PARAMS ((tree));
+static void pop_labels PARAMS ((tree));
+static void maybe_deduce_size_from_array_init PARAMS ((tree, tree));
+static void layout_var_decl PARAMS ((tree));
+static void maybe_commonize_var PARAMS ((tree));
+static tree check_initializer PARAMS ((tree, tree));
+static void make_rtl_for_nonlocal_decl PARAMS ((tree, tree, const char *));
+static void push_cp_function_context PARAMS ((struct function *));
+static void pop_cp_function_context PARAMS ((struct function *));
+static void mark_binding_level PARAMS ((void *));
+static void mark_cp_function_context PARAMS ((struct function *));
+static void mark_saved_scope PARAMS ((void *));
+static void mark_lang_function PARAMS ((struct language_function *));
+static void mark_stmt_tree PARAMS ((struct stmt_tree *));
+static void save_function_data PARAMS ((tree));
+static void check_function_type PARAMS ((tree));
+static void destroy_local_var PARAMS ((tree));
+static void finish_constructor_body PARAMS ((void));
+static void finish_destructor_body PARAMS ((void));
+static tree create_array_type_for_decl PARAMS ((tree, tree, tree));
+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 PROTO((void));
+static void indent PARAMS ((void));
 #endif
 
 /* Erroneous argument lists can use this *IFF* they do not modify it.  */
@@ -208,10 +207,12 @@ tree error_mark_list;
 #if 0
        tree __tp_desc_type_node;
 #endif
-       tree __access_mode_type_node;
-       tree __bltn_desc_type_node, __user_desc_type_node, __class_desc_type_node;
-       tree __ptr_desc_type_node, __attr_desc_type_node, __func_desc_type_node;
-       tree __ptmf_desc_type_node, __ptmd_desc_type_node;
+        tree ti_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;
+       tree base_desc_type_node;
 #if 0
    Not needed yet?  May be needed one day?
        tree __bltn_desc_array_type, __user_desc_array_type, __class_desc_array_type;
@@ -219,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;
 
@@ -228,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
@@ -243,7 +244,8 @@ tree error_mark_list;
        tree global_delete_fndecl;
 
    Used by RTTI
-       tree type_info_type_node, tinfo_fn_id, tinfo_fn_type;
+       tree type_info_type_node, tinfo_decl_id, tinfo_decl_type;
+       tree tinfo_var_id;
 
 */
 
@@ -310,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
@@ -321,9 +319,9 @@ tree current_function_decl;
 
 tree current_function_return_value;
 
-/* Nonzero means use the ISO C9x dialect of C.  */
+/* Nonzero means use the ISO C99 dialect of C.  */
 
-int flag_isoc9x;
+int flag_isoc99;
 
 /* Nonzero means give `double' the same size as `float'.  */
 
@@ -338,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
@@ -439,6 +433,9 @@ struct binding_level
        If 0, the BLOCK is allocated (if needed) when the level is popped.  */
     tree this_block;
 
+    /* The _TYPE node for this level, if parm_flag == 2.  */
+    tree this_class;
+
     /* The binding level which this one is contained in (inherits from).  */
     struct binding_level *level_chain;
 
@@ -447,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;
@@ -469,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.  */
@@ -533,7 +534,7 @@ indent ()
 }
 #endif /* defined(DEBUG_CP_BINDING_LEVELS) */
 
-static tree pushdecl_with_scope        PROTO((tree, struct binding_level *));
+static tree pushdecl_with_scope        PARAMS ((tree, struct binding_level *));
 
 static void
 push_binding_level (newlevel, tag_transparent, keep)
@@ -701,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
@@ -747,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->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;
 {
-  return current_binding_level->pseudo_global;
+  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
@@ -803,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 ()
 {
@@ -999,12 +1118,11 @@ push_class_binding (id, decl)
       else
        {
          if (TREE_CODE (decl) == OVERLOAD)
-           context = DECL_REAL_CONTEXT (OVL_CURRENT (decl));
+           context = CP_DECL_CONTEXT (OVL_CURRENT (decl));
          else
            {
-             my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd',
-                                 0);
-             context = DECL_REAL_CONTEXT (decl);
+             my_friendly_assert (DECL_P (decl), 0);
+             context = CP_DECL_CONTEXT (decl);
            }
 
          if (is_properly_derived_from (current_class_type, context))
@@ -1327,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);
@@ -1521,6 +1639,7 @@ pushlevel_class ()
 
   class_binding_level = current_binding_level;
   class_binding_level->parm_flag = 2;
+  class_binding_level->this_class = current_class_type;
 }
 
 /* ...and a poplevel for class declarations.  */
@@ -1638,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.  */
@@ -1781,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)
     {
@@ -1834,6 +1963,7 @@ mark_binding_level (arg)
       ggc_mark_tree (lvl->shadowed_labels);
       ggc_mark_tree (lvl->blocks);
       ggc_mark_tree (lvl->this_block);
+      ggc_mark_tree (lvl->this_class);
       ggc_mark_tree (lvl->incomplete);
       ggc_mark_tree (lvl->dead_vars_from_for);
 
@@ -2275,6 +2405,8 @@ mark_saved_scope (arg)
       ggc_mark_tree (t->x_previous_class_type);
       ggc_mark_tree (t->x_previous_class_values);
       ggc_mark_tree (t->x_saved_tree);
+      ggc_mark_tree (t->incomplete);
+      ggc_mark_tree (t->lookups);
 
       mark_stmt_tree (&t->x_stmt_tree);
       mark_binding_level (&t->bindings);
@@ -2363,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);
@@ -2572,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));
@@ -2581,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;
            }
        }
@@ -2647,17 +2779,16 @@ 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.  */
-               context = hack_decl_function_context (get_type_decl (cs));
+               context = decl_function_context (get_type_decl (cs));
            }
          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;
 
@@ -2697,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;
        }
     }
@@ -2795,37 +2926,18 @@ decls_match (newdecl, olddecl)
       tree p1 = TYPE_ARG_TYPES (f1);
       tree p2 = TYPE_ARG_TYPES (f2);
 
-      if (DECL_REAL_CONTEXT (newdecl) != DECL_REAL_CONTEXT (olddecl)
+      if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
          && ! (DECL_LANGUAGE (newdecl) == lang_c
                && 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);
@@ -3060,7 +3172,7 @@ duplicate_decls (newdecl, olddecl)
     }
   else if (!types_match)
     {
-      if (DECL_REAL_CONTEXT (newdecl) != DECL_REAL_CONTEXT (olddecl))
+      if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
        /* These are certainly not duplicate declarations; they're
           from different scopes.  */
        return 0;
@@ -3245,10 +3357,10 @@ duplicate_decls (newdecl, olddecl)
         definition.  */
       if (DECL_VINDEX (olddecl))
        DECL_VINDEX (newdecl) = DECL_VINDEX (olddecl);
+      if (DECL_VIRTUAL_CONTEXT (olddecl))
+       DECL_VIRTUAL_CONTEXT (newdecl) = DECL_VIRTUAL_CONTEXT (olddecl);
       if (DECL_CONTEXT (olddecl))
        DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
-      if (DECL_CLASS_CONTEXT (olddecl))
-       DECL_CLASS_CONTEXT (newdecl) = DECL_CLASS_CONTEXT (olddecl);
       if (DECL_PENDING_INLINE_INFO (newdecl) == (struct pending_inline *)0)
        DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
       DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl);
@@ -3517,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)
@@ -3631,8 +3741,6 @@ pushdecl (x)
             scoped of the current namespace, not the current
             function.  */
          && !(TREE_CODE (x) == VAR_DECL && DECL_EXTERNAL (x))
-         /* Don't change DECL_CONTEXT of virtual methods.  */
-         && (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
          && !DECL_CONTEXT (x))
        DECL_CONTEXT (x) = current_function_decl;
       if (!DECL_CONTEXT (x))
@@ -3932,6 +4040,19 @@ pushdecl (x)
            set_identifier_type_value_with_scope (name, NULL_TREE,
                                                  current_binding_level);
 
+         if (oldlocal)
+           {
+             tree d = oldlocal;
+
+             while (oldlocal
+                    && TREE_CODE (oldlocal) == VAR_DECL
+                    && DECL_DEAD_FOR_LOCAL (oldlocal))
+               oldlocal = DECL_SHADOWED_FOR_VAR (oldlocal);
+
+             if (oldlocal == NULL_TREE)
+               oldlocal = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (d));
+           }
+
          /* If this is an extern function declaration, see if we
             have a global definition or declaration for the function.  */
          if (oldlocal == NULL_TREE
@@ -3958,15 +4079,14 @@ pushdecl (x)
              && TREE_PUBLIC (x))
            TREE_PUBLIC (name) = 1;
 
-         if (DECL_FROM_INLINE (x))
-           /* Inline decls shadow nothing.  */;
-
          /* Warn if shadowing an argument at the top level of the body.  */
-         else if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x)
-                  && TREE_CODE (oldlocal) == PARM_DECL
-                  /* Don't complain if it's from an enclosing function.  */
-                  && DECL_CONTEXT (oldlocal) == current_function_decl
-                  && TREE_CODE (x) != PARM_DECL)
+         if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x)
+             /* Inline decls shadow nothing.  */
+             && !DECL_FROM_INLINE (x)
+             && TREE_CODE (oldlocal) == PARM_DECL
+             /* Don't complain if it's from an enclosing function.  */
+             && DECL_CONTEXT (oldlocal) == current_function_decl
+             && TREE_CODE (x) != PARM_DECL)
            {
              /* Go to where the parms should be and see if we
                 find them there.  */
@@ -3979,20 +4099,15 @@ pushdecl (x)
              if (b->parm_flag == 1)
                cp_error ("declaration of `%#D' shadows a parameter", name);
            }
-         else if (warn_shadow && oldlocal != NULL_TREE
-                  && current_binding_level->is_for_scope
-                  && !DECL_DEAD_FOR_LOCAL (oldlocal))
-           {
-             warning ("variable `%s' shadows local",
-                      IDENTIFIER_POINTER (name));
-             cp_warning_at ("  this is the shadowed declaration", oldlocal);
-           }
+
          /* Maybe warn if shadowing something else.  */
-         else if (warn_shadow && !DECL_EXTERNAL (x)
-                  /* No shadow warnings for internally generated vars.  */
-                  && ! DECL_ARTIFICIAL (x)
-                  /* No shadow warnings for vars made for inlining.  */
-                  && ! DECL_FROM_INLINE (x))
+         if (warn_shadow && !DECL_EXTERNAL (x)
+             /* Inline decls shadow nothing.  */
+             && !DECL_FROM_INLINE (x)
+             /* No shadow warnings for internally generated vars.  */
+             && ! DECL_ARTIFICIAL (x)
+             /* No shadow warnings for vars made for inlining.  */
+             && ! DECL_FROM_INLINE (x))
            {
              if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL)
                warning ("declaration of `%s' shadows a parameter",
@@ -4018,13 +4133,19 @@ 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))
                  && TYPE_BEING_DEFINED (TREE_TYPE (x)))))
-       current_binding_level->incomplete
-         = tree_cons (NULL_TREE, x, current_binding_level->incomplete);
+       {
+         if (namespace_bindings_p ())
+           namespace_scope_incomplete
+             = tree_cons (NULL_TREE, x, namespace_scope_incomplete);
+         else
+           current_binding_level->incomplete
+             = tree_cons (NULL_TREE, x, current_binding_level->incomplete);
+       }
     }
 
   if (need_new_binding)
@@ -4186,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.  */
 
@@ -4346,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
@@ -4488,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);
@@ -4559,12 +4657,12 @@ 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;
     }
-  else if (toplevel_bindings_p ())
+  else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
     {
       /* Objects declared at top level:  */
       /* If at least one is a reference, it's ok.  */
@@ -4832,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;
@@ -4841,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
@@ -4960,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)
     {
@@ -4981,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));
@@ -5028,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:
 
@@ -5041,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
@@ -5120,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);
     }
 
@@ -5270,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)
@@ -5592,7 +5694,10 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
          else if (type == current_class_type)
            val = IDENTIFIER_CLASS_VALUE (name);
          else
-           val = lookup_member (type, name, 0, prefer_type);
+           {
+             val = lookup_member (type, name, 0, prefer_type);
+             type_access_control (type, val);
+           }
        }
       else
        val = NULL_TREE;
@@ -5631,6 +5736,11 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
       else
        binding = NULL_TREE;
 
+      /* Handle access control on types from enclosing or base classes.  */
+      if (binding && ! yylex
+         && BINDING_LEVEL (t) && BINDING_LEVEL (t)->parm_flag == 2)
+       type_access_control (BINDING_LEVEL (t)->this_class, binding);
+
       if (binding
          && (!val || !IMPLICIT_TYPENAME_TYPE_DECL_P (binding)))
        {
@@ -5923,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,
@@ -5960,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.  */
@@ -6035,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);
@@ -6129,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);
 
@@ -6163,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.
@@ -6177,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);
 
@@ -6266,6 +6399,7 @@ init_decl_processing ()
       DECL_NAME (fields[3]) = delta2_identifier;
       DECL_MODE (fields[3]) = TYPE_MODE (delta_type_node);
       DECL_SIZE (fields[3]) = TYPE_SIZE (delta_type_node);
+      DECL_SIZE_UNIT (fields[3]) = TYPE_SIZE_UNIT (delta_type_node);
       TREE_UNSIGNED (fields[3]) = 0;
       TREE_CHAIN (fields[2]) = fields[3];
       vtable_entry_type = build_qualified_type (vtable_entry_type,
@@ -6286,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");
@@ -6304,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 ();
@@ -6331,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.  */
@@ -6381,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
@@ -6391,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) PROTO((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.  */
+
+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
+build_library_fn (name, type)
+     tree name;
+     tree type;
+{
+  tree fn = build_library_fn_1 (name, type);
+  make_function_rtl (fn);
+  return fn;
+}
 
-/* 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.  */
+/* Returns the _DECL for a library function with C++ linkage.  */
 
 tree
-builtin_function (name, type, code, class, libname)
+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 (*) PROTO((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
@@ -6478,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");
 }
@@ -6494,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;
@@ -6502,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;
 
@@ -6517,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]
@@ -6533,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
@@ -6636,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;
@@ -6682,10 +6974,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   if (type == error_mark_node)
     return NULL_TREE;
 
-  context
-    = (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
-      ? DECL_CLASS_CONTEXT (decl)
-      : DECL_CONTEXT (decl);
+  context = DECL_CONTEXT (decl);
 
   if (initialized && context && TREE_CODE (context) == NAMESPACE_DECL
       && context != current_namespace && TREE_CODE (decl) == VAR_DECL)
@@ -6748,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);
 
@@ -6761,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);
@@ -6839,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);
@@ -6855,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)
        {
@@ -6864,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);
@@ -6881,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);
@@ -6931,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;
     }
 
@@ -7082,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)
@@ -7128,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)
@@ -7163,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);
@@ -7225,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;
@@ -7294,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);
@@ -7310,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);
 
     }
@@ -7485,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;
     }
@@ -7517,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)
@@ -7539,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 &&
@@ -7593,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)
@@ -7619,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)
@@ -7627,39 +7905,19 @@ 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;
     }
 
   if (current_class_type
-      && DECL_REAL_CONTEXT (decl) == current_class_type
+      && CP_DECL_CONTEXT (decl) == current_class_type
       && TYPE_BEING_DEFINED (current_class_type)
       && (DECL_INITIAL (decl) || init))
     DECL_DEFINED_IN_CLASS_P (decl) = 1;
@@ -7678,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);
@@ -7719,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,
@@ -7815,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:
@@ -7824,9 +8082,9 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
         due to initialization of qualified member variable.
         I.e., Foo::x = 10;  */
       {
-       tree context = DECL_REAL_CONTEXT (decl);
+       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.  */
@@ -7834,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 ();
       }
@@ -7842,24 +8100,6 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
 
  finish_end:
 
-  /* If requested, warn about definitions of large data objects.  */
-
-  if (warn_larger_than
-      && ! processing_template_decl
-      && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
-      && !DECL_EXTERNAL (decl))
-    {
-      register tree decl_size = DECL_SIZE (decl);
-
-      if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
-       {
-         unsigned units = TREE_INT_CST_LOW (decl_size) / BITS_PER_UNIT;
-
-         if (units > larger_than_size)
-           warning_with_decl (decl, "size of `%s' is %u bytes", units);
-       }
-    }
-
   if (was_readonly)
     TREE_READONLY (decl) = 1;
 }
@@ -7957,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);
@@ -8048,7 +8288,7 @@ end_cleanup_fn ()
 {
   do_poplevel ();
 
-  expand_body (finish_function (lineno, 0));
+  expand_body (finish_function (0));
 
   pop_from_top_level ();
 }
@@ -8067,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
@@ -8253,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);
        }
@@ -8318,13 +8559,18 @@ complete_array_type (type, initial_value, do_default)
    message to print in that case.  Otherwise, quietly return 1.  */
 
 static int
-member_function_or_else (ctype, cur_type, string)
+member_function_or_else (ctype, cur_type, flags)
      tree ctype, cur_type;
-     const char *string;
+     enum overload_flags flags;
 {
   if (ctype && ctype != cur_type)
     {
-      error (string, TYPE_NAME_STRING (ctype));
+      if (flags == DTOR_FLAG)
+       error ("destructor for alien class `%s' cannot be a member",
+              TYPE_NAME_STRING (ctype));
+      else
+       error ("constructor for alien class `%s' cannot be a member",
+              TYPE_NAME_STRING (ctype));
       return 0;
     }
   return 1;
@@ -8429,16 +8675,16 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
     }
 
   if (ctype)
-    DECL_CLASS_CONTEXT (decl) = ctype;
+    DECL_CONTEXT (decl) = ctype;
 
   if (ctype == NULL_TREE && DECL_MAIN_P (decl))
     {
       if (processing_template_decl)
-       error ("cannot declare `main' to be a template");
+       error ("cannot declare `::main' to be a template");
       if (inlinep)
-       error ("cannot declare `main' to be inline");
+       error ("cannot declare `::main' to be inline");
       else if (! publicp)
-       error ("cannot declare `main' to be static");
+       error ("cannot declare `::main' to be static");
       inlinep = 0;
       publicp = 1;
     }
@@ -8446,7 +8692,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
   /* Members of anonymous types and local classes have no linkage; make
      them internal.  */
   if (ctype && (ANON_AGGRNAME_P (TYPE_IDENTIFIER (ctype))
-               || hack_decl_function_context (TYPE_MAIN_DECL (ctype))))
+               || decl_function_context (TYPE_MAIN_DECL (ctype))))
     publicp = 0;
 
   if (publicp)
@@ -8494,7 +8740,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
   if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
     grok_op_properties (decl, virtualp, check < 0);
 
-  if (ctype && hack_decl_function_context (decl))
+  if (ctype && decl_function_context (decl))
     DECL_NO_STATIC_CHAIN (decl) = 1;
 
   for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
@@ -8517,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;
            }
@@ -8561,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;
 }
 
@@ -8683,7 +8911,6 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
       type = TREE_TYPE (type);
       decl = build_lang_decl (VAR_DECL, declarator, type);
       DECL_CONTEXT (decl) = basetype;
-      DECL_CLASS_CONTEXT (decl) = basetype;
       DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator);
     }
   else
@@ -8790,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.  */
@@ -8856,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
@@ -8865,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;
 }
@@ -8952,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");
        }
     }
 
@@ -8973,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.  */
@@ -9059,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;
     }
@@ -9073,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.
@@ -9103,7 +9386,7 @@ create_array_type_for_decl (name, type, size)
    ATTRLIST is a TREE_LIST node with prefix attributes in TREE_VALUE and
    normal attributes in TREE_PURPOSE, or NULL_TREE.
 
-   In the TYPENAME case, DECLARATOR is really an absolute declarator.
+   In the TYPENAME case, DECLARATOR is really an abstract declarator.
    It may also be so in the PARM case, for a prototype where the
    argument type is specified but not the name.
 
@@ -9133,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;
@@ -9173,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;
@@ -9223,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);
@@ -9293,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 */
@@ -9321,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;
@@ -9369,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);
              }
@@ -9433,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
@@ -9441,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);
@@ -9590,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
@@ -9657,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);
-
-         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);
+      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 = ctor_return_type;
+      type = integer_type_node;
     }
 
   ctype = NULL_TREE;
@@ -9853,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)))
@@ -10150,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)
              {
@@ -10161,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)
@@ -10174,8 +10433,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                      }
                    if (decl_context == FIELD)
                      {
-                       if (! member_function_or_else (ctype, current_class_type,
-                                                      "destructor for alien class `%s' cannot be a member"))
+                       if (! member_function_or_else (ctype,
+                                                      current_class_type,
+                                                      flags))
                          return void_type_node;
                      }
                  }
@@ -10183,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)
@@ -10207,14 +10468,14 @@ 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, current_class_type,
-                                                      "constructor for alien class `%s' cannot be member"))
+                       if (! member_function_or_else (ctype,
+                                                      current_class_type,
+                                                      flags))
                          return void_type_node;
                        TYPE_HAS_CONSTRUCTOR (ctype) = 1;
-                       if (return_type != return_ctor)
+                       if (sfk != sfk_constructor)
                          return NULL_TREE;
                      }
                  }
@@ -10445,12 +10706,24 @@ 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_CLASS_CONTEXT (t);
+                 t = DECL_CONTEXT (t);
                else
                  t = NULL_TREE;
              }
@@ -10489,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;
@@ -10639,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);
        }
@@ -10658,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))
@@ -10710,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);
            }
@@ -10781,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;
@@ -10937,7 +11216,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
            /* Tell grokfndecl if it needs to set TREE_PUBLIC on the node.  */
            function_context = (ctype != NULL_TREE) ?
-             hack_decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
+             decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
            publicp = (! friendp || ! staticp)
              && function_context == NULL_TREE;
            decl = grokfndecl (ctype, type,
@@ -10976,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
@@ -11001,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)
@@ -11026,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;
              }
@@ -11084,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;
@@ -11109,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)
@@ -11321,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",
@@ -11680,17 +11959,25 @@ replace_defarg (arg, init)
   TREE_PURPOSE (arg) = init;
 }
 \f
+/* D is a constructor or overloaded `operator='.  Returns non-zero if
+   D's arguments allow it to be a copy constructor, or copy assignment
+   operator.  */
+
 int
 copy_args_p (d)
      tree d;
 {
-  tree t = FUNCTION_ARG_CHAIN (d);
-  if (DECL_CONSTRUCTOR_P (d)
-      && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (d)))
+  tree t;
+
+  if (!DECL_FUNCTION_MEMBER_P (d))
+    return 0;
+
+  t = FUNCTION_ARG_CHAIN (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)))
-         == DECL_CLASS_CONTEXT (d))
+         == DECL_CONTEXT (d))
       && (TREE_CHAIN (t) == NULL_TREE
          || TREE_CHAIN (t) == void_list_node
          || TREE_PURPOSE (TREE_CHAIN (t))))
@@ -11717,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,
@@ -11838,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;
     }
@@ -11853,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)
@@ -11868,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)
@@ -11876,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
     {
@@ -11933,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";
 
@@ -11979,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))
        {
@@ -12144,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:
@@ -12163,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);
@@ -12214,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)
@@ -12313,21 +12594,13 @@ xref_tag (code_type_node, name, globalize)
     }
   else
     {
-      /* If it no longer looks like a nested type, make sure it's
-        in global scope.
-         If it is not an IDENTIFIER, this is not a declaration */
-      if (b->namespace_p && !class_binding_level
-         && TREE_CODE (name) == IDENTIFIER_NODE
-         && IDENTIFIER_NAMESPACE_VALUE (name) == NULL_TREE)
-       SET_IDENTIFIER_NAMESPACE_VALUE (name, TYPE_NAME (ref));
-
       if (!globalize && processing_template_decl && IS_AGGR_TYPE (ref))
        redeclare_class_template (ref, current_template_parms);
     }
 
   /* 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)))
@@ -12380,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)
     {
@@ -12437,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);
@@ -12468,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)
@@ -12498,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)
@@ -12761,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);
@@ -12850,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));
 
@@ -12937,12 +13213,11 @@ 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_CLASS_CONTEXT (decl1);
+         ctype = DECL_FRIEND_CONTEXT (decl1);
 
          /* CTYPE could be null here if we're dealing with a template;
             for example, `inline friend float foo()' inside a template
@@ -13000,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;
     }
@@ -13125,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);
     }
 
@@ -13174,19 +13448,13 @@ 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);
     }
 
   if (DECL_INTERFACE_KNOWN (decl1))
     {
-      tree ctx = hack_decl_function_context (decl1);
+      tree ctx = decl_function_context (decl1);
 
       if (DECL_NOT_REALLY_EXTERN (decl1))
        DECL_EXTERNAL (decl1) = 0;
@@ -13243,7 +13511,7 @@ start_function (declspecs, declarator, attrs, flags)
       if ((DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1))
          && ! DECL_INTERFACE_KNOWN (decl1)
          /* Don't try to defer nested functions for now.  */
-         && ! hack_decl_function_context (decl1))
+         && ! decl_function_context (decl1))
        DECL_DEFER_OUTPUT (decl1) = 1;
       else
        DECL_INTERFACE_KNOWN (decl1) = 1;
@@ -13289,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;
@@ -13371,13 +13644,15 @@ store_parm_decls ()
                  else
                    cp_error ("parameter `%D' declared void", parm);
 
-                 cleanup = maybe_build_cleanup (parm);
+                 cleanup = (processing_template_decl 
+                            ? NULL_TREE
+                            : maybe_build_cleanup (parm));
 
                  if (cleanup)
                    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
@@ -13442,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 ();
@@ -13518,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.  */
@@ -13538,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);
@@ -13558,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);
 
@@ -13593,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);
            }
@@ -13624,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);
@@ -13651,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
@@ -13665,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;
@@ -13677,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.  */
@@ -13697,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))
        {
@@ -13719,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)),
@@ -13790,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);
        }
 
@@ -13829,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
@@ -13882,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
-         && hack_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;
@@ -13933,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
@@ -13942,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
@@ -14097,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))
@@ -14205,56 +14452,75 @@ hack_incomplete_structures (type)
      tree type;
 {
   tree *list;
-
-  if (current_binding_level->incomplete == NULL_TREE)
-    return;
+  struct binding_level *level;
 
   if (!type) /* Don't do this for class templates.  */
     return;
 
-  for (list = &current_binding_level->incomplete; *list; )
-    {
-      tree decl = TREE_VALUE (*list);
-      if ((decl && TREE_TYPE (decl) == type)
-         || (TREE_TYPE (decl)
-             && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
-             && TREE_TYPE (TREE_TYPE (decl)) == type))
-       {
-         int toplevel = toplevel_bindings_p ();
-         if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
-             && TREE_TYPE (TREE_TYPE (decl)) == type)
-           layout_type (TREE_TYPE (decl));
-         layout_decl (decl, 0);
-         rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
-         if (! toplevel)
+  if (namespace_bindings_p ())
+    {
+      level = 0;
+      list = &namespace_scope_incomplete;
+    }
+  else
+    {
+      level = innermost_nonclass_level ();
+      list = &level->incomplete;
+    }
+
+  while (1)
+    {
+      while (*list)
+       {
+         tree decl = TREE_VALUE (*list);
+         if ((decl && TREE_TYPE (decl) == type)
+             || (TREE_TYPE (decl)
+                 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
+                 && TREE_TYPE (TREE_TYPE (decl)) == type))
            {
-             tree cleanup;
-             expand_decl (decl);
-             cleanup = maybe_build_cleanup (decl);
-             expand_decl_init (decl);
-             if (! expand_decl_cleanup (decl, cleanup))
-               cp_error ("parser lost in parsing declaration of `%D'",
-                         decl);
+             int toplevel = toplevel_bindings_p ();
+             if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
+                 && TREE_TYPE (TREE_TYPE (decl)) == type)
+               layout_type (TREE_TYPE (decl));
+             layout_decl (decl, 0);
+             rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
+             if (! toplevel)
+               {
+                 tree cleanup;
+                 expand_decl (decl);
+                 cleanup = maybe_build_cleanup (decl);
+                 expand_decl_init (decl);
+                 if (! expand_decl_cleanup (decl, cleanup))
+                   cp_error ("parser lost in parsing declaration of `%D'",
+                             decl);
+               }
+             *list = TREE_CHAIN (*list);
            }
-         *list = TREE_CHAIN (*list);
+         else
+           list = &TREE_CHAIN (*list);
+       }
+
+      /* Keep looking through artificial binding levels generated
+        for local variables.  */
+      if (level && level->keep == 2)
+       {
+         level = level->level_chain;
+         list = &level->incomplete;
        }
       else
-       list = &TREE_CHAIN (*list);
+       break;
     }
 }
 
 /* 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;
@@ -14285,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
@@ -14316,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.  */
@@ -14343,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)
@@ -14368,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++
@@ -14445,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;
@@ -14509,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