86th Cygnus<->FSF quick merge
authorMike Stump <mrs@gcc.gnu.org>
Thu, 16 May 1996 18:43:00 +0000 (18:43 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Thu, 16 May 1996 18:43:00 +0000 (18:43 +0000)
From-SVN: r11974

17 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/init.c
gcc/cp/method.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/sig.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c

index ee57c7e..4b4c2b8 100644 (file)
@@ -3,6 +3,82 @@ Sat May 11 04:33:50 1996  Doug Evans  <dje@canuck.cygnus.com>
        * decl2.c (finish_vtable_vardecl): Surround DECL_ONE_ONLY with ifdef.
        (finish_file): Likewise.
 
+Wed May 15 14:46:14 1996  Mike Stump  <mrs@cygnus.com>
+
+       * call.c (build_method_call): Allow implicit & on METHOD_TYPEs,
+       but pedwarn as the code is bogus.
+       * typeck.c (decay_conversion): Ditto.
+       (build_function_call_real): Use build_addr_func instead of
+       default_conversion.  Don't allow pointer-to-method functions down
+       here.
+       (build_unary_op): Use real pointer-to-member functions instead of
+       fake ones.
+       (build_ptrmemfunc): Use build_addr_func instead of build_unary_op.
+       (convert_for_assignment): Removed some obsolete code.
+       * decl2.c (reparse_absdcl_as_expr): Pass current_class_ref to
+       build_x_function_call instead of current_class_ptr.  Only call
+       digest_init once on an initializer, we do this just checking
+       TREE_TYPE.
+       (build_expr_from_tree): Pass current_class_ref to
+       build_x_function_call instead of current_class_ptr.
+       * init.c (build_member_call): Ditto.
+       * pase.y: Ditto.
+       * error.c (dump_expr): Handle OFFSET_REFs better.
+       * pt.c (unify): Handle pointer-to-member functions better.
+       * decl.c (finish_function): Clear out current_class_ref just like
+       we do for current_class_ptr.
+
+       * typeck.c (get_delta_difference): Handle virtual bases better.
+
+Tue May 14 16:37:37 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * sig.c (build_signature_table_constructor): Use the delta for
+       the original basetype for this virtual function with thunks.
+       (build_signature_method_call): We still need to adjust 'this'
+       with thunks.
+
+Tue May 14 16:27:25 1996  Mike Stump  <mrs@cygnus.com>
+
+       * call.c (build_addr_func): New routine.  Used to get the `real'
+       address of a function or a method.  Needed to avoid getting a
+       pointer-to-member function.
+       (build_call): New routine to build CALL_EXPRs.
+       (build_method_call): Use it.
+       * cvt.c (convert_to_aggr): Ditto.
+       * typeck.c (build_function_call_real): Ditto.
+       * sig.c (build_signature_table_constructor): Use build_addr_func.
+       * cp-tree.h (build_call, build_addr_func): Declare them.
+
+Tue May 14 12:47:47 1996  Mike Stump  <mrs@cygnus.com>
+
+       * cp-tree.h (LOOKUP_AGGR): Remove, unused.
+       * parse.y: Remove uses of LOOKUP_AGGR.
+
+Tue May 14 12:07:51 1996  Mike Stump  <mrs@cygnus.com>
+
+       * *.[chy]: Rename current_class_decl to current_class_ptr, and
+       C_C_D to current_class_ref.
+
+Mon May 13 16:55:23 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * call.c (convert_harshness): Tighten up pointer conversions.
+
+Sat May 11 04:33:50 1996  Doug Evans  <dje@canuck.cygnus.com>
+
+       * decl2.c (finish_vtable_vardecl): Surround DECL_ONE_ONLY with ifdef.
+       (finish_file): Likewise.
+
+Fri May 10 11:09:57 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * cvt.c (convert_fn_ptr): We don't use thunks for pmfs.
+
+       * method.c (emit_thunk): Set flag_omit_frame_pointer in default
+       code.
+
+Thu May  9 18:18:30 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * decl2.c: Turn on thunks by default where supported.
+
 Tue May  7 20:39:57 1996  Mike Stump  <mrs@cygnus.com>
 
        * cp-tree.h (build_overload_call_maybe): Removed.
index a50c588..f51d09b 100644 (file)
@@ -506,12 +506,6 @@ convert_harshness (type, parmtype, parm)
       if (TREE_CODE (ttl) != VOID_TYPE
          && (TREE_CODE (ttr) != VOID_TYPE || !parm || !integer_zerop (parm)))
        {
-         if (TREE_UNSIGNED (ttl) != TREE_UNSIGNED (ttr))
-           {
-             ttl = unsigned_type (ttl);
-             ttr = unsigned_type (ttr);
-             penalty = 10;
-           }
          if (comp_target_types (type, parmtype, 1) <= 0)
            return EVIL_RETURN (h);
        }
@@ -526,22 +520,18 @@ convert_harshness (type, parmtype, parm)
        return EVIL_RETURN (h);
 #endif
 
-      if (penalty == 10 || ttr == ttl)
+      if (ttr == ttl)
        {
          tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype);
 
-         /* If one was unsigned but the other wasn't, then we need to
-            do a standard conversion from T to unsigned T.  */
-         if (penalty == 10)
-           h.code = PROMO_CODE; /* was STD_CODE */
-         else
-           h.code = 0;
-
+         h.code = 0;
          /* Note conversion from `T*' to `const T*',
                               or `T*' to `volatile T*'.  */
-         if (ttl == ttr
-             && ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
-                 || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2))))
+         if ((TYPE_READONLY (tmp1) < TREE_READONLY (tmp2))
+             || (TYPE_VOLATILE (tmp1) < TYPE_VOLATILE (tmp2)))
+           h.code = EVIL_CODE;
+         else if ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
+                  || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2)))
            h.code |= QUAL_CODE;
 
          h.distance = 0;
@@ -580,8 +570,11 @@ convert_harshness (type, parmtype, parm)
       if (ttl != ttr)
        {
          tree tmp1 = TREE_TYPE (type), tmp2 = TREE_TYPE (parmtype);
-         if ((TYPE_READONLY (tmp1) != TREE_READONLY (tmp2))
-             || (TYPE_VOLATILE (tmp1) != TYPE_VOLATILE (tmp2)))
+         if ((TYPE_READONLY (tmp1) < TREE_READONLY (tmp2))
+             || (TYPE_VOLATILE (tmp1) < TYPE_VOLATILE (tmp2)))
+           h.code = EVIL_CODE;
+         else if ((TYPE_READONLY (tmp1) > TREE_READONLY (tmp2))
+                  || (TYPE_VOLATILE (tmp1) > TYPE_VOLATILE (tmp2)))
            h.code |= QUAL_CODE;
        }
       return h;
@@ -1192,7 +1185,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
 {
   tree field, instance;
 
-  if (instance_ptr == current_class_decl)
+  if (instance_ptr == current_class_ptr)
     {
       /* Check to see if we really have a reference to an instance variable
         with `operator()()' overloaded.  */
@@ -1208,7 +1201,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
        {
          /* If it's a field, try overloading operator (),
             or calling if the field is a pointer-to-function.  */
-         instance = build_component_ref_1 (C_C_D, field, 0);
+         instance = build_component_ref_1 (current_class_ref, field, 0);
          if (instance == error_mark_node)
            return error_mark_node;
 
@@ -1221,7 +1214,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
              if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE)
                return build_function_call (instance, parms);
              else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == METHOD_TYPE)
-               return build_function_call (instance, tree_cons (NULL_TREE, current_class_decl, parms));
+               return build_function_call (instance, tree_cons (NULL_TREE, current_class_ptr, parms));
            }
        }
       return NULL_TREE;
@@ -1527,6 +1520,71 @@ print_n_candidates (candidates, n)
     cp_error_at ("                %D", candidates[i].function);
 }
 
+/* We want the address of a function or method.  We avoid creating a
+   pointer-to-member function.  */
+tree
+build_addr_func (function)
+     tree function;
+{
+  tree type = TREE_TYPE (function);
+
+  /* We have to do these by hand to avoid real pointer to member
+     functions.  */
+  if (TREE_CODE (type) == METHOD_TYPE)
+    {
+      tree addr;
+
+      type = build_pointer_type (type);
+
+      if (mark_addressable (function) == 0)
+       return error_mark_node;
+
+      addr = build1 (ADDR_EXPR, type, function);
+
+      /* Address of a static or external variable or function counts
+        as a constant */
+      if (staticp (function))
+       TREE_CONSTANT (addr) = 1;
+
+      function = addr;
+    }
+  else
+    function = default_conversion (function);
+
+  return function;
+}
+
+/* Build a CALL_EXPR, we can handle FUNCTION_TYPEs, METHOD_TYPEs, or
+   POINTER_TYPE to those.  Note, pointer to member function types
+   (TYPE_PTRMEMFUNC_P) must be handled by our callers.  */
+tree
+build_call (function, result_type, parms)
+     tree function, result_type, parms;
+{
+  int is_constructor = 0;
+
+  function = build_addr_func (function);
+
+  if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
+    {
+      sorry ("unable to call pointer to member function here");
+      return error_mark_node;
+    }
+
+  if (TREE_CODE (function) == ADDR_EXPR
+      && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
+      && DECL_CONSTRUCTOR_P (TREE_OPERAND (function, 0)))
+    is_constructor = 1;
+
+  function = build_nt (CALL_EXPR, function, parms, NULL_TREE);
+  TREE_HAS_CONSTRUCTOR (function) = is_constructor;
+  TREE_TYPE (function) = result_type;
+  TREE_SIDE_EFFECTS (function) = 1;
+  
+  return function;
+}
+
+
 /* Build something of the form ptr->method (args)
    or object.method (args).  This can also build
    calls to constructors, and find friends.
@@ -1739,11 +1797,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
          return error_mark_node;
        }
     }
-  else if (instance == C_C_D || instance == current_class_decl)
+  else if (instance == current_class_ref || instance == current_class_ptr)
     {
       /* When doing initialization, we side-effect the TREE_TYPE of
-        C_C_D, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE.  */
-      basetype = TREE_TYPE (C_C_D);
+        current_class_ref, hence we cannot set up BASETYPE from CURRENT_CLASS_TYPE.  */
+      basetype = TREE_TYPE (current_class_ref);
 
       /* Anything manifestly `this' in constructors and destructors
         has a known type, so virtual function tables are not needed.  */
