OSDN Git Service

* lex.c (handle_cp_pragma): Remove #pragma vtable.
[pf3gnuchains/gcc-fork.git] / gcc / cp / call.c
index 8cef2f9..bb0b71a 100644 (file)
@@ -1,7 +1,7 @@
 /* Functions related to invoking methods and overloaded functions.
-   Copyright (C) 1987, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1987, 92-97, 1998 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com) and
-   hacked by Brendan Kehoe (brendan@cygnus.com).
+   modified by Brendan Kehoe (brendan@cygnus.com).
 
 This file is part of GNU CC.
 
@@ -24,15 +24,13 @@ Boston, MA 02111-1307, USA.  */
 /* High-level class interface.  */
 
 #include "config.h"
+#include "system.h"
 #include "tree.h"
-#include <stdio.h>
 #include "cp-tree.h"
 #include "output.h"
 #include "flags.h"
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
+#include "rtl.h"
+#include "toplev.h"
 
 #include "obstack.h"
 #define obstack_chunk_alloc xmalloc
@@ -46,12 +44,9 @@ static tree build_new_method_call PROTO((tree, tree, tree, tree, int));
 static tree build_field_call PROTO((tree, tree, tree, tree));
 static tree find_scoped_type PROTO((tree, tree, tree));
 static struct z_candidate * tourney PROTO((struct z_candidate *));
-static int joust PROTO((struct z_candidate *, struct z_candidate *));
-static int compare_qual PROTO((tree, tree));
+static int joust PROTO((struct z_candidate *, struct z_candidate *, int));
 static int compare_ics PROTO((tree, tree));
-static tree build_over_call PROTO((tree, tree, tree, int));
-static tree convert_default_arg PROTO((tree, tree));
-static void enforce_access PROTO((tree, tree));
+static tree build_over_call PROTO((struct z_candidate *, tree, int));
 static tree convert_like PROTO((tree, tree));
 static void op_error PROTO((enum tree_code, enum tree_code, tree, tree,
                            tree, char *));
@@ -64,7 +59,11 @@ static tree build_this PROTO((tree));
 static struct z_candidate * splice_viable PROTO((struct z_candidate *));
 static int any_viable PROTO((struct z_candidate *));
 static struct z_candidate * add_template_candidate
-       PROTO((struct z_candidate *, tree, tree, tree, tree, int));
+       PROTO((struct z_candidate *, tree, tree, tree, tree, int,
+              unification_kind_t));
+static struct z_candidate * add_template_candidate_real
+       PROTO((struct z_candidate *, tree, tree, tree, tree, int,
+              tree, unification_kind_t));
 static struct z_candidate * add_template_conv_candidate 
         PROTO((struct z_candidate *, tree, tree, tree, tree));
 static struct z_candidate * add_builtin_candidates
@@ -88,6 +87,9 @@ static tree strip_top_quals PROTO((tree));
 static tree non_reference PROTO((tree));
 static tree build_conv PROTO((enum tree_code, tree, tree));
 static int is_subseq PROTO((tree, tree));
+static int is_properly_derived_from PROTO((tree, tree));
+static int maybe_handle_ref_bind PROTO((tree*, tree*));
+static void maybe_handle_implicit_object PROTO((tree*));
 
 tree
 build_vfield_ref (datum, type)
@@ -169,7 +171,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
   if (field == error_mark_node)
     return error_mark_node;
 
-  if (field)
+  if (field && TREE_CODE (field) == FIELD_DECL)
     {
       tree basetype;
       tree ftype = TREE_TYPE (field);
@@ -338,6 +340,37 @@ resolve_scope_to_name (outer_type, inner_stuff)
   return tmp;
 }
 
+/* Returns nonzero iff the destructor name specified in NAME
+   (a BIT_NOT_EXPR) matches BASETYPE.  The operand of NAME can take many
+   forms...  */
+
+int
+check_dtor_name (basetype, name)
+     tree basetype, name;
+{
+  name = TREE_OPERAND (name, 0);
+
+  if (TREE_CODE (name) == TYPE_DECL)
+    name = TREE_TYPE (name);
+  else if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
+    /* OK */;
+  else if (TREE_CODE (name) == IDENTIFIER_NODE)
+    {
+      if ((IS_AGGR_TYPE (basetype) && name == constructor_name (basetype))
+         || (TREE_CODE (basetype) == ENUMERAL_TYPE
+             && name == TYPE_IDENTIFIER (basetype)))
+       name = basetype;
+      else
+       name = get_type_value (name);
+    }
+  else
+    my_friendly_abort (980605);
+
+  if (name && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (name))
+    return 1;
+  return 0;
+}
+
 /* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'.
    This is how virtual function calls are avoided.  */
 
@@ -360,7 +393,8 @@ build_scoped_method_call (exp, basetype, name, parms)
 
   if (processing_template_decl)
     {
-      if (TREE_CODE (name) == BIT_NOT_EXPR)
+      if (TREE_CODE (name) == BIT_NOT_EXPR
+         && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
        {
          tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0);
          if (type)
@@ -381,19 +415,30 @@ build_scoped_method_call (exp, basetype, name, parms)
   else
     binfo = NULL_TREE;
 
-  /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note
-     that explicit ~int is caught in the parser; this deals with typedefs
-     and template parms.  */
-  if (TREE_CODE (name) == BIT_NOT_EXPR && ! IS_AGGR_TYPE (basetype))
+  /* Check the destructor call syntax.  */
+  if (TREE_CODE (name) == BIT_NOT_EXPR)
     {
-      if (type != basetype)
-       cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')",
-                 exp, basetype, type);
-      name = TREE_OPERAND (name, 0);
-      if (basetype != name && basetype != get_type_value (name))
+      /* We can get here if someone writes their destructor call like
+        `obj.NS::~T()'; this isn't really a scoped method call, so hand
+        it off.  */
+      if (TREE_CODE (basetype) == NAMESPACE_DECL)
+       return build_method_call (exp, name, parms, NULL_TREE, LOOKUP_NORMAL);
+
+      if (! check_dtor_name (basetype, name))
        cp_error ("qualified type `%T' does not match destructor name `~%T'",
-                 basetype, name);
-      return cp_convert (void_type_node, exp);
+                 basetype, TREE_OPERAND (name, 0));
+
+      /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note
+        that explicit ~int is caught in the parser; this deals with typedefs
+        and template parms.  */
+      if (! IS_AGGR_TYPE (basetype))
+       {
+         if (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (basetype))
+           cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')",
+                     exp, basetype, type);
+
+         return cp_convert (void_type_node, exp);
+       }
     }
 
   if (! is_aggr_type (basetype, 1))
@@ -427,17 +472,6 @@ build_scoped_method_call (exp, basetype, name, parms)
       /* Call to a destructor.  */
       if (TREE_CODE (name) == BIT_NOT_EXPR)
        {
-         /* Explicit call to destructor.  */
-         name = TREE_OPERAND (name, 0);
-         if (! (name == TYPE_MAIN_VARIANT (TREE_TYPE (decl))
-                || name == constructor_name (TREE_TYPE (decl))
-                || TREE_TYPE (decl) == get_type_value (name)))
-           {
-             cp_error
-               ("qualified type `%T' does not match destructor name `~%T'",
-                TREE_TYPE (decl), name);
-             return error_mark_node;
-           }
          if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl)))
            return cp_convert (void_type_node, exp);
          
@@ -497,6 +531,8 @@ build_call (function, result_type, parms)
      tree function, result_type, parms;
 {
   int is_constructor = 0;
+  tree tmp;
+  tree decl;
 
   function = build_addr_func (function);
 
@@ -507,10 +543,30 @@ build_call (function, result_type, parms)
     }
 
   if (TREE_CODE (function) == ADDR_EXPR
-      && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
-      && DECL_CONSTRUCTOR_P (TREE_OPERAND (function, 0)))
+      && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
+    decl = TREE_OPERAND (function, 0);
+  else
+    decl = NULL_TREE;
+
+  if (decl && DECL_CONSTRUCTOR_P (decl))
     is_constructor = 1;
 
+  /* Don't pass empty class objects by value.  This is useful
+     for tags in STL, which are used to control overload resolution.
+     We don't need to handle other cases of copying empty classes.  */
+  if (! decl || ! DECL_BUILT_IN (decl))
+    for (tmp = parms; tmp; tmp = TREE_CHAIN (tmp))
+      if (is_empty_class (TREE_TYPE (TREE_VALUE (tmp)))
+         && ! TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (tmp))))
+       {
+         tree t = make_node (RTL_EXPR);
+         TREE_TYPE (t) = TREE_TYPE (TREE_VALUE (tmp));
+         RTL_EXPR_RTL (t) = const0_rtx;
+         RTL_EXPR_SEQUENCE (t) = NULL_RTX;
+         TREE_VALUE (tmp) = build (COMPOUND_EXPR, TREE_TYPE (t),
+                                   TREE_VALUE (tmp), t);
+       }
+
   function = build_nt (CALL_EXPR, function, parms, NULL_TREE);
   TREE_HAS_CONSTRUCTOR (function) = is_constructor;
   TREE_TYPE (function) = result_type;
@@ -570,10 +626,14 @@ build_method_call (instance, name, parms, basetype_path, flags)
 
   if (processing_template_decl)
     {
-      if (TREE_CODE (name) == BIT_NOT_EXPR)
+      /* We need to process template parm names here so that tsubst catches
+        them properly.  Other type names can wait.  */
+      if (TREE_CODE (name) == BIT_NOT_EXPR
+         && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
        {
-         tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 1);
-         name = build_min_nt (BIT_NOT_EXPR, type);
+         tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0);
+         if (type && TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+           name = build_min_nt (BIT_NOT_EXPR, type);
        }
 
       return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
@@ -604,22 +664,16 @@ build_method_call (instance, name, parms, basetype_path, flags)
 
   if (TREE_CODE (name) == BIT_NOT_EXPR)
     {
-      flags |= LOOKUP_DESTRUCTOR;
-      name = TREE_OPERAND (name, 0);
       if (parms)
        error ("destructors take no parameters");
       basetype = TREE_TYPE (instance);
       if (TREE_CODE (basetype) == REFERENCE_TYPE)
        basetype = TREE_TYPE (basetype);
-      if (! (name == basetype
-            || (IS_AGGR_TYPE (basetype)
-                && name == constructor_name (basetype))
-            || basetype == get_type_value (name)))
-       {
-         cp_error ("destructor name `~%D' does not match type `%T' of expression",
-                   name, basetype);
-         return cp_convert (void_type_node, instance);
-       }
+
+      if (! check_dtor_name (basetype, name))
+       cp_error
+         ("destructor name `~%T' does not match type `%T' of expression",
+          TREE_OPERAND (name, 0), basetype);
 
       if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype)))
        return cp_convert (void_type_node, instance);
@@ -642,6 +696,7 @@ struct z_candidate {
   int viable;
   tree basetype_path;
   tree template;
+  tree warnings;
   struct z_candidate *next;
 };
 
