]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/cp/sig.c
new
[gcc.git] / gcc / cp / sig.c
index 979d7aa837b681965b05623980ed429137f82175..ba3af4253840709668633800579147b0fbfe2748 100644 (file)
@@ -1,5 +1,5 @@
 /* Functions dealing with signatures and signature pointers/references.
-   Copyright (C) 1992 Free Software Foundation, Inc.
+   Copyright (C) 1992, 93, 94, 95, 1996 Free Software Foundation, Inc.
    Contributed by Gerald Baumgartner (gb@cs.purdue.edu)
 
 This file is part of GNU CC.
@@ -16,7 +16,8 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 #include "config.h"
@@ -31,10 +32,22 @@ extern struct obstack *current_obstack;
 extern struct obstack permanent_obstack;
 extern struct obstack *saveable_obstack;
 
-extern void error ();
-extern void sorry ();
 extern void compiler_error ();
-extern void make_decl_rtl                      PROTO((tree, char *, int));
+
+static tree save_this PROTO((tree));
+static tree build_sptr_ref PROTO((tree));
+static tree build_member_function_pointer PROTO((tree));
+static void undo_casts PROTO((tree));
+static tree build_signature_pointer_or_reference_name
+       PROTO((tree, int, int, int));
+static void build_signature_pointer_or_reference_decl
+       PROTO((tree, tree));
+static tree build_signature_pointer_or_reference_type 
+       PROTO((tree, int, int, int));
+static tree get_sigtable_name PROTO((tree, tree));
+static tree build_signature_table_constructor PROTO((tree, tree));
+static int match_method_types PROTO((tree, tree));
+static tree build_sigtable PROTO((tree, tree, tree));
 
 /* Used to help generate globally unique names for signature tables.  */
 
@@ -143,7 +156,6 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
        struct {
          void * optr;
         const s * sptr;
-        vtbl_type_node * vptr;
        };
 
      A `const' signature pointer/reference is a
@@ -151,17 +163,15 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
        struct {
          const void * optr;
         const s * sptr;
-        vtbl_type_node * vptr;
        };
 
-     Similarly, for `volatile' and `const volatile'.
-   */
+     Similarly, for `volatile' and `const volatile'.  */
 
   t = make_lang_type (RECORD_TYPE);
   {
     tree obj_type = build_type_variant (void_type_node, constp, volatilep);
     tree optr_type = build_pointer_type (obj_type);
-    tree optr, sptr, vptr;
+    tree optr, sptr;
 
     optr = build_lang_field_decl (FIELD_DECL,
                                  get_identifier (SIGNATURE_OPTR_NAME),
@@ -170,35 +180,29 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
     DECL_CLASS_CONTEXT (optr) = t;
 
     if (m)
-      {
-       /* We can share `sptr' and `vptr' among type variants.  */
-       sptr = TREE_CHAIN (TYPE_FIELDS (m));
-       vptr = TREE_CHAIN (sptr);
-      }
+      /* We can share the `sptr' field among type variants.  */
+      sptr = TREE_CHAIN (TYPE_FIELDS (m));
     else
       {
-       tree sig_tbl_type = build_type_variant (to_type, 1, 0);
+       tree sig_tbl_type = cp_build_type_variant (to_type, 1, 0);
        
        sptr = build_lang_field_decl (FIELD_DECL,
                                      get_identifier (SIGNATURE_SPTR_NAME),
                                      build_pointer_type (sig_tbl_type));
-       vptr = build_lang_field_decl (FIELD_DECL,
-                                     get_identifier (SIGNATURE_VPTR_NAME),
-                                     build_pointer_type (vtbl_type_node));
        DECL_FIELD_CONTEXT (sptr) = t;
        DECL_CLASS_CONTEXT (sptr) = t;
-       DECL_FIELD_CONTEXT (vptr) = t;
-       DECL_CLASS_CONTEXT (vptr) = t;
-       TREE_CHAIN (sptr) = vptr;
-       TREE_CHAIN (vptr) = NULL_TREE;
+       TREE_CHAIN (sptr) = NULL_TREE;
       }
 
     TREE_CHAIN (optr) = sptr;
     TYPE_FIELDS (t) = optr;
-    /* To make `build_vfn_ref' work when building a signature method call.  */
-    CLASSTYPE_VFIELD (t) = vptr;
-    DECL_FCONTEXT (CLASSTYPE_VFIELD (t)) = t;
-    TYPE_ALIGN (t) = TYPE_ALIGN (optr_type);
+    /* Allow signature pointers/references to be grabbed 2 words at a time.
+       For this to work on a Sparc, we need 8-byte alignment.  */
+    TYPE_ALIGN (t) = MAX (TYPE_ALIGN (double_type_node),
+                         TYPE_ALIGN (optr_type));
+
+    /* A signature pointer/reference type isn't a `real' class type.  */
+    IS_AGGR_TYPE (t) = 0;
   }
 
   {
@@ -236,7 +240,7 @@ build_signature_pointer_or_reference_type (to_type, constp, volatilep, refp)
   current_obstack = ambient_obstack;
   saveable_obstack = ambient_saveable_obstack;
 
-  /* Ouput debug information for this type.  */
+  /* Output debug information for this type.  */
   rest_of_type_compilation (t, 1);
 
   return t;
@@ -406,8 +410,8 @@ match_method_types (sig_mtype, class_mtype)
   /* Compare the first argument `this.'  */
   {
     /* Get the type of what the `optr' is pointing to.  */
-    tree sig_this =
-      TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_VALUE (sig_arg_types))));
+    tree sig_this
+      TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_VALUE (sig_arg_types))));
     tree class_this = TREE_VALUE (class_arg_types);
 
     if (TREE_CODE (class_this) == RECORD_TYPE) /* Is `this' a sig ptr?  */
