OSDN Git Service

50th Cygnus<->FSF merge
[pf3gnuchains/gcc-fork.git] / gcc / cp / call.c
index e957776..85a2788 100644 (file)
@@ -131,6 +131,13 @@ convert_harshness (type, parmtype, parm)
   if (TYPE_PTRMEMFUNC_P (parmtype))
     parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype);
 
+  if (TREE_CODE (parmtype) == REFERENCE_TYPE)
+    {
+      if (parm)
+       parm = convert_from_reference (parm);
+      parmtype = TREE_TYPE (parmtype);
+    }
+
   codel = TREE_CODE (type);
   coder = TREE_CODE (parmtype);
 
@@ -474,196 +481,138 @@ convert_harshness (type, parmtype, parm)
        }
     }
 
-  /* C++: one of the types must be a reference type.  */
-  {
-    tree ttl, ttr;
-    register tree intype = TYPE_MAIN_VARIANT (parmtype);
-    register enum tree_code form = TREE_CODE (intype);
-    int penalty = 0;
-
-    if (codel == REFERENCE_TYPE || coder == REFERENCE_TYPE)
-      {
-       ttl = TYPE_MAIN_VARIANT (type);
+  /* C++: Since the `this' parameter of a signature member function
+     is represented as a signature pointer to handle default implementations
+     correctly, we can have the case that `type' is a signature pointer
+     while `parmtype' is a pointer to a signature table.  We don't really
+     do any conversions in this case, so just return 0.  */
 
-       if (codel == REFERENCE_TYPE)
-         {
-           ttl = TREE_TYPE (ttl);
-
-           /* When passing a non-const argument into a const reference,
-              dig it a little, so a non-const reference is preferred over
-              this one. (mrs) */
-           if (parm && TREE_READONLY (ttl) && ! TREE_READONLY (parm))
-             penalty = 2;
-           else
-             penalty = 0;
+  if (codel == RECORD_TYPE && coder == POINTER_TYPE
+      && IS_SIGNATURE_POINTER (type) && IS_SIGNATURE (TREE_TYPE (parmtype)))
+    return ZERO_RETURN (h);
 
-           ttl = TYPE_MAIN_VARIANT (ttl);
+  if (codel == REFERENCE_TYPE)
+    {
+      tree ttl, ttr;
+      int constp = parm ? TREE_READONLY (parm) : TYPE_READONLY (parmtype);
+      int volatilep = (parm ? TREE_THIS_VOLATILE (parm)
+                      : TYPE_VOLATILE (parmtype));
+      register tree intype = TYPE_MAIN_VARIANT (parmtype);
+      register enum tree_code form = TREE_CODE (intype);
+      int penalty = 0;
+
+      ttl = TREE_TYPE (type);
+
+      /* When passing a non-const argument into a const reference (or vice
+        versa), dig it a little, so a non-const reference is preferred
+        over this one. (mrs) */
+      if (TYPE_READONLY (ttl) != constp
+         || TYPE_VOLATILE (ttl) != volatilep)
+       penalty = 2;
+      else
+       penalty = 0;
 
-           if (form == OFFSET_TYPE)
-             {
-               intype = TREE_TYPE (intype);
-               form = TREE_CODE (intype);
-             }
+      ttl = TYPE_MAIN_VARIANT (ttl);
 
-           if (form == REFERENCE_TYPE)
-             {
-               intype = TYPE_MAIN_VARIANT (TREE_TYPE (intype));
+      if (form == OFFSET_TYPE)
+       {
+         intype = TREE_TYPE (intype);
+         form = TREE_CODE (intype);
+       }
 
-               if (ttl == intype)
-                 return ZERO_RETURN (h);
-               penalty = 2;
-             }
-           else
-             {
-               /* Can reference be built up?  */
-               if (ttl == intype && penalty == 0) {
-                 /* Because the READONLY and VIRTUAL bits are not always in
-                    the type, this extra check is necessary.  The problem
-                    should be fixed someplace else, and this extra code
-                    removed.
-
-                    Also, if type if a reference, the readonly bits could
-                    either be in the outer type (with reference) or on the
-                    inner type (the thing being referenced).  (mrs)  */
-                 if (parm
-                     && ((TREE_READONLY (parm)
-                          && ! (TYPE_READONLY (type)
-                                || (TREE_CODE (type) == REFERENCE_TYPE
-                                    && TYPE_READONLY (TREE_TYPE (type)))))
-                         || (TREE_SIDE_EFFECTS (parm)
-                             && ! (TYPE_VOLATILE (type)
-                                   || (TREE_CODE (type) == REFERENCE_TYPE
-                                       && TYPE_VOLATILE (TREE_TYPE (type)))))))
-                   penalty = 2;
-                 else
-                   return ZERO_RETURN (h);
-               }
-               else
-                 penalty = 2;
-             }
-         }
-       else if (form == REFERENCE_TYPE)
-         {
-           if (parm)
-             {
-               tree tmp = convert_from_reference (parm);
-               intype = TYPE_MAIN_VARIANT (TREE_TYPE (tmp));
-             }
-           else
-             {
-               intype = parmtype;
-               do
-                 intype = TREE_TYPE (intype);
-               while (TREE_CODE (intype) == REFERENCE_TYPE);
-               intype = TYPE_MAIN_VARIANT (intype);
-             }
-
-           if (ttl == intype)
-             return ZERO_RETURN (h);
-           else
-             penalty = 2;
-         }
+      if (ttl == intype && penalty == 0)
+       return ZERO_RETURN (h);
+      else
+       penalty = 2;
 
-       if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype))
-         {
-           ttl = unsigned_type (ttl);
-           intype = unsigned_type (intype);
-           penalty += 2;
-         }
+      ttr = intype;
 
-       ttr = intype;
+      /* If the initializer is not an lvalue, then it does not
+        matter if we make life easier for the programmer
+        by creating a temporary variable with which to
+        hold the result.  */
+      if (parm && (INTEGRAL_CODE_P (coder)
+                  || coder == REAL_TYPE)
+         && ! lvalue_p (parm))
+       {
+         h = convert_harshness (ttl, ttr, NULL_TREE);
+         if (penalty > 2 || h.code != 0)
+           h.code |= STD_CODE;
+         else
+           h.code |= TRIVIAL_CODE;
+         h.distance = 0;
+         return h;
+       }
 
-       /* If the initializer is not an lvalue, then it does not
-          matter if we make life easier for the programmer
-          by creating a temporary variable with which to
-          hold the result.  */
-       if (parm && (INTEGRAL_CODE_P (coder)
-                    || coder == REAL_TYPE)
-           && ! lvalue_p (parm))
-         {
-           h = convert_harshness (ttl, ttr, NULL_TREE);
-           if (penalty > 2 || h.code != 0)
-             h.code |= STD_CODE;
-           else
-             h.code |= TRIVIAL_CODE;
-           h.distance = 0;
-           return h;
-         }
+      if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype))
+       {
+         ttl = unsigned_type (ttl);
+         ttr = intype = unsigned_type (intype);
+         penalty += 2;
+       }
 