@@ -667,7 +722,9 @@ struct z_candidate {
 #define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE)
 #define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE)
 
-#define USER_CONV_FN(NODE) TREE_OPERAND (NODE, 1)
+#define USER_CONV_CAND(NODE) \
+  ((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1)))
+#define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn)
 
 int
 null_ptr_cst_p (t)
@@ -782,8 +839,11 @@ standard_conversion (to, from, expr)
       enum tree_code ufcode = TREE_CODE (TREE_TYPE (from));
       enum tree_code utcode = TREE_CODE (TREE_TYPE (to));
 
-      if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE
-         && ufcode != FUNCTION_TYPE)
+      if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (from)),
+                    TYPE_MAIN_VARIANT (TREE_TYPE (to)), 1))
+       ;
+      else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE
+              && ufcode != FUNCTION_TYPE)
        {
          from = build_pointer_type
            (cp_build_type_variant (void_type_node,
@@ -823,6 +883,9 @@ standard_conversion (to, from, expr)
        /* OK */;
       else if (comp_ptr_ttypes (TREE_TYPE (to), TREE_TYPE (from)))
        conv = build_conv (QUAL_CONV, to, conv);
+      else if (expr && string_conv_p (to, expr, 0))
+       /* converting from string constant to char *.  */
+       conv = build_conv (QUAL_CONV, to, conv);
       else if (ptr_reasonably_similar (TREE_TYPE (to), TREE_TYPE (from)))
        {
          conv = build_conv (PTR_CONV, to, conv);
@@ -1024,6 +1087,30 @@ implicit_conversion (to, from, expr, flags)
   return conv;
 }
 
+/* Add a new entry to the list of candidates.  Used by the add_*_candidate
+   functions.  */
+
+static struct z_candidate *
+add_candidate (candidates, fn, convs, viable)
+     struct z_candidate *candidates;
+     tree fn, convs;
+     int viable;
+{
+  struct z_candidate *cand
+    = (struct z_candidate *) scratchalloc (sizeof (struct z_candidate));
+
+  cand->fn = fn;
+  cand->convs = convs;
+  cand->second_conv = NULL_TREE;
+  cand->viable = viable;
+  cand->basetype_path = NULL_TREE;
+  cand->template = NULL_TREE;
+  cand->warnings = NULL_TREE;
+  cand->next = candidates;
+
+  return cand;
+}
+
 /* Create an overload candidate for the function or method FN called with
    the argument list ARGLIST and add it to CANDIDATES.  FLAGS is passed on
    to implicit_conversion.  */
@@ -1040,7 +1127,6 @@ add_function_candidate (candidates, fn, arglist, flags)
   tree parmnode = parmlist;
   tree argnode = arglist;
   int viable = 1;
-  struct z_candidate *cand;
 
   /* The `this' and `in_chrg' arguments to constructors are not considered
      in overload resolution.  */
@@ -1061,12 +1147,9 @@ add_function_candidate (candidates, fn, arglist, flags)
   for (i = 0; i < len; ++i)
     {
       tree arg = TREE_VALUE (argnode);
-      tree argtype = TREE_TYPE (arg);
+      tree argtype = lvalue_type (arg);
       tree t;
 
-      argtype = cp_build_type_variant
-       (argtype, TREE_READONLY (arg), TREE_THIS_VOLATILE (arg));
-
       if (parmnode == void_list_node)
        break;
       else if (parmnode)
@@ -1105,17 +1188,7 @@ add_function_candidate (candidates, fn, arglist, flags)
        break;
       }
 
-  cand = (struct z_candidate *) scratchalloc (sizeof (struct z_candidate));
-
-  cand->fn = fn;
-  cand->convs = convs;
-  cand->second_conv = NULL_TREE;
-  cand->viable = viable;
-  cand->basetype_path = NULL_TREE;
-  cand->template = NULL_TREE;
-  cand->next = candidates;
-
-  return cand;
+  return add_candidate (candidates, fn, convs, viable);
 }
 
 /* Create an overload candidate for the conversion function FN which will
@@ -1135,7 +1208,6 @@ add_conv_candidate (candidates, fn, obj, arglist)
   tree parmnode = parmlist;
   tree argnode = arglist;
   int viable = 1;
-  struct z_candidate *cand;
   int flags = LOOKUP_NORMAL;
 
   for (i = 0; i < len; ++i)
@@ -1182,17 +1254,7 @@ add_conv_candidate (candidates, fn, obj, arglist)
        break;
       }
 
-  cand = (struct z_candidate *) scratchalloc (sizeof (struct z_candidate));
-
-  cand->fn = fn;
-  cand->convs = convs;
-  cand->second_conv = NULL_TREE;
-  cand->viable = viable;
-  cand->basetype_path = NULL_TREE;
-  cand->template = NULL_TREE;
-  cand->next = candidates;
-
-  return cand;
+  return add_candidate (candidates, fn, convs, viable);
 }
 
 static struct z_candidate *
@@ -1205,7 +1267,6 @@ build_builtin_candidate (candidates, fnname, type1, type2,
 {
   tree t, convs;
   int viable = 1, i;
-  struct z_candidate *cand;
   tree types[2];
 
   types[0] = type1;
@@ -1242,17 +1303,7 @@ build_builtin_candidate (candidates, fnname, type1, type2,
        viable = 0;
     }      
 
-  cand = (struct z_candidate *) scratchalloc (sizeof (struct z_candidate));
-
-  cand->fn = fnname;
-  cand->convs = convs;
-  cand->second_conv = NULL_TREE;
-  cand->viable = viable;
-  cand->basetype_path = NULL_TREE;
-  cand->template = NULL_TREE;
-  cand->next = candidates;
-
-  return cand;
+  return add_candidate (candidates, fnname, convs, viable);
 }
 
 static int
@@ -1751,6 +1802,11 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
        {
          tree convs = lookup_conversions (argtypes[i]);
 
+         if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR)
+           return candidates;
+
+         convs = lookup_conversions (argtypes[i]);
+
          if (code == COND_EXPR)
            {
              if (real_lvalue_p (args[i]))
@@ -1760,9 +1816,8 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
              types[i] = scratch_tree_cons
                (NULL_TREE, TYPE_MAIN_VARIANT (argtypes[i]), types[i]);
            }
-               
-         else if (! convs || (i == 0 && code == MODIFY_EXPR
-                              && code2 == NOP_EXPR))
+
+         else if (! convs)
            return candidates;
 
          for (; convs; convs = TREE_CHAIN (convs))
@@ -1839,11 +1894,12 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
 static struct z_candidate*
 add_template_candidate_real (candidates, tmpl, explicit_targs,
                             arglist, return_type, flags,
-                            obj)
+                            obj, strict)
      struct z_candidate *candidates;
      tree tmpl, explicit_targs, arglist, return_type;
      int flags;
      tree obj;
+     unification_kind_t strict;
 {
   int ntparms = DECL_NTPARMS (tmpl);
   tree targs = make_scratch_vec (ntparms);
@@ -1852,7 +1908,7 @@ add_template_candidate_real (candidates, tmpl, explicit_targs,
   tree fn;
 
   i = fn_type_unification (tmpl, explicit_targs, targs, arglist,
-                          return_type, 0, NULL_TREE); 
+                          return_type, strict, NULL_TREE);
 
   if (i != 0)
     return candidates;
@@ -1894,14 +1950,16 @@ add_template_candidate_real (candidates, tmpl, explicit_targs,
 
 static struct z_candidate *
 add_template_candidate (candidates, tmpl, explicit_targs, 
-                       arglist, return_type, flags)
+                       arglist, return_type, flags, strict)
      struct z_candidate *candidates;
      tree tmpl, explicit_targs, arglist, return_type;
      int flags;
+     unification_kind_t strict;
 {
   return 
     add_template_candidate_real (candidates, tmpl, explicit_targs,
-                                arglist, return_type, flags, NULL_TREE);
+                                arglist, return_type, flags,
+                                NULL_TREE, strict);
 }
 
 
@@ -1912,7 +1970,7 @@ add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
 {
   return 
     add_template_candidate_real (candidates, tmpl, NULL_TREE, arglist,
-                                return_type, 0, obj);
+                                return_type, 0, obj, DEDUCE_CONV);
 }
 
 
@@ -2021,20 +2079,22 @@ build_user_type_conversion_1 (totype, expr, flags)
 
       ctors = TREE_VALUE (ctors);
     }
-  for (; ctors; ctors = DECL_CHAIN (ctors))
+  for (; ctors; ctors = OVL_NEXT (ctors))
     {
-      if (DECL_NONCONVERTING_P (ctors))
+      tree ctor = OVL_CURRENT (ctors);
+      if (DECL_NONCONVERTING_P (ctor))
        continue;
 
-      if (TREE_CODE (ctors) == TEMPLATE_DECL) 
+      if (TREE_CODE (ctor) == TEMPLATE_DECL) 
        {
-         templates = scratch_tree_cons (NULL_TREE, ctors, templates);
+         templates = scratch_tree_cons (NULL_TREE, ctor, templates);
          candidates = 
-           add_template_candidate (candidates, ctors,
-                                   NULL_TREE, args, NULL_TREE, flags);
+           add_template_candidate (candidates, ctor,
+                                   NULL_TREE, args, NULL_TREE, flags,
+                                   DEDUCE_CALL);
        } 
       else 
-       candidates = add_function_candidate (candidates, ctors,
+       candidates = add_function_candidate (candidates, ctor,
                                             args, flags); 
 
       if (candidates) 
@@ -2049,7 +2109,7 @@ build_user_type_conversion_1 (totype, expr, flags)
 
   for (; convs; convs = TREE_CHAIN (convs))
     {
-      tree fn = TREE_VALUE (convs);
+      tree fns = TREE_VALUE (convs);
       int convflags = LOOKUP_NO_CONVERSION;
       tree ics;
 
@@ -2060,39 +2120,46 @@ build_user_type_conversion_1 (totype, expr, flags)
       if (TREE_CODE (totype) == REFERENCE_TYPE)
        convflags |= LOOKUP_NO_TEMP_BIND;
 
-      if (TREE_CODE (fn) != TEMPLATE_DECL)
+      if (TREE_CODE (fns) != TEMPLATE_DECL)
        ics = implicit_conversion
-         (totype, TREE_TYPE (TREE_TYPE (fn)), 0, convflags);
+         (totype, TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))), 0, convflags);
       else
-       /* Here, the template conversion operator result must
-          precisely match the TOTYPE.  (FIXME: Actually, we're
-          supposed to do some simple conversions here; see
-          [temp.deduct.conv].).  If the result of the conversion
-          operator is not actually TOTYPE, then
-          add_template_candidate will fail below.  */
-       ics = implicit_conversion (totype, totype, 0, convflags);
+       /* We can't compute this yet.  */
+       ics = error_mark_node;
 
       if (TREE_CODE (totype) == REFERENCE_TYPE && ics && ICS_BAD_FLAG (ics))
        /* ignore the near match.  */;
       else if (ics)
-       for (; fn; fn = DECL_CHAIN (fn))
+       for (; fns; fns = OVL_NEXT (fns))
          {
+           tree fn = OVL_CURRENT (fns);
+           struct z_candidate *old_candidates = candidates;
+
            if (TREE_CODE (fn) == TEMPLATE_DECL)
              {
                templates = scratch_tree_cons (NULL_TREE, fn, templates);
                candidates = 
                  add_template_candidate (candidates, fn, NULL_TREE,
-                                         args, totype, flags);
+                                         args, totype, flags,
+                                         DEDUCE_CONV);
              } 
            else 
              candidates = add_function_candidate (candidates, fn,
                                                   args, flags); 
 
-           if (candidates
+           if (candidates != old_candidates)
              {
+               if (TREE_CODE (fn) == TEMPLATE_DECL)
+                 ics = implicit_conversion
+                   (totype, TREE_TYPE (TREE_TYPE (candidates->fn)),
+                    0, convflags);
+
                candidates->second_conv = ics;
                candidates->basetype_path = TREE_PURPOSE (convs);
-               if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
+
+               if (ics == NULL_TREE)
+                 candidates->viable = 0;
+               else if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
                  candidates->viable = -1;
              }
          }
@@ -2148,7 +2215,7 @@ build_user_type_conversion_1 (totype, expr, flags)
     (USER_CONV,
      (DECL_CONSTRUCTOR_P (cand->fn)
       ? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))),
-     expr, cand->fn, cand->convs, cand->basetype_path);
+     expr, build_expr_ptr_wrapper (cand));
   ICS_USER_FLAG (cand->second_conv) = 1;
   if (cand->viable == -1)
     ICS_BAD_FLAG (cand->second_conv) = 1;