@@ -430,6 +434,7 @@ match_method_types (sig_mtype, class_mtype)
 }
 
 /* Undo casts of opaque type variables to the RHS types.  */
+
 static void
 undo_casts (sig_ty)
      tree sig_ty;
@@ -512,8 +517,8 @@ build_signature_table_constructor (sig_ty, rhs)
        {
          if (! IS_DEFAULT_IMPLEMENTATION (sig_method))
            {
-             cp_error ("class `%T' does not contain method `%s'",
-                       rhstype, (int) IDENTIFIER_POINTER (sig_mname));
+             cp_error ("class `%T' does not contain method `%D'",
+                       rhstype, sig_mname);
              undo_casts (sig_ty);
              return error_mark_node;
            }
@@ -540,11 +545,11 @@ build_signature_table_constructor (sig_ty, rhs)
 
          if (rhs_method == NULL_TREE
              || (compute_access (basetypes, rhs_method)
-                 != access_public))
+                 != access_public_node))
            {
              error ("class `%s' does not contain a method conforming to `%s'",
                     TYPE_NAME_STRING (rhstype),
-                    fndecl_as_string (NULL, sig_method, 1));
+                    fndecl_as_string (sig_method, 1));
              undo_casts (sig_ty);
              return error_mark_node;
            }
@@ -569,35 +574,86 @@ build_signature_table_constructor (sig_ty, rhs)
        }
       else
        {
-         tree code, offset, pfn;
+         tree tag, vb_off, delta, idx, pfn, vt_off;
+         tree tag_decl, vb_off_decl, delta_decl, index_decl;
+         tree pfn_decl, vt_off_decl;
 
          if (rhs_method == sig_method)
            {
-             code = integer_two_node;
-             offset = integer_zero_node;
-             pfn = build_unary_op (ADDR_EXPR, rhs_method, 0);
+             /* default implementation */
+             tag = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
+             vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
+             delta = integer_zero_node;
+             idx = integer_zero_node;
+             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;
              offset_p = 0;     /* we can't offset the rhs sig table */
            }
          else if (DECL_VINDEX (rhs_method))
            {
-             code = integer_one_node;
-             offset = DECL_VINDEX (rhs_method);
-             pfn = null_pointer_node;
+             /* virtual member function */
+             tag = integer_one_node;
+             vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
+             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));
+             idx = DECL_VINDEX (rhs_method);
+             vt_off = get_vfield_offset (get_binfo (DECL_CONTEXT (rhs_method),
+                                                    rhstype, 0));
            }
          else
            {
-             code = integer_zero_node;
-             offset = integer_zero_node;
-             pfn = build_unary_op (ADDR_EXPR, rhs_method, 0);
+             /* non-virtual member function */
+             tag = integer_zero_node;
+             vb_off = build_unary_op (NEGATE_EXPR, integer_one_node, 0);
+             delta = BINFO_OFFSET (get_binfo (DECL_CLASS_CONTEXT (rhs_method),
+                                              rhstype, 1));
+             idx = integer_zero_node;
+             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;
            }
 
