OSDN Git Service

* decl2.c (import_export_class): Never export/import vtables
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl2.c
index b1ee970..4465873 100644 (file)
@@ -1,6 +1,6 @@
 /* Process declarations and variables for C++ compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -38,7 +38,6 @@ Boston, MA 02111-1307, USA.  */
 #include "flags.h"
 #include "cp-tree.h"
 #include "decl.h"
-#include "lex.h"
 #include "output.h"
 #include "except.h"
 #include "toplev.h"
@@ -46,8 +45,10 @@ Boston, MA 02111-1307, USA.  */
 #include "cpplib.h"
 #include "target.h"
 #include "c-common.h"
+#include "tree-mudflap.h"
 #include "cgraph.h"
 #include "tree-inline.h"
+
 extern cpp_reader *parse_in;
 
 /* This structure contains information about the initializations
@@ -64,16 +65,10 @@ typedef struct priority_info_s {
 static void mark_vtable_entries (tree);
 static void grok_function_init (tree, tree);
 static bool maybe_emit_vtables (tree);
-static void add_using_namespace (tree, tree, bool);
-static cxx_binding *ambiguous_decl (tree, cxx_binding *, cxx_binding *, int);
 static tree build_anon_union_vars (tree);
 static bool acceptable_java_type (tree);
 static tree start_objects (int, int);
 static void finish_objects (int, int, tree);
-static tree merge_functions (tree, tree);
-static tree decl_namespace (tree);
-static tree validate_nonmember_using_decl (tree, tree *, tree *);
-static void do_nonmember_using_decl (tree, tree, tree, tree, tree *, tree *);
 static tree start_static_storage_duration_function (unsigned);
 static void finish_static_storage_duration_function (tree);
 static priority_info get_priority_info (int);
@@ -115,9 +110,6 @@ int at_eof;
 tree static_ctors;
 tree static_dtors;
 
-/* The :: namespace.  */
-
-tree global_namespace;
 \f
 /* Incorporate `const' and `volatile' qualifiers for member functions.
    FUNCTION is a TYPE_DECL or a FUNCTION_DECL.
@@ -126,32 +118,15 @@ tree global_namespace;
    TYPE_UNQUALIFIED will be an extension.  */
 
 int
-grok_method_quals (tree ctype, tree function, tree quals)
+grok_method_quals (tree ctype, tree function, cp_cv_quals quals)
 {
   tree fntype = TREE_TYPE (function);
   tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
   int type_quals = TYPE_UNQUALIFIED;
-  int dup_quals = TYPE_UNQUALIFIED;
   int this_quals = TYPE_UNQUALIFIED;
 
-  do
-    {
-      int tq = cp_type_qual_from_rid (TREE_VALUE (quals));
-      
-      if ((type_quals | this_quals) & tq)
-       dup_quals |= tq;
-      else if (tq & TYPE_QUAL_RESTRICT)
-        this_quals |= tq;
-      else
-       type_quals |= tq;
-      quals = TREE_CHAIN (quals);
-    } 
-  while (quals);
-
-  if (dup_quals != TYPE_UNQUALIFIED)
-    error ("duplicate type qualifiers in %s declaration",
-             TREE_CODE (function) == FUNCTION_DECL 
-             ? "member function" : "type");
+  type_quals = quals & ~TYPE_QUAL_RESTRICT;
+  this_quals = quals & TYPE_QUAL_RESTRICT;
 
   ctype = cp_build_qualified_type (ctype, type_quals);
   fntype = build_method_type_directly (ctype, TREE_TYPE (fntype),
@@ -165,57 +140,6 @@ grok_method_quals (tree ctype, tree function, tree quals)
   return this_quals;
 }
 
-/* Warn when -fexternal-templates is used and #pragma
-   interface/implementation is not used all the times it should be,
-   inform the user.  */
-
-void
-warn_if_unknown_interface (tree decl)
-{
-  static int already_warned = 0;
-  if (already_warned++)
-    return;
-
-  if (flag_alt_external_templates)
-    {
-      tree til = tinst_for_decl ();
-      location_t saved_loc = input_location;
-
-      if (til)
-       {
-         input_line = TINST_LINE (til);
-         input_filename = TINST_FILE (til);
-       }
-      warning ("template `%#D' instantiated in file without #pragma interface",
-                 decl);
-      input_location = saved_loc;
-    }
-  else
-    cp_warning_at ("template `%#D' defined in file without #pragma interface",
-                  decl);
-}
-
-/* A subroutine of the parser, to handle a component list.  */
-
-void
-grok_x_components (tree specs)
-{
-  tree t;
-
-  specs = strip_attrs (specs);
-
-  check_tag_decl (specs);
-  t = groktypename (build_tree_list (specs, NULL_TREE)); 
-
-  /* The only case where we need to do anything additional here is an
-     anonymous union field, e.g.: `struct S { union { int i; }; };'.  */
-  if (t == NULL_TREE || !ANON_AGGR_TYPE_P (t))
-    return;
-
-  fixup_anonymous_aggr (t);
-  finish_member_declaration (build_decl (FIELD_DECL, NULL_TREE, t)); 
-}
-
 /* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE
    appropriately.  */
 
@@ -268,7 +192,7 @@ maybe_retrofit_in_chrg (tree fn)
 
   /* When processing templates we can't know, in general, whether or
      not we're going to have virtual baseclasses.  */
-  if (uses_template_parms (fn))
+  if (processing_template_decl)
     return;
 
   /* We don't need an in-charge parameter for constructors that don't
@@ -341,10 +265,11 @@ maybe_retrofit_in_chrg (tree fn)
    QUALS are the qualifiers for the this pointer.  */
 
 void
-grokclassfn (tree ctype, tree function, enum overload_flags flags, tree quals)
+grokclassfn (tree ctype, tree function, enum overload_flags flags, 
+            cp_cv_quals quals)
 {
   tree fn_name = DECL_NAME (function);
-  int this_quals = TYPE_UNQUALIFIED;
+  cp_cv_quals this_quals = TYPE_UNQUALIFIED;
 
   /* Even within an `extern "C"' block, members get C++ linkage.  See
      [dcl.link] for details.  */
@@ -375,11 +300,10 @@ grokclassfn (tree ctype, tree function, enum overload_flags flags, tree quals)
       qual_type = cp_build_qualified_type (type, this_quals);
       parm = build_artificial_parm (this_identifier, qual_type);
       c_apply_type_quals_to_decl (this_quals, parm);
-      TREE_CHAIN (parm) = last_function_parms;
-      last_function_parms = parm;
+      TREE_CHAIN (parm) = DECL_ARGUMENTS (function);
+      DECL_ARGUMENTS (function) = parm;
     }
 
-  DECL_ARGUMENTS (function) = last_function_parms;
   DECL_CONTEXT (function) = ctype;
 
   if (flags == DTOR_FLAG)
@@ -407,7 +331,8 @@ grok_array_decl (tree array_expr, tree index_exp)
     {
       if (type_dependent_expression_p (array_expr)
          || type_dependent_expression_p (index_exp))
-       return build_min_nt (ARRAY_REF, array_expr, index_exp);
+       return build_min_nt (ARRAY_REF, array_expr, index_exp,
+                            NULL_TREE, NULL_TREE);
       array_expr = build_non_dependent_expr (array_expr);
       index_exp = build_non_dependent_expr (index_exp);
     }
@@ -419,7 +344,8 @@ grok_array_decl (tree array_expr, tree index_exp)
   /* If they have an `operator[]', use that.  */
   if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
     expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL,
-                        array_expr, index_exp, NULL_TREE);
+                        array_expr, index_exp, NULL_TREE,
+                        /*overloaded_p=*/NULL);
   else
     {
       tree p1, p2, i1, i2;
@@ -463,26 +389,22 @@ grok_array_decl (tree array_expr, tree index_exp)
       expr = build_array_ref (array_expr, index_exp);
     }
   if (processing_template_decl && expr != error_mark_node)
-    return build_min_non_dep (ARRAY_REF, expr,
-                             orig_array_expr, orig_index_exp);
+    return build_min_non_dep (ARRAY_REF, expr, orig_array_expr, orig_index_exp,
+                             NULL_TREE, NULL_TREE);
   return expr;
 }
 
 /* Given the cast expression EXP, checking out its validity.   Either return
    an error_mark_node if there was an unavoidable error, return a cast to
    void for trying to delete a pointer w/ the value 0, or return the
-   call to delete.  If DOING_VEC is 1, we handle things differently
-   for doing an array delete.  If DOING_VEC is 2, they gave us the
-   array size as an argument to delete.
+   call to delete.  If DOING_VEC is true, we handle things differently
+   for doing an array delete.
    Implements ARM $5.3.4.  This is called from the parser.  */
 
 tree
-delete_sanity (tree exp, tree size, int doing_vec, int use_global_delete)
+delete_sanity (tree exp, tree size, bool doing_vec, int use_global_delete)
 {
   tree t, type;
-  /* For a regular vector delete (aka, no size argument) we will pass
-     this down as a NULL_TREE into build_vec_delete.  */
-  tree maxindex = NULL_TREE;
 
   if (exp == error_mark_node)
     return exp;
@@ -492,10 +414,17 @@ delete_sanity (tree exp, tree size, int doing_vec, int use_global_delete)
       t = build_min (DELETE_EXPR, void_type_node, exp, size);
       DELETE_EXPR_USE_GLOBAL (t) = use_global_delete;
       DELETE_EXPR_USE_VEC (t) = doing_vec;
+      TREE_SIDE_EFFECTS (t) = 1;
       return t;
     }
 
   exp = convert_from_reference (exp);
+
+  /* An array can't have been allocated by new, so complain.  */
+  if (TREE_CODE (exp) == VAR_DECL
+      && TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+    warning ("deleting array `%#D'", exp);
+
   t = build_expr_type_conversion (WANT_POINTER, exp, true);
 
   if (t == NULL_TREE || t == error_mark_node)
@@ -505,12 +434,6 @@ delete_sanity (tree exp, tree size, int doing_vec, int use_global_delete)
       return error_mark_node;
     }
 
