]> gcc.gnu.org Git - gcc.git/commitdiff
call.c, [...]: Remove support for -fno-ansi-overloading and overloading METHOD_CALL_EXPR.
authorJason Merrill <jason@yorick.cygnus.com>
Tue, 3 Mar 1998 03:24:44 +0000 (03:24 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 3 Mar 1998 03:24:44 +0000 (22:24 -0500)
* call.c, class.c, cp-tree.h, cvt.c, decl.c, init.c, lex.c,
method.c, pt.c, ptree.c, typeck.c: Remove support for
-fno-ansi-overloading and overloading METHOD_CALL_EXPR.
* class.h: Remove.
* Makefile.in: Adjust.

From-SVN: r18384

15 files changed:
gcc/cp/ChangeLog
gcc/cp/Makefile.in
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/class.h [deleted file]
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/lex.c
gcc/cp/method.c
gcc/cp/pt.c
gcc/cp/ptree.c
gcc/cp/typeck.c

index 73b3b3ac190135811220987595df4d2b97ecac8f..54b45e1b30b4730f75589441c1bab743156dec66 100644 (file)
@@ -1,5 +1,11 @@
 Tue Mar  3 01:38:17 1998  Jason Merrill  <jason@yorick.cygnus.com>
 
+       * call.c, class.c, cp-tree.h, cvt.c, decl.c, init.c, lex.c,
+       method.c, pt.c, ptree.c, typeck.c: Remove support for 
+       -fno-ansi-overloading and overloading METHOD_CALL_EXPR.
+       * class.h: Remove.
+       * Makefile.in: Adjust.
+
        * pt.c (unify): Don't allow reduced cv-quals when strict.
 
        * call.c, class.c, pt.c, cp-tree.h: Remove nsubsts parm from
index 9007bf28dab6e192df3e9a8356fe850eb4bc4c49..a6f0f3cd1f6e8fc4a731b2e5c66a84ce7ad37e3f 100644 (file)
@@ -240,12 +240,12 @@ typeck2.o : typeck2.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
 typeck.o : typeck.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
   $(srcdir)/../expr.h ../insn-codes.h
 class.o : class.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
-call.o : call.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h class.h
+call.o : call.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
 friend.o : friend.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H)
 init.o : init.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h $(RTL_H) \
   $(srcdir)/../expr.h ../insn-codes.h
-method.o : method.c $(CONFIG_H) $(CXX_TREE_H) class.h
-cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H) class.h
+method.o : method.c $(CONFIG_H) $(CXX_TREE_H)
+cvt.o : cvt.c $(CONFIG_H) $(CXX_TREE_H)
 search.o : search.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../stack.h $(srcdir)/../flags.h
 tree.o : tree.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
 ptree.o : ptree.c $(CONFIG_H) $(CXX_TREE_H)
index 276b32e7750886c1f6477f99e1799b8ab4c1162f..8fe87aa8c76b1969afc332001fa44d23098752d4 100644 (file)
@@ -27,7 +27,6 @@ Boston, MA 02111-1307, USA.  */
 #include "tree.h"
 #include <stdio.h>
 #include "cp-tree.h"
-#include "class.h"
 #include "output.h"
 #include "flags.h"
 
@@ -42,22 +41,10 @@ Boston, MA 02111-1307, USA.  */
 extern int inhibit_warnings;
 extern tree ctor_label, dtor_label;
 
-/* Compute the ease with which a conversion can be performed
-   between an expected and the given type.  */
+static tree build_new_method_call PROTO((tree, tree, tree, tree, int));
 
-static struct harshness_code convert_harshness PROTO((register tree, register tree, tree));
-static tree build_new_method_call              PROTO((tree, tree, tree, tree, int));
-
-static int rank_for_ideal PROTO((struct candidate *,
-                                struct candidate *));
-static int user_harshness PROTO((tree, tree));
-static int strictly_better PROTO((unsigned int, unsigned int));
-static struct candidate * ideal_candidate PROTO((struct candidate *,
-                                                int, int));
-static int may_be_remote PROTO((tree));
 static tree build_field_call PROTO((tree, tree, tree, tree));
 static tree find_scoped_type PROTO((tree, tree, tree));
-static void print_candidates PROTO((tree));
 static struct z_candidate * tourney PROTO((struct z_candidate *));
 static int joust PROTO((struct z_candidate *, struct z_candidate *));
 static int compare_qual PROTO((tree, tree));
@@ -100,2864 +87,551 @@ static tree reference_binding PROTO((tree, tree, tree, int));
 static tree strip_top_quals PROTO((tree));
 static tree non_reference PROTO((tree));
 static tree build_conv PROTO((enum tree_code, tree, tree));
-static void print_n_candidates PROTO((struct candidate *, int));
 static tree default_parm_conversions PROTO((tree, tree *));
 static int is_subseq PROTO((tree, tree));
 
-#define EVIL_RETURN(ARG)       ((ARG).code = EVIL_CODE, (ARG))
-#define STD_RETURN(ARG)                ((ARG).code = STD_CODE, (ARG))
-#define QUAL_RETURN(ARG)       ((ARG).code = QUAL_CODE, (ARG))
-#define TRIVIAL_RETURN(ARG)    ((ARG).code = TRIVIAL_CODE, (ARG))
-#define ZERO_RETURN(ARG)       ((ARG).code = 0, (ARG))
-
-/* Ordering function for overload resolution.  Compare two candidates
-   by gross quality.  */
-
-int
-rank_for_overload (x, y)
-     struct candidate *x, *y;
+tree
+build_vfield_ref (datum, type)
+     tree datum, type;
 {
-  if (y->h.code & (EVIL_CODE|ELLIPSIS_CODE|USER_CODE))
-    return y->h.code - x->h.code;
-  if (x->h.code & (EVIL_CODE|ELLIPSIS_CODE|USER_CODE))
-    return -1;
-
-  /* This is set by compute_conversion_costs, for calling a non-const
-     member function from a const member function.  */
-  if ((y->harshness[0].code & CONST_CODE) ^ (x->harshness[0].code & CONST_CODE))
-    return y->harshness[0].code - x->harshness[0].code;
-
-  if (y->h.code & STD_CODE)
-    {
-      if (x->h.code & STD_CODE)
-       return y->h.distance - x->h.distance;
-      return 1;
-    }
-  if (x->h.code & STD_CODE)
-    return -1;
-
-  return y->h.code - x->h.code;
-}
+  tree rval;
+  int old_assume_nonnull_objects = flag_assume_nonnull_objects;
 
-/* Compare two candidates, argument by argument.  */
+  if (datum == error_mark_node)
+    return error_mark_node;
 
-static int
-rank_for_ideal (x, y)
-     struct candidate *x, *y;
-{
-  int i;
+  /* Vtable references are always made from non-null objects.  */
+  flag_assume_nonnull_objects = 1;
+  if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
+    datum = convert_from_reference (datum);
 
-  if (x->h_len != y->h_len)
-    abort ();
+  if (! TYPE_USES_COMPLEX_INHERITANCE (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)), NULL_TREE, 0);
+  flag_assume_nonnull_objects = old_assume_nonnull_objects;
 
-  for (i = 0; i < x->h_len; i++)
-    {
-      if (y->harshness[i].code - x->harshness[i].code)
-       return y->harshness[i].code - x->harshness[i].code;
-      if ((y->harshness[i].code & STD_CODE)
-         && (y->harshness[i].distance - x->harshness[i].distance))
-       return y->harshness[i].distance - x->harshness[i].distance;
-
-      /* They're both the same code.  Now see if we're dealing with an
-        integral promotion that needs a finer grain of accuracy.  */
-      if (y->harshness[0].code & PROMO_CODE
-         && (y->harshness[i].int_penalty ^ x->harshness[i].int_penalty))
-       return y->harshness[i].int_penalty - x->harshness[i].int_penalty;
-    }
-  return 0;
+  return rval;
 }
 
-/* TYPE is the type we wish to convert to.  PARM is the parameter
-   we have to work with.  We use a somewhat arbitrary cost function
-   to measure this conversion.  */
+/* Build a call to a member of an object.  I.e., one that overloads
+   operator ()(), or is a pointer-to-function or pointer-to-method.  */
 
-static struct harshness_code
-convert_harshness (type, parmtype, parm)
-     register tree type, parmtype;
-     tree parm;
+static tree
+build_field_call (basetype_path, instance_ptr, name, parms)
+     tree basetype_path, instance_ptr, name, parms;
 {
-  struct harshness_code h;
-  register enum tree_code codel;
-  register enum tree_code coder;
-  int lvalue;
-
-  h.code = 0;
-  h.distance = 0;
-  h.int_penalty = 0;
-
-#ifdef GATHER_STATISTICS
-  n_convert_harshness++;
-#endif
-
-  if (TREE_CODE (parmtype) == REFERENCE_TYPE)
-    {
-      if (parm)
-       parm = convert_from_reference (parm);
-      parmtype = TREE_TYPE (parmtype);
-      lvalue = 1;
-    }
-  else if (parm)
-    lvalue = lvalue_p (parm);
-  else
-    lvalue = 0;
-
-  if (TYPE_PTRMEMFUNC_P (type))
-    type = TYPE_PTRMEMFUNC_FN_TYPE (type);
-  if (TYPE_PTRMEMFUNC_P (parmtype))
-    parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype);
-
-  codel = TREE_CODE (type);
-  coder = TREE_CODE (parmtype);
-
-  if (TYPE_MAIN_VARIANT (parmtype) == TYPE_MAIN_VARIANT (type))
-    return ZERO_RETURN (h);
+  tree field, instance;
 
-  if (coder == ERROR_MARK)
-    return EVIL_RETURN (h);
+  if (name == ctor_identifier || name == dtor_identifier)
+    return NULL_TREE;
 
-  if (codel == REFERENCE_TYPE)
+  if (instance_ptr == current_class_ptr)
     {
-      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);
-
-      /* Only allow const reference binding if we were given a parm to deal
-         with, since it isn't really a conversion.  This is a hack to
-         prevent build_type_conversion from finding this conversion, but
-         still allow overloading to find it.  */
-      if (! lvalue && ! (parm && TYPE_READONLY (ttl)))
-       return EVIL_RETURN (h);
-
-      if ((TYPE_READONLY (ttl) < constp)
-         || (TYPE_VOLATILE (ttl) < volatilep))
-       return EVIL_RETURN (h);
-
-      /* When passing a non-const argument into a const reference, dig it a
-        little, so a non-const reference is preferred over this one.  */
-      penalty = ((TYPE_READONLY (ttl) > constp)
-                + (TYPE_VOLATILE (ttl) > volatilep));
-
-      ttl = TYPE_MAIN_VARIANT (ttl);
-
-      if (form == OFFSET_TYPE)
-       {
-         intype = TREE_TYPE (intype);
-         form = TREE_CODE (intype);
-       }
-
-      ttr = intype;
-
-      if (TREE_CODE (ttl) == ARRAY_TYPE && TREE_CODE (ttr) == ARRAY_TYPE)
-       {
-         if (comptypes (ttl, ttr, 1))
-           return ZERO_RETURN (h);
-         return EVIL_RETURN (h);
-       }
+      /* Check to see if we really have a reference to an instance variable
+        with `operator()()' overloaded.  */
+      field = IDENTIFIER_CLASS_VALUE (name);
 
-      h = convert_harshness (ttl, ttr, NULL_TREE);
-      if (penalty && h.code == 0)
+      if (field == NULL_TREE)
        {
-         h.code = QUAL_CODE;
-         h.int_penalty = penalty;
+         cp_error ("`this' has no member named `%D'", name);
+         return error_mark_node;
        }
-      return h;
-    }
-
-  if (codel == POINTER_TYPE && fntype_p (parmtype))
-    {
-      tree p1, p2;
-      struct harshness_code h1, h2;
-
-      /* Get to the METHOD_TYPE or FUNCTION_TYPE that this might be.  */
-      type = TREE_TYPE (type);
 
-      if (coder == POINTER_TYPE)
+      if (TREE_CODE (field) == FIELD_DECL)
        {
-         parmtype = TREE_TYPE (parmtype);
-         coder = TREE_CODE (parmtype);
-       }
-
-      if (coder != TREE_CODE (type))
-       return EVIL_RETURN (h);
+         /* If it's a field, try overloading operator (),
+            or calling if the field is a pointer-to-function.  */
+         instance = build_component_ref_1 (current_class_ref, field, 0);
+         if (instance == error_mark_node)
+           return error_mark_node;
 
-      if (type != parmtype && coder == METHOD_TYPE)
-       {
-         tree ttl = TYPE_METHOD_BASETYPE (type);
-         tree ttr = TYPE_METHOD_BASETYPE (parmtype);
+         if (TYPE_LANG_SPECIFIC (TREE_TYPE (instance)))
+           return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, instance, parms, NULL_TREE);
 
-         int b_or_d = get_base_distance (ttr, ttl, 0, (tree*)0);
-         if (b_or_d < 0)
+         if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
            {
-             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;
+             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, expr_tree_cons (NULL_TREE, current_class_ptr, parms));
            }
-         else
-           h.distance = b_or_d;
-         h.code = STD_CODE;
-
-         type = build_function_type
-           (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type)));
-         parmtype = build_function_type
-           (TREE_TYPE (parmtype), TREE_CHAIN (TYPE_ARG_TYPES (parmtype)));
        }
+      return NULL_TREE;
+    }
 
-      /* We allow the default conversion between function type
-        and pointer-to-function type for free.  */
-      if (comptypes (type, parmtype, 1))
-       return h;
+  /* Check to see if this is not really a reference to an instance variable
+     with `operator()()' overloaded.  */
+  field = lookup_field (basetype_path, name, 1, 0);
 
-      if (pedantic)
-       return EVIL_RETURN (h);
+  /* This can happen if the reference was ambiguous or for access
+     violations.  */
+  if (field == error_mark_node)
+    return error_mark_node;
 
-      /* Compare return types.  */
-      p1 = TREE_TYPE (type);
-      p2 = TREE_TYPE (parmtype);
-      h2 = convert_harshness (p1, p2, NULL_TREE);
-      if (h2.code & EVIL_CODE)
-       return h2;
+  if (field)
+    {
+      tree basetype;
+      tree ftype = TREE_TYPE (field);
 
-      h1.code = TRIVIAL_CODE;
-      h1.distance = 0;
+      if (TREE_CODE (ftype) == REFERENCE_TYPE)
+       ftype = TREE_TYPE (ftype);
 
-      if (h2.distance != 0)
+      if (TYPE_LANG_SPECIFIC (ftype))
        {
-         tree binfo;
-
-         /* This only works for pointers.  */
-         if (TREE_CODE (p1) != POINTER_TYPE
-             && TREE_CODE (p1) != REFERENCE_TYPE)
-           return EVIL_RETURN (h);
-
-         p1 = TREE_TYPE (p1);
-         p2 = TREE_TYPE (p2);
-         /* Don't die if we happen to be dealing with void*.  */
-         if (!IS_AGGR_TYPE (p1) || !IS_AGGR_TYPE (p2))
-           return EVIL_RETURN (h);
-         if (h2.distance < 0)
-           binfo = get_binfo (p2, p1, 0);
-         else
-           binfo = get_binfo (p1, p2, 0);
-
-         if (! BINFO_OFFSET_ZEROP (binfo))
-           {
-#if 0
-             static int explained = 0;
-             if (h2.distance < 0)
-               message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p2, p1);
-             else
-               message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p1, p2);
+         /* Make the next search for this field very short.  */
+         basetype = DECL_FIELD_CONTEXT (field);
+         instance_ptr = convert_pointer_to (basetype, instance_ptr);
 
-             if (! explained++)
-               sorry ("(because pointer values change during conversion)");
-#endif
-             return EVIL_RETURN (h);
-           }
+         instance = build_indirect_ref (instance_ptr, NULL_PTR);
+         return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
+                                build_component_ref_1 (instance, field, 0),
+                                parms, NULL_TREE);
        }
-
-      h1.code |= h2.code;
-      if (h2.distance > h1.distance)
-       h1.distance = h2.distance;
-
-      p1 = TYPE_ARG_TYPES (type);
-      p2 = TYPE_ARG_TYPES (parmtype);
-      while (p1 && TREE_VALUE (p1) != void_type_node
-            && p2 && TREE_VALUE (p2) != void_type_node)
+      if (TREE_CODE (ftype) == POINTER_TYPE)
        {
-         h2 = convert_harshness (TREE_VALUE (p1), TREE_VALUE (p2),
-                                      NULL_TREE);
-         if (h2.code & EVIL_CODE)
-           return h2;
-
-         if (h2.distance)
+         if (TREE_CODE (TREE_TYPE (ftype)) == FUNCTION_TYPE
+             || TREE_CODE (TREE_TYPE (ftype)) == METHOD_TYPE)
            {
-             /* This only works for pointers and references.  */
-             if (TREE_CODE (TREE_VALUE (p1)) != POINTER_TYPE
-                 && TREE_CODE (TREE_VALUE (p1)) != REFERENCE_TYPE)
-               return EVIL_RETURN (h);
-             h2.distance = - h2.distance;
+             /* This is a member which is a pointer to function.  */
+             tree ref
+               = build_component_ref_1 (build_indirect_ref (instance_ptr,
+                                                            NULL_PTR),
+                                        field, LOOKUP_COMPLAIN);
+             if (ref == error_mark_node)
+               return error_mark_node;
+             return build_function_call (ref, parms);
            }
-
-         h1.code |= h2.code;
-         if (h2.distance > h1.distance)
-           h1.distance = h2.distance;
-         p1 = TREE_CHAIN (p1);
-         p2 = TREE_CHAIN (p2);
-       }
-      if (p1 == p2)
-       return h1;
-      if (p2)
-       {
-         if (p1)
-           return EVIL_RETURN (h);
-         h1.code |= ELLIPSIS_CODE;
-         return h1;
        }
-      if (p1)
+      else if (TREE_CODE (ftype) == METHOD_TYPE)
        {
-         if (TREE_PURPOSE (p1) == NULL_TREE)
-           h1.code |= EVIL_CODE;
-         return h1;
+         error ("invalid call via pointer-to-member function");
+         return error_mark_node;
        }
-    }
-  else if (codel == POINTER_TYPE && coder == OFFSET_TYPE)
-    {
-      tree ttl, ttr;
-
-      /* Get to the OFFSET_TYPE that this might be.  */
-      type = TREE_TYPE (type);
-
-      if (coder != TREE_CODE (type))
-       return EVIL_RETURN (h);
-
-      ttl = TYPE_OFFSET_BASETYPE (type);
-      ttr = TYPE_OFFSET_BASETYPE (parmtype);
-
-      if (ttl == ttr)
-       h.code = 0;
       else
-       {
-         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, (tree*)0);
-             if (b_or_d < 0)
-               return EVIL_RETURN (h);
-             h.distance = -b_or_d;
-           }
-         else
-           h.distance = b_or_d;
-         h.code = STD_CODE;
-       }
-
-      /* Now test the OFFSET_TYPE's target compatibility.  */
-      type = TREE_TYPE (type);
-      parmtype = TREE_TYPE (parmtype);
-    }
-
-  if (coder == UNKNOWN_TYPE)
-    {
-      if (codel == FUNCTION_TYPE
-         || codel == METHOD_TYPE
-         || (codel == POINTER_TYPE
-             && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
-                 || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)))
-       return TRIVIAL_RETURN (h);
-      return EVIL_RETURN (h);
+       return NULL_TREE;
     }
+  return NULL_TREE;
+}
 