-       if (ttl == ttr)
-         {
-           if (penalty > 2)
-             {
-               h.code = STD_CODE;
-               h.distance = 0;
-             }
-           else
-             {
-               h.code = TRIVIAL_CODE;
-               /* We set this here so that build_overload_call_real will be
-                  able to see the penalty we found, rather than just looking
-                  at a TRIVIAL_CODE with no other information.  */
-               h.int_penalty = penalty;
-             }
-           return h;
-         }
+      if (ttl == ttr)
+       {
+         if (penalty > 2)
+           {
+             h.code = STD_CODE;
+             h.distance = 0;
+           }
+         else
+           {
+             h.code = TRIVIAL_CODE;
+             /* We set this here so that build_overload_call_real will be
+                able to see the penalty we found, rather than just looking
+                at a TRIVIAL_CODE with no other information.  */
+             h.int_penalty = penalty;
+           }
+         return h;
+       }
 
-       /* Pointers to voids always convert for pointers.  But
-          make them less natural than more specific matches.  */
-       if (TREE_CODE (ttl) == POINTER_TYPE && TREE_CODE (ttr) == POINTER_TYPE)
-         {
-           if (TREE_TYPE (ttl) == void_type_node
-               || TREE_TYPE (ttr) == void_type_node)
-             {
-               h.code = STD_CODE;
-               h.distance = 0;
-               return h;
-             }
-         }
+      /* Pointers to voids always convert for pointers.  But
+        make them less natural than more specific matches.  */
+      if (TREE_CODE (ttl) == POINTER_TYPE && TREE_CODE (ttr) == POINTER_TYPE)
+       {
+         if (TREE_TYPE (ttl) == void_type_node
+             || TREE_TYPE (ttr) == void_type_node)
+           {
+             h.code = STD_CODE;
+             h.distance = 0;
+             return h;
+           }
+       }
 
