OSDN Git Service

* cp/decl2.c (cxx_decode_option): Support -fno-builtin-foo.
[pf3gnuchains/gcc-fork.git] / gcc / cp / call.c
index 4d2e7a1..1599d0b 100644 (file)
@@ -1,6 +1,6 @@
 /* Functions related to invoking methods and overloaded functions.
    Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com) and
    modified by Brendan Kehoe (brendan@cygnus.com).
 
@@ -32,9 +32,9 @@ Boston, MA 02111-1307, USA.  */
 #include "flags.h"
 #include "rtl.h"
 #include "toplev.h"
-#include "defaults.h"
 #include "expr.h"
 #include "ggc.h"
+#include "diagnostic.h"
 
 extern int inhibit_warnings;
 
@@ -46,8 +46,11 @@ static int equal_functions PARAMS ((tree, tree));
 static int joust PARAMS ((struct z_candidate *, struct z_candidate *, int));
 static int compare_ics PARAMS ((tree, tree));
 static tree build_over_call PARAMS ((struct z_candidate *, tree, int));
-#define convert_like(CONV, EXPR) convert_like_real (CONV, EXPR, NULL_TREE, 0, 0)
-#define convert_like_with_context(CONV, EXPR, FN, ARGNO) convert_like_real (CONV, EXPR, FN, ARGNO, 0)
+static tree build_java_interface_fn_ref PARAMS ((tree, tree));
+#define convert_like(CONV, EXPR) \
+  convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0)
+#define convert_like_with_context(CONV, EXPR, FN, ARGNO) \
+  convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0)
 static tree convert_like_real PARAMS ((tree, tree, tree, int, int));
 static void op_error PARAMS ((enum tree_code, enum tree_code, tree, tree,
                            tree, const char *));
@@ -59,6 +62,7 @@ static void print_z_candidates PARAMS ((struct z_candidate *));
 static tree build_this PARAMS ((tree));
 static struct z_candidate * splice_viable PARAMS ((struct z_candidate *));
 static int any_viable PARAMS ((struct z_candidate *));
+static int any_strictly_viable PARAMS ((struct z_candidate *));
 static struct z_candidate * add_template_candidate
        PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, int,
               unification_kind_t));
@@ -87,7 +91,7 @@ static tree reference_binding PARAMS ((tree, tree, tree, int));
 static tree non_reference PARAMS ((tree));
 static tree build_conv PARAMS ((enum tree_code, tree, tree));
 static int is_subseq PARAMS ((tree, tree));
-static int maybe_handle_ref_bind PARAMS ((tree*, tree*));
+static tree maybe_handle_ref_bind PARAMS ((tree*));
 static void maybe_handle_implicit_object PARAMS ((tree*));
 static struct z_candidate * add_candidate PARAMS ((struct z_candidate *,
                                                   tree, tree, int));
@@ -147,7 +151,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
     {
       /* If it's a field, try overloading operator (),
         or calling if the field is a pointer-to-function.  */
-      instance = build_indirect_ref (instance_ptr, NULL_PTR);
+      instance = build_indirect_ref (instance_ptr, NULL);
       instance = build_component_ref_1 (instance, field, 0);
 
       if (instance == error_mark_node)
@@ -156,15 +160,11 @@ build_field_call (basetype_path, instance_ptr, name, parms)
       if (IS_AGGR_TYPE (TREE_TYPE (instance)))
        return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
                               instance, parms, NULL_TREE);
-      else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
-       {
-         if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE)
-           return build_function_call (instance, parms);
-         else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance)))
-                  == METHOD_TYPE)
-           return build_function_call
-             (instance, tree_cons (NULL_TREE, instance_ptr, parms));
-       }
+      else if (TREE_CODE (TREE_TYPE (instance)) == FUNCTION_TYPE
+              || (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE
+                  && (TREE_CODE (TREE_TYPE (TREE_TYPE (instance)))
+                      == FUNCTION_TYPE)))
+       return build_function_call (instance, parms);
     }
 
   return NULL_TREE;
@@ -197,8 +197,17 @@ check_dtor_name (basetype, name)
       else
        name = get_type_value (name);
     }
+  /* In the case of:
+      
+       template <class T> struct S { ~S(); };
+       int i;
+       i.~S();
+
+     NAME will be a class template.  */
+  else if (DECL_CLASS_TEMPLATE_P (name))
+    return 0;
   else
-    my_friendly_abort (980605);
+    abort ();
 
   if (name && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (name))
     return 1;
@@ -259,7 +268,7 @@ build_scoped_method_call (exp, basetype, name, parms)
        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'",
+       error ("qualified type `%T' does not match destructor name `~%T'",
                  basetype, TREE_OPERAND (name, 0));
 
       /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note
@@ -268,7 +277,7 @@ build_scoped_method_call (exp, basetype, name, 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')",
+           error ("type of `%E' does not match destructor type `%T' (type was `%T')",
                      exp, basetype, type);
 
          return cp_convert (void_type_node, exp);
@@ -277,7 +286,7 @@ build_scoped_method_call (exp, basetype, name, parms)
 
   if (TREE_CODE (basetype) == NAMESPACE_DECL)
     {
-      cp_error ("`%D' is a namespace", basetype);
+      error ("`%D' is a namespace", basetype);
       return error_mark_node;
     }
   if (! is_aggr_type (basetype, 1))
@@ -285,29 +294,15 @@ build_scoped_method_call (exp, basetype, name, parms)
 
   if (! IS_AGGR_TYPE (type))
     {
-      cp_error ("base object `%E' of scoped method call is of non-aggregate type `%T'",
+      error ("base object `%E' of scoped method call is of non-aggregate type `%T'",
                exp, type);
       return error_mark_node;
     }
 
-  if (! binfo)
-    {
-      binfo = get_binfo (basetype, type, 1);
-      if (binfo == error_mark_node)
-       return error_mark_node;
-      if (! binfo)
-       error_not_base_type (basetype, type);
-    }
+  decl = build_scoped_ref (exp, basetype, &binfo);
 
   if (binfo)
     {
-      if (TREE_CODE (exp) == INDIRECT_REF)
-       decl = build_indirect_ref
-         (convert_pointer_to_real
-          (binfo, build_unary_op (ADDR_EXPR, exp, 0)), NULL_PTR);
-      else
-       decl = build_scoped_ref (exp, basetype);
-
       /* Call to a destructor.  */
       if (TREE_CODE (name) == BIT_NOT_EXPR)
        {
@@ -344,7 +339,7 @@ build_addr_func (function)
 
       type = build_pointer_type (type);
 
-      if (mark_addressable (function) == 0)
+      if (!cxx_mark_addressable (function))
        return error_mark_node;
 
       addr = build1 (ADDR_EXPR, type, function);
@@ -396,7 +391,13 @@ build_call (function, parms)
      throw without being declared throw().  */
   nothrow = ((decl && TREE_NOTHROW (decl))
             || TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function))));
-  
+
+  if (decl && TREE_THIS_VOLATILE (decl))
+    current_function_returns_abnormally = 1;
+
+  if (decl && TREE_DEPRECATED (decl))
+    warn_deprecated_use (decl);
+
   if (decl && DECL_CONSTRUCTOR_P (decl))
     is_constructor = 1;
 
@@ -409,7 +410,7 @@ build_call (function, parms)
          || !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "__", 2))
        mark_used (decl);
       else
-       my_friendly_abort (990125);
+       abort ();
     }
 
   /* Don't pass empty class objects by value.  This is useful
@@ -516,7 +517,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
        basetype = TREE_TYPE (basetype);
 
       if (! check_dtor_name (basetype, name))
-       cp_error
+       error
          ("destructor name `~%T' does not match type `%T' of expression",
           TREE_OPERAND (name, 0), basetype);
 
@@ -534,7 +535,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
 
 /* New overloading code.  */
 
-struct z_candidate {
+struct z_candidate GTY(()) {
   tree fn;
   tree convs;
   tree second_conv;
@@ -555,7 +556,7 @@ struct z_candidate {
 #define BAD_RANK 7
 
 #define ICS_RANK(NODE)                         \
-  (ICS_BAD_FLAG (NODE) ? BAD_RANK   \
+  (ICS_BAD_FLAG (NODE) ? BAD_RANK              \
    : ICS_ELLIPSIS_FLAG (NODE) ? ELLIPSIS_RANK  \
    : ICS_USER_FLAG (NODE) ? USER_RANK          \
    : ICS_STD_RANK (NODE))
@@ -569,10 +570,9 @@ struct z_candidate {
 
 /* In a REF_BIND or a BASE_CONV, this indicates that a temporary
    should be created to hold the result of the conversion.  */
-#define NEED_TEMPORARY_P(NODE) (TREE_LANG_FLAG_4 ((NODE)))
+#define NEED_TEMPORARY_P(NODE) TREE_LANG_FLAG_4 (NODE)
 
-#define USER_CONV_CAND(NODE) \
-  ((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1)))
+#define USER_CONV_CAND(NODE) WRAPPER_ZC (TREE_OPERAND (NODE, 1))
 #define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn)
 
 int
@@ -589,13 +589,36 @@ null_ptr_cst_p (t)
   return 0;
 }
 
+
+/* Returns non-zero if PARMLIST consists of only default parms and/or
+   ellipsis. */
+
+int
+sufficient_parms_p (parmlist)
+     tree parmlist;
+{
+  for (; parmlist && parmlist != void_list_node;
+       parmlist = TREE_CHAIN (parmlist))
+    if (!TREE_PURPOSE (parmlist))
+      return 0;
+  return 1;
+}
+
 static tree
 build_conv (code, type, from)
      enum tree_code code;
      tree type, from;
 {
-  tree t = build1 (code, type, from);
+  tree t;
   int rank = ICS_STD_RANK (from);
+
+  /* We can't use buildl1 here because CODE could be USER_CONV, which
+     takes two arguments.  In that case, the caller is responsible for
+     filling in the second argument.  */
+  t = make_node (code);
+  TREE_TYPE (t) = type;
+  TREE_OPERAND (t, 0) = from;
+
   switch (code)
     {
     case PTR_CONV:
@@ -619,6 +642,9 @@ build_conv (code, type, from)
   return t;
 }
 
+/* If T is a REFERENCE_TYPE return the type to which T refers.
+   Otherwise, return T itself.  */
+
 static tree
 non_reference (t)
      tree t;
@@ -662,7 +688,7 @@ standard_conversion (to, from, expr)
   if ((TYPE_PTRFN_P (to) || TYPE_PTRMEMFUNC_P (to))
       && expr && type_unknown_p (expr))
     {
-      expr = instantiate_type (to, expr, itf_none);
+      expr = instantiate_type (to, expr, tf_none);
       if (expr == error_mark_node)
        return NULL_TREE;
       from = TREE_TYPE (expr);
@@ -716,6 +742,22 @@ standard_conversion (to, from, expr)
     {
       conv = build_conv (STD_CONV, to, conv);
     }
+  else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE)
+          || (tcode == POINTER_TYPE && fcode == INTEGER_TYPE))
+    {
+      /* For backwards brain damage compatibility, allow interconversion of
+        pointers and integers with a pedwarn.  */
+      conv = build_conv (STD_CONV, to, conv);
+      ICS_BAD_FLAG (conv) = 1;
+    }
+  else if (tcode == ENUMERAL_TYPE && fcode == INTEGER_TYPE
+          && TYPE_PRECISION (to) == TYPE_PRECISION (from))
+    {
+      /* For backwards brain damage compatibility, allow interconversion of
+        enums and integers with a pedwarn.  */
+      conv = build_conv (STD_CONV, to, conv);
+      ICS_BAD_FLAG (conv) = 1;
+    }
   else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE)
     {
       enum tree_code ufcode = TREE_CODE (TREE_TYPE (from));
@@ -729,7 +771,7 @@ standard_conversion (to, from, expr)
        {
          from = build_pointer_type
            (cp_build_qualified_type (void_type_node, 
-                                     CP_TYPE_QUALS (TREE_TYPE (from))));
+                                     cp_type_quals (TREE_TYPE (from))));
          conv = build_conv (PTR_CONV, from, conv);
        }
       else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE)
@@ -754,7 +796,7 @@ standard_conversion (to, from, expr)
            {
              from = 
                cp_build_qualified_type (TREE_TYPE (to),
-                                        CP_TYPE_QUALS (TREE_TYPE (from)));
+                                        cp_type_quals (TREE_TYPE (from)));
              from = build_pointer_type (from);
              conv = build_conv (PTR_CONV, from, conv);
            }
@@ -784,14 +826,14 @@ standard_conversion (to, from, expr)
       tree fbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fromfn)));
       tree tbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (tofn)));
 