@@ -1765,8 +1823,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
        }
       else
        {
-         instance = C_C_D;
-         instance_ptr = current_class_decl;
+         instance = current_class_ref;
+         instance_ptr = current_class_ptr;
          basetype_path = TYPE_BINFO (current_class_type);
        }
       result = build_field_call (basetype_path, instance_ptr, name, parms);
@@ -1940,9 +1998,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
          TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm));
          t = TREE_TYPE (TREE_VALUE (parm));
        }
-      if (TREE_CODE (TREE_VALUE (parm)) == OFFSET_REF
-         && TREE_CODE (t) == METHOD_TYPE)
+      if (TREE_CODE (t) == METHOD_TYPE)
        {
+         cp_pedwarn ("assuming & on `%E'", TREE_VALUE (parm));
          TREE_VALUE (parm) = build_unary_op (ADDR_EXPR, TREE_VALUE (parm), 0);
        }
 #if 0
@@ -2365,7 +2423,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
      type (if it exists) is a pointer to.  */
 
   if (DECL_ABSTRACT_VIRTUAL_P (function)
-      && instance == C_C_D
+      && instance == current_class_ref
       && DECL_CONSTRUCTOR_P (current_function_decl)
       && ! (flags & LOOKUP_NONVIRTUAL)
       && value_member (function, get_abstract_virtuals (basetype)))
@@ -2422,7 +2480,7 @@ build_method_call (instance, name, parms, basetype_path, flags)
     {
       /* Let's be nasty to the user now, and give reasonable
         error messages.  */
-      instance_ptr = current_class_decl;
+      instance_ptr = current_class_ptr;
       if (instance_ptr)
        {
          if (basetype != current_class_type)
@@ -2540,21 +2598,9 @@ build_method_call (instance, name, parms, basetype_path, flags)
     GNU_xref_call (current_function_decl,
                   IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (function)));
 
-  {
-    int is_constructor
-      = TREE_CODE (function) == FUNCTION_DECL
-       && DECL_CONSTRUCTOR_P (function);
-
-    function = default_conversion (function);
-
-    result = build_nt (CALL_EXPR, function, parms, NULL_TREE);
-
-    TREE_TYPE (result) = value_type;
-    TREE_SIDE_EFFECTS (result) = 1;
-    TREE_HAS_CONSTRUCTOR (result) = is_constructor;
-    result = convert_from_reference (result);
-    return result;
-  }
+  result = build_call (function, value_type, parms);
+  result = convert_from_reference (result);
+  return result;
 }
 
 /* Similar to `build_method_call', but for overloaded non-member functions.
index 4f1f23a..4c6cf3e 100644 (file)
@@ -72,7 +72,9 @@ struct class_level
   int unused;
 };
 
-tree current_class_decl, C_C_D;        /* PARM_DECL: the class instance variable */
+/* The currect_class_ptr is the pointer to the current class.
+   current_class_ref is the actual current class.  */
+tree current_class_ptr, current_class_ref;
 
 /* The following two can be derived from the previous one */
 tree current_class_name;       /* IDENTIFIER_NODE: name of current class */
@@ -434,7 +436,7 @@ build_vtbl_ref (instance, idx)
   if (TREE_CODE (basetype) == REFERENCE_TYPE)
     basetype = TREE_TYPE (basetype);
 
-  if (instance == C_C_D)
+  if (instance == current_class_ref)
     vtbl = build_indirect_ref (build_vfield_ref (instance, basetype),
                               NULL_PTR);
   else
@@ -4494,7 +4496,7 @@ resolves_to_fixed_type_p (instance, nonnull)
        }
       else if (nonnull)
        {
-         if (instance == current_class_decl
+         if (instance == current_class_ptr
              && flag_this_is_variable <= 0)
            {
              /* Some people still use `this = 0' inside destructors.  */
@@ -4941,12 +4943,6 @@ instantiate_type (lhstype, rhs, complain)
        tree elem, baselink, name;
        int globals = overloaded_globals_p (rhs);
 
-#if 0 /* obsolete */
-       /* If there's only one function we know about, return that.  */
-       if (globals > 0 && TREE_CHAIN (rhs) == NULL_TREE)
-         return TREE_VALUE (rhs);
-#endif
-
        /* First look for an exact match.  Search either overloaded
           functions or member functions.  May have to undo what
           `default_conversion' might do to lhstype.  */
index d6db7a0..cb850e0 100644 (file)
@@ -1002,7 +1002,7 @@ struct lang_decl
 
 /* Nonzero for FUNCTION_DECL means that this constructor is known to
    not make any assignment to `this', and therefore can be trusted
-   to return it unchanged.  Otherwise, we must re-assign `current_class_decl'
+   to return it unchanged.  Otherwise, we must re-assign `current_class_ptr'
    after performing base initializations.  */
 #define DECL_PRESERVES_THIS(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.preserves_first_arg)
 
@@ -1551,7 +1551,8 @@ extern tree current_lang_name, lang_name_cplusplus, lang_name_c;
    of CURRENT_FUNCTION_DECL due to overloading */
 extern tree original_function_name;
 
-extern tree current_class_name, current_class_type, current_class_decl, C_C_D;
+extern tree current_class_name, current_class_type;
+extern tree current_class_ptr, current_class_ref;
 
 /* in init.c  */
 extern tree global_base_init_list;
@@ -1820,8 +1821,6 @@ extern int at_eof;
 
 enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
 
-extern tree current_class_decl, C_C_D; /* PARM_DECL: the class instance variable */
-
 /* The following two can be derived from the previous one */
 extern tree current_class_name;        /* IDENTIFIER_NODE: name of current class */
 extern tree current_class_type;        /* _TYPE: the type of the current class */
@@ -1838,7 +1837,6 @@ extern tree current_class_type;   /* _TYPE: the type of the current class */
    LOOKUP_COMPLAIN mean complain if no suitable member function
      matching the arguments is found.
    LOOKUP_NORMAL is just a combination of these two.
-   LOOKUP_AGGR requires the instance to be of aggregate type.
    LOOKUP_NONVIRTUAL means make a direct call to the member function found
    LOOKUP_GLOBAL means search through the space of overloaded functions,
      as well as the space of member functions.
@@ -1858,7 +1856,7 @@ extern tree current_class_type;   /* _TYPE: the type of the current class */
 #define LOOKUP_PROTECT (1)
 #define LOOKUP_COMPLAIN (2)
 #define LOOKUP_NORMAL (3)
-#define LOOKUP_AGGR (4)
+/* #define LOOKUP_UNUSED (4) */
 #define LOOKUP_NONVIRTUAL (8)
 #define LOOKUP_GLOBAL (16)
 #define LOOKUP_HAS_IN_CHARGE (32)
@@ -1941,6 +1939,8 @@ extern int get_arglist_len_in_bytes               PROTO((tree));
 extern tree build_vfield_ref                   PROTO((tree, tree));
 extern tree find_scoped_type                   PROTO((tree, tree, tree));
 extern tree resolve_scope_to_name              PROTO((tree, tree));
+extern tree build_call                         PROTO((tree, tree, tree));
+extern tree build_addr_func                    PROTO((tree));
 extern tree build_scoped_method_call           PROTO((tree, 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));
index 5c09175..972939e 100644 (file)
@@ -82,6 +82,7 @@ static tree
 convert_fn_ptr (type, expr)
      tree type, expr;
 {
+#if 0                          /* We don't use thunks for pmfs.  */
   if (flag_vtable_thunks)
     {
       tree intype = TREE_TYPE (expr);
@@ -104,6 +105,7 @@ convert_fn_ptr (type, expr)
       return build1 (NOP_EXPR, type, build_thunk (BINFO_OFFSET (binfo), expr));
     }
   else
+#endif
     return build_ptrmemfunc (type, expr, 1);
 }
 
@@ -477,7 +479,7 @@ build_up_reference (type, arg, flags, checkconst)
 
     case PARM_DECL:
 #if 0
-      if (targ == current_class_decl)
+      if (targ == current_class_ptr)
        {
          error ("address of `this' not available");
 /* #if 0 */      
@@ -1056,14 +1058,11 @@ convert_to_aggr (type, expr, msgp, protect)
     return NULL_TREE;
 
   fntype = TREE_TYPE (function);
-  function = default_conversion (function);
-
-  result = build_nt (CALL_EXPR, function,
-                    convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
-                                       parmlist, NULL_TREE, LOOKUP_NORMAL),
-                    NULL_TREE);
-  TREE_TYPE (result) = TREE_TYPE (fntype);
-  TREE_SIDE_EFFECTS (result) = 1;
+
+  parmlist = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),
+                               parmlist, NULL_TREE, LOOKUP_NORMAL);
+
+  result = build_call (function, TREE_TYPE (fntype), parmlist);
   return result;
 }
 