-         tbl_entry = tree_cons (NULL_TREE, code,
-                                tree_cons (NULL_TREE, offset,
-                                           build_tree_list (NULL_TREE, pfn)));
-         tbl_entry = build_nt (CONSTRUCTOR, NULL_TREE, tbl_entry);
-         TREE_HAS_CONSTRUCTOR (tbl_entry) = 1;
+         /* Since digest_init doesn't handle initializing selected fields
+            of a struct (i.e., anonymous union), we build the constructor
+            by hand, without calling digest_init.  */
+         tag_decl = TYPE_FIELDS (sigtable_entry_type);
+         vb_off_decl = TREE_CHAIN (tag_decl);
+         delta_decl = TREE_CHAIN (vb_off_decl);
+         index_decl = TREE_CHAIN (delta_decl);
+         pfn_decl = TREE_CHAIN (index_decl);
+         vt_off_decl = TREE_CHAIN (pfn_decl);
+         
+         tag = cp_convert (TREE_TYPE (tag_decl), tag);
+         vb_off = cp_convert (TREE_TYPE (vb_off_decl), vb_off);
+         delta = cp_convert (TREE_TYPE (delta_decl), delta);
+         idx = cp_convert (TREE_TYPE (index_decl), idx);
+
+         if (DECL_VINDEX (rhs_method))
+           {
+             vt_off = cp_convert (TREE_TYPE (vt_off_decl), vt_off);
+
+             tbl_entry = build_tree_list (vt_off_decl, vt_off);
+           }
+         else
+           {
+             pfn = cp_convert (TREE_TYPE (pfn_decl), pfn);
+
+             tbl_entry = build_tree_list (pfn_decl, pfn);
+           }
+         tbl_entry = tree_cons (delta_decl, delta,
+                                tree_cons (index_decl, idx, tbl_entry));
+         tbl_entry = tree_cons (tag_decl, tag,
+                                tree_cons (vb_off_decl, vb_off, tbl_entry));
+         tbl_entry = build (CONSTRUCTOR, sigtable_entry_type,
+                            NULL_TREE, tbl_entry);
+
          TREE_CONSTANT (tbl_entry) = 1;
        }
 
@@ -610,6 +666,7 @@ build_signature_table_constructor (sig_ty, rhs)
 
   if (result == NULL_TREE)
     {
+      /* The signature was empty, we don't need a signature table.  */
       undo_casts (sig_ty);
       return NULL_TREE;
     }
@@ -618,17 +675,20 @@ build_signature_table_constructor (sig_ty, rhs)
     {
       if (first_rhs_field == TYPE_FIELDS (rhstype))
        {
+         /* The sptr field on the lhs can be copied from the rhs.  */
          undo_casts (sig_ty);
          return integer_zero_node;
        }
       else
        {
+         /* The sptr field on the lhs will point into the rhs sigtable.  */
          undo_casts (sig_ty);
          return build_component_ref (rhs, DECL_NAME (first_rhs_field),
                                      NULL_TREE, 0);
        }
     }
 
+  /* We need to construct a new signature table.  */
   result = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (result));
   TREE_HAS_CONSTRUCTOR (result) = 1;
   TREE_CONSTANT (result) = !sig_ptr_p;
@@ -642,7 +702,7 @@ build_signature_table_constructor (sig_ty, rhs)
    as initialization expression, we don't need a new signature table
    variable and just hand back the init expression.
 
-   The declaration processing is done by hand instead of using `finish_decl'
+   The declaration processing is done by hand instead of using `cp_finish_decl'
    so that we can make signature pointers global variables instead of
    static ones.  */
 
@@ -679,7 +739,7 @@ build_sigtable (sig_type, rhs_type, init_from)
       SIGTABLE_HAS_BEEN_GENERATED (sig_type) = 1;
 
       init_expr = build_signature_table_constructor (sig_type, init_from);
-      if (TREE_CODE (init_expr) != CONSTRUCTOR)
+      if (init_expr == NULL_TREE || TREE_CODE (init_expr) != CONSTRUCTOR)
        return init_expr;
 
       if (name == NULL_TREE)