@@ -2212,7 +2279,7 @@ build_new_function_call (fn, args)
 
   if (really_overloaded_fn (fn))
     {
-      tree t;
+      tree t1;
       tree templates = NULL_TREE;
 
       args = resolve_args (args);
@@ -2220,14 +2287,15 @@ build_new_function_call (fn, args)
       if (args == error_mark_node)
        return error_mark_node;
 
-      for (t = TREE_VALUE (fn); t; t = DECL_CHAIN (t))
+      for (t1 = fn; t1; t1 = OVL_CHAIN (t1))
        {
+         tree t = OVL_FUNCTION (t1);
          if (TREE_CODE (t) == TEMPLATE_DECL)
            {
              templates = scratch_tree_cons (NULL_TREE, t, templates);
              candidates = add_template_candidate
                (candidates, t, explicit_targs, args, NULL_TREE,
-                LOOKUP_NORMAL);  
+                LOOKUP_NORMAL, DEDUCE_CALL);  
            }
          else if (! template_only)
            candidates = add_function_candidate
@@ -2239,7 +2307,7 @@ build_new_function_call (fn, args)
          if (candidates && ! candidates->next)
            return build_function_call (candidates->fn, args);
          cp_error ("no matching function for call to `%D (%A)'",
-                   TREE_PURPOSE (fn), args);
+                   DECL_NAME (OVL_FUNCTION (fn)), args);
          if (candidates)
            print_z_candidates (candidates);
          return error_mark_node;
@@ -2250,7 +2318,7 @@ build_new_function_call (fn, args)
       if (cand == 0)
        {
          cp_error ("call of overloaded `%D (%A)' is ambiguous",
-                   TREE_PURPOSE (fn), args);
+                   DECL_NAME (OVL_FUNCTION (fn)), args);
          print_z_candidates (candidates);
          return error_mark_node;
        }
@@ -2262,9 +2330,12 @@ build_new_function_call (fn, args)
          && ! DECL_INITIAL (cand->fn))
        add_maybe_template (cand->fn, templates);
 
-      return build_over_call (cand->fn, cand->convs, args, LOOKUP_NORMAL);
+      return build_over_call (cand, args, LOOKUP_NORMAL);
     }
 
+  /* This is not really overloaded. */
+  fn = OVL_CURRENT (fn);
+
   return build_function_call (fn, args);
 }
 
@@ -2277,7 +2348,18 @@ build_object_call (obj, args)
   tree type = TREE_TYPE (obj);
   tree templates = NULL_TREE;
 
-  fns = lookup_fnfields (TYPE_BINFO (type), ansi_opname [CALL_EXPR], 0);
+  if (TYPE_PTRMEMFUNC_P (type))
+    {
+      /* It's no good looking for an overloaded operator() on a
+        pointer-to-member-function.  */
+      cp_error ("pointer-to-member function %E cannot be called", obj);
+      cp_error ("without an object; consider using .* or ->*");
+      return error_mark_node;
+    }
+
+  fns = lookup_fnfields (TYPE_BINFO (type), ansi_opname [CALL_EXPR], 1);
+  if (fns == error_mark_node)
+    return error_mark_node;
 
   args = resolve_args (args);
 
@@ -2286,25 +2368,26 @@ build_object_call (obj, args)
 
   if (fns)
     {
-      tree fn = TREE_VALUE (fns);
+      tree base = TREE_PURPOSE (fns);
       mem_args = scratch_tree_cons (NULL_TREE, build_this (obj), args);
 
-      for (; fn; fn = DECL_CHAIN (fn))
+      for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
        {
+         tree fn = OVL_CURRENT (fns);
          if (TREE_CODE (fn) == TEMPLATE_DECL)
            {
              templates = scratch_tree_cons (NULL_TREE, fn, templates);
              candidates 
                = add_template_candidate (candidates, fn, NULL_TREE,
                                          mem_args, NULL_TREE, 
-                                         LOOKUP_NORMAL);
+                                         LOOKUP_NORMAL, DEDUCE_CALL);
            }
          else
            candidates = add_function_candidate
              (candidates, fn, mem_args, LOOKUP_NORMAL);
 
          if (candidates)
-           candidates->basetype_path = TREE_PURPOSE (fns);
+           candidates->basetype_path = base;
        }
     }
 
@@ -2312,13 +2395,15 @@ build_object_call (obj, args)
 
   for (; convs; convs = TREE_CHAIN (convs))
     {
-      tree fn = TREE_VALUE (convs);
-      tree totype = TREE_TYPE (TREE_TYPE (fn));
+      tree fns = TREE_VALUE (convs);
+      tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns)));
+      tree fn;
 
       if (TREE_CODE (totype) == POINTER_TYPE
          && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
-       for (; fn; fn = DECL_CHAIN (fn))
+       for (; fns; fns = OVL_NEXT (fn))
          {
+           fn = OVL_CURRENT (fn);
            if (TREE_CODE (fn) == TEMPLATE_DECL) 
              {
                templates = scratch_tree_cons (NULL_TREE, fn, templates);
@@ -2354,7 +2439,7 @@ build_object_call (obj, args)
     }
 
   if (DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR])
-    return build_over_call (cand->fn, cand->convs, mem_args, LOOKUP_NORMAL);
+    return build_over_call (cand, mem_args, LOOKUP_NORMAL);
 
   obj = convert_like (TREE_VEC_ELT (cand->convs, 0), obj);
 
@@ -2438,7 +2523,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
        arglist = scratch_tree_cons (NULL_TREE, arg2, arg3);
        if (flags & LOOKUP_GLOBAL)
          return build_new_function_call
-           (lookup_name_nonclass (fnname), arglist);
+           (lookup_function_nonclass (fnname, arglist), arglist);
 
        /* FIXME */
        rval = build_method_call
@@ -2460,9 +2545,11 @@ build_new_op (code, flags, arg1, arg2, arg3)
        tree rval;
 
        if (flags & LOOKUP_GLOBAL)
-         return build_new_function_call
-           (lookup_name_nonclass (fnname),
-            build_scratch_list (NULL_TREE, arg1));
+         {
+           arglist = build_scratch_list (NULL_TREE, arg1);
+           return build_new_function_call
+             (lookup_function_nonclass (fnname, arglist), arglist);
+         }    
 
        arglist = scratch_tree_cons (NULL_TREE, arg1, build_scratch_list (NULL_TREE, arg2));
 
@@ -2537,36 +2624,41 @@ build_new_op (code, flags, arg1, arg2, arg3)
   else
     arglist = build_scratch_list (NULL_TREE, arg1);
 
-  fns = lookup_name_nonclass (fnname);
-  /* + Koenig lookup */
+  fns = lookup_function_nonclass (fnname, arglist);
 
   if (fns && TREE_CODE (fns) == TREE_LIST)
     fns = TREE_VALUE (fns);
-  for (; fns; fns = DECL_CHAIN (fns))
+  for (; fns; fns = OVL_NEXT (fns))
     {
-      if (TREE_CODE (fns) == TEMPLATE_DECL)
+      tree fn = OVL_CURRENT (fns);
+      if (TREE_CODE (fn) == TEMPLATE_DECL)
        {
-         templates = scratch_tree_cons (NULL_TREE, fns, templates);
+         templates = scratch_tree_cons (NULL_TREE, fn, templates);
          candidates 
-           = add_template_candidate (candidates, fns, NULL_TREE,
+           = add_template_candidate (candidates, fn, NULL_TREE,
                                      arglist, TREE_TYPE (fnname),
-                                     flags); 
+                                     flags, DEDUCE_CALL); 
        }
       else
-       candidates = add_function_candidate (candidates, fns, arglist, flags);
+       candidates = add_function_candidate (candidates, fn, arglist, flags);
     }
 
   if (IS_AGGR_TYPE (TREE_TYPE (arg1)))
-    fns = lookup_fnfields (TYPE_BINFO (TREE_TYPE (arg1)), fnname, 0);
+    {
+      fns = lookup_fnfields (TYPE_BINFO (TREE_TYPE (arg1)), fnname, 1);
+      if (fns == error_mark_node)
+       return fns;
+    }
   else
     fns = NULL_TREE;
 
   if (fns)
     {
-      tree fn = TREE_VALUE (fns);
+      tree basetype = TREE_PURPOSE (fns);
       mem_arglist = scratch_tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
-      for (; fn; fn = DECL_CHAIN (fn))
+      for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
        {
+         tree fn = OVL_CURRENT (fns);
          tree this_arglist;
 
          if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
@@ -2581,14 +2673,14 @@ build_new_op (code, flags, arg1, arg2, arg3)
              candidates 
                = add_template_candidate (candidates, fn, NULL_TREE,
                                          this_arglist,  TREE_TYPE (fnname),
-                                         flags); 
+                                         flags, DEDUCE_CALL); 
            }
          else
            candidates = add_function_candidate
              (candidates, fn, this_arglist, flags);
 
          if (candidates) 
-           candidates->basetype_path = TREE_PURPOSE (fns);
+           candidates->basetype_path = basetype;
        }
     }
 
@@ -2679,9 +2771,6 @@ build_new_op (code, flags, arg1, arg2, arg3)
                         : candidates->fn);
        }
 