-  if (coder == VOID_TYPE)
-    return EVIL_RETURN (h);
+static tree
+find_scoped_type (type, inner_name, inner_types)
+     tree type, inner_name, inner_types;
+{
+  tree tags = CLASSTYPE_TAGS (type);
 
-  if (codel == BOOLEAN_TYPE)
+  while (tags)
     {
-      if (INTEGRAL_CODE_P (coder) || coder == REAL_TYPE)
-       return STD_RETURN (h);
-      else if (coder == POINTER_TYPE || coder == OFFSET_TYPE)
+      /* The TREE_PURPOSE of an enum tag (which becomes a member of the
+        enclosing class) is set to the name for the enum type.  So, if
+        inner_name is `bar', and we strike `baz' for `enum bar { baz }',
+        then this test will be true.  */
+      if (TREE_PURPOSE (tags) == inner_name)
        {
-         /* Make this worse than any conversion to another pointer.
-            FIXME this is how I think the language should work, but it may not
-            end up being how the language is standardized (jason 1/30/95).  */
-         h.distance = 32767;
-         return STD_RETURN (h);
+         if (inner_types == NULL_TREE)
+           return TYPE_MAIN_DECL (TREE_VALUE (tags));
+         return resolve_scope_to_name (TREE_VALUE (tags), inner_types);
        }
-      return EVIL_RETURN (h);
+      tags = TREE_CHAIN (tags);
     }
 
-  if (INTEGRAL_CODE_P (codel))
-    {
-      /* Control equivalence of ints an enums.  */
+  /* Look for a TYPE_DECL.  */
+  for (tags = TYPE_FIELDS (type); tags; tags = TREE_CHAIN (tags))
+    if (TREE_CODE (tags) == TYPE_DECL && DECL_NAME (tags) == inner_name)
+      {
+       /* Code by raeburn.  */
+       if (inner_types == NULL_TREE)
+         return tags;
+       return resolve_scope_to_name (TREE_TYPE (tags), inner_types);
+      }
 
-      if (codel == ENUMERAL_TYPE
-         && flag_int_enum_equivalence == 0)
-       {
-         /* Enums can be converted to ints, but not vice-versa.  */
-         if (coder != ENUMERAL_TYPE
-             || TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (parmtype))
-           return EVIL_RETURN (h);
-       }
+  return NULL_TREE;
+}
+
+/* Resolve an expression NAME1::NAME2::...::NAMEn to
+   the name that names the above nested type.  INNER_TYPES
+   is a chain of nested type names (held together by SCOPE_REFs);
+   OUTER_TYPE is the type we know to enclose INNER_TYPES.
+   Returns NULL_TREE if there is an error.  */
 
-      /* else enums and ints (almost) freely interconvert.  */
+tree
+resolve_scope_to_name (outer_type, inner_stuff)
+     tree outer_type, inner_stuff;
+{
+  register tree tmp;
+  tree inner_name, inner_type;
 
-      if (INTEGRAL_CODE_P (coder))
-       {
-         if (TYPE_MAIN_VARIANT (type)
-             == TYPE_MAIN_VARIANT (type_promotes_to (parmtype)))
-           {
-             h.code = PROMO_CODE;
-           }
-         else
-           h.code = STD_CODE;
-           
-         return h;
-       }
-      else if (coder == REAL_TYPE)
-       {
-         h.code = STD_CODE;
-         h.distance = 0;
-         return h;
+  if (outer_type == NULL_TREE && current_class_type != NULL_TREE)
+    {
+      /* We first try to look for a nesting in our current class context,
+         then try any enclosing classes.  */
+      tree type = current_class_type;
+      
+      while (type && (TREE_CODE (type) == RECORD_TYPE
+                     || TREE_CODE (type) == UNION_TYPE))
+        {
+          tree rval = resolve_scope_to_name (type, inner_stuff);
+
+         if (rval != NULL_TREE)
+           return rval;
+         type = DECL_CONTEXT (TYPE_MAIN_DECL (type));
        }
     }
 
-  if (codel == REAL_TYPE)
+  if (TREE_CODE (inner_stuff) == SCOPE_REF)
     {
-      if (coder == REAL_TYPE)
-       {
-         if (TYPE_MAIN_VARIANT (type)
-             == TYPE_MAIN_VARIANT (type_promotes_to (parmtype)))
-           h.code = PROMO_CODE;
-         else
-           h.code = STD_CODE;
-           
-         return h;
-       }
-      else if (INTEGRAL_CODE_P (coder))
-       {
-         h.code = STD_CODE;
-         h.distance = 0;
-         return h;
-       }
+      inner_name = TREE_OPERAND (inner_stuff, 0);
+      inner_type = TREE_OPERAND (inner_stuff, 1);
     }
-
-  /* Convert arrays which have not previously been converted.  */
-  if (coder == ARRAY_TYPE)
+  else
     {
-      coder = POINTER_TYPE;
-      if (parm)
-       {
-         parm = decay_conversion (parm);
-         parmtype = TREE_TYPE (parm);
-       }
-      else
-       parmtype = build_pointer_type (TREE_TYPE (parmtype));
+      inner_name = inner_stuff;
+      inner_type = NULL_TREE;
     }
 
-  /* Conversions among pointers */
-  if (codel == POINTER_TYPE && coder == POINTER_TYPE)
+  if (outer_type == NULL_TREE)
     {
-      register tree ttl = TYPE_MAIN_VARIANT (TREE_TYPE (type));
-      register tree ttr = TYPE_MAIN_VARIANT (TREE_TYPE (parmtype));
-      int penalty = 4 * (ttl != ttr);
-
-      /* Anything converts to void *.  Since this may be `const void *'
-        (etc.) use VOID_TYPE instead of void_type_node.  Otherwise, the
-        targets must be the same, except that we do allow (at some cost)
-        conversion between signed and unsigned pointer types.  */
-
-      if ((TREE_CODE (ttl) == METHOD_TYPE
-          || TREE_CODE (ttl) == FUNCTION_TYPE)
-         && TREE_CODE (ttl) == TREE_CODE (ttr))
+      tree x;
+      /* If we have something that's already a type by itself,
+        use that.  */
+      if (IDENTIFIER_HAS_TYPE_VALUE (inner_name))
        {
-         if (comptypes (ttl, ttr, -1))
-           {
-             h.code = penalty ? STD_CODE : 0;
-             h.distance =  0;
-           }
-         else
-           h.code = EVIL_CODE;
-         return h;
+         if (inner_type)
+           return resolve_scope_to_name (IDENTIFIER_TYPE_VALUE (inner_name),
+                                         inner_type);
+         return inner_name;
        }
+      
+      x = lookup_name (inner_name, 0);
 
-#if 1
-      if (TREE_CODE (ttl) != VOID_TYPE
-         && (TREE_CODE (ttr) != VOID_TYPE || !parm || !null_ptr_cst_p (parm)))
+      if (x && TREE_CODE (x) == NAMESPACE_DECL)
        {
-         if (comp_target_types (type, parmtype, 1) <= 0)
-           return EVIL_RETURN (h);
+         x = lookup_namespace_name (x, inner_type);
+         return x;
        }
-#else
-      if (!(TREE_CODE (ttl) == VOID_TYPE
-           || TREE_CODE (ttr) == VOID_TYPE
-           || (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (ttr)
-               && (ttl = unsigned_type (ttl),
-                   ttr = unsigned_type (ttr),
-                   penalty = 10, 0))
-           || (comp_target_types (ttl, ttr, 0) > 0)))
-       return EVIL_RETURN (h);
-#endif
+      return NULL_TREE;
+    }
 
-      if (ttr == ttl)
-       {
-         tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype);
-
-         h.code = 0;
-         /* Note conversion from `T*' to `const T*',
-                              or `T*' to `volatile T*'.  */
-         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;
-         return h;
-       }
-
-
-      if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
-       {
-         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, (tree*)0);
-             if (b_or_d < 0)
-               return EVIL_RETURN (h);
-             h.distance = -b_or_d;
-           }
-         else
-           h.distance = b_or_d;
-         h.code = STD_CODE;
-         return h;
-       }
-
-      /* If converting from a `class*' to a `void*', make it
-        less favorable than any inheritance relationship.  */
-      if (TREE_CODE (ttl) == VOID_TYPE && IS_AGGR_TYPE (ttr))
-       {
-         h.code = STD_CODE;
-         h.distance = CLASSTYPE_MAX_DEPTH (ttr)+1;
-         return h;
-       }
-
-      h.code = penalty ? STD_CODE : PROMO_CODE;
-      /* Catch things like `const char *' -> `const void *'
-        vs `const char *' -> `void *'.  */
-      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)))
-           h.code = EVIL_CODE;
-         else if ((TYPE_READONLY (tmp1) > TREE_READONLY (tmp2))
-                  || (TYPE_VOLATILE (tmp1) > TYPE_VOLATILE (tmp2)))
-           h.code |= QUAL_CODE;
-       }
-      return h;
-    }
-
-  if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
-    {
-      /* This is not a bad match, but don't let it beat
-        integer-enum combinations.  */
-      if (parm && integer_zerop (parm))
-       {
-         h.code = STD_CODE;
-         h.distance = 0;
-         return h;
-       }
-    }
-
-  /* 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 == RECORD_TYPE && coder == POINTER_TYPE
-      && IS_SIGNATURE_POINTER (type) && IS_SIGNATURE (TREE_TYPE (parmtype)))
-    return ZERO_RETURN (h);
-
-  if (codel == RECORD_TYPE && coder == RECORD_TYPE)
-    {
-      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, (tree*)0);
-         if (b_or_d < 0)
-           return EVIL_RETURN (h);
-         h.distance = -b_or_d;
-       }
-      else
-       h.distance = b_or_d;
-      h.code = STD_CODE;
-      return h;
-    }
-  return EVIL_RETURN (h);
-}
-
-/* A clone of build_type_conversion for checking user-defined conversions in
-   overload resolution.  */
-
-static int
-user_harshness (type, parmtype)
-     register tree type, parmtype;
-{
-  tree conv;
-  tree winner = NULL_TREE;
-  int code = 0;
-
-  {
-    tree typename = build_typename_overload (type);
-    if (lookup_fnfields (TYPE_BINFO (parmtype), typename, 0))
-      return 0;
-  }
-                       
-  for (conv = lookup_conversions (parmtype); conv; conv = TREE_CHAIN (conv))
-    {
-      struct harshness_code tmp;
-      tree cand = TREE_VALUE (conv);
-
-      if (winner && winner == cand)
-       continue;
-
-      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 = cand;
-             code = tmp.code;
-           }
-       }
-    }
-
-  if (winner)
-    return code;
-
-  return -1;
-}
-
-#ifdef DEBUG_MATCHING
-static char *
-print_harshness (h)
-     struct harshness_code *h;
-{
-  static char buf[1024];
-  char tmp[1024];
-
-  bzero (buf, 1024 * sizeof (char));
-  strcat (buf, "codes=[");
-  if (h->code & EVIL_CODE)
-    strcat (buf, "EVIL");
-  if (h->code & CONST_CODE)
-    strcat (buf, " CONST");
-  if (h->code & ELLIPSIS_CODE)
-    strcat (buf, " ELLIPSIS");
-  if (h->code & USER_CODE)
-    strcat (buf, " USER");
-  if (h->code & STD_CODE)
-    strcat (buf, " STD");
-  if (h->code & PROMO_CODE)
-    strcat (buf, " PROMO");
-  if (h->code & QUAL_CODE)
-    strcat (buf, " QUAL");
-  if (h->code & TRIVIAL_CODE)
-    strcat (buf, " TRIVIAL");
-  if (buf[0] == '\0')
-    strcat (buf, "0");
-
-  sprintf (tmp, "] distance=%d int_penalty=%d", h->distance, h->int_penalty);
-
-  strcat (buf, tmp);
-
-  return buf;
-}
-#endif
-
-/* Algorithm: For each argument, calculate how difficult it is to
-   make FUNCTION accept that argument.  If we can easily tell that
-   FUNCTION won't be acceptable to one of the arguments, then we
-   don't need to compute the ease of converting the other arguments,
-   since it will never show up in the intersection of all arguments'
-   favorite functions.
-
-   Conversions between builtin and user-defined types are allowed, but
-   no function involving such a conversion is preferred to one which
-   does not require such a conversion.  Furthermore, such conversions
-   must be unique.  */
-
-void
-compute_conversion_costs (function, tta_in, cp, arglen)
-     tree function;
-     tree tta_in;
-     struct candidate *cp;
-     int arglen;
-{
-  tree ttf_in = TYPE_ARG_TYPES (TREE_TYPE (function));
-  tree ttf = ttf_in;
-  tree tta = tta_in;
-
-  /* Start out with no strikes against.  */
-  int evil_strikes = 0;
-  int ellipsis_strikes = 0;
-  int user_strikes = 0;
-  int b_or_d_strikes = 0;
-  int easy_strikes = 0;
-
-  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!  */
-
-  cp->h.code = 0;
-  cp->h.distance = 0;
-  cp->h.int_penalty = 0;
-  bzero ((char *) cp->harshness,
-        (cp->h_len + 1) * sizeof (struct harshness_code));
-
-  while (ttf && tta)
-    {
-      struct harshness_code h;
-
-      if (ttf == void_list_node)
-       break;
-
-      if (type_unknown_p (TREE_VALUE (tta)))
-       {         
-         /* Must perform some instantiation here.  */
-         tree rhs = TREE_VALUE (tta);
-         tree lhstype = TREE_VALUE (ttf);
-
-         /* Keep quiet about possible contravariance violations.  */
-         int old_inhibit_warnings = inhibit_warnings;
-         inhibit_warnings = 1;
-
-         /* @@ This is to undo what `grokdeclarator' does to
-            parameter types.  It really should go through
-            something more general.  */
-
-         TREE_TYPE (tta) = unknown_type_node;
-         rhs = instantiate_type (lhstype, rhs, 0);
-         inhibit_warnings = old_inhibit_warnings;
-
-         if (TREE_CODE (rhs) == ERROR_MARK)
-           h.code = EVIL_CODE;
-         else
-           h = convert_harshness (lhstype, TREE_TYPE (rhs), rhs);
-       }
-      else
-       {
-#ifdef DEBUG_MATCHING
-         static tree old_function = NULL_TREE;
-
-         if (!old_function || function != old_function)
-           {
-             cp_error ("trying %D", function);
-             old_function = function;
-           }
-
-         cp_error ("      doing (%T) %E against arg %T",
-                   TREE_TYPE (TREE_VALUE (tta)), TREE_VALUE (tta),
-                   TREE_VALUE (ttf));
-#endif
-
-         h = convert_harshness (TREE_VALUE (ttf),
-                                TREE_TYPE (TREE_VALUE (tta)),
-                                TREE_VALUE (tta));
-
-#ifdef DEBUG_MATCHING
-         cp_error ("     evaluated %s", print_harshness (&h));
-#endif
-       }
-
-      cp->harshness[strike_index] = h;
-      if ((h.code & EVIL_CODE)
-         || ((h.code & STD_CODE) && h.distance < 0))
-       {
-         cp->u.bad_arg = strike_index;
-         evil_strikes = 1;
-       }
-     else if (h.code & ELLIPSIS_CODE)
-       ellipsis_strikes += 1;
-#if 0
-      /* This is never set by `convert_harshness'.  */
-      else if (h.code & USER_CODE)
-       {
-         user_strikes += 1;
-       }
-#endif
-      else
-       {
-         if ((h.code & STD_CODE) && h.distance)
-           {
-             if (h.distance > b_or_d_strikes)
-               b_or_d_strikes = h.distance;
-           }
-         else
-           easy_strikes += (h.code & (STD_CODE|PROMO_CODE|TRIVIAL_CODE));
-         cp->h.code |= h.code;
-         /* Make sure we communicate this.  */
-         cp->h.int_penalty += h.int_penalty;
-       }
-
-      ttf = TREE_CHAIN (ttf);
-      tta = TREE_CHAIN (tta);
-      strike_index += 1;
-    }
-
-  if (tta)
-    {
-      /* ran out of formals, and parmlist is fixed size.  */
-      if (ttf /* == void_type_node */)
-       {
-         cp->h.code = EVIL_CODE;
-         cp->u.bad_arg = -1;
-         cp_silent = 0;
-         return;
-       }
-      else
-       {
-         struct harshness_code h;
-         int l = list_length (tta);
-         ellipsis_strikes += l;
-         h.code = ELLIPSIS_CODE;
-         h.distance = 0;
-         h.int_penalty = 0;
-         for (; l; --l)
-           cp->harshness[strike_index++] = h;
-       }
-    }
-  else if (ttf && ttf != void_list_node)
-    {
-      /* ran out of actuals, and no defaults.  */
-      if (TREE_PURPOSE (ttf) == NULL_TREE)
-       {
-         cp->h.code = EVIL_CODE;
-         cp->u.bad_arg = -2;
-         cp_silent = 0;
-         return;
-       }
-      /* Store index of first default.  */
-      cp->harshness[arglen].distance = strike_index+1;
-    }
-  else
-    cp->harshness[arglen].distance = 0;
-
-  /* Argument list lengths work out, so don't need to check them again.  */
-  if (evil_strikes)
-    {
-      /* We do not check for derived->base conversions here, since in
-        no case would they give evil strike counts, unless such conversions
-        are somehow ambiguous.  */
-
-      /* See if any user-defined conversions apply.
-         But make sure that we do not loop.  */
-      static int dont_convert_types = 0;
-
-      if (dont_convert_types)
-       {
-         cp->h.code = EVIL_CODE;
-         cp_silent = 0;
-         return;
-       }
-
-      win = 0;                 /* Only get one chance to win.  */
-      ttf = TYPE_ARG_TYPES (TREE_TYPE (function));
-      tta = tta_in;
-      strike_index = 0;
-      evil_strikes = 0;
-
-      while (ttf && tta)
-       {
-         if (ttf == void_list_node)
-           break;
-
-         lose = cp->harshness[strike_index];
-         if ((lose.code & EVIL_CODE)
-             || ((lose.code & STD_CODE) && lose.distance < 0))
-           {
-             tree actual_type = TREE_TYPE (TREE_VALUE (tta));
-             tree formal_type = TREE_VALUE (ttf);
-             int extra_conversions = 0;
-
-             dont_convert_types = 1;
-
-             if (TREE_CODE (formal_type) == REFERENCE_TYPE)
-               formal_type = TREE_TYPE (formal_type);
-             if (TREE_CODE (actual_type) == REFERENCE_TYPE)
-               actual_type = TREE_TYPE (actual_type);
-
-             if (formal_type != error_mark_node
-                 && actual_type != error_mark_node)
-               {
-                 formal_type = complete_type (TYPE_MAIN_VARIANT (formal_type));
-                 actual_type = complete_type (TYPE_MAIN_VARIANT (actual_type));
-
-                 if (TYPE_HAS_CONSTRUCTOR (formal_type))
-                   {
-                     /* If it has a constructor for this type,
-                        try to use it.  */
-                     /* @@ There is no way to save this result yet, so
-                        success is a NULL_TREE for now.  */
-                     if (convert_to_aggr (formal_type, TREE_VALUE (tta), 0, 1)
-                         != error_mark_node)
-                       win++;
-                   }
-                 if (TYPE_LANG_SPECIFIC (actual_type)
-                     && TYPE_HAS_CONVERSION (actual_type))
-                   {
-                     int extra = user_harshness (formal_type, actual_type);
-
-                     if (extra == EVIL_CODE)
-                       win += 2;
-                     else if (extra >= 0)
-                       {
-                         win++;
-                         extra_conversions = extra;
-                       }
-                   }
-               }
-             dont_convert_types = 0;
-
-             if (win == 1)
-               {
-                 user_strikes += 1;
-                 cp->harshness[strike_index].code
-                   = USER_CODE | (extra_conversions ? STD_CODE : 0);
-                 win = 0;
-               }
-             else
-               {
-                 if (cp->u.bad_arg > strike_index)
-                   cp->u.bad_arg = strike_index;
-
-                 evil_strikes = win ? 2 : 1;
-                 break;
-               }
-           }
-
-         ttf = TREE_CHAIN (ttf);
-         tta = TREE_CHAIN (tta);
-         strike_index += 1;
-       }
-    }
-
-  /* Const member functions get a small penalty because defaulting
-     to const is less useful than defaulting to non-const.  */
-  /* This is bogus, it does not correspond to anything in the ARM.
-     This code will be fixed when this entire section is rewritten
-     to conform to the ARM.  (mrs)  */
-  if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
-    {
-      tree this_parm = TREE_VALUE (ttf_in);
-
-      if (TREE_CODE (this_parm) == RECORD_TYPE /* Is `this' a sig ptr?  */
-           ? TYPE_READONLY (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (this_parm))))
-           : TYPE_READONLY (TREE_TYPE (this_parm)))
-       {
-         cp->harshness[0].code |= TRIVIAL_CODE;
-         ++easy_strikes;
-       }
-      else
-       {
-         /* Calling a non-const member function from a const member function
-            is probably invalid, but for now we let it only draw a warning.
-            We indicate that such a mismatch has occurred by setting the
-            harshness to a maximum value.  */
-         if (TREE_CODE (TREE_TYPE (TREE_VALUE (tta_in))) == POINTER_TYPE
-             && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (TREE_VALUE (tta_in))))))
-           cp->harshness[0].code |= CONST_CODE;
-       }
-    }
-
-  if (evil_strikes)
-    cp->h.code = EVIL_CODE;
-  if (ellipsis_strikes)
-    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
-}
-
-/* Subroutine of ideal_candidate.  See if X or Y is a better match
-   than the other.  */
-
-static int
-strictly_better (x, y)
-     unsigned int x, y;
-{
-  unsigned short xor;
-
-  if (x == y)
-    return 0;
-
-  xor = x ^ y;
-  if (xor >= x || xor >= y)
-    return 1;
-  return 0;
-}
-
-/* When one of several possible overloaded functions and/or methods
-   can be called, choose the best candidate for overloading.
-
-   BASETYPE is the context from which we start method resolution
-   or NULL if we are comparing overloaded functions.
-   CANDIDATES is the array of candidates we have to choose from.
-   N_CANDIDATES is the length of CANDIDATES.
-   PARMS is a TREE_LIST of parameters to the function we'll ultimately
-   choose.  It is modified in place when resolving methods.  It is not
-   modified in place when resolving overloaded functions.
-   LEN is the length of the parameter list.  */
-
-static struct candidate *
-ideal_candidate (candidates, n_candidates, len)
-     struct candidate *candidates;
-     int n_candidates;
-     int len;
-{
-  struct candidate *cp = candidates+n_candidates;
-  int i, j = -1, best_code;
-
-  /* For each argument, sort the functions from best to worst for the arg.
-     For each function that's not best for this arg, set its overall
-     harshness to EVIL so that other args won't like it.  The candidate
-     list for the last argument is the intersection of all the best-liked
-     functions.  */
-
-  qsort (candidates, n_candidates, sizeof (struct candidate),
-        (int (*) PROTO((const void *, const void *))) rank_for_overload);
-  best_code = cp[-1].h.code;
-
-  /* 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))
-    {
-      int better = 0;
-      int worse = 0;
-
-      for (j = 0; j < n_candidates; j++)
-       if (! strictly_better (candidates[j].h.code, best_code))
-         break;
-
-      qsort (candidates+j, n_candidates-j, sizeof (struct candidate),
-            (int (*) PROTO((const void *, const void *))) rank_for_ideal);
-      for (i = 0; i < len; i++)
-       {
-         if (cp[-1].harshness[i].code < cp[-2].harshness[i].code)
-           better = 1;
-         else if (cp[-1].harshness[i].code > cp[-2].harshness[i].code)
-           worse = 1;
-         else if (cp[-1].harshness[i].code & STD_CODE)
-           {
-             /* If it involves a standard conversion, let the
-                inheritance lattice be the final arbiter.  */
-             if (cp[-1].harshness[i].distance > cp[-2].harshness[i].distance)
-               worse = 1;
-             else if (cp[-1].harshness[i].distance < cp[-2].harshness[i].distance)
-               better = 1;
-           }
-         else if (cp[-1].harshness[i].code & PROMO_CODE)
-           {
-             /* For integral promotions, take into account a finer
-                granularity for determining which types should be favored
-                over others in such promotions.  */
-             if (cp[-1].harshness[i].int_penalty > cp[-2].harshness[i].int_penalty)
-               worse = 1;
-             else if (cp[-1].harshness[i].int_penalty < cp[-2].harshness[i].int_penalty)
-               better = 1;
-           }
-       }
-
-      if (! better || worse)
-       return NULL;
-    }
-  return cp-1;
-}
-
-/* Assume that if the class referred to is not in the
-   current class hierarchy, that it may be remote.
-   PARENT is assumed to be of aggregate type here.  */
-
-static int
-may_be_remote (parent)
-     tree parent;
-{
-  if (TYPE_OVERLOADS_METHOD_CALL_EXPR (parent) == 0)
-    return 0;
-
-  if (current_class_type == NULL_TREE)
-    return 0;
-
-  if (parent == current_class_type)
-    return 0;
-
-  if (UNIQUELY_DERIVED_FROM_P (parent, current_class_type))
-    return 0;
-  return 1;
-}
-
-tree
-build_vfield_ref (datum, type)
-     tree datum, type;
-{
-  tree rval;
-  int old_assume_nonnull_objects = flag_assume_nonnull_objects;
-
-  if (datum == error_mark_node)
-    return error_mark_node;
-
-  /* Vtable references are always made from non-null objects.  */
-  flag_assume_nonnull_objects = 1;
-  if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)
-    datum = convert_from_reference (datum);
-
-  if (! TYPE_USES_COMPLEX_INHERITANCE (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)), NULL_TREE, 0);
-  flag_assume_nonnull_objects = old_assume_nonnull_objects;
-
-  return rval;
-}
-
-/* Build a call to a member of an object.  I.e., one that overloads
-   operator ()(), or is a pointer-to-function or pointer-to-method.  */
-
-static tree
-build_field_call (basetype_path, instance_ptr, name, parms)
-     tree basetype_path, instance_ptr, name, parms;
-{
-  tree field, instance;
-
-  if (name == ctor_identifier || name == dtor_identifier)
-    return NULL_TREE;
-
-  if (instance_ptr == current_class_ptr)
-    {
-      /* Check to see if we really have a reference to an instance variable
-        with `operator()()' overloaded.  */
-      field = IDENTIFIER_CLASS_VALUE (name);
-
-      if (field == NULL_TREE)
-       {
-         cp_error ("`this' has no member named `%D'", name);
-         return error_mark_node;
-       }
-
-      if (TREE_CODE (field) == FIELD_DECL)
-       {
-         /* If it's a field, try overloading operator (),
-            or calling if the field is a pointer-to-function.  */
-         instance = build_component_ref_1 (current_class_ref, field, 0);
-         if (instance == error_mark_node)
-           return error_mark_node;
-
-         if (TYPE_LANG_SPECIFIC (TREE_TYPE (instance))
-             && (TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (instance))
-                 || flag_ansi_overloading))
-           return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, instance, parms, NULL_TREE);
-
-         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, expr_tree_cons (NULL_TREE, current_class_ptr, parms));
-           }
-       }
-      return NULL_TREE;
-    }
-
-  /* Check to see if this is not really a reference to an instance variable
-     with `operator()()' overloaded.  */
-  field = lookup_field (basetype_path, name, 1, 0);
-
-  /* This can happen if the reference was ambiguous or for access
-     violations.  */
-  if (field == error_mark_node)
-    return error_mark_node;
-
-  if (field)
-    {
-      tree basetype;
-      tree ftype = TREE_TYPE (field);
-
-      if (TREE_CODE (ftype) == REFERENCE_TYPE)
-       ftype = TREE_TYPE (ftype);
-
-      if (TYPE_LANG_SPECIFIC (ftype)
-         && (TYPE_OVERLOADS_CALL_EXPR (ftype) || flag_ansi_overloading))
-       {
-         /* Make the next search for this field very short.  */
-         basetype = DECL_FIELD_CONTEXT (field);
-         instance_ptr = convert_pointer_to (basetype, instance_ptr);
-
-         instance = build_indirect_ref (instance_ptr, NULL_PTR);
-         return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
-                                build_component_ref_1 (instance, field, 0),
-                                parms, NULL_TREE);
-       }
-      if (TREE_CODE (ftype) == POINTER_TYPE)
-       {
-         if (TREE_CODE (TREE_TYPE (ftype)) == FUNCTION_TYPE
-             || TREE_CODE (TREE_TYPE (ftype)) == METHOD_TYPE)
-           {
-             /* This is a member which is a pointer to function.  */
-             tree ref
-               = build_component_ref_1 (build_indirect_ref (instance_ptr,
-                                                            NULL_PTR),
-                                        field, LOOKUP_COMPLAIN);
-             if (ref == error_mark_node)
-               return error_mark_node;
-             return build_function_call (ref, parms);
-           }
-       }
-      else if (TREE_CODE (ftype) == METHOD_TYPE)
-       {
-         error ("invalid call via pointer-to-member function");
-         return error_mark_node;
-       }
-      else
-       return NULL_TREE;
-    }
-  return NULL_TREE;
-}
-
-static tree
-find_scoped_type (type, inner_name, inner_types)
-     tree type, inner_name, inner_types;
-{
-  tree tags = CLASSTYPE_TAGS (type);
-
-  while (tags)
-    {
-      /* The TREE_PURPOSE of an enum tag (which becomes a member of the
-        enclosing class) is set to the name for the enum type.  So, if
-        inner_name is `bar', and we strike `baz' for `enum bar { baz }',
-        then this test will be true.  */
-      if (TREE_PURPOSE (tags) == inner_name)
-       {
-         if (inner_types == NULL_TREE)
-           return TYPE_MAIN_DECL (TREE_VALUE (tags));
-         return resolve_scope_to_name (TREE_VALUE (tags), inner_types);
-       }
-      tags = TREE_CHAIN (tags);
-    }
-
-  /* Look for a TYPE_DECL.  */
-  for (tags = TYPE_FIELDS (type); tags; tags = TREE_CHAIN (tags))
-    if (TREE_CODE (tags) == TYPE_DECL && DECL_NAME (tags) == inner_name)
-      {
-       /* Code by raeburn.  */
-       if (inner_types == NULL_TREE)
-         return tags;
-       return resolve_scope_to_name (TREE_TYPE (tags), inner_types);
-      }
-
-  return NULL_TREE;
-}
-
-/* Resolve an expression NAME1::NAME2::...::NAMEn to
-   the name that names the above nested type.  INNER_TYPES
-   is a chain of nested type names (held together by SCOPE_REFs);
-   OUTER_TYPE is the type we know to enclose INNER_TYPES.
-   Returns NULL_TREE if there is an error.  */
-
-tree
-resolve_scope_to_name (outer_type, inner_stuff)
-     tree outer_type, inner_stuff;
-{
-  register tree tmp;
-  tree inner_name, inner_type;
-
-  if (outer_type == NULL_TREE && current_class_type != NULL_TREE)
-    {
-      /* We first try to look for a nesting in our current class context,
-         then try any enclosing classes.  */
-      tree type = current_class_type;
-      
-      while (type && (TREE_CODE (type) == RECORD_TYPE
-                     || TREE_CODE (type) == UNION_TYPE))
-        {
-          tree rval = resolve_scope_to_name (type, inner_stuff);
-
-         if (rval != NULL_TREE)
-           return rval;
-         type = DECL_CONTEXT (TYPE_MAIN_DECL (type));
-       }
-    }
-
-  if (TREE_CODE (inner_stuff) == SCOPE_REF)
-    {
-      inner_name = TREE_OPERAND (inner_stuff, 0);
-      inner_type = TREE_OPERAND (inner_stuff, 1);
-    }
-  else
-    {
-      inner_name = inner_stuff;
-      inner_type = NULL_TREE;
-    }
-
-  if (outer_type == NULL_TREE)
-    {
-      tree x;
-      /* If we have something that's already a type by itself,
-        use that.  */
-      if (IDENTIFIER_HAS_TYPE_VALUE (inner_name))
-       {
-         if (inner_type)
-           return resolve_scope_to_name (IDENTIFIER_TYPE_VALUE (inner_name),
-                                         inner_type);
-         return inner_name;
-       }
-      
-      x = lookup_name (inner_name, 0);
-
-      if (x && TREE_CODE (x) == NAMESPACE_DECL)
-       {
-         x = lookup_namespace_name (x, inner_type);
-         return x;
-       }
-      return NULL_TREE;
-    }
-
-  if (! IS_AGGR_TYPE (outer_type))
-    return NULL_TREE;
-
-  /* Look for member classes or enums.  */
-  tmp = find_scoped_type (outer_type, inner_name, inner_type);
-
-  /* If it's not a type in this class, then go down into the
-     base classes and search there.  */
-  if (! tmp && TYPE_BINFO (outer_type))
-    {
-      tree binfos = TYPE_BINFO_BASETYPES (outer_type);
-      int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
-      for (i = 0; i < n_baselinks; i++)
-       {
-         tree base_binfo = TREE_VEC_ELT (binfos, i);
-         tmp = resolve_scope_to_name (BINFO_TYPE (base_binfo), inner_stuff);
-         if (tmp)
-           return tmp;
-       }
-      tmp = NULL_TREE;
-    }
-
-  return tmp;
-}
-
-/* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'.
-   This is how virtual function calls are avoided.  */
-
-tree
-build_scoped_method_call (exp, basetype, name, parms)
-     tree exp, basetype, name, parms;
-{
-  /* Because this syntactic form does not allow
-     a pointer to a base class to be `stolen',
-     we need not protect the derived->base conversion
-     that happens here.
-     
-     @@ But we do have to check access privileges later.  */
-  tree binfo, decl;
-  tree type = TREE_TYPE (exp);
-
-  if (type == error_mark_node
-      || basetype == error_mark_node)
-    return error_mark_node;
-
-  if (processing_template_decl)
-    {
-      if (TREE_CODE (name) == BIT_NOT_EXPR)
-       {
-         tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0);
-         if (type)
-           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, NULL_TREE);
-    }
-
-  if (TREE_CODE (type) == REFERENCE_TYPE)
-    type = TREE_TYPE (type);
-
-  if (TREE_CODE (basetype) == TREE_VEC)
-    {
-      binfo = basetype;
-      basetype = BINFO_TYPE (binfo);
-    }
-  else
-    binfo = NULL_TREE;
-
-  /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note
-     that explicit ~int is caught in the parser; this deals with typedefs
-     and template parms.  */
-  if (TREE_CODE (name) == BIT_NOT_EXPR && ! IS_AGGR_TYPE (basetype))
-    {
-      if (type != basetype)
-       cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')",
-                 exp, basetype, type);
-      name = TREE_OPERAND (name, 0);
-      if (basetype != name && basetype != get_type_value (name))
-       cp_error ("qualified type `%T' does not match destructor name `~%T'",
-                 basetype, name);
-      return cp_convert (void_type_node, exp);
-    }
-
-  if (! is_aggr_type (basetype, 1))
-    return error_mark_node;
-
-  if (! IS_AGGR_TYPE (type))
-    {
-      cp_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);
-    }
-
-  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)
-       {
-         /* Explicit call to destructor.  */
-         name = TREE_OPERAND (name, 0);
-         if (! (name == TYPE_MAIN_VARIANT (TREE_TYPE (decl))
-                || name == constructor_name (TREE_TYPE (decl))
-                || TREE_TYPE (decl) == get_type_value (name)))
-           {
-             cp_error
-               ("qualified type `%T' does not match destructor name `~%T'",
-                TREE_TYPE (decl), name);
-             return error_mark_node;
-           }
-         if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl)))
-           return cp_convert (void_type_node, exp);
-         
-         return build_delete (TREE_TYPE (decl), decl, integer_two_node,
-                              LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR,
-                              0);
-       }
-
-      /* Call to a method.  */
-      return build_method_call (decl, name, parms, binfo,
-                               LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
-    }
-  return error_mark_node;
-}
-
-static void
-print_candidates (candidates)
-     tree candidates;
-{
-  cp_error_at ("candidates are: %D", TREE_VALUE (candidates));
-  candidates = TREE_CHAIN (candidates);
-
-  while (candidates)
-    {
-      cp_error_at ("                %D", TREE_VALUE (candidates));
-      candidates = TREE_CHAIN (candidates);
-    }
-}
-
-static void
-print_n_candidates (candidates, n)
-     struct candidate *candidates;
-     int n;
-{
-  int i;
-
-  cp_error_at ("candidates are: %D", candidates[0].function);
-  for (i = 1; i < n; i++)
-    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.
-
-   Member functions always take their class variable
-   as a pointer.
-
-   INSTANCE is a class instance.
-
-   NAME is the name of the method desired, usually an IDENTIFIER_NODE.
-
-   PARMS help to figure out what that NAME really refers to.
-
-   BASETYPE_PATH, if non-NULL, contains a chain from the type of INSTANCE
-   down to the real instance type to use for access checking.  We need this
-   information to get protected accesses correct.  This parameter is used
-   by build_member_call.
-
-   FLAGS is the logical disjunction of zero or more LOOKUP_
-   flags.  See cp-tree.h for more info.
-
-   If this is all OK, calls build_function_call with the resolved
-   member function.
-
-   This function must also handle being called to perform
-   initialization, promotion/coercion of arguments, and
-   instantiation of default parameters.
-
-   Note that NAME may refer to an instance variable name.  If
-   `operator()()' is defined for the type of that field, then we return
-   that result.  */
-
-tree
-build_method_call (instance, name, parms, basetype_path, flags)
-     tree instance, name, parms, basetype_path;
-     int flags;
-{
-  register tree function, fntype, value_type;
-  register tree basetype, save_basetype;
-  register tree baselink, result, parmtypes;
-  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;
-  int static_call_context = 0;
-  tree found_fns = NULL_TREE;
-
-  /* Keep track of `const' and `volatile' objects.  */
-  int constp, volatilep;
-
-#ifdef GATHER_STATISTICS
-  n_build_method_call++;
-#endif
-
-  if (instance == error_mark_node
-      || name == error_mark_node
-      || parms == error_mark_node
-      || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node))
-    return error_mark_node;
-
-  if (processing_template_decl)
-    {
-      if (TREE_CODE (name) == BIT_NOT_EXPR)
-       {
-         tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 1);
-         name = build_min_nt (BIT_NOT_EXPR, type);
-       }
-
-      return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
-    }
-
-  /* This is the logic that magically deletes the second argument to
-     operator delete, if it is not needed.  */
-  if (name == ansi_opname[(int) DELETE_EXPR] && list_length (parms)==2)
-    {
-      tree save_last = TREE_CHAIN (parms);
-      tree result;
-      /* get rid of unneeded argument */
-      TREE_CHAIN (parms) = NULL_TREE;
-      result = build_method_call (instance, name, parms, basetype_path,
-                                 (LOOKUP_SPECULATIVELY|flags)
-                                 &~LOOKUP_COMPLAIN);
-      /* If it finds a match, return it.  */
-      if (result)
-       return build_method_call (instance, name, parms, basetype_path, flags);
-      /* If it doesn't work, two argument delete must work */
-      TREE_CHAIN (parms) = save_last;
-    }
-  /* We already know whether it's needed or not for vec delete.  */
-  else if (name == ansi_opname[(int) VEC_DELETE_EXPR]
-          && TYPE_LANG_SPECIFIC (TREE_TYPE (instance))
-          && ! TYPE_VEC_DELETE_TAKES_SIZE (TREE_TYPE (instance)))
-    TREE_CHAIN (parms) = NULL_TREE;
-
-  if (TREE_CODE (name) == BIT_NOT_EXPR)
-    {
-      flags |= LOOKUP_DESTRUCTOR;
-      name = TREE_OPERAND (name, 0);
-      if (parms)
-       error ("destructors take no parameters");
-      basetype = TREE_TYPE (instance);
-      if (TREE_CODE (basetype) == REFERENCE_TYPE)
-       basetype = TREE_TYPE (basetype);
-      if (! (name == basetype
-            || (IS_AGGR_TYPE (basetype)
-                && name == constructor_name (basetype))
-            || basetype == get_type_value (name)))
-       {
-         cp_error ("destructor name `~%D' does not match type `%T' of expression",
-                   name, basetype);
-         return cp_convert (void_type_node, instance);
-       }
-
-      if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype)))
-       return cp_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),
-                          instance_ptr, integer_two_node,
-                          LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
-    }
-
-  if (flag_ansi_overloading)
-    return build_new_method_call (instance, name, parms, basetype_path, flags);
-
-  {
-    char *xref_name;
-    
-    /* Initialize name for error reporting.  */
-    if (IDENTIFIER_OPNAME_P (name) && ! IDENTIFIER_TYPENAME_P (name))
-      {
-       char *p = operator_name_string (name);
-       xref_name = (char *)alloca (strlen (p) + 10);
-       sprintf (xref_name, "operator %s", p);
-      }
-    else if (TREE_CODE (name) == SCOPE_REF)
-      xref_name = IDENTIFIER_POINTER (TREE_OPERAND (name, 1));
-    else
-      xref_name = IDENTIFIER_POINTER (name);
-
-    GNU_xref_call (current_function_decl, xref_name);
-  }
-
-  if (instance == NULL_TREE)
-    {
-      basetype = NULL_TREE;
-      /* Check cases where this is really a call to raise
-        an exception.  */
-      if (current_class_type && TREE_CODE (name) == IDENTIFIER_NODE)
-       {
-         basetype = purpose_member (name, CLASSTYPE_TAGS (current_class_type));
-         if (basetype)
-           basetype = TREE_VALUE (basetype);
-       }
-      else if (TREE_CODE (name) == SCOPE_REF
-              && TREE_CODE (TREE_OPERAND (name, 0)) == IDENTIFIER_NODE)
-       {
-         if (! is_aggr_typedef (TREE_OPERAND (name, 0), 1))
-           return error_mark_node;
-         basetype = purpose_member (TREE_OPERAND (name, 1),
-                                    CLASSTYPE_TAGS (IDENTIFIER_TYPE_VALUE (TREE_OPERAND (name, 0))));
-         if (basetype)
-           basetype = TREE_VALUE (basetype);
-       }
-
-      if (basetype != NULL_TREE)
-       ;
-      /* call to a constructor...  */
-      else if (basetype_path)
-       {
-         basetype = BINFO_TYPE (basetype_path);
-         if (name == TYPE_IDENTIFIER (basetype))
-           name = ctor_identifier;
-       }
-      else if (IDENTIFIER_HAS_TYPE_VALUE (name))
-       {
-         basetype = IDENTIFIER_TYPE_VALUE (name);
-         name = ctor_identifier;
-       }
-      else
-       {
-         tree typedef_name = lookup_name (name, 1);
-         if (typedef_name && TREE_CODE (typedef_name) == TYPE_DECL)
-           {
-             /* Canonicalize the typedef name.  */
-             basetype = TREE_TYPE (typedef_name);
-             name = ctor_identifier;
-           }
-         else
-           {
-             cp_error ("no constructor named `%T' in scope",
-                       name);
-             return error_mark_node;
-           }
-       }
-
-      if (! IS_AGGR_TYPE (basetype))
-       {
-       non_aggr_error:
-         if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node)
-           cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
-                     name, instance, basetype);
-
-         return error_mark_node;
-       }
-    }
-  else if (instance == current_class_ref || instance == current_class_ptr)
-    {
-      /* When doing initialization, we side-effect the TREE_TYPE of
-        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.  */
-      if (TYPE_VIRTUAL_P (basetype)
-         && !(flags & LOOKUP_NONVIRTUAL))
-       need_vtbl = (dtor_label || ctor_label)
-         ? unneeded : maybe_needed;
-
-      /* If `this' is a signature pointer and `name' is not a constructor,
-        we are calling a signature member function.  In that case, set the
-        `basetype' to the signature type and dereference the `optr' field.  */
-      if (IS_SIGNATURE_POINTER (basetype)
-         && TYPE_IDENTIFIER (basetype) != name)
-       {
-         basetype = SIGNATURE_TYPE (basetype);
-         instance_ptr = instance;
-         basetype_path = TYPE_BINFO (basetype);
-       }
-      else
-       {
-         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);
-
-      if (result)
-       return result;
-    }
-  else if (TREE_CODE (instance) == RESULT_DECL)
-    {
-      basetype = TREE_TYPE (instance);
-      /* Should we ever have to make a virtual function reference
-        from a RESULT_DECL, know that it must be of fixed type
-        within the scope of this function.  */
-      if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype))
-       need_vtbl = maybe_needed;
-      instance_ptr = build1 (ADDR_EXPR, build_pointer_type (basetype), instance);
-    }
-  else
-    {
-      /* The MAIN_VARIANT of the type that `instance_ptr' winds up being.  */
-      tree inst_ptr_basetype;
-
-      static_call_context
-       = (TREE_CODE (instance) == INDIRECT_REF
-          && 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);
-
-      if (TREE_CODE (basetype) == REFERENCE_TYPE)
-       {
-         basetype = TREE_TYPE (basetype);
-         if (! IS_AGGR_TYPE (basetype))
-           goto non_aggr_error;
-         /* Call to convert not needed because we are remaining
-            within the same type.  */
-         instance_ptr = build1 (NOP_EXPR, build_pointer_type (basetype),
-                                instance);
-         inst_ptr_basetype = TYPE_MAIN_VARIANT (basetype);
-       }
-      else
-       {
-         if (! IS_AGGR_TYPE (basetype)
-             && ! (TYPE_LANG_SPECIFIC (basetype)
-                   && (IS_SIGNATURE_POINTER (basetype)
-                       || IS_SIGNATURE_REFERENCE (basetype))))
-           goto non_aggr_error;
-
-         /* 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);
-
-         basetype = complete_type (basetype);
-
-         if ((IS_SIGNATURE (basetype)
-              && (instance_ptr = instance))
-             || (lvalue_p (instance)
-                 && (instance_ptr = build_unary_op (ADDR_EXPR, instance, 0)))
-             || (instance_ptr = unary_complex_lvalue (ADDR_EXPR, instance)))
-           {
-             if (instance_ptr == error_mark_node)
-               return error_mark_node;
-           }
-         else if (TREE_CODE (instance) == NOP_EXPR
-                  || TREE_CODE (instance) == CONSTRUCTOR)
-           {
-             /* A cast is not an lvalue.  Initialize a fresh temp
-                with the value we are casting from, and proceed with
-                that temporary.  We can't cast to a reference type,
-                so that simplifies the initialization to something
-                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, flags);
-             else
-               {
-                 store_init_value (temp, instance);
-                 expand_decl_init (temp);
-               }
-             instance = temp;
-             instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
-           }
-         else
-           {
-             if (TREE_CODE (instance) != CALL_EXPR)
-               my_friendly_abort (125);
-             if (TYPE_NEEDS_CONSTRUCTING (basetype))
-               instance = build_cplus_new (basetype, instance);
-             else
-               {
-                 instance = get_temp_name (basetype, 0);
-                 TREE_ADDRESSABLE (instance) = 1;
-               }
-             instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
-           }
-         /* @@ Should we call comp_target_types here?  */
-         if (IS_SIGNATURE (basetype))
-           inst_ptr_basetype = basetype;
-         else
-           inst_ptr_basetype = TREE_TYPE (TREE_TYPE (instance_ptr));
-         if (TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (inst_ptr_basetype))
-           basetype = inst_ptr_basetype;
-         else
-           {
-             instance_ptr = cp_convert (build_pointer_type (basetype), instance_ptr);
-             if (instance_ptr == error_mark_node)
-               return error_mark_node;
-           }
-       }
-
-      /* After converting `instance_ptr' above, `inst_ptr_basetype' was
-        not updated, so we use `basetype' instead.  */
-      if (basetype_path == NULL_TREE
-         && IS_SIGNATURE (basetype))
-       basetype_path = TYPE_BINFO (basetype);
-      else if (basetype_path == NULL_TREE
-              || (BINFO_TYPE (basetype_path)
-                  != TYPE_MAIN_VARIANT (inst_ptr_basetype)))
-       basetype_path = TYPE_BINFO (inst_ptr_basetype);
-
-      result = build_field_call (basetype_path, instance_ptr, name, parms);
-      if (result)
-       return result;
-
-      if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype))
-       {
-         if (TREE_SIDE_EFFECTS (instance_ptr))
-           {
-             /* This action is needed because the instance is needed
-                for providing the base of the virtual function table.
-                Without using a SAVE_EXPR, the function we are building
-                may be called twice, or side effects on the instance
-                variable (such as a post-increment), may happen twice.  */
-             instance_ptr = save_expr (instance_ptr);
-             instance = build_indirect_ref (instance_ptr, NULL_PTR);
-           }
-         else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
-           {
-             /* This happens when called for operator new ().  */
-             instance = build_indirect_ref (instance, NULL_PTR);
-           }
-
-         need_vtbl = maybe_needed;
-       }
-    }
-
-  if (save_name == ctor_identifier)
-    save_name = TYPE_IDENTIFIER (basetype);
-
-  if (TYPE_SIZE (complete_type (basetype)) == 0)
-    {
-      /* This is worth complaining about, I think.  */
-      cp_error ("cannot lookup method in incomplete type `%T'", basetype);
-      return error_mark_node;
-    }
+  if (! IS_AGGR_TYPE (outer_type))
+    return NULL_TREE;
 