@@ -735,19 +795,27 @@ build_signature_pointer_constructor (lhs, rhs)
   tree lhstype = initp ? lhs : TREE_TYPE (lhs);
   tree rhstype = TREE_TYPE (rhs);
   tree sig_ty  = SIGNATURE_TYPE (lhstype);
-  tree sig_tbl, sptr_expr, optr_expr, vptr_expr;
+  tree sig_tbl, sptr_expr, optr_expr;
   tree result;
 
   if (! ((TREE_CODE (rhstype) == POINTER_TYPE
          && TREE_CODE (TREE_TYPE (rhstype)) == RECORD_TYPE)
-        || (TYPE_LANG_SPECIFIC (rhstype) &&
-            (IS_SIGNATURE_POINTER (rhstype)
-             || IS_SIGNATURE_REFERENCE (rhstype)))))
+        || (TYPE_LANG_SPECIFIC (rhstype)
+            && (IS_SIGNATURE_POINTER (rhstype)
+                || IS_SIGNATURE_REFERENCE (rhstype)))))
     {
       error ("invalid assignment to signature pointer or reference");
       return error_mark_node;
     }
 
+  if (TYPE_SIZE (sig_ty) == NULL_TREE)
+    {
+      cp_error ("undefined signature `%T' used in signature %s declaration",
+               sig_ty,
+               IS_SIGNATURE_POINTER (lhstype) ? "pointer" : "reference");
+      return error_mark_node;
+    }
+
   /* If SIG_TY is permanent, make the signature table constructor and
      the signature pointer/reference constructor permanent too.  */
   if (TREE_PERMANENT (sig_ty))
@@ -756,15 +824,14 @@ build_signature_pointer_constructor (lhs, rhs)
       saveable_obstack = &permanent_obstack;
     }
 
-  if (TYPE_LANG_SPECIFIC (rhstype) &&
-      (IS_SIGNATURE_POINTER (rhstype) || IS_SIGNATURE_REFERENCE (rhstype)))
+  if (TYPE_LANG_SPECIFIC (rhstype)
+      && (IS_SIGNATURE_POINTER (rhstype) || IS_SIGNATURE_REFERENCE (rhstype)))
     {
       if (SIGNATURE_TYPE (rhstype) == sig_ty)
        {
          /* LHS and RHS are signature pointers/refs of the same signature.  */
          optr_expr = build_optr_ref (rhs);
          sptr_expr = build_sptr_ref (rhs);
-         vptr_expr = build_vptr_ref (rhs);
        }
       else
        {
@@ -779,46 +846,39 @@ build_signature_pointer_constructor (lhs, rhs)
            return error_mark_node;
 
          optr_expr = build_optr_ref (rhs);
-         if (sig_tbl == integer_zero_node)
+         if (sig_tbl == NULL_TREE)
+           /* The signature was empty.  The signature pointer is
+              pretty useless, but the user has been warned.  */
+           sptr_expr = copy_node (null_pointer_node);
+         else if (sig_tbl == integer_zero_node)
            sptr_expr = rhs_sptr_ref;
          else
            sptr_expr = build_unary_op (ADDR_EXPR, sig_tbl, 0);
          TREE_TYPE (sptr_expr) = build_pointer_type (sig_ty);
-         vptr_expr = build_vptr_ref (rhs);
        }
     }
   else
     {
-      tree rhs_vptr;
-
-      if (TYPE_USES_COMPLEX_INHERITANCE (TREE_TYPE (rhstype)))
-       {
-         sorry ("class with multiple inheritance as implementation of signature");
-         return error_mark_node;
-       }
-
       sig_tbl = build_sigtable (sig_ty, TREE_TYPE (rhstype), rhs);
       if (sig_tbl == error_mark_node)
        return error_mark_node;
 
       optr_expr = rhs;
-      sptr_expr = build_unary_op (ADDR_EXPR, sig_tbl, 0);
-      if (CLASSTYPE_VFIELD (TREE_TYPE (rhstype)))
+      if (sig_tbl == NULL_TREE)
+       /* The signature was empty.  The signature pointer is
+          pretty useless, but the user has been warned.  */
        {
-         rhs_vptr = DECL_NAME (CLASSTYPE_VFIELD (TREE_TYPE (rhstype)));
-         vptr_expr = build_component_ref (build_indirect_ref (rhs, 0),
-                                          rhs_vptr, NULL_TREE, 0);
+         sptr_expr = copy_node (null_pointer_node);
+         TREE_TYPE (sptr_expr) = build_pointer_type (sig_ty);
        }
       else
-       vptr_expr = null_pointer_node;
-      TREE_TYPE (vptr_expr) = build_pointer_type (vtbl_type_node);
+       sptr_expr = build_unary_op (ADDR_EXPR, sig_tbl, 0);
     }
 
   if (initp)
     {
       result = tree_cons (NULL_TREE, optr_expr,
-                         tree_cons (NULL_TREE, sptr_expr,
-                                    build_tree_list (NULL_TREE, vptr_expr)));
+                         build_tree_list (NULL_TREE, sptr_expr));
       result = build_nt (CONSTRUCTOR, NULL_TREE, result);
       TREE_HAS_CONSTRUCTOR (result) = 1;
       result = digest_init (lhstype, result, 0);