-      if (DECL_FUNCTION_MEMBER_P (cand->fn))
-       enforce_access (cand->basetype_path, cand->fn);
-
       /* Pedantically, normal function declarations are never considered
         to refer to template instantiations, so we only do this with
         -fguiding-decls.  */ 
@@ -2691,7 +2780,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
        add_maybe_template (cand->fn, templates);
 
       return build_over_call
-       (cand->fn, cand->convs,
+       (cand,
         TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
         ? mem_arglist : arglist,
         LOOKUP_NORMAL);
@@ -2820,7 +2909,8 @@ build_op_new_call (code, type, args, flags)
       return build_method_call (dummy, fnname, args, NULL_TREE, flags);
     }
   else
-    return build_new_function_call (lookup_name_nonclass (fnname), args);
+    return build_new_function_call 
+      (lookup_function_nonclass (fnname, args), args);
 }
 
 /* Build a call to operator delete.  This has to be handled very specially,
@@ -2833,16 +2923,16 @@ build_op_new_call (code, type, args, flags)
    ADDR is the pointer to be deleted.  For placement delete, it is also
      used to determine what the corresponding new looked like.
    SIZE is the size of the memory block to be deleted.
-   FLAGS are the usual overloading flags.  */
+   FLAGS are the usual overloading flags.
+   PLACEMENT is the corresponding placement new call, or 0.  */
 
 tree
-build_op_delete_call (code, addr, size, flags)
+build_op_delete_call (code, addr, size, flags, placement)
      enum tree_code code;
-     tree addr, size;
+     tree addr, size, placement;
      int flags;
 {
   tree fn, fns, fnname, fntype, argtypes, args, type;
-  int placement;
 
   if (addr == error_mark_node)
     return error_mark_node;
@@ -2851,43 +2941,35 @@ build_op_delete_call (code, addr, size, flags)
   fnname = ansi_opname[code];
 
   if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL))
-    fns = lookup_fnfields (TYPE_BINFO (type), fnname, 0);
-  else
-    fns = NULL_TREE;
+    /* In [class.free]
 
-  if (fns)
+       If the result of the lookup is ambiguous or inaccessible, or if
+       the lookup selects a placement deallocation function, the
+       program is ill-formed.
+  
+       Therefore, we ask lookup_fnfields to complain ambout ambiguity.  */
     {
-      /* Build this up like build_offset_ref does.  */
-      fns = build_tree_list (error_mark_node, fns);
-      TREE_TYPE (fns) = build_offset_type (type, unknown_type_node);
+      fns = lookup_fnfields (TYPE_BINFO (type), fnname, 1);
+      if (fns == error_mark_node)
+       return error_mark_node;
     }
   else
+    fns = NULL_TREE;
+
+  if (fns == NULL_TREE)
     fns = lookup_name_nonclass (fnname);
 
-  /* We can recognize a placement delete because of LOOKUP_SPECULATIVELY;
-     if we are doing placement delete we do nothing if we don't find a
-     matching op delete.  */
-  placement = !!(flags & LOOKUP_SPECULATIVELY);
   if (placement)
     {
-      /* If placement, we are coming from build_new, and we know that addr
-        is the allocation expression, so extract the info we need from it.
-        Obviously, if the build_new process changes this may have to
-        change as well.  */
-
-      /* The NOP_EXPR.  */
-      tree t = TREE_OPERAND (addr, 1);
-      /* The CALL_EXPR.  */
-      t = TREE_OPERAND (t, 0);
-      /* The function.  */
-      argtypes = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
-      /* The second parm type.  */
+      /* placement is a CALL_EXPR around an ADDR_EXPR around a function.  */
+
+      /* Extract the function.  */
+      argtypes = TREE_OPERAND (TREE_OPERAND (placement, 0), 0);
+      /* Then the second parm type.  */
       argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (argtypes)));
-      /* The second argument.  */
-      args = TREE_CHAIN (TREE_OPERAND (t, 1));
 
-      /* Pull the dummy var out of the TARGET_EXPR for use in our call.  */
-      addr = TREE_OPERAND (addr, 0);
+      /* Also the second argument.  */
+      args = TREE_CHAIN (TREE_OPERAND (placement, 1));
     }
   else
     {
@@ -2906,18 +2988,20 @@ build_op_delete_call (code, addr, size, flags)
   /* instantiate_type will always return a plain function; pretend it's
      overloaded.  */
   if (TREE_CODE (fns) == FUNCTION_DECL)
-    fns = scratch_tree_cons (NULL_TREE, fns, NULL_TREE);
+    fns = scratch_ovl_cons (fns, NULL_TREE);
 
   fn = instantiate_type (fntype, fns, 0);
 
   if (fn != error_mark_node)
     {
-      if (TREE_CODE (TREE_VALUE (fns)) == TREE_LIST)
+      if (TREE_CODE (fns) == TREE_LIST)
        /* Member functions.  */
-       enforce_access (TREE_PURPOSE (TREE_VALUE (fns)), fn);
+       enforce_access (TREE_PURPOSE (fns), fn);
       return build_function_call (fn, expr_tree_cons (NULL_TREE, addr, args));
     }
 
+  /* If we are doing placement delete we do nothing if we don't find a
+     matching op delete.  */
   if (placement)
     return NULL_TREE;
 
@@ -2929,34 +3013,45 @@ build_op_delete_call (code, addr, size, flags)
   fn = instantiate_type (fntype, fns, 0);
 
   if (fn != error_mark_node)
-    return build_function_call
-      (fn, expr_tree_cons (NULL_TREE, addr,
-                          build_expr_list (NULL_TREE, size)));
+    {
+      if (TREE_CODE (fns) == TREE_LIST)
+       /* Member functions.  */
+       enforce_access (TREE_PURPOSE (fns), fn);
+      return build_function_call
+       (fn, expr_tree_cons (NULL_TREE, addr,
+                            build_expr_list (NULL_TREE, size)));
+    }
+
+  /* finish_function passes LOOKUP_SPECULATIVELY if we're in a
+     destructor, in which case the error should be deferred
+     until someone actually tries to delete one of these.  */
+  if (flags & LOOKUP_SPECULATIVELY)
+    return NULL_TREE;
 
   cp_error ("no suitable operator delete for `%T'", type);
   return error_mark_node;
 }
 
-/* If the current scope isn't allowed to access FUNCTION along
+/* If the current scope isn't allowed to access DECL along
    BASETYPE_PATH, give an error.  */
 
-static void
-enforce_access (basetype_path, function)
-     tree basetype_path, function;
+void
+enforce_access (basetype_path, decl)
+     tree basetype_path, decl;
 {
-  tree access = compute_access (basetype_path, function);
+  tree access = compute_access (basetype_path, decl);
 
   if (access == access_private_node)
     {
-      cp_error_at ("`%+#D' is %s", function
-                  TREE_PRIVATE (function) ? "private"
+      cp_error_at ("`%+#D' is %s", decl
+                  TREE_PRIVATE (decl) ? "private"
                   : "from private base class");
       error ("within this context");
     }
   else if (access == access_protected_node)
     {
-      cp_error_at ("`%+#D' %s", function,
-                  TREE_PROTECTED (function) ? "is protected"
+      cp_error_at ("`%+#D' %s", decl,
+                  TREE_PROTECTED (decl) ? "is protected"
                   : "has protected accessibility");
       error ("within this context");
     }
@@ -2994,9 +3089,10 @@ convert_like (convs, expr)
     {
     case USER_CONV:
       {
-       tree fn = TREE_OPERAND (convs, 1);
+       struct z_candidate *cand
+         = WRAPPER_PTR (TREE_OPERAND (convs, 1));
+       tree fn = cand->fn;
        tree args;
-       enforce_access (TREE_OPERAND (convs, 3), fn);
 
        if (DECL_CONSTRUCTOR_P (fn))
          {
@@ -3010,9 +3106,7 @@ convert_like (convs, expr)
          }
        else
          args = build_this (expr);
-       expr = build_over_call
-         (TREE_OPERAND (convs, 1), TREE_OPERAND (convs, 2),
-          args, LOOKUP_NORMAL);
+       expr = build_over_call (cand, args, LOOKUP_NORMAL);
 
        /* If this is a constructor or a function returning an aggr type,
           we need to build up a TARGET_EXPR.  */
@@ -3047,8 +3141,32 @@ convert_like (convs, expr)
        return expr;
       /* else fall through */
     case BASE_CONV:
-      return build_user_type_conversion
-       (TREE_TYPE (convs), expr, LOOKUP_NORMAL);
+      {
+       tree cvt_expr = build_user_type_conversion
+         (TREE_TYPE (convs), expr, LOOKUP_NORMAL);
+       if (!cvt_expr) 
+         {
+           /* This can occur if, for example, the EXPR has incomplete
+              type.  We can't check for that before attempting the
+              conversion because the type might be an incomplete
+              array type, which is OK if some constructor for the
+              destination type takes a pointer argument.  */
+           if (TYPE_SIZE (TREE_TYPE (expr)) == 0)
+             {
+               if (comptypes (TREE_TYPE (expr), TREE_TYPE (convs), 1))
+                 incomplete_type_error (expr, TREE_TYPE (expr));
+               else
+                 cp_error ("could not convert `%E' (with incomplete type `%T') to `%T'",
+                           expr, TREE_TYPE (expr), TREE_TYPE (convs));
+             }
+           else
+             cp_error ("could not convert `%E' to `%T'",
+                       expr, TREE_TYPE (convs));
+           return error_mark_node;
+         }
+       return cvt_expr;
+      }
+
     case REF_BIND:
       return convert_to_reference
        (TREE_TYPE (convs), expr,
@@ -3057,6 +3175,11 @@ convert_like (convs, expr)
     case LVALUE_CONV:
       return decay_conversion (expr);
 
+    case QUAL_CONV:
+      /* Warn about deprecated conversion if appropriate.  */
+      string_conv_p (TREE_TYPE (convs), expr, 1);
+      break;
+      
     default:
       break;
     }
@@ -3064,7 +3187,34 @@ convert_like (convs, expr)
                      LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
 }
 
-static tree
+/* ARG is being passed to a varargs function.  Perform any conversions
+   required.  Return the converted value.  */
+
+tree
+convert_arg_to_ellipsis (arg)
+     tree arg;
+{
+  if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE
+      && (TYPE_PRECISION (TREE_TYPE (arg))
+         < TYPE_PRECISION (double_type_node)))
+    /* Convert `float' to `double'.  */
+    arg = cp_convert (double_type_node, arg);
+  else if (IS_AGGR_TYPE (TREE_TYPE (arg))
+          && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (arg)))
+    cp_warning ("cannot pass objects of type `%T' through `...'",
+               TREE_TYPE (arg));
+  else
+    /* Convert `short' and `char' to full-size `int'.  */
+    arg = default_conversion (arg);
+
+  return arg;
+}
+
+/* ARG is a default argument expression being passed to a parameter of
+   the indicated TYPE.  Do any required conversions.  Return the
+   converted value.  */
+
+tree
 convert_default_arg (type, arg)
      tree type, arg;
 {
@@ -3096,16 +3246,27 @@ convert_default_arg (type, arg)
 }
 
 static tree
-build_over_call (fn, convs, args, flags)
-     tree fn, convs, args;
+build_over_call (cand, args, flags)
+     struct z_candidate *cand;
+     tree args;
      int flags;
 {
+  tree fn = cand->fn;
+  tree convs = cand->convs;
   tree converted_args = NULL_TREE;
   tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
   tree conv, arg, val;
   int i = 0;
   int is_method = 0;
 
+  /* Give any warnings we noticed during overload resolution.  */
+  if (cand->warnings)
+    for (val = cand->warnings; val; val = TREE_CHAIN (val))
+      joust (cand, WRAPPER_PTR (TREE_VALUE (val)), 1);
+
+  if (DECL_FUNCTION_MEMBER_P (fn))
+    enforce_access (cand->basetype_path, fn);
+
   if (args && TREE_CODE (args) != TREE_LIST)
     args = build_scratch_list (NULL_TREE, args);
   arg = args;
@@ -3130,6 +3291,7 @@ build_over_call (fn, convs, args, flags)
     {
       tree parmtype = TREE_VALUE (parm);
       tree argtype = TREE_TYPE (TREE_VALUE (arg));
+      tree t;
       if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i)))
        {
          int dv = (TYPE_VOLATILE (TREE_TYPE (parmtype))
@@ -3142,9 +3304,18 @@ build_over_call (fn, convs, args, flags)
          cp_pedwarn ("passing `%T' as `this' argument of `%#D' discards %s",
                      TREE_TYPE (argtype), fn, p);
        }
-      converted_args = expr_tree_cons
-       (NULL_TREE, convert_force (TREE_VALUE (parm), TREE_VALUE (arg), CONV_C_CAST),
-        converted_args);
+      /* [class.mfct.nonstatic]: If a nonstatic member function of a class
+        X is called for an object that is not of type X, or of a type
+        derived from X, the behavior is undefined.
+
+         So we can assume that anything passed as 'this' is non-null, and
+        optimize accordingly.  */
+      if (TREE_CODE (parmtype) == POINTER_TYPE)
+       t = convert_pointer_to_real (TREE_TYPE (parmtype), TREE_VALUE (arg));
+      else
+       /* This happens with signatures.  */
+       t = convert_force (parmtype, TREE_VALUE (arg), CONV_C_CAST);
+      converted_args = expr_tree_cons (NULL_TREE, t, converted_args);
       parm = TREE_CHAIN (parm);
       arg = TREE_CHAIN (arg);
       ++i;
@@ -3178,7 +3349,14 @@ build_over_call (fn, convs, args, flags)
             "argument passing", fn, i - is_method);
        }
       else