-  save_basetype = TYPE_MAIN_VARIANT (basetype);
+  /* Look for member classes or enums.  */
+  tmp = find_scoped_type (outer_type, inner_name, inner_type);
 
-  parmtypes = default_parm_conversions (parms, &last);
-  if (parmtypes == error_mark_node)
+  /* If it's not a type in this class, then go down into the
+     base classes and search there.  */
+  if (! tmp && TYPE_BINFO (outer_type))
     {
-      return error_mark_node;
-    }
+      tree binfos = TYPE_BINFO_BASETYPES (outer_type);
+      int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
 
-  if (instance && IS_SIGNATURE (basetype))
-    {
-      /* @@ Should this be the constp/volatilep flags for the optr field
-        of the signature pointer?  */
-      constp = TYPE_READONLY (basetype);
-      volatilep = TYPE_VOLATILE (basetype);
-      parms = expr_tree_cons (NULL_TREE, instance_ptr, parms);
-    }
-  else if (instance)
-    {
-      /* TREE_READONLY (instance) fails for references.  */
-      constp = TYPE_READONLY (TREE_TYPE (TREE_TYPE (instance_ptr)));
-      volatilep = TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (instance_ptr)));
-      parms = expr_tree_cons (NULL_TREE, instance_ptr, parms);
-    }
-  else
-    {
-      /* Raw constructors are always in charge.  */
-      if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)
-         && ! (flags & LOOKUP_HAS_IN_CHARGE))
+      for (i = 0; i < n_baselinks; i++)
        {
-         flags |= LOOKUP_HAS_IN_CHARGE;
-         parms = expr_tree_cons (NULL_TREE, integer_one_node, parms);
-         parmtypes = scratch_tree_cons (NULL_TREE, integer_type_node, parmtypes);
+         tree base_binfo = TREE_VEC_ELT (binfos, i);
+         tmp = resolve_scope_to_name (BINFO_TYPE (base_binfo), inner_stuff);
+         if (tmp)
+           return tmp;
        }