-      if (! DERIVED_FROM_P (fbase, tbase)
-         || ! same_type_p (TREE_TYPE (fromfn), TREE_TYPE (tofn))
-         || ! compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)),
-                         TREE_CHAIN (TYPE_ARG_TYPES (tofn)))
-         || CP_TYPE_QUALS (fbase) != CP_TYPE_QUALS (tbase))
+      if (!DERIVED_FROM_P (fbase, tbase)
+         || !same_type_p (TREE_TYPE (fromfn), TREE_TYPE (tofn))
+         || !compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)),
+                        TREE_CHAIN (TYPE_ARG_TYPES (tofn)))
+         || cp_type_quals (fbase) != cp_type_quals (tbase))
        return 0;
 
-      from = cp_build_qualified_type (tbase, CP_TYPE_QUALS (fbase));
+      from = cp_build_qualified_type (tbase, cp_type_quals (fbase));
       from = build_cplus_method_type (from, TREE_TYPE (fromfn),
                                      TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
       from = build_ptrmemfunc_type (build_pointer_type (from));
@@ -977,10 +1019,9 @@ convert_class_to_reference (t, s, expr)
     return NULL_TREE;
 
   conv = build1 (IDENTITY_CONV, s, expr);
-  conv = build_conv (USER_CONV,
-                    non_reference (TREE_TYPE (TREE_TYPE (cand->fn))),
+  conv = build_conv (USER_CONV, TREE_TYPE (TREE_TYPE (cand->fn)),
                     conv);
-  TREE_OPERAND (conv, 1) = build_expr_ptr_wrapper (cand);
+  TREE_OPERAND (conv, 1) = build_zc_wrapper (cand);
   ICS_USER_FLAG (conv) = 1;
   if (cand->viable == -1)
     ICS_BAD_FLAG (conv) = 1;
@@ -1048,7 +1089,7 @@ reference_binding (rto, rfrom, expr, flags)
 
   if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
     {
-      expr = instantiate_type (to, expr, itf_none);
+      expr = instantiate_type (to, expr, tf_none);
       if (expr == error_mark_node)
        return NULL_TREE;
       from = TREE_TYPE (expr);
@@ -1073,7 +1114,7 @@ reference_binding (rto, rfrom, expr, flags)
     {
       /* [dcl.init.ref]
 
-        If the intializer expression 
+        If the initializer expression 
         
         -- is an lvalue (but not an lvalue for a bit-field), and "cv1 T1"
            is reference-compatible with "cv2 T2,"
@@ -1220,29 +1261,18 @@ implicit_conversion (to, from, expr, flags)
   if (conv)
     ;
   else if (expr != NULL_TREE
-          && (IS_AGGR_TYPE (non_reference (from))
-              || IS_AGGR_TYPE (non_reference (to)))
+          && (IS_AGGR_TYPE (from)
+              || IS_AGGR_TYPE (to))
           && (flags & LOOKUP_NO_CONVERSION) == 0)
     {
       cand = build_user_type_conversion_1
        (to, expr, LOOKUP_ONLYCONVERTING);
       if (cand)
        conv = cand->second_conv;
-      if ((! conv || ICS_BAD_FLAG (conv))
-         && TREE_CODE (to) == REFERENCE_TYPE
-         && (flags & LOOKUP_NO_TEMP_BIND) == 0)
-       {
-         cand = build_user_type_conversion_1
-           (TYPE_MAIN_VARIANT (TREE_TYPE (to)), expr, LOOKUP_ONLYCONVERTING);
-         if (cand)
-           {
-             if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (to)))
-               ICS_BAD_FLAG (cand->second_conv) = 1;
-             if (!conv || (ICS_BAD_FLAG (conv)
-                           > ICS_BAD_FLAG (cand->second_conv)))
-               conv = build_conv (REF_BIND, to, cand->second_conv);
-           }
-       }
+
+      /* We used to try to bind a reference to a temporary here, but that
+        is now handled by the recursive call to this function at the end
+        of reference_binding.  */
     }
 
   return conv;
@@ -1287,17 +1317,12 @@ add_function_candidate (candidates, fn, ctype, arglist, flags)
   tree parmnode, argnode;
   int viable = 1;
 
-  /* The `this' and `in_chrg' arguments to constructors are not considered
-     in overload resolution.  */
+  /* The `this', `in_chrg' and VTT arguments to constructors are not
+     considered in overload resolution.  */
   if (DECL_CONSTRUCTOR_P (fn))
     {
-      parmlist = TREE_CHAIN (parmlist);
-      arglist = TREE_CHAIN (arglist);
-      if (DECL_HAS_IN_CHARGE_PARM_P (fn))
-       {
-         parmlist = TREE_CHAIN (parmlist);
-         arglist = TREE_CHAIN (arglist);
-       }
+      parmlist = skip_artificial_parms_for (fn, parmlist);
+      arglist = skip_artificial_parms_for (fn, arglist);
     }
 
   len = list_length (arglist);
@@ -1322,13 +1347,8 @@ add_function_candidate (candidates, fn, ctype, arglist, flags)
     viable = 0;
 
   /* Make sure there are default args for the rest of the parms.  */
-  else for (; parmnode && parmnode != void_list_node;
-           parmnode = TREE_CHAIN (parmnode))
-    if (! TREE_PURPOSE (parmnode))
-      {
-       viable = 0;
-       break;
-      }
+  else if (!sufficient_parms_p (parmnode))
+    viable = 0;
 
   if (! viable)
     goto out;
@@ -1421,13 +1441,19 @@ add_conv_candidate (candidates, fn, obj, arglist)
      tree fn, obj, arglist;
 {
   tree totype = TREE_TYPE (TREE_TYPE (fn));
-  tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (totype));
-  int i, len = list_length (arglist) + 1;
-  tree convs = make_tree_vec (len);
-  tree parmnode = parmlist;
-  tree argnode = arglist;
-  int viable = 1;
-  int flags = LOOKUP_NORMAL;
+  int i, len, viable, flags;
+  tree parmlist, convs, parmnode, argnode;
+
+  for (parmlist = totype; TREE_CODE (parmlist) != FUNCTION_TYPE; )
+    parmlist = TREE_TYPE (parmlist);
+  parmlist = TYPE_ARG_TYPES (parmlist);
+
+  len = list_length (arglist) + 1;
+  convs = make_tree_vec (len);
+  parmnode = parmlist;
+  argnode = arglist;
+  viable = 1;
+  flags = LOOKUP_NORMAL;
 
   /* Don't bother looking up the same type twice.  */
   if (candidates && candidates->fn == totype)
@@ -1469,13 +1495,8 @@ add_conv_candidate (candidates, fn, obj, arglist)
   if (i < len)
     viable = 0;
 
-  for (; parmnode && parmnode != void_list_node;
-       parmnode = TREE_CHAIN (parmnode))
-    if (! TREE_PURPOSE (parmnode))
-      {
-       viable = 0;
-       break;
-      }
+  if (!sufficient_parms_p (parmnode))
+    viable = 0;
 
   return add_candidate (candidates, totype, convs, viable);
 }
@@ -1557,7 +1578,12 @@ promoted_arithmetic_type_p (type)
 /* Create any builtin operator overload candidates for the operator in
    question given the converted operand types TYPE1 and TYPE2.  The other
    args are passed through from add_builtin_candidates to
-   build_builtin_candidate.  */
+   build_builtin_candidate.  
+   
+   TYPE1 and TYPE2 may not be permissible, and we must filter them. 
+   If CODE is requires candidates operands of the same type of the kind
+   of which TYPE1 and TYPE2 are, we add both candidates
+   CODE (TYPE1, TYPE1) and CODE (TYPE2, TYPE2).  */
 
 static struct z_candidate *
 add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
@@ -1605,8 +1631,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
        return candidates;
     case POSTINCREMENT_EXPR:
     case PREINCREMENT_EXPR:
-      if ((ARITHMETIC_TYPE_P (type1) && TREE_CODE (type1) != ENUMERAL_TYPE)
-         || TYPE_PTROB_P (type1))
+      if (ARITHMETIC_TYPE_P (type1) || TYPE_PTROB_P (type1))
        {
          type1 = build_reference_type (type1);
          break;
@@ -1706,8 +1731,8 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
      candidate operator functions of the form112)
             ptrdiff_t operator-(T, T);
 
-   16For  every pointer type T, there exist candidate operator functions of
-     the form
+   16For every pointer or enumeration type T, there exist candidate operator
+     functions of the form
             bool    operator<(T, T);
             bool    operator>(T, T);
             bool    operator<=(T, T);
@@ -1751,15 +1776,19 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
          type1 = type2;
          break;
        }
+      /* FALLTHROUGH */
     case LT_EXPR:
     case GT_EXPR:
     case LE_EXPR:
     case GE_EXPR:
     case MAX_EXPR:
     case MIN_EXPR:
-      if ((ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
-         || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2)))
+      if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
+        break;
+      if (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))
        break;
+      if (TREE_CODE (type1) == ENUMERAL_TYPE && TREE_CODE (type2) == ENUMERAL_TYPE)
+        break;
       if (TYPE_PTR_P (type1) && null_ptr_cst_p (args[1]))
        {
          type2 = type1;
@@ -1887,13 +1916,13 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
          return candidates;
 
        default:
-         my_friendly_abort (367);
+         abort ();
        }
       type1 = build_reference_type (type1);
       break;
 
     case COND_EXPR:
-      /* [over.builtin]
+      /* [over.built]
 
         For every pair of promoted arithmetic types L and R, there
         exist candidate operator functions of the form 
@@ -1931,18 +1960,19 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
       return candidates;
 
     default:
-      my_friendly_abort (367);
+      abort ();
     }
 
-  /* If we're dealing with two pointer types, we need candidates
-     for both of them.  */
+  /* If we're dealing with two pointer types or two enumeral types,
+     we need candidates for both of them.  */
   if (type2 && !same_type_p (type1, type2)
       && TREE_CODE (type1) == TREE_CODE (type2)
       && (TREE_CODE (type1) == REFERENCE_TYPE
          || (TREE_CODE (type1) == POINTER_TYPE
              && TYPE_PTRMEM_P (type1) == TYPE_PTRMEM_P (type2))
          || TYPE_PTRMEMFUNC_P (type1)
-         || IS_AGGR_TYPE (type1)))
+         || IS_AGGR_TYPE (type1)
+         || TREE_CODE (type1) == ENUMERAL_TYPE))
     {
       candidates = build_builtin_candidate
        (candidates, fnname, type1, type1, args, argtypes, flags);
@@ -1971,7 +2001,12 @@ type_decays_to (type)
    2) pointer-pair taking candidates.  These are generated for each type
       one of the input types converts to.
    3) arithmetic candidates.  According to the standard, we should generate
-      all of these, but I'm trying not to... */
+      all of these, but I'm trying not to...
+   
+   Here we generate a superset of the possible candidates for this particular
+   case.  That is a subset of the full set the standard defines, plus some
+   other cases which the standard disallows. add_builtin_candidate will
+   filter out the illegal set.  */
 
 static struct z_candidate *
 add_builtin_candidates (candidates, code, code2, fnname, args, flags)
@@ -1981,6 +2016,7 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
      int flags;
 {
   int ref1, i;
+  int enum_p = 0;
   tree type, argtypes[3];
   /* TYPES[i] is the set of possible builtin-operator parameter types
      we will consider for the Ith argument.  These are represented as
@@ -2032,6 +2068,16 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
     case COMPONENT_REF:
       return candidates;
 
+    case COND_EXPR:
+    case EQ_EXPR:
+    case NE_EXPR:
+    case LT_EXPR:
+    case LE_EXPR:
+    case GT_EXPR:
+    case GE_EXPR:
+      enum_p = 1;
+      /* FALLTHROUGH */
+    
     default:
       ref1 = 0;
     }
@@ -2080,8 +2126,8 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
              if (i != 0 || ! ref1)
                {
                  type = TYPE_MAIN_VARIANT (type_decays_to (type));
-                 if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE)
-                   types[i] = tree_cons (NULL_TREE, type, types[i]);
+                 if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
+                   types[i] = tree_cons (NULL_TREE, type, types[i]);
                  if (INTEGRAL_TYPE_P (type))
                    type = type_promotes_to (type);
                }
@@ -2099,8 +2145,8 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
          if (i != 0 || ! ref1)
            {
              type = TYPE_MAIN_VARIANT (type_decays_to (type));
-             if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE)
-               types[i] = tree_cons (NULL_TREE, type, types[i]);
+             if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
+               types[i] = tree_cons (NULL_TREE, type, types[i]);
              if (INTEGRAL_TYPE_P (type))
                type = type_promotes_to (type);
            }