-  if (doing_vec == 2)
-    {
-      maxindex = cp_build_binary_op (MINUS_EXPR, size, integer_one_node);
-      pedwarn ("anachronistic use of array size in vector delete");
-    }
-
   type = TREE_TYPE (t);
 
   /* As of Valley Forge, you can delete a pointer to const.  */
@@ -529,18 +452,13 @@ delete_sanity (tree exp, tree size, int doing_vec, int use_global_delete)
       doing_vec = 0;
     }
 
-  /* An array can't have been allocated by new, so complain.  */
-  if (TREE_CODE (t) == ADDR_EXPR
-      && TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL
-      && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == ARRAY_TYPE)
-    warning ("deleting array `%#D'", TREE_OPERAND (t, 0));
-
   /* Deleting a pointer with the value zero is valid and has no effect.  */
   if (integer_zerop (t))
     return build1 (NOP_EXPR, void_type_node, t);
 
   if (doing_vec)
-    return build_vec_delete (t, maxindex, sfk_deleting_destructor,
+    return build_vec_delete (t, /*maxindex=*/NULL_TREE, 
+                            sfk_deleting_destructor,
                             use_global_delete);
   else
     return build_delete (type, t, sfk_deleting_destructor,
@@ -631,12 +549,20 @@ check_java_method (tree method)
   bool jerr = false;
   tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (method));
   tree ret_type = TREE_TYPE (TREE_TYPE (method));
+
   if (!acceptable_java_type (ret_type))
     {
       error ("Java method '%D' has non-Java return type `%T'",
                method, ret_type);
       jerr = true;
     }
+
+  arg_types = TREE_CHAIN (arg_types);
+  if (DECL_HAS_IN_CHARGE_PARM_P (method))
+    arg_types = TREE_CHAIN (arg_types);
+  if (DECL_HAS_VTT_PARM_P (method))
+    arg_types = TREE_CHAIN (arg_types);
+  
   for (; arg_types != NULL_TREE; arg_types = TREE_CHAIN (arg_types))
     {
       tree type = TREE_VALUE (arg_types);
@@ -652,13 +578,19 @@ check_java_method (tree method)
 
 /* Sanity check: report error if this function FUNCTION is not
    really a member of the class (CTYPE) it is supposed to belong to.
-   CNAME is the same here as it is for grokclassfn above.  */
+   TEMPLATE_PARMS is used to specifiy the template parameters of a member
+   template passed as FUNCTION_DECL. If the member template is passed as a 
+   TEMPLATE_DECL, it can be NULL since the parameters can be extracted
+   from the declaration. If the function is not a function template, it
+   must be NULL.
+   It returns the original declaration for the function, or NULL_TREE
+   if no declaration was found (and an error was emitted).  */
 
 tree
-check_classfn (tree ctype, tree function)
+check_classfn (tree ctype, tree function, tree template_parms)
 {
   int ix;
-  int is_template;
+  bool is_template;
   
   if (DECL_USE_TEMPLATE (function)
       && !(TREE_CODE (function) == TEMPLATE_DECL
@@ -676,9 +608,20 @@ check_classfn (tree ctype, tree function)
        find the method, but we don't complain.  */
     return NULL_TREE;
 
+  /* Basic sanity check: for a template function, the template parameters
+     either were not passed, or they are the same of DECL_TEMPLATE_PARMS.  */
+  if (TREE_CODE (function) == TEMPLATE_DECL)
+    {
+      my_friendly_assert (!template_parms 
+                         || comp_template_parms 
+                             (template_parms, 
+                              DECL_TEMPLATE_PARMS (function)),
+                         20040303);
+      template_parms = DECL_TEMPLATE_PARMS (function);
+    }
+
   /* OK, is this a definition of a member template?  */
-  is_template = (TREE_CODE (function) == TEMPLATE_DECL
-                || (processing_template_decl - template_class_depth (ctype)));
+  is_template = (template_parms != NULL_TREE);
 
   ix = lookup_fnfields_1 (complete_type (ctype),
                          DECL_CONSTRUCTOR_P (function) ? ctor_identifier :
@@ -690,9 +633,10 @@ check_classfn (tree ctype, tree function)
       tree methods = CLASSTYPE_METHOD_VEC (ctype);
       tree fndecls, fndecl = 0;
       bool is_conv_op;
+      bool pop_p;
       const char *format = NULL;
       
-      push_scope (ctype);
+      pop_p = push_scope (ctype);
       for (fndecls = TREE_VEC_ELT (methods, ix);
           fndecls; fndecls = OVL_NEXT (fndecls))
        {
@@ -721,6 +665,9 @@ check_classfn (tree ctype, tree function)
          if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
                           TREE_TYPE (TREE_TYPE (fndecl)))
              && compparms (p1, p2)
+             && (!is_template
+                 || comp_template_parms (template_parms, 
+                                         DECL_TEMPLATE_PARMS (fndecl)))
              && (DECL_TEMPLATE_SPECIALIZATION (function)
                  == DECL_TEMPLATE_SPECIALIZATION (fndecl))
              && (!DECL_TEMPLATE_SPECIALIZATION (function)
@@ -728,7 +675,8 @@ check_classfn (tree ctype, tree function)
                      == DECL_TI_TEMPLATE (fndecl))))
            break;
        }
-      pop_scope (ctype);
+      if (pop_p)
+       pop_scope (ctype);
       if (fndecls)
        return OVL_CURRENT (fndecls);
       error ("prototype for `%#D' does not match any in class `%T'",
@@ -855,23 +803,28 @@ finish_static_data_member_decl (tree decl, tree init, tree asmspec_tree,
    CHANGES TO CODE IN `start_method'.  */
 
 tree
-grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree,
+grokfield (const cp_declarator *declarator, 
+          cp_decl_specifier_seq *declspecs, 
+          tree init, tree asmspec_tree,
            tree attrlist)
 {
   tree value;
   const char *asmspec = 0;
   int flags = LOOKUP_ONLYCONVERTING;
 
-  if (declspecs == NULL_TREE
-      && TREE_CODE (declarator) == SCOPE_REF
-      && TREE_CODE (TREE_OPERAND (declarator, 1)) == IDENTIFIER_NODE)
+  if (!declspecs->any_specifiers_p
+      && declarator->kind == cdk_id
+      && TREE_CODE (declarator->u.id.name) == SCOPE_REF
+      && (TREE_CODE (TREE_OPERAND (declarator->u.id.name, 1)) 
+         == IDENTIFIER_NODE))
     {
       /* Access declaration */
-      if (! IS_AGGR_TYPE_CODE (TREE_CODE (TREE_OPERAND (declarator, 0))))
+      if (! IS_AGGR_TYPE_CODE (TREE_CODE 
+                              (TREE_OPERAND (declarator->u.id.name, 0))))
        ;
-      else if (TREE_COMPLEXITY (declarator) == current_class_depth)
+      else if (TREE_COMPLEXITY (declarator->u.id.name) == current_class_depth)
        pop_nested_class ();
-      return do_class_using_decl (declarator);
+      return do_class_using_decl (declarator->u.id.name);
     }
 
   if (init
@@ -881,10 +834,8 @@ grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree,
     init = NULL_TREE;
 
   value = grokdeclarator (declarator, declspecs, FIELD, init != 0, &attrlist);
-  if (! value || value == error_mark_node)
+  if (! value || error_operand_p (value))
     /* friend or constructor went bad.  */
-    return value;
-  if (TREE_TYPE (value) == error_mark_node)
     return error_mark_node;
 
   if (TREE_CODE (value) == TYPE_DECL && init)
@@ -980,7 +931,11 @@ grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree,
 
   if (processing_template_decl
       && (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL))
-    value = push_template_decl (value);
+    {
+      value = push_template_decl (value);
+      if (error_operand_p (value))
+       return error_mark_node;
+    }
 
   if (attrlist)
     cplus_decl_attributes (&value, attrlist, 0);
@@ -1009,7 +964,7 @@ grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree,
          /* This must override the asm specifier which was placed
             by grokclassfn.  Lay this out fresh.  */
          SET_DECL_RTL (value, NULL_RTX);
-         SET_DECL_ASSEMBLER_NAME (value, get_identifier (asmspec));
+         change_decl_assembler_name (value, get_identifier (asmspec));
        }
       if (!DECL_FRIEND_P (value))
        grok_special_member_properties (value);
@@ -1032,10 +987,10 @@ grokfield (tree declarator, tree declspecs, tree init, tree asmspec_tree,
    WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node.  */
 
 tree
-grokbitfield (tree declarator, tree declspecs, tree width)
+grokbitfield (const cp_declarator *declarator, 
+             cp_decl_specifier_seq *declspecs, tree width)
 {
-  register tree value = grokdeclarator (declarator, declspecs, BITFIELD,
-                                       0, NULL);
+  tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL);
 
   if (! value) return NULL_TREE; /* friends went bad.  */
 
@@ -1150,73 +1105,6 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags)
     SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
 }
 \f
-/* Return the name for the constructor (or destructor) for the
-   specified class TYPE.  When given a template, this routine doesn't
-   lose the specialization.  */
-
-tree
-constructor_name_full (tree type)
-{
-  type = TYPE_MAIN_VARIANT (type);
-  if (CLASS_TYPE_P (type) && TYPE_WAS_ANONYMOUS (type) 
-      && TYPE_HAS_CONSTRUCTOR (type))
-    return DECL_NAME (OVL_CURRENT (CLASSTYPE_CONSTRUCTORS (type)));
-  else
-    return TYPE_IDENTIFIER (type);
-}
-
-/* Return the name for the constructor (or destructor) for the
-   specified class.  When given a template, return the plain
-   unspecialized name.  */
-
-tree
-constructor_name (tree type)
-{
-  tree name;
-  name = constructor_name_full (type);
-  if (IDENTIFIER_TEMPLATE (name))
-    name = IDENTIFIER_TEMPLATE (name);
-  return name;
-}
-
-/* Returns TRUE if NAME is the name for the constructor for TYPE.  */
-
-bool
-constructor_name_p (tree name, tree type)
-{
-  tree ctor_name;
-
-  if (!name)
-    return false;
-  
-  if (TREE_CODE (name) != IDENTIFIER_NODE)
-    return false;
-  
-  ctor_name = constructor_name_full (type);
-  if (name == ctor_name)
-    return true;
-  if (IDENTIFIER_TEMPLATE (ctor_name)
-      && name == IDENTIFIER_TEMPLATE (ctor_name))
-    return true;
-  return false;
-}
-
-\f
-/* Defer the compilation of the FN until the end of compilation.  */
-
-void
-defer_fn (tree fn)
-{
-  if (DECL_DEFERRED_FN (fn))
-    return;
-  DECL_DEFERRED_FN (fn) = 1;
-  DECL_DEFER_OUTPUT (fn) = 1;
-  if (!deferred_fns)
-    VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
-
-  VARRAY_PUSH_TREE (deferred_fns, fn);
-}
-
 /* Walks through the namespace- or function-scope anonymous union OBJECT,
    building appropriate ALIAS_DECLs.  Returns one of the fields for use in
    the mangled name.  */
@@ -1256,7 +1144,8 @@ build_anon_union_vars (tree object)
        cp_pedwarn_at ("protected member `%#D' in anonymous union", field);
 
       if (processing_template_decl)
-       ref = build_min_nt (COMPONENT_REF, object, DECL_NAME (field));
+       ref = build_min_nt (COMPONENT_REF, object,
+                           DECL_NAME (field), NULL_TREE);
       else
        ref = build_class_member_access_expr (object, field, NULL_TREE,
                                              false);
@@ -1323,7 +1212,7 @@ finish_anon_union (tree anon_union_decl)
   pushdecl (anon_union_decl);
   if (building_stmt_tree ()
       && at_function_scope_p ())
-    add_decl_stmt (anon_union_decl);
+    add_decl_expr (anon_union_decl);
   else if (!processing_template_decl)
     rest_of_decl_compilation (anon_union_decl, NULL,
                              toplevel_bindings_p (), at_eof);
@@ -1356,12 +1245,12 @@ coerce_new_type (tree type)
   {
     case 2:
       args = tree_cons (NULL_TREE, size_type_node, args);
-      /* FALLTHROUGH */
+      /* Fall through.  */
     case 1:
       type = build_exception_variant
               (build_function_type (ptr_type_node, args),
                TYPE_RAISES_EXCEPTIONS (type));
-      /* FALLTHROUGH */
+      /* Fall through.  */
     default:;
   }
   return type;
@@ -1390,12 +1279,12 @@ coerce_delete_type (tree type)
   {
     case 2:
       args = tree_cons (NULL_TREE, ptr_type_node, args);
-      /* FALLTHROUGH */
+      /* Fall through.  */
     case 1:
       type = build_exception_variant
               (build_function_type (void_type_node, args),
                TYPE_RAISES_EXCEPTIONS (type));
-      /* FALLTHROUGH */
+      /* Fall through.  */
     default:;
   }
 
@@ -1486,7 +1375,9 @@ comdat_linkage (tree decl)
 
 /* For win32 we also want to put explicit instantiations in
    linkonce sections, so that they will be merged with implicit
-   instantiations; otherwise we get duplicate symbol errors.  */
+   instantiations; otherwise we get duplicate symbol errors.  
+   For Darwin we do not want explicit instantiations to be 
+   linkonce.  */
 
 void
 maybe_make_one_only (tree decl)
@@ -1505,13 +1396,18 @@ maybe_make_one_only (tree decl)
      to for variables so that cp_finish_decl will update their linkage,
      because their DECL_INITIAL may not have been set properly yet.  */
 
-  make_decl_one_only (decl);
-
-  if (TREE_CODE (decl) == VAR_DECL)
+  if (!TARGET_WEAK_NOT_IN_ARCHIVE_TOC
+      || (! DECL_EXPLICIT_INSTANTIATION (decl)
+         && ! DECL_TEMPLATE_SPECIALIZATION (decl)))
     {
-      DECL_COMDAT (decl) = 1;
-      /* Mark it needed so we don't forget to emit it.  */
-      mark_referenced (DECL_ASSEMBLER_NAME (decl));
+      make_decl_one_only (decl);
+
+      if (TREE_CODE (decl) == VAR_DECL)
+       {
+         DECL_COMDAT (decl) = 1;
+         /* Mark it needed so we don't forget to emit it.  */
+         mark_decl_referenced (decl);
+       }
     }
 }
 
@@ -1605,7 +1501,14 @@ import_export_class (tree ctype)
       && TYPE_POLYMORPHIC_P (ctype))
     {
       tree method = CLASSTYPE_KEY_METHOD (ctype);
-      if (method)
+
+      /* If weak symbol support is not available, then we must be
+        careful not to emit the vtable when the key function is
+        inline.  An inline function can be defined in multiple
+        translation units.  If we were to emit the vtable in each
+        translation unit containing a definition, we would get
+        multiple definition errors at link-time.  */
+      if (method && (flag_weak || ! DECL_DECLARED_INLINE_P (method)))
        import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1);
     }
 
@@ -1614,6 +1517,10 @@ import_export_class (tree ctype)
     import_export = 0;
 #endif
 
+  /* Allow backends the chance to overrule the decision.  */
+  if (targetm.cxx.import_export_class)
+    import_export = targetm.cxx.import_export_class (ctype, import_export);
+
   if (import_export)
     {
       SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
@@ -1641,6 +1548,7 @@ maybe_emit_vtables (tree ctype)
   tree vtbl;
   tree primary_vtbl;
   bool needed = false;
+  bool weaken_vtables;
 
   /* If the vtables for this class have already been emitted there is
      nothing more to do.  */
@@ -1652,12 +1560,14 @@ maybe_emit_vtables (tree ctype)
     return false;
 
   import_export_class (ctype);
-  import_export_vtable (primary_vtbl, ctype, 1);
 
   /* See if any of the vtables are needed.  */
   for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
-    if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl))
-      break;
+    {
+      import_export_vtable (vtbl, ctype, 1);
+      if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl))
+       break;
+    }
   if (!vtbl)
     {
       /* If the references to this class' vtables are optimized away,
@@ -1671,6 +1581,29 @@ maybe_emit_vtables (tree ctype)
   else if (TREE_PUBLIC (vtbl) && !DECL_COMDAT (vtbl))
     needed = true;
   
+  /* Determine whether to make vtables weak.  The ABI requires that we
+      do so.  There are two cases in which we have to violate the ABI
+      specification: targets where we don't have weak symbols
+      (obviously), and targets where weak symbols don't appear in
+      static archives' tables of contents.  On such targets, avoiding
+      undefined symbol link errors requires that we only make a symbol
+      weak if we know that it will be emitted everywhere it's needed.
+      So on such targets we don't make vtables weak in the common case
+      where we're emitting a vtable of a nontemplate class in the 
+      translation unit containing the definition of a noninline key
+      method. */
+  if (flag_weak && !TARGET_WEAK_NOT_IN_ARCHIVE_TOC)
+    weaken_vtables = true;
+  else if (flag_weak)
+    {
+      if (CLASSTYPE_USE_TEMPLATE (ctype))
+       weaken_vtables = CLASSTYPE_IMPLICIT_INSTANTIATION (ctype);
+      else
+       weaken_vtables = !CLASSTYPE_KEY_METHOD (ctype)
+         || DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (ctype));
+    }
+  else
+    weaken_vtables = false;
 
   /* The ABI requires that we emit all of the vtables if we emit any
      of them.  */
