86th Cygnus<->FSF quick merge
[gcc.git] / gcc / cp / call.c
index 5f0560f39916972e9566b60c4ec1996bcc9cbbb7..c9d3f8802abbd4251177748419c5a1d18b71386e 100644 (file)
@@ -38,15 +38,11 @@ Boston, MA 02111-1307, USA.  */
 extern void sorry ();
 
 extern int inhibit_warnings;
-extern int flag_assume_nonnull_objects;
 extern tree ctor_label, dtor_label;
 
-/* From typeck.c:  */
-extern tree unary_complex_lvalue ();
-
 /* Compute the ease with which a conversion can be performed
    between an expected and the given type.  */
-static struct harshness_code convert_harshness ();
+static struct harshness_code convert_harshness PROTO((register tree, register tree, tree));
 
 #define EVIL_RETURN(ARG)       ((ARG).code = EVIL_CODE, (ARG))
 #define STD_RETURN(ARG)                ((ARG).code = STD_CODE, (ARG))
@@ -232,10 +228,10 @@ convert_harshness (type, parmtype, parm)
          tree ttl = TYPE_METHOD_BASETYPE (type);
          tree ttr = TYPE_METHOD_BASETYPE (parmtype);
 
-         int b_or_d = get_base_distance (ttr, ttl, 0, 0);
+         int b_or_d = get_base_distance (ttr, ttl, 0, (tree*)0);
          if (b_or_d < 0)
            {
-             b_or_d = get_base_distance (ttl, ttr, 0, 0);
+             b_or_d = get_base_distance (ttl, ttr, 0, (tree*)0);
              if (b_or_d < 0)
                return EVIL_RETURN (h);
              h.distance = -b_or_d;
@@ -365,10 +361,10 @@ convert_harshness (type, parmtype, parm)
        h.code = 0;
       else
        {
-         int b_or_d = get_base_distance (ttr, ttl, 0, 0);
+         int b_or_d = get_base_distance (ttr, ttl, 0, (tree*)0);
          if (b_or_d < 0)
            {
-             b_or_d = get_base_distance (ttl, ttr, 0, 0);
+             b_or_d = get_base_distance (ttl, ttr, 0, (tree*)0);
              if (b_or_d < 0)
                return EVIL_RETURN (h);
              h.distance = -b_or_d;
@@ -433,13 +429,6 @@ convert_harshness (type, parmtype, parm)
              == TYPE_MAIN_VARIANT (type_promotes_to (parmtype)))
            {
              h.code = PROMO_CODE;
-#if 0 /* What purpose does this serve?  -jason */
-             /* A char, short, wchar_t, etc., should promote to an int if
-                it can handle it, otherwise to an unsigned.  So we'll make
-                an unsigned.  */
-             if (type != integer_type_node)
-               h.int_penalty = 1;
-#endif
            }
          else
            h.code = STD_CODE;
@@ -475,10 +464,6 @@ convert_harshness (type, parmtype, parm)
     }
 
   /* Convert arrays which have not previously been converted.  */
-#if 0
-  if (codel == ARRAY_TYPE)
-    codel = POINTER_TYPE;
-#endif
   if (coder == ARRAY_TYPE)
     {
       coder = POINTER_TYPE;
@@ -521,12 +506,6 @@ convert_harshness (type, parmtype, parm)
       if (TREE_CODE (ttl) != VOID_TYPE
          && (TREE_CODE (ttr) != VOID_TYPE || !parm || !integer_zerop (parm)))
        {
-         if (TREE_UNSIGNED (ttl) != TREE_UNSIGNED (ttr))
-           {
-             ttl = unsigned_type (ttl);
-             ttr = unsigned_type (ttr);
-             penalty = 10;
-           }
          if (comp_target_types (type, parmtype, 1) <= 0)
            return EVIL_RETURN (h);
        }
@@ -541,22 +520,18 @@ convert_harshness (type, parmtype, parm)
        return EVIL_RETURN (h);
 #endif
 
-      if (penalty == 10 || ttr == ttl)
+      if (ttr == ttl)
        {
          tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype);
 
-         /* If one was unsigned but the other wasn't, then we need to
-            do a standard conversion from T to unsigned T.  */
-         if (penalty == 10)
-           h.code = PROMO_CODE; /* was STD_CODE */
-         else
-           h.code = 0;
-
+         h.code = 0;
          /* Note conversion from `T*' to `const T*',
                               or `T*' to `volatile T*'.  */
-         if (ttl == ttr
-             && ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
-                 || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2))))
+         if ((TYPE_READONLY (tmp1) < TREE_READONLY (tmp2))
+             || (TYPE_VOLATILE (tmp1) < TYPE_VOLATILE (tmp2)))
+           h.code = EVIL_CODE;
+         else if ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
+                  || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2)))
            h.code |= QUAL_CODE;
 
          h.distance = 0;