-       val = convert_like (conv, TREE_VALUE (arg));
+       {
+         /* Issue warnings about peculiar, but legal, uses of NULL.  */
+         if (ARITHMETIC_TYPE_P (TREE_VALUE (parm))
+             && TREE_VALUE (arg) == null_node)
+           cp_warning ("converting NULL to non-pointer type");
+           
+         val = convert_like (conv, TREE_VALUE (arg));
+       }
 
 #ifdef PROMOTE_PROTOTYPES
       if ((TREE_CODE (type) == INTEGER_TYPE
@@ -3195,9 +3373,26 @@ build_over_call (fn, convs, args, flags)
       tree arg = TREE_PURPOSE (parm);
 
       if (DECL_TEMPLATE_INFO (fn))
-       /* This came from a template.  Instantiate the default arg here,
-          not in tsubst.  */
-       arg = tsubst_expr (arg, DECL_TI_ARGS (fn), NULL_TREE);
+       {
+         /* This came from a template.  Instantiate the default arg here,
+            not in tsubst.  In the case of something like:
+
+              template <class T>
+              struct S {
+                static T t();
+                void f(T = t());
+              };
+
+            we must be careful to do name lookup in the scope of
+            S<T>, rather than in the current class.  */
+         if (DECL_CLASS_SCOPE_P (fn))
+           pushclass (DECL_REAL_CONTEXT (fn), 2);
+
+         arg = tsubst_expr (arg, DECL_TI_ARGS (fn), NULL_TREE);
+
+         if (DECL_CLASS_SCOPE_P (fn))
+           popclass (1);
+       }
       converted_args = expr_tree_cons
        (NULL_TREE, convert_default_arg (TREE_VALUE (parm), arg),
         converted_args);
@@ -3205,31 +3400,20 @@ build_over_call (fn, convs, args, flags)
 
   /* Ellipsis */
   for (; arg; arg = TREE_CHAIN (arg))
-    {
-      val = TREE_VALUE (arg);
-
-      if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
-         && (TYPE_PRECISION (TREE_TYPE (val))
-             < TYPE_PRECISION (double_type_node)))
-       /* Convert `float' to `double'.  */
-       val = cp_convert (double_type_node, val);
-      else if (TYPE_LANG_SPECIFIC (TREE_TYPE (val))
-              && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val)))
-       cp_warning ("cannot pass objects of type `%T' through `...'",
-                   TREE_TYPE (val));
-      else
-       /* Convert `short' and `char' to full-size `int'.  */
-       val = default_conversion (val);
-
-      converted_args = expr_tree_cons (NULL_TREE, val, converted_args);
-    }
+    converted_args 
+      = expr_tree_cons (NULL_TREE,
+                       convert_arg_to_ellipsis (TREE_VALUE (arg)),
+                       converted_args);
 
   converted_args = nreverse (converted_args);
 
   /* Avoid actually calling copy constructors and copy assignment operators,
      if possible.  */