@@ -1809,3 +1808,166 @@ type_promotes_to (type)
 
   return cp_build_type_variant (type, constp, volatilep);
 }
+
+#if 0
+/* Work in progress.  Ask jason before removing. */
+
+int
+null_ptr_cst (t)
+     tree t;
+{
+  return (INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t));
+}
+
+tree
+standard_conversion (to, from, expr)
+     tree to, from, expr;
+{
+  enum tree_code fcode = TREE_CODE (from);
+  enum tree_code tcode = TREE_CODE (to);
+  tree conv;
+
+  if (from == to)
+    return from;
+
+  conv = from;
+
+  if (fcode == FUNCTION_TYPE)
+    {
+      from = build_pointer_type (from);
+      fcode = TREE_CODE (from);
+      conv = build1 (LVALUE_CONV, from, conv);
+    }
+  else if (fcode == ARRAY_TYPE)
+    {
+      from = build_pointer_type (TREE_TYPE (from));
+      fcode = TREE_CODE (from);
+      conv = build1 (LVALUE_CONV, from, conv);
+    }
+
+  if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to))
+      && expr && null_ptr_cst (expr))
+    {
+      conv = build1 (CONV_CONV, to, conv);
+    }
+  else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE)
+    {
+      enum tree_code ufcode = TREE_CODE (TREE_TYPE (from));
+      enum tree_code utcode = TREE_CODE (TREE_TYPE (to));
+
+      if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (from))),
+                    TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (to))), 1))
+       /* OK for now */;
+      else if (utcode == VOID_TYPE && ufcode != OFFSET_TYPE
+              && ufcode != FUNCTION_TYPE)
+       {
+         from = cp_build_type_variant (void_type_node,
+                                       TYPE_READONLY (TREE_TYPE (from)),
+                                       TYPE_VOLATILE (TREE_TYPE (from)));
+         conv = build1 (CONV_CONV, from, conv);
+       }
+      else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE)
+       {
+         tree fbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (from));
+         tree tbase = TYPE_OFFSET_BASETYPE (TREE_TYPE (to));
+
+         if (DERIVED_FROM_P (tbase, fbase)
+             && (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (from))),
+                            TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (to))),
+                            1)))
+           {
+             from = build_offset_type (tbase, TREE_TYPE (TREE_TYPE (from)));
+             conv = build1 (CONV_CONV, from, conv);
+           }
+         else
+           return 0;
+       }
+      else if (IS_AGGR_TYPE (TREE_TYPE (from))
+              && IS_AGGR_TYPE (TREE_TYPE (to)))
+       {
+         if (DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
+           {
+             from = cp_build_type_variant (TREE_TYPE (to),
+                                           TYPE_READONLY (TREE_TYPE (from)),
+                                           TYPE_VOLATILE (TREE_TYPE (from)));
+             conv = build1 (CONV_CONV, from, conv);
+           }
+         else
+           return 0;
+       }
+      else
+       return 0;
+
+      if (! comptypes (from, to, 1) && comp_ptr_ttypes (to, from))
+       {
+         from = to;
+         conv = build1 (QUAL_CONV, from, conv);
+       }
+    }
+  else if (TYPE_PTRMEMFUNC_P (to) && TYPE_PTRMEMFUNC_P (from))
+    {
+      tree fromfn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (from));
+      tree tofn = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (to));
+      tree fbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fromfn)));
+      tree tbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (tofn)));
+
+      if (! DERIVED_FROM_P (tbase, fbase)
+         || ! comptypes (TREE_TYPE (fromfn), TREE_TYPE (tofn), 1)
+         || ! compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)),
+                         TREE_CHAIN (TYPE_ARG_TYPES (tofn)), 1)
+         || TYPE_READONLY (fbase) != TYPE_READONLY (tbase)
+         || TYPE_VOLATILE (fbase) != TYPE_VOLATILE (tbase))
+       return 0;
+
+      from = cp_build_type_variant (tbase, TYPE_READONLY (fbase),
+                                   TYPE_VOLATILE (fbase));
+      from = build_cplus_method_type (from, TREE_TYPE (fromfn),
+                                     TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
+      conv = build1 (CONV_CONV, from, conv);
+    }
+  else if (tcode == BOOLEAN_TYPE)
+    {
+      if (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE
+         || fcode == POINTER_TYPE)
+       return build1 (CONV_CONV, to, conv);
+      else
+       return 0;
+    }
+  else if (INTEGRAL_CODE_P (tcode) || tcode == REAL_TYPE)
+    {
+      if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE))
+       return 0;
+      else if (to == type_promotes_to (from))
+       conv = build1 (PROMO_CONV, to, conv);
+      else 
+       conv = build1 (CONV_CONV, to, conv);
+    }
+  else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
+          && DERIVED_FROM_P (to, from))
+    {
+      conv = build1 (CONV_CONV, to, conv);
+    }
+  else
+    return 0;
+
+  return conv;
+}
+
+tree
+implicit_conversion (to, from, expr, flags)
+     tree to, from, expr;
+     int flags;
+{
+  tree conv = standard_conversion (to, from, expr);
+
+  if (conv || (flags & LOOKUP_NO_CONVERSION))
+    return conv;
+
+  flags |= LOOKUP_NO_CONVERSION;
+
+    /* try constructors */;
+    /* try conversion ops */;
+
+  return conv;
+}
+#endif
index 83ed195..73b5709 100644 (file)
@@ -3275,7 +3275,7 @@ pushdecl (x)
              if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL)
                warnstring = "declaration of `%s' shadows a parameter";
              else if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE
-                      && current_class_decl
+                      && current_class_ptr
                       && !TREE_STATIC (name))
                warnstring = "declaration of `%s' shadows a member of `this'";
              else if (oldlocal != NULL_TREE)
@@ -11075,14 +11075,14 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
       push_nested_class (ctype, 1);
 
       /* If we're compiling a friend function, neither of the variables
-        current_class_decl nor current_class_type will have values.  */
+        current_class_ptr nor current_class_type will have values.  */
       if (! doing_friend)
        {
          /* We know that this was set up by `grokclassfn'.
             We do not wait until `store_parm_decls', since evil
             parse errors may never get us to that point.  Here
             we keep the consistency between `current_class_type'
-            and `current_class_decl'.  */
+            and `current_class_ptr'.  */
          tree t = current_function_parms;
 
          my_friendly_assert (t != NULL_TREE
@@ -11093,14 +11093,14 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
              int i = suspend_momentary ();
 
              /* Fool build_indirect_ref.  */
-             current_class_decl = NULL_TREE;
-             C_C_D = build_indirect_ref (t, NULL_PTR);
-             current_class_decl = t;
+             current_class_ptr = NULL_TREE;
+             current_class_ref = build_indirect_ref (t, NULL_PTR);
+             current_class_ptr = t;
              resume_momentary (i);
            }
          else
            /* We're having a signature pointer here.  */
-           C_C_D = current_class_decl = t;
+           current_class_ref = current_class_ptr = t;
 
        }
     }
@@ -11110,7 +11110,7 @@ start_function (declspecs, declarator, raises, attrs, pre_parsed_p)
        push_nested_class (DECL_CONTEXT (decl1), 2);
       else
        push_memoized_context (0, 1);
-      current_class_decl = C_C_D = NULL_TREE;
+      current_class_ptr = current_class_ref = NULL_TREE;
     }
 
   pushlevel (0);
@@ -11502,7 +11502,7 @@ finish_function (lineno, call_poplevel, nested)
 
          if (current_function_assigns_this)
            cond = build (NE_EXPR, boolean_type_node,
-                         current_class_decl, integer_zero_node);
+                         current_class_ptr, integer_zero_node);
          else
            {
              int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
@@ -11541,10 +11541,10 @@ finish_function (lineno, call_poplevel, nested)
          /* These are two cases where we cannot delegate deletion.  */
          if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)
              || TYPE_GETS_REG_DELETE (current_class_type))
-           exprstmt = build_delete (current_class_type, C_C_D, integer_zero_node,
+           exprstmt = build_delete (current_class_type, current_class_ref, integer_zero_node,
                                     LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
          else
-           exprstmt = build_delete (current_class_type, C_C_D, in_charge_node,
+           exprstmt = build_delete (current_class_type, current_class_ref, in_charge_node,
                                     LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
 
          /* If we did not assign to this, then `this' is non-zero at
@@ -11576,7 +11576,7 @@ finish_function (lineno, call_poplevel, nested)
                    {
                      if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
                        {
-                         tree ptr = convert_pointer_to_vbase (BINFO_TYPE (vbases), current_class_decl);
+                         tree ptr = convert_pointer_to_vbase (BINFO_TYPE (vbases), current_class_ptr);
                          expand_expr_stmt (build_delete (build_pointer_type (BINFO_TYPE (vbases)),
                                                          ptr, integer_zero_node,
                                                          LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_HAS_IN_CHARGE, 0));
@@ -11605,11 +11605,11 @@ finish_function (lineno, call_poplevel, nested)
                          error_mark_node),
                  NULL_PTR),
                 ansi_opname[(int) DELETE_EXPR],
-                tree_cons (NULL_TREE, current_class_decl,
+                tree_cons (NULL_TREE, current_class_ptr,
                            build_tree_list (NULL_TREE, virtual_size)),
                 NULL_TREE, LOOKUP_NORMAL);
          else if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
-           exprstmt = build_x_delete (ptr_type_node, current_class_decl, 0,
+           exprstmt = build_x_delete (ptr_type_node, current_class_ptr, 0,
                                       virtual_size);
          else
            exprstmt = NULL_TREE;
@@ -11646,16 +11646,16 @@ finish_function (lineno, call_poplevel, nested)
              /* Make all virtual function table pointers in non-virtual base
                 classes point to CURRENT_CLASS_TYPE's virtual function
                 tables.  */
-             expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_decl);
+             expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_ptr);
 
              if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