@@ -566,10 +541,10 @@ convert_harshness (type, parmtype, parm)
 
       if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
        {
-         int b_or_d = get_base_distance (ttl, ttr, 0, 0);
+         int b_or_d = get_base_distance (ttl, ttr, 0, (tree*)0);
          if (b_or_d < 0)
            {
-             b_or_d = get_base_distance (ttr, ttl, 0, 0);
+             b_or_d = get_base_distance (ttr, ttl, 0, (tree*)0);
              if (b_or_d < 0)
                return EVIL_RETURN (h);
              h.distance = -b_or_d;
@@ -595,8 +570,11 @@ convert_harshness (type, parmtype, parm)
       if (ttl != ttr)
        {
          tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype);
-         if ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
-             || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2)))
+         if ((TYPE_READONLY (tmp1) < TREE_READONLY (tmp2))
+             || (TYPE_VOLATILE (tmp1) < TYPE_VOLATILE (tmp2)))
+           h.code = EVIL_CODE;
+         else if ((TYPE_READONLY (tmp1) > TREE_READONLY (tmp2))
+                  || (TYPE_VOLATILE (tmp1) > TYPE_VOLATILE (tmp2)))
            h.code |= QUAL_CODE;
        }
       return h;
@@ -626,10 +604,10 @@ convert_harshness (type, parmtype, parm)
 
   if (codel == RECORD_TYPE && coder == RECORD_TYPE)
     {
-      int b_or_d = get_base_distance (type, parmtype, 0, 0);
+      int b_or_d = get_base_distance (type, parmtype, 0, (tree*)0);
       if (b_or_d < 0)
        {
-         b_or_d = get_base_distance (parmtype, type, 0, 0);
+         b_or_d = get_base_distance (parmtype, type, 0, (tree*)0);
          if (b_or_d < 0)
            return EVIL_RETURN (h);
          h.distance = -b_or_d;
@@ -662,18 +640,19 @@ user_harshness (type, parmtype)
   for (conv = lookup_conversions (parmtype); conv; conv = TREE_CHAIN (conv))
     {
       struct harshness_code tmp;
+      tree cand = TREE_VALUE (conv);
 
-      if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
+      if (winner && winner == cand)
        continue;
 
-      if (tmp = convert_harshness (type, TREE_VALUE (conv), NULL_TREE),
-         (tmp.code < USER_CODE) && (tmp.distance >= 0))
+      tmp = convert_harshness (type, TREE_TYPE (TREE_TYPE (cand)), NULL_TREE);
+      if ((tmp.code < USER_CODE) && (tmp.distance >= 0))
        {
          if (winner)
            return EVIL_CODE;
          else
            {
-             winner = conv;
+             winner = cand;
              code = tmp.code;
            }
        }
@@ -1104,36 +1083,9 @@ ideal_candidate (candidates, n_candidates, len)
      list for the last argument is the intersection of all the best-liked
      functions.  */
 
-#if 0
-  for (i = 0; i < len; i++)
-    {
-      qsort (candidates, n_candidates, sizeof (struct candidate),
-            rank_for_overload);
-      best_code = cp[-1].h.code;
-
-      /* To find out functions that are worse than that represented
-        by BEST_CODE, we can't just do a comparison like h.code>best_code.
-        The total harshness for the "best" fn may be 8|8 for two args, and
-        the harshness for the next-best may be 8|2.  If we just compared,
-        that would be checking 8>10, which would lead to the next-best
-        being disqualified.  What we actually want to do is get rid
-        of functions that are definitely worse than that represented
-        by best_code, i.e. those which have bits set higher than the
-        highest in best_code.  Sooooo, what we do is clear out everything
-        represented by best_code, and see if we still come up with something
-        higher.  If so (e.g., 8|8 vs 8|16), it'll disqualify it properly.  */
-      for (j = n_candidates-2; j >= 0; j--)
-       if ((candidates[j].h.code & ~best_code) > best_code)
-         candidates[j].h.code = EVIL_CODE;
-    }
-
-  if (cp[-1].h.code & EVIL_CODE)
-    return NULL;
-#else
   qsort (candidates, n_candidates, sizeof (struct candidate),
         rank_for_overload);
   best_code = cp[-1].h.code;
-#endif
 
   /* If they're at least as good as each other, do an arg-by-arg check.  */
   if (! strictly_better (cp[-1].h.code, cp[-2].h.code))
@@ -1220,7 +1172,7 @@ build_vfield_ref (datum, type)
     rval = build (COMPONENT_REF, TREE_TYPE (CLASSTYPE_VFIELD (type)),
                  datum, CLASSTYPE_VFIELD (type));
   else
-    rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), 0, 0);
+    rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), NULL_TREE, 0);
   flag_assume_nonnull_objects = old_assume_nonnull_objects;
 
   return rval;