@@ -2149,26 +2195,24 @@ add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
 {
   int ntparms = DECL_NTPARMS (tmpl);
   tree targs = make_tree_vec (ntparms);
-  tree args_without_in_chrg;
+  tree args_without_in_chrg = arglist;
   struct z_candidate *cand;
   int i;
   tree fn;
 
-  /* TEMPLATE_DECLs do not have the in-charge parameter, nor the VTT
-     parameter.  So, skip it here before attempting to perform
-     argument deduction.  */
+  /* We don't do deduction on the in-charge parameter, the VTT
+     parameter or 'this'.  */
+  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl))
+    args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
+
   if ((DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (tmpl)
        || DECL_BASE_CONSTRUCTOR_P (tmpl))
       && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (tmpl)))
-    args_without_in_chrg = tree_cons (NULL_TREE, 
-                                     TREE_VALUE (arglist),
-                                     TREE_CHAIN (TREE_CHAIN (arglist)));
-  else
-    args_without_in_chrg = arglist;
+    args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
 
   i = fn_type_unification (tmpl, explicit_targs, targs,
                           args_without_in_chrg,
-                          return_type, strict);
+                          return_type, strict, -1);
 
   if (i != 0)
     return candidates;
@@ -2177,6 +2221,36 @@ add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
   if (fn == error_mark_node)
     return candidates;
 
+  /* In [class.copy]:
+
+       A member function template is never instantiated to perform the
+       copy of a class object to an object of its class type.  
+
+     It's a little unclear what this means; the standard explicitly
+     does allow a template to be used to copy a class.  For example,
+     in:
+
+       struct A {
+         A(A&);
+        template <class T> A(const T&);
+       };
+       const A f ();
+       void g () { A a (f ()); }
+       
+     the member template will be used to make the copy.  The section
+     quoted above appears in the paragraph that forbids constructors
+     whose only parameter is (a possibly cv-qualified variant of) the
+     class type, and a logical interpretation is that the intent was
+     to forbid the instantiation of member templates which would then
+     have that form.  */
+  if (DECL_CONSTRUCTOR_P (fn) && list_length (arglist) == 2) 
+    {
+      tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
+      if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),
+                                   ctype))
+       return candidates;
+    }
+
   if (obj != NULL_TREE)
     /* Aha, this is a conversion function.  */
     cand = add_conv_candidate (candidates, fn, obj, arglist);
@@ -2245,6 +2319,16 @@ any_viable (cands)
   return 0;
 }
 
+static int
+any_strictly_viable (cands)
+     struct z_candidate *cands;
+{
+  for (; cands; cands = cands->next)
+    if (cands->viable == 1)
+      return 1;
+  return 0;
+}
+
 static struct z_candidate *
 splice_viable (cands)
      struct z_candidate *cands;
@@ -2280,20 +2364,20 @@ print_z_candidates (candidates)
       if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
        {
          if (TREE_VEC_LENGTH (candidates->convs) == 3)
-           cp_error ("%s %D(%T, %T, %T) <builtin>", str, candidates->fn,
+           error ("%s %D(%T, %T, %T) <built-in>", str, candidates->fn,
                      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
                      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)),
                      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2)));
          else if (TREE_VEC_LENGTH (candidates->convs) == 2)
-           cp_error ("%s %D(%T, %T) <builtin>", str, candidates->fn,
+           error ("%s %D(%T, %T) <built-in>", str, candidates->fn,
                      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
                      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)));
          else
-           cp_error ("%s %D(%T) <builtin>", str, candidates->fn,
+           error ("%s %D(%T) <built-in>", str, candidates->fn,
                      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)));
        }
       else if (TYPE_P (candidates->fn))
-       cp_error ("%s %T <conversion>", str, candidates->fn);
+       error ("%s %T <conversion>", str, candidates->fn);
       else
        cp_error_at ("%s %+#D%s", str, candidates->fn,
                     candidates->viable == -1 ? " <near match>" : "");
@@ -2318,15 +2402,18 @@ build_user_type_conversion_1 (totype, expr, flags)
   tree args = NULL_TREE;
   tree templates = NULL_TREE;
 
+  /* We represent conversion within a hierarchy using RVALUE_CONV and
+     BASE_CONV, as specified by [over.best.ics]; these become plain
+     constructor calls, as specified in [dcl.init].  */
+  my_friendly_assert (!IS_AGGR_TYPE (fromtype) || !IS_AGGR_TYPE (totype)
+                     || !DERIVED_FROM_P (totype, fromtype), 20011226);
+
   if (IS_AGGR_TYPE (totype))
     ctors = lookup_fnfields (TYPE_BINFO (totype),
-                            (flag_new_abi 
-                             ? complete_ctor_identifier
-                             : ctor_identifier),
+                            complete_ctor_identifier,
                             0);
 
-  if (IS_AGGR_TYPE (fromtype)
-      && (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype)))
+  if (IS_AGGR_TYPE (fromtype))
     convs = lookup_conversions (fromtype);
 
   candidates = 0;
@@ -2341,10 +2428,11 @@ build_user_type_conversion_1 (totype, expr, flags)
       t = build_int_2 (0, 0);
       TREE_TYPE (t) = build_pointer_type (totype);
       args = build_tree_list (NULL_TREE, expr);
-      if (DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors)))
-       args = tree_cons (NULL_TREE, 
-                         in_charge_arg_for_name (complete_ctor_identifier), 
-                         args);
+      /* We should never try to call the abstract or base constructor
+        from here.  */
+      my_friendly_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors))
+                         && !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors)),
+                         20011226);
       args = tree_cons (NULL_TREE, t, args);
     }
   for (; ctors; ctors = OVL_NEXT (ctors))
@@ -2379,7 +2467,6 @@ build_user_type_conversion_1 (totype, expr, flags)
     {
       tree fns = TREE_VALUE (convs);
       int convflags = LOOKUP_NO_CONVERSION;
-      tree ics;
 
       /* If we are called to convert to a reference type, we are trying to
         find an lvalue binding, so don't even consider temporaries.  If
@@ -2387,57 +2474,46 @@ build_user_type_conversion_1 (totype, expr, flags)
         look for a temporary binding.  */
       if (TREE_CODE (totype) == REFERENCE_TYPE)
        convflags |= LOOKUP_NO_TEMP_BIND;
+      
+      for (; fns; fns = OVL_NEXT (fns))
+       {
+         tree fn = OVL_CURRENT (fns);
+         struct z_candidate *old_candidates = candidates;
+         
+         /* [over.match.funcs] For conversion functions, the function
+            is considered to be a member of the class of the implicit
+            object argument for the purpose of defining the type of
+            the implicit object parameter.
 
-      if (TREE_CODE (OVL_CURRENT (fns)) != TEMPLATE_DECL)
-       ics = implicit_conversion
-         (totype, TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))), 0, convflags);
-      else
-       /* 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 (; fns; fns = OVL_NEXT (fns))
-         {
-           tree fn = OVL_CURRENT (fns);
-           struct z_candidate *old_candidates = candidates;
-
-           /* [over.match.funcs] For conversion functions, the function is
-              considered to be a member of the class of the implicit object
-              argument for the purpose of defining the type of the implicit
-              object parameter.
+            So we pass fromtype as CTYPE to add_*_candidate.  */
 
-              So we pass fromtype as CTYPE to add_*_candidate.  */
+         if (TREE_CODE (fn) == TEMPLATE_DECL)
+           {
+             templates = tree_cons (NULL_TREE, fn, templates);
+             candidates = 
+               add_template_candidate (candidates, fn, fromtype, NULL_TREE,
+                                       args, totype, flags,
+                                       DEDUCE_CONV);
+           } 
+         else 
+           candidates = add_function_candidate (candidates, fn, fromtype,
+                                                args, flags); 
 
-           if (TREE_CODE (fn) == TEMPLATE_DECL)
-             {
-               templates = tree_cons (NULL_TREE, fn, templates);
-               candidates = 
-                 add_template_candidate (candidates, fn, fromtype, NULL_TREE,
-                                         args, totype, flags,
-                                         DEDUCE_CONV);
-             } 
-           else 
-             candidates = add_function_candidate (candidates, fn, fromtype,
-                                                  args, flags); 
+         if (candidates != old_candidates)
+           {
+             tree ics = implicit_conversion
+               (totype, TREE_TYPE (TREE_TYPE (candidates->fn)),
+                0, convflags);
 
-           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 = TYPE_BINFO (fromtype);
-
-               if (ics == NULL_TREE)
-                 candidates->viable = 0;
-               else if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
-                 candidates->viable = -1;
-             }
-         }
+             candidates->second_conv = ics;
+             candidates->basetype_path = TYPE_BINFO (fromtype);
+             
+             if (ics == NULL_TREE)
+               candidates->viable = 0;
+             else if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
+               candidates->viable = -1;
+           }
+       }
     }
 
   if (! any_viable (candidates))
@@ -2448,7 +2524,7 @@ build_user_type_conversion_1 (totype, expr, flags)
          if (candidates && ! candidates->next)
            /* say why this one won't work or try to be loose */;
          else
-           cp_error ("no viable candidates");
+           error ("no viable candidates");
        }
 #endif
 
@@ -2462,7 +2538,7 @@ build_user_type_conversion_1 (totype, expr, flags)
     {
       if (flags & LOOKUP_COMPLAIN)
        {
-         cp_error ("conversion from `%T' to `%T' is ambiguous",
+         error ("conversion from `%T' to `%T' is ambiguous",
                    fromtype, totype);
          print_z_candidates (candidates);
        }
@@ -2482,10 +2558,11 @@ 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, build_expr_ptr_wrapper (cand));
-  ICS_USER_FLAG (cand->second_conv) = 1;
+     expr, build_zc_wrapper (cand));
+  
+  ICS_USER_FLAG (cand->second_conv) = ICS_USER_FLAG (*p) = 1;
   if (cand->viable == -1)
-    ICS_BAD_FLAG (cand->second_conv) = 1;
+    ICS_BAD_FLAG (cand->second_conv) = ICS_BAD_FLAG (*p) = 1;
 
   return cand;
 }
@@ -2502,9 +2579,7 @@ build_user_type_conversion (totype, expr, flags)
     {
       if (TREE_CODE (cand->second_conv) == AMBIG_CONV)
        return error_mark_node;
-      return convert_from_reference
-              (convert_like_with_context
-                (cand->second_conv, expr, cand->fn, 0));
+      return convert_from_reference (convert_like (cand->second_conv, expr));
     }
   return NULL_TREE;
 }
@@ -2518,15 +2593,19 @@ resolve_args (args)
   tree t;
   for (t = args; t; t = TREE_CHAIN (t))
     {
-      if (TREE_VALUE (t) == error_mark_node)
+      tree arg = TREE_VALUE (t);
+      
+      if (arg == error_mark_node)
        return error_mark_node;
-      else if (TREE_CODE (TREE_TYPE (TREE_VALUE (t))) == VOID_TYPE)
+      else if (VOID_TYPE_P (TREE_TYPE (arg)))
        {
          error ("invalid use of void expression");
          return error_mark_node;
        }
-      else if (TREE_CODE (TREE_VALUE (t)) == OFFSET_REF)
-       TREE_VALUE (t) = resolve_offset_ref (TREE_VALUE (t));
+      else if (TREE_CODE (arg) == OFFSET_REF)
+       arg = resolve_offset_ref (arg);
+      arg = convert_from_reference (arg);
+      TREE_VALUE (t) = arg;
     }
   return args;
 }
@@ -2576,7 +2655,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)'",
+         error ("no matching function for call to `%D(%A)'",
                    DECL_NAME (OVL_FUNCTION (fn)), args);
          if (candidates)
            print_z_candidates (candidates);