@@ -1685,7 +1618,11 @@ maybe_emit_vtables (tree ctype)
        cgraph_varpool_mark_needed_node (cgraph_varpool_node (vtbl));
 
       if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
-       store_init_value (vtbl, DECL_INITIAL (vtbl));
+       {
+         /* It had better be all done at compile-time.  */
+         if (store_init_value (vtbl, DECL_INITIAL (vtbl)))
+           abort ();
+       }
 
       if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
        {
@@ -1713,8 +1650,8 @@ maybe_emit_vtables (tree ctype)
          DECL_IGNORED_P (vtbl) = 1;
        }
 
-      /* Always make vtables weak.  */
-      if (flag_weak)
+      /* Always make vtables weak.  Or at least almost always; see above. */
+      if (weaken_vtables)
        comdat_linkage (vtbl);
 
       rest_of_decl_compilation (vtbl, NULL, 1, 1);
@@ -1884,7 +1821,7 @@ get_guard (tree decl)
 
       /* We use a type that is big enough to contain a mutex as well
         as an integer counter.  */
-      guard_type = long_long_integer_type_node;
+      guard_type = targetm.cxx.guard_type ();
       guard = build_decl (VAR_DECL, sname, guard_type);
       
       /* The guard should have the same linkage as what it guards.  */
@@ -1908,15 +1845,18 @@ get_guard (tree decl)
 static tree
 get_guard_bits (tree guard)
 {
-  /* We only set the first byte of the guard, in order to leave room
-     for a mutex in the high-order bits.  */
-  guard = build1 (ADDR_EXPR, 
-                 build_pointer_type (TREE_TYPE (guard)),
-                 guard);
-  guard = build1 (NOP_EXPR, 
-                 build_pointer_type (char_type_node), 
-                 guard);
-  guard = build1 (INDIRECT_REF, char_type_node, guard);
+  if (!targetm.cxx.guard_mask_bit ())
+    {
+      /* We only set the first byte of the guard, in order to leave room
+        for a mutex in the high-order bits.  */
+      guard = build1 (ADDR_EXPR, 
+                     build_pointer_type (TREE_TYPE (guard)),
+                     guard);
+      guard = build1 (NOP_EXPR, 
+                     build_pointer_type (char_type_node), 
+                     guard);
+      guard = build1 (INDIRECT_REF, char_type_node, guard);
+    }
 
   return guard;
 }