-               expand_indirect_vtbls_init (binfo, C_C_D, current_class_decl);
+               expand_indirect_vtbls_init (binfo, current_class_ref, current_class_ptr);
            }
          
          if (! ok_to_optimize_dtor)
            {
              cond = build_binary_op (NE_EXPR,
-                                     current_class_decl, integer_zero_node, 1);
+                                     current_class_ptr, integer_zero_node, 1);
              expand_start_cond (cond, 0);
            }
 
@@ -11691,7 +11691,7 @@ finish_function (lineno, call_poplevel, nested)
                  expand_end_bindings (decls, decls != NULL_TREE, 0);
                  poplevel (decls != NULL_TREE, 0, 0);
                }
-             c_expand_return (current_class_decl);
+             c_expand_return (current_class_ptr);
            }
          else if (TYPE_MAIN_VARIANT (TREE_TYPE (
                                                 DECL_RESULT (current_function_decl))) != void_type_node
@@ -11715,8 +11715,8 @@ finish_function (lineno, call_poplevel, nested)
          if (flag_this_is_variable > 0)
            {
              cond = build_binary_op (EQ_EXPR,
-                                     current_class_decl, integer_zero_node, 1);
-             thenclause = build_modify_expr (current_class_decl, NOP_EXPR,
+                                     current_class_ptr, integer_zero_node, 1);
+             thenclause = build_modify_expr (current_class_ptr, NOP_EXPR,
                                              build_new (NULL_TREE, current_class_type, void_type_node, 0));
            }
 
@@ -11769,7 +11769,7 @@ finish_function (lineno, call_poplevel, nested)
              poplevel (decls != NULL_TREE, 1, 0);
            }
 
-         c_expand_return (current_class_decl);
+         c_expand_return (current_class_ptr);
 
          current_function_assigns_this = 0;
          current_function_just_assigned_this = 0;
@@ -11974,7 +11974,8 @@ finish_function (lineno, call_poplevel, nested)
     }
 
   named_label_uses = NULL_TREE;
-  current_class_decl = NULL_TREE;
+  current_class_ptr = NULL_TREE;
+  current_class_ref = NULL_TREE;
 }
 \f
 /* Create the FUNCTION_DECL for a function definition.
@@ -12412,8 +12413,8 @@ struct cp_function
   tree base_init_list;
   tree member_init_list;
   tree base_init_expr;
-  tree class_decl;
-  tree C_C_D;
+  tree current_class_ptr;
+  tree current_class_ref;
   rtx result_rtx;
   struct cp_function *next;
   struct binding_level *binding_level;
@@ -12459,8 +12460,8 @@ push_cp_function_context (context)
   p->temp_name_counter = temp_name_counter;
   p->base_init_list = current_base_init_list;
   p->member_init_list = current_member_init_list;
-  p->class_decl = current_class_decl;
-  p->C_C_D = C_C_D;
+  p->current_class_ptr = current_class_ptr;
+  p->current_class_ref = current_class_ref;
 
   p->eh_context = push_eh_context ();
 }
@@ -12502,8 +12503,8 @@ pop_cp_function_context (context)
   temp_name_counter = p->temp_name_counter;
   current_base_init_list = p->base_init_list;
   current_member_init_list = p->member_init_list;
-  current_class_decl = p->class_decl;
-  C_C_D = p->C_C_D;
+  current_class_ptr = p->current_class_ptr;
+  current_class_ref = p->current_class_ref;
 
   pop_eh_context (p->eh_context);
 
index 2ca80b5..18fb1af 100644 (file)
@@ -155,9 +155,13 @@ int warn_implicit = 1;
 int warn_ctor_dtor_privacy = 1;
 
 /* True if we want to implement vtables using "thunks".
-   The default is off now, but will be on later. */
+   The default is off by default, on if explicitly supported. */
 
+#ifdef ASM_OUTPUT_MI_THUNK
+int flag_vtable_thunks = 1;
+#else
 int flag_vtable_thunks;
+#endif
 
 /* True if we want to deal with repository information.  */
 
@@ -3336,7 +3340,7 @@ reparse_absdcl_as_expr (type, decl)
   /* recurse */
   decl = reparse_decl_as_expr (type, TREE_OPERAND (decl, 0));
 
-  decl = build_x_function_call (decl, NULL_TREE, current_class_decl);
+  decl = build_x_function_call (decl, NULL_TREE, current_class_ref);
 
   if (TREE_CODE (decl) == CALL_EXPR && TREE_TYPE (decl) != void_type_node)
     decl = require_complete_type (decl);
@@ -3357,7 +3361,8 @@ reparse_absdcl_as_casts (decl, expr)
 {
   tree type;
   
-  if (TREE_CODE (expr) == CONSTRUCTOR)
+  if (TREE_CODE (expr) == CONSTRUCTOR
+      && TREE_TYPE (expr) == 0)
     {
       type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1)));
       decl = TREE_OPERAND (decl, 0);
@@ -3556,7 +3561,7 @@ build_expr_from_tree (t)
            name = build_expr_from_tree (name);
          return build_x_function_call
            (name, build_expr_from_tree (TREE_OPERAND (t, 1)),
-            current_class_decl);
+            current_class_ref);
        }
 
     case COND_EXPR:
index 652ed3f..1f66155 100644 (file)
@@ -1259,8 +1259,9 @@ dump_expr (t, nop)
          dump_expr (TREE_OPERAND (t, 1), 0);
        else
          {
-           sorry ("operand of OFFSET_REF not understood");
-           goto error;
+           dump_expr (TREE_OPERAND (t, 0), 0);
+           OB_PUTS (" .* ");
+           dump_expr (TREE_OPERAND (t, 1), 0);
          }
        break;
       }
index 45dc9c2..5695c98 100644 (file)
@@ -174,7 +174,7 @@ perform_member_init (member, name, init, explicit, protect_list)
       if (init != NULL_TREE && TREE_CODE (init) != TREE_LIST)
        init = build_tree_list (NULL_TREE, init);
 
-      decl = build_component_ref (C_C_D, name, NULL_TREE, explicit);
+      decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
 
       if (explicit
          && TREE_CODE (type) == ARRAY_TYPE
@@ -220,7 +220,7 @@ perform_member_init (member, name, init, explicit, protect_list)
         current_member_init_list.  */
       if (init || explicit)
        {
-         decl = build_component_ref (C_C_D, name, NULL_TREE, explicit);
+         decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
          expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
        }
     }
@@ -237,7 +237,7 @@ perform_member_init (member, name, init, explicit, protect_list)
 
   if (TYPE_NEEDS_DESTRUCTOR (type))
     {
-      tree expr = build_component_ref (C_C_D, name, NULL_TREE, explicit);
+      tree expr = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
       expr = build_delete (type, expr, integer_zero_node,
                           LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
 
@@ -487,7 +487,7 @@ build_partial_cleanup_for (binfo)
      tree binfo;
 {
   tree expr = convert_pointer_to_real (binfo,
-                                      build_unary_op (ADDR_EXPR, C_C_D, 0));
+                                      build_unary_op (ADDR_EXPR, current_class_ref, 0));
 
   return build_delete (TREE_TYPE (expr),
                       expr,
@@ -561,7 +561,7 @@ emit_base_init (t, immediately)
       tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
 
       expand_start_cond (first_arg, 0);
-      expand_aggr_vbase_init (t_binfo, C_C_D, current_class_decl,
+      expand_aggr_vbase_init (t_binfo, current_class_ref, current_class_ptr,
                              vbase_init_list);
       expand_end_cond ();
     }
@@ -596,7 +596,7 @@ emit_base_init (t, immediately)
          push_temp_slots ();
          target_temp_slot_level = temp_slot_level;
 
-         member = convert_pointer_to_real (base_binfo, current_class_decl);
+         member = convert_pointer_to_real (base_binfo, current_class_ptr);
          expand_aggr_init_1 (base_binfo, NULL_TREE,
                              build_indirect_ref (member, NULL_PTR), init,
                              BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL);
@@ -626,11 +626,11 @@ emit_base_init (t, immediately)
   /* Initialize all the virtual function table fields that
      do come from virtual base classes. */
   if (TYPE_USES_VIRTUAL_BASECLASSES (t))
-    expand_indirect_vtbls_init (t_binfo, C_C_D, current_class_decl);
+    expand_indirect_vtbls_init (t_binfo, current_class_ref, current_class_ptr);
 
   /* Initialize all the virtual function table fields that
      do not come from virtual base classes.  */
-  expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_decl);
+  expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_ptr);
 
   for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
     {
@@ -863,7 +863,7 @@ do_member_init (s_id, name, init)
       return;
     }
 
-  base = convert_pointer_to (binfo, current_class_decl);
+  base = convert_pointer_to (binfo, current_class_ptr);
   expand_member_init (build_indirect_ref (base, NULL_PTR), name, init);
 }
 