@@ -2587,7 +2666,7 @@ build_new_function_call (fn, args)
 
       if (cand == 0)
        {
-         cp_error ("call of overloaded `%D (%A)' is ambiguous",
+         error ("call of overloaded `%D(%A)' is ambiguous",
                    DECL_NAME (OVL_FUNCTION (fn)), args);
          print_z_candidates (candidates);
          return error_mark_node;
@@ -2614,7 +2693,7 @@ build_object_call (obj, args)
     {
       /* 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 without an object; consider using .* or ->*", obj);
+      error ("pointer-to-member function %E cannot be called without an object; consider using .* or ->*", obj);
       return error_mark_node;
     }
 
@@ -2659,8 +2738,12 @@ build_object_call (obj, args)
       tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns)));
 
       if ((TREE_CODE (totype) == POINTER_TYPE
-          || TREE_CODE (totype) == REFERENCE_TYPE)
-         && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
+          && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
+         || (TREE_CODE (totype) == REFERENCE_TYPE
+             && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
+         || (TREE_CODE (totype) == REFERENCE_TYPE
+             && TREE_CODE (TREE_TYPE (totype)) == POINTER_TYPE
+             && TREE_CODE (TREE_TYPE (TREE_TYPE (totype))) == FUNCTION_TYPE))
        for (; fns; fns = OVL_NEXT (fns))
          {
            tree fn = OVL_CURRENT (fns);
@@ -2679,7 +2762,7 @@ build_object_call (obj, args)
 
   if (! any_viable (candidates))
     {
-      cp_error ("no match for call to `(%T) (%A)'", TREE_TYPE (obj), args);
+      error ("no match for call to `(%T) (%A)'", TREE_TYPE (obj), args);
       print_z_candidates (candidates);
       return error_mark_node;
     }
@@ -2689,7 +2772,7 @@ build_object_call (obj, args)
 
   if (cand == 0)
     {
-      cp_error ("call of `(%T) (%A)' is ambiguous", TREE_TYPE (obj), args);
+      error ("call of `(%T) (%A)' is ambiguous", TREE_TYPE (obj), args);
       print_z_candidates (candidates);
       return error_mark_node;
     }
@@ -2714,7 +2797,7 @@ op_error (code, code2, arg1, arg2, arg3, problem)
      tree arg1, arg2, arg3;
      const char *problem;
 {
-  const char * opname;
+  const char *opname;
 
   if (code == MODIFY_EXPR)
     opname = assignment_operator_name_info[code2].name;
@@ -2724,23 +2807,23 @@ op_error (code, code2, arg1, arg2, arg3, problem)
   switch (code)
     {
     case COND_EXPR:
-      cp_error ("%s for `%T ? %T : %T'", problem,
+      error ("%s for `%T ? %T : %T' operator", problem,
                error_type (arg1), error_type (arg2), error_type (arg3));
       break;
     case POSTINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
-      cp_error ("%s for `%T%s'", problem, error_type (arg1), opname);
+      error ("%s for `%T %s' operator", problem, error_type (arg1), opname);
       break;
     case ARRAY_REF:
-      cp_error ("%s for `%T[%T]'", problem,
+      error ("%s for `%T [%T]' operator", problem,
                error_type (arg1), error_type (arg2));
       break;
     default:
       if (arg2)
-       cp_error ("%s for `%T %s %T'", problem,
+       error ("%s for `%T %s %T' operator", problem,
                  error_type (arg1), opname, error_type (arg2));
       else
-       cp_error ("%s for `%s%T'", problem, opname, error_type (arg1));
+       error ("%s for `%s %T' operator", problem, opname, error_type (arg1));
     }
 }
 
@@ -2852,11 +2935,6 @@ build_conditional_expr (arg1, arg2, arg3)
       || TREE_TYPE (arg3) == error_mark_node)
     return error_mark_node;
 
-  /* Convert from reference types to ordinary types; no expressions
-     really have reference type in C++.  */
-  arg2 = convert_from_reference (arg2);
-  arg3 = convert_from_reference (arg3);
-     
   /* [expr.cond]
 
      If either the second or the third operand has type (possibly
@@ -2896,7 +2974,7 @@ build_conditional_expr (arg1, arg2, arg3)
        result_type = void_type_node;
       else
        {
-         cp_error ("`%E' has type `void' and is not a throw-expression",
+         error ("`%E' has type `void' and is not a throw-expression",
                    VOID_TYPE_P (arg2_type) ? arg2 : arg3);
          return error_mark_node;
        }
@@ -2929,7 +3007,7 @@ build_conditional_expr (arg1, arg2, arg3)
          || (conv2 && TREE_CODE (conv2) == AMBIG_CONV)
          || (conv3 && TREE_CODE (conv3) == AMBIG_CONV))
        {
-         cp_error ("operands to ?: have different types");
+         error ("operands to ?: have different types");
          return error_mark_node;
        }
       else if (conv2 && !ICS_BAD_FLAG (conv2))
@@ -3055,6 +3133,9 @@ build_conditional_expr (arg1, arg2, arg3)
     arg3 = decay_conversion (arg3);
   arg3_type = TREE_TYPE (arg3);
 
+  if (arg2 == error_mark_node || arg3 == error_mark_node)
+    return error_mark_node;
+  
   /* [expr.cond]
      
      After those conversions, one of the following shall hold:
@@ -3079,14 +3160,14 @@ build_conditional_expr (arg1, arg2, arg3)
       
       if (TREE_CODE (arg2_type) == ENUMERAL_TYPE
           && TREE_CODE (arg3_type) == ENUMERAL_TYPE)
-         cp_warning ("enumeral mismatch in conditional expression: `%T' vs `%T'",
+         warning ("enumeral mismatch in conditional expression: `%T' vs `%T'",
                    arg2_type, arg3_type);
       else if (extra_warnings
                && ((TREE_CODE (arg2_type) == ENUMERAL_TYPE
                     && !same_type_p (arg3_type, type_promotes_to (arg2_type)))
                    || (TREE_CODE (arg3_type) == ENUMERAL_TYPE
                        && !same_type_p (arg2_type, type_promotes_to (arg3_type)))))
-        cp_warning ("enumeral and non-enumeral type in conditional expression");
+        warning ("enumeral and non-enumeral type in conditional expression");
       
       arg2 = perform_implicit_conversion (result_type, arg2);
       arg3 = perform_implicit_conversion (result_type, arg3);
@@ -3126,7 +3207,7 @@ build_conditional_expr (arg1, arg2, arg3)
 
   if (!result_type)
     {
-      cp_error ("operands to ?: have different types");
+      error ("operands to ?: have different types");
       return error_mark_node;
     }
 
@@ -3157,6 +3238,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
   enum tree_code code2 = NOP_EXPR;
   tree templates = NULL_TREE;
   tree conv;
+  bool viable_candidates;
 
   if (arg1 == error_mark_node
       || arg2 == error_mark_node
@@ -3167,7 +3249,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
      undeclared_template<1, 5, 72>a;  */
   if (code == LT_EXPR && TREE_CODE (arg1) == TEMPLATE_DECL)
     {
-      cp_error ("`%D' must be declared before use", arg1);
+      error ("`%D' must be declared before use", arg1);
       return error_mark_node;
     }
 
@@ -3180,6 +3262,10 @@ build_new_op (code, flags, arg1, arg2, arg3)
   else
     fnname = ansi_opname (code);
 
+  if (TREE_CODE (arg1) == OFFSET_REF)
+    arg1 = resolve_offset_ref (arg1);
+  arg1 = convert_from_reference (arg1);
+  
   switch (code)
     {
     case NEW_EXPR:
@@ -3187,7 +3273,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
     case VEC_DELETE_EXPR:
     case DELETE_EXPR:
       /* Use build_op_new_call and build_op_delete_call instead. */
-      my_friendly_abort (981018);
+      abort ();
 
     case CALL_EXPR:
       return build_object_call (arg1, arg2);
@@ -3196,14 +3282,19 @@ build_new_op (code, flags, arg1, arg2, arg3)
       break;
     }
 
-  /* The comma operator can have void args.  */
-  if (TREE_CODE (arg1) == OFFSET_REF)
-    arg1 = resolve_offset_ref (arg1);
-  if (arg2 && TREE_CODE (arg2) == OFFSET_REF)
-    arg2 = resolve_offset_ref (arg2);
-  if (arg3 && TREE_CODE (arg3) == OFFSET_REF)
-    arg3 = resolve_offset_ref (arg3);
-
+  if (arg2)
+    {
+      if (TREE_CODE (arg2) == OFFSET_REF)
+       arg2 = resolve_offset_ref (arg2);
+      arg2 = convert_from_reference (arg2);
+    }
+  if (arg3)
+    {
+      if (TREE_CODE (arg3) == OFFSET_REF)
+       arg3 = resolve_offset_ref (arg3);
+      arg3 = convert_from_reference (arg3);
+    }
+  
   if (code == COND_EXPR)
     {
       if (arg2 == NULL_TREE
@@ -3220,13 +3311,12 @@ build_new_op (code, flags, arg1, arg2, arg3)
   if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
     arg2 = integer_zero_node;
 
-  if (arg2 && arg3)
-    arglist = tree_cons (NULL_TREE, arg1, tree_cons
-                     (NULL_TREE, arg2, build_tree_list (NULL_TREE, arg3)));
-  else if (arg2)
-    arglist = tree_cons (NULL_TREE, arg1, build_tree_list (NULL_TREE, arg2));
-  else
-    arglist = build_tree_list (NULL_TREE, arg1);
+  arglist = NULL_TREE;
+  if (arg3)
+    arglist = tree_cons (NULL_TREE, arg3, arglist);
+  if (arg2)
+    arglist = tree_cons (NULL_TREE, arg2, arglist);
+  arglist = tree_cons (NULL_TREE, arg1, arglist);
 
   fns = lookup_function_nonclass (fnname, arglist);
 
@@ -3313,7 +3403,25 @@ build_new_op (code, flags, arg1, arg2, arg3)
       (candidates, code, code2, fnname, args, flags);
   }
 
-  if (! any_viable (candidates))
+  switch (code)
+    {
+    case COMPOUND_EXPR:
+    case ADDR_EXPR:
+      /* For these, the built-in candidates set is empty
+        [over.match.oper]/3.  We don't want non-strict matches
+        because exact matches are always possible with built-in
+        operators.  The built-in candidate set for COMPONENT_REF
+        would be empty too, but since there are no such built-in
+        operators, we accept non-strict matches for them.  */
+      viable_candidates = any_strictly_viable (candidates);
+      break;
+
+    default:
+      viable_candidates = any_viable (candidates);
+      break;
+    }      
+
+  if (! viable_candidates)
     {
       switch (code)
        {
@@ -3322,7 +3430,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
          /* Look for an `operator++ (int)'.  If they didn't have
             one, then we fall back to the old way of doing things.  */
          if (flags & LOOKUP_COMPLAIN)
-           cp_pedwarn ("no `%D (int)' declared for postfix `%s', trying prefix operator instead",
+           pedwarn ("no `%D(int)' declared for postfix `%s', trying prefix operator instead",
                        fnname, 
                        operator_name_info[code].name);
          if (code == POSTINCREMENT_EXPR)
@@ -3369,7 +3477,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
          && candidates->next
          && ! candidates->next->next)
        {
-         cp_warning ("using synthesized `%#D' for copy assignment",
+         warning ("using synthesized `%#D' for copy assignment",
                      cand->fn);
          cp_warning_at ("  where cfront would use `%#D'",
                         cand == candidates
@@ -3398,7 +3506,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
          && (TYPE_MAIN_VARIANT (TREE_TYPE (arg1))
              != TYPE_MAIN_VARIANT (TREE_TYPE (arg2))))
        {
-         cp_warning ("comparison between `%#T' and `%#T'", 
+         warning ("comparison between `%#T' and `%#T'", 
                      TREE_TYPE (arg1), TREE_TYPE (arg2));
        }
       break;
@@ -3479,7 +3587,7 @@ builtin:
 
     case MEMBER_REF:
       return build_m_component_ref
-       (build_indirect_ref (arg1, NULL_PTR), arg2);
+       (build_indirect_ref (arg1, NULL), arg2);
 
       /* The caller will deal with these.  */
     case ADDR_EXPR:
@@ -3488,7 +3596,7 @@ builtin:
       return NULL_TREE;
 
     default:
-      my_friendly_abort (367);
+      abort ();
       return NULL_TREE;
     }
 }
@@ -3500,11 +3608,10 @@ builtin:
    match with the placement new is accepted.
 
    CODE is either DELETE_EXPR or VEC_DELETE_EXPR.
-   ADDR is the pointer to be deleted.  For placement delete, it is also
-     used to determine what the corresponding new looked like.
+   ADDR is the pointer to be deleted.
    SIZE is the size of the memory block to be deleted.
    FLAGS are the usual overloading flags.
-   PLACEMENT is the corresponding placement new call, or 0.  */
+   PLACEMENT is the corresponding placement new call, or NULL_TREE.  */
 
 tree
 build_op_delete_call (code, addr, size, flags, placement)
@@ -3512,12 +3619,17 @@ build_op_delete_call (code, addr, size, flags, placement)
      tree addr, size, placement;
      int flags;
 {
-  tree fn, fns, fnname, fntype, argtypes, args, type;
+  tree fn = NULL_TREE;
+  tree fns, fnname, fntype, argtypes, args, type;
+  int pass;
 
   if (addr == error_mark_node)
     return error_mark_node;
 
   type = TREE_TYPE (TREE_TYPE (addr));
+  while (TREE_CODE (type) == ARRAY_TYPE)
+    type = TREE_TYPE (type);
+
   fnname = ansi_opname (code);
 
   if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL))
@@ -3541,15 +3653,22 @@ build_op_delete_call (code, addr, size, flags, placement)
 
   if (placement)
     {
-      /* placement is a CALL_EXPR around an ADDR_EXPR around a function.  */
+      tree alloc_fn;
+      tree call_expr;
 
+      /* Find the allocation function that is being called. */
+      call_expr = placement;
+      /* Sometimes we have a COMPOUND_EXPR, rather than a simple
+        CALL_EXPR. */
+      while (TREE_CODE (call_expr) == COMPOUND_EXPR)
+       call_expr = TREE_OPERAND (call_expr, 1);
       /* Extract the function.  */
-      argtypes = TREE_OPERAND (TREE_OPERAND (placement, 0), 0);
+      alloc_fn = get_callee_fndecl (call_expr);
+      my_friendly_assert (alloc_fn != NULL_TREE, 20020327);
       /* Then the second parm type.  */
-      argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (argtypes)));
-
+      argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)));
       /* Also the second argument.  */
-      args = TREE_CHAIN (TREE_OPERAND (placement, 1));
+      args = TREE_CHAIN (TREE_OPERAND (call_expr, 1));
     }
   else
     {
@@ -3558,52 +3677,75 @@ build_op_delete_call (code, addr, size, flags, placement)
       args = NULL_TREE;
     }
 
-  argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes);
-  fntype = build_function_type (void_type_node, argtypes);
-
   /* Strip const and volatile from addr.  */