-
-      constp = 0;
-      volatilep = 0;
-      instance_ptr = build_int_2 (0, 0);
-      TREE_TYPE (instance_ptr) = build_pointer_type (basetype);
-      parms = expr_tree_cons (NULL_TREE, instance_ptr, parms);
+      tmp = NULL_TREE;
     }
 
-  parmtypes = scratch_tree_cons (NULL_TREE, TREE_TYPE (instance_ptr), parmtypes);
+  return tmp;
+}
 
-  if (last == NULL_TREE)
-    last = parmtypes;
+/* Build a method call of the form `EXP->SCOPES::NAME (PARMS)'.
+   This is how virtual function calls are avoided.  */
 
-  /* Look up function name in the structure type definition.  */
+tree
+build_scoped_method_call (exp, basetype, name, parms)
+     tree exp, basetype, name, parms;
+{
+  /* Because this syntactic form does not allow
+     a pointer to a base class to be `stolen',
+     we need not protect the derived->base conversion
+     that happens here.
+     
+     @@ But we do have to check access privileges later.  */
+  tree binfo, decl;
+  tree type = TREE_TYPE (exp);
 
-  /* FIXME Axe most of this now?  */
-  if ((IDENTIFIER_HAS_TYPE_VALUE (name)
-       && ! IDENTIFIER_OPNAME_P (name)
-       && IS_AGGR_TYPE (IDENTIFIER_TYPE_VALUE (name)))
-      || name == constructor_name (basetype)
-      || name == ctor_identifier)
-    {
-      tree tmp = NULL_TREE;
-      if (IDENTIFIER_TYPE_VALUE (name) == basetype
-         || name == constructor_name (basetype)
-         || name == ctor_identifier)
-       tmp = TYPE_BINFO (basetype);
-      else
-       tmp = get_binfo (IDENTIFIER_TYPE_VALUE (name), basetype, 0);
-      
-      if (tmp != NULL_TREE)
-       {
-         name_kind = "constructor";
-         
-         if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)
-             && ! (flags & LOOKUP_HAS_IN_CHARGE))
-           {
-             /* Constructors called for initialization
-                only are never in charge.  */
-             tree tmplist;
-             
-             flags |= LOOKUP_HAS_IN_CHARGE;
-             tmplist = expr_tree_cons (NULL_TREE, integer_zero_node,
-                                  TREE_CHAIN (parms));
-             TREE_CHAIN (parms) = tmplist;
-             tmplist = scratch_tree_cons (NULL_TREE, integer_type_node, TREE_CHAIN (parmtypes));
-             TREE_CHAIN (parmtypes) = tmplist;
-           }
-         basetype = BINFO_TYPE (tmp);
-       }
-      else
-       name_kind = "method";
-    }
-  else
-    name_kind = "method";
-  
-  if (basetype_path == NULL_TREE
-      || BINFO_TYPE (basetype_path) != TYPE_MAIN_VARIANT (basetype))
-    basetype_path = TYPE_BINFO (basetype);
-  result = lookup_fnfields (basetype_path, name,
-                           (flags & LOOKUP_COMPLAIN));
-  if (result == error_mark_node)
+  if (type == error_mark_node
+      || basetype == error_mark_node)
     return error_mark_node;
 
-  for (pass = 0; pass < 2; pass++)
-    {
-      struct candidate *candidates = 0;
-      struct candidate *cp = 0;
-      int len = 0;
-      unsigned best = 1;
-
-      baselink = result;
-
-      if (pass > 0)
-       {
-         candidates
-           = (struct candidate *) alloca ((ever_seen+1)
-                                          * sizeof (struct candidate));
-         bzero ((char *) candidates, (ever_seen + 1) * sizeof (struct candidate));
-         cp = candidates;
-         len = list_length (parms);
-         ever_seen = 0;
-
-         /* First see if a global function has a shot at it.  */
-         if (flags & LOOKUP_GLOBAL)
-           {
-             tree friend_parms;
-             tree parm = instance_ptr;
-
-             if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE)
-               parm = convert_from_reference (parm);
-             else if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)
-               parm = build_indirect_ref (parm, "friendifying parms (compiler error)");
-             else
-               my_friendly_abort (167);
-
-             friend_parms = expr_tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));
-
-             cp->h_len = len;
-             cp->harshness = (struct harshness_code *)
-               alloca ((len + 1) * sizeof (struct harshness_code));
-
-             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.  */
-             if (TREE_CODE (result) == CALL_EXPR)
-               return result;
-
-             while ((cp->h.code & EVIL_CODE) == 0)
-               {
-                 /* non-standard uses: set the field to 0 to indicate
-                    we are using a non-member function.  */
-                 cp->u.field = 0;
-                 if (cp->harshness[len].distance == 0
-                     && cp->h.code < best)
-                   best = cp->h.code;
-                 cp += 1;
-               }
-           }
-       }
-
-      if (baselink)
-       {
-         /* We have a hit (of sorts). If the parameter list is
-            "error_mark_node", or some variant thereof, it won't
-            match any methods.  Since we have verified that the is
-            some method vaguely matching this one (in name at least),
-            silently return.
-            
-            Don't stop for friends, however.  */
-         basetype_path = TREE_PURPOSE (baselink);
-
-         function = TREE_VALUE (baselink);
-         if (TREE_CODE (basetype_path) == TREE_LIST)
-           basetype_path = TREE_VALUE (basetype_path);
-         basetype = BINFO_TYPE (basetype_path);
-
-         for (; function; function = DECL_CHAIN (function))
-           {
-#ifdef GATHER_STATISTICS
-             n_inner_fields_searched++;
-#endif
-             ever_seen++;
-             if (pass > 0)
-               found_fns = scratch_tree_cons (NULL_TREE, function, found_fns);
-
-             /* Not looking for friends here.  */
-             if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE
-                 && ! DECL_STATIC_FUNCTION_P (function))
-               continue;
-
-             if (pass > 0)
-               {
-                 tree these_parms = parms;
-
-#ifdef GATHER_STATISTICS
-                 n_inner_fields_searched++;
-#endif
-                 cp->h_len = len;
-                 cp->harshness = (struct harshness_code *)
-                   alloca ((len + 1) * sizeof (struct harshness_code));
-
-                 if (DECL_STATIC_FUNCTION_P (function))
-                   these_parms = TREE_CHAIN (these_parms);
-                 compute_conversion_costs (function, these_parms, cp, len);
-
-                 if ((cp->h.code & EVIL_CODE) == 0)
-                   {
-                     cp->u.field = function;
-                     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))
-                       continue;
-
-                     cp++;
-                   }
-               }
-           }
-       }
-
-      if (pass == 0)
-       {
-         tree igv = lookup_name_nonclass (name);
-
-         /* No exact match could be found.  Now try to find match
-            using default conversions.  */
-         if ((flags & LOOKUP_GLOBAL) && igv)
-           {
-             if (TREE_CODE (igv) == FUNCTION_DECL)
-               ever_seen += 1;
-             else if (TREE_CODE (igv) == TREE_LIST)
-               ever_seen += count_functions (igv);
-           }
-
-         if (ever_seen == 0)
-           {
-             if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN))
-                 == LOOKUP_SPECULATIVELY)
-               return NULL_TREE;
-             
-             TREE_CHAIN (last) = void_list_node;
-             if (flags & LOOKUP_GLOBAL)
-               cp_error ("no global or member function `%D(%A)' defined",
-                         save_name, parmtypes);
-             else
-               cp_error ("no member function `%T::%D(%A)' defined",
-                         save_basetype, save_name, TREE_CHAIN (parmtypes));
-             return error_mark_node;
-           }
-         continue;
-       }
-
-      if (cp - candidates != 0)
-       {
-         /* Rank from worst to best.  Then cp will point to best one.
-            Private fields have their bits flipped.  For unsigned
-            numbers, this should make them look very large.
-            If the best alternate has a (signed) negative value,
-            then all we ever saw were private members.  */
-         if (cp - candidates > 1)
-           {
-             int n_candidates = cp - candidates;
-             extern int warn_synth;
-             TREE_VALUE (parms) = instance_ptr;
-             cp = ideal_candidate (candidates, n_candidates, len);
-             if (cp == (struct candidate *)0)
-               {
-                 if (flags & LOOKUP_COMPLAIN)
-                   {
-                     TREE_CHAIN (last) = void_list_node;
-                     cp_error ("call of overloaded %s `%D(%A)' is ambiguous",
-                               name_kind, save_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)
-           {
-             if (flags & LOOKUP_COMPLAIN)
-               cp_error ("ambiguous type conversion requested for %s `%D'",
-                         name_kind, save_name);
-             return error_mark_node;
-           }
-         else
-           cp--;
-
-         /* The global function was the best, so use it.  */
-         if (cp->u.field == 0)
-           {
-             /* We must convert the instance pointer into a reference type.
-                Global overloaded functions can only either take
-                aggregate objects (which come for free from references)
-                or reference data types anyway.  */
-             TREE_VALUE (parms) = copy_node (instance_ptr);
-             TREE_TYPE (TREE_VALUE (parms)) = build_reference_type (TREE_TYPE (TREE_TYPE (instance_ptr)));
-             return build_function_call (cp->function, parms);
-           }
-
-         function = cp->function;
-         basetype_path = cp->basetypes;
-         if (! DECL_STATIC_FUNCTION_P (function))
-           TREE_VALUE (parms) = cp->arg;
-         goto found_and_maybe_warn;
-       }
-
-      if (flags & (LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY))
-       {
-         if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN))
-             == LOOKUP_SPECULATIVELY)
-           return NULL_TREE;
-
-         if (DECL_STATIC_FUNCTION_P (cp->function))
-           parms = TREE_CHAIN (parms);
-         if (ever_seen)
-           {
-             if (flags & LOOKUP_SPECULATIVELY)
-               return NULL_TREE;
-             if (static_call_context
-                 && TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE)
-               cp_error ("object missing in call to `%D'", cp->function);
-             else if (ever_seen > 1)
-               {
-                 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))),
-                           save_name, TREE_CHAIN (parmtypes),
-                           TREE_TYPE (TREE_TYPE (instance_ptr)));
-                 TREE_CHAIN (last) = NULL_TREE;
-                 print_candidates (found_fns);
-               }
-             else
-               report_type_mismatch (cp, parms, name_kind);
-             return error_mark_node;
-           }
-
-         if ((flags & (LOOKUP_SPECULATIVELY|LOOKUP_COMPLAIN))
-             == LOOKUP_COMPLAIN)
-           {
-             cp_error ("%T has no method named %D", save_basetype, save_name);
-             return error_mark_node;
-           }
-         return NULL_TREE;
-       }
-      continue;
-
-    found_and_maybe_warn:
-      if ((cp->harshness[0].code & CONST_CODE)
-         /* 12.1p2: Constructors can be called for const objects.  */
-         && ! DECL_CONSTRUCTOR_P (cp->function))
-       {
-         if (flags & LOOKUP_COMPLAIN)
-           {
-             cp_error_at ("non-const member function `%D'", cp->function);
-             error ("called for const object at this point in file");
-           }
-         /* Not good enough for a match.  */
-         else
-           return error_mark_node;
-       }
-      goto found;
-    }
-  /* Silently return error_mark_node.  */
-  return error_mark_node;
-
- found:
-  if (flags & LOOKUP_PROTECT)
-    access = compute_access (basetype_path, function);
-
-  if (access == access_private_node)
-    {
-      if (flags & LOOKUP_COMPLAIN)
-       {
-         cp_error_at ("%s `%+#D' is %s", name_kind, function, 
-                      TREE_PRIVATE (function) ? "private"
-                      : "from private base class");
-         error ("within this context");
-       }
-      return error_mark_node;
-    }
-  else if (access == access_protected_node)
-    {
-      if (flags & LOOKUP_COMPLAIN)
-       {
-         cp_error_at ("%s `%+#D' %s", name_kind, function,
-                      TREE_PROTECTED (function) ? "is protected"
-                      : "has protected accessibility");
-         error ("within this context");
-       }
-      return error_mark_node;
-    }
-
-  /* From here on down, BASETYPE is the type that INSTANCE_PTR's
-     type (if it exists) is a pointer to.  */
-
-  if (DECL_ABSTRACT_VIRTUAL_P (function)
-      && 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))
+  if (processing_template_decl)
     {
-      if (static_call_context)
+      if (TREE_CODE (name) == BIT_NOT_EXPR)
        {
-         cp_error ("cannot call signature member function `%T::%D' without signature pointer/reference",
-                   basetype, save_name);
-         return error_mark_node;
+         tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 0);
+         if (type)
+           name = build_min_nt (BIT_NOT_EXPR, type);
        }