@@ -1139,8 +1139,9 @@ expand_member_init (exp, name, init)
    explaining that such initializations are invalid.
 
    ALIAS_THIS is nonzero iff we are initializing something which is
-   essentially an alias for C_C_D.  In this case, the base constructor
-   may move it on us, and we must keep track of such deviations.
+   essentially an alias for current_class_ref.  In this case, the base
+   constructor may move it on us, and we must keep track of such
+   deviations.
 
    If INIT resolves to a CALL_EXPR which happens to return
    something of the type we are looking for, then we know
@@ -1160,8 +1161,7 @@ expand_member_init (exp, name, init)
    initialization.
 
    A constructor or a conversion operator may have to be used to
-   perform the initialization, but not both, as it would be ambiguous.
-   */
+   perform the initialization, but not both, as it would be ambiguous. */
 
 void
 expand_aggr_init (exp, init, alias_this, flags)
@@ -1318,8 +1318,8 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
             value is used in the derived class.  */
          if ((flag_this_is_variable & 1) && alias_this)
            {
-             TREE_TYPE (rval) = TREE_TYPE (current_class_decl);
-             expand_assignment (current_class_decl, rval, 0, 0);
+             TREE_TYPE (rval) = TREE_TYPE (current_class_ptr);
+             expand_assignment (current_class_ptr, rval, 0, 0);
            }
          else
            expand_expr_stmt (rval);
@@ -1676,7 +1676,7 @@ build_member_call (type, name, parmlist)
       tree ns = lookup_name (type, 0);
       if (ns && TREE_CODE (ns) == NAMESPACE_DECL)
        {
-         return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_decl);
+         return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_ref);
        }
     }
 
@@ -1705,14 +1705,14 @@ build_member_call (type, name, parmlist)
       basetype_path = TYPE_BINFO (type);
       decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
     }
-  else if (current_class_decl == 0)
+  else if (current_class_ptr == 0)
     {
       dont_use_this = 1;
       decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);
     }
   else
     {
-      tree olddecl = current_class_decl;
+      tree olddecl = current_class_ptr;
       tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));
       if (oldtype != type)
        {
@@ -1846,10 +1846,10 @@ build_offset_ref (type, name)
       basebinfo = TYPE_BINFO (type);
       decl = build1 (NOP_EXPR, type, error_mark_node);
     }
-  else if (current_class_decl == 0)
+  else if (current_class_ptr == 0)
     decl = build1 (NOP_EXPR, type, error_mark_node);
   else
-    decl = C_C_D;
+    decl = current_class_ref;
 
   if (constructor_name (BINFO_TYPE (basebinfo)) == name)
     if (dtor)
@@ -1978,7 +1978,12 @@ resolve_offset_ref (exp)
   if (TREE_CODE (exp) == TREE_LIST)
     return build_unary_op (ADDR_EXPR, exp, 0);
 
-  if (TREE_CODE (exp) != OFFSET_REF)
+  if (TREE_CODE (exp) == OFFSET_REF)
+    {
+      member = TREE_OPERAND (exp, 1);
+      base = TREE_OPERAND (exp, 0);
+    }
+  else
     {
       my_friendly_assert (TREE_CODE (type) == OFFSET_TYPE, 214);
       if (TYPE_OFFSET_BASETYPE (type) != current_class_type)
@@ -1988,12 +1993,7 @@ resolve_offset_ref (exp)
        }
       member = exp;
       type = TREE_TYPE (type);
-      base = C_C_D;
-    }
-  else
-    {
-      member = TREE_OPERAND (exp, 1);
-      base = TREE_OPERAND (exp, 0);
+      base = current_class_ref;
     }
 
   if ((TREE_CODE (member) == VAR_DECL
@@ -2008,7 +2008,7 @@ resolve_offset_ref (exp)
 
   /* Syntax error can cause a member which should
      have been seen as static to be grok'd as non-static.  */
-  if (TREE_CODE (member) == FIELD_DECL && C_C_D == NULL_TREE)
+  if (TREE_CODE (member) == FIELD_DECL && current_class_ref == NULL_TREE)
     {
       if (TREE_ADDRESSABLE (member) == 0)
        {
@@ -2022,7 +2022,7 @@ resolve_offset_ref (exp)
 
   /* The first case is really just a reference to a member of `this'.  */
   if (TREE_CODE (member) == FIELD_DECL
-      && (base == C_C_D
+      && (base == current_class_ref
          || (TREE_CODE (base) == NOP_EXPR
              && TREE_OPERAND (base, 0) == error_mark_node)))
     {
@@ -2033,7 +2033,7 @@ resolve_offset_ref (exp)
       else
        basetype = DECL_CONTEXT (member);
 
-      base = current_class_decl;
+      base = current_class_ptr;
       
       if (get_base_distance (basetype, TREE_TYPE (TREE_TYPE (base)), 0, &basetype_path) < 0)
        {
@@ -3555,8 +3555,8 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
        addr = convert_force (build_pointer_type (type), addr, 0);
 
       if (TREE_CODE (addr) == NOP_EXPR
-         && TREE_OPERAND (addr, 0) == current_class_decl)
-       ref = C_C_D;
+         && TREE_OPERAND (addr, 0) == current_class_ptr)
+       ref = current_class_ref;
       else
        ref = build_indirect_ref (addr, NULL_PTR);
       ptr = 0;
index 5d16db6..79761e9 100644 (file)
@@ -1549,19 +1549,19 @@ hack_identifier (value, name)
   type = TREE_TYPE (value);
   if (TREE_CODE (value) == FIELD_DECL)
     {
-      if (current_class_decl == NULL_TREE)
+      if (current_class_ptr == NULL_TREE)
        {
          error ("request for member `%s' in static member function",
                 IDENTIFIER_POINTER (DECL_NAME (value)));
          return error_mark_node;
        }
-      TREE_USED (current_class_decl) = 1;
+      TREE_USED (current_class_ptr) = 1;
 
       /* Mark so that if we are in a constructor, and then find that
         this field was initialized by a base initializer,
         we can emit an error message.  */
       TREE_USED (value) = 1;
-      value = build_component_ref (C_C_D, name, NULL_TREE, 1);
+      value = build_component_ref (current_class_ref, name, NULL_TREE, 1);
     }
   else if (really_overloaded_fn (value))
     {
@@ -1653,141 +1653,6 @@ hack_identifier (value, name)
 }
 
 \f
-#if 0
-/* Given an object OF, and a type conversion operator COMPONENT
-   build a call to the conversion operator, if a call is requested,
-   or return the address (as a pointer to member function) if one is not.
-
-   OF can be a TYPE_DECL or any kind of datum that would normally
-   be passed to `build_component_ref'.  It may also be NULL_TREE,
-   in which case `current_class_type' and `current_class_decl'
-   provide default values.
-
-   BASETYPE_PATH, if non-null, is the path of basetypes
-   to go through before we get the the instance of interest.
-
-   PROTECT says whether we apply C++ scoping rules or not.  */
-tree
-build_component_type_expr (of, component, basetype_path, protect)
-     tree of, component, basetype_path;
-     int protect;
-{
-  tree cname = NULL_TREE;
-  tree tmp, last;
-  tree name;
-  int flags = protect ? LOOKUP_NORMAL : LOOKUP_COMPLAIN;
-
-  if (of)
-    my_friendly_assert (IS_AGGR_TYPE (TREE_TYPE (of)), 253);
-  my_friendly_assert (TREE_CODE (component) == TYPE_EXPR, 254);
-
-  tmp = TREE_OPERAND (component, 0);
-  last = NULL_TREE;
-
-  while (tmp)
-    {
-      switch (TREE_CODE (tmp))
-       {
-       case CALL_EXPR:
-         if (last)
-           TREE_OPERAND (last, 0) = TREE_OPERAND (tmp, 0);
-         else
-           TREE_OPERAND (component, 0) = TREE_OPERAND (tmp, 0);
-
-         last = groktypename (build_tree_list (TREE_TYPE (component),
-                                               TREE_OPERAND (component, 0)));
-         name = build_typename_overload (last);
-         TREE_TYPE (name) = last;
-
-         if (TREE_OPERAND (tmp, 0)
-             && TREE_OPERAND (tmp, 0) != void_list_node)
-           {
-             cp_error ("`operator %T' requires empty parameter list", last);
-             TREE_OPERAND (tmp, 0) = NULL_TREE;
-           }
-
-         if (of && TREE_CODE (of) != TYPE_DECL)
-           return build_method_call (of, name, NULL_TREE, NULL_TREE, flags);
-         else if (of)
-           {
-             tree this_this;
-
-             if (current_class_decl == NULL_TREE)
-               {
-                 cp_error ("object required for `operator %T' call",
-                           TREE_TYPE (name));
-                 return error_mark_node;
-               }
-
-             this_this = convert_pointer_to (TREE_TYPE (of),
-                                             current_class_decl);
-             this_this = build_indirect_ref (this_this, NULL_PTR);
-             return build_method_call (this_this, name, NULL_TREE,
-                                       NULL_TREE, flags | LOOKUP_NONVIRTUAL);
-           }
-         else if (current_class_decl)
-           return build_method_call (tmp, name, NULL_TREE, NULL_TREE, flags);
-
-         cp_error ("object required for `operator %T' call",
-                   TREE_TYPE (name));
-         return error_mark_node;
-
-       case INDIRECT_REF:
-       case ADDR_EXPR:
-       case ARRAY_REF:
-         break;
-
-       case SCOPE_REF:
-         my_friendly_assert (cname == 0, 255);
-         cname = TREE_OPERAND (tmp, 0);
-         tmp = TREE_OPERAND (tmp, 1);
-         break;
-
-       default:
-         my_friendly_abort (77);
-       }
-      last = tmp;
-      tmp = TREE_OPERAND (tmp, 0);
-    }
-
-  last = groktypename (build_tree_list (TREE_TYPE (component), TREE_OPERAND (component, 0)));
-  name = build_typename_overload (last);
-  TREE_TYPE (name) = last;
-  if (of && TREE_CODE (of) == TYPE_DECL)
-    {
-      if (cname == NULL_TREE)
-       {
-         cname = DECL_NAME (of);
-         of = NULL_TREE;
-       }
-      else my_friendly_assert (cname == DECL_NAME (of), 256);
-    }
-
-  if (of)
-    {
-      tree this_this;
-
-      if (current_class_decl == NULL_TREE)
-       {
-         cp_error ("object required for `operator %T' call",
-                   TREE_TYPE (name));
-         return error_mark_node;
-       }
-
-      this_this = convert_pointer_to (TREE_TYPE (of), current_class_decl);
-      return build_component_ref (this_this, name, NULL_TREE, protect);
-    }
-  else if (cname)
-    return build_offset_ref (cname, name);
-  else if (current_class_name)
-    return build_offset_ref (current_class_name, name);
-
-  cp_error ("object required for `operator %T' member reference",
-           TREE_TYPE (name));
-  return error_mark_node;
-}
-#endif
-\f
 static char *
 thunk_printable_name (decl)
      tree decl;
@@ -1863,6 +1728,7 @@ emit_thunk (thunk_fndecl)
   char *fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
   int tem;
   int failure = 0;
+  int save_ofp;
 
   /* Used to remember which regs we need to emit a USE rtx for. */
   rtx need_use[FIRST_PSEUDO_REGISTER];
@@ -1892,6 +1758,8 @@ emit_thunk (thunk_fndecl)
   ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
   assemble_end_function (thunk_fndecl, fnname);
 #else
+  save_ofp = flag_omit_frame_pointer;
+  flag_omit_frame_pointer = 1;
   init_function_start (thunk_fndecl, input_filename, lineno);
   pushlevel (0);
   expand_start_bindings (1);
@@ -2063,13 +1931,12 @@ emit_thunk (thunk_fndecl)
   final (insns, asm_out_file, optimize, 0);
   assemble_end_function (thunk_fndecl, fnname);
 
- exit_rest_of_compilation:
-
   reload_completed = 0;
 
   /* Cancel the effect of rtl_in_current_obstack.  */
 
   permanent_allocation (1);
+  flag_omit_frame_pointer = save_ofp;
 #endif /* ASM_OUTPUT_MI_THUNK */
 
   decl_printable_name = save_decl_printable_name;
@@ -2112,7 +1979,7 @@ do_build_copy_constructor (fndecl)
 
   if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
     {
-      t = build (INIT_EXPR, void_type_node, C_C_D, parm);
+      t = build (INIT_EXPR, void_type_node, current_class_ref, parm);
       TREE_SIDE_EFFECTS (t) = 1;
       cplus_expand_expr_stmt (t);
     }
@@ -2202,7 +2069,7 @@ do_build_assign_ref (fndecl)
 
   if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))
     {
-      tree t = build (MODIFY_EXPR, void_type_node, C_C_D, parm);
+      tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm);
       TREE_SIDE_EFFECTS (t) = 1;
       cplus_expand_expr_stmt (t);
     }
@@ -2253,13 +2120,13 @@ do_build_assign_ref (fndecl)
          else
            continue;
 
-         comp = build (COMPONENT_REF, TREE_TYPE (field), C_C_D, field);
+         comp = build (COMPONENT_REF, TREE_TYPE (field), current_class_ref, field);
          init = build (COMPONENT_REF, TREE_TYPE (field), parm, field);
 
          expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
        }
     }
-  c_expand_return (C_C_D);
+  c_expand_return (current_class_ref);
   pop_momentary ();
 }
 
