]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
cp-tree.h (DECL_VIRTUAL_CONTEXT): New macro.
authorJason Merrill <jason@yorick.cygnus.com>
Wed, 28 Jul 1999 00:45:12 +0000 (00:45 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 28 Jul 1999 00:45:12 +0000 (20:45 -0400)
* cp-tree.h (DECL_VIRTUAL_CONTEXT): New macro.
* typeck.c (expand_ptrmemfunc_cst): Calculate delta correctly for
virtual functions and MI.  Simplify.

From-SVN: r28304

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/typeck.c

index 27df6bc4d2084446576d8c0a7f472a8a6c3de153..63adc40f37c8df855329b6e72cd3165245c71d8f 100644 (file)
@@ -1,5 +1,9 @@
 1999-07-27  Jason Merrill  <jason@yorick.cygnus.com>
 
+       * cp-tree.h (DECL_VIRTUAL_CONTEXT): New macro.
+       * typeck.c (expand_ptrmemfunc_cst): Calculate delta correctly for
+       virtual functions and MI.  Simplify.
+
        * method.c: Remove prototype for largest_union_member.
        * pt.c (determine_specialization): Fix uninitialized warning.
        * lex.c (real_yylex): Likewise.
index 4a47e9bcd3342f5635bf796e8e0e12c6679cedcf..55d94bb36a3aaf5b46d0ab0444d0edf90d387f37 100644 (file)
@@ -212,12 +212,12 @@ struct tree_overload
    indicating a particular base class, and whose TREE_VALUE is a
    (possibly overloaded) function from that base class.  */
 #define BASELINK_P(NODE) \
-  (TREE_CODE ((NODE)) == TREE_LIST && TREE_LANG_FLAG_1 ((NODE)))
+  (TREE_CODE (NODE) == TREE_LIST && TREE_LANG_FLAG_1 (NODE))
 #define SET_BASELINK_P(NODE) \
-  (TREE_LANG_FLAG_1 ((NODE)) = 1)
+  (TREE_LANG_FLAG_1 (NODE) = 1)
 
-#define WRAPPER_PTR(NODE) (((struct tree_wrapper*)NODE)->u.ptr)
-#define WRAPPER_INT(NODE) (((struct tree_wrapper*)NODE)->u.i)
+#define WRAPPER_PTR(NODE) (((struct tree_wrapper*)(NODE))->u.ptr)
+#define WRAPPER_INT(NODE) (((struct tree_wrapper*)(NODE))->u.i)
 
 struct tree_wrapper
 {
@@ -1404,6 +1404,10 @@ struct lang_decl
   (DECL_CONTEXT (NODE) ? DECL_CONTEXT (NODE) : global_namespace)
 #define FROB_CONTEXT(NODE)   ((NODE) == global_namespace ? NULL_TREE : (NODE))
 
+/* For a virtual function, the base where we find its vtable entry.
+   For a non-virtual function, the base where it is defined.  */
+#define DECL_VIRTUAL_CONTEXT(NODE) DECL_CONTEXT (NODE)
+
 /* 1 iff NODE has namespace scope, including the global namespace.  */
 #define DECL_NAMESPACE_SCOPE_P(NODE) \
   (DECL_CONTEXT (NODE) == NULL_TREE \
index 905b3e3a1b253bb959339f2651e139198f05cac1..e62f7e34e3f67c7cd9cde09ae26f3fc1dd44dd89 100644 (file)
@@ -6078,7 +6078,12 @@ build_x_modify_expr (lhs, modifycode, rhs)
 \f
 /* Get difference in deltas for different pointer to member function
    types.  Return integer_zero_node, if FROM cannot be converted to a
-   TO type.  If FORCE is true, then allow reverse conversions as well.  */
+   TO type.  If FORCE is true, then allow reverse conversions as well.
+
+   Note that the naming of FROM and TO is kind of backwards; the return
+   value is what we add to a TO in order to get a FROM.  They are named
+   this way because we call this function to find out how to convert from
+   a pointer to member of FROM to a pointer to member of TO.  */
 
 static tree
 get_delta_difference (from, to, force)
@@ -6338,37 +6343,41 @@ expand_ptrmemfunc_cst (cst, delta, idx, pfn, delta2)
 {
   tree type = TREE_TYPE (cst);
   tree fn = PTRMEM_CST_MEMBER (cst);
+  tree ptr_class, fn_class;
 
   my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0);
-  
-  *delta 
-    = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (fn)),
-                           TYPE_PTRMEMFUNC_OBJECT_TYPE (type),
-                           /*force=*/0);
+
+  /* The class that the function belongs to.  */
+  fn_class = DECL_CLASS_CONTEXT (fn);
+
+  /* The class that we're creating a pointer to member of.  */
+  ptr_class = TYPE_PTRMEMFUNC_OBJECT_TYPE (type);
+
+  /* First, calculate the adjustment to the function's class.  */
+  *delta = get_delta_difference (fn_class, ptr_class, /*force=*/0);
+
   if (!DECL_VIRTUAL_P (fn))
     {
-      *idx = size_binop (MINUS_EXPR, integer_zero_node,
-                        integer_one_node);
-      *pfn = build_addr_func (fn);
-      if (!same_type_p (TYPE_METHOD_BASETYPE (TREE_TYPE (fn)),
-                       TYPE_PTRMEMFUNC_OBJECT_TYPE (type)))
-       *pfn = build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type), 
-                      *pfn);
+      *idx = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
+      *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn));
       *delta2 = NULL_TREE;
     }
   else
     {
-      *idx = size_binop (PLUS_EXPR, DECL_VINDEX (fn), 
-                        integer_one_node);
+      /* If we're dealing with a virtual function, we have to adjust 'this'
+         again, to point to the base which provides the vtable entry for
+         fn; the call will do the opposite adjustment.  */
+      tree orig_class = DECL_VIRTUAL_CONTEXT (fn);
+      tree binfo = binfo_or_else (orig_class, fn_class);
+      *delta = size_binop (PLUS_EXPR, *delta, BINFO_OFFSET (binfo));
+
+      /* Map everything down one to make room for the null PMF.  */
+      *idx = size_binop (PLUS_EXPR, DECL_VINDEX (fn), integer_one_node);
       *pfn = NULL_TREE;
-      *delta2 = get_binfo (DECL_CONTEXT (fn),
-                         DECL_CLASS_CONTEXT (fn),
-                         0);
-      *delta2 = get_vfield_offset (*delta2);
-      *delta2 = size_binop (PLUS_EXPR, *delta2,
-                          build_binary_op (PLUS_EXPR,
-                                           *delta, 
-                                           integer_zero_node));
+
+      /* Offset from an object of PTR_CLASS to the vptr for ORIG_CLASS.  */
+      *delta2 = size_binop (PLUS_EXPR, *delta,
+                           get_vfield_offset (TYPE_BINFO (orig_class)));
     }
 }