-      return build_signature_method_call (function, parms);
+      name = build_min_nt (SCOPE_REF, basetype, name);
+      return build_min_nt (METHOD_CALL_EXPR, name, exp, parms, NULL_TREE);
     }
 
-  function = DECL_MAIN_VARIANT (function);
-  mark_used (function);
-
-  fntype = TREE_TYPE (function);
-  if (TREE_CODE (fntype) == POINTER_TYPE)
-    fntype = TREE_TYPE (fntype);
-  basetype = DECL_CLASS_CONTEXT (function);
+  if (TREE_CODE (type) == REFERENCE_TYPE)
+    type = TREE_TYPE (type);
 
-  /* If we are referencing a virtual function from an object
-     of effectively static type, then there is no need
-     to go through the virtual function table.  */
-  if (need_vtbl == maybe_needed)
+  if (TREE_CODE (basetype) == TREE_VEC)
     {
-      int fixed_type = resolves_to_fixed_type_p (instance, 0);
-
-      if (all_virtual == 1
-         && DECL_VINDEX (function)
-         && may_be_remote (basetype))
-       need_vtbl = needed;
-      else if (DECL_VINDEX (function))
-       need_vtbl = fixed_type ? unneeded : needed;
-      else
-       need_vtbl = not_needed;
+      binfo = basetype;
+      basetype = BINFO_TYPE (binfo);
     }
+  else
+    binfo = NULL_TREE;
 
-  if (TREE_CODE (fntype) == METHOD_TYPE && static_call_context
-      && !DECL_CONSTRUCTOR_P (function))
+  /* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note
+     that explicit ~int is caught in the parser; this deals with typedefs
+     and template parms.  */
+  if (TREE_CODE (name) == BIT_NOT_EXPR && ! IS_AGGR_TYPE (basetype))
     {
-      /* 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)
-           {
-             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
-        function.  */
-      else if (DECL_LANG_SPECIFIC (function)
-              && !DECL_STATIC_FUNCTION_P (function))
-       {
-         cp_error ("cannot call member function `%D' without object",
-                   function);
-         return error_mark_node;
-       }
+      if (type != basetype)
+       cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')",
+                 exp, basetype, type);
+      name = TREE_OPERAND (name, 0);
+      if (basetype != name && basetype != get_type_value (name))
+       cp_error ("qualified type `%T' does not match destructor name `~%T'",
+                 basetype, name);
+      return cp_convert (void_type_node, exp);
     }
 
-  value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node;
+  if (! is_aggr_type (basetype, 1))
+    return error_mark_node;
 
-  if (TYPE_SIZE (complete_type (value_type)) == 0)
+  if (! IS_AGGR_TYPE (type))
     {
-      if (flags & LOOKUP_COMPLAIN)
-       incomplete_type_error (0, value_type);
+      cp_error ("base object `%E' of scoped method call is of non-aggregate type `%T'",
+               exp, type);
       return error_mark_node;
     }
 
-  if (DECL_STATIC_FUNCTION_P (function))
-    parms = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
-                              TREE_CHAIN (parms), function, LOOKUP_NORMAL);
-  else if (need_vtbl == unneeded)
+  if (! binfo)
     {
-      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))
-       {
-         basetype = DECL_CLASS_CONTEXT (function);
-         instance_ptr = convert_pointer_to (basetype, instance_ptr);
-         instance = build_indirect_ref (instance_ptr, NULL_PTR);
-       }
-      parms = expr_tree_cons (NULL_TREE, instance_ptr,
-                        convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, sub_flags));
+      binfo = get_binfo (basetype, type, 1);
+      if (binfo == error_mark_node)
+       return error_mark_node;
+      if (! binfo)
+       error_not_base_type (basetype, type);
     }
-  else
+
+  if (binfo)
     {
-      if ((flags & LOOKUP_NONVIRTUAL) == 0)
-       basetype = DECL_CONTEXT (function);
+      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);
 
-      /* First parm could be integer_zerop with casts like
-        ((Object*)0)->Object::IsA()  */
-      if (!integer_zerop (TREE_VALUE (parms)))
+      /* Call to a destructor.  */
+      if (TREE_CODE (name) == BIT_NOT_EXPR)
        {
-         /* Since we can't have inheritance with a union, doing get_binfo
-            on it won't work.  We do all the convert_pointer_to_real
-            stuff to handle MI correctly...for unions, that's not
-            an issue, so we must short-circuit that extra work here.  */
-         tree tmp = TREE_TYPE (TREE_TYPE (TREE_VALUE (parms)));
-         if (tmp != NULL_TREE && TREE_CODE (tmp) == UNION_TYPE)
-           instance_ptr = TREE_VALUE (parms);
-         else
-           {
-             tree binfo = get_binfo (basetype,
-                                     TREE_TYPE (TREE_TYPE (TREE_VALUE (parms))),
-                                     0);
-             instance_ptr = convert_pointer_to_real (binfo, TREE_VALUE (parms));
-           }
-         instance_ptr
-           = convert_pointer_to (build_type_variant (basetype,
-                                                     constp, volatilep),
-                                 instance_ptr);
-
-         if (TREE_CODE (instance_ptr) == COND_EXPR)
+         /* Explicit call to destructor.  */
+         name = TREE_OPERAND (name, 0);
+         if (! (name == TYPE_MAIN_VARIANT (TREE_TYPE (decl))
+                || name == constructor_name (TREE_TYPE (decl))
+                || TREE_TYPE (decl) == get_type_value (name)))
            {
-             instance_ptr = save_expr (instance_ptr);
-             instance = build_indirect_ref (instance_ptr, NULL_PTR);
+             cp_error
+               ("qualified type `%T' does not match destructor name `~%T'",
+                TREE_TYPE (decl), name);
+             return error_mark_node;
            }
-         else if (TREE_CODE (instance_ptr) == NOP_EXPR
-                  && TREE_CODE (TREE_OPERAND (instance_ptr, 0)) == ADDR_EXPR
-                  && TREE_OPERAND (TREE_OPERAND (instance_ptr, 0), 0) == instance)
-           ;
-         /* The call to `convert_pointer_to' may return error_mark_node.  */
-         else if (instance_ptr == error_mark_node)
-           return instance_ptr;
-         else if (instance == NULL_TREE
-                  || TREE_CODE (instance) != INDIRECT_REF
-                  || TREE_OPERAND (instance, 0) != instance_ptr)
-           instance = build_indirect_ref (instance_ptr, NULL_PTR);
+         if (! TYPE_HAS_DESTRUCTOR (TREE_TYPE (decl)))
+           return cp_convert (void_type_node, exp);
+         
+         return build_delete (TREE_TYPE (decl), decl, integer_two_node,
+                              LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR,
+                              0);
        }
-      parms = expr_tree_cons (NULL_TREE, instance_ptr,
-                        convert_arguments (NULL_TREE, TREE_CHAIN (TYPE_ARG_TYPES (fntype)), TREE_CHAIN (parms), function, LOOKUP_NORMAL));
+
+      /* Call to a method.  */
+      return build_method_call (decl, name, parms, binfo,
+                               LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);
     }
+  return error_mark_node;
+}
 
-  if (parms == error_mark_node
-      || (parms && TREE_CHAIN (parms) == error_mark_node))
-    return error_mark_node;
+/* 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);
 
-  if (need_vtbl == needed)
+  /* We have to do these by hand to avoid real pointer to member
+     functions.  */
+  if (TREE_CODE (type) == METHOD_TYPE)
     {
-      function = build_vfn_ref (&TREE_VALUE (parms), instance,
-                               DECL_VINDEX (function));
-      TREE_TYPE (function) = build_pointer_type (fntype);
-    }
+      tree addr;
 
-  if (TREE_CODE (function) == FUNCTION_DECL)
-    GNU_xref_call (current_function_decl,
-                  IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)));
+      type = build_pointer_type (type);
 
-  result = build_call (function, value_type, parms);
-  if (IS_AGGR_TYPE (value_type))
-    result = build_cplus_new (value_type, result);
-  result = convert_from_reference (result);
-  return result;
-}
+      if (mark_addressable (function) == 0)
+       return error_mark_node;
 
-/* Similar to `build_method_call', but for overloaded non-member functions.
-   The name of this function comes through NAME.  The name depends
-   on PARMS.
+      addr = build1 (ADDR_EXPR, type, function);
 
-   Note that this function must handle simple `C' promotions,
-   as well as variable numbers of arguments (...), and
-   default arguments to boot.
+      /* Address of a static or external variable or function counts
+        as a constant */
+      if (staticp (function))
+       TREE_CONSTANT (addr) = 1;
 
-   If the overloading is successful, we return a tree node which
-   contains the call to the function.
+      function = addr;
+    }
+  else
+    function = default_conversion (function);
 
-   If overloading produces candidates which are probable, but not definite,
-   we hold these candidates.  If FINAL_CP is non-zero, then we are free
-   to assume that final_cp points to enough storage for all candidates that
-   this function might generate.  The `harshness' array is preallocated for
-   the first candidate, but not for subsequent ones.
+  return function;
+}
 
-   Note that the DECL_RTL of FUNCTION must be made to agree with this
-   function's new name.  */
+/* 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_overload_call_real (fnname, parms, flags, final_cp, require_complete)
-     tree fnname, parms;
-     int flags;
-     struct candidate *final_cp;
-     int require_complete;
+build_call (function, result_type, parms)
+     tree function, result_type, parms;
 {
-  /* must check for overloading here */
-  tree functions, function;
-  tree parmtypes, last;
-  register tree outer;
-  int length;
-  int parmlength = list_length (parms);
-
-  struct candidate *candidates, *cp;
+  int is_constructor = 0;
 
-  if (final_cp)
-    {
-      final_cp[0].h.code = 0;
-      final_cp[0].h.distance = 0;
-      final_cp[0].function = 0;
-      /* end marker.  */
-      final_cp[1].h.code = EVIL_CODE;
-    }
+  function = build_addr_func (function);
 
-  parmtypes = default_parm_conversions (parms, &last);
-  if (parmtypes == error_mark_node)
+  if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
     {
-      if (final_cp)
-       final_cp->h.code = EVIL_CODE;
+      sorry ("unable to call pointer to member function here");
       return error_mark_node;
     }
 
-  if (last)
-    TREE_CHAIN (last) = void_list_node;
-  else
-    parmtypes = void_list_node;
-
-  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 (TREE_CODE (function) == ADDR_EXPR
+      && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
+      && DECL_CONSTRUCTOR_P (TREE_OPERAND (function, 0)))
+    is_constructor = 1;
 
-  if (functions == NULL_TREE)
-    {
-      if (flags & LOOKUP_SPECULATIVELY)
-       return NULL_TREE;
-      if (flags & LOOKUP_COMPLAIN)
-       error ("only member functions apply");
-      if (final_cp)
-       final_cp->h.code = EVIL_CODE;
-      return error_mark_node;
-    }
+  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;
+}
 
-  if (TREE_CODE (functions) == FUNCTION_DECL && ! IDENTIFIER_OPNAME_P (fnname))
-    {
-      functions = DECL_MAIN_VARIANT (functions);
-      if (final_cp)
-       {
-         /* We are just curious whether this is a viable alternative or
-             not.  */
-         compute_conversion_costs (functions, parms, final_cp, parmlength);
-         return functions;
-       }
-      else
-       return build_function_call_real (functions, parms, 1, flags);
-    }
+/* Build something of the form ptr->method (args)
+   or object.method (args).  This can also build
+   calls to constructors, and find friends.
 
-  if (TREE_CODE (functions) == TREE_LIST
-      && TREE_VALUE (functions) == NULL_TREE)
-    {
-      if (flags & LOOKUP_SPECULATIVELY)
-       return NULL_TREE;
-      
-      if (flags & LOOKUP_COMPLAIN)
-       cp_error ("function `%D' declared overloaded, but no instances of that function declared",
-                 TREE_PURPOSE (functions));
-      if (final_cp)
-       final_cp->h.code = EVIL_CODE;
-      return error_mark_node;
-    }
+   Member functions always take their class variable
+   as a pointer.
 
-  length = count_functions (functions);
-  
-  if (final_cp)
-    candidates = final_cp;
-  else
-    {
-      candidates
-       = (struct candidate *)alloca ((length+1) * sizeof (struct candidate));
-      bzero ((char *) candidates, (length + 1) * sizeof (struct candidate));
-    }
+   INSTANCE is a class instance.
 
-  cp = candidates;
+   NAME is the name of the method desired, usually an IDENTIFIER_NODE.
 
-  my_friendly_assert (is_overloaded_fn (functions), 169);
+   PARMS help to figure out what that NAME really refers to.
 
-  functions = get_first_fn (functions);
+   BASETYPE_PATH, if non-NULL, contains a chain from the type of INSTANCE
+   down to the real instance type to use for access checking.  We need this
+   information to get protected accesses correct.  This parameter is used
+   by build_member_call.
 
-  /* OUTER is the list of FUNCTION_DECLS, in a TREE_LIST.  */
-  for (outer = functions; outer; outer = DECL_CHAIN (outer))
-    {
-      int template_cost = 0;
-      function = outer;
-      if (TREE_CODE (function) != FUNCTION_DECL
-         && ! (TREE_CODE (function) == TEMPLATE_DECL
-               && TREE_CODE (DECL_TEMPLATE_RESULT (function)) == FUNCTION_DECL))
-       {
-         enum tree_code code = TREE_CODE (function);
-         if (code == TEMPLATE_DECL)
-           code = TREE_CODE (DECL_TEMPLATE_RESULT (function));
-         if (code == CONST_DECL)
-           cp_error_at
-             ("enumeral value `%D' conflicts with function of same name",
-              function);
-         else if (code == VAR_DECL)
-           {
-             if (TREE_STATIC (function))
-               cp_error_at
-                 ("variable `%D' conflicts with function of same name",
-                  function);
-             else
-               cp_error_at
-                 ("constant field `%D' conflicts with function of same name",
-                  function);
-           }
-         else if (code == TYPE_DECL)
-           continue;
-         else
-           my_friendly_abort (2);
-         error ("at this point in file");
-         continue;
-       }
-      if (TREE_CODE (function) == TEMPLATE_DECL)
-       {
-         int ntparms = DECL_NTPARMS (function);
-         tree targs = make_scratch_vec (ntparms);
-         int i;
-
-         i = type_unification (DECL_INNERMOST_TEMPLATE_PARMS (function),
-                               &TREE_VEC_ELT (targs, 0),
-                               TYPE_ARG_TYPES (TREE_TYPE (function)),
-                               parms, NULL_TREE, 0, 0);
-         if (i == 0)
-           {
-             function = instantiate_template (function, targs);
-             if (function == error_mark_node)
-               return function;
-           }
-       }
+   FLAGS is the logical disjunction of zero or more LOOKUP_
+   flags.  See cp-tree.h for more info.
 
-      if (TREE_CODE (function) == TEMPLATE_DECL)
-       {
-         /* Unconverted template -- failed match.  */
-         cp->function = function;
-         cp->u.bad_arg = -4;
-         cp->h.code = EVIL_CODE;
-       }
-      else
-       {
-         struct candidate *cp2;
+   If this is all OK, calls build_function_call with the resolved
+   member function.
 
-         /* Check that this decl is not the same as a function that's in
-            the list due to some template instantiation.  */
-         cp2 = candidates;
-         while (cp2 != cp)
-           if (cp2->function == function)
-             break;
-           else
-             cp2 += 1;
-         if (cp2->function == function)
-           continue;
+   This function must also handle being called to perform
+   initialization, promotion/coercion of arguments, and
+   instantiation of default parameters.
 
-         function = DECL_MAIN_VARIANT (function);
+   Note that NAME may refer to an instance variable name.  If
+   `operator()()' is defined for the type of that field, then we return
+   that result.  */
 
-         /* Can't use alloca here, since result might be
-            passed to calling function.  */
-         cp->h_len = parmlength;
-         cp->harshness = (struct harshness_code *)
-           scratchalloc ((parmlength + 1) * sizeof (struct harshness_code));
+tree
+build_method_call (instance, name, parms, basetype_path, flags)
+     tree instance, name, parms, basetype_path;
+     int flags;
+{
+  tree result, basetype, instance_ptr;
 
-         compute_conversion_costs (function, parms, cp, parmlength);
+#ifdef GATHER_STATISTICS
+  n_build_method_call++;
+#endif
 
-         /* Make sure this is clear as well.  */
-         cp->h.int_penalty += template_cost;
+  if (instance == error_mark_node
+      || name == error_mark_node
+      || parms == error_mark_node
+      || (instance != NULL_TREE && TREE_TYPE (instance) == error_mark_node))
+    return error_mark_node;
 
-         if ((cp[0].h.code & EVIL_CODE) == 0)
-           {
-             cp[1].h.code = EVIL_CODE;
-             cp++;
-           }
+  if (processing_template_decl)
+    {
+      if (TREE_CODE (name) == BIT_NOT_EXPR)
+       {
+         tree type = get_aggr_from_typedef (TREE_OPERAND (name, 0), 1);
+         name = build_min_nt (BIT_NOT_EXPR, type);
        }
+
+      return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
     }
 
-  if (cp - candidates)
+  /* This is the logic that magically deletes the second argument to
+     operator delete, if it is not needed.  */
+  if (name == ansi_opname[(int) DELETE_EXPR] && list_length (parms)==2)
     {
-      tree rval = error_mark_node;
+      tree save_last = TREE_CHAIN (parms);
+      tree result;
+      /* get rid of unneeded argument */
+      TREE_CHAIN (parms) = NULL_TREE;
+      result = build_method_call (instance, name, parms, basetype_path,
+                                 (LOOKUP_SPECULATIVELY|flags)
+                                 &~LOOKUP_COMPLAIN);
+      /* If it finds a match, return it.  */
+      if (result)
+       return build_method_call (instance, name, parms, basetype_path, flags);
+      /* If it doesn't work, two argument delete must work */
+      TREE_CHAIN (parms) = save_last;
+    }
+  /* We already know whether it's needed or not for vec delete.  */
+  else if (name == ansi_opname[(int) VEC_DELETE_EXPR]
+          && TYPE_LANG_SPECIFIC (TREE_TYPE (instance))
+          && ! TYPE_VEC_DELETE_TAKES_SIZE (TREE_TYPE (instance)))
+    TREE_CHAIN (parms) = NULL_TREE;
 
-      /* Leave marker.  */
-      cp[0].h.code = EVIL_CODE;
-      if (cp - candidates > 1)
-       {
-         struct candidate *best_cp
-           = ideal_candidate (candidates, cp - candidates, parmlength);
-         if (best_cp == (struct candidate *)0)
-           {
-             if (flags & LOOKUP_COMPLAIN)
-               {
-                 cp_error ("call of overloaded `%D' is ambiguous", fnname);
-                 print_n_candidates (candidates, cp - candidates);
-               }
-             return error_mark_node;
-           }
-         else
-           rval = best_cp->function;
-       }
-      else
+  if (TREE_CODE (name) == BIT_NOT_EXPR)
+    {
+      flags |= LOOKUP_DESTRUCTOR;
+      name = TREE_OPERAND (name, 0);
+      if (parms)
+       error ("destructors take no parameters");
+      basetype = TREE_TYPE (instance);
+      if (TREE_CODE (basetype) == REFERENCE_TYPE)
+       basetype = TREE_TYPE (basetype);
+      if (! (name == basetype
+            || (IS_AGGR_TYPE (basetype)
+                && name == constructor_name (basetype))
+            || basetype == get_type_value (name)))
        {
-         cp -= 1;
-         if (cp->h.code & EVIL_CODE)
-           {
-             if (flags & LOOKUP_COMPLAIN)
-               error ("type conversion ambiguous");
-           }
-         else
-           rval = cp->function;
+         cp_error ("destructor name `~%D' does not match type `%T' of expression",
+                   name, basetype);
+         return cp_convert (void_type_node, instance);
        }
 
-      if (final_cp)
-       return rval;
-
-      return build_function_call_real (rval, parms, require_complete, flags);
+      if (! TYPE_HAS_DESTRUCTOR (complete_type (basetype)))
+       return cp_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),
+                          instance_ptr, integer_two_node,
+                          LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
     }
 