@@ -1931,6 +1871,16 @@ get_guard_cond (tree guard)
 
   /* Check to see if the GUARD is zero.  */
   guard = get_guard_bits (guard);
+
+  /* Mask off all but the low bit.  */
+  if (targetm.cxx.guard_mask_bit ())
+    {
+      guard_value = integer_one_node;
+      if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
+       guard_value = convert (TREE_TYPE (guard), guard_value);
+       guard = cp_build_binary_op (BIT_AND_EXPR, guard, guard_value);
+    }
+
   guard_value = integer_zero_node;
   if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
     guard_value = convert (TREE_TYPE (guard), guard_value);
@@ -1959,8 +1909,8 @@ set_guard (tree guard)
 static tree
 start_objects (int method_type, int initp)
 {
-  tree fnname;
   tree body;
+  tree fndecl;
   char type[10];
 
   /* Make ctor or dtor function.  METHOD_TYPE may be 'I' or 'D'.  */
@@ -1980,12 +1930,11 @@ start_objects (int method_type, int initp)
   else
     sprintf (type, "%c", method_type);
 
-  fnname = get_file_function_name_long (type);
-
-  start_function (void_list_node,
-                 make_call_declarator (fnname, void_list_node, NULL_TREE,
-                                       NULL_TREE),
-                 NULL_TREE, SF_DEFAULT);
+  fndecl = build_lang_decl (FUNCTION_DECL, 
+                           get_file_function_name_long (type),
+                           build_function_type (void_type_node,
+                                                void_list_node));
+  start_preparsed_function (fndecl, /*attrs=*/NULL_TREE, SF_PRE_PARSED);
 
   /* It can be a static function as long as collect2 does not have
      to scan the object file to find its ctor/dtor routine.  */
@@ -2001,14 +1950,14 @@ start_objects (int method_type, int initp)
     DECL_GLOBAL_DTOR_P (current_function_decl) = 1;
   DECL_LANG_SPECIFIC (current_function_decl)->decl_flags.u2sel = 1;
 
-  body = begin_compound_stmt (/*has_no_scope=*/false);
+  body = begin_compound_stmt (BCS_FN_BODY);
 
   /* We cannot allow these functions to be elided, even if they do not
      have external linkage.  And, there's no point in deferring
      compilation of thes functions; they're all going to have to be
      out anyhow.  */
-  current_function_cannot_inline
-    = "static constructors and destructors cannot be inlined";
+  DECL_INLINE (current_function_decl) = 0;
+  DECL_UNINLINABLE (current_function_decl) = 1;
 
   return body;
 }
@@ -2145,25 +2094,24 @@ start_static_storage_duration_function (unsigned count)
   /* Put the function in the global scope.  */
   pushdecl (ssdf_decl);
 
-  /* Start the function itself.  This is equivalent to declarating the
+  /* Start the function itself.  This is equivalent to declaring the
      function as:
 
        static void __ssdf (int __initialize_p, init __priority_p);
        
      It is static because we only need to call this function from the
      various constructor and destructor functions for this module.  */
-  start_function (/*specs=*/NULL_TREE, 
-                 ssdf_decl,
-                 /*attrs=*/NULL_TREE,
-                 SF_PRE_PARSED);
+  start_preparsed_function (ssdf_decl,
+                           /*attrs=*/NULL_TREE,
+                           SF_PRE_PARSED);
 
   /* Set up the scope of the outermost block in the function.  */
-  body = begin_compound_stmt (/*has_no_scope=*/false);
+  body = begin_compound_stmt (BCS_FN_BODY);
 
   /* This function must not be deferred because we are depending on
      its compilation to tell us what is TREE_SYMBOL_REFERENCED.  */
-  current_function_cannot_inline 
-    = "static storage duration functions cannot be inlined";
+  DECL_INLINE (ssdf_decl) = 0;
+  DECL_UNINLINABLE (ssdf_decl) = 1;
 
   return body;
 }
@@ -2338,7 +2286,7 @@ static void
 finish_static_initialization_or_destruction (tree guard_if_stmt)
 {
   finish_then_clause (guard_if_stmt);
-  finish_if_stmt ();
+  finish_if_stmt (guard_if_stmt);
 
   /* Now that we're done with DECL we don't need to pretend to be a
      member of its class any longer.  */
@@ -2368,7 +2316,7 @@ do_static_initialization (tree decl, tree init)
   if (flag_use_cxa_atexit)
     register_dtor_fn (decl);
 
-  /* Finsh up.  */
+  /* Finish up.  */
   finish_static_initialization_or_destruction (guard_if_stmt);
 }
 
@@ -2482,7 +2430,11 @@ generate_ctor_or_dtor_function (bool constructor_p, int priority,
   size_t i;
 
   input_location = *locus;
+#ifdef USE_MAPPED_LOCATION
+  /* ??? */
+#else
   locus->line++;
+#endif
   
   /* We use `I' to indicate initialization and `D' to indicate
      destruction.  */
@@ -2576,16 +2528,21 @@ cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
 {
   tree t = *tp;
 
-  switch (TREE_CODE (t))
-    {
-    case PTRMEM_CST:
-      if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
-       cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
-      break;
+  if (flag_unit_at_a_time)
+    switch (TREE_CODE (t))
+      {
+      case PTRMEM_CST:
+       if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
+         cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (t)));
+       break;
+      case BASELINK:
+       if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL)
+         cgraph_mark_needed_node (cgraph_node (BASELINK_FUNCTIONS (t)));
+       break;
 
-    default:
-      break;
-    }
+      default:
+       break;
+      }
 
   return NULL;
 }
@@ -2596,7 +2553,7 @@ cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
    first, since that way we only need to reverse the decls once.  */
 
 void
-finish_file ()
+finish_file (void)
 {
   tree vars;
   bool reconsider;
@@ -2614,9 +2571,13 @@ finish_file ()
   if (pch_file)
     c_common_write_pch ();
 
+#ifdef USE_MAPPED_LOCATION
+  /* FIXME - huh? */
+#else
   /* Otherwise, GDB can get confused, because in only knows
      about source for LINENO-1 lines.  */
   input_line -= 1;
+#endif
 
   interface_unknown = 1;
   interface_only = 0;
@@ -2640,7 +2601,7 @@ finish_file ()
   timevar_push (TV_VARCONST);
 
   emit_support_tinfos ();
-  
+
   do 
     {
       tree t;
@@ -2651,6 +2612,7 @@ finish_file ()
       /* If there are templates that we've put off instantiating, do
         them now.  */
       instantiate_pending_templates ();
+      ggc_collect ();
 
       /* Write out virtual tables as required.  Note that writing out
         the virtual table for a template class may cause the
@@ -2771,13 +2733,20 @@ finish_file ()
             instantiations, etc.  */
          reconsider = true;
          ssdf_count++;
+#ifdef USE_MAPPED_LOCATION
+         /* ??? */
+#else
          locus.line++;
+#endif
        }
       
       for (i = 0; i < deferred_fns_used; ++i)
        {
          tree decl = VARRAY_TREE (deferred_fns, i);
 
+         if (! DECL_DECLARED_INLINE_P (decl) || ! TREE_USED (decl))
+           abort ();
+
          /* Does it need synthesizing?  */
          if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
              && TREE_USED (decl)
@@ -2794,12 +2763,6 @@ finish_file ()
              reconsider = true;
            }
 
-         /* If the function has no body, avoid calling
-            import_export_decl.  On a system without weak symbols,
-            calling import_export_decl will make an inline template
-            instantiation "static", which will result in errors about
-            the use of undefined functions if there is no body for
-            the function.  */
          if (!DECL_SAVED_TREE (decl))
            continue;
 
@@ -2826,7 +2789,6 @@ finish_file ()
             gotten around to synthesizing yet.)  */
          if (!DECL_EXTERNAL (decl)
              && DECL_NEEDED_P (decl)
-             && DECL_SAVED_TREE (decl)
              && !TREE_ASM_WRITTEN (decl)
              && (!flag_unit_at_a_time 
                  || !cgraph_node (decl)->local.finalized))
@@ -2874,12 +2836,11 @@ finish_file ()
     {
       tree decl = VARRAY_TREE (deferred_fns, i);
 
-      if (TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl)
-         && !(TREE_ASM_WRITTEN (decl) || DECL_SAVED_TREE (decl)
-              /* An explicit instantiation can be used to specify
-                 that the body is in another unit. It will have
-                 already verified there was a definition.  */
-              || DECL_EXPLICIT_INSTANTIATION (decl)))
+      if (!TREE_ASM_WRITTEN (decl) && !DECL_SAVED_TREE (decl)
+         /* An explicit instantiation can be used to specify
+            that the body is in another unit. It will have
+            already verified there was a definition.  */
+         && !DECL_EXPLICIT_INSTANTIATION (decl))
        {
          cp_warning_at ("inline function `%D' used but never defined", decl);
          /* This symbol is effectively an "extern" declaration now.
@@ -2924,6 +2885,11 @@ finish_file ()
       cgraph_optimize ();
     }
 
+  /* Emit mudflap static registration function.  This must be done
+     after all the user functions have been expanded.  */
+  if (flag_mudflap)
+    mudflap_finish_file ();
+
   /* Now, issue warnings about static, but not defined, functions,
      etc., and emit debugging information.  */
   walk_namespaces (wrapup_globals_for_namespace, /*data=*/&reconsider);
@@ -2937,12 +2903,12 @@ finish_file ()
      to a file.  */
   {
     int flags;
-    FILE *stream = dump_begin (TDI_all, &flags);
+    FILE *stream = dump_begin (TDI_tu, &flags);
 
     if (stream)
       {
        dump_node (global_namespace, flags & ~TDF_SLIM, stream);
-       dump_end (TDI_all, stream);
+       dump_end (TDI_tu, stream);
       }
   }
   
@@ -2954,6 +2920,10 @@ finish_file ()
       dump_time_statistics ();
     }
   input_location = locus;