-       if (parm && codel != REFERENCE_TYPE)
-         {
-           h = convert_harshness (ttl, ttr, NULL_TREE);
-           if (penalty == 2)
-             h.code |= QUAL_CODE;
-           else if (penalty == 4)
-             h.code |= STD_CODE;
-           h.distance = 0;
-           return h;
-         }
+      /* Here it does matter.  If this conversion is from derived to base,
+        allow it.  Otherwise, types must be compatible in the strong sense.  */
+      if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
+       {
+         int b_or_d = get_base_distance (ttl, ttr, 0, 0);
+         if (b_or_d < 0)
+           {
+             b_or_d = get_base_distance (ttr, ttl, 0, 0);
+             if (b_or_d < 0)
+               return EVIL_RETURN (h);
+             h.distance = -b_or_d;
+           }
+         /* Say that this conversion is relatively painless.
+            If it turns out that there is a user-defined X(X&)
+            constructor, then that will be invoked, but that's
+            preferable to dealing with other user-defined conversions
+            that may produce surprising results.  */
+         else
+           h.distance = b_or_d;
+         h.code = STD_CODE;
+         return h;
+       }
 
-       /* Here it does matter.  If this conversion is from derived to base,
-          allow it.  Otherwise, types must be compatible in the strong sense.  */
-       if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
-         {
-           int b_or_d = get_base_distance (ttl, ttr, 0, 0);
-           if (b_or_d < 0)
-             {
-               b_or_d = get_base_distance (ttr, ttl, 0, 0);
-               if (b_or_d < 0)
-                 return EVIL_RETURN (h);
-               h.distance = -b_or_d;
-             }
-           /* Say that this conversion is relatively painless.
-              If it turns out that there is a user-defined X(X&)
-              constructor, then that will be invoked, but that's
-              preferable to dealing with other user-defined conversions
-              that may produce surprising results.  */
-           else
-             h.distance = b_or_d;
+      if (comp_target_types (ttl, intype, 1))
+       {
+         if (penalty)
            h.code = STD_CODE;
-           return h;
-         }
-
-       if (comp_target_types (ttl, intype, 1))
-         {
-           if (penalty)
-             h.code = STD_CODE;
-           h.distance = 0;
-           return h;
-         }
-      }
-  }
+         h.distance = 0;
+         return h;
+       }
+    }
   if (codel == RECORD_TYPE && coder == RECORD_TYPE)
     {
       int b_or_d = get_base_distance (type, parmtype, 0, 0);
@@ -751,11 +700,17 @@ compute_conversion_costs (function, tta_in, cp, arglen)
 
   int strike_index = 0, win;
   struct harshness_code lose;
+  extern int cp_silent;
 
 #ifdef GATHER_STATISTICS
   n_compute_conversion_costs++;
 #endif
 
+#ifndef DEBUG_MATCHING
+  /* We don't emit any warnings or errors while trying out each candidate.  */
+  cp_silent = 1;
+#endif
+
   cp->function = function;
   cp->arg = tta ? TREE_VALUE (tta) : NULL_TREE;
   cp->u.bad_arg = 0;           /* optimistic!  */
@@ -763,7 +718,7 @@ compute_conversion_costs (function, tta_in, cp, arglen)
   cp->h.code = 0;
   cp->h.distance = 0;
   cp->h.int_penalty = 0;
-  bzero (cp->harshness,
+  bzero ((char *) cp->harshness,
         (cp->h_len + 1) * sizeof (struct harshness_code));
 
   while (ttf && tta)
@@ -813,8 +768,8 @@ compute_conversion_costs (function, tta_in, cp, arglen)
 #endif
 
          h = convert_harshness (TREE_VALUE (ttf),
-                                     TREE_TYPE (TREE_VALUE (tta)),
-                                     TREE_VALUE (tta));
+                                TREE_TYPE (TREE_VALUE (tta)),
+                                TREE_VALUE (tta));
 
 #ifdef DEBUG_MATCHING
          cp_error ("     evaluated %s", print_harshness (&h));
@@ -863,6 +818,7 @@ compute_conversion_costs (function, tta_in, cp, arglen)
        {
          cp->h.code = EVIL_CODE;
          cp->u.bad_arg = -1;
+         cp_silent = 0;
          return;
        }
       else
@@ -884,6 +840,7 @@ compute_conversion_costs (function, tta_in, cp, arglen)
        {
          cp->h.code = EVIL_CODE;
          cp->u.bad_arg = -2;
+         cp_silent = 0;
          return;
        }
       /* Store index of first default.  */
@@ -906,6 +863,7 @@ compute_conversion_costs (function, tta_in, cp, arglen)
       if (dont_convert_types)
        {
          cp->h.code = EVIL_CODE;
+         cp_silent = 0;
          return;
        }
 
@@ -1053,6 +1011,7 @@ compute_conversion_costs (function, tta_in, cp, arglen)
     cp->h.code |= ELLIPSIS_CODE;
   if (user_strikes)
     cp->h.code |= USER_CODE;
+  cp_silent = 0;
 #ifdef DEBUG_MATCHING
   cp_error ("final eval %s", print_harshness (&cp->h));
 #endif
@@ -1479,11 +1438,11 @@ build_scoped_method_call (exp, scopes, name, parms)
       if (type != basetype)
        cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')",
                  exp, basetype, type);