@@ -832,14 +892,10 @@ build_signature_pointer_constructor (lhs, rhs)
                                     optr_expr);
       sptr_expr = build_modify_expr (build_sptr_ref (lhs), NOP_EXPR,
                                     sptr_expr);
-      vptr_expr = build_modify_expr (build_vptr_ref (lhs), NOP_EXPR,
-                                    vptr_expr);
 
       result = tree_cons (NULL_TREE, optr_expr,
                          tree_cons (NULL_TREE, sptr_expr,
-                                    tree_cons (NULL_TREE, vptr_expr,
-                                               build_tree_list (NULL_TREE,
-                                                                lhs))));
+                                    build_tree_list (NULL_TREE, lhs)));
       result = build_compound_expr (result);
     }
 
@@ -875,53 +931,80 @@ save_this (instance)
 /* Build a signature member function call.  Looks up the signature table
    entry corresponding to FUNCTION.  Depending on the value of the CODE
    field, either call the function in PFN directly, or use OFFSET to
-   index INSTANCE's virtual function table.  */
+   index the object's virtual function table.  */
 
 tree
-build_signature_method_call (basetype, instance, function, parms)
-     tree basetype, instance, function, parms;
+build_signature_method_call (function, parms)
+     tree function, parms;
 {
+  tree instance = TREE_VALUE (parms);
   tree saved_instance = save_this (instance);  /* Create temp for `this'.  */
+  tree object_ptr = build_optr_ref (saved_instance);
+  tree new_object_ptr, new_parms;
   tree signature_tbl_ptr = build_sptr_ref (saved_instance);
   tree sig_field_name = DECL_NAME (DECL_MEMFUNC_POINTER_TO (function));
+  tree basetype = DECL_CONTEXT (function);
   tree basetype_path = TYPE_BINFO (basetype);
   tree tbl_entry = build_component_ref (build1 (INDIRECT_REF, basetype,
                                                signature_tbl_ptr),
                                        sig_field_name, basetype_path, 1);
-  tree code, offset, pfn, vfn;
+  tree tag, delta, pfn, vt_off, idx, vfn;
   tree deflt_call = NULL_TREE, direct_call, virtual_call, result;
 
-  code = build_component_ref (tbl_entry, get_identifier (SIGTABLE_CODE_NAME),
-                            NULL_TREE, 1);
-  offset = build_component_ref (tbl_entry,
-                               get_identifier (SIGTABLE_OFFSET_NAME),
-                            NULL_TREE, 1);
-  pfn = build_component_ref (tbl_entry, get_identifier (SIGTABLE_PFN_NAME),
-                            NULL_TREE, 1);
+  tbl_entry = save_expr (tbl_entry);
+  tag = build_component_ref (tbl_entry, tag_identifier, NULL_TREE, 1);
+  delta = build_component_ref (tbl_entry, delta_identifier, NULL_TREE, 1);
+  pfn = build_component_ref (tbl_entry, pfn_identifier, NULL_TREE, 1);
+  vt_off = build_component_ref (tbl_entry, vt_off_identifier, NULL_TREE, 1);
+  idx = build_component_ref (tbl_entry, index_identifier, NULL_TREE, 1);
   TREE_TYPE (pfn) = build_pointer_type (TREE_TYPE (function)); 
 
   if (IS_DEFAULT_IMPLEMENTATION (function))
     {
       pfn = save_expr (pfn);
-      deflt_call = build_function_call (pfn,
-                                       tree_cons (NULL_TREE, saved_instance,
-                                                  TREE_CHAIN (parms)));
+      deflt_call = build_function_call (pfn, parms);
     }
 
+  new_object_ptr = build (PLUS_EXPR, build_pointer_type (basetype),
+                         cp_convert (ptrdiff_type_node, object_ptr),
+                         cp_convert (ptrdiff_type_node, delta));
+
+  parms = tree_cons (NULL_TREE,
+                    cp_convert (build_pointer_type (basetype), object_ptr),
+                    TREE_CHAIN (parms));
+  new_parms = tree_cons (NULL_TREE, new_object_ptr, TREE_CHAIN (parms));
+
   {
     /* Cast the signature method to have `this' of a normal pointer type.  */
     tree old_this = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn))));
 