+
+#ifdef ENABLE_CHECKING
+  validate_conversion_obstack ();
+#endif /* ENABLE_CHECKING */
 }
 
 /* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the
@@ -2980,7 +2950,7 @@ build_offset_ref_call_from_tree (tree fn, tree args)
                          20030708);
       if (type_dependent_expression_p (fn)
          || any_type_dependent_arguments_p (args))
-       return build_min_nt (CALL_EXPR, fn, args);
+       return build_min_nt (CALL_EXPR, fn, args, NULL_TREE);
 
       /* Transform the arguments and add the implicit "this"
         parameter.  That must be done before the FN is transformed
@@ -3010,1119 +2980,10 @@ build_offset_ref_call_from_tree (tree fn, tree args)
 
   expr = build_function_call (fn, args);
   if (processing_template_decl && expr != error_mark_node)
-    return build_min_non_dep (CALL_EXPR, expr, orig_fn, orig_args);
+    return build_min_non_dep (CALL_EXPR, expr, orig_fn, orig_args, NULL_TREE);
   return expr;
 }
-
-/* Returns true if ROOT (a namespace, class, or function) encloses
-   CHILD.  CHILD may be either a class type or a namespace.  */
-
-bool
-is_ancestor (tree root, tree child)
-{
-  my_friendly_assert ((TREE_CODE (root) == NAMESPACE_DECL
-                      || TREE_CODE (root) == FUNCTION_DECL
-                      || CLASS_TYPE_P (root)), 20030307);
-  my_friendly_assert ((TREE_CODE (child) == NAMESPACE_DECL
-                      || CLASS_TYPE_P (child)),
-                     20030307);
-  
-  /* The global namespace encloses everything.  */
-  if (root == global_namespace)
-    return true;
-
-  while (true)
-    {
-      /* If we've run out of scopes, stop.  */
-      if (!child)
-       return false;
-      /* If we've reached the ROOT, it encloses CHILD.  */
-      if (root == child)
-       return true;
-      /* Go out one level.  */
-      if (TYPE_P (child))
-       child = TYPE_NAME (child);
-      child = DECL_CONTEXT (child);
-    }
-}
-  
-
-/* Return the namespace that is the common ancestor 
-   of two given namespaces.  */
-
-tree
-namespace_ancestor (tree ns1, tree ns2)
-{
-  timevar_push (TV_NAME_LOOKUP);
-  if (is_ancestor (ns1, ns2))
-    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ns1);
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
-                          namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2));
-}
-
-/* Insert USED into the using list of USER. Set INDIRECT_flag if this
-   directive is not directly from the source. Also find the common
-   ancestor and let our users know about the new namespace */
-static void 
-add_using_namespace (tree user, tree used, bool indirect)
-{
-  tree t;
-  timevar_push (TV_NAME_LOOKUP);
-  /* Using oneself is a no-op.  */
-  if (user == used)
-    {
-      timevar_pop (TV_NAME_LOOKUP);
-      return;
-    }
-  my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380);
-  my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380);
-  /* Check if we already have this.  */
-  t = purpose_member (used, DECL_NAMESPACE_USING (user));
-  if (t != NULL_TREE)
-    {
-      if (!indirect)
-       /* Promote to direct usage.  */
-       TREE_INDIRECT_USING (t) = 0;
-      timevar_pop (TV_NAME_LOOKUP);
-      return;
-    }
-
-  /* Add used to the user's using list.  */
-  DECL_NAMESPACE_USING (user) 
-    = tree_cons (used, namespace_ancestor (user, used), 
-                DECL_NAMESPACE_USING (user));
-
-  TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect;
-
-  /* Add user to the used's users list.  */
-  DECL_NAMESPACE_USERS (used)
-    = tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
-
-  /* Recursively add all namespaces used.  */
-  for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))
-    /* indirect usage */
-    add_using_namespace (user, TREE_PURPOSE (t), 1);
-
-  /* Tell everyone using us about the new used namespaces.  */
-  for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t))
-    add_using_namespace (TREE_PURPOSE (t), used, 1);
-  timevar_pop (TV_NAME_LOOKUP);
-}
-
-/* Combines two sets of overloaded functions into an OVERLOAD chain, removing
-   duplicates.  The first list becomes the tail of the result.
-
-   The algorithm is O(n^2).  We could get this down to O(n log n) by
-   doing a sort on the addresses of the functions, if that becomes
-   necessary.  */
-
-static tree
-merge_functions (tree s1, tree s2)
-{
-  for (; s2; s2 = OVL_NEXT (s2))
-    {
-      tree fn2 = OVL_CURRENT (s2);
-      tree fns1;
-
-      for (fns1 = s1; fns1; fns1 = OVL_NEXT (fns1))
-       {
-         tree fn1 = OVL_CURRENT (fns1);
-
-         /* If the function from S2 is already in S1, there is no
-            need to add it again.  For `extern "C"' functions, we
-            might have two FUNCTION_DECLs for the same function, in
-            different namespaces; again, we only need one of them.  */
-         if (fn1 == fn2 
-             || (DECL_EXTERN_C_P (fn1) && DECL_EXTERN_C_P (fn2)
-                 && DECL_NAME (fn1) == DECL_NAME (fn2)))
-           break;
-       }
-      
-      /* If we exhausted all of the functions in S1, FN2 is new.  */
-      if (!fns1)
-       s1 = build_overload (fn2, s1);
-    }
-  return s1;
-}
-
-/* This should return an error not all definitions define functions.
-   It is not an error if we find two functions with exactly the
-   same signature, only if these are selected in overload resolution.
-   old is the current set of bindings, new the freshly-found binding.
-   XXX Do we want to give *all* candidates in case of ambiguity?
-   XXX In what way should I treat extern declarations?
-   XXX I don't want to repeat the entire duplicate_decls here */
-
-static cxx_binding *
-ambiguous_decl (tree name, cxx_binding *old, cxx_binding *new, int flags)
-{
-  tree val, type;
-  my_friendly_assert (old != NULL, 393);
-  /* Copy the value.  */
-  val = BINDING_VALUE (new);
-  if (val)
-    switch (TREE_CODE (val))
-      {
-      case TEMPLATE_DECL:
-        /* If we expect types or namespaces, and not templates,
-           or this is not a template class.  */
-        if (LOOKUP_QUALIFIERS_ONLY (flags)
-            && !DECL_CLASS_TEMPLATE_P (val))
-          val = NULL_TREE;
-        break;
-      case TYPE_DECL:
-        if (LOOKUP_NAMESPACES_ONLY (flags))
-          val = NULL_TREE;
-        break;
-      case NAMESPACE_DECL:
-        if (LOOKUP_TYPES_ONLY (flags))
-          val = NULL_TREE;
-        break;
-      case FUNCTION_DECL:
-        /* Ignore built-in functions that are still anticipated.  */
-        if (LOOKUP_QUALIFIERS_ONLY (flags) || DECL_ANTICIPATED (val))
-          val = NULL_TREE;
-        break;
-      default:
-        if (LOOKUP_QUALIFIERS_ONLY (flags))
-          val = NULL_TREE;
-      }
-        
-  if (!BINDING_VALUE (old))
-    BINDING_VALUE (old) = val;
-  else if (val && val != BINDING_VALUE (old))
-    {
-      if (is_overloaded_fn (BINDING_VALUE (old)) && is_overloaded_fn (val))
-        BINDING_VALUE (old) = merge_functions (BINDING_VALUE (old), val);
-      else
-       {
-         /* Some declarations are functions, some are not.  */
-          if (flags & LOOKUP_COMPLAIN)
-            {
-             /* If we've already given this error for this lookup,
-                BINDING_VALUE (old) is error_mark_node, so let's not
-                repeat ourselves.  */
-             if (BINDING_VALUE (old) != error_mark_node)
-               {
-                 error ("use of `%D' is ambiguous", name);
-                 cp_error_at ("  first declared as `%#D' here",
-                              BINDING_VALUE (old));
-               }
-              cp_error_at ("  also declared as `%#D' here", val);
-            }
-         BINDING_VALUE (old) = error_mark_node;
-       }
-    }
-  /* ... and copy the type.  */
-  type = BINDING_TYPE (new);
-  if (LOOKUP_NAMESPACES_ONLY (flags))
-    type = NULL_TREE;
-  if (!BINDING_TYPE (old))
-    BINDING_TYPE (old) = type;
-  else if (type && BINDING_TYPE (old) != type)
-    {
-      if (flags & LOOKUP_COMPLAIN)
-        {
-          error ("`%D' denotes an ambiguous type",name);
-          error ("%J  first type here", TYPE_MAIN_DECL (BINDING_TYPE (old)));
-          error ("%J  other type here", TYPE_MAIN_DECL (type));
-        }
-    }
-  return old;
-}
-
-/* Subroutine of unualified_namespace_lookup:
-   Add the bindings of NAME in used namespaces to VAL.
-   We are currently looking for names in namespace SCOPE, so we
-   look through USINGS for using-directives of namespaces
-   which have SCOPE as a common ancestor with the current scope.
-   Returns false on errors.  */
-
-bool
-lookup_using_namespace (tree name, cxx_binding *val, tree usings, tree scope,
-                        int flags, tree *spacesp)
-{
-  tree iter;
-  timevar_push (TV_NAME_LOOKUP);
-  /* Iterate over all used namespaces in current, searching for using
-     directives of scope.  */
-  for (iter = usings; iter; iter = TREE_CHAIN (iter))
-    if (TREE_VALUE (iter) == scope)
-      {
-        tree used = ORIGINAL_NAMESPACE (TREE_PURPOSE (iter));
-        cxx_binding *val1 =
-          cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (used), name);
-        if (spacesp)
-          *spacesp = tree_cons (used, NULL_TREE, *spacesp);
-        /* Resolve ambiguities.  */
-        if (val1)
-          val = ambiguous_decl (name, val, val1, flags);
-      }
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
-                          BINDING_VALUE (val) != error_mark_node);
-}
-
-/* [namespace.qual]
-   Accepts the NAME to lookup and its qualifying SCOPE.
-   Returns the name/type pair found into the cxx_binding *RESULT,
-   or false on error.  */
-
-bool
-qualified_lookup_using_namespace (tree name, tree scope, cxx_binding *result,
-                                  int flags)
-{
-  /* Maintain a list of namespaces visited...  */
-  tree seen = NULL_TREE;
-  /* ... and a list of namespace yet to see.  */
-  tree todo = NULL_TREE;
-  tree usings;
-  timevar_push (TV_NAME_LOOKUP);
-  /* Look through namespace aliases.  */
-  scope = ORIGINAL_NAMESPACE (scope);
-  while (scope && result->value != error_mark_node)
-    {
-      cxx_binding *binding =
-        cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name);
-      seen = tree_cons (scope, NULL_TREE, seen);
-      if (binding)
-        result = ambiguous_decl (name, result, binding, flags);
-      if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
-       /* Consider using directives.  */
-       for (usings = DECL_NAMESPACE_USING (scope); usings;
-            usings = TREE_CHAIN (usings))
-         /* If this was a real directive, and we have not seen it.  */
-         if (!TREE_INDIRECT_USING (usings)
-             && !purpose_member (TREE_PURPOSE (usings), seen))
-           todo = tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
-      if (todo)
-       {
-         scope = TREE_PURPOSE (todo);
-         todo = TREE_CHAIN (todo);
-       }
-      else
-       scope = NULL_TREE; /* If there never was a todo list.  */
-    }
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result->value != error_mark_node);
-}
-
-/* [namespace.memdef]/2 */
-
-/* Set the context of a declaration to scope. Complain if we are not
-   outside scope.  */
-
-void
-set_decl_namespace (tree decl, tree scope, bool friendp)
-{
-  tree old;
-  
-  /* Get rid of namespace aliases.  */
-  scope = ORIGINAL_NAMESPACE (scope);
-  
-  /* It is ok for friends to be qualified in parallel space.  */
-  if (!friendp && !is_ancestor (current_namespace, scope))
-    error ("declaration of `%D' not in a namespace surrounding `%D'",
-             decl, scope);
-  DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
-  if (scope != current_namespace)
-    {
-      /* See whether this has been declared in the namespace.  */
-      old = namespace_binding (DECL_NAME (decl), scope);
-      if (!old)
-       /* No old declaration at all.  */
-       goto complain;
-      /* A template can be explicitly specialized in any namespace.  */
-      if (processing_explicit_instantiation)
-       return;
-      if (!is_overloaded_fn (decl))
-       /* Don't compare non-function decls with decls_match here,
-          since it can't check for the correct constness at this
-          point. pushdecl will find those errors later.  */
-       return;
-      /* Since decl is a function, old should contain a function decl.  */
-      if (!is_overloaded_fn (old))
-       goto complain;
-      if (processing_template_decl || processing_specialization)
-       /* We have not yet called push_template_decl to turn a
-          FUNCTION_DECL into a TEMPLATE_DECL, so the declarations
-          won't match.  But, we'll check later, when we construct the
-          template.  */
-       return;
-      if (is_overloaded_fn (old))
-       {
-         for (; old; old = OVL_NEXT (old))
-           if (decls_match (decl, OVL_CURRENT (old)))
-             return;
-       }
-      else
-       if (decls_match (decl, old))
-         return;
-    }
-  else
-    return;
- complain:
-  error ("`%D' should have been declared inside `%D'",
-           decl, scope);
-} 
-
-/* Compute the namespace where a declaration is defined.  */
-
-static tree
-decl_namespace (tree decl)
-{
-  timevar_push (TV_NAME_LOOKUP);
-  if (TYPE_P (decl))
-    decl = TYPE_STUB_DECL (decl);
-  while (DECL_CONTEXT (decl))
-    {
-      decl = DECL_CONTEXT (decl);
-      if (TREE_CODE (decl) == NAMESPACE_DECL)
-       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
-      if (TYPE_P (decl))
-       decl = TYPE_STUB_DECL (decl);
-      my_friendly_assert (DECL_P (decl), 390);
-    }
-
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, global_namespace);
-}
-
-/* Return the namespace where the current declaration is declared.  */
-
-tree
-current_decl_namespace (void)
-{
-  tree result;
-  /* If we have been pushed into a different namespace, use it.  */
-  if (decl_namespace_list)
-    return TREE_PURPOSE (decl_namespace_list);
-
-  if (current_class_type)
-    result = decl_namespace (TYPE_STUB_DECL (current_class_type));
-  else if (current_function_decl)
-    result = decl_namespace (current_function_decl);
-  else 
-    result = current_namespace;
-  return result;
-}
-
-/* Temporarily set the namespace for the current declaration.  */
-
-void
-push_decl_namespace (tree decl)
-{
-  if (TREE_CODE (decl) != NAMESPACE_DECL)
-    decl = decl_namespace (decl);
-  decl_namespace_list = tree_cons (ORIGINAL_NAMESPACE (decl),
-                                   NULL_TREE, decl_namespace_list);
-}
-
-void
-pop_decl_namespace (void)
-{
-  decl_namespace_list = TREE_CHAIN (decl_namespace_list);
-}
-
-/* Enter a class or namespace scope.  */
-
-void
-push_scope (tree t)
-{
-  if (TREE_CODE (t) == NAMESPACE_DECL)
-    push_decl_namespace (t);
-  else if CLASS_TYPE_P (t)
-    push_nested_class (t);
-}
-
-/* Leave scope pushed by push_scope.  */
-
-void
-pop_scope (tree t)
-{
-  if (TREE_CODE (t) == NAMESPACE_DECL)
-    pop_decl_namespace ();
-  else if CLASS_TYPE_P (t)
-    pop_nested_class ();
-}
-
-/* [basic.lookup.koenig] */
-/* A nonzero return value in the functions below indicates an error.  */
-
-struct arg_lookup
-{
-  tree name;
-  tree namespaces;
-  tree classes;
-  tree functions;
-};
-
-static bool arg_assoc (struct arg_lookup*, tree);
-static bool arg_assoc_args (struct arg_lookup*, tree);
-static bool arg_assoc_type (struct arg_lookup*, tree);
-static bool add_function (struct arg_lookup *, tree);
-static bool arg_assoc_namespace (struct arg_lookup *, tree);
-static bool arg_assoc_class (struct arg_lookup *, tree);
-static bool arg_assoc_template_arg (struct arg_lookup*, tree);
-
-/* Add a function to the lookup structure.
-   Returns true on error.  */
-
-static bool
-add_function (struct arg_lookup *k, tree fn)
-{
-  /* We used to check here to see if the function was already in the list,
-     but that's O(n^2), which is just too expensive for function lookup.
-     Now we deal with the occasional duplicate in joust.  In doing this, we
-     assume that the number of duplicates will be small compared to the
-     total number of functions being compared, which should usually be the
-     case.  */
-
-  /* We must find only functions, or exactly one non-function.  */
-  if (!k->functions) 
-    k->functions = fn;
-  else if (fn == k->functions)
-    ;
-  else if (is_overloaded_fn (k->functions) && is_overloaded_fn (fn))
-    k->functions = build_overload (fn, k->functions);
-  else
-    {
-      tree f1 = OVL_CURRENT (k->functions);
-      tree f2 = fn;
-      if (is_overloaded_fn (f1))
-       {
-         fn = f1; f1 = f2; f2 = fn;
-       }
-      cp_error_at ("`%D' is not a function,", f1);
-      cp_error_at ("  conflict with `%D'", f2);
-      error ("  in call to `%D'", k->name);
-      return true;
-    }
-
-  return false;
-}
-
-/* Add functions of a namespace to the lookup structure.
-   Returns true on error.  */
-
-static bool
-arg_assoc_namespace (struct arg_lookup *k, tree scope)
-{
-  tree value;
-
-  if (purpose_member (scope, k->namespaces))
-    return 0;
-  k->namespaces = tree_cons (scope, NULL_TREE, k->namespaces);
-  
-  value = namespace_binding (k->name, scope);
-  if (!value)
-    return false;
-
-  for (; value; value = OVL_NEXT (value))
-    if (add_function (k, OVL_CURRENT (value)))
-      return true;
-  
-  return false;
-}
-
-/* Adds everything associated with a template argument to the lookup
-   structure.  Returns true on error.  */
-
-static bool
-arg_assoc_template_arg (struct arg_lookup *k, tree arg)
-{
-  /* [basic.lookup.koenig]
-
-     If T is a template-id, its associated namespaces and classes are
-     ... the namespaces and classes associated with the types of the
-     template arguments provided for template type parameters
-     (excluding template template parameters); the namespaces in which
-     any template template arguments are defined; and the classes in
-     which any member templates used as template template arguments
-     are defined.  [Note: non-type template arguments do not
-     contribute to the set of associated namespaces.  ]  */
-
-  /* Consider first template template arguments.  */
-  if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
-      || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE)
-    return false;
-  else if (TREE_CODE (arg) == TEMPLATE_DECL)
-    {
-      tree ctx = CP_DECL_CONTEXT (arg);
-
-      /* It's not a member template.  */
-      if (TREE_CODE (ctx) == NAMESPACE_DECL)
-        return arg_assoc_namespace (k, ctx);
-      /* Otherwise, it must be member template.  */
-      else 
-        return arg_assoc_class (k, ctx);
-    }
-  /* It's not a template template argument, but it is a type template
-     argument.  */
-  else if (TYPE_P (arg))
-    return arg_assoc_type (k, arg);
-  /* It's a non-type template argument.  */
-  else
-    return false;
-}
-
-/* Adds everything associated with class to the lookup structure.
-   Returns true on error.  */
-
-static bool
-arg_assoc_class (struct arg_lookup *k, tree type)
-{
-  tree list, friends, context;
-  int i;
-  
-  /* Backend build structures, such as __builtin_va_list, aren't
-     affected by all this.  */
-  if (!CLASS_TYPE_P (type))
-    return false;
-
-  if (purpose_member (type, k->classes))
-    return false;
-  k->classes = tree_cons (type, NULL_TREE, k->classes);
-  
-  context = decl_namespace (TYPE_MAIN_DECL (type));
-  if (arg_assoc_namespace (k, context))
-    return true;
-  
-  /* Process baseclasses.  */
-  for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); i++)
-    if (arg_assoc_class (k, TYPE_BINFO_BASETYPE (type, i)))
-      return true;
-  
-  /* Process friends.  */
-  for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list; 
-       list = TREE_CHAIN (list))
-    if (k->name == FRIEND_NAME (list))
-      for (friends = FRIEND_DECLS (list); friends; 
-          friends = TREE_CHAIN (friends))
-       /* Only interested in global functions with potentially hidden
-           (i.e. unqualified) declarations.  */
-       if (CP_DECL_CONTEXT (TREE_VALUE (friends)) == context)
-         if (add_function (k, TREE_VALUE (friends)))
-           return true;
-
-  /* Process template arguments.  */
-  if (CLASSTYPE_TEMPLATE_INFO (type))
-    {
-      list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
-      for (i = 0; i < TREE_VEC_LENGTH (list); ++i) 
-        arg_assoc_template_arg (k, TREE_VEC_ELT (list, i));
-    }
-
-  return false;
-}
-
-/* Adds everything associated with a given type.
-   Returns 1 on error.  */
-
-static bool
-arg_assoc_type (struct arg_lookup *k, tree type)
-{
-  /* As we do not get the type of non-type dependent expressions
-     right, we can end up with such things without a type.  */
-  if (!type)
-    return false;
-
-  if (TYPE_PTRMEM_P (type))
-    {
-      /* Pointer to member: associate class type and value type.  */
-      if (arg_assoc_type (k, TYPE_PTRMEM_CLASS_TYPE (type)))
-       return true;
-      return arg_assoc_type (k, TYPE_PTRMEM_POINTED_TO_TYPE (type));
-    }
-  else switch (TREE_CODE (type))
-    {
-    case ERROR_MARK:
-      return false;
-    case VOID_TYPE:
-    case INTEGER_TYPE:
-    case REAL_TYPE:
-    case COMPLEX_TYPE:
-    case VECTOR_TYPE:
-    case CHAR_TYPE:
-    case BOOLEAN_TYPE:
-      return false;
-    case RECORD_TYPE:
-      if (TYPE_PTRMEMFUNC_P (type))
-       return arg_assoc_type (k, TYPE_PTRMEMFUNC_FN_TYPE (type));
-      return arg_assoc_class (k, type);
-    case POINTER_TYPE:
-    case REFERENCE_TYPE:
-    case ARRAY_TYPE:
-      return arg_assoc_type (k, TREE_TYPE (type));
-    case UNION_TYPE:
-    case ENUMERAL_TYPE:
-      return arg_assoc_namespace (k, decl_namespace (TYPE_MAIN_DECL (type)));
-    case METHOD_TYPE:
-      /* The basetype is referenced in the first arg type, so just
-        fall through.  */
-    case FUNCTION_TYPE:
-      /* Associate the parameter types.  */
-      if (arg_assoc_args (k, TYPE_ARG_TYPES (type)))
-       return true;
-      /* Associate the return type.  */
-      return arg_assoc_type (k, TREE_TYPE (type));
-    case TEMPLATE_TYPE_PARM:
-    case BOUND_TEMPLATE_TEMPLATE_PARM:
-      return false;
-    case TYPENAME_TYPE:
-      return false;
-    case LANG_TYPE:
-      if (type == unknown_type_node)
-       return false;
-      /* else fall through */
-    default:
-      abort ();
-    }
-  return false;
-}
-
-/* Adds everything associated with arguments.  Returns true on error.  */
-
-static bool
-arg_assoc_args (struct arg_lookup *k, tree args)
-{
-  for (; args; args = TREE_CHAIN (args))
-    if (arg_assoc (k, TREE_VALUE (args)))
-      return true;
-  return false;
-}
-
-/* Adds everything associated with a given tree_node.  Returns 1 on error.  */
-
-static bool
-arg_assoc (struct arg_lookup *k, tree n)
-{
-  if (n == error_mark_node)
-    return false;
-
-  if (TYPE_P (n))
-    return arg_assoc_type (k, n);
-
-  if (! type_unknown_p (n))
-    return arg_assoc_type (k, TREE_TYPE (n));
-
-  if (TREE_CODE (n) == ADDR_EXPR)
-    n = TREE_OPERAND (n, 0);
-  if (TREE_CODE (n) == COMPONENT_REF)
-    n = TREE_OPERAND (n, 1);
-  if (TREE_CODE (n) == OFFSET_REF)
-    n = TREE_OPERAND (n, 1);
-  while (TREE_CODE (n) == TREE_LIST)
-    n = TREE_VALUE (n);
-  if (TREE_CODE (n) == BASELINK)
-    n = BASELINK_FUNCTIONS (n);
-
-  if (TREE_CODE (n) == FUNCTION_DECL)
-    return arg_assoc_type (k, TREE_TYPE (n));
-  if (TREE_CODE (n) == TEMPLATE_ID_EXPR)
-    {
-      /* [basic.lookup.koenig]
-
-        If T is a template-id, its associated namespaces and classes
-        are the namespace in which the template is defined; for
-        member templates, the member template's class...  */
-      tree template = TREE_OPERAND (n, 0);
-      tree args = TREE_OPERAND (n, 1);
-      tree ctx;
-      int ix;
-
-      if (TREE_CODE (template) == COMPONENT_REF)
-        template = TREE_OPERAND (template, 1);
-      
-      /* First, the template.  There may actually be more than one if
-        this is an overloaded function template.  But, in that case,
-        we only need the first; all the functions will be in the same
-        namespace.  */
-      template = OVL_CURRENT (template);
-
-      ctx = CP_DECL_CONTEXT (template);
-       
-      if (TREE_CODE (ctx) == NAMESPACE_DECL)
-       {
-         if (arg_assoc_namespace (k, ctx) == 1)
-           return true;
-       }
-      /* It must be a member template.  */
-      else if (arg_assoc_class (k, ctx) == 1)
-       return true;
-
-      /* Now the arguments.  */
-      for (ix = TREE_VEC_LENGTH (args); ix--;)
-       if (arg_assoc_template_arg (k, TREE_VEC_ELT (args, ix)) == 1)
-         return true;
-    }
-  else
-    {
-      my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
-      
-      for (; n; n = OVL_CHAIN (n))
-       if (arg_assoc_type (k, TREE_TYPE (OVL_FUNCTION (n))))
-         return true;
-    }
-
-  return false;
-}
-
-/* Performs Koenig lookup depending on arguments, where fns
-   are the functions found in normal lookup.  */
-
-tree
-lookup_arg_dependent (tree name, tree fns, tree args)
-{
-  struct arg_lookup k;
-  tree fn = NULL_TREE;
-
-  timevar_push (TV_NAME_LOOKUP);
-  k.name = name;
-  k.functions = fns;
-  k.classes = NULL_TREE;
-
-  /* Note that we've already looked at some namespaces during normal
-     unqualified lookup, unless we found a decl in function scope.  */
-  if (fns)
-    fn = OVL_CURRENT (fns);
-  if (fn && TREE_CODE (fn) == FUNCTION_DECL && DECL_LOCAL_FUNCTION_P (fn))
-    k.namespaces = NULL_TREE;
-  else
-    unqualified_namespace_lookup (name, 0, &k.namespaces);
-
-  arg_assoc_args (&k, args);
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, k.functions);
-}
-
-/* Process a namespace-alias declaration.  */
-
-void
-do_namespace_alias (tree alias, tree namespace)
-{
-  if (TREE_CODE (namespace) != NAMESPACE_DECL)
-    {
-      /* The parser did not find it, so it's not there.  */
-      error ("unknown namespace `%D'", namespace);
-      return;
-    }
-
-  namespace = ORIGINAL_NAMESPACE (namespace);
-
-  /* Build the alias.  */
-  alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node);     
-  DECL_NAMESPACE_ALIAS (alias) = namespace;
-  DECL_EXTERNAL (alias) = 1;
-  pushdecl (alias);
-}
-
-/* Check a non-member using-declaration. Return the name and scope
-   being used, and the USING_DECL, or NULL_TREE on failure.  */
-
-static tree
-validate_nonmember_using_decl (tree decl, tree *scope, tree *name)
-{
-  *scope = global_namespace;
-  *name = NULL_TREE;
-
-  if (TREE_CODE (decl) == TEMPLATE_ID_EXPR)
-    {
-      *name = TREE_OPERAND (decl, 0);
-      /* 7.3.3/5
-          A using-declaration shall not name a template-id.  */
-      error ("a using-declaration cannot specify a template-id.  Try `using %D'", *name);
-      return NULL_TREE;
-    }
-
-  if (TREE_CODE (decl) == NAMESPACE_DECL)
-    {
-      error ("namespace `%D' not allowed in using-declaration", decl);
-      return NULL_TREE;
-    }
-
-  if (TREE_CODE (decl) == SCOPE_REF)
-    {
-      /* It's a nested name with template parameter dependent scope.
-        This can only be using-declaration for class member.  */
-      error ("`%T' is not a namespace", TREE_OPERAND (decl, 0));
-      return NULL_TREE;
-    }
-
-  if (is_overloaded_fn (decl))
-    decl = get_first_fn (decl);
-
-  my_friendly_assert (DECL_P (decl), 20020908);
-
-  if (TREE_CODE (decl) == CONST_DECL)
-    /* Enumeration constants to not have DECL_CONTEXT set.  */
-    *scope = TYPE_CONTEXT (TREE_TYPE (decl));
-  else
-    *scope = DECL_CONTEXT (decl);
-  if (!*scope)
-    *scope = global_namespace;
-
-  /* [namespace.udecl]
-       A using-declaration for a class member shall be a
-       member-declaration.  */
-  if (TYPE_P (*scope))
-    {
-      error ("`%T' is not a namespace", *scope);
-      return NULL_TREE;
-    }
-  *name = DECL_NAME (decl);
-  /* Make a USING_DECL.  */
-  return push_using_decl (*scope, *name);
-}
-
-/* Process local and global using-declarations.  */
-
-static void
-do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype,
-                         tree *newval, tree *newtype)
-{
-  cxx_binding decls;
-
-  *newval = *newtype = NULL_TREE;
-  cxx_binding_clear (&decls);
-  if (!qualified_lookup_using_namespace (name, scope, &decls, 0))
-    /* Lookup error */
-    return;
-
-  if (!decls.value && !decls.type)
-    {
-      error ("`%D' not declared", name);
-      return;
-    }
-
-  /* Check for using functions.  */
-  if (decls.value && is_overloaded_fn (decls.value))
-    {
-      tree tmp, tmp1;
-
-      if (oldval && !is_overloaded_fn (oldval))
-       {
-         if (!DECL_IMPLICIT_TYPEDEF_P (oldval))
-           error ("`%D' is already declared in this scope", name);
-         oldval = NULL_TREE;
-       }
-
-      *newval = oldval;
-      for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp))
-       {
-         tree new_fn = OVL_CURRENT (tmp);
-
-         /* [namespace.udecl]
-
-            If a function declaration in namespace scope or block
-            scope has the same name and the same parameter types as a
-            function introduced by a using declaration the program is
-            ill-formed.  */
-         for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
-           {
-             tree old_fn = OVL_CURRENT (tmp1);
-
-              if (new_fn == old_fn)
-                /* The function already exists in the current namespace.  */
-                break;
-             else if (OVL_USED (tmp1))
-               continue; /* this is a using decl */
-             else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
-                                 TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
-               {
-                 /* There was already a non-using declaration in
-                    this scope with the same parameter types. If both
-                    are the same extern "C" functions, that's ok.  */
-                  if (decls_match (new_fn, old_fn))
-                   {
-                     /* If the OLD_FN was a builtin, there is now a
-                        real declaration.  */
-                     if (DECL_ANTICIPATED (old_fn))
-                       DECL_ANTICIPATED (old_fn) = 0;
-                     break;
-                   }
-                 else if (!DECL_ANTICIPATED (old_fn))
-                   {
-                     /* If the OLD_FN was really declared, the
-                        declarations don't match.  */
-                     error ("`%D' is already declared in this scope", name);
-                     break;
-                   }
-
-                 /* If the OLD_FN was not really there, just ignore
-                    it and keep going.  */
-               }
-           }
-
-         /* If we broke out of the loop, there's no reason to add
-            this function to the using declarations for this
-            scope.  */
-         if (tmp1)
-           continue;
-           
-         *newval = build_overload (OVL_CURRENT (tmp), *newval);
-         if (TREE_CODE (*newval) != OVERLOAD)
-           *newval = ovl_cons (*newval, NULL_TREE);
-         OVL_USED (*newval) = 1;
-       }
-    }
-  else 
-    {
-      *newval = decls.value;
-      if (oldval && !decls_match (*newval, oldval))
-       error ("`%D' is already declared in this scope", name);
-    }
-
-  *newtype = decls.type;
-  if (oldtype && *newtype && !same_type_p (oldtype, *newtype))
-    {
-      error ("using declaration `%D' introduced ambiguous type `%T'",
-               name, oldtype);
-      return;
-    }
-}
-
-/* Process a using-declaration not appearing in class or local scope.  */
-
-void
-do_toplevel_using_decl (tree decl)
-{
-  tree scope, name;
-  tree oldval, oldtype, newval, newtype;
-  cxx_binding *binding;
-
-  decl = validate_nonmember_using_decl (decl, &scope, &name);
-  if (decl == NULL_TREE)
-    return;
   
-  binding = binding_for_name (NAMESPACE_LEVEL (current_namespace), name);
-
-  oldval = BINDING_VALUE (binding);
-  oldtype = BINDING_TYPE (binding);
-
-  do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
-
-  /* Copy declarations found.  */
-  if (newval)
-    BINDING_VALUE (binding) = newval;
-  if (newtype)
-    BINDING_TYPE (binding) = newtype;
-  return;
-}
-
-/* Process a using-declaration at function scope.  */
-
-void
-do_local_using_decl (tree decl)
-{
-  tree scope, name;
-  tree oldval, oldtype, newval, newtype;
-
-  decl = validate_nonmember_using_decl (decl, &scope, &name);
-  if (decl == NULL_TREE)
-    return;
-
-  if (building_stmt_tree ()
-      && at_function_scope_p ())
-    add_decl_stmt (decl);
-
-  oldval = lookup_name_current_level (name);
-  oldtype = lookup_type_current_level (name);
-
-  do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
-
-  if (newval)
-    {
-      if (is_overloaded_fn (newval))
-       {
-         tree fn, term;
-
-         /* We only need to push declarations for those functions
-            that were not already bound in the current level.
-            The old value might be NULL_TREE, it might be a single
-            function, or an OVERLOAD.  */
-         if (oldval && TREE_CODE (oldval) == OVERLOAD)
-           term = OVL_FUNCTION (oldval);
-         else
-           term = oldval;
-         for (fn = newval; fn && OVL_CURRENT (fn) != term; 
-              fn = OVL_NEXT (fn))
-           push_overloaded_decl (OVL_CURRENT (fn), 
-                                 PUSH_LOCAL | PUSH_USING);
-       }
-      else
-       push_local_binding (name, newval, PUSH_USING);
-    }
-  if (newtype)
-    set_identifier_type_value (name, newtype);
-}
-
-tree
-do_class_using_decl (tree decl)
-{
-  tree name, value, scope, type;
-  
-  if (TREE_CODE (decl) != SCOPE_REF
-      || !TREE_OPERAND (decl, 0)
-      || !TYPE_P (TREE_OPERAND (decl, 0)))
-    {
-      error ("using-declaration for non-member at class scope");
-      return NULL_TREE;
-    }
-  scope = TREE_OPERAND (decl, 0);
-  name = TREE_OPERAND (decl, 1);
-  if (TREE_CODE (name) == BIT_NOT_EXPR)
-    {
-      error ("using-declaration cannot name destructor");
-      return NULL_TREE;
-    }
-  if (TREE_CODE (name) == TYPE_DECL)
-    name = DECL_NAME (name);
-  else if (TREE_CODE (name) == TEMPLATE_DECL)
-     name = DECL_NAME (name);
-  else if (BASELINK_P (name))
-    {
-      tree fns = BASELINK_FUNCTIONS (name);
-      name = DECL_NAME (get_first_fn (fns));
-    }
-
-  my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
-
-  /* Dependent using decls have a NULL type, non-dependent ones have a
-     void type.  */
-  type = dependent_type_p (scope) ? NULL_TREE : void_type_node;
-  value = build_lang_decl (USING_DECL, name, type);
-  DECL_INITIAL (value) = scope;
-  return value;
-}
-
-/* Process a using-directive.  */
-
-void
-do_using_directive (tree namespace)
-{
-  if (building_stmt_tree ())
-    add_stmt (build_stmt (USING_STMT, namespace));
-  
-  /* using namespace A::B::C; */
-  if (TREE_CODE (namespace) == SCOPE_REF)
-      namespace = TREE_OPERAND (namespace, 1);
-  if (TREE_CODE (namespace) == IDENTIFIER_NODE)
-    {
-      /* Lookup in lexer did not find a namespace.  */
-      if (!processing_template_decl)
-       error ("namespace `%T' undeclared", namespace);
-      return;
-    }
-  if (TREE_CODE (namespace) != NAMESPACE_DECL)
-    {
-      if (!processing_template_decl)
-       error ("`%T' is not a namespace", namespace);
-      return;
-    }
-  namespace = ORIGINAL_NAMESPACE (namespace);
-  if (!toplevel_bindings_p ())
-    push_using_directive (namespace);
-  else
-    /* direct usage */
-    add_using_namespace (current_namespace, namespace, 0);
-}
 
 void
 check_default_args (tree x)