-      name = IDENTIFIER_TYPE_VALUE (TREE_OPERAND (name, 0));
-      if (basetype != name)
-       cp_error ("qualified type `%T' does not match destructor type `%T'",
+      name = TREE_OPERAND (name, 0);
+      if (basetype != get_type_value (name))
+       cp_error ("qualified type `%T' does not match destructor name `~%T'",
                  basetype, name);
-      return void_zero_node;
+      return convert (void_type_node, exp);
     }
 
   if (! is_aggr_typedef (basename, 1))
@@ -1511,15 +1470,16 @@ build_scoped_method_call (exp, scopes, name, parms)
        {
          /* Explicit call to destructor.  */
          name = TREE_OPERAND (name, 0);
-         if (name != constructor_name (TREE_TYPE (decl)))
+         if (! (name == constructor_name (TREE_TYPE (decl))
+                || TREE_TYPE (decl) == get_type_value (name)))
            {
              cp_error
-               ("qualified type `%T' does not match destructor type `%T'",
+               ("qualified type `%T' does not match destructor name `~%T'",
                 TREE_TYPE (decl), name);
              return error_mark_node;
            }
          if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl)))
-           return void_zero_node;
+           return convert (void_type_node, exp);
          
          return build_delete (TREE_TYPE (decl), decl, integer_two_node,
                               LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR,
@@ -1654,16 +1614,20 @@ build_method_call (instance, name, parms, basetype_path, flags)
       name = TREE_OPERAND (name, 0);
       if (parms)
        error ("destructors take no parameters");
-      basetype = get_type_value (name);
-      if (basetype == NULL_TREE)
+      basetype = TREE_TYPE (instance);
+      if (TREE_CODE (basetype) == REFERENCE_TYPE)
+       basetype = TREE_TYPE (basetype);
+      if (! ((IS_AGGR_TYPE (basetype)
+             && name == constructor_name (basetype))
+            || basetype == get_type_value (name)))
        {
-         cp_error ("call to destructor for non-type `%D'", name);
-         return void_zero_node;
+         cp_error ("destructor name `~%D' does not match type `%T' of expression",
+                   name, basetype);
+         return convert (void_type_node, instance);
        }
-      if (basetype != TREE_TYPE(instance))
-       basetype = TREE_TYPE(instance);
+
       if (! TYPE_HAS_DESTRUCTOR (basetype))
-       return void_zero_node;
+       return convert (void_type_node, instance);
       instance = default_conversion (instance);
       instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
       return build_delete (build_pointer_type (basetype),
@@ -1789,6 +1753,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
         && TREE_CODE (TREE_OPERAND (instance, 0)) == NOP_EXPR
         && TREE_OPERAND (TREE_OPERAND (instance, 0), 0) == error_mark_node);
 
+      if (TREE_CODE (instance) == OFFSET_REF)
+       instance = resolve_offset_ref (instance);
+
       /* the base type of an instance variable is pointer to class */
       basetype = TREE_TYPE (instance);
 
@@ -1808,14 +1775,18 @@ build_method_call (instance, name, parms, basetype_path, flags)
          if (! IS_AGGR_TYPE (basetype))
            goto non_aggr_error;
 
-         if (IS_SIGNATURE_POINTER (basetype)
-             || IS_SIGNATURE_REFERENCE (basetype))
+         /* If `instance' is a signature pointer/reference and `name' is
+            not a constructor, we are calling a signature member function.
+            In that case set the `basetype' to the signature type.  */
+         if ((IS_SIGNATURE_POINTER (basetype)
+              || IS_SIGNATURE_REFERENCE (basetype))
+             && TYPE_IDENTIFIER (basetype) != name)
            basetype = SIGNATURE_TYPE (basetype);
 
          if ((IS_SIGNATURE (basetype)
               && (instance_ptr = build_optr_ref (instance)))
              || (lvalue_p (instance)
-              && (instance_ptr = build_unary_op (ADDR_EXPR, instance, 0)))
+                 && (instance_ptr = build_unary_op (ADDR_EXPR, instance, 0)))
              || (instance_ptr = unary_complex_lvalue (ADDR_EXPR, instance)))
            {
              if (instance_ptr == error_mark_node)
@@ -1831,7 +1802,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
                 we can manage.  */
              tree temp = get_temp_name (TREE_TYPE (instance), 0);
              if (IS_AGGR_TYPE (TREE_TYPE (instance)))
-               expand_aggr_init (temp, instance, 0);
+               expand_aggr_init (temp, instance, 0, flags);
              else
                {
                  store_init_value (temp, instance);
@@ -1842,7 +1813,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
            }
          else
            {
-             if (TREE_CODE (instance) != CALL_EXPR)
+             if (TREE_CODE (instance) != CALL_EXPR
+#ifdef PCC_STATIC_STRUCT_RETURN
+                 && TREE_CODE (instance) != RTL_EXPR
+#endif
+                 )
                my_friendly_abort (125);
              if (TYPE_NEEDS_CONSTRUCTING (basetype))
                instance = build_cplus_new (basetype, instance, 0);
@@ -1933,6 +1908,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
        {
          TREE_VALUE (parm) = build_unary_op (ADDR_EXPR, TREE_VALUE (parm), 0);
        }
+#if 0
+      /* This breaks reference-to-array parameters.  */
       if (TREE_CODE (t) == ARRAY_TYPE)
        {
          /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.
@@ -1940,6 +1917,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
          TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));
          t = TREE_TYPE (TREE_VALUE (parm));
        }