@@ -1234,7 +1186,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
 {
   tree field, instance;
 
-  if (instance_ptr == current_class_decl)
+  if (instance_ptr == current_class_ptr)
     {
       /* Check to see if we really have a reference to an instance variable
         with `operator()()' overloaded.  */
@@ -1250,7 +1202,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_component_ref_1 (C_C_D, field, 0);
+         instance = build_component_ref_1 (current_class_ref, field, 0);
          if (instance == error_mark_node)
            return error_mark_node;
 
@@ -1263,7 +1215,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
              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, current_class_decl, parms));
+               return build_function_call (instance, tree_cons (NULL_TREE, current_class_ptr, parms));
            }
        }
       return NULL_TREE;
@@ -1338,7 +1290,7 @@ find_scoped_type (type, inner_name, inner_types)
       if (TREE_PURPOSE (tags) == inner_name)
        {
          if (inner_types == NULL_TREE)
-           return DECL_NESTED_TYPENAME (TYPE_NAME (TREE_VALUE (tags)));
+           return TYPE_NAME (TREE_VALUE (tags));
          return resolve_scope_to_name (TREE_VALUE (tags), inner_types);
        }
       tags = TREE_CHAIN (tags);
@@ -1350,7 +1302,7 @@ find_scoped_type (type, inner_name, inner_types)
       {
        /* Code by raeburn.  */
        if (inner_types == NULL_TREE)
-         return DECL_NESTED_TYPENAME (tags);
+         return tags;
        return resolve_scope_to_name (TREE_TYPE (tags), inner_types);
       }
 
@@ -1473,7 +1425,7 @@ build_scoped_method_call (exp, basetype, name, parms)
          name = build_min_nt (BIT_NOT_EXPR, type);
        }
       name = build_min_nt (SCOPE_REF, basetype, name);
-      return build_min_nt (METHOD_CALL_EXPR, name, exp, parms, 0);
+      return build_min_nt (METHOD_CALL_EXPR, name, exp, parms, NULL_TREE);
     }
 
   if (TREE_CODE (type) == REFERENCE_TYPE)
@@ -1569,6 +1521,101 @@ print_n_candidates (candidates, n)
     cp_error_at ("                %D", candidates[i].function);
 }
 