-  if (flags & LOOKUP_SPECULATIVELY)
-    return NULL_TREE;
-  
-  if (flags & LOOKUP_COMPLAIN)
-    report_type_mismatch (cp, parms, "function");
-
-  return error_mark_node;
-}
-
-/* This requires a complete type on the result of the call.  */
-
-tree
-build_overload_call (fnname, parms, flags)
-     tree fnname, parms;
-     int flags;
-{
-  return build_overload_call_real (fnname, parms, flags, (struct candidate *)0, 1);
+  return build_new_method_call (instance, name, parms, basetype_path, flags);
 }
 
 /* New overloading code.  */
@@ -6451,32 +4125,14 @@ int
 can_convert (to, from)
      tree to, from;
 {
-  if (flag_ansi_overloading)
-    {
-      tree t = implicit_conversion (to, from, NULL_TREE, LOOKUP_NORMAL);
-      return (t && ! ICS_BAD_FLAG (t));
-    }
-  else
-    {
-      struct harshness_code h;
-      h = convert_harshness (to, from, NULL_TREE);
-      return (h.code < USER_CODE) && (h.distance >= 0);
-    }
+  tree t = implicit_conversion (to, from, NULL_TREE, LOOKUP_NORMAL);
+  return (t && ! ICS_BAD_FLAG (t));
 }
 
 int
 can_convert_arg (to, from, arg)
      tree to, from, arg;
 {
-  if (flag_ansi_overloading)
-    {
-      tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL);
-      return (t && ! ICS_BAD_FLAG (t));
-    }
-  else
-    {
-      struct harshness_code h;
-      h = convert_harshness (to, from, arg);
-      return (h.code < USER_CODE) && (h.distance >= 0);
-    }
+  tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL);
+  return (t && ! ICS_BAD_FLAG (t));
 }
index da2f41905261a3c7a07dbf1ccfe0cccac3a8264a..f13180fb973af5c2b70e02ee828e26d1be4a157c 100644 (file)
@@ -3229,7 +3229,7 @@ finish_struct_1 (t, warn_anon)
 
   if (IS_SIGNATURE (t))
     all_virtual = 0;
-  else if (flag_all_virtual == 1 && TYPE_OVERLOADS_METHOD_CALL_EXPR (t))
+  else if (flag_all_virtual == 1)
     all_virtual = 1;
   else
     all_virtual = 0;
diff --git a/gcc/cp/class.h b/gcc/cp/class.h
deleted file mode 100644 (file)
index 12e45f7..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Variables and structures for overloading rules.
-   Copyright (C) 1993 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* The following structure is used when comparing various alternatives
-   for overloading.  The unsigned quantity `strikes.i' is used
-   for fast comparison of two possibilities.  This number is an
-   aggregate of four constituents:
-
-     EVIL: if this is non-zero, then the candidate should not be considered
-     ELLIPSIS: if this is non-zero, then some actual argument has been matched
-               against an ellipsis
-     USER: if this is non-zero, then a user-defined type conversion is needed
-     B_OR_D: if this is non-zero, then use a base pointer instead of the
-             type of the pointer we started with.
-     EASY: if this is non-zero, then we have a builtin conversion
-           (such as int to long, int to float, etc) to do.
-
-   If two candidates require user-defined type conversions, and the
-   type conversions are not identical, then an ambiguity error
-   is reported.
-
-   If two candidates agree on user-defined type conversions,
-   and one uses pointers of strictly higher type (derived where
-   another uses base), then that alternative is silently chosen.
-
-   Note that this technique really only works for 255 arguments.  Perhaps
-   this is not enough.  */
-
-/* These macros and harshness_code are used by the NEW METHOD.  */
-#define EVIL_CODE (1<<7)
-#define CONST_CODE (1<<6)
-#define ELLIPSIS_CODE (1<<5)
-#define USER_CODE (1<<4)
-#define STD_CODE (1<<3)
-#define PROMO_CODE (1<<2)
-#define QUAL_CODE (1<<1)
-#define TRIVIAL_CODE (1<<0)
-
-struct harshness_code
-{
-  /* What kind of conversion is involved.  */
-  unsigned short code;
-
-  /* The inheritance distance.  */
-  short distance;
-
-  /* For a PROMO_CODE, Any special penalties involved in integral conversions.
-     This exists because $4.1 of the ARM states that something like
-     `short unsigned int' should promote to `int', not `unsigned int'.
-     If, for example, it tries to match two fns, f(int) and f(unsigned),
-     f(int) should be a better match than f(unsigned) by this rule.  Without
-     this extra metric, they both only appear as "integral promotions", which
-     will lead to an ambiguity.
-     For a TRIVIAL_CODE, This is also used by build_overload_call_real and
-     convert_harshness to keep track of other information we need.  */
-  unsigned short int_penalty;
-};
-
-struct candidate
-{
-  struct harshness_code h;     /* Used for single-argument conversions.  */
-
-  int h_len;                   /* The length of the harshness vector.  */
-
-  tree function;               /* A FUNCTION_DECL */
-  tree basetypes;              /* The path to function.  */
-  tree arg;                    /* first parm to function.  */
-
-  /* Indexed by argument number, encodes evil, user, d_to_b, and easy
-     strikes for that argument.  At end of array, we store the index+1
-     of where we started using default parameters, or 0 if there are
-     none.  */
-  struct harshness_code *harshness;
-
-  union
-    {
-      tree field;              /* If no evil strikes, the FUNCTION_DECL of
-                                  the function (if a member function).  */
-      int bad_arg;             /* the index of the first bad argument:
-                                  0 if no bad arguments
-                                  > 0 is first bad argument
-                                  -1 if extra actual arguments
-                                  -2 if too few actual arguments.
-                                  -3 if const/non const method mismatch.
-                                  -4 if type unification failed.
-                                  -5 if contravariance violation.  */
-    } u;
-};
-int rank_for_overload PROTO ((struct candidate *, struct candidate *));
-
-/* Variables shared between class.c and call.c.  */
-
-extern int n_vtables;
-extern int n_vtable_entries;
-extern int n_vtable_searches;
-extern int n_vtable_elems;
-extern int n_convert_harshness;
-extern int n_compute_conversion_costs;
-extern int n_build_method_call;
-extern int n_inner_fields_searched;
index 5f346b51488c54da9224641f6378147edf0586ba..95bc071aee0424ea372290f033e8bd6969852713 100644 (file)
@@ -327,11 +327,6 @@ extern int flag_elide_constructors;
 
 extern int flag_ansi;
 
-/* Nonzero means do argument matching for overloading according to the
-   ANSI rules, rather than what g++ used to believe to be correct.  */
-
-extern int flag_ansi_overloading;
-
 /* Nonzero means recognize and handle signature language constructs.  */
 
 extern int flag_handle_signatures;
@@ -620,10 +615,6 @@ struct lang_type
    convenient, don't reprocess any methods that appear in its redefinition.  */
 #define TYPE_REDEFINED(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.redefined)
 
-/* Nonzero means that this _CLASSTYPE node overloads the method call
-   operator.  In this case, all method calls go through `operator->()(...).  */
-#define TYPE_OVERLOADS_METHOD_CALL_EXPR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_method_call_overloaded)
-
 /* Nonzero means that this type is a signature.  */
 # define IS_SIGNATURE(NODE) (TYPE_LANG_SPECIFIC(NODE)?TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature:0)
 # define SET_SIGNATURE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.is_signature=1)
@@ -2039,19 +2030,14 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
 extern char **opname_tab, **assignop_tab;
 \f
 /* in call.c */
-extern struct candidate *ansi_c_filler;
 extern int get_arglist_len_in_bytes            PROTO((tree));
 
-extern int rank_for_overload                   PROTO((struct candidate *, struct candidate *));
-extern void compute_conversion_costs           PROTO((tree, tree, struct candidate *, int));
 extern tree build_vfield_ref                   PROTO((tree, tree));
 extern tree resolve_scope_to_name              PROTO((tree, tree));
 extern tree build_scoped_method_call           PROTO((tree, tree, tree, tree));
 extern tree build_addr_func                    PROTO((tree));
 extern tree build_call                         PROTO((tree, tree, tree));
 extern tree build_method_call                  PROTO((tree, tree, tree, tree, int));
-extern tree build_overload_call_real           PROTO((tree, tree, int, struct candidate *, int));
-extern tree build_overload_call                        PROTO((tree, tree, int));
 extern int null_ptr_cst_p                      PROTO((tree));
 extern tree type_decays_to                     PROTO((tree));
 extern tree build_user_type_conversion         PROTO((tree, tree, int));
@@ -2090,7 +2076,6 @@ extern void warn_hidden                           PROTO((tree));
 /* in cvt.c */
 extern tree convert_to_reference               PROTO((tree, tree, int, int, tree));
 extern tree convert_from_reference             PROTO((tree));
-extern tree convert_to_aggr                    PROTO((tree, tree, char **, int));
 extern tree convert_pointer_to_real            PROTO((tree, tree));
 extern tree convert_pointer_to                 PROTO((tree, tree));
 extern tree ocp_convert                                PROTO((tree, tree, int, int));
@@ -2399,7 +2384,6 @@ extern void yyhook                                PROTO((int));
 /* in method.c */
 extern void init_method                                PROTO((void));
 extern void do_inline_function_hair            PROTO((tree, tree));
-extern void  report_type_mismatch              PROTO((struct candidate *, tree, char *));
 extern char *build_overload_name               PROTO((tree, int, int));
 extern tree build_static_name                  PROTO((tree, tree));
 extern tree build_decl_overload                        PROTO((tree, tree, int));
index d308805aa62e175108114e689bed2562acd42619..05cd667777055b2445413fb013edb75b5f419e54 100644 (file)
@@ -30,7 +30,6 @@ Boston, MA 02111-1307, USA.  */
 #include "tree.h"
 #include "flags.h"
 #include "cp-tree.h"
-#include "class.h"
 #include "convert.h"
 
 #ifdef HAVE_STDLIB_H
@@ -482,11 +481,8 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
     {
       /* Look for a user-defined conversion to lvalue that we can use.  */
 
-      if (flag_ansi_overloading)
-       rval_as_conversion
-         = build_type_conversion (CONVERT_EXPR, reftype, expr, 1);
-      else
-       rval_as_conversion = build_type_conversion (CONVERT_EXPR, type, expr, 1);
+      rval_as_conversion
+       = build_type_conversion (CONVERT_EXPR, reftype, expr, 1);
 
       if (rval_as_conversion && rval_as_conversion != error_mark_node
          && real_lvalue_p (rval_as_conversion))
@@ -556,7 +552,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
       if (rval != error_mark_node)
        rval = build1 (NOP_EXPR, reftype, rval);
     }
-  else if (flag_ansi_overloading)
+  else
     {
       rval = convert_for_initialization (NULL_TREE, type, expr, flags,
                                         "converting", 0, 0);
@@ -568,89 +564,6 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
        cp_pedwarn ("initializing non-const `%T' with `%T' will use a temporary",
                    reftype, intype);
     }
-  else
-    {
-      tree rval_as_ctor = NULL_TREE;
-      
-      if (rval_as_conversion)
-       {
-         if (rval_as_conversion == error_mark_node)
-           {
-             cp_error ("conversion from `%T' to `%T' is ambiguous",
-                       intype, reftype);
-             return error_mark_node;
-           }
-         rval_as_conversion = build_up_reference (reftype, rval_as_conversion,
-                                                  flags, 1);
-       }
-      
-      /* Definitely need to go through a constructor here.  */
-      if (TYPE_HAS_CONSTRUCTOR (type)
-         && ! CLASSTYPE_ABSTRACT_VIRTUALS (type)
-         && (rval = build_method_call
-             (NULL_TREE, ctor_identifier,
-              build_expr_list (NULL_TREE, expr), TYPE_BINFO (type),
-              LOOKUP_NO_CONVERSION|LOOKUP_SPECULATIVELY
-              | LOOKUP_ONLYCONVERTING)))
-       {
-         tree init;
-
-         if (toplevel_bindings_p ())
-           {
-             tree t = get_temp_name (type, toplevel_bindings_p ());
-             init = build_method_call (t, ctor_identifier,
-                                       build_expr_list (NULL_TREE, expr),
-                                       TYPE_BINFO (type),
-                                       LOOKUP_NORMAL|LOOKUP_NO_CONVERSION
-                                       | LOOKUP_ONLYCONVERTING);
-
-             if (init == error_mark_node)
-               return error_mark_node;
-
-             make_decl_rtl (t, NULL_PTR, 1);
-             static_aggregates = perm_tree_cons (expr, t, static_aggregates);
-             rval = build_unary_op (ADDR_EXPR, t, 0);
-           }
-         else
-           {
-             init = build_method_call (NULL_TREE, ctor_identifier,
-                                       build_expr_list (NULL_TREE, expr),
-                                       TYPE_BINFO (type),
-                                       LOOKUP_NORMAL|LOOKUP_NO_CONVERSION
-                                       |LOOKUP_ONLYCONVERTING);
-
-             if (init == error_mark_node)
-               return error_mark_node;
-
-             rval = build_cplus_new (type, init);
-             rval = build_up_reference (reftype, rval, flags, 1);
-           }
-         rval_as_ctor = rval;
-       }
-
-      if (rval_as_ctor && rval_as_conversion)
-       {
-         cp_error ("ambiguous conversion from `%T' to `%T'; both user-defined conversion and constructor apply",
-                   intype, reftype);
-         return error_mark_node;
-       }
-      else if (rval_as_ctor)
-       rval = rval_as_ctor;
-      else if (rval_as_conversion)
-       rval = rval_as_conversion;
-      else if (! IS_AGGR_TYPE (type) && ! IS_AGGR_TYPE (intype))
-       {
-         rval = cp_convert (type, expr);
-         if (rval == error_mark_node)
-           return error_mark_node;
-         
-         rval = build_up_reference (reftype, rval, flags, 1);
-       }
-
-      if (rval && ! TYPE_READONLY (TREE_TYPE (reftype)))
-       cp_pedwarn ("initializing non-const `%T' with `%T' will use a temporary",
-                   reftype, intype);
-    }
 
   if (rval)
     {
@@ -685,190 +598,6 @@ convert_from_reference (val)
   return val;
 }
 \f
-/* See if there is a constructor of type TYPE which will convert
-   EXPR.  The reference manual seems to suggest (8.5.6) that we need
-   not worry about finding constructors for base classes, then converting
-   to the derived class.
-
-   MSGP is a pointer to a message that would be an appropriate error
-   string.  If MSGP is NULL, then we are not interested in reporting
-   errors.  */
-
-tree
-convert_to_aggr (type, expr, msgp, protect)
-     tree type, expr;
-     char **msgp;
-     int protect;
-{
-  tree basetype = type;
-  tree name = TYPE_IDENTIFIER (basetype);
-  tree function, fndecl, fntype, parmtypes, parmlist, result;
-#if 0
-  /* See code below that used this.  */
-  tree method_name;
-#endif
-  tree access;
-  int can_be_private, can_be_protected;
-
-  if (! TYPE_HAS_CONSTRUCTOR (basetype))
-    {
-      if (msgp)
-       *msgp = "type `%s' does not have a constructor";
-      return error_mark_node;
-    }
-
-  access = access_public_node;
-  can_be_private = 0;
-  can_be_protected = IDENTIFIER_CLASS_VALUE (name) || name == current_class_name;
-
-  parmlist = build_expr_list (NULL_TREE, expr);
-  parmtypes = scratch_tree_cons (NULL_TREE, TREE_TYPE (expr), void_list_node);
-
-  if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))
-    {
-      parmtypes = expr_tree_cons (NULL_TREE, integer_type_node, parmtypes);
-      parmlist = scratch_tree_cons (NULL_TREE, integer_one_node, parmlist);
-    }
-
-  /* The type of the first argument will be filled in inside the loop.  */
-  parmlist = expr_tree_cons (NULL_TREE, integer_zero_node, parmlist);
-  parmtypes = scratch_tree_cons (NULL_TREE, build_pointer_type (basetype), parmtypes);
-
-  /* No exact conversion was found.  See if an approximate
-     one will do.  */
-  fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);
-
-  {
-    int saw_private = 0;
-    int saw_protected = 0;
-    struct candidate *candidates
-      = (struct candidate *) alloca ((decl_list_length (fndecl)+1) * sizeof (struct candidate));
-    struct candidate *cp = candidates;
-
-    while (fndecl)
-      {
-       function = fndecl;
-       cp->h_len = 2;
-       cp->harshness = (struct harshness_code *)
-         alloca (3 * sizeof (struct harshness_code));
-
-       compute_conversion_costs (fndecl, parmlist, cp, 2);
-       if ((cp->h.code & EVIL_CODE) == 0)
-         {
-           cp->u.field = fndecl;
-           if (protect)
-             {
-               if (TREE_PRIVATE (fndecl))
-                 access = access_private_node;
-               else if (TREE_PROTECTED (fndecl))
-                 access = access_protected_node;
-               else
-                 access = access_public_node;
-             }
-           else
-             access = access_public_node;
-
-           if (access == access_private_node
-               ? (basetype == current_class_type
-                  || is_friend (basetype, cp->function)
-                  || purpose_member (basetype, DECL_ACCESS (fndecl)))
-               : access == access_protected_node
-               ? (can_be_protected
-                  || purpose_member (basetype, DECL_ACCESS (fndecl)))
-               : 1)
-             {
-               if (cp->h.code <= TRIVIAL_CODE)
-                 goto found_and_ok;
-               cp++;
-             }
-           else
-             {
-               if (access == access_private_node)
-                 saw_private = 1;
-               else
-                 saw_protected = 1;
-             }
-         }
-       fndecl = DECL_CHAIN (fndecl);
-      }
-    if (cp - candidates)
-      {
-       /* Rank from worst to best.  Then cp will point to best one.
-          Private fields have their bits flipped.  For unsigned
-          numbers, this should make them look very large.
-          If the best alternate has a (signed) negative value,
-          then all we ever saw were private members.  */
-       if (cp - candidates > 1)
-         qsort (candidates,    /* char *base */
-                cp - candidates, /* int nel */
-                sizeof (struct candidate), /* int width */
-                (int (*) PROTO((const void *, const void *))) rank_for_overload); /* int (*compar)() */
-
-       --cp;
-       if (cp->h.code & EVIL_CODE)
-         {
-           if (msgp)
-             *msgp = "ambiguous type conversion possible for `%s'";
-           return error_mark_node;
-         }
-
-       function = cp->function;
-       fndecl = cp->u.field;
-       goto found_and_ok;
-      }
-    else if (msgp)
-      {
-       if (saw_private)
-         {
-           if (saw_protected)
-             *msgp = "only private and protected conversions apply";
-           else
-             *msgp = "only private conversions apply";
-         }
-       else if (saw_protected)
-         *msgp = "only protected conversions apply";
-       else
-         *msgp = "no appropriate conversion to type `%s'";
-      }
-    return error_mark_node;
-  }
-  /* NOTREACHED */
-
- found:
-  if (access == access_private_node)
-    if (! can_be_private)
-      {
-       if (msgp)
-         *msgp = TREE_PRIVATE (fndecl)
-           ? "conversion to type `%s' is private"
-           : "conversion to type `%s' is from private base class";
-       return error_mark_node;
-      }
-  if (access == access_protected_node)
-    if (! can_be_protected)
-      {
-       if (msgp)
-         *msgp = TREE_PRIVATE (fndecl)
-           ? "conversion to type `%s' is protected"
-           : "conversion to type `%s' is from protected base class";
-       return error_mark_node;
-      }
-  function = fndecl;
- found_and_ok:
-
-  /* It will convert, but we don't do anything about it yet.  */
-  if (msgp == 0)
-    return NULL_TREE;
-
-  fntype = TREE_TYPE (function);
-
-  parmlist = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
-                               parmlist, NULL_TREE, LOOKUP_NORMAL);
-
-  result = build_call (function, TREE_TYPE (fntype), parmlist);
-  return result;
-}
-
 /* Call this when we know (for any reason) that expr is not, in fact,
    zero.  This routine is like convert_pointer_to, but it pays
    attention to which specific instance of what type we want to
@@ -1119,71 +848,20 @@ ocp_convert (type, expr, convtype, flags)
         There may be some ambiguity between using a constructor
         vs. using a type conversion operator when both apply.  */
 