@@ -4153,8 +3014,17 @@ mark_used (tree decl)
   if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
       && !TREE_ASM_WRITTEN (decl))
     /* Remember it, so we can check it was defined.  */
-    defer_fn (decl);
-
+    {
+      if (DECL_DEFERRED_FN (decl))
+       return;
+      DECL_DEFERRED_FN (decl) = 1;
+      DECL_DEFER_OUTPUT (decl) = 1;
+      if (!deferred_fns)
+       VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
+      
+      VARRAY_PUSH_TREE (deferred_fns, decl);
+    }
+  
   assemble_external (decl);
 
   /* Is it a synthesized method that needs to be synthesized?  */
@@ -4192,13 +3062,20 @@ mark_used (tree decl)
 
         However, if instantiating this function might help us mark
         the current function TREE_NOTHROW, we go ahead and
-        instantiate it now.  */
+        instantiate it now.  
+        
+        This is not needed for unit-at-a-time since we reorder the functions
+        in topological order anyway.
+        */
       defer = (!flag_exceptions
+              || flag_unit_at_a_time
+              || !optimize
               || TREE_CODE (decl) != FUNCTION_DECL
               /* If the called function can't throw, we don't need to
                  generate its body to find that out.  */
               || TREE_NOTHROW (decl)
               || !cfun
+              || !current_function_decl
               /* If we already know the current function can't throw,
                  then we don't need to work hard to prove it.  */
               || TREE_NOTHROW (current_function_decl)
@@ -4207,7 +3084,7 @@ mark_used (tree decl)
                  information.  */
               || cp_function_chain->can_throw);
 
-      instantiate_decl (decl, defer);
+      instantiate_decl (decl, defer, /*undefined_ok=*/0);
     }
 }