index bd44fd4..adda622 100644 (file)
@@ -782,22 +782,22 @@ member_init: '(' nonnull_exprlist ')'
                {
                  if (current_class_name && !flag_traditional)
                    pedwarn ("anachronistic old style base class initializer");
-                 expand_member_init (C_C_D, NULL_TREE, $2);
+                 expand_member_init (current_class_ref, NULL_TREE, $2);
                }
        | LEFT_RIGHT
                {
                  if (current_class_name && !flag_traditional)
                    pedwarn ("anachronistic old style base class initializer");
-                 expand_member_init (C_C_D, NULL_TREE, void_type_node);
+                 expand_member_init (current_class_ref, NULL_TREE, void_type_node);
                }
        | notype_identifier '(' nonnull_exprlist ')'
-               { expand_member_init (C_C_D, $1, $3); }
+               { expand_member_init (current_class_ref, $1, $3); }
        | notype_identifier LEFT_RIGHT
-               { expand_member_init (C_C_D, $1, void_type_node); }
+               { expand_member_init (current_class_ref, $1, void_type_node); }
        | complete_type_name '(' nonnull_exprlist ')'
-               { expand_member_init (C_C_D, $1, $3); }
+               { expand_member_init (current_class_ref, $1, $3); }
        | complete_type_name LEFT_RIGHT
-               { expand_member_init (C_C_D, $1, void_type_node); }
+               { expand_member_init (current_class_ref, $1, void_type_node); }
        /* GNU extension */
        | notype_qualified_id '(' nonnull_exprlist ')'
                {
@@ -1046,12 +1046,7 @@ nonnull_exprlist:
 
 unary_expr:
          primary %prec UNARY
-               {
-#if 0
-                 if (TREE_CODE ($$) == TYPE_EXPR)
-                   $$ = build_component_type_expr (C_C_D, $$, NULL_TREE, 1);
-#endif
-               }
+               { $$ = $1; }
        /* __extension__ turns off -pedantic for following primary.  */
        | EXTENSION
                { $<itype>1 = pedantic;
@@ -1362,14 +1357,14 @@ primary:
                }
        | primary '(' nonnull_exprlist ')'
                 {
-                  $$ = build_x_function_call ($1, $3, current_class_decl); 
+                  $$ = build_x_function_call ($1, $3, current_class_ref); 
                   if (TREE_CODE ($$) == CALL_EXPR
                       && TREE_TYPE ($$) != void_type_node)
                    $$ = require_complete_type ($$);
                 }
        | primary LEFT_RIGHT
                 {
-                 $$ = build_x_function_call ($$, NULL_TREE, current_class_decl);
+                 $$ = build_x_function_call ($$, NULL_TREE, current_class_ref);
                  if (TREE_CODE ($$) == CALL_EXPR
                      && TREE_TYPE ($$) != void_type_node)
                    $$ = require_complete_type ($$);
@@ -1391,12 +1386,12 @@ primary:
                  $$ = build_x_unary_op (POSTDECREMENT_EXPR, $$); }
        /* C++ extensions */
        | THIS
-               { if (current_class_decl)
+               { if (current_class_ptr)
                    {
 #ifdef WARNING_ABOUT_CCD
-                     TREE_USED (current_class_decl) = 1;
+                     TREE_USED (current_class_ptr) = 1;
 #endif
-                     $$ = current_class_decl;
+                     $$ = current_class_ptr;
                    }
                  else if (current_function_decl
                           && DECL_STATIC_FUNCTION_P (current_function_decl))
@@ -1516,13 +1511,13 @@ primary:
                  /* This is a future direction of this code, but because
                     build_x_function_call cannot always undo what is done
                     in build_component_ref entirely yet, we cannot do this. */
-                 $$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), $4, $$);
+                 $$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), $4, current_class_ref);
                  if (TREE_CODE ($$) == CALL_EXPR
                      && TREE_TYPE ($$) != void_type_node)
                    $$ = require_complete_type ($$);
 #else
                  $$ = build_method_call ($$, $2, $4, NULL_TREE,
-                                         (LOOKUP_NORMAL|LOOKUP_AGGR));
+                                         LOOKUP_NORMAL);
 #endif
                }
        | object unqualified_id LEFT_RIGHT
@@ -1531,13 +1526,13 @@ primary:
                  /* This is a future direction of this code, but because
                     build_x_function_call cannot always undo what is done
                     in build_component_ref entirely yet, we cannot do this. */
-                 $$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), NULL_TREE, $$);
+                 $$ = build_x_function_call (build_component_ref ($$, $2, NULL_TREE, 1), NULL_TREE, current_class_ref);
                  if (TREE_CODE ($$) == CALL_EXPR
                      && TREE_TYPE ($$) != void_type_node)
                    $$ = require_complete_type ($$);
 #else
                  $$ = build_method_call ($$, $2, NULL_TREE, NULL_TREE,
-                                         (LOOKUP_NORMAL|LOOKUP_AGGR));
+                                         LOOKUP_NORMAL);
 #endif
                }
        | object overqualified_id '(' nonnull_exprlist ')'