+#endif
       if (t == error_mark_node)
        return error_mark_node;
       last = build_tree_list (NULL_TREE, t);
@@ -1968,7 +1946,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
        {
          constp = 0;
          volatilep = 0;
-         parms = tree_cons (NULL_TREE, build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), integer_zero_node), parms);
+         parms = tree_cons (NULL_TREE,
+                            build1 (NOP_EXPR, TYPE_POINTER_TO (basetype),
+                                    integer_zero_node), parms);
        }
       else
        {
@@ -1981,6 +1961,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
          TREE_CALLS_NEW (instance_ptr) = 1;
          instance = build_indirect_ref (instance_ptr, NULL_PTR);
 
+#if 0
+         /* This breaks initialization of a reference from a new
+             expression of a different type.  And it doesn't appear to
+             serve its original purpose any more, either.  jason 10/12/94 */
          /* If it's a default argument initialized from a ctor, what we get
             from instance_ptr will match the arglist for the FUNCTION_DECL
             of the constructor.  */
@@ -1989,6 +1973,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
              && TREE_CALLS_NEW (TREE_VALUE (TREE_OPERAND (TREE_VALUE (parms), 1))))
            parms = build_tree_list (NULL_TREE, instance_ptr);
          else
+#endif
            parms = tree_cons (NULL_TREE, instance_ptr, parms);
        }
     }