-      if (flag_ansi_overloading)
-       {
-         ctor = e;
-         
-         if ((flags & LOOKUP_ONLYCONVERTING)
-             && ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))
-           {
-             ctor = build_user_type_conversion (type, ctor, flags);
-             flags |= LOOKUP_NO_CONVERSION;
-           }
-         if (ctor)
-           ctor = build_method_call (NULL_TREE, ctor_identifier,
-                                     build_expr_list (NULL_TREE, ctor),
-                                     TYPE_BINFO (type), flags);
-         if (ctor)
-           return build_cplus_new (type, ctor);
-       }
-      else
-       {
-         if (IS_AGGR_TYPE (dtype) && ! DERIVED_FROM_P (type, dtype)
-             && TYPE_HAS_CONVERSION (dtype))
-           conversion = build_type_conversion (CONVERT_EXPR, type, e, 1);
-
-         if (conversion == error_mark_node)
-           {
-             if (flags & LOOKUP_COMPLAIN)
-               error ("ambiguous pointer conversion");
-             return conversion;
-           }
+      ctor = e;
 
-         if (TYPE_HAS_CONSTRUCTOR (complete_type (type)))
-           ctor = build_method_call (NULL_TREE, ctor_identifier,
-                                     build_expr_list (NULL_TREE, e),
-                                     TYPE_BINFO (type),
-                                     (flags & LOOKUP_NORMAL)
-                                     | LOOKUP_SPECULATIVELY
-                                     | (flags & LOOKUP_ONLYCONVERTING)
-                                     | (flags & LOOKUP_NO_CONVERSION)
-                                     | (conversion ? LOOKUP_NO_CONVERSION : 0));
-
-         if (ctor == error_mark_node)
-           {
-             if (flags & LOOKUP_COMPLAIN)
-               cp_error ("in conversion to type `%T'", type);
-             if (flags & LOOKUP_SPECULATIVELY)
-               return NULL_TREE;
-             return error_mark_node;
-           }
-      
-         if (conversion && ctor)
-           {
-             if (flags & LOOKUP_COMPLAIN)
-               error ("both constructor and type conversion operator apply");
-             if (flags & LOOKUP_SPECULATIVELY)
-               return NULL_TREE;
-             return error_mark_node;
-           }
-         else if (conversion)
-           return conversion;
-         else if (ctor)
-           {
-             ctor = build_cplus_new (type, ctor);
-             return ctor;
-           }
+      if ((flags & LOOKUP_ONLYCONVERTING)
+         && ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))
+       {
+         ctor = build_user_type_conversion (type, ctor, flags);
+         flags |= LOOKUP_NO_CONVERSION;
        }
+      if (ctor)
+       ctor = build_method_call (NULL_TREE, ctor_identifier,
+                                 build_expr_list (NULL_TREE, ctor),
+                                 TYPE_BINFO (type), flags);
+      if (ctor)
+       return build_cplus_new (type, ctor);
     }
 
   /* If TYPE or TREE_TYPE (E) is not on the permanent_obstack,
@@ -1339,64 +1017,8 @@ build_type_conversion (code, xtype, expr, for_sure)
 {
   /* C++: check to see if we can convert this aggregate type
      into the required type.  */
-  tree basetype;
-  tree conv;
-  tree winner = NULL_TREE;
-
-  if (flag_ansi_overloading)
-    return build_user_type_conversion
-      (xtype, expr, for_sure ? LOOKUP_NORMAL : 0);
-
-  if (expr == error_mark_node)
-    return error_mark_node;
-
-  basetype = TREE_TYPE (expr);
-  if (TREE_CODE (basetype) == REFERENCE_TYPE)
-    basetype = TREE_TYPE (basetype);
-
-  basetype = TYPE_MAIN_VARIANT (basetype);
-  if (! TYPE_LANG_SPECIFIC (basetype) || ! TYPE_HAS_CONVERSION (basetype))
-    return NULL_TREE;
-
-  /* Do we have an exact match?  */
-  {
-    tree typename = build_typename_overload (xtype);
-    if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0))
-      return build_type_conversion_1 (xtype, basetype, expr, typename,
-                                     for_sure);
-  }
-
-  /* Nope; try looking for others.  */
-  for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
-    {
-      tree cand = TREE_VALUE (conv);
-
-      if (winner && winner == cand)
-       continue;
-
-      if (can_convert (xtype, TREE_TYPE (TREE_TYPE (cand))))
-       {
-         if (winner)
-           {
-             if (for_sure)
-               {
-                 cp_error ("ambiguous conversion from `%T' to `%T'", basetype,
-                           xtype);
-                 cp_error ("  candidate conversions include `%D' and `%D'",
-                           winner, cand);
-               }
-             return NULL_TREE;
-           }
-         else
-           winner = cand;
-       }
-    }
-
-  if (winner)
-    return build_type_conversion_1 (xtype, basetype, expr,
-                                   DECL_NAME (winner), for_sure);
-
-  return NULL_TREE;
+  return build_user_type_conversion
+    (xtype, expr, for_sure ? LOOKUP_NORMAL : 0);
 }
 
 /* Convert the given EXPR to one of a group of types suitable for use in an
index e5ab625e7232cc07f58720f3dcaf1a1d3d6fa6b4..334db914a144624e35713cfa022cd5651c465701 100644 (file)
@@ -10760,8 +10760,7 @@ grok_op_properties (decl, virtualp, friendp)
            }
        }
       
-      if (name == ansi_opname[(int) CALL_EXPR]
-         || name == ansi_opname[(int) METHOD_CALL_EXPR])
+      if (name == ansi_opname[(int) CALL_EXPR])
        return;                 /* no restrictions on args */
 
       if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
@@ -11245,7 +11244,6 @@ xref_basetypes (code_type_node, name, ref, binfo)
              TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
            }
 
-         TYPE_OVERLOADS_METHOD_CALL_EXPR (ref) |= TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype);
          TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
          TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
          CLASSTYPE_LOCAL_TYPEDECLS (ref) |= CLASSTYPE_LOCAL_TYPEDECLS (basetype);
index fa39b9e4b8ddebdb03460c32dcc89c4714bc86ed..246834219088170710656f71327bb6661026fc1e 100644 (file)
@@ -143,11 +143,6 @@ int flag_no_ident;
 
 int flag_ansi;
 
-/* Nonzero means do argument matching for overloading according to the
-   ANSI rules, rather than what g++ used to believe to be correct.  */
-
-int flag_ansi_overloading = 1;
-
 /* Nonzero means do emit exported implementations of functions even if
    they can be inlined.  */
 
@@ -470,7 +465,6 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
   {"implement-inlines", &flag_implement_inlines, 1},
   {"external-templates", &flag_external_templates, 1},
   {"implicit-templates", &flag_implicit_templates, 1},
-  {"ansi-overloading", &flag_ansi_overloading, 1},
   {"huge-objects", &flag_huge_objects, 1},
   {"conserve-space", &flag_conserve_space, 1},
   {"vtable-thunks", &flag_vtable_thunks, 1},
@@ -565,6 +559,13 @@ lang_decode_option (p)
          flag_guiding_decls = 0;
          found = 1;
        }
+      else if (!strcmp (p, "ansi-overloading"))
+       found = 1;
+      else if (!strcmp (p, "no-ansi-overloading"))
+       {
+         error ("-fno-ansi-overloading is no longer supported");
+         found = 1;
+       }
       else if (!strncmp (p, "template-depth-", 15))
        {
          char *endp = p + 15;
index ee68dfc1b483b053138b9e825bbf4dee2e61b52e..a420092984f4c679d51f2a240314e1ffad8d7bcd 100644 (file)
@@ -1249,7 +1249,7 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
   tree rval;
   tree parms;
 
-  if (flag_ansi_overloading && init && TREE_CODE (init) != TREE_LIST
+  if (init && TREE_CODE (init) != TREE_LIST
       && (flags & LOOKUP_ONLYCONVERTING))
     {
       /* Base subobjects should only get direct-initialization.  */
@@ -1287,15 +1287,6 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
       if (parms)
        init = TREE_VALUE (parms);
     }
-  else if (! flag_ansi_overloading
-          && TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init)
-          && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
-    {
-      rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0);
-      TREE_USED (rval) = 1;
-      expand_expr_stmt (rval);
-      return;
-    }
   else
     parms = build_expr_list (NULL_TREE, init);
 
@@ -1308,52 +1299,9 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
       flags |= LOOKUP_HAS_IN_CHARGE;
     }
 
-  if (flag_ansi_overloading)
-    {
-      rval = build_method_call (exp, ctor_identifier,
-                               parms, binfo, flags);
-      expand_expr_stmt (rval);
-      return;
-    }
-
-  if (init && TREE_CHAIN (parms) == NULL_TREE
-      && TYPE_HAS_TRIVIAL_INIT_REF (type)
-      && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))
-    {
-      rval = build (INIT_EXPR, type, exp, init);
-      TREE_SIDE_EFFECTS (rval) = 1;
-      expand_expr_stmt (rval);
-    }
-  else
-    {
-      if (flags & LOOKUP_ONLYCONVERTING)
-       flags |= LOOKUP_NO_CONVERSION;
-      rval = build_method_call (exp, ctor_identifier,
-                               parms, binfo, flags);
-
-      /* Private, protected, or otherwise unavailable.  */
-      if (rval == error_mark_node)
-       {
-         if (flags & LOOKUP_COMPLAIN)
-           cp_error ("in base initialization for %sclass `%T'",
-                     TREE_VIA_VIRTUAL (binfo) ? "virtual base " : "",
-                     binfo);
-       }
-      else if (rval == NULL_TREE)
-       my_friendly_abort (361);
-      else
-       {
-         /* p. 222: if the base class assigns to `this', then that
-            value is used in the derived class.  */
-         if ((flag_this_is_variable & 1) && alias_this)
-           {
-             TREE_TYPE (rval) = TREE_TYPE (current_class_ptr);
-             expand_assignment (current_class_ptr, rval, 0, 0);
-           }
-         else
-           expand_expr_stmt (rval);
-       }
-    }
+  rval = build_method_call (exp, ctor_identifier,
+                           parms, binfo, flags);
+  expand_expr_stmt (rval);
 }
 
 /* This function is responsible for initializing EXP with INIT
@@ -1413,171 +1361,6 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)
       return;
     }
 
-  if (init && ! flag_ansi_overloading)
-    {
-      tree init_list = NULL_TREE;
-
-      if (TREE_CODE (init) == TREE_LIST)
-       {
-         init_list = init;
-         if (TREE_CHAIN (init) == NULL_TREE)
-           init = TREE_VALUE (init);
-       }
-
-      init_type = TREE_TYPE (init);
-
-      if (TREE_CODE (init) != TREE_LIST)
-       {
-         if (init_type == error_mark_node)
-           return;
-
-         /* This happens when we use C++'s functional cast notation.
-            If the types match, then just use the TARGET_EXPR
-            directly.  Otherwise, we need to create the initializer
-            separately from the object being initialized.  */
-         if (TREE_CODE (init) == TARGET_EXPR)
-           {
-             if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type))
-               {
-                 if (TREE_CODE (exp) == VAR_DECL
-                     || TREE_CODE (exp) == RESULT_DECL)
-                   /* Unify the initialization targets.  */
-                   DECL_RTL (TREE_OPERAND (init, 0)) = DECL_RTL (exp);
-                 else
-                   DECL_RTL (TREE_OPERAND (init, 0)) = expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL);
-
-                 expand_expr_stmt (init);
-                 return;
-               }
-           }
-
-         if (init_type == type && TREE_CODE (init) == CALL_EXPR)
-           {
-             /* A CALL_EXPR is a legitimate form of initialization, so
-                we should not print this warning message.  */
-
-             expand_assignment (exp, init, 0, 0);
-             if (exp == DECL_RESULT (current_function_decl))
-               {
-                 /* Failing this assertion means that the return value
-                    from receives multiple initializations.  */
-                 my_friendly_assert (DECL_INITIAL (exp) == NULL_TREE
-                                     || DECL_INITIAL (exp) == error_mark_node,
-                                     212);
-                 DECL_INITIAL (exp) = init;
-               }
-             return;
-           }
-         else if (init_type == type
-                  && TREE_CODE (init) == COND_EXPR)
-           {
-             /* Push value to be initialized into the cond, where possible.
-                Avoid spurious warning messages when initializing the
-                result of this function.  */
-             TREE_OPERAND (init, 1)
-               = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 1));
-             if (exp == DECL_RESULT (current_function_decl))
-               DECL_INITIAL (exp) = NULL_TREE;
-             TREE_OPERAND (init, 2)
-               = build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 2));
-             if (exp == DECL_RESULT (current_function_decl))
-               DECL_INITIAL (exp) = init;
-             TREE_SIDE_EFFECTS (init) = 1;
-             expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
-             free_temp_slots ();
-             return;
-           }
-       }
-
-      /* We did not know what we were initializing before.  Now we do.  */
-      if (TREE_CODE (init) == TARGET_EXPR)
-       {
-         tree tmp = TREE_OPERAND (TREE_OPERAND (init, 1), 1);
-
-         if (tmp && TREE_CODE (TREE_VALUE (tmp)) == NOP_EXPR
-             && TREE_OPERAND (TREE_VALUE (tmp), 0) == integer_zero_node)
-           {
-             /* In order for this to work for RESULT_DECLs, if their
-                type has a constructor, then they must be BLKmode
-                so that they will be meaningfully addressable.  */
-             tree arg = build_unary_op (ADDR_EXPR, exp, 0);
-             init = TREE_OPERAND (init, 1);
-             init = build (CALL_EXPR, build_pointer_type (TREE_TYPE (init)),
-                           TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), NULL_TREE);
-             TREE_SIDE_EFFECTS (init) = 1;
-             TREE_VALUE (TREE_OPERAND (init, 1))
-               = convert_pointer_to (TREE_TYPE (TREE_TYPE (TREE_VALUE (tmp))), arg);
-
-             if (alias_this)
-               {
-                 expand_assignment (current_function_decl, init, 0, 0);
-                 return;
-               }
-             if (exp == DECL_RESULT (current_function_decl))
-               {
-                 if (DECL_INITIAL (DECL_RESULT (current_function_decl)))
-                   fatal ("return value from function receives multiple initializations");
-                 DECL_INITIAL (exp) = init;
-               }
-             expand_expr_stmt (init);
-             return;
-           }
-       }
-
-      /* Handle this case: when calling a constructor: xyzzy foo(bar);
-        which really means:  xyzzy foo = bar; Ugh!
-
-        More useful for this case: xyzzy *foo = new xyzzy (bar);  */
-
-      if (! TYPE_NEEDS_CONSTRUCTING (type) && ! IS_AGGR_TYPE (type))
-       {
-         if (init_list && TREE_CHAIN (init_list))
-           {
-             warning ("initializer list being treated as compound expression");
-             init = cp_convert (type, build_compound_expr (init_list));
-             if (init == error_mark_node)
-               return;
-           }
-
-         expand_assignment (exp, init, 0, 0);
-
-         return;
-       }
-
-      /* If this is copy-initialization, see whether we can go through a
-        type conversion operator.  */
-      if (TREE_CODE (init) != TREE_LIST && (flags & LOOKUP_ONLYCONVERTING))
-       {
-         tree ttype = TREE_CODE (init_type) == REFERENCE_TYPE
-           ? TREE_TYPE (init_type) : init_type;
-
-         if (ttype != type && IS_AGGR_TYPE (ttype))
-           {
-             tree rval = build_type_conversion (CONVERT_EXPR, type, init, 1);
-
-             if (rval)
-               {
-                 /* See if there is a constructor for``type'' that takes a
-                    ``ttype''-typed object.  */
-                 tree parms = build_expr_list (NULL_TREE, init);
-                 tree as_cons = NULL_TREE;
-                 if (TYPE_HAS_CONSTRUCTOR (type))
-                   as_cons = build_method_call (exp, ctor_identifier,
-                                                parms, binfo,
-                                                LOOKUP_SPECULATIVELY|LOOKUP_NO_CONVERSION);
-                 if (as_cons != NULL_TREE && as_cons != error_mark_node)
-                   /* ANSI C++ June 5 1992 WP 12.3.2.6.1 */
-                   cp_error ("ambiguity between conversion to `%T' and constructor",
-                             type);
-                 else
-                   if (rval != error_mark_node)
-                     expand_aggr_init_1 (binfo, true_exp, exp, rval, alias_this, flags);
-                 return;
-               }
-           }
-       }
-    }
-
   /* We know that expand_default_init can handle everything we want
      at this point.  */
   expand_default_init (binfo, true_exp, exp, init, alias_this, flags);
index 7ee6ba1b011ca07b04417eda015ad5c8a657284e..7dfcc1f4c21c62c638be1dd64f5e19864ae97c40 100644 (file)
@@ -615,8 +615,6 @@ init_lex ()
   IDENTIFIER_OPNAME_P (ansi_opname[(int) MAX_EXPR]) = 1;
   ansi_opname[(int) COND_EXPR] = get_identifier ("__cn");
   IDENTIFIER_OPNAME_P (ansi_opname[(int) COND_EXPR]) = 1;
-  ansi_opname[(int) METHOD_CALL_EXPR] = get_identifier ("__wr");
-  IDENTIFIER_OPNAME_P (ansi_opname[(int) METHOD_CALL_EXPR]) = 1;
 
   init_method ();
   init_error ();
@@ -747,7 +745,6 @@ init_lex ()
 
   opname_tab[(int) COMPONENT_REF] = "->";
   opname_tab[(int) MEMBER_REF] = "->*";
-  opname_tab[(int) METHOD_CALL_EXPR] = "->()";
   opname_tab[(int) INDIRECT_REF] = "*";
   opname_tab[(int) ARRAY_REF] = "[]";
   opname_tab[(int) MODIFY_EXPR] = "=";
index 3a800dafc7107d00a318223702081ffeda37ad0e..e1ae25072acfb1282d3add22762bd7c701c4b16d 100644 (file)
@@ -34,7 +34,6 @@ Boston, MA 02111-1307, USA.  */
 #include <stdio.h>
 #include "tree.h"
 #include "cp-tree.h"
-#include "class.h"
 #include "obstack.h"
 #include <ctype.h>
 #include "rtl.h"
@@ -175,92 +174,6 @@ do_inline_function_hair (type, friend_list)
     }
 }
 \f
-/* Report an argument type mismatch between the best declared function
-   we could find and the current argument list that we have.  */
-
-void
-report_type_mismatch (cp, parmtypes, name_kind)
-     struct candidate *cp;
-     tree parmtypes;
-     char *name_kind;
-{
-  int i = cp->u.bad_arg;
-  tree ttf, tta;
-  char *tmp_firstobj;
-
-  switch (i)
-    {
-    case -4:
-      my_friendly_assert (TREE_CODE (cp->function) == TEMPLATE_DECL, 240);
-      cp_error ("type unification failed for function template `%#D'",
-               cp->function);
-      return;
-
-    case -2:
-      cp_error ("too few arguments for %s `%#D'", name_kind, cp->function);
-      return;
-    case -1:
-      cp_error ("too many arguments for %s `%#D'", name_kind, cp->function);
-      return;
-    case 0:
-      if (TREE_CODE (TREE_TYPE (cp->function)) != METHOD_TYPE)
-       break;
-    case -3:
-      /* Happens when the implicit object parameter is rejected.  */
-      my_friendly_assert (! TYPE_READONLY (TREE_TYPE (TREE_VALUE (parmtypes))),
-                         241);
-      if (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (TREE_VALUE (parmtypes))))
-         && ! TYPE_VOLATILE (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (cp->function))))))
-       cp_error ("call to non-volatile %s `%#D' with volatile object",
-                 name_kind, cp->function);
-      else
-       cp_error ("call to non-const %s `%#D' with const object",
-                 name_kind, cp->function);
-      return;
-    }
-
-  ttf = TYPE_ARG_TYPES (TREE_TYPE (cp->function));
-  tta = parmtypes;
-
-  while (i-- > 0)
-    {
-      ttf = TREE_CHAIN (ttf);
-      tta = TREE_CHAIN (tta);
-    }
-
-  OB_INIT ();
-  OB_PUTS ("bad argument ");
-  sprintf (digit_buffer, "%d", cp->u.bad_arg
-          - (TREE_CODE (TREE_TYPE (cp->function)) == METHOD_TYPE)
-          + 1);
-  OB_PUTCP (digit_buffer);
-
-  OB_PUTS (" for function `");
-  OB_PUTCP (decl_as_string (cp->function, 1));
-  OB_PUTS ("' (type was ");
-
-  /* Reset `i' so that type printing routines do the right thing.  */
-  if (tta)
-    {
-      enum tree_code code = TREE_CODE (TREE_TYPE (TREE_VALUE (tta)));
-      if (code == ERROR_MARK)
-       OB_PUTS ("(failed type instantiation)");
-      else
-       {
-         i = (code == FUNCTION_TYPE || code == METHOD_TYPE);
-         OB_PUTCP (type_as_string (TREE_TYPE (TREE_VALUE (tta)), 1));
-       }
-    }
-  else OB_PUTS ("void");
-  OB_PUTC (')');
-  OB_FINISH ();
-
-  tmp_firstobj = (char *)alloca (obstack_object_size (&scratch_obstack));
-  bcopy (obstack_base (&scratch_obstack), tmp_firstobj,
-        obstack_object_size (&scratch_obstack));
-  error (tmp_firstobj);
-}
-\f
 /* Here is where overload code starts.  */
 
 /* type tables for K and B type compression */