-  if (DECL_CONSTRUCTOR_P (fn)
-      && TREE_VEC_LENGTH (convs) == 1
+
+  if (! flag_elide_constructors)
+    /* Do things the hard way.  */;
+  else if (DECL_CONSTRUCTOR_P (fn)
+          && TREE_VEC_LENGTH (convs) == 1
       && copy_args_p (fn))
     {
       tree targ;
@@ -3287,6 +3471,15 @@ build_over_call (fn, convs, args, flags)
        {
          tree to = stabilize_reference
            (build_indirect_ref (TREE_VALUE (args), 0));
+
+         /* Don't copy the padding byte; it might not have been allocated
+            if to is a base subobject.  */
+         if (is_empty_class (DECL_CLASS_CONTEXT (fn)))
+           return build_unary_op
+             (ADDR_EXPR, build (COMPOUND_EXPR, TREE_TYPE (to),
+                                cp_convert (void_type_node, arg), to),
+              0);
+
          val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
          TREE_SIDE_EFFECTS (val) = 1;
          return build_unary_op (ADDR_EXPR, val, 0);
@@ -3294,11 +3487,19 @@ build_over_call (fn, convs, args, flags)
     }
   else if (DECL_NAME (fn) == ansi_opname[MODIFY_EXPR]
           && copy_args_p (fn)
-          && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn)))
+          && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CLASS_CONTEXT (fn)))
     {
       tree to = stabilize_reference
        (build_indirect_ref (TREE_VALUE (converted_args), 0));
+
       arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
+
+      /* Don't copy the padding byte; it might not have been allocated
+        if to is a base subobject.  */
+      if (is_empty_class (DECL_CLASS_CONTEXT (fn)))
+       return build (COMPOUND_EXPR, TREE_TYPE (to),
+                     cp_convert (void_type_node, arg), to);
+
       val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
       TREE_SIDE_EFFECTS (val) = 1;
       return val;
@@ -3306,7 +3507,7 @@ build_over_call (fn, convs, args, flags)
 
   mark_used (fn);
 
-  if (DECL_CONTEXT (fn) && IS_SIGNATURE (DECL_CONTEXT (fn)))
+  if (DECL_CLASS_SCOPE_P (fn) && IS_SIGNATURE (DECL_CONTEXT (fn)))
     return build_signature_method_call (fn, converted_args);
   else if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
     {
@@ -3447,7 +3648,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
     return error_mark_node;
   if (fns)
     {
-      tree t = TREE_VALUE (fns);
+      tree fn = TREE_VALUE (fns);
       if (name == ctor_identifier && TYPE_USES_VIRTUAL_BASECLASSES (basetype)
          && ! (flags & LOOKUP_HAS_IN_CHARGE))
        {
@@ -3455,8 +3656,9 @@ build_new_method_call (instance, name, args, basetype_path, flags)
          args = scratch_tree_cons (NULL_TREE, integer_one_node, args);
        }
       mem_args = scratch_tree_cons (NULL_TREE, instance_ptr, args);
-      for (; t; t = DECL_CHAIN (t))
+      for (; fn; fn = OVL_NEXT (fn))
        {
+         tree t = OVL_CURRENT (fn);
          tree this_arglist;
 
          /* We can end up here for copy-init of same or base class.  */
@@ -3476,7 +3678,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
              candidates = 
                add_template_candidate (candidates, t, explicit_targs,
                                        this_arglist,
-                                       TREE_TYPE (name), flags); 
+                                       TREE_TYPE (name), flags, DEDUCE_CALL); 
            }
          else if (! template_only)
            candidates = add_function_candidate (candidates, t,
@@ -3508,7 +3710,6 @@ build_new_method_call (instance, name, args, basetype_path, flags)
       return error_mark_node;
     }
 
-  enforce_access (cand->basetype_path, cand->fn);
   if (DECL_ABSTRACT_VIRTUAL_P (cand->fn)
       && instance == current_class_ref
       && DECL_CONSTRUCTOR_P (current_function_decl)
@@ -3533,124 +3734,205 @@ build_new_method_call (instance, name, args, basetype_path, flags)
     add_maybe_template (cand->fn, templates);
 
   return build_over_call
-    (cand->fn, cand->convs,
+    (cand,
      TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ? mem_args : args,
      flags);
 }
 
-/* Compare two implicit conversion sequences that differ only in their
-   qualification conversion.  Subroutine of compare_ics.  */
+/* Returns non-zero iff standard conversion sequence ICS1 is a proper
+   subsequence of ICS2.  */
 
 static int
-compare_qual (ics1, ics2)
+is_subseq (ics1, ics2)
      tree ics1, ics2;
 {
-  tree to1 = TREE_TYPE (ics1);
-  tree to2 = TREE_TYPE (ics2);
+  /* We can assume that a conversion of the same code
+     between the same types indicates a subsequence since we only get
+     here if the types we are converting from are the same.  */
 
-  if (TYPE_PTRMEMFUNC_P (to1))
-    to1 = TYPE_PTRMEMFUNC_FN_TYPE (to1);
-  if (TYPE_PTRMEMFUNC_P (to2))
-    to2 = TYPE_PTRMEMFUNC_FN_TYPE (to2);
+  while (TREE_CODE (ics1) == RVALUE_CONV
+        || TREE_CODE (ics1) == LVALUE_CONV)
+    ics1 = TREE_OPERAND (ics1, 0);
 
-  to1 = TREE_TYPE (to1);
-  to2 = TREE_TYPE (to2);
-
-  if (TREE_CODE (to1) == OFFSET_TYPE)
+  while (1)
     {
-      to1 = TREE_TYPE (to1);
-      to2 = TREE_TYPE (to2);
-    }
+      while (TREE_CODE (ics2) == RVALUE_CONV
+         || TREE_CODE (ics2) == LVALUE_CONV)
+       ics2 = TREE_OPERAND (ics2, 0);
 
-  if (TYPE_READONLY (to1) >= TYPE_READONLY (to2)
-      && TYPE_VOLATILE (to1) > TYPE_VOLATILE (to2))
-    return -1;
-  else if (TYPE_READONLY (to1) > TYPE_READONLY (to2)
-          && TYPE_VOLATILE (to1) == TYPE_VOLATILE (to2))
-    return -1;
-  else if (TYPE_READONLY (to1) <= TYPE_READONLY (to2)
-          && TYPE_VOLATILE (to1) < TYPE_VOLATILE (to2))
-    return 1;
-  else if (TYPE_READONLY (to1) < TYPE_READONLY (to2)
-          && TYPE_VOLATILE (to1) == TYPE_VOLATILE (to2))
-    return 1;
-  return 0;
-}
-
-/* Determine whether standard conversion sequence ICS1 is a proper
-   subsequence of ICS2.  We assume that a conversion of the same code
-   between the same types indicates a subsequence.  */
+      if (TREE_CODE (ics2) == USER_CONV
+         || TREE_CODE (ics2) == AMBIG_CONV
+         || TREE_CODE (ics2) == IDENTITY_CONV)
+       /* At this point, ICS1 cannot be a proper subsequence of
+          ICS2.  We can get a USER_CONV when we are comparing the
+          second standard conversion sequence of two user conversion
+          sequences.  */
+       return 0;
 
-static int
-is_subseq (ics1, ics2)
-     tree ics1, ics2;
-{
-  /* Do not consider lvalue transformations here.  */
-  if (TREE_CODE (ics2) == RVALUE_CONV
-      || TREE_CODE (ics2) == LVALUE_CONV)
-    return 0;
+      ics2 = TREE_OPERAND (ics2, 0);
 
-  for (;; ics2 = TREE_OPERAND (ics2, 0))
-    {
       if (TREE_CODE (ics2) == TREE_CODE (ics1)
          && comptypes (TREE_TYPE (ics2), TREE_TYPE (ics1), 1)
          && comptypes (TREE_TYPE (TREE_OPERAND (ics2, 0)),
                        TREE_TYPE (TREE_OPERAND (ics1, 0)), 1))
        return 1;
-
-      if (TREE_CODE (ics2) == USER_CONV
-         || TREE_CODE (ics2) == AMBIG_CONV
-         || TREE_CODE (ics2) == IDENTITY_CONV)
-       return 0;
     }
 }
 
-/* Compare two implicit conversion sequences according to the rules set out in
-   [over.ics.rank].  Return values:
-
-      1: ics1 is better than ics2
-     -1: ics2 is better than ics1
-      0: ics1 and ics2 are indistinguishable */
+/* Returns non-zero iff DERIVED is derived from BASE.  The inputs may
+   be any _TYPE nodes.  */
 
 static int
-compare_ics (ics1, ics2)
-     tree ics1, ics2;
+is_properly_derived_from (derived, base)
+     tree derived;
+     tree base;
 {
-  tree main1, main2;
+  if (!IS_AGGR_TYPE_CODE (TREE_CODE (derived))
+      || !IS_AGGR_TYPE_CODE (TREE_CODE (base)))
+    return 0;
 
-  if (TREE_CODE (ics1) == QUAL_CONV)
-    main1 = TREE_OPERAND (ics1, 0);
-  else
-    main1 = ics1;
+  /* We only allow proper derivation here.  The DERIVED_FROM_P macro
+     considers every class derived from itself.  */
+  return (!comptypes (TYPE_MAIN_VARIANT (derived),
+                     TYPE_MAIN_VARIANT (base), 1)
+         && DERIVED_FROM_P (base, derived));
+}
 
-  if (TREE_CODE (ics2) == QUAL_CONV)
-    main2 = TREE_OPERAND (ics2, 0);
-  else
-    main2 = ics2;
+/* We build the ICS for an implicit object parameter as a pointer
+   conversion sequence.  However, such a sequence should be compared
+   as if it were a reference conversion sequence.  If ICS is the
+   implicit conversion sequence for an implicit object parameter,
+   modify it accordingly.  */
 
-  /* Conversions for `this' are PTR_CONVs, but we compare them as though
-     they were REF_BINDs.  */
-  if (ICS_THIS_FLAG (ics1))
+static void
+maybe_handle_implicit_object (ics)
+     tree* ics;
+{
+  if (ICS_THIS_FLAG (*ics))
     {
-      tree t = main1;
+      /* [over.match.funcs]
+        
+        For non-static member functions, the type of the
+        implicit object parameter is "reference to cv X"
+        where X is the class of which the function is a
+        member and cv is the cv-qualification on the member
+        function declaration.  */
+      tree t = *ics;
+      if (TREE_CODE (t) == QUAL_CONV)
+       t = TREE_OPERAND (t, 0);
       if (TREE_CODE (t) == PTR_CONV)
        t = TREE_OPERAND (t, 0);
       t = build1 (IDENTITY_CONV, TREE_TYPE (TREE_TYPE (t)), NULL_TREE);
-      t = build_conv (REF_BIND, TREE_TYPE (ics1), t);
-      ICS_STD_RANK (t) = ICS_STD_RANK (main1);
-      main1 = ics1 = t;
+      t = build_conv (REF_BIND, 
+                     build_reference_type (TREE_TYPE (TREE_TYPE (*ics))), 
+                     t);
+      ICS_STD_RANK (t) = ICS_STD_RANK (*ics);
+      *ics = t;
     }
-  if (ICS_THIS_FLAG (ics2))
+}
+
+/* If ICS is a REF_BIND, modify it appropriately, set TARGET_TYPE
+   to the type the reference originally referred to, and return 1.
+   Otherwise, return 0.  */
+
+static int
+maybe_handle_ref_bind (ics, target_type)
+     tree* ics;
+     tree* target_type;
+{
+  if (TREE_CODE (*ics) == REF_BIND)
     {
-      tree t = main2;
-      if (TREE_CODE (t) == PTR_CONV)
-       t = TREE_OPERAND (t, 0);
-      t = build1 (IDENTITY_CONV, TREE_TYPE (TREE_TYPE (t)), NULL_TREE);
-      t = build_conv (REF_BIND, TREE_TYPE (ics2), t);
-      ICS_STD_RANK (t) = ICS_STD_RANK (main2);
-      main2 = ics2 = t;
+      /* [over.ics.rank] 
+        
+        When a parameter of reference type binds directly
+        (_dcl.init.ref_) to an argument expression, the implicit
+        conversion sequence is the identity conversion, unless the
+        argument expression has a type that is a derived class of the
+        parameter type, in which case the implicit conversion
+        sequence is a derived-to-base Conversion.
+        
+        If the parameter binds directly to the result of applying a
+        conversion function to the argument expression, the implicit
+        conversion sequence is a user-defined conversion sequence
+        (_over.ics.user_), with the second standard conversion
+        sequence either an identity conversion or, if the conversion
+        function returns an entity of a type that is a derived class
+        of the parameter type, a derived-to-base Conversion.
+        
+        When a parameter of reference type is not bound directly to
+        an argument expression, the conversion sequence is the one
+        required to convert the argument expression to the underlying
+        type of the reference according to _over.best.ics_.
+        Conceptually, this conversion sequence corresponds to
+        copy-initializing a temporary of the underlying type with the
+        argument expression.  Any difference in top-level
+        cv-qualification is subsumed by the initialization itself and
+        does not constitute a conversion.  */
+
+      tree old_ics = *ics;
+
+      *target_type = TREE_TYPE (TREE_TYPE (*ics));
+      *ics = TREE_OPERAND (*ics, 0);
+      if (TREE_CODE (*ics) == IDENTITY_CONV
+         && is_properly_derived_from (TREE_TYPE (*ics), *target_type))
+       *ics = build_conv (BASE_CONV, *target_type, *ics);
+      ICS_USER_FLAG (*ics) = ICS_USER_FLAG (old_ics);
+      ICS_BAD_FLAG (*ics) = ICS_BAD_FLAG (old_ics);
+      
+      return 1;
     }
+  
+  return 0;
+}
 
+/* Compare two implicit conversion sequences according to the rules set out in
+   [over.ics.rank].  Return values:
+
+      1: ics1 is better than ics2
+     -1: ics2 is better than ics1
+      0: ics1 and ics2 are indistinguishable */
+
+static int
+compare_ics (ics1, ics2)
+     tree ics1, ics2;
+{
+  tree from_type1;
+  tree from_type2;
+  tree to_type1;
+  tree to_type2;
+  tree deref_from_type1 = NULL_TREE;
+  tree deref_from_type2;
+  tree deref_to_type1;
+  tree deref_to_type2;
+
+  /* REF_BINDING is non-zero if the result of the conversion sequence
+     is a reference type.   In that case TARGET_TYPE is the
+     type referred to by the reference.  */
+  int ref_binding1;
+  int ref_binding2;
+  tree target_type1;
+  tree target_type2;
+
+  /* Handle implicit object parameters.  */
+  maybe_handle_implicit_object (&ics1);
+  maybe_handle_implicit_object (&ics2);
+
+  /* Handle reference parameters.  */
+  ref_binding1 = maybe_handle_ref_bind (&ics1, &target_type1);
+  ref_binding2 = maybe_handle_ref_bind (&ics2, &target_type2);
+
+  /* [over.ics.rank]
+
+     When  comparing  the  basic forms of implicit conversion sequences (as
+     defined in _over.best.ics_)
+
+     --a standard conversion sequence (_over.ics.scs_) is a better
+       conversion sequence than a user-defined conversion sequence
+       or an ellipsis conversion sequence, and
+     
+     --a user-defined conversion sequence (_over.ics.user_) is a
+       better conversion sequence than an ellipsis conversion sequence
+       (_over.ics.ellipsis_).  */
   if (ICS_RANK (ics1) > ICS_RANK (ics2))
     return -1;
   else if (ICS_RANK (ics1) < ICS_RANK (ics2))
@@ -3658,6 +3940,8 @@ compare_ics (ics1, ics2)
 
   if (ICS_RANK (ics1) == BAD_RANK)
     {
+      /* Both ICS are bad.  We try to make a decision based on what
+        would have happenned if they'd been good.  */
       if (ICS_USER_FLAG (ics1) > ICS_USER_FLAG (ics2)
          || ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2))
        return -1;
@@ -3665,9 +3949,13 @@ compare_ics (ics1, ics2)
               || ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
        return 1;
 
-      /* else fall through */
+      /* We couldn't make up our minds; try to figure it out below.  */
     }
 
+  if (ICS_ELLIPSIS_FLAG (ics1))
+    /* Both conversions are ellipsis conversions.  */
+    return 0;
+
   /* User-defined  conversion sequence U1 is a better conversion sequence
      than another user-defined conversion sequence U2 if they contain the
      same user-defined conversion operator or constructor and if the sec-
@@ -3687,175 +3975,249 @@ compare_ics (ics1, ics2)
 
       if (USER_CONV_FN (t1) != USER_CONV_FN (t2))
        return 0;
-      else if (ICS_STD_RANK (ics1) > ICS_STD_RANK (ics2))
-       return -1;
-      else if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
-       return 1;
 
-      /* else fall through */
+      /* We can just fall through here, after setting up
+        FROM_TYPE1 and FROM_TYPE2.  */
+      from_type1 = TREE_TYPE (t1);
+      from_type2 = TREE_TYPE (t2);
     }
+  else
+    {
+      /* We're dealing with two standard conversion sequences. 
 
-#if 0 /* Handled by ranking */
-  /* A conversion that is not a conversion of a pointer,  or  pointer  to
-     member,  to  bool  is  better than another conversion that is such a
-     conversion.  */
-#endif
+        [over.ics.rank]
+        
+        Standard conversion sequence S1 is a better conversion
+        sequence than standard conversion sequence S2 if
+     
+        --S1 is a proper subsequence of S2 (comparing the conversion
+          sequences in the canonical form defined by _over.ics.scs_,
+          excluding any Lvalue Transformation; the identity
+          conversion sequence is considered to be a subsequence of
+          any non-identity conversion sequence */
+      
+      from_type1 = ics1;
+      while (TREE_CODE (from_type1) != IDENTITY_CONV)
+       from_type1 = TREE_OPERAND (from_type1, 0);
+      from_type1 = TREE_TYPE (from_type1);
+      
+      from_type2 = ics2;
+      while (TREE_CODE (from_type2) != IDENTITY_CONV)
+       from_type2 = TREE_OPERAND (from_type2, 0);
+      from_type2 = TREE_TYPE (from_type2);
+    }
 
-  if (TREE_CODE (main1) != TREE_CODE (main2))
+  if (comptypes (from_type1, from_type2, 1))
     {
-      /* ...if S1  is  a  proper  subsequence  of  S2  */
-      if (is_subseq (main1, main2))
+      if (is_subseq (ics1, ics2))
        return 1;
-      if (is_subseq (main2, main1))
+      if (is_subseq (ics2, ics1))
        return -1;
-      return 0;
     }
+  /* Otherwise, one sequence cannot be a subsequence of the other; they
+     don't start with the same type.  This can happen when comparing the
+     second standard conversion sequence in two user-defined conversion
+     sequences.  */
 
-  if (TREE_CODE (main1) == PTR_CONV || TREE_CODE (main1) == PMEM_CONV
-      || TREE_CODE (main1) == REF_BIND || TREE_CODE (main1) == BASE_CONV)
-    {
-      tree to1 = TREE_TYPE (main1);
-      tree from1 = TREE_TYPE (TREE_OPERAND (main1, 0));
-      tree to2 = TREE_TYPE (main2);
-      tree from2 = TREE_TYPE (TREE_OPERAND (main2, 0));
-      int distf, distt;
-
-      /* Standard conversion sequence S1 is a better conversion sequence than
-        standard conversion sequence S2 if...
-
-        S1 and S2 differ only in their qualification conversion  and  they
-        yield types identical except for cv-qualifiers and S2 adds all the
-        qualifiers that S1 adds (and in the same places) and S2  adds  yet
-        more  cv-qualifiers  than  S1,  or the similar case with reference
-        binding15).  */
-      if (TREE_CODE (main1) == REF_BIND)
-       {
-         if (TYPE_MAIN_VARIANT (TREE_TYPE (to1))
-             == TYPE_MAIN_VARIANT (TREE_TYPE (to2)))
-           return compare_qual (ics1, ics2);
-       }
-      else if (TREE_CODE (main1) != BASE_CONV && from1 == from2 && to1 == to2)
-       return compare_qual (ics1, ics2);
-       
-      if (TYPE_PTRMEMFUNC_P (to1))
-       {
-         to1 = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to1)));
-         from1 = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from1)));
-       }
-      else if (TREE_CODE (main1) != BASE_CONV)
-       {
-         to1 = TREE_TYPE (to1);
-         if (TREE_CODE (main1) != REF_BIND)
-           from1 = TREE_TYPE (from1);
+  /* [over.ics.rank]
 
-         if (TREE_CODE (to1) == OFFSET_TYPE)
-           {
-             to1 = TYPE_OFFSET_BASETYPE (to1);
-             from1 = TYPE_OFFSET_BASETYPE (from1);
-           }
-       }
+     Or, if not that,
 
-      if (TYPE_PTRMEMFUNC_P (to2))
-       {
-         to2 = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to2)));
-         from2 = TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from2)));
-       }
-      else if (TREE_CODE (main1) != BASE_CONV)
-       {
-         to2 = TREE_TYPE (to2);
-         if (TREE_CODE (main1) != REF_BIND)
-           from2 = TREE_TYPE (from2);
+     --the rank of S1 is better than the rank of S2 (by the rules
+       defined below):
 
-         if (TREE_CODE (to2) == OFFSET_TYPE)
-           {
-             to2 = TYPE_OFFSET_BASETYPE (to2);
-             from2 = TYPE_OFFSET_BASETYPE (from2);
-           }
-       }
+    Standard conversion sequences are ordered by their ranks: an Exact
+    Match is a better conversion than a Promotion, which is a better
+    conversion than a Conversion.
 
-      if (! (IS_AGGR_TYPE (from1) && IS_AGGR_TYPE (from2)))
-       return 0;
+    Two conversion sequences with the same rank are indistinguishable
+    unless one of the following rules applies:
 
-      /* The sense of pmem conversions is reversed from that of the other
-        conversions.  */
-      if (TREE_CODE (main1) == PMEM_CONV)
-       {
-         tree t = from1; from1 = from2; from2 = t;
-         t = to1; to1 = to2; to2 = t;
-       }
+    --A conversion that is not a conversion of a pointer, or pointer
+      to member, to bool is better than another conversion that is such
+      a conversion.  
 
-      distf = get_base_distance (from1, from2, 0, 0);
-      if (distf == -1)
-       {
-         distf = -get_base_distance (from2, from1, 0, 0);
-         if (distf == 1)
-           return 0;
-       }
+    The ICS_STD_RANK automatically handles the pointer-to-bool rule,
+    so that we do not have to check it explicitly.  */
+  if (ICS_STD_RANK (ics1) < ICS_STD_RANK (ics2))
+    return 1;
+  else if (ICS_STD_RANK (ics2) < ICS_STD_RANK (ics1))
+    return -1;
 
-      /* If class B is derived directly or indirectly from class A,
-        conver- sion of B* to A* is better than conversion of B* to
-        void*, and conversion of A* to void* is better than
-        conversion of B* to void*.  */
+  to_type1 = TREE_TYPE (ics1);
+  to_type2 = TREE_TYPE (ics2);
 
-      if (TREE_CODE (to1) == VOID_TYPE && TREE_CODE (to2) == VOID_TYPE)
+  if (TYPE_PTR_P (from_type1)
+      && TYPE_PTR_P (from_type2)
+      && TYPE_PTR_P (to_type1)
+      && TYPE_PTR_P (to_type2))
+    {
+      deref_from_type1 = TREE_TYPE (from_type1);
+      deref_from_type2 = TREE_TYPE (from_type2);
+      deref_to_type1 = TREE_TYPE (to_type1);
+      deref_to_type2 = TREE_TYPE (to_type2);
+    }
+  /* The rules for pointers to members A::* are just like the rules
+     for pointers A*, except opposite: if B is derived from A then
+     A::* converts to B::*, not vice versa.  For that reason, we
+     switch the from_ and to_ variables here.  */
+  else if (TYPE_PTRMEM_P (from_type1)
+          && TYPE_PTRMEM_P (from_type2)
+          && TYPE_PTRMEM_P (to_type1)
+          && TYPE_PTRMEM_P (to_type2))
+    {
+      deref_to_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type1));
+      deref_to_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (from_type2));
+      deref_from_type1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type1));
+      deref_from_type2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (to_type2));
+    }
+  else if (TYPE_PTRMEMFUNC_P (from_type1)
+          && TYPE_PTRMEMFUNC_P (from_type2)
+          && TYPE_PTRMEMFUNC_P (to_type1)
+          && TYPE_PTRMEMFUNC_P (to_type2))
+    {
+      deref_to_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type1);
+      deref_to_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (from_type2);
+      deref_from_type1 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type1);
+      deref_from_type2 = TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type2);
+    }
+
+  if (deref_from_type1 != NULL_TREE
+      && IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type1))
+      && IS_AGGR_TYPE_CODE (TREE_CODE (deref_from_type2)))
+    {
+      /* This was one of the pointer or pointer-like conversions.  
+
+        [over.ics.rank]
+        
+        --If class B is derived directly or indirectly from class A,
+          conversion of B* to A* is better than conversion of B* to
+          void*, and conversion of A* to void* is better than
+          conversion of B* to void*.  */
+      if (TREE_CODE (deref_to_type1) == VOID_TYPE
+         && TREE_CODE (deref_to_type2) == VOID_TYPE)
        {
-         if (distf > 0)
-           return 1;
-         else if (distf < 0)
+         if (is_properly_derived_from (deref_from_type1,
+                                       deref_from_type2))
            return -1;
+         else if (is_properly_derived_from (deref_from_type2,
+                                            deref_from_type1))
+           return 1;
        }
-      else if (TREE_CODE (to2) == VOID_TYPE && IS_AGGR_TYPE (to1)
-              && get_base_distance (to1, from1, 0, 0) != -1)
-       return 1;
-      else if (TREE_CODE (to1) == VOID_TYPE && IS_AGGR_TYPE (to2)
-              && get_base_distance (to2, from2, 0, 0) != -1)
-       return -1;
-
-      if (! (IS_AGGR_TYPE (to1) && IS_AGGR_TYPE (to2)))
-       return 0;
-
-      /* If  class B is derived directly or indirectly from class A and class
-        C is derived directly or indirectly from B */
-
-      distt = get_base_distance (to1, to2, 0, 0);
-      if (distt == -1)
+      else if (TREE_CODE (deref_to_type1) == VOID_TYPE
+              || TREE_CODE (deref_to_type2) == VOID_TYPE)
        {
-         distt = -get_base_distance (to2, to1, 0, 0);
-         if (distt == 1)
-           return 0;
+         if (comptypes (deref_from_type1, deref_from_type2, 1))
+           {
+             if (TREE_CODE (deref_to_type2) == VOID_TYPE)
+               {
+                 if (is_properly_derived_from (deref_from_type1,
+                                               deref_to_type1))
+                   return 1;
+               }
+             /* We know that DEREF_TO_TYPE1 is `void' here.  */
+             else if (is_properly_derived_from (deref_from_type1,
+                                                deref_to_type2))
+               return -1;
+           }
        }
-
-      /* --conversion of C* to B* is better than conversion of C* to A*, */
-      if (distf == 0)
+      else if (IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type1))
+              && IS_AGGR_TYPE_CODE (TREE_CODE (deref_to_type2)))
        {
-         if (distt > 0)
-           return -1;
-         else if (distt < 0)
-           return 1;
+         /* [over.ics.rank]
+
+            --If class B is derived directly or indirectly from class A
+              and class C is derived directly or indirectly from B,
+            
+            --conversion of C* to B* is better than conversion of C* to
+              A*, 
+            
+            --conversion of B* to A* is better than conversion of C* to
+              A*  */
+         if (comptypes (deref_from_type1, deref_from_type2, 1))
+           {
+             if (is_properly_derived_from (deref_to_type1,
+                                           deref_to_type2))
+               return 1;
+             else if (is_properly_derived_from (deref_to_type2,
+                                                deref_to_type1))
+               return -1;
+           }
+         else if (comptypes (deref_to_type1, deref_to_type2, 1))
+           {
+             if (is_properly_derived_from (deref_from_type2,
+                                           deref_from_type1))
+               return 1;
+             else if (is_properly_derived_from (deref_from_type1,
+                                                deref_from_type2))
+               return -1;
+           }
        }