@@ -2001,8 +1986,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
   /* Look up function name in the structure type definition.  */
 
   if ((IDENTIFIER_HAS_TYPE_VALUE (name)
+       && ! IDENTIFIER_OPNAME_P (name)
        && IS_AGGR_TYPE (IDENTIFIER_TYPE_VALUE (name))
-       && TREE_CODE(IDENTIFIER_TYPE_VALUE (name)) != UNINSTANTIATED_P_TYPE)
+       && TREE_CODE (IDENTIFIER_TYPE_VALUE (name)) != UNINSTANTIATED_P_TYPE)
       || name == constructor_name (basetype))
     {
       tree tmp = NULL_TREE;
@@ -2047,6 +2033,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
     return error_mark_node;
 
 
+#if 0
   /* Now, go look for this method name.  We do not find destructors here.
 
      Putting `void_list_node' on the end of the parmtypes
@@ -2056,6 +2043,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
                                     1 + (name == constructor_name (save_basetype)
                                          || name == constructor_name_full (save_basetype)));
   TREE_CHAIN (last) = NULL_TREE;
+#endif
 
   for (pass = 0; pass < 2; pass++)
     {
@@ -2075,7 +2063,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
          candidates
            = (struct candidate *) alloca ((ever_seen+1)
                                           * sizeof (struct candidate));
-         bzero (candidates, (ever_seen + 1) * sizeof (struct candidate));
+         bzero ((char *) candidates, (ever_seen + 1) * sizeof (struct candidate));
          cp = candidates;
          len = list_length (parms);
          ever_seen = 0;
@@ -2097,9 +2085,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
                {
                  tree new_type;
                  parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
-                 new_type = build_reference_type (TREE_TYPE (parm));
-                 /* It is possible that this should go down a layer. */
-                 new_type = build_type_variant (new_type, constp, volatilep);
+                 new_type = cp_build_type_variant (TREE_TYPE (parm), constp,
+                                                  volatilep);
+                 new_type = build_reference_type (new_type);
                  parm = convert (new_type, parm);
                  friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
                }
@@ -2156,7 +2144,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
                {
                  tree type = build_pointer_type
                    (build_type_variant (basetype, constp, volatilep));
-                 TREE_VALUE (parms) = convert_force (type, instance_ptr);
+                 TREE_VALUE (parms) = convert_force (type, instance_ptr, 0);
                }
            }
 
@@ -2182,9 +2170,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
                  && ! DECL_STATIC_FUNCTION_P (function))
                continue;
 
+#if 0
              if (pass == 0
                  && DECL_ASSEMBLER_NAME (function) == method_name)
                goto found;
+#endif
 
              if (pass > 0)
                {
@@ -2207,6 +2197,12 @@ build_method_call (instance, name, parms, basetype_path, flags)
                      cp->function = function;
                      cp->basetypes = basetype_path;
 
+                     /* Don't allow non-converting constructors to convert. */
+                     if (flags & LOOKUP_ONLYCONVERTING
+                         && DECL_LANG_SPECIFIC (function)
+                         && DECL_NONCONVERTING_P (function))
+                       continue;
+
                      /* No "two-level" conversions.  */
                      if (flags & LOOKUP_NO_CONVERSION
                          && (cp->h.code & USER_CODE))
@@ -2279,6 +2275,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
          if (cp - candidates > 1)
            {
              int n_candidates = cp - candidates;
+             extern int warn_synth;
              TREE_VALUE (parms) = instance_ptr;
              cp = ideal_candidate (save_basetype, candidates,
                                    n_candidates, parms, len);
@@ -2286,14 +2283,25 @@ build_method_call (instance, name, parms, basetype_path, flags)
                {
                  if (flags & LOOKUP_COMPLAIN)
                    {
-                     cp_error ("call of overloaded %s `%D' is ambiguous",
-                               name_kind, name);
+                     TREE_CHAIN (last) = void_list_node;
+                     cp_error ("call of overloaded %s `%D(%A)' is ambiguous",
+                               name_kind, name, TREE_CHAIN (parmtypes));
                      print_n_candidates (candidates, n_candidates);
                    }
                  return error_mark_node;
                }
              if (cp->h.code & EVIL_CODE)
                return error_mark_node;
+             if (warn_synth
+                 && DECL_NAME (cp->function) == ansi_opname[MODIFY_EXPR]
+                 && DECL_ARTIFICIAL (cp->function)
+                 && n_candidates == 2)
+               {
+                 cp_warning ("using synthesized `%#D' for copy assignment",
+                             cp->function);
+                 cp_warning_at ("  where cfront would use `%#D'",
+                                candidates->function);
+               }
            }
          else if (cp[-1].h.code & EVIL_CODE)
            {
@@ -2432,6 +2440,13 @@ build_method_call (instance, name, parms, basetype_path, flags)
   /* Declare external function if necessary. */
   assemble_external (function);
 
+#if 0
+  if (DECL_ARTIFICIAL (function) && ! flag_no_inline
+      && DECL_SAVED_INSNS (function) == 0
+      && ! TREE_ASM_WRITTEN (function))
+    synthesize_method (function);
+#endif
+
   fntype = TREE_TYPE (function);
   if (TREE_CODE (fntype) == POINTER_TYPE)
     fntype = TREE_TYPE (fntype);
@@ -2494,11 +2509,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
       return error_mark_node;
     }
 
-  /* We do not pass FUNCTION into `convert_arguments', because by
-     now everything should be ok.  If not, then we have a serious error.  */
   if (DECL_STATIC_FUNCTION_P (function))
     parms = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
-                              TREE_CHAIN (parms), NULL_TREE, LOOKUP_NORMAL);
+                              TREE_CHAIN (parms), function, LOOKUP_NORMAL);
   else if (need_vtbl == unneeded)
     {
       int sub_flags = DECL_CONSTRUCTOR_P (function) ? flags : LOOKUP_NORMAL;
@@ -2511,7 +2524,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
          instance = build_indirect_ref (instance_ptr, NULL_PTR);
        }
       parms = tree_cons (NULL_TREE, instance_ptr,
-                        convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), NULL_TREE, sub_flags));
+                        convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, sub_flags));
     }
   else
     {
@@ -2559,7 +2572,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
            instance = build_indirect_ref (instance_ptr, NULL_PTR);
        }
       parms = tree_cons (NULL_TREE, instance_ptr,
-                        convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), NULL_TREE, LOOKUP_NORMAL));
+                        convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, LOOKUP_NORMAL));
     }
 
 #if 0