-  if (type != TYPE_MAIN_VARIANT (type))
-    addr = cp_convert (build_pointer_type (TYPE_MAIN_VARIANT (type)), addr);
+  addr = cp_convert (ptr_type_node, addr);
 
-  fn = instantiate_type (fntype, fns, itf_no_attributes);
-
-  if (fn != error_mark_node)
+  /* We make two tries at finding a matching `operator delete'.  On
+     the first pass, we look for an one-operator (or placement)
+     operator delete.  If we're not doing placement delete, then on
+     the second pass we look for a two-argument delete.  */
+  for (pass = 0; pass < (placement ? 1 : 2); ++pass) 
     {
-      if (TREE_CODE (fns) == TREE_LIST)
-       /* Member functions.  */
-       enforce_access (type, fn);
-      return build_function_call (fn, tree_cons (NULL_TREE, addr, args));
+      if (pass == 0)
+       argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes);
+      else 
+       /* Normal delete; now try to find a match including the size
+          argument.  */
+       argtypes = tree_cons (NULL_TREE, ptr_type_node,
+                             tree_cons (NULL_TREE, sizetype, 
+                                        void_list_node));
+      fntype = build_function_type (void_type_node, argtypes);
+
+      /* Go through the `operator delete' functions looking for one
+        with a matching type.  */
+      for (fn = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns; 
+          fn; 
+          fn = OVL_NEXT (fn))
+       {
+         tree t;
+
+         /* Exception specifications on the `delete' operator do not
+            matter.  */
+         t = build_exception_variant (TREE_TYPE (OVL_CURRENT (fn)),
+                                      NULL_TREE);
+         /* We also don't compare attributes.  We're really just
+            trying to check the types of the first two parameters.  */
+         if (comptypes (t, fntype, COMPARE_NO_ATTRIBUTES))
+           break;
+       }
+
+      /* If we found a match, we're done.  */
+      if (fn)
+       break;
     }
 
-  /* If we are doing placement delete we do nothing if we don't find a
-     matching op delete.  */
-  if (placement)
-    return NULL_TREE;
+  /* If we have a matching function, call it.  */
+  if (fn)
+    {
+      /* Make sure we have the actual function, and not an
+        OVERLOAD.  */
+      fn = OVL_CURRENT (fn);
 
-  /* Normal delete; now try to find a match including the size argument.  */
-  argtypes = tree_cons (NULL_TREE, ptr_type_node,
-                       tree_cons (NULL_TREE, sizetype, void_list_node));
-  fntype = build_function_type (void_type_node, argtypes);
+      /* If the FN is a member function, make sure that it is
+        accessible.  */
+      if (DECL_CLASS_SCOPE_P (fn))
+       enforce_access (type, fn);
 
-  fn = instantiate_type (fntype, fns, itf_no_attributes);
+      if (pass == 0)
+       args = tree_cons (NULL_TREE, addr, args);
+      else
+       args = tree_cons (NULL_TREE, addr, 
+                         build_tree_list (NULL_TREE, size));
 
-  if (fn != error_mark_node)
-    {
-      if (BASELINK_P (fns))
-       /* Member functions.  */
-       enforce_access (type, fn);
-      return build_function_call
-       (fn, tree_cons (NULL_TREE, addr,
-                       build_tree_list (NULL_TREE, size)));
+      return build_function_call (fn, args);
     }
 
-  /* 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)
+  /* If we are doing placement delete we do nothing if we don't find a
+     matching op delete.  */
+  if (placement)
     return NULL_TREE;
 
-  cp_error ("no suitable `operator delete' for `%T'", type);
+  error ("no suitable `operator delete' for `%T'", type);
   return error_mark_node;
 }
 
@@ -3627,7 +3769,7 @@ enforce_access (basetype_path, decl)
        cp_error_at ("`%+#D' is protected", decl);
       else
        cp_error_at ("`%+#D' is inaccessible", decl);
-      cp_error ("within this context");
+      error ("within this context");
       return 0;
     }
 
@@ -3637,7 +3779,8 @@ enforce_access (basetype_path, decl)
 /* Perform the conversions in CONVS on the expression EXPR. 
    FN and ARGNUM are used for diagnostics.  ARGNUM is zero based, -1
    indicates the `this' argument of a method.  INNER is non-zero when
-   being called to continue a conversion chain. */
+   being called to continue a conversion chain. It is negative when a
+   reference binding will be applied, positive otherwise. */
 
 static tree
 convert_like_real (convs, expr, fn, argnum, inner)
@@ -3646,6 +3789,10 @@ convert_like_real (convs, expr, fn, argnum, inner)
      int argnum;
      int inner;
 {
+  int savew, savee;
+
+  tree totype = TREE_TYPE (convs);
+
   if (ICS_BAD_FLAG (convs)
       && TREE_CODE (convs) != USER_CONV
       && TREE_CODE (convs) != AMBIG_CONV
@@ -3654,7 +3801,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
       tree t = convs; 
       for (; t; t = TREE_OPERAND (t, 0))
        {
-         if (TREE_CODE (t) == USER_CONV)
+         if (TREE_CODE (t) == USER_CONV || !ICS_BAD_FLAG (t))
            {
              expr = convert_like_real (t, expr, fn, argnum, 1);
              break;
@@ -3664,31 +3811,35 @@ convert_like_real (convs, expr, fn, argnum, inner)
          else if (TREE_CODE (t) == IDENTITY_CONV)
            break;
        }
-      return convert_for_initialization
-       (NULL_TREE, TREE_TYPE (convs), expr, LOOKUP_NORMAL,
-        "conversion", fn, argnum);
+      pedwarn ("invalid conversion from `%T' to `%T'", TREE_TYPE (expr), totype);
+      if (fn)
+       pedwarn ("  initializing argument %P of `%D'", argnum, fn);
+      return cp_convert (totype, expr);
     }
   
   if (!inner)
     expr = dubious_conversion_warnings
-             (TREE_TYPE (convs), expr, "argument", fn, argnum);
+             (totype, expr, "argument", fn, argnum);
   switch (TREE_CODE (convs))
     {
     case USER_CONV:
       {
        struct z_candidate *cand
-         = WRAPPER_PTR (TREE_OPERAND (convs, 1));
-       tree fn = cand->fn;
+         = WRAPPER_ZC (TREE_OPERAND (convs, 1));
+       tree convfn = cand->fn;
        tree args;
 
-       if (DECL_CONSTRUCTOR_P (fn))
+       if (DECL_CONSTRUCTOR_P (convfn))
          {
            tree t = build_int_2 (0, 0);
-           TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (fn));
+           TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (convfn));
 
            args = build_tree_list (NULL_TREE, expr);
-           if (DECL_HAS_IN_CHARGE_PARM_P (fn))
-             args = tree_cons (NULL_TREE, integer_one_node, args);
+           if (DECL_HAS_IN_CHARGE_PARM_P (convfn)
+               || DECL_HAS_VTT_PARM_P (convfn))
+             /* We should never try to call the abstract or base constructor
+                from here.  */
+             abort ();
            args = tree_cons (NULL_TREE, t, args);
          }
        else
@@ -3697,25 +3848,69 @@ convert_like_real (convs, expr, fn, argnum, inner)
 
        /* If this is a constructor or a function returning an aggr type,
           we need to build up a TARGET_EXPR.  */
-       if (DECL_CONSTRUCTOR_P (fn))
-         expr = build_cplus_new (TREE_TYPE (convs), expr);
+       if (DECL_CONSTRUCTOR_P (convfn))
+         expr = build_cplus_new (totype, expr);
+
+       /* The result of the call is then used to direct-initialize the object
+          that is the destination of the copy-initialization.  [dcl.init]
+
+          Note that this step is not reflected in the conversion sequence;
+          it affects the semantics when we actually perform the
+          conversion, but is not considered during overload resolution.
 
+          If the target is a class, that means call a ctor.  */
+       if (IS_AGGR_TYPE (totype)
+           && (inner >= 0 || !lvalue_p (expr)))
+         {
+           savew = warningcount, savee = errorcount;
+           expr = build_new_method_call
+             (NULL_TREE, complete_ctor_identifier,
+              build_tree_list (NULL_TREE, expr), TYPE_BINFO (totype),
+              /* Core issue 84, now a DR, says that we don't allow UDCs
+                 for these args (which deliberately breaks copy-init of an
+                 auto_ptr<Base> from an auto_ptr<Derived>).  */
+              LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING|LOOKUP_NO_CONVERSION);
+
+           /* Tell the user where this failing constructor call came from.  */
+           if (fn)
+             {
+               if (warningcount > savew)
+                 warning
+                   ("  initializing argument %P of `%D' from result of `%D'",
+                    argnum, fn, convfn);
+               else if (errorcount > savee)
+                 error
+                   ("  initializing argument %P of `%D' from result of `%D'",
+                    argnum, fn, convfn);
+             }
+           else
+             {
+               if (warningcount > savew)
+                 warning ("  initializing temporary from result of `%D'",
+                             convfn);
+               else if (errorcount > savee)
+                 error ("  initializing temporary from result of `%D'",
+                           convfn);
+             }
+           expr = build_cplus_new (totype, expr);
+         }
        return expr;
       }
     case IDENTITY_CONV:
       if (type_unknown_p (expr))
-       expr = instantiate_type (TREE_TYPE (convs), expr, itf_complain);
+       expr = instantiate_type (totype, expr, tf_error | tf_warning);
       return expr;
     case AMBIG_CONV:
       /* Call build_user_type_conversion again for the error.  */
       return build_user_type_conversion
-       (TREE_TYPE (convs), TREE_OPERAND (convs, 0), LOOKUP_NORMAL);
+       (totype, TREE_OPERAND (convs, 0), LOOKUP_NORMAL);
 
     default:
       break;
     };
 
-  expr = convert_like_real (TREE_OPERAND (convs, 0), expr, fn, argnum, 1);
+  expr = convert_like_real (TREE_OPERAND (convs, 0), expr, fn, argnum,
+                            TREE_CODE (convs) == REF_BIND ? -1 : 1);
   if (expr == error_mark_node)
     return error_mark_node;
 