-    TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) =
-      build_type_variant (TYPE_POINTER_TO (basetype),
-                         TYPE_READONLY (old_this),
-                         TYPE_VOLATILE (old_this));
+    TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn))))
+      = build_type_variant (build_pointer_type (basetype),
+                           TYPE_READONLY (old_this),
+                           TYPE_VOLATILE (old_this));
 
-    direct_call = build_function_call (pfn, parms);
+    direct_call = build_function_call (pfn, new_parms);
 
-    vfn = build_vfn_ref (&TREE_VALUE (parms), saved_instance, offset);
-    TREE_TYPE (vfn) = build_pointer_type (TREE_TYPE (function));
-    virtual_call = build_function_call (vfn, parms);
+    {
+      tree vfld, vtbl, aref;
+
+      vfld = build (PLUS_EXPR,
+                   build_pointer_type (build_pointer_type (vtbl_type_node)),
+                   cp_convert (ptrdiff_type_node, object_ptr),
+                   cp_convert (ptrdiff_type_node, vt_off));
+      vtbl = build_indirect_ref (build_indirect_ref (vfld, NULL_PTR),
+                                NULL_PTR);
+      aref = build_array_ref (vtbl, idx);
+
+      if (flag_vtable_thunks)
+       vfn = aref;
+      else
+       vfn = build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
+
+      TREE_TYPE (vfn) = build_pointer_type (TREE_TYPE (function));
+
+      virtual_call = build_function_call (vfn, new_parms);
+    }
 
     /* Undo the cast, make `this' a signature pointer again.  */
     TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))) = old_this;
@@ -935,22 +1018,22 @@ build_signature_method_call (basetype, instance, function, parms)
          && (!deflt_call || deflt_call == error_mark_node)))
     {
       compiler_error ("cannot build call of signature member function `%s'",
-                     fndecl_as_string (NULL, function, 1));
+                     fndecl_as_string (function, 1));
       return error_mark_node;
     }
 
   if (IS_DEFAULT_IMPLEMENTATION (function))
     {
-      tree test = build_binary_op_nodefault (EQ_EXPR, code, integer_one_node,
-                                            EQ_EXPR);
-      result = build_conditional_expr (code,
+      tree test = build_binary_op_nodefault (LT_EXPR, tag, integer_zero_node,
+                                            LT_EXPR);
+      result = build_conditional_expr (tag,
                                       build_conditional_expr (test,
-                                                              virtual_call,
-                                                              deflt_call),
+                                                              deflt_call,
+                                                              virtual_call),
                                       direct_call);
     }
   else
-    result = build_conditional_expr (code, virtual_call, direct_call);
+    result = build_conditional_expr (tag, virtual_call, direct_call);
 
   /* If we created a temporary variable for `this', initialize it first.  */
   if (instance != saved_instance)
@@ -976,7 +1059,7 @@ build_optr_ref (instance)
 /* Create a COMPONENT_REF expression for referencing the SPTR field
    of a signature pointer or reference.  */
 
-tree
+static tree
 build_sptr_ref (instance)
      tree instance;
 {
@@ -984,15 +1067,3 @@ build_sptr_ref (instance)
 
   return build_component_ref (instance, field, NULL_TREE, 1);
 }
-
-/* Create a COMPONENT_REF expression for referencing the VPTR field
-   of a signature pointer or reference.  */
-
-tree
-build_vptr_ref (instance)
-     tree instance;
-{
-  tree field = get_identifier (SIGNATURE_VPTR_NAME);
-
-  return build_component_ref (instance, field, NULL_TREE, 1);
-}
This page took 0.051902 seconds and 5 git commands to generate.