@@ -2639,8 +2652,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
 
     TREE_TYPE (result) = value_type;
     TREE_SIDE_EFFECTS (result) = 1;
-    TREE_RAISES (result)
-      = TYPE_RAISES_EXCEPTIONS (fntype) || (parms && TREE_RAISES (parms));
     TREE_HAS_CONSTRUCTOR (result) = is_constructor;
     return result;
   }
@@ -2701,7 +2712,11 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
            final_cp->h.code = EVIL_CODE;
          return error_mark_node;
        }
-      if (TREE_CODE (t) == ARRAY_TYPE || TREE_CODE (t) == OFFSET_TYPE)
+      if (TREE_CODE (t) == OFFSET_TYPE)
+#if 0
+      /* This breaks reference-to-array parameters.  */
+         || TREE_CODE (t) == ARRAY_TYPE
+#endif
        {
          /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.
             Also convert OFFSET_TYPE entities to their normal selves.
@@ -2717,7 +2732,16 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
   else
     parmtypes = void_list_node;
 
-  functions = lookup_name_nonclass (fnname);
+  if (is_overloaded_fn (fnname))
+    {
+      functions = fnname;
+      if (TREE_CODE (fnname) == TREE_LIST)
+       fnname = TREE_PURPOSE (functions);
+      else if (TREE_CODE (fnname) == FUNCTION_DECL)
+       fnname = DECL_NAME (functions);
+    }
+  else 
+    functions = lookup_name_nonclass (fnname);
 
   if (functions == NULL_TREE)
     {
@@ -2766,7 +2790,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
     {
       candidates
        = (struct candidate *)alloca ((length+1) * sizeof (struct candidate));
-      bzero (candidates, (length + 1) * sizeof (struct candidate));
+      bzero ((char *) candidates, (length + 1) * sizeof (struct candidate));
     }
 
   cp = candidates;
@@ -2861,18 +2885,6 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
          if ((cp[0].h.code & EVIL_CODE) == 0)
            {
              cp[1].h.code = EVIL_CODE;
-
-             /* int_penalty is set by convert_harshness_ansi for cases
-                where we need to know about any penalties that would
-                otherwise make a TRIVIAL_CODE pass.  */
-             if (final_cp
-                 && template_cost == 0
-                 && cp[0].h.code <= TRIVIAL_CODE
-                 && cp[0].h.int_penalty == 0)
-               {
-                 final_cp[0].h = cp[0].h;
-                 return function;
-               }
              cp++;
            }
        }