@@ -3729,7 +3924,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
   switch (TREE_CODE (convs))
     {
     case RVALUE_CONV:
-      if (! IS_AGGR_TYPE (TREE_TYPE (convs)))
+      if (! IS_AGGR_TYPE (totype))
        return expr;
       /* else fall through */
     case BASE_CONV:
@@ -3737,7 +3932,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
        {
          /* We are going to bind a reference directly to a base-class
             subobject of EXPR.  */
-         tree base_ptr = build_pointer_type (TREE_TYPE (convs));
+         tree base_ptr = build_pointer_type (totype);
 
          /* Build an expression for `*((base*) &expr)'.  */
          expr = build_unary_op (ADDR_EXPR, expr, 0);
@@ -3746,38 +3941,29 @@ convert_like_real (convs, expr, fn, argnum, inner)
          return expr;
        }
 
-      {
-       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 (!COMPLETE_TYPE_P (TREE_TYPE (expr)))
-             {
-               if (same_type_p (TREE_TYPE (expr), TREE_TYPE (convs)))
-                 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;
-      }
+      /* Copy-initialization where the cv-unqualified version of the source
+        type is the same class as, or a derived class of, the class of the
+        destination [is treated as direct-initialization].  [dcl.init] */
+      savew = warningcount, savee = errorcount;
+      expr = build_new_method_call (NULL_TREE, complete_ctor_identifier,
+                                   build_tree_list (NULL_TREE, expr),
+                                   TYPE_BINFO (totype),
+                                   LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING);
+      if (fn)
+       {
+         if (warningcount > savew)
+           warning ("  initializing argument %P of `%D'", argnum, fn);
+         else if (errorcount > savee)
+           error ("  initializing argument %P of `%D'", argnum, fn);
+       }
+      return build_cplus_new (totype, expr);
 
     case REF_BIND:
       {
-       tree ref_type = TREE_TYPE (convs);
+       tree ref_type = totype;
 
        /* If necessary, create a temporary.  */
-       if (NEED_TEMPORARY_P (convs))
+       if (NEED_TEMPORARY_P (convs) || !lvalue_p (expr))
          {
            tree type = TREE_TYPE (TREE_OPERAND (convs, 0));
            expr = build_target_expr_with_type (expr, type);
@@ -3805,13 +3991,13 @@ convert_like_real (convs, expr, fn, argnum, inner)
 
     case QUAL_CONV:
       /* Warn about deprecated conversion if appropriate.  */
-      string_conv_p (TREE_TYPE (convs), expr, 1);
+      string_conv_p (totype, expr, 1);
       break;
       
     default:
       break;
     }
-  return ocp_convert (TREE_TYPE (convs), expr, CONV_IMPLICIT,
+  return ocp_convert (totype, expr, CONV_IMPLICIT,
                      LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
 }
 
@@ -3837,7 +4023,7 @@ convert_arg_to_ellipsis (arg)
   if (arg != error_mark_node && ! pod_type_p (TREE_TYPE (arg)))
     {
       /* Undefined behaviour [expr.call] 5.2.2/7.  */
-      cp_warning ("cannot pass objects of non-POD type `%#T' through `...'",
+      warning ("cannot pass objects of non-POD type `%#T' through `...'",
                  TREE_TYPE (arg));
     }
 
@@ -3862,31 +4048,34 @@ build_x_va_arg (expr, type)
   if (! pod_type_p (type))
     {
       /* Undefined behaviour [expr.call] 5.2.2/7.  */
-      cp_warning ("cannot receive objects of non-POD type `%#T' through `...'",
+      warning ("cannot receive objects of non-POD type `%#T' through `...'",
                  type);
     }
   
   return build_va_arg (expr, type);
 }
 
-/* TYPE has been given to va_arg. Apply the default conversions which would
-   have happened when passed via ellipsis. Return the promoted type, or
-   NULL_TREE, if there is no change.  */
+/* TYPE has been given to va_arg.  Apply the default conversions which
+   would have happened when passed via ellipsis.  Return the promoted
+   type, or the passed type if there is no change.  */
 
 tree
-convert_type_from_ellipsis (type)
+cxx_type_promotes_to (type)
      tree type;
 {
   tree promote;
-  
+
   if (TREE_CODE (type) == ARRAY_TYPE)
-    promote = build_pointer_type (TREE_TYPE (type));
-  else if (TREE_CODE (type) == FUNCTION_TYPE)
-    promote = build_pointer_type (type);
-  else
-    promote = type_promotes_to (type);
+    return build_pointer_type (TREE_TYPE (type));
+
+  if (TREE_CODE (type) == FUNCTION_TYPE)
+    return build_pointer_type (type);
+
+  promote = type_promotes_to (type);
+  if (same_type_p (type, promote))
+    promote = type;
   
-  return same_type_p (type, promote) ? NULL_TREE : promote;
+  return promote;
 }
 
 /* ARG is a default argument expression being passed to a parameter of
@@ -3900,6 +4089,26 @@ convert_default_arg (type, arg, fn, parmnum)
      tree fn;
      int parmnum;
 {
+  if (TREE_CODE (arg) == DEFAULT_ARG)
+    {
+      /* When processing the default args for a class, we can find that
+         there is an ordering constraint, and we call a function who's
+         default args have not yet been converted. For instance,
+          class A {
+              A (int = 0);
+              void Foo (A const & = A ());
+          };
+         We must process A::A before A::Foo's default arg can be converted.
+         Remember the dependent function, so do_pending_defargs can retry,
+         and check loops.  */
+      unprocessed_defarg_fn (fn);
+      
+      /* Don't return error_mark node, as we won't be able to distinguish
+         genuine errors from this case, and that would lead to repeated
+         diagnostics.  Just make something of the right type.  */
+      return build1 (NOP_EXPR, type, integer_zero_node);
+    }
+
   if (fn && DECL_TEMPLATE_INFO (fn))
     arg = tsubst_default_argument (fn, type, arg);
 
@@ -3919,16 +4128,65 @@ convert_default_arg (type, arg, fn, parmnum)
 
       arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
                                        "default argument", fn, parmnum);
-      if (PROMOTE_PROTOTYPES
-         && (TREE_CODE (type) == INTEGER_TYPE
-             || TREE_CODE (type) == ENUMERAL_TYPE)
-         && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
-       arg = default_conversion (arg);
+      arg = convert_for_arg_passing (type, arg);
     }
 
   return arg;
 }
 
+/* Returns the type which will really be used for passing an argument of
+   type TYPE.  */
+
+tree
+type_passed_as (type)
+     tree type;
+{
+  /* Pass classes with copy ctors by invisible reference.  */
+  if (TREE_ADDRESSABLE (type))
+    type = build_reference_type (type);
+  else if (PROMOTE_PROTOTYPES
+          && INTEGRAL_TYPE_P (type)
+          && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+    type = integer_type_node;
+
+  return type;
+}
+
+/* Actually perform the appropriate conversion.  */
+
+tree
+convert_for_arg_passing (type, val)
+     tree type, val;
+{
+  /* Pass classes with copy ctors by invisible reference.  */
+  if (TREE_ADDRESSABLE (type))
+    val = build1 (ADDR_EXPR, build_reference_type (type), val);
+  else if (PROMOTE_PROTOTYPES
+          && INTEGRAL_TYPE_P (type)
+          && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+    val = default_conversion (val);
+  return val;
+}
+
+/* Convert VALUE for assignment into inlined parameter PARM.  */
+
+tree
+cp_convert_parm_for_inlining (parm, value, fn)
+     tree parm, value;
+     tree fn ATTRIBUTE_UNUSED;
+{
+  /* When inlining, we don't need to mess with invisible references, so
+     undo the ADDR_EXPR.  */
+  if (TREE_ADDRESSABLE (TREE_TYPE (parm)))
+    value = build_indirect_ref (value, NULL);
+  return value;
+}
+
+/* Subroutine of the various build_*_call functions.  Overload resolution
+   has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
+   ARGS is a TREE_LIST of the unconverted arguments to the call.  FLAGS is a
+   bitmask of various LOOKUP_* flags which apply to the call itself.  */
+
 static tree
 build_over_call (cand, args, flags)
      struct z_candidate *cand;
@@ -3946,7 +4204,7 @@ build_over_call (cand, args, flags)
   /* 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);
+      joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);
 
   if (DECL_FUNCTION_MEMBER_P (fn))
     enforce_access (cand->basetype_path, fn);
@@ -3963,6 +4221,9 @@ build_over_call (cand, args, flags)
       arg = TREE_CHAIN (arg);
       parm = TREE_CHAIN (parm);
       if (DECL_HAS_IN_CHARGE_PARM_P (fn))
+       /* We should never try to call the abstract constructor.  */
+       abort ();
+      if (DECL_HAS_VTT_PARM_P (fn))
        {
          converted_args = tree_cons
            (NULL_TREE, TREE_VALUE (arg), converted_args);
@@ -3977,7 +4238,7 @@ build_over_call (cand, args, flags)
       tree argtype = TREE_TYPE (TREE_VALUE (arg));
       tree t;
       if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i)))
-       cp_pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers",
+       pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers",
                    TREE_TYPE (argtype), fn);
 
       /* [class.mfct.nonstatic]: If a nonstatic member function of a class
@@ -3987,7 +4248,9 @@ build_over_call (cand, args, flags)
          So we can assume that anything passed as 'this' is non-null, and
         optimize accordingly.  */
       my_friendly_assert (TREE_CODE (parmtype) == POINTER_TYPE, 19990811);
-      t = convert_pointer_to_real (TREE_TYPE (parmtype), TREE_VALUE (arg));
+      t = lookup_base (TREE_TYPE (TREE_TYPE (TREE_VALUE (arg))),
+                      TREE_TYPE (parmtype), ba_ignore, NULL);
+      t = build_base_path (PLUS_EXPR, TREE_VALUE (arg), t, 1);
       converted_args = tree_cons (NULL_TREE, t, converted_args);
       parm = TREE_CHAIN (parm);
       arg = TREE_CHAIN (arg);
@@ -4001,38 +4264,10 @@ build_over_call (cand, args, flags)
       tree type = TREE_VALUE (parm);
 
       conv = TREE_VEC_ELT (convs, i);
-      if (ICS_BAD_FLAG (conv))
-       {
-         tree t = conv;
-         val = TREE_VALUE (arg);
+      val = convert_like_with_context
+       (conv, TREE_VALUE (arg), fn, i - is_method);
 
-         for (; t; t = TREE_OPERAND (t, 0))
-           {
-             if (TREE_CODE (t) == USER_CONV
-                 || TREE_CODE (t) == AMBIG_CONV)
-               {
-                 val = convert_like_with_context (t, val, fn, i - is_method);
-                 break;
-               }
-             else if (TREE_CODE (t) == IDENTITY_CONV)
-               break;
-           }
-         val = convert_for_initialization
-           (NULL_TREE, type, val, LOOKUP_NORMAL,
-            "argument", fn, i - is_method);
-       }
-      else
-       {
-         val = TREE_VALUE (arg);
-         val = convert_like_with_context
-                 (conv, TREE_VALUE (arg), fn, i - is_method);
-       }
-
-      if (PROMOTE_PROTOTYPES
-         && (TREE_CODE (type) == INTEGER_TYPE
-             || TREE_CODE (type) == ENUMERAL_TYPE)
-         && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
-       val = default_conversion (val);
+      val = convert_for_arg_passing (type, val);
       converted_args = tree_cons (NULL_TREE, val, converted_args);
     }
 
@@ -4054,9 +4289,9 @@ build_over_call (cand, args, flags)
 
   converted_args = nreverse (converted_args);
 
-  if (warn_format && (DECL_NAME (fn) || DECL_ASSEMBLER_NAME (fn)))
-    check_function_format (NULL, DECL_NAME (fn), DECL_ASSEMBLER_NAME (fn),
-                          converted_args); 
+  if (warn_format)
+    check_function_format (NULL, TYPE_ATTRIBUTES (TREE_TYPE (fn)),
+                          converted_args);
 
   /* Avoid actually calling copy constructors and copy assignment operators,
      if possible.  */
@@ -4067,9 +4302,7 @@ build_over_call (cand, args, flags)
           && DECL_COPY_CONSTRUCTOR_P (fn))
     {
       tree targ;
-      arg = TREE_CHAIN (converted_args);
-      if (DECL_HAS_IN_CHARGE_PARM_P (fn))
-       arg = TREE_CHAIN (arg);
+      arg = skip_artificial_parms_for (fn, converted_args);
       arg = TREE_VALUE (arg);
 
       /* Pull out the real argument, disregarding const-correctness.  */
@@ -4110,31 +4343,21 @@ build_over_call (cand, args, flags)
          else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
            return build_target_expr_with_type (arg, DECL_CONTEXT (fn));
        }