@@ -1546,7 +1541,7 @@ primary:
                    {
                      warning ("signature name in scope resolution ignored");
                      $$ = build_method_call ($$, OP1 ($2), $4, NULL_TREE,
-                                             (LOOKUP_NORMAL|LOOKUP_AGGR));
+                                             LOOKUP_NORMAL);
                    }
                  else
                    $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), $4);
@@ -1557,7 +1552,7 @@ primary:
                    {
                      warning ("signature name in scope resolution ignored");
                      $$ = build_method_call ($$, OP1 ($2), NULL_TREE, NULL_TREE,
-                                             (LOOKUP_NORMAL|LOOKUP_AGGR));
+                                             LOOKUP_NORMAL);
                    }
                  else
                    $$ = build_scoped_method_call ($$, OP0 ($2), OP1 ($2), NULL_TREE);
@@ -1605,9 +1600,9 @@ primary_no_id:
                    pedwarn ("ANSI C++ forbids braced-groups within expressions");
                  $$ = expand_end_stmt_expr ($<ttype>2); }
        | primary_no_id '(' nonnull_exprlist ')'
-               { $$ = build_x_function_call ($$, $3, current_class_decl); }
+               { $$ = build_x_function_call ($$, $3, current_class_ref); }
        | primary_no_id LEFT_RIGHT
-               { $$ = build_x_function_call ($$, NULL_TREE, current_class_decl); }
+               { $$ = build_x_function_call ($$, NULL_TREE, current_class_ref); }
        | primary_no_id '[' expr ']'
                { goto do_array; }
        | primary_no_id PLUSPLUS
index 47a37c8..0addffd 100644 (file)
@@ -2581,6 +2581,10 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts)
       return 0;
 
     case POINTER_TYPE:
+      if (TREE_CODE (arg) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (arg))
+       return unify (tparms, targs, ntparms, parm,
+                     TYPE_PTRMEMFUNC_FN_TYPE (arg), nsubsts);
+
       if (TREE_CODE (arg) != POINTER_TYPE)
        return 1;
       return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg),
index d7db46b..2a852cd 100644 (file)
@@ -769,7 +769,7 @@ lookup_field_1 (type, name)
    itself inside a class, we need decls to go into the fn's decls (our
    second case below).  But if we're in a class and the class itself is
    inside a function, we need decls to go into the decls for the class.  To
-   achieve this last goal, we must see if, when both current_class_decl and
+   achieve this last goal, we must see if, when both current_class_ptr and
    current_function_decl are set, the class was declared inside that
    function.  If so, we know to put the decls into the class's scope.  */
 
index 00f257e..701b3be 100644 (file)
@@ -573,7 +573,7 @@ build_signature_table_constructor (sig_ty, rhs)
              vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
              delta = integer_zero_node;
              index = integer_zero_node;
-             pfn = build_unary_op (ADDR_EXPR, rhs_method, 0);
+             pfn = build_addr_func (rhs_method);
              TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (rhs_method)) = 1;
              TREE_TYPE (pfn) = ptr_type_node;
              TREE_ADDRESSABLE (rhs_method) = 1;
@@ -584,8 +584,12 @@ build_signature_table_constructor (sig_ty, rhs)
              /* virtual member function */
              tag = integer_one_node;
              vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
-             delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method),
-                                              rhstype, 1));
+             if (flag_vtable_thunks)
+               delta = BINFO_OFFSET
+                 (get_binfo (DECL_CONTEXT (rhs_method), rhstype, 1));
+             else
+               delta = BINFO_OFFSET
+                 (get_binfo (DECL_CLASS_CONTEXT (rhs_method), rhstype, 1));
              index = DECL_VINDEX (rhs_method);
              vt_off = get_vfield_offset (get_binfo (DECL_CONTEXT (rhs_method),
                                                     rhstype, 0));
@@ -598,7 +602,7 @@ build_signature_table_constructor (sig_ty, rhs)
              delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method),
                                               rhstype, 1));
              index = integer_zero_node;
-             pfn = build_unary_op (ADDR_EXPR, rhs_method, 0);
+             pfn = build_addr_func (rhs_method);
              TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (rhs_method)) = 1;
              TREE_TYPE (pfn) = ptr_type_node;
              TREE_ADDRESSABLE (rhs_method) = 1;
@@ -985,10 +989,7 @@ build_signature_method_call (basetype, instance, function, parms)
 
       TREE_TYPE (vfn) = build_pointer_type (TREE_TYPE (function));
 
-      if (flag_vtable_thunks)
-       virtual_call = build_function_call (vfn, parms);
-      else
-       virtual_call = build_function_call (vfn, new_parms);
+      virtual_call = build_function_call (vfn, new_parms);
     }
 
     /* Undo the cast, make `this' a signature pointer again.  */
index 7a8ef46..3684a2a 100644 (file)
@@ -48,7 +48,7 @@ real_lvalue_p (ref)
   if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
     return 1;
 
-  if (ref == current_class_decl && flag_this_is_variable <= 0)
+  if (ref == current_class_ptr && flag_this_is_variable <= 0)
     return 0;
 
   switch (TREE_CODE (ref))
@@ -118,7 +118,7 @@ lvalue_p (ref)
   if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
     return 1;
 
-  if (ref == current_class_decl && flag_this_is_variable <= 0)
+  if (ref == current_class_ptr && flag_this_is_variable <= 0)
     return 0;
 
   switch (TREE_CODE (ref))
index 88ce4db..507150c 100644 (file)
@@ -100,13 +100,13 @@ require_complete_type (value)
      not been laid out.  Try to avoid an error by interpreting
      it as this->X::Y, if reasonable.  */
   if (TREE_CODE (value) == OFFSET_REF
-      && C_C_D != 0
-      && TREE_OPERAND (value, 0) == C_C_D)
+      && current_class_ref != 0
+      && TREE_OPERAND (value, 0) == current_class_ref)
     {
       tree base, member = TREE_OPERAND (value, 1);
       tree basetype = TYPE_OFFSET_BASETYPE (type);
       my_friendly_assert (TREE_CODE (member) == FIELD_DECL, 305);
-      base = convert_pointer_to (basetype, current_class_decl);
+      base = convert_pointer_to (basetype, current_class_ptr);
       value = build (COMPONENT_REF, TREE_TYPE (member),
                     build_indirect_ref (base, NULL_PTR), member);
       return require_complete_type (value);
@@ -1470,14 +1470,7 @@ decay_conversion (exp)
     }
   if (code == METHOD_TYPE)
     {
-      if (TREE_CODE (exp) == OFFSET_REF)
-       {
-         /* FIXME: We should emit an error here about using a ptrmemfunc
-            for something other than a function call.  */
-         my_friendly_assert (TREE_CODE (TREE_OPERAND (exp, 1)) == FUNCTION_DECL,
-                             308);
-         return build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0);
-       }
+      cp_pedwarn ("assuming & on `%E'", exp);
       return build_unary_op (ADDR_EXPR, exp, 0);
     }
   if (code == ARRAY_TYPE)
@@ -1628,7 +1621,7 @@ build_object_ref (datum, basetype, field)
 }
 
 /* Like `build_component_ref, but uses an already found field.
-   Must compute access for C_C_D.  Otherwise, ok.  */
+   Must compute access for current_class_ref.  Otherwise, ok.  */
 tree
 build_component_ref_1 (datum, field, protect)
      tree datum, field;
@@ -1667,7 +1660,7 @@ build_component_ref_1 (datum, field, protect)
   if (TREE_STATIC (field))
     return field;
 
-  if (datum == C_C_D)
+  if (datum == current_class_ref)
     {
       tree access = compute_access (TYPE_BINFO (current_class_type), field);
 
@@ -2020,8 +2013,8 @@ build_indirect_ref (ptr, errorstring)
                           ptr : default_conversion (ptr));
   register tree type = TREE_TYPE (pointer);
 
-  if (ptr == current_class_decl)
-    return C_C_D;
+  if (ptr == current_class_ptr)
+    return current_class_ref;
 
   if (IS_AGGR_TYPE (type))
     {
@@ -2226,8 +2219,9 @@ build_array_ref (array, idx)
 \f
 /* Build a function call to function FUNCTION with parameters PARAMS.
    PARAMS is a list--a chain of TREE_LIST nodes--in which the
-   TREE_VALUE of each node is a parameter-expression.
-   FUNCTION's data type may be a function type or a pointer-to-function.
+   TREE_VALUE of each node is a parameter-expression.  The PARAMS do
+   not include any object pointer that may be required.  FUNCTION's
+   data type may be a function type or a pointer-to-function.
 
    For C++: If FUNCTION's data type is a TREE_LIST, then the tree list
    is the list of possible methods that FUNCTION could conceivably
@@ -2242,7 +2236,7 @@ build_array_ref (array, idx)
    In the second case, TREE_PURPOSE (function) is the function's
    name directly.
 
-   DECL is the class instance variable, usually CURRENT_CLASS_DECL.
+   DECL is the class instance variable, usually CURRENT_CLASS_REF.
 
    When calling a TEMPLATE_DECL, we don't require a complete return
    type.  */
@@ -2392,7 +2386,7 @@ build_x_function_call (function, params, decl)
       if (TREE_OPERAND (function, 0))
        decl = TREE_OPERAND (function, 0);
       else
-       decl = C_C_D;
+       decl = current_class_ref;
 
       decl_addr = build_unary_op (ADDR_EXPR, decl, 0);
       function = get_member_function_from_ptrfunc (&decl_addr,
@@ -2594,25 +2588,25 @@ build_function_call_real (function, params, require_complete, flags)
          function = inline_conversion (function);
        }
       else
-       function = default_conversion (function);
+       function = build_addr_func (function);
     }
   else
     {
       fndecl = NULL_TREE;
 
-      /* Convert anything with function type to a pointer-to-function.  */
-      if (function == error_mark_node)
-       return error_mark_node;
-      function = default_conversion (function);
+      function = build_addr_func (function);
     }
 