+/* We want the address of a function or method.  We avoid creating a
+   pointer-to-member function.  */
+tree
+build_addr_func (function)
+     tree function;
+{
+  tree type = TREE_TYPE (function);
+
+  /* We have to do these by hand to avoid real pointer to member
+     functions.  */
+  if (TREE_CODE (type) == METHOD_TYPE)
+    {
+      tree addr;
+
+      type = build_pointer_type (type);
+
+      if (mark_addressable (function) == 0)
+       return error_mark_node;
+
+      addr = build1 (ADDR_EXPR, type, function);
+
+      /* Address of a static or external variable or function counts
+        as a constant */
+      if (staticp (function))
+       TREE_CONSTANT (addr) = 1;
+
+      function = addr;
+    }
+  else
+    function = default_conversion (function);
+
+  return function;
+}
+
+/* Build a CALL_EXPR, we can handle FUNCTION_TYPEs, METHOD_TYPEs, or
+   POINTER_TYPE to those.  Note, pointer to member function types
+   (TYPE_PTRMEMFUNC_P) must be handled by our callers.  */
+tree
+build_call (function, result_type, parms)
+     tree function, result_type, parms;
+{
+  int is_constructor = 0;
+
+  function = build_addr_func (function);
+
+  if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
+    {
+      sorry ("unable to call pointer to member function here");
+      return error_mark_node;
+    }
+
+  if (TREE_CODE (function) == ADDR_EXPR
+      && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
+      && DECL_CONSTRUCTOR_P (TREE_OPERAND (function, 0)))
+    is_constructor = 1;
+
+  function = build_nt (CALL_EXPR, function, parms, NULL_TREE);
+  TREE_HAS_CONSTRUCTOR (function) = is_constructor;
+  TREE_TYPE (function) = result_type;
+  TREE_SIDE_EFFECTS (function) = 1;
+  
+  return function;
+}
+
+static tree
+default_parm_conversions (parms, last)
+     tree parms, *last;
+{
+  tree parm, parmtypes = NULL_TREE;
+
+  *last = NULL_TREE;
+
+  for (parm = parms; parm; parm = TREE_CHAIN (parm))
+    {
+      tree t = TREE_TYPE (TREE_VALUE (parm));
+
+      if (TREE_CODE (t) == OFFSET_TYPE
+         || TREE_CODE (t) == METHOD_TYPE
+         || TREE_CODE (t) == FUNCTION_TYPE)
+       {
+         TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));
+         t = TREE_TYPE (TREE_VALUE (parm));
+       }
+
+      if (t == error_mark_node)
+         return error_mark_node;
+
+      *last = build_tree_list (NULL_TREE, t);
+      parmtypes = chainon (parmtypes, *last);
+    }
+
+  return parmtypes;
+}
+
+
 /* Build something of the form ptr->method (args)
    or object.method (args).  This can also build
    calls to constructors, and find friends.
@@ -1608,18 +1655,17 @@ build_method_call (instance, name, parms, basetype_path, flags)
   register tree function, fntype, value_type;
   register tree basetype, save_basetype;
   register tree baselink, result, parmtypes, parm;
-#if 0
-  register tree method_name;
-#endif
   tree last;
   int pass;
   tree access = access_public_node;
+  tree orig_basetype = basetype_path ? BINFO_TYPE (basetype_path) : NULL_TREE;
 
   /* Range of cases for vtable optimization.  */
   enum vtable_needs { not_needed, maybe_needed, unneeded, needed };
   enum vtable_needs need_vtbl = not_needed;
 
   char *name_kind;
+  tree save_name = name;
   int ever_seen = 0;
   tree instance_ptr = NULL_TREE;
   int all_virtual = flag_all_virtual;
@@ -1647,7 +1693,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
          name = build_min_nt (BIT_NOT_EXPR, type);
        }
 
-      return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, 0);
+      return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
     }
 
   /* This is the logic that magically deletes the second argument to
@@ -1747,7 +1793,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
       else if (basetype_path)
        {
          basetype = BINFO_TYPE (basetype_path);
-         if (name == DECL_NAME (TYPE_NAME (basetype)))
+         if (name == TYPE_IDENTIFIER (basetype))
            name = ctor_identifier;
        }
       else if (IDENTIFIER_HAS_TYPE_VALUE (name))
@@ -1782,11 +1828,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
          return error_mark_node;
        }
     }
-  else if (instance == C_C_D || instance == current_class_decl)
+  else if (instance == current_class_ref || instance == current_class_ptr)
     {
       /* When doing initialization, we side-effect the TREE_TYPE of
-        C_C_D, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE.  */
-      basetype = TREE_TYPE (C_C_D);
+        current_class_ref, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE.  */
+      basetype = TREE_TYPE (current_class_ref);
 
       /* Anything manifestly `this' in constructors and destructors
         has a known type, so virtual function tables are not needed.  */
@@ -1808,8 +1854,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
        }
       else
        {
-         instance = C_C_D;
-         instance_ptr = current_class_decl;
+         instance = current_class_ref;
+         instance_ptr = current_class_ptr;
          basetype_path = TYPE_BINFO (current_class_type);
        }
       result = build_field_call (basetype_path, instance_ptr, name, parms);
@@ -1961,6 +2007,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
        }
     }
 