-      else if (! real_lvalue_p (arg)
-              || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
+      else if ((!real_lvalue_p (arg)
+               || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
+              /* Empty classes have padding which can be hidden
+                 inside an (empty) base of the class. This must not
+                 be touched as it might overlay things. When the
+                 gcc core learns about empty classes, we can treat it
+                 like other classes. */
+              && !(is_empty_class (DECL_CONTEXT (fn))
+                   && TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))))
        {
          tree address;
          tree to = stabilize_reference
            (build_indirect_ref (TREE_VALUE (args), 0));
 
-         /* If we're initializing an empty class, then we actually
-            have to use a MODIFY_EXPR rather than an INIT_EXPR.  The
-            reason is that the dummy padding member in the target may
-            not actually be allocated if TO is a base class
-            subobject.  Since we've set TYPE_NONCOPIED_PARTS on the
-            padding, a MODIFY_EXPR will preserve its value, which is
-            the right thing to do if it's not really padding at all.
-         
-            It's not safe to just throw away the ARG if we're looking
-            at an empty class because the ARG might contain a
-            TARGET_EXPR which wants to be bound to TO.  If it is not,
-            expand_expr will assign a dummy slot for the TARGET_EXPR,
-            and we will call a destructor for it, which is wrong,
-            because we will also destroy TO, but will never have
-            constructed it.  */
-         val = build (is_empty_class (DECL_CONTEXT (fn))
-                      ? MODIFY_EXPR : INIT_EXPR, 
-                      DECL_CONTEXT (fn), to, arg);
+         val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
          address = build_unary_op (ADDR_EXPR, val, 0);
          /* Avoid a warning about this expression, if the address is
             never used.  */
@@ -4143,15 +4366,31 @@ build_over_call (cand, args, flags)
        }
     }
   else if (DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR
-          && copy_args_p (fn)
+          && copy_fn_p (fn)
           && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_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);
-
-      val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
+      if (is_empty_class (TREE_TYPE (to)))
+       {
+         TREE_USED (arg) = 1;
+
+         val = build (COMPOUND_EXPR, DECL_CONTEXT (fn), arg, to);
+         /* Even though the assignment may not actually result in any
+            code being generated, we do not want to warn about the
+            assignment having no effect.  That would be confusing to
+            users who may be performing the assignment as part of a
+            generic algorithm, for example.
+            
+            Ideally, the notions of having side-effects and of being
+            useless would be orthogonal.  */
+         TREE_SIDE_EFFECTS (val) = 1;
+         TREE_NO_UNUSED_WARNING (val) = 1;
+       }
+      else
+       val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
       return val;
     }
 
@@ -4160,13 +4399,19 @@ build_over_call (cand, args, flags)
   if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
     {
       tree t, *p = &TREE_VALUE (converted_args);
-      tree binfo = get_binfo
-       (DECL_VIRTUAL_CONTEXT (fn), TREE_TYPE (TREE_TYPE (*p)), 0);
-      *p = convert_pointer_to_real (binfo, *p);
+      tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)),
+                               DECL_VIRTUAL_CONTEXT (fn),
+                               ba_any, NULL);
+      my_friendly_assert (binfo && binfo != error_mark_node, 20010730);
+      
+      *p = build_base_path (PLUS_EXPR, *p, binfo, 1);
       if (TREE_SIDE_EFFECTS (*p))
        *p = save_expr (*p);
       t = build_pointer_type (TREE_TYPE (fn));
-      fn = build_vfn_ref (p, build_indirect_ref (*p, 0), DECL_VINDEX (fn));
+      if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn)))
+       fn = build_java_interface_fn_ref (fn, *p);
+      else
+       fn = build_vfn_ref (build_indirect_ref (*p, 0), DECL_VINDEX (fn));
       TREE_TYPE (fn) = t;
     }
   else if (DECL_INLINE (fn))
@@ -4188,15 +4433,84 @@ build_over_call (cand, args, flags)
        return exp;
     }
 
+  /* Some built-in function calls will be evaluated at
+     compile-time in fold ().  */
   fn = fold (build_call (fn, converted_args));
-  if (TREE_CODE (TREE_TYPE (fn)) == VOID_TYPE)
+  if (VOID_TYPE_P (TREE_TYPE (fn)))
     return fn;
   fn = require_complete_type (fn);
+  if (fn == error_mark_node)
+    return error_mark_node;
   if (IS_AGGR_TYPE (TREE_TYPE (fn)))
     fn = build_cplus_new (TREE_TYPE (fn), fn);
   return convert_from_reference (fn);
 }
 
+static GTY(()) tree java_iface_lookup_fn;
+
+/* Make an expression which yields the address of the Java interface
+   method FN.  This is achieved by generating a call to libjava's
+   _Jv_LookupInterfaceMethodIdx().  */
+
+static tree
+build_java_interface_fn_ref (fn, instance)
+    tree fn, instance;
+{
+  tree lookup_args, lookup_fn, method, idx;
+  tree klass_ref, iface, iface_ref;
+  int i;
+  
+  if (!java_iface_lookup_fn)
+    {
+      tree endlink = build_void_list_node ();
+      tree t = tree_cons (NULL_TREE, ptr_type_node,
+                         tree_cons (NULL_TREE, ptr_type_node,
+                                    tree_cons (NULL_TREE, java_int_type_node,
+                                               endlink)));
+      java_iface_lookup_fn 
+       = builtin_function ("_Jv_LookupInterfaceMethodIdx",
+                           build_function_type (ptr_type_node, t),
+                           0, NOT_BUILT_IN, NULL, NULL_TREE);
+    }
+
+  /* Look up the pointer to the runtime java.lang.Class object for `instance'. 
+     This is the first entry in the vtable. */
+  klass_ref = build_vtbl_ref (build_indirect_ref (instance, 0), 
+                             integer_zero_node);
+
+  /* Get the java.lang.Class pointer for the interface being called. */
+  iface = DECL_CONTEXT (fn);
+  iface_ref = lookup_field (iface, get_identifier ("class$"), 0, 0);
+  if (!iface_ref || TREE_CODE (iface_ref) != VAR_DECL
+      || DECL_CONTEXT (iface_ref) != iface)
+    {
+      error ("could not find class$ field in java interface type `%T'", 
+               iface);
+      return error_mark_node;
+    }
+  iface_ref = build1 (ADDR_EXPR, build_pointer_type (iface), iface_ref);
+  
+  /* Determine the itable index of FN. */
+  i = 1;
+  for (method = TYPE_METHODS (iface); method; method = TREE_CHAIN (method))
+    {
+      if (!DECL_VIRTUAL_P (method))
+        continue;
+      if (fn == method)
+        break;
+      i++;
+    }
+  idx = build_int_2 (i, 0);
+
+  lookup_args = tree_cons (NULL_TREE, klass_ref, 
+                          tree_cons (NULL_TREE, iface_ref,
+                                     build_tree_list (NULL_TREE, idx)));
+  lookup_fn = build1 (ADDR_EXPR, 
+                     build_pointer_type (TREE_TYPE (java_iface_lookup_fn)),
+                     java_iface_lookup_fn);
+  return build (CALL_EXPR, ptr_type_node, lookup_fn, lookup_args, NULL_TREE);
+}
+
 /* Returns the value to use for the in-charge parameter when making a
    call to a function with the indicated NAME.  */
 
@@ -4216,7 +4530,7 @@ in_charge_arg_for_name (name)
 
   /* This function should only be called with one of the names listed
      above.  */
-  my_friendly_abort (20000411);
+  abort ();
   return NULL_TREE;
 }
 
@@ -4231,6 +4545,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
   tree pretty_name;
   tree user_args;
   tree templates = NULL_TREE;
+  tree call;
   int template_only = 0;
 
   if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
@@ -4270,7 +4585,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
       if (! IS_AGGR_TYPE (basetype))
        {
          if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node)
-           cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
+           error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
                      name, instance, basetype);
 
          return error_mark_node;
@@ -4313,42 +4628,32 @@ build_new_method_call (instance, name, args, basetype_path, flags)
       pretty_name = (constructor_p 
                     ? constructor_name (basetype) : dtor_identifier);
 
-      if (!flag_new_abi)
-       {
-         /* Add the in-charge parameter as an implicit first argument.  */
-         if (!constructor_p
-             || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
-           args = tree_cons (NULL_TREE,
-                             in_charge_arg_for_name (name),
-                             args);
-
-         /* We want to call the normal constructor function under the
-            old ABI.  */
-         name = constructor_p ? ctor_identifier : dtor_identifier;
-       }
-      /* If we're call a subobject constructor or destructor for a
+      /* If we're a call to a constructor or destructor for a
         subobject that uses virtual base classes, then we need to
         pass down a pointer to a VTT for the subobject.  */
-      else if ((name == base_ctor_identifier
-               || name == base_dtor_identifier)
-              && TYPE_USES_VIRTUAL_BASECLASSES (basetype))
+      if ((name == base_ctor_identifier
+          || name == base_dtor_identifier)
+         && TYPE_USES_VIRTUAL_BASECLASSES (basetype))
        {
          tree vtt;
          tree sub_vtt;
+         tree basebinfo = basetype_path;
 
          /* If the current function is a complete object constructor
             or destructor, then we fetch the VTT directly.
             Otherwise, we look it up using the VTT we were given.  */
          vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type));
-         vtt = build_unary_op (ADDR_EXPR, vtt, /*noconvert=*/1);
-         vtt = build (COND_EXPR, TREE_TYPE (vtt), 
-                      DECL_USE_VTT_PARM (current_function_decl),
-                      DECL_VTT_PARM (current_function_decl),
+         vtt = decay_conversion (vtt);
+         vtt = build (COND_EXPR, TREE_TYPE (vtt),
+                      build (EQ_EXPR, boolean_type_node,
+                             current_in_charge_parm, integer_zero_node),
+                      current_vtt_parm,
                       vtt);
-
+         if (TREE_VIA_VIRTUAL (basebinfo))
+           basebinfo = binfo_for_vbase (basetype, current_class_type);
+         my_friendly_assert (BINFO_SUBVTT_INDEX (basebinfo), 20010110);
          sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt,
-                          BINFO_SUBVTT_INDEX (basetype_path));
-         sub_vtt = build_indirect_ref (sub_vtt, NULL);
+                          BINFO_SUBVTT_INDEX (basebinfo));
 
          args = tree_cons (NULL_TREE, sub_vtt, args);
        }
@@ -4404,11 +4709,11 @@ build_new_method_call (instance, name, args, basetype_path, flags)
       if (flags & LOOKUP_SPECULATIVELY)
        return NULL_TREE;
       if (!COMPLETE_TYPE_P (basetype))
-       incomplete_type_error (instance_ptr, basetype);
+       cxx_incomplete_type_error (instance_ptr, basetype);
       else
-       cp_error ("no matching function for call to `%T::%D (%A)%V'",
-                 basetype, pretty_name, user_args,
-                 TREE_TYPE (TREE_TYPE (instance_ptr)));
+       error ("no matching function for call to `%T::%D(%A)%#V'",
+              basetype, pretty_name, user_args,
+              TREE_TYPE (TREE_TYPE (instance_ptr)));
       print_z_candidates (candidates);
       return error_mark_node;
     }
@@ -4417,7 +4722,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
 
   if (cand == 0)
     {
-      cp_error ("call of overloaded `%D(%A)' is ambiguous", pretty_name,
+      error ("call of overloaded `%D(%A)' is ambiguous", pretty_name,
                user_args);
       print_z_candidates (candidates);
       return error_mark_node;
@@ -4429,26 +4734,33 @@ build_new_method_call (instance, name, args, basetype_path, flags)
          || DECL_DESTRUCTOR_P (current_function_decl))
       && ! (flags & LOOKUP_NONVIRTUAL)
       && value_member (cand->fn, CLASSTYPE_PURE_VIRTUALS (basetype)))
-    cp_error ((DECL_CONSTRUCTOR_P (current_function_decl) ? 
+    error ((DECL_CONSTRUCTOR_P (current_function_decl) ? 
               "abstract virtual `%#D' called from constructor"
               : "abstract virtual `%#D' called from destructor"),
              cand->fn);
   if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
       && is_dummy_object (instance_ptr))
     {
-      cp_error ("cannot call member function `%D' without object", cand->fn);
+      error ("cannot call member function `%D' without object", cand->fn);
       return error_mark_node;
     }
 
   if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
-      && ((instance == current_class_ref && (dtor_label || ctor_label))
-         || resolves_to_fixed_type_p (instance, 0)))
+      && resolves_to_fixed_type_p (instance, 0))
     flags |= LOOKUP_NONVIRTUAL;
 
-  return build_over_call
-    (cand,
-     TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ? mem_args : args,
-     flags);
+  if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE)
+    call = build_over_call (cand, mem_args, flags);
+  else
+    {
+      call = build_over_call (cand, args, flags);
+      /* Do evaluate the object parameter in a call to a static member
+        function.  */
+      if (TREE_SIDE_EFFECTS (instance))
+       call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
+    }
+
+  return call;
 }
 
 /* Returns non-zero iff standard conversion sequence ICS1 is a proper
@@ -4547,23 +4859,25 @@ maybe_handle_implicit_object (ics)
     }
 }
 
-/* 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.  */
+/* If *ICS is a REF_BIND set *ICS to the remainder of the conversion,
+   and return the type to which the reference refers.  Otherwise,
+   leave *ICS unchanged and return NULL_TREE.  */
 