@@ -1733,311 +1646,7 @@ build_opfncall (code, flags, xarg1, xarg2, arg3)
      int flags;
      tree xarg1, xarg2, arg3;
 {
-  tree rval = 0;
-  tree arg1, arg2;
-  tree type1, type2, fnname;
-  tree fields1 = 0, parms = 0;
-  tree global_fn;
-  int try_second;
-  int binary_is_unary;
-
-  if (flag_ansi_overloading)
-    return build_new_op (code, flags, xarg1, xarg2, arg3);
-
-  if (xarg1 == error_mark_node)
-    return error_mark_node;
-
-  if (code == COND_EXPR)
-    {
-      if (xarg2 == error_mark_node
-         || arg3 == error_mark_node)
-       return error_mark_node;
-    }
-  if (code == COMPONENT_REF)
-    if (TREE_CODE (TREE_TYPE (xarg1)) == POINTER_TYPE)
-      return rval;
-
-  /* First, see if we can work with the first argument */
-  type1 = TREE_TYPE (xarg1);
-
-  /* Some tree codes have length > 1, but we really only want to
-     overload them if their first argument has a user defined type.  */
-  switch (code)
-    {
-    case PREINCREMENT_EXPR:
-    case PREDECREMENT_EXPR:
-    case POSTINCREMENT_EXPR:
-    case POSTDECREMENT_EXPR:
-    case COMPONENT_REF:
-      binary_is_unary = 1;
-      try_second = 0;
-      break;
-
-      /* ARRAY_REFs and CALL_EXPRs must overload successfully.
-        If they do not, return error_mark_node instead of NULL_TREE.  */
-    case ARRAY_REF:
-      if (xarg2 == error_mark_node)
-       return error_mark_node;
-    case CALL_EXPR:
-      rval = error_mark_node;
-      binary_is_unary = 0;
-      try_second = 0;
-      break;
-
-    case VEC_NEW_EXPR:
-    case NEW_EXPR:
-      {
-       tree args = expr_tree_cons (NULL_TREE, xarg2, arg3);
-       fnname = ansi_opname[(int) code];
-       if (flags & LOOKUP_GLOBAL)
-         return build_overload_call (fnname, args, flags & LOOKUP_COMPLAIN);
-
-       rval = build_method_call
-         (build_indirect_ref (build1 (NOP_EXPR, xarg1, error_mark_node),
-                              "new"),
-          fnname, args, NULL_TREE, flags);
-       if (rval == error_mark_node)
-         /* User might declare fancy operator new, but invoke it
-            like standard one.  */
-         return rval;
-
-       TREE_TYPE (rval) = xarg1;
-       return rval;
-      }
-      break;
-
-    case VEC_DELETE_EXPR:
-    case DELETE_EXPR:
-      {
-       fnname = ansi_opname[(int) code];
-       if (flags & LOOKUP_GLOBAL)
-         return build_overload_call (fnname,
-                                     build_expr_list (NULL_TREE, xarg1),
-                                     flags & LOOKUP_COMPLAIN);
-       arg1 = TREE_TYPE (xarg1);
-
-       /* This handles the case where we're trying to delete
-          X (*a)[10];
-          a=new X[5][10];
-          delete[] a; */
-          
-       if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
-         {
-           /* Strip off the pointer and the array.  */
-           arg1 = TREE_TYPE (TREE_TYPE (arg1));
-
-           while (TREE_CODE (arg1) == ARRAY_TYPE)
-               arg1 = (TREE_TYPE (arg1));
-
-           arg1 = build_pointer_type (arg1);
-         }
-
-       rval = build_method_call
-         (build_indirect_ref (build1 (NOP_EXPR, arg1,
-                                      error_mark_node),
-                              NULL_PTR),
-          fnname, expr_tree_cons (NULL_TREE, xarg1,
-                              build_expr_list (NULL_TREE, xarg2)),
-          NULL_TREE, flags);
-#if 0
-       /* This can happen when operator delete is protected.  */
-       my_friendly_assert (rval != error_mark_node, 250);
-       TREE_TYPE (rval) = void_type_node;
-#endif
-       return rval;
-      }
-      break;
-
-    default:
-      binary_is_unary = 0;
-      try_second = tree_code_length [(int) code] == 2;
-      if (try_second && xarg2 == error_mark_node)
-       return error_mark_node;
-      break;
-    }
-
-  if (try_second && xarg2 == error_mark_node)
-    return error_mark_node;
-
-  /* What ever it was, we do not know how to deal with it.  */
-  if (type1 == NULL_TREE)
-    return rval;
-
-  if (TREE_CODE (type1) == OFFSET_TYPE)
-    type1 = TREE_TYPE (type1);
-
-  if (TREE_CODE (type1) == REFERENCE_TYPE)
-    {
-      arg1 = convert_from_reference (xarg1);
-      type1 = TREE_TYPE (arg1);
-    }
-  else
-    {
-      arg1 = xarg1;
-    }
-
-  if (!IS_AGGR_TYPE (type1) || TYPE_PTRMEMFUNC_P (type1))
-    {
-      /* Try to fail. First, fail if unary */
-      if (! try_second)
-       return rval;
-      /* Second, see if second argument is non-aggregate.  */
-      type2 = TREE_TYPE (xarg2);
-      if (TREE_CODE (type2) == OFFSET_TYPE)
-       type2 = TREE_TYPE (type2);
-      if (TREE_CODE (type2) == REFERENCE_TYPE)
-       {
-         arg2 = convert_from_reference (xarg2);
-         type2 = TREE_TYPE (arg2);
-       }
-      else
-       {
-         arg2 = xarg2;
-       }
-
-      if (!IS_AGGR_TYPE (type2))
-       return rval;
-      try_second = 0;
-    }
-
-  if (try_second)
-    {
-      /* First arg may succeed; see whether second should.  */
-      type2 = TREE_TYPE (xarg2);
-      if (TREE_CODE (type2) == OFFSET_TYPE)
-       type2 = TREE_TYPE (type2);
-      if (TREE_CODE (type2) == REFERENCE_TYPE)
-       {
-         arg2 = convert_from_reference (xarg2);
-         type2 = TREE_TYPE (arg2);
-       }
-      else
-       {
-         arg2 = xarg2;
-       }
-
-      if (! IS_AGGR_TYPE (type2))
-       try_second = 0;
-    }
-
-  if (type1 == unknown_type_node
-      || (try_second && TREE_TYPE (xarg2) == unknown_type_node))
-    {
-      /* This will not be implemented in the foreseeable future.  */
-      return rval;
-    }
-
-  if (code == MODIFY_EXPR)
-    fnname = ansi_assopname[(int) TREE_CODE (arg3)];
-  else
-    fnname = ansi_opname[(int) code];
-
-  global_fn = lookup_name_nonclass (fnname);
-
-  /* This is the last point where we will accept failure.  This
-     may be too eager if we wish an overloaded operator not to match,
-     but would rather a normal operator be called on a type-converted
-     argument.  */
-
-  if (IS_AGGR_TYPE (type1))
-    {
-      fields1 = lookup_fnfields (TYPE_BINFO (type1), fnname, 0);
-      /* ARM $13.4.7, prefix/postfix ++/--.  */
-      if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
-       {
-         xarg2 = integer_zero_node;
-         binary_is_unary = 0;
-
-         if (fields1)
-           {
-             tree t, t2;
-             int have_postfix = 0;
-
-             /* Look for an `operator++ (int)'.  If they didn't have
-                one, then we fall back to the old way of doing things.  */
-             for (t = TREE_VALUE (fields1); t ; t = DECL_CHAIN (t))
-               {
-                 t2 = TYPE_ARG_TYPES (TREE_TYPE (t));
-                 if (TREE_CHAIN (t2) != NULL_TREE
-                     && TREE_VALUE (TREE_CHAIN (t2)) == integer_type_node)
-                   {
-                     have_postfix = 1;
-                     break;
-                   }
-               }
-
-             if (! have_postfix)
-               {
-                 char *op = POSTINCREMENT_EXPR ? "++" : "--";
-
-                 /* There's probably a LOT of code in the world that
-                    relies upon this old behavior.  */
-                 pedwarn ("no `operator%s (int)' declared for postfix `%s', using prefix operator instead",
-                          op, op);
-                 xarg2 = NULL_TREE;
-                 binary_is_unary = 1;
-               }
-           }
-       }
-    }
-
-  if (fields1 == NULL_TREE && global_fn == NULL_TREE)
-    return rval;
-
-  /* If RVAL winds up being `error_mark_node', we will return
-     that... There is no way that normal semantics of these
-     operators will succeed.  */
-
-  /* This argument may be an uncommitted OFFSET_REF.  This is
-     the case for example when dealing with static class members
-     which are referenced from their class name rather than
-     from a class instance.  */
-  if (TREE_CODE (xarg1) == OFFSET_REF
-      && TREE_CODE (TREE_OPERAND (xarg1, 1)) == VAR_DECL)
-    xarg1 = TREE_OPERAND (xarg1, 1);
-  if (try_second && xarg2 && TREE_CODE (xarg2) == OFFSET_REF
-      && TREE_CODE (TREE_OPERAND (xarg2, 1)) == VAR_DECL)
-    xarg2 = TREE_OPERAND (xarg2, 1);
-
-  if (global_fn)
-    flags |= LOOKUP_GLOBAL;
-
-  if (code == CALL_EXPR)
-    {
-      /* This can only be a member function.  */
-      return build_method_call (xarg1, fnname, xarg2,
-                               NULL_TREE, LOOKUP_NORMAL);
-    }
-  else if (tree_code_length[(int) code] == 1 || binary_is_unary)
-    {
-      parms = NULL_TREE;
-      rval = build_method_call (xarg1, fnname, NULL_TREE, NULL_TREE, flags);
-    }
-  else if (code == COND_EXPR)
-    {
-      parms = expr_tree_cons (NULL_TREE, xarg2, build_expr_list (NULL_TREE, arg3));
-      rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags);
-    }
-  else if (code == METHOD_CALL_EXPR)
-    {
-      /* must be a member function.  */
-      parms = expr_tree_cons (NULL_TREE, xarg2, arg3);
-      return build_method_call (xarg1, fnname, parms, NULL_TREE,
-                               LOOKUP_NORMAL);
-    }
-  else if (fields1)
-    {
-      parms = build_expr_list (NULL_TREE, xarg2);
-      rval = build_method_call (xarg1, fnname, parms, NULL_TREE, flags);
-    }
-  else
-    {
-      parms = expr_tree_cons (NULL_TREE, xarg1,
-                        build_expr_list (NULL_TREE, xarg2));
-      rval = build_overload_call (fnname, parms, flags);
-    }
-
-  return rval;
+  return build_new_op (code, flags, xarg1, xarg2, arg3);
 }
 \f
 /* This function takes an identifier, ID, and attempts to figure out what
index 36f8aafa5541d6c3e5946a32b47da653d074cd0f..dcc137396dceac16fc82b39ef2c9f4e40406d874 100644 (file)
@@ -3890,38 +3890,6 @@ tsubst (t, args, in_decl)
        if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
          grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
 
-       /* Look for matching decls for the moment.  */
-       if (! member && ! flag_ansi_overloading)
-         {
-           tree decls = lookup_name_nonclass (DECL_NAME (t));
-           tree d = NULL_TREE;
-    
-           if (decls == NULL_TREE)
-             /* no match */;
-           else if (is_overloaded_fn (decls))
-             for (decls = get_first_fn (decls); decls;
-                  decls = DECL_CHAIN (decls))
-               {
-                 if (TREE_CODE (decls) == FUNCTION_DECL
-                     && TREE_TYPE (decls) == type)
-                   {
-                     d = decls;
-                     break;
-                   }
-               }
-
-           if (d)
-             {
-               int dcl_only = ! DECL_INITIAL (d);
-               if (dcl_only)
-                 DECL_INITIAL (r) = error_mark_node;
-               duplicate_decls (r, d);
-               r = d;
-               if (dcl_only)
-                 DECL_INITIAL (r) = 0;
-             }
-         }
-
        if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
          {
            DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE);
@@ -5539,7 +5507,7 @@ unify (tparms, targs, ntparms, parm, arg, strict)
       if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm))
        {
          tree t = NULL_TREE;
-         if (flag_ansi_overloading && ! strict)
+         if (! strict)
            t = get_template_base (CLASSTYPE_TI_TEMPLATE (parm), arg);
          else if
            (CLASSTYPE_TEMPLATE_INFO (arg)
index 13f171aa0a19280861645619a502451102c9b9c2..6ad4d39de9331ca36b2ff2dde97f424563426e07 100644 (file)
@@ -118,8 +118,6 @@ print_lang_type (file, node, indent)
     fputs (" has=", file);
   if (TYPE_HAS_ASSIGN_REF (node))
     fputs (" this=(X&)", file);
-  if (TYPE_OVERLOADS_METHOD_CALL_EXPR (node))
-    fputs (" op->()", file);
   if (TYPE_GETS_INIT_AGGR (node))
     fputs (" gets X(X, ...)", file);
   if (TYPE_OVERLOADS_CALL_EXPR (node))
index ce695e0b44d82c724c37c8549b128cb04e37a05c..7820f6ea3cf2ba93314902f9ebcb3ff0b1d558b0 100644 (file)
@@ -2470,24 +2470,10 @@ build_x_function_call (function, params, decl)
        }
       else
        {
-         tree val = TREE_VALUE (function);
-
-         if (flag_ansi_overloading)
-           {
-             /* Put back explicit template arguments, if any.  */
-             if (template_id)
-               function = template_id;
-             return build_new_function_call (function, params);
-           }
-
-         if (TREE_CODE (val) == TEMPLATE_DECL)
-           return build_overload_call_real
-             (function, params, LOOKUP_COMPLAIN, (struct candidate *)0, 0);
-         else if (DECL_CHAIN (val) != NULL_TREE)
-           return build_overload_call
-             (function, params, LOOKUP_COMPLAIN);
-         else
-           my_friendly_abort (360);
+         /* Put back explicit template arguments, if any.  */
+         if (template_id)
+           function = template_id;
+         return build_new_function_call (function, params);
        }
     }
 
@@ -3062,17 +3048,7 @@ build_x_binary_op (code, arg1, arg2)
   if (processing_template_decl)
     return build_min_nt (code, arg1, arg2);
 
-  if (flag_ansi_overloading)
-    return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
-
-  rval = build_opfncall (code, LOOKUP_SPECULATIVELY,
-                        arg1, arg2, NULL_TREE);
-  if (rval)
-    return build_opfncall (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
-  if (code == MEMBER_REF)
-    return build_m_component_ref (build_indirect_ref (arg1, NULL_PTR),
-                                 arg2);
-  return build_binary_op (code, arg1, arg2, 1);
+  return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
 }
 
 tree
@@ -4131,21 +4107,10 @@ build_x_unary_op (code, xarg)
     {
       tree rval;
 
-      if (flag_ansi_overloading)
-       {
-         rval = build_new_op (code, LOOKUP_NORMAL, xarg,
-                              NULL_TREE, NULL_TREE);
-         if (rval || code != ADDR_EXPR)
-           return rval;
-       }
-      else
-       {
-         rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg,
-                                NULL_TREE, NULL_TREE);
-         if (rval)
-           return build_opfncall (code, LOOKUP_NORMAL, xarg,
-                                  NULL_TREE, NULL_TREE);
-       }
+      rval = build_new_op (code, LOOKUP_NORMAL, xarg,
+                          NULL_TREE, NULL_TREE);
+      if (rval || code != ADDR_EXPR)
+       return rval;
     }
 
   if (code == ADDR_EXPR)
@@ -4907,16 +4872,7 @@ build_x_conditional_expr (ifexp, op1, op2)
   if (processing_template_decl)
     return build_min_nt (COND_EXPR, ifexp, op1, op2);
 
-  if (flag_ansi_overloading)
-    return build_new_op (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2);
-
-  /* See comments in `build_x_binary_op'.  */
-  if (op1 != 0)
-    rval = build_opfncall (COND_EXPR, LOOKUP_SPECULATIVELY, ifexp, op1, op2);
-  if (rval)
-    return build_opfncall (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2);
-  
-  return build_conditional_expr (ifexp, op1, op2);
+  return build_new_op (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2);
 }
 
 tree
@@ -7092,82 +7048,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
 
   if (IS_AGGR_TYPE (type)
       && (TYPE_NEEDS_CONSTRUCTING (type) || TREE_HAS_CONSTRUCTOR (rhs)))
-    {
-      if (flag_ansi_overloading)
-       return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
-
-      if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
-       {
-         /* This is sufficient to perform initialization.  No need,
-            apparently, to go through X(X&) to do first-cut
-            initialization.  Return through a TARGET_EXPR so that we get
-            cleanups if it is used.  */
-         if (TREE_CODE (rhs) == CALL_EXPR)
-           {
-             rhs = build_cplus_new (type, rhs);
-             return rhs;
-           }
-         /* Handle the case of default parameter initialization and
-            initialization of static variables.  */
-         else if (TREE_CODE (rhs) == TARGET_EXPR)
-           return rhs;
-         else if (TREE_CODE (rhs) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (rhs))
-           {
-             my_friendly_assert (TREE_CODE (TREE_OPERAND (rhs, 0)) == CALL_EXPR, 318);
-             if (exp)
-               {
-                 my_friendly_assert (TREE_VALUE (TREE_OPERAND (TREE_OPERAND (rhs, 0), 1)) == NULL_TREE, 316);
-                 TREE_VALUE (TREE_OPERAND (TREE_OPERAND (rhs, 0), 1))
-                   = build_unary_op (ADDR_EXPR, exp, 0);
-               }
-             else
-               rhs = build_cplus_new (type, TREE_OPERAND (rhs, 0));
-             return rhs;
-           }
-         else if (TYPE_HAS_TRIVIAL_INIT_REF (type))
-           return rhs;
-       }
-      if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)
-         || (IS_AGGR_TYPE (rhstype) && UNIQUELY_DERIVED_FROM_P (type, rhstype)))
-       {
-         if (TYPE_HAS_INIT_REF (type))
-           {
-             tree init = build_method_call (exp, ctor_identifier,
-                                            build_expr_list (NULL_TREE, rhs),
-                                            TYPE_BINFO (type), LOOKUP_NORMAL);
-
-             if (init == error_mark_node)
-               return error_mark_node;
-
-             if (exp == 0)
-               {
-                 exp = build_cplus_new (type, init);
-                 return exp;
-               }
-
-             return build (COMPOUND_EXPR, type, init, exp);
-           }
-
-         /* ??? The following warnings are turned off because
-            this is another place where the default X(X&) constructor
-            is implemented.  */
-         if (TYPE_HAS_ASSIGNMENT (type))
-           cp_warning ("bitwise copy: `%T' defines operator=", type);
-
-         if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
-           rhs = convert_from_reference (rhs);
-         if (type != rhstype)
-           {
-             tree nrhs = build1 (NOP_EXPR, type, rhs);
-             TREE_CONSTANT (nrhs) = TREE_CONSTANT (rhs);
-             rhs = nrhs;
-           }
-         return rhs;
-       }
-
-      return ocp_convert (type, rhs, CONV_OLD_CONVERT,
-                         flags | LOOKUP_NO_CONVERSION);
-    }
+    return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
 
   if (type == TREE_TYPE (rhs))
     {
This page took 0.19306 seconds and 5 git commands to generate.