+  if (save_name == ctor_identifier)
+    save_name = TYPE_IDENTIFIER (basetype);
+
   if (TYPE_SIZE (complete_type (basetype)) == 0)
     {
       /* This is worth complaining about, I think.  */
@@ -1970,44 +2019,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
 
   save_basetype = TYPE_MAIN_VARIANT (basetype);
 
-#if 0
-  if (all_virtual == 1
-      && (! strncmp (IDENTIFIER_POINTER (name), OPERATOR_METHOD_FORMAT,
-                    OPERATOR_METHOD_LENGTH)
-         || instance_ptr == NULL_TREE
-         || (TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype) == 0)))
-    all_virtual = 0;
-#endif
-
-  last = NULL_TREE;
-  for (parmtypes = NULL_TREE, parm = parms; parm; parm = TREE_CHAIN (parm))
+  parmtypes = default_parm_conversions (parms, &last);
+  if (parmtypes == error_mark_node)
     {
-      tree t = TREE_TYPE (TREE_VALUE (parm));
-      if (TREE_CODE (t) == OFFSET_TYPE)
-       {
-         /* Convert OFFSET_TYPE entities to their normal selves.  */
-         TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm));
-         t = TREE_TYPE (TREE_VALUE (parm));
-       }
-      if (TREE_CODE (TREE_VALUE (parm)) == OFFSET_REF
-         && TREE_CODE (t) == METHOD_TYPE)
-       {
-         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.
-            This eliminates needless calls to `compute_conversion_costs'.  */
-         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);
-      parmtypes = chainon (parmtypes, last);
+      return error_mark_node;
     }
 
   if (instance && IS_SIGNATURE (basetype))
@@ -2137,7 +2152,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
              cp->harshness = (struct harshness_code *)
                alloca ((len + 1) * sizeof (struct harshness_code));
 
-             result = build_overload_call (name, friend_parms, 0, cp);
+             result = build_overload_call_real (name, friend_parms, 0, cp, 1);
+
              /* If it turns out to be the one we were actually looking for
                 (it was probably a friend function), the return the
                 good result.  */
@@ -2187,12 +2203,6 @@ 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)
                {
                  tree these_parms = parms;
@@ -2254,10 +2264,10 @@ build_method_call (instance, name, parms, basetype_path, flags)
              TREE_CHAIN (last) = void_list_node;
              if (flags & LOOKUP_GLOBAL)
                cp_error ("no global or member function `%D(%A)' defined",
-                         name, parmtypes);
+                         save_name, parmtypes);
              else
                cp_error ("no member function `%T::%D(%A)' defined",
-                         save_basetype, name, TREE_CHAIN (parmtypes));
+                         save_basetype, save_name, TREE_CHAIN (parmtypes));
              return error_mark_node;
            }
          continue;
@@ -2282,7 +2292,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
                    {
                      TREE_CHAIN (last) = void_list_node;
                      cp_error ("call of overloaded %s `%D(%A)' is ambiguous",
-                               name_kind, name, TREE_CHAIN (parmtypes));
+                               name_kind, save_name, TREE_CHAIN (parmtypes));
                      print_n_candidates (candidates, n_candidates);
                    }
                  return error_mark_node;
@@ -2304,7 +2314,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
            {
              if (flags & LOOKUP_COMPLAIN)
                cp_error ("ambiguous type conversion requested for %s `%D'",
-                         name_kind, name);
+                         name_kind, save_name);
              return error_mark_node;
            }
          else
@@ -2349,7 +2359,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
                  TREE_CHAIN (last) = void_list_node;
                  cp_error ("no matching function for call to `%T::%D (%A)%V'",
                            TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (instance_ptr))),
-                           name, TREE_CHAIN (parmtypes),
+                           save_name, TREE_CHAIN (parmtypes),
                            TREE_TYPE (TREE_TYPE (instance_ptr)));
                  TREE_CHAIN (last) = NULL_TREE;
                  print_candidates (found_fns);
@@ -2362,7 +2372,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
          if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN))
              == LOOKUP_COMPLAIN)
            {
-             cp_error ("%T has no method named %D", save_basetype, name);
+             cp_error ("%T has no method named %D", save_basetype, save_name);
              return error_mark_node;
            }
          return NULL_TREE;
@@ -2419,20 +2429,22 @@ build_method_call (instance, name, parms, basetype_path, flags)
      type (if it exists) is a pointer to.  */
 
   if (DECL_ABSTRACT_VIRTUAL_P (function)
-      && instance == C_C_D
+      && instance == current_class_ref
       && DECL_CONSTRUCTOR_P (current_function_decl)
       && ! (flags & LOOKUP_NONVIRTUAL)
       && value_member (function, get_abstract_virtuals (basetype)))
     cp_error ("abstract virtual `%#D' called from constructor", function);
 