-static int
-maybe_handle_ref_bind (ics, target_type)
+static tree
+maybe_handle_ref_bind (ics)
      tree* ics;
-     tree* target_type;
 {
   if (TREE_CODE (*ics) == REF_BIND)
     {
-      *target_type = TREE_TYPE (TREE_TYPE (*ics));
-      *ics = TREE_OPERAND (*ics, 0);
-      return 1;
+      tree old_ics = *ics;
+      tree type = TREE_TYPE (TREE_TYPE (old_ics));
+      *ics = TREE_OPERAND (old_ics, 0);
+      ICS_USER_FLAG (*ics) = ICS_USER_FLAG (old_ics);
+      ICS_BAD_FLAG (*ics) = ICS_BAD_FLAG (old_ics);
+      return type;
     }
-  
-  return 0;
+
+  return NULL_TREE;
 }
 
 /* Compare two implicit conversion sequences according to the rules set out in
@@ -4585,12 +4899,11 @@ compare_ics (ics1, ics2)
   tree deref_from_type2 = NULL_TREE;
   tree deref_to_type1 = NULL_TREE;
   tree deref_to_type2 = NULL_TREE;
+  int rank1, rank2;
 
   /* 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;
 
@@ -4599,8 +4912,8 @@ compare_ics (ics1, ics2)
   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);
+  target_type1 = maybe_handle_ref_bind (&ics1);
+  target_type2 = maybe_handle_ref_bind (&ics2);
 
   /* [over.ics.rank]
 
@@ -4614,13 +4927,17 @@ compare_ics (ics1, ics2)
      --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))
+  rank1 = ICS_RANK (ics1);
+  rank2 = ICS_RANK (ics2);
+  
+  if (rank1 > rank2)
     return -1;
-  else if (ICS_RANK (ics1) < ICS_RANK (ics2))
+  else if (rank1 < rank2)
     return 1;
 
-  if (ICS_RANK (ics1) == BAD_RANK)
+  if (rank1 == BAD_RANK)
     {
+      /* XXX Isn't this an extension? */
       /* 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)
@@ -4835,9 +5152,11 @@ compare_ics (ics1, ics2)
            }
        }
     }
-  else if (IS_AGGR_TYPE_CODE (TREE_CODE (from_type1))
+  else if (CLASS_TYPE_P (non_reference (from_type1))
           && same_type_p (from_type1, from_type2))
     {
+      tree from = non_reference (from_type1);
+
       /* [over.ics.rank]
         
         --binding of an expression of type C to a reference of type
@@ -4845,8 +5164,8 @@ compare_ics (ics1, ics2)
           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 (is_properly_derived_from (from, to_type1)
+         && is_properly_derived_from (from, to_type2))
        {
          if (is_properly_derived_from (to_type1, to_type2))
            return 1;
@@ -4854,9 +5173,11 @@ compare_ics (ics1, ics2)
            return -1;
        }
     }
-  else if (IS_AGGR_TYPE_CODE (TREE_CODE (to_type1))
+  else if (CLASS_TYPE_P (non_reference (to_type1))
           && same_type_p (to_type1, to_type2))
     {
+      tree to = non_reference (to_type1);
+
       /* [over.ics.rank]
 
         --binding of an expression of type B to a reference of type
@@ -4864,8 +5185,8 @@ compare_ics (ics1, ics2)
           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_type1, to)
+         && is_properly_derived_from (from_type2, to))
        {
          if (is_properly_derived_from (from_type2, from_type1))
            return 1;
@@ -4893,7 +5214,7 @@ compare_ics (ics1, ics2)
      initialized by S2 refers is more cv-qualified than the type to
      which the reference initialized by S1 refers */
       
-  if (ref_binding1 && ref_binding2
+  if (target_type1 && target_type2
       && same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2))
     return comp_cv_qualification (target_type2, target_type1);
 
@@ -4914,7 +5235,7 @@ source_type (t)
          || TREE_CODE (t) == IDENTITY_CONV)
        return TREE_TYPE (t);
     }
-  my_friendly_abort (1823);
+  abort ();
 }
 
 /* Note a warning about preferring WINNER to LOSER.  We do this by storing
@@ -4925,8 +5246,8 @@ static void
 add_warning (winner, loser)
      struct z_candidate *winner, *loser;
 {
-  winner->warnings = tree_cons (NULL_PTR,
-                               build_expr_ptr_wrapper (loser),
+  winner->warnings = tree_cons (NULL_TREE,
+                               build_zc_wrapper (loser),
                                winner->warnings);
 }
 
@@ -4998,7 +5319,7 @@ joust (cand1, cand2, warn)
          --len;
        }
       else
-       my_friendly_abort (42);
+       abort ();
     }
 
   for (i = 0; i < len; ++i)
@@ -5033,9 +5354,9 @@ joust (cand1, cand2, warn)
 
              if (warn)
                {
-                 cp_warning ("passing `%T' chooses `%T' over `%T'",
+                 warning ("passing `%T' chooses `%T' over `%T'",
                              type, type1, type2);
-                 cp_warning ("  in call to `%D'", w->fn);
+                 warning ("  in call to `%D'", w->fn);
                }
              else
                add_warning (w, l);
@@ -5084,10 +5405,10 @@ joust (cand1, cand2, 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'",
+             warning ("choosing `%D' over `%D'", w->fn, l->fn);
+             warning ("  for conversion from `%T' to `%T'",
                          source, TREE_TYPE (w->second_conv));
-             cp_warning ("  because conversion sequence for the argument is better");
+             warning ("  because conversion sequence for the argument is better");
            }
          else
            add_warning (w, l);
@@ -5098,16 +5419,39 @@ joust (cand1, cand2, warn)
     return winner;
 
   /* or, if not that,
-     F1 is a non-template function and F2 is a template function */
-
+     F1 is a non-template function and F2 is a template function
+     specialization.  */
+         
   if (! cand1->template && cand2->template)
     return 1;
   else if (cand1->template && ! cand2->template)
     return -1;
-  else if (cand1->template && cand2->template)
-    winner = more_specialized
-      (TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template),
-       NULL_TREE);
+  
+  /* or, if not that,
+     F1 and F2 are template functions and the function template for F1 is
+     more specialized than the template for F2 according to the partial
+     ordering rules.  */
+  
+  if (cand1->template && cand2->template)
+    {
+      winner = more_specialized
+        (TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template),
+         DEDUCE_ORDER,
+         /* Tell the deduction code how many real function arguments
+           we saw, not counting the implicit 'this' argument.  But,
+           add_function_candidate() suppresses the "this" argument
+           for constructors.
+
+           [temp.func.order]: The presence of unused ellipsis and default
+           arguments has no effect on the partial ordering of function
+           templates.  */
+         TREE_VEC_LENGTH (cand1->convs)
+        - (DECL_NONSTATIC_MEMBER_FUNCTION_P (cand1->fn)
+           - DECL_CONSTRUCTOR_P (cand1->fn)));
+      /* HERE */
+      if (winner)
+        return winner;
+    }
 
   /* or, if not that,
      the  context  is  an  initialization by user-defined conversion (see
@@ -5117,37 +5461,42 @@ joust (cand1, cand2, warn)
      sequence  than the standard conversion sequence from the return type
      of F2 to the destination type.  */
 
-  if (! winner && cand1->second_conv)
-    winner = compare_ics (cand1->second_conv, cand2->second_conv);
+  if (cand1->second_conv)
+    {
+      winner = compare_ics (cand1->second_conv, cand2->second_conv);
+      if (winner)
+        return winner;
+    }
+  
+  /* Check whether we can discard a builtin candidate, either because we
+     have two identical ones or matching builtin and non-builtin candidates.
 
-  /* If the built-in candidates are the same, arbitrarily pick one.  */
-  if (! winner && cand1->fn == cand2->fn
-      && TREE_CODE (cand1->fn) == IDENTIFIER_NODE)
+     (Pedantically in the latter case the builtin which matched the user
+     function should not be added to the overload set, but we spot it here.
+     
+     [over.match.oper]
+     ... the builtin candidates include ...
+     - do not have the same parameter type list as any non-template
+       non-member candidate.  */
+                            
+  if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE
+      || TREE_CODE (cand2->fn) == IDENTIFIER_NODE)
     {
       for (i = 0; i < len; ++i)
        if (!same_type_p (TREE_TYPE (TREE_VEC_ELT (cand1->convs, i)),
                          TREE_TYPE (TREE_VEC_ELT (cand2->convs, i))))
          break;
       if (i == TREE_VEC_LENGTH (cand1->convs))
-       return 1;
-
-      /* Kludge around broken overloading rules whereby
-        Integer a, b; test ? a : b; is ambiguous, since there's a builtin
-        that takes references and another that takes values.  */
-      if (cand1->fn == ansi_opname (COND_EXPR))
        {
-         tree c1 = TREE_VEC_ELT (cand1->convs, 1);
-         tree c2 = TREE_VEC_ELT (cand2->convs, 1);
-         tree t1 = strip_top_quals (non_reference (TREE_TYPE (c1)));
-         tree t2 = strip_top_quals (non_reference (TREE_TYPE (c2)));
-
-         if (same_type_p (t1, t2))
-           {
-             if (TREE_CODE (c1) == REF_BIND && TREE_CODE (c2) != REF_BIND)
-               return 1;
-             if (TREE_CODE (c1) != REF_BIND && TREE_CODE (c2) == REF_BIND)
-               return -1;
-           }
+         if (cand1->fn == cand2->fn)
+           /* Two built-in candidates; arbitrarily pick one.  */
+           return 1;
+         else if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE)
+           /* cand1 is built-in; prefer cand2.  */
+           return -1;
+         else
+           /* cand2 is built-in; prefer cand1.  */
+           return 1;
        }
     }
 
@@ -5161,9 +5510,10 @@ tweak:
 
   /* Extension: If the worst conversion for one candidate is worse than the
      worst conversion for the other, take the first.  */
-  if (! winner && ! pedantic)
+  if (!pedantic)
     {
       int rank1 = IDENTITY_RANK, rank2 = IDENTITY_RANK;
+      struct z_candidate *w = 0, *l = 0;
 
       for (i = 0; i < len; ++i)
        {
@@ -5172,14 +5522,26 @@ tweak:
          if (ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2)) > rank2)
            rank2 = ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2));
        }
-
       if (rank1 < rank2)
-       return 1;
+       winner = 1, w = cand1, l = cand2;
       if (rank1 > rank2)
-       return -1;
+       winner = -1, w = cand2, l = cand1;
+      if (winner)
+        {
+         if (warn)
+           {
+             pedwarn ("choosing `%D' over `%D'", w->fn, l->fn);
+             pedwarn (
+"  because worst conversion for the former is better than worst conversion for the latter");
+           }
+         else
+           add_warning (w, l);
+          return winner;
+        }
     }
 
-  return winner;
+  my_friendly_assert (!winner, 20010121);
+  return 0;
 }
 
 /* Given a list of candidates for overloading, find the best one, if any.
@@ -5257,7 +5619,21 @@ can_convert_arg (to, from, arg)
   return (t && ! ICS_BAD_FLAG (t));
 }
 
-/* Convert EXPR to TYPE.  Return the converted expression.  */
+/* Like can_convert_arg, but allows dubious conversions as well.  */
+
+int
+can_convert_arg_bad (to, from, arg)
+     tree to, from, arg;
+{
+  tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL);
+  return !!t;
+}
+
+/* Convert EXPR to TYPE.  Return the converted expression.
+
+   Note that we allow bad conversions here because by the time we get to
+   this point we are committed to doing the conversion.  If we end up
+   doing a bad conversion, convert_like will complain.  */
 
 tree
 perform_implicit_conversion (type, expr)
@@ -5270,9 +5646,9 @@ perform_implicit_conversion (type, expr)
     return error_mark_node;
   conv = implicit_conversion (type, TREE_TYPE (expr), expr,
                              LOOKUP_NORMAL);
-  if (!conv || ICS_BAD_FLAG (conv))
+  if (!conv)
     {
-      cp_error ("could not convert `%E' to `%T'", expr, type);
+      error ("could not convert `%E' to `%T'", expr, type);
       return error_mark_node;
     }
 
@@ -5293,9 +5669,11 @@ initialize_reference (type, expr)
   conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL);
   if (!conv || ICS_BAD_FLAG (conv))
     {
-      cp_error ("could not convert `%E' to `%T'", expr, type);
+      error ("could not convert `%E' to `%T'", expr, type);
       return error_mark_node;
     }
 
   return convert_like (conv, expr);
 }
+
+#include "gt-cp-call.h"