-      /* --conversion of B* to A* is better than conversion of C* to A*, */
-      else if (distt == 0)
+    }
+  else if (IS_AGGR_TYPE_CODE (TREE_CODE (from_type1))
+          && comptypes (from_type1, from_type2, 1))
+    {
+      /* [over.ics.rank]
+        
+        --binding of an expression of type C to a reference of type
+          B& is better than binding an expression of type C to a
+          reference of type A&
+
+        --conversion of C to B is better than conversion of C to A,  */
+      if (is_properly_derived_from (from_type1, to_type1)
+         && is_properly_derived_from (from_type1, to_type2))
        {
-         if (distf > 0)
+         if (is_properly_derived_from (to_type1, to_type2))
            return 1;
-         else if (distf < 0)
+         else if (is_properly_derived_from (to_type2, to_type1))
            return -1;
        }
     }
-  else if (TREE_CODE (TREE_TYPE (main1)) == POINTER_TYPE
-          || TYPE_PTRMEMFUNC_P (TREE_TYPE (main1)))
+  else if (IS_AGGR_TYPE_CODE (TREE_CODE (to_type1))
+          && comptypes (to_type1, to_type2, 1))
     {
-      if (TREE_TYPE (main1) == TREE_TYPE (main2))
-       return compare_qual (ics1, ics2);
-
-#if 0 /* This is now handled by making identity better than anything else.  */
-      /* existing practice, not WP-endorsed: const char * -> const char *
-        is better than char * -> const char *.  (jason 6/29/96) */
-      if (TREE_TYPE (ics1) == TREE_TYPE (ics2))
-       return -compare_qual (main1, main2);
-#endif
+      /* [over.ics.rank]
+
+        --binding of an expression of type B to a reference of type
+          A& is better than binding an expression of type C to a
+          reference of type A&, 
+
+        --onversion of B to A is better than conversion of C to A  */
+      if (is_properly_derived_from (from_type1, to_type1)
+         && is_properly_derived_from (from_type2, to_type1))
+       {
+         if (is_properly_derived_from (from_type2, from_type1))
+           return 1;
+         else if (is_properly_derived_from (from_type1, from_type2))
+           return -1;
+       }
     }
 