+  if (function == error_mark_node)
+    return error_mark_node;
+
   fntype = TREE_TYPE (function);
 
   if (TYPE_PTRMEMFUNC_P (fntype))
     {
-      tree instance_ptr = build_unary_op (ADDR_EXPR, C_C_D, 0);
-      fntype = TYPE_PTRMEMFUNC_FN_TYPE (fntype);
-      function = get_member_function_from_ptrfunc (&instance_ptr, function);
+      cp_error ("must use .* or ->* to call pointer-to-member function in `%E (...)'",
+               function);
+      return error_mark_node;
     }
 
   is_method = (TREE_CODE (fntype) == POINTER_TYPE
@@ -2670,17 +2664,15 @@ build_function_call_real (function, params, require_complete, flags)
   /* C++ */
   value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node;
   {
-    register tree result = 
-      build (CALL_EXPR, value_type,
-            function, coerced_params, NULL_TREE);
-
-    TREE_SIDE_EFFECTS (result) = 1;
+    register tree result
+      = build_call (function, value_type, coerced_params);
 
-    if (! require_complete)
-      return convert_from_reference (result);
-    if (value_type == void_type_node)
-      return result;
-    result = require_complete_type (result);
+    if (require_complete)
+      {
+       if (value_type == void_type_node)
+         return result;
+       result = require_complete_type (result);
+      }
     return convert_from_reference (result);
   }
 }
@@ -4282,10 +4274,10 @@ build_unary_op (code, xarg, noconvert)
       /* Let &* cancel out to simplify resulting code.  */
       if (TREE_CODE (arg) == INDIRECT_REF)
        {
-         /* We don't need to have `current_class_decl' wrapped in a
+         /* We don't need to have `current_class_ptr' wrapped in a
             NON_LVALUE_EXPR node.  */
-         if (arg == C_C_D)
-           return current_class_decl;
+         if (arg == current_class_ref)
+           return current_class_ptr;
 
          /* Keep `default_conversion' from converting if
             ARG is of REFERENCE_TYPE.  */
@@ -4402,6 +4394,14 @@ build_unary_op (code, xarg, noconvert)
           function counts as a constant */
        if (staticp (arg))
          TREE_CONSTANT (addr) = 1;
+
+       if (TREE_CODE (argtype) == POINTER_TYPE &&
+           TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
+         {
+           build_ptrmemfunc_type (argtype);
+           addr = build_ptrmemfunc (argtype, addr, 0);
+         }
+
        return addr;
       }
     }
@@ -4542,31 +4542,6 @@ unary_complex_lvalue (code, arg)
     }
 
   
-#if 0
-  /* This seems to be obsolete now (and posssibly wrong, compare with
-     resolve_offset_ref).  */
-  if (TREE_CODE (arg) == OFFSET_REF)
-    {
-      tree left = TREE_OPERAND (arg, 0), left_addr;
-      tree right_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 1), 0);
-
-      if (left == 0)
-       if (current_class_decl)
-         left_addr = current_class_decl;
-       else
-         {
-           error ("no `this' for pointer to member");
-           return error_mark_node;
-         }
-      else
-       left_addr = build_unary_op (ADDR_EXPR, left, 0);
-
-      return build (PLUS_EXPR, build_pointer_type (TREE_TYPE (arg)),
-                   build1 (NOP_EXPR, integer_type_node, left_addr),
-                   build1 (NOP_EXPR, integer_type_node, right_addr));
-    }
-#endif
-
   /* We permit compiler to make function calls returning
      objects of aggregate type look like lvalues.  */
   {
@@ -4597,7 +4572,7 @@ unary_complex_lvalue (code, arg)
    address of it; it should not be allocated in a register.
    Value is 1 if successful.
 
-   C++: we do not allow `current_class_decl' to be addressable.  */
+   C++: we do not allow `current_class_ptr' to be addressable.  */
 
 int
 mark_addressable (exp)
@@ -4618,7 +4593,7 @@ mark_addressable (exp)
        break;
 
       case PARM_DECL:
-       if (x == current_class_decl)
+       if (x == current_class_ptr)
          {
            error ("address of `this' not available");
            TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */
@@ -5702,7 +5677,7 @@ build_modify_expr (lhs, modifycode, rhs)
     }
 
   /* check to see if there is an assignment to `this' */
-  if (lhs == current_class_decl)
+  if (lhs == current_class_ptr)
     {
       if (flag_this_is_variable > 0
          && DECL_NAME (current_function_decl) != NULL_TREE
@@ -5976,11 +5951,16 @@ get_delta_difference (from, to, force)
        }
       if (TREE_VIA_VIRTUAL (binfo))
        {
+         binfo = binfo_member (BINFO_TYPE (binfo),
+                               CLASSTYPE_VBASECLASSES (from));
          warning ("pointer to member conversion to virtual base class will only work if you are very careful");
        }
+      delta = BINFO_OFFSET (binfo);
+      delta = convert (ptrdiff_type_node, delta);
+      
       return build_binary_op (MINUS_EXPR,
                              integer_zero_node,
-                             BINFO_OFFSET (binfo), 1);
+                             delta, 1);
     }
   if (TREE_VIA_VIRTUAL (binfo))
     {
@@ -6099,8 +6079,7 @@ build_ptrmemfunc (type, pfn, force)
       pfn = instantiate_type (type, pfn, 1);
       if (pfn == error_mark_node)
        return error_mark_node;
-      if (TREE_CODE (pfn) != ADDR_EXPR)
-       pfn = build_unary_op (ADDR_EXPR, pfn, 0);
+      pfn = build_addr_func (pfn);
     }
 
   /* Allow pointer to member conversions here. */
@@ -6109,6 +6088,14 @@ build_ptrmemfunc (type, pfn, force)
                                force);
   delta2 = build_binary_op (PLUS_EXPR, delta2, delta, 1);
 
+#if 0
+  /* We need to check the argument types to see if they are compatible
+     (any const or volatile violations.  */
+  something like this:
+  comptype (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (type))),
+           TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))), ?);
+#endif
+
   if (TREE_CODE (TREE_OPERAND (pfn, 0)) != FUNCTION_DECL)
     warning ("assuming pointer to member function is non-virtual");
 
@@ -6414,12 +6401,12 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
             some type instantiation if that resolves the
             ambiguity of (X Y::*) and (X *).  */
 
-         if (current_class_decl)
+         if (current_class_ptr)
            {
              if (TREE_CODE (rhs) == INTEGER_CST)
                {
                  rhs = build (PLUS_EXPR, build_pointer_type (TREE_TYPE (ttr)),
-                              current_class_decl, rhs);
+                              current_class_ptr, rhs);
                  return convert_for_assignment (type, rhs,
                                                 errtype, fndecl, parmnum);
                }
@@ -6522,24 +6509,6 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
                    cp_warning ("\t`%T' != `%T'", type, rhstype);
                  }
            }
-         else if (TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
-           {
-             /* When does this happen?  */
-             my_friendly_abort (119);
-             /* Conversion of a pointer-to-member type to void *.  */
-             rhs = build_unary_op (ADDR_EXPR, rhs, 0);
-             TREE_TYPE (rhs) = type;
-             return rhs;
-           }
-         else if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE)
-           {
-             /* When does this happen?  */
-             my_friendly_abort (120);
-             /* Conversion of a pointer-to-member type to void *.  */
-             rhs = build_unary_op (ADDR_EXPR, rhs, 0);
-             TREE_TYPE (rhs) = type;
-             return rhs;
-           }
          else
            {
              if (fndecl)
@@ -6931,7 +6900,7 @@ c_expand_return (retval)
        }
 
       if (DECL_CONSTRUCTOR_P (current_function_decl))
-       retval = current_class_decl;
+       retval = current_class_ptr;
       else if (DECL_NAME (result) != NULL_TREE
               && TREE_CODE (valtype) != VOID_TYPE)
        retval = result;
@@ -6956,10 +6925,10 @@ c_expand_return (retval)
        }
     }
   else if (DECL_CONSTRUCTOR_P (current_function_decl)
-          && retval != current_class_decl)
+          && retval != current_class_ptr)
     {
       error ("return from a constructor: use `this = ...' instead");
-      retval = current_class_decl;
+      retval = current_class_ptr;
     }
 
   if (valtype == NULL_TREE || TREE_CODE (valtype) == VOID_TYPE)
@@ -7164,7 +7133,7 @@ c_expand_return (retval)
        }
       else if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK)
        {
-         /* Here RETVAL is CURRENT_CLASS_DECL, so there's nothing to do.  */
+         /* Here RETVAL is CURRENT_CLASS_PTR, so there's nothing to do.  */
          expand_goto (ctor_label);
        }
       else if (retval)
index 602a092..14802dc 100644 (file)
@@ -1341,7 +1341,7 @@ build_m_component_ref (datum, component)
     {
       component = build_indirect_ref (component, NULL_PTR);
       type = TREE_TYPE (component);
-      rettype = TREE_TYPE (TREE_TYPE (component));
+      rettype = TREE_TYPE (type);
     }
 
   if (datum == error_mark_node || component == error_mark_node)