-  if (IS_SIGNATURE (basetype) && static_call_context)
+  if (IS_SIGNATURE (basetype))
     {
-      cp_error ("cannot call signature member function `%T::%D' without signature pointer/reference",
-               basetype, name);
-      return error_mark_node;
+      if (static_call_context)
+       {
+         cp_error ("cannot call signature member function `%T::%D' without signature pointer/reference",
+                   basetype, save_name);
+         return error_mark_node;
        }
-  else if (IS_SIGNATURE (basetype))
-    return build_signature_method_call (basetype, instance, function, parms);
+      return build_signature_method_call (basetype, instance, function, parms);
+    }
 
   function = DECL_MAIN_VARIANT (function);
   mark_used (function);
@@ -2444,7 +2456,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
     synthesize_method (function);
 
   if (pedantic && DECL_THIS_INLINE (function) && ! DECL_ARTIFICIAL (function)
-       && ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function))
+      && ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function)
+      && ! (DECL_TEMPLATE_INFO (function)
+           && TREE_LANG_FLAG_0 (DECL_TEMPLATE_INFO (function))))
     cp_warning ("inline function `%#D' called before definition", function);
 
   fntype = TREE_TYPE (function);
@@ -2472,21 +2486,23 @@ build_method_call (instance, name, parms, basetype_path, flags)
   if (TREE_CODE (fntype) == METHOD_TYPE && static_call_context
       && !DECL_CONSTRUCTOR_P (function))
     {
-      /* Let's be nice to the user for now, and give reasonable
-        default behavior.  */
-      instance_ptr = current_class_decl;
+      /* Let's be nasty to the user now, and give reasonable
+        error messages.  */
+      instance_ptr = current_class_ptr;
       if (instance_ptr)
        {
          if (basetype != current_class_type)
            {
-             tree binfo = get_binfo (basetype, current_class_type, 1);
-             if (binfo == NULL_TREE)
-               {
-                 error_not_base_type (function, current_class_type);
-                 return error_mark_node;
-               }
-             else if (basetype == error_mark_node)
+             if (basetype == error_mark_node)
                return error_mark_node;
+             else 
+                {
+                 if (orig_basetype != NULL_TREE)
+                   error_not_base_type (orig_basetype, current_class_type);
+                 else
+                   error_not_base_type (function, current_class_type);
+                  return error_mark_node;
+                }
            }
        }
       /* Only allow a static member function to call another static member
@@ -2516,8 +2532,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
     {
       int sub_flags = DECL_CONSTRUCTOR_P (function) ? flags : LOOKUP_NORMAL;
       basetype = TREE_TYPE (instance);
-      if (TYPE_METHOD_BASETYPE (TREE_TYPE (function)) != TYPE_MAIN_VARIANT (basetype)
-         && TYPE_USES_COMPLEX_INHERITANCE (basetype))
+      if (TYPE_METHOD_BASETYPE (TREE_TYPE (function))
+         != TYPE_MAIN_VARIANT (basetype))
        {
          basetype = DECL_CLASS_CONTEXT (function);
          instance_ptr = convert_pointer_to (basetype, instance_ptr);
@@ -2575,47 +2591,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
                         convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, LOOKUP_NORMAL));
     }
 
-#if 0
-  /* Constructors do not overload method calls.  */
-  else if (TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype)
-          && name != TYPE_IDENTIFIER (basetype)
-          && (TREE_CODE (function) != FUNCTION_DECL
-              || strncmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)),
-                          OPERATOR_METHOD_FORMAT,
-                          OPERATOR_METHOD_LENGTH))
-          && (may_be_remote (basetype) || instance != C_C_D))
-    {
-      tree fn_as_int;
-
-      parms = TREE_CHAIN (parms);
-
-      if (!all_virtual && TREE_CODE (function) == FUNCTION_DECL)
-       fn_as_int = build_unary_op (ADDR_EXPR, function, 0);
-      else
-       fn_as_int = convert (TREE_TYPE (default_conversion (function)), DECL_VINDEX (function));
-      if (all_virtual == 1)
-       fn_as_int = convert (integer_type_node, fn_as_int);
-
-      result = build_opfncall (METHOD_CALL_EXPR, LOOKUP_NORMAL, instance, fn_as_int, parms);
-
-      if (result == NULL_TREE)
-       {
-         compiler_error ("could not overload `operator->()(...)'");
-         return error_mark_node;
-       }
-      else if (result == error_mark_node)
-       return error_mark_node;
-
-#if 0
-      /* Do this if we want the result of operator->() to inherit
-        the type of the function it is subbing for.  */
-      TREE_TYPE (result) = value_type;
-#endif
-
-      return result;
-    }
-#endif
-
   if (parms == error_mark_node
       || (parms && TREE_CHAIN (parms) == error_mark_node))
     return error_mark_node;