+  /* [over.ics.rank]
+
+     --S1 and S2 differ only in their qualification conversion and  yield
+       similar  types  T1 and T2 (_conv.qual_), respectively, and the cv-
+       qualification signature of type T1 is a proper subset of  the  cv-
+       qualification signature of type T2  */
+  if (TREE_CODE (ics1) == QUAL_CONV 
+      && TREE_CODE (ics2) == QUAL_CONV
+      && comptypes (from_type1, from_type2, 1))
+    return comp_cv_qual_signature (to_type1, to_type2);
+
+  /* [over.ics.rank]
+     
+     --S1 and S2 are reference bindings (_dcl.init.ref_), and the
+     types to which the references refer are the same type except for
+     top-level cv-qualifiers, and the type to which the reference
+     initialized by S2 refers is more cv-qualified than the type to
+     which the reference initialized by S1 refers */
+      
+  if (ref_binding1 && ref_binding2
+      && comptypes (TYPE_MAIN_VARIANT (to_type1),
+                   TYPE_MAIN_VARIANT (to_type2), 1))
+    return comp_cv_qualification (target_type2, target_type1);
+
+  /* Neither conversion sequence is better than the other.  */
   return 0;
 }
 
@@ -3875,6 +4237,19 @@ source_type (t)
   my_friendly_abort (1823);
 }
 
+/* Note a warning about preferring WINNER to LOSER.  We do this by storing
+   a pointer to LOSER and re-running joust to produce the warning if WINNER
+   is actually used.  */
+
+static void
+add_warning (winner, loser)
+     struct z_candidate *winner, *loser;
+{
+  winner->warnings = expr_tree_cons (NULL_PTR,
+                                    build_expr_ptr_wrapper (loser),
+                                    winner->warnings);
+}
+
 /* Compare two candidates for overloading as described in
    [over.match.best].  Return values:
 
@@ -3883,8 +4258,9 @@ source_type (t)
       0: cand1 and cand2 are indistinguishable */
 
 static int
-joust (cand1, cand2)
+joust (cand1, cand2, warn)
      struct z_candidate *cand1, *cand2;
+     int warn;
 {
   int winner = 0;
   int i, off1 = 0, off2 = 0, len;
@@ -3932,7 +4308,6 @@ joust (cand1, cand2)
 
       if (comp != 0)
        {
-#if 0 /* move this warning to tourney.  */
          if (warn_sign_promo
              && ICS_RANK (t1) + ICS_RANK (t2) == STD_RANK + PROMO_RANK
              && TREE_CODE (t1) == STD_CONV
@@ -3947,16 +4322,23 @@ joust (cand1, cand2)
            {
              tree type = TREE_TYPE (TREE_OPERAND (t1, 0));
              tree type1, type2;
+             struct z_candidate *w, *l;
              if (comp > 0)
-               type1 = TREE_TYPE (t1), type2 = TREE_TYPE (t2);
+               type1 = TREE_TYPE (t1), type2 = TREE_TYPE (t2),
+                 w = cand1, l = cand2;
              else
-               type1 = TREE_TYPE (t2), type2 = TREE_TYPE (t1);
+               type1 = TREE_TYPE (t2), type2 = TREE_TYPE (t1),
+                 w = cand2, l = cand1;
 
-             cp_warning ("passing `%T' chooses `%T' over `%T'",
-                         type, type1, type2);
-             cp_warning ("  in call to `%D'", DECL_NAME (cand1->fn));
+             if (warn)
+               {
+                 cp_warning ("passing `%T' chooses `%T' over `%T'",
+                             type, type1, type2);
+                 cp_warning ("  in call to `%D'", w->fn);
+               }
+             else
+               add_warning (w, l);
            }
-#endif
 
          if (winner && comp != winner)
            {
@@ -3967,28 +4349,39 @@ joust (cand1, cand2)
        }
     }
 
-#if 0 /* move this warning to tourney.  */
-  /* warn about confusing overload resolution */
+  /* warn about confusing overload resolution for user-defined conversions,
+     either between a constructor and a conversion op, or between two
+     conversion ops.  */
   if (winner && cand1->second_conv
-      && ! DECL_CONSTRUCTOR_P (cand1->fn)
-      && ! DECL_CONSTRUCTOR_P (cand2->fn))
+      && ((DECL_CONSTRUCTOR_P (cand1->fn)
+          != DECL_CONSTRUCTOR_P (cand2->fn))
+         /* Don't warn if the two conv ops convert to the same type...  */
+         || (! DECL_CONSTRUCTOR_P (cand1->fn)
+             && ! comptypes (TREE_TYPE (cand1->second_conv),
+                             TREE_TYPE (cand2->second_conv), 1))))
     {
       int comp = compare_ics (cand1->second_conv, cand2->second_conv);
-      if (comp && comp != winner)
+      if (comp != winner)
        {
          struct z_candidate *w, *l;
          if (winner == 1)
            w = cand1, l = cand2;
          else
            w = cand2, l = cand1;
-         cp_warning ("choosing `%D' over `%D'", w->fn, l->fn);
-         cp_warning ("  for conversion from `%T' to `%T'",
-                     TREE_TYPE (source_type (TREE_VEC_ELT (w->convs, 0))),
-                     TREE_TYPE (w->second_conv));
-         cp_warning ("  because conversion sequence for `this' argument is better");
+         if (warn)
+           {
+             tree source = source_type (TREE_VEC_ELT (w->convs, 0));
+             if (! DECL_CONSTRUCTOR_P (w->fn))
+               source = TREE_TYPE (source);
+             cp_warning ("choosing `%D' over `%D'", w->fn, l->fn);
+             cp_warning ("  for conversion from `%T' to `%T'",
+                         source, TREE_TYPE (w->second_conv));
+             cp_warning ("  because conversion sequence for the argument is better");
+           }
+         else
+           add_warning (w, l);
        }
     }
-#endif
 
   if (winner)
     return winner;
@@ -4083,13 +4476,14 @@ tourney (candidates)
 {
   struct z_candidate *champ = candidates, *challenger;
   int fate;
+  int champ_compared_to_predecessor = 0;
 
   /* Walk through the list once, comparing each current champ to the next
      candidate, knocking out a candidate or two with each comparison.  */
 
   for (challenger = champ->next; challenger; )
     {
-      fate = joust (champ, challenger);
+      fate = joust (champ, challenger, 0);
       if (fate == 1)
        challenger = challenger->next;
       else
@@ -4099,22 +4493,27 @@ tourney (candidates)
              champ = challenger->next;
              if (champ == 0)
                return 0;
+             champ_compared_to_predecessor = 0;
            }
          else
-           champ = challenger;
+           {
+             champ = challenger;
+             champ_compared_to_predecessor = 1;
+           }
 
          challenger = champ->next;
        }
     }
 
   /* Make sure the champ is better than all the candidates it hasn't yet
-     been compared to.  This may do one more comparison than necessary.  Oh
-     well.  */
+     been compared to.  */
 
-  for (challenger = candidates; challenger != champ;
+  for (challenger = candidates; 
+       challenger != champ 
+        && !(champ_compared_to_predecessor && challenger->next == champ);
        challenger = challenger->next)
     {
-      fate = joust (champ, challenger);
+      fate = joust (champ, challenger, 0);
       if (fate != 1)
        return 0;
     }