@@ -2631,28 +2606,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
     GNU_xref_call (current_function_decl,
                   IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)));
 
-  {
-    int is_constructor;
-    
-    if (TREE_CODE (function) == FUNCTION_DECL)
-      {
-       is_constructor = DECL_CONSTRUCTOR_P (function);
-       function = default_conversion (function);
-      }
-    else
-      {
-       is_constructor = 0;
-       function = default_conversion (function);
-      }
-
-    result = build_nt (CALL_EXPR, function, parms, NULL_TREE);
-
-    TREE_TYPE (result) = value_type;
-    TREE_SIDE_EFFECTS (result) = 1;
-    TREE_HAS_CONSTRUCTOR (result) = is_constructor;
-    result = convert_from_reference (result);
-    return result;
-  }
+  result = build_call (function, value_type, parms);
+  result = convert_from_reference (result);
+  return result;
 }
 
 /* Similar to `build_method_call', but for overloaded non-member functions.
@@ -2676,15 +2632,15 @@ build_method_call (instance, name, parms, basetype_path, flags)
    function's new name.  */
 
 tree
-build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
+build_overload_call_real (fnname, parms, flags, final_cp, require_complete)
      tree fnname, parms;
      int flags;
      struct candidate *final_cp;
-     int buildxxx;
+     int require_complete;
 {
   /* must check for overloading here */
   tree functions, function, parm;
-  tree parmtypes = NULL_TREE, last = NULL_TREE;
+  tree parmtypes, last;
   register tree outer;
   int length;
   int parmlength = list_length (parms);
@@ -2700,31 +2656,14 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
       final_cp[1].h.code = EVIL_CODE;
     }
 
-  for (parm = parms; parm; parm = TREE_CHAIN (parm))
+  parmtypes = default_parm_conversions (parms, &last);
+  if (parmtypes == error_mark_node)
     {
-      register tree t = TREE_TYPE (TREE_VALUE (parm));
-
-      if (t == error_mark_node)
-       {
-         if (final_cp)
-           final_cp->h.code = EVIL_CODE;
-         return error_mark_node;
-       }
-      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.
-            This eliminates needless calls to `compute_conversion_costs'.  */
-         TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));
-         t = TREE_TYPE (TREE_VALUE (parm));
-       }
-      last = build_tree_list (NULL_TREE, t);
-      parmtypes = chainon (parmtypes, last);
+      if (final_cp)
+       final_cp->h.code = EVIL_CODE;
+      return error_mark_node;
     }
+
   if (last)
     TREE_CHAIN (last) = void_list_node;
   else
@@ -2928,8 +2867,7 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
       if (final_cp)
        return rval;
 
-      return buildxxx ? build_function_call_real (rval, parms, 0, flags)
-        : build_function_call_real (rval, parms, 1, flags);
+      return build_function_call_real (rval, parms, require_complete, flags);
     }
 
   if (flags & LOOKUP_SPECULATIVELY)
@@ -2942,20 +2880,11 @@ build_overload_call_real (fnname, parms, flags, final_cp, buildxxx)
   return error_mark_node;
 }
 
+/* This requires a complete type on the result of the call.  */
 tree
-build_overload_call (fnname, parms, flags, final_cp)
+build_overload_call (fnname, parms, flags)
      tree fnname, parms;
      int flags;
-     struct candidate *final_cp;
-{
-  return build_overload_call_real (fnname, parms, flags, final_cp, 0);
-}
-
-tree
-build_overload_call_maybe (fnname, parms, flags, final_cp)
-     tree fnname, parms;
-     int flags;
-     struct candidate *final_cp;
 {
-  return build_overload_call_real (fnname, parms, flags, final_cp, 1);
+  return build_overload_call_real (fnname, parms, flags, (struct candidate *)0, 1);
 }