(C++) preliminary COM support patch

Jason Merrill jason@cygnus.com
Tue Apr 13 00:39:00 GMT 1999


This patch adds support for classes that serve as COM interfaces.  Mainly,
this means that their vtables don't have the extra RTTI slots at the
beginning, because COM expects the virtual functions to start right away.

This flag will be set via an attribute yet to come...

1999-04-12  Jason Merrill  <jason@yorick.cygnus.com>

	* cp-tree.h (struct lang_type): Add com_interface.
	(CLASSTYPE_COM_INTERFACE): New macro.
	* class.c (set_rtti_entry): COM interface classes have no RTTI 
	entries in their vtables; adjust.
	(add_virtual_function, finish_base_struct, skip_rtti_stuff,
	modify_one_vtable, fixup_vtable_deltas1, override_one_vtable, 
	finish_struct_1): Likewise.
	* decl2.c (mark_vtable_entries): Likewise.
	* rtti.c (build_headof, get_tinfo_fn_dynamic): Likewise.
	* search.c (get_abstract_virtuals_1, get_abstract_virtuals,
	expand_upcast_fixups): Likewise.
	* tree.c (debug_binfo): Likewise.

Index: class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.143
diff -c -p -r1.143 class.c
*** class.c	1999/04/13 00:20:40	1.143
--- class.c	1999/04/13 07:34:52
*************** set_rtti_entry (virtuals, offset, type)
*** 671,676 ****
--- 671,679 ----
  {
    tree vfn;
  
+   if (CLASSTYPE_COM_INTERFACE (type))
+     return;
+ 
    if (flag_rtti)
      vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn (type));
    else
*************** add_virtual_function (pv, phv, has_virtu
*** 1035,1044 ****
        CLASSTYPE_RTTI (t) = t;
  
        /* If we are using thunks, use two slots at the front, one
! 	 for the offset pointer, one for the tdesc pointer.  */
!       if (*has_virtual == 0 && flag_vtable_thunks)
  	{
! 	  *has_virtual = 1;
  	}
  
        /* Build a new INT_CST for this DECL_VINDEX.  */
--- 1038,1051 ----
        CLASSTYPE_RTTI (t) = t;
  
        /* If we are using thunks, use two slots at the front, one
! 	 for the offset pointer, one for the tdesc pointer.
!          For ARM-style vtables, use the same slot for both.  */
!       if (*has_virtual == 0 && ! CLASSTYPE_COM_INTERFACE (t))
  	{
! 	  if (flag_vtable_thunks)
! 	    *has_virtual = 2;
! 	  else
! 	    *has_virtual = 1;
  	}
  
        /* Build a new INT_CST for this DECL_VINDEX.  */
*************** add_virtual_function (pv, phv, has_virtu
*** 1046,1052 ****
  	static tree index_table[256];
  	tree idx;
  	/* We skip a slot for the offset/tdesc entry.  */
! 	int i = ++(*has_virtual);
  
  	if (i >= 256 || index_table[i] == 0)
  	  {
--- 1053,1059 ----
  	static tree index_table[256];
  	tree idx;
  	/* We skip a slot for the offset/tdesc entry.  */
! 	int i = (*has_virtual)++;
  
  	if (i >= 256 || index_table[i] == 0)
  	  {
*************** finish_base_struct (t, b)
*** 1634,1639 ****
--- 1641,1661 ----
        TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
        TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype);
  
+       if (CLASSTYPE_COM_INTERFACE (basetype))
+ 	{
+ 	  CLASSTYPE_COM_INTERFACE (t) = 1;
+ 	  if (i > 0)
+ 	    cp_error
+ 	      ("COM interface type `%T' must be the leftmost base class",
+ 	       basetype);
+ 	}
+       else if (CLASSTYPE_COM_INTERFACE (t))
+ 	{
+ 	  cp_error ("COM interface type `%T' with non-COM base class `%T'",
+ 		    t, basetype);
+ 	  CLASSTYPE_COM_INTERFACE (t) = 0;
+ 	}
+ 
        if (TYPE_VIRTUAL_P (basetype))
  	{
  	  /* Ensure that this is set from at least a virtual base
*************** get_class_offset (context, t, binfo, fnd
*** 2285,2295 ****
  /* Skip RTTI information at the front of the virtual list.  */
  
  unsigned HOST_WIDE_INT
! skip_rtti_stuff (virtuals)
!      tree *virtuals;
  {
    int n;
  
    n = 0;
    if (*virtuals)
      {
--- 2307,2320 ----
  /* Skip RTTI information at the front of the virtual list.  */
  
  unsigned HOST_WIDE_INT
! skip_rtti_stuff (virtuals, t)
!      tree *virtuals, t;
  {
    int n;
  
+   if (CLASSTYPE_COM_INTERFACE (t))
+     return 0;
+ 
    n = 0;
    if (*virtuals)
      {
*************** modify_one_vtable (binfo, t, fndecl, pfn
*** 2331,2337 ****
    if (fndecl == NULL_TREE)
      return;
  
!   n = skip_rtti_stuff (&virtuals);
  
    while (virtuals)
      {
--- 2356,2362 ----
    if (fndecl == NULL_TREE)
      return;
  
!   n = skip_rtti_stuff (&virtuals, t);
  
    while (virtuals)
      {
*************** fixup_vtable_deltas1 (binfo, t)
*** 2425,2431 ****
    tree virtuals = BINFO_VIRTUALS (binfo);
    unsigned HOST_WIDE_INT n;
    
!   n = skip_rtti_stuff (&virtuals);
  
    while (virtuals)
      {
--- 2450,2456 ----
    tree virtuals = BINFO_VIRTUALS (binfo);
    unsigned HOST_WIDE_INT n;
    
!   n = skip_rtti_stuff (&virtuals, t);
  
    while (virtuals)
      {
*************** override_one_vtable (binfo, old, t)
*** 2598,2605 ****
    if (BINFO_NEW_VTABLE_MARKED (binfo))
      choose = NEITHER;
  
!   skip_rtti_stuff (&virtuals);
!   skip_rtti_stuff (&old_virtuals);
  
    while (virtuals)
      {
--- 2623,2630 ----
    if (BINFO_NEW_VTABLE_MARKED (binfo))
      choose = NEITHER;
  
!   skip_rtti_stuff (&virtuals, t);
!   skip_rtti_stuff (&old_virtuals, t);
  
    while (virtuals)
      {
*************** finish_struct_1 (t, warn_anon)
*** 3874,3888 ****
        /* We must enter these virtuals into the table.  */
        if (first_vfn_base_index < 0)
  	{
! 	  /* The second slot is for the tdesc pointer when thunks are used.  */
! 	  if (flag_vtable_thunks)
! 	    pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
  
! 	  /* The first slot is for the rtti offset.  */
! 	  pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
  
! 	  set_rtti_entry (pending_virtuals,
! 			  convert (ssizetype, integer_zero_node), t);
  	  build_vtable (NULL_TREE, t);
  	}
        else
--- 3899,3916 ----
        /* We must enter these virtuals into the table.  */
        if (first_vfn_base_index < 0)
  	{
! 	  if (! CLASSTYPE_COM_INTERFACE (t))
! 	    {
! 	      /* The second slot is for the tdesc pointer when thunks are used.  */
! 	      if (flag_vtable_thunks)
! 		pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
  
! 	      /* The first slot is for the rtti offset.  */
! 	      pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
  
! 	      set_rtti_entry (pending_virtuals,
! 			      convert (ssizetype, integer_zero_node), t);
! 	    }
  	  build_vtable (NULL_TREE, t);
  	}
        else
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.215
diff -c -p -r1.215 cp-tree.h
*** cp-tree.h	1999/04/13 00:20:37	1.215
--- cp-tree.h	1999/04/13 07:34:52
*************** struct lang_type
*** 736,746 ****
        unsigned non_aggregate : 1;
        unsigned is_partial_instantiation : 1;
        unsigned has_mutable : 1;
  
        /* The MIPS compiler gets it wrong if this struct also
  	 does not fill out to a multiple of 4 bytes.  Add a
  	 member `dummy' with new bits if you go over the edge.  */
!       unsigned dummy : 11;
      } type_flags;
  
    int vsize;
--- 736,747 ----
        unsigned non_aggregate : 1;
        unsigned is_partial_instantiation : 1;
        unsigned has_mutable : 1;
+       unsigned com_interface : 1;
  
        /* The MIPS compiler gets it wrong if this struct also
  	 does not fill out to a multiple of 4 bytes.  Add a
  	 member `dummy' with new bits if you go over the edge.  */
!       unsigned dummy : 10;
      } type_flags;
  
    int vsize;
*************** struct lang_type
*** 1010,1015 ****
--- 1011,1020 ----
  #define CLASSTYPE_HAS_MUTABLE(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_mutable)
  #define TYPE_HAS_MUTABLE_P(NODE) (cp_has_mutable_p (NODE))
  
+ /* Nonzero means that this type is meant for communication via COM.  */
+ #define CLASSTYPE_COM_INTERFACE(NODE) \
+   (TYPE_LANG_SPECIFIC(NODE)->type_flags.com_interface)
+ 
  /* A list of class types of which this type is a friend.  The
     TREE_VALUE is normally a TYPE, but will be a TEMPLATE_DECL in the
     case of a template friend.  */
*************** extern void pop_lang_context			PROTO((vo
*** 2724,2730 ****
  extern tree instantiate_type			PROTO((tree, tree, int));
  extern void print_class_statistics		PROTO((void));
  extern void maybe_push_cache_obstack		PROTO((void));
! extern unsigned HOST_WIDE_INT skip_rtti_stuff	PROTO((tree *));
  extern void build_self_reference		PROTO((void));
  extern void warn_hidden				PROTO((tree));
  extern tree get_enclosing_class			PROTO((tree));
--- 2729,2735 ----
  extern tree instantiate_type			PROTO((tree, tree, int));
  extern void print_class_statistics		PROTO((void));
  extern void maybe_push_cache_obstack		PROTO((void));
! extern unsigned HOST_WIDE_INT skip_rtti_stuff	PROTO((tree *, tree));
  extern void build_self_reference		PROTO((void));
  extern void warn_hidden				PROTO((tree));
  extern tree get_enclosing_class			PROTO((tree));
Index: decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.197
diff -c -p -r1.197 decl2.c
*** decl2.c	1999/04/02 15:36:10	1.197
--- decl2.c	1999/04/13 07:34:53
*************** mark_vtable_entries (decl)
*** 2339,2359 ****
  {
    tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL (decl));
  
-   if (flag_rtti)
-     {
-       tree fnaddr = (flag_vtable_thunks ? TREE_VALUE (TREE_CHAIN (entries))
- 		     : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
-       tree fn = TREE_OPERAND (fnaddr, 0);
-       TREE_ADDRESSABLE (fn) = 1;
-       mark_used (fn);
-     }
-   skip_rtti_stuff (&entries);
- 
    for (; entries; entries = TREE_CHAIN (entries))
      {
!       tree fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries) 
! 		     : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
!       tree fn = TREE_OPERAND (fnaddr, 0);
        TREE_ADDRESSABLE (fn) = 1;
        if (DECL_LANG_SPECIFIC (fn) && DECL_ABSTRACT_VIRTUAL_P (fn))
  	{
--- 2339,2356 ----
  {
    tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL (decl));
  
    for (; entries; entries = TREE_CHAIN (entries))
      {
!       tree fnaddr;
!       tree fn;
! 
!       if (TREE_CODE (TREE_VALUE (entries)) == NOP_EXPR)
! 	/* RTTI offset.  */
! 	continue;
! 
!       fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries) 
! 		: FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
!       fn = TREE_OPERAND (fnaddr, 0);
        TREE_ADDRESSABLE (fn) = 1;
        if (DECL_LANG_SPECIFIC (fn) && DECL_ABSTRACT_VIRTUAL_P (fn))
  	{
Index: rtti.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/rtti.c,v
retrieving revision 1.28
diff -c -p -r1.28 rtti.c
*** rtti.c	1999/03/26 07:44:50	1.28
--- rtti.c	1999/04/13 07:34:53
*************** build_headof (exp)
*** 108,113 ****
--- 108,118 ----
  
    if (!TYPE_VIRTUAL_P (type))
      return exp;
+   if (CLASSTYPE_COM_INTERFACE (type))
+     {
+       cp_error ("RTTI not supported for COM interface type `%T'", type);
+       return error_mark_node;
+     }
  
    /* If we don't have rtti stuff, get to a sub-object that does.  */
    if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp))))
*************** get_tinfo_fn_dynamic (exp)
*** 216,221 ****
--- 221,231 ----
  
        if (! flag_rtti)
  	error ("taking dynamic typeid of object with -fno-rtti");
+       if (CLASSTYPE_COM_INTERFACE (type))
+ 	{
+ 	  cp_error ("RTTI not supported for COM interface type `%T'", type);
+ 	  return error_mark_node;
+ 	}
  
        /* If we don't have rtti stuff, get to a sub-object that does.  */
        if (! CLASSTYPE_VFIELDS (type))
Index: search.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/search.c,v
retrieving revision 1.94
diff -c -p -r1.94 search.c
*** search.c	1999/04/08 13:05:50	1.94
--- search.c	1999/04/13 07:34:53
*************** get_abstract_virtuals_1 (binfo, do_self,
*** 2034,2040 ****
      {
        tree virtuals = BINFO_VIRTUALS (binfo);
  
!       skip_rtti_stuff (&virtuals);
  
        while (virtuals)
  	{
--- 2034,2040 ----
      {
        tree virtuals = BINFO_VIRTUALS (binfo);
  
!       skip_rtti_stuff (&virtuals, BINFO_TYPE (binfo));
  
        while (virtuals)
  	{
*************** get_abstract_virtuals (type)
*** 2067,2073 ****
      {
        tree virtuals = BINFO_VIRTUALS (vbases);
  
!       skip_rtti_stuff (&virtuals);
  
        while (virtuals)
  	{
--- 2067,2073 ----
      {
        tree virtuals = BINFO_VIRTUALS (vbases);
  
!       skip_rtti_stuff (&virtuals, type);
  
        while (virtuals)
  	{
*************** expand_upcast_fixups (binfo, addr, orig_
*** 2528,2534 ****
        *vbase_offsets = delta;
      }
  
!   n = skip_rtti_stuff (&virtuals);
  
    while (virtuals)
      {
--- 2528,2534 ----
        *vbase_offsets = delta;
      }
  
!   n = skip_rtti_stuff (&virtuals, t);
  
    while (virtuals)
      {
Index: tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.104
diff -c -p -r1.104 tree.c
*** tree.c	1999/04/06 14:38:08	1.104
--- tree.c	1999/04/13 07:34:53
*************** debug_binfo (elem)
*** 1169,1175 ****
    fprintf (stderr, "virtuals:\n");
    virtuals = BINFO_VIRTUALS (elem);
  
!   n = skip_rtti_stuff (&virtuals);
  
    while (virtuals)
      {
--- 1169,1175 ----
    fprintf (stderr, "virtuals:\n");
    virtuals = BINFO_VIRTUALS (elem);
  
!   n = skip_rtti_stuff (&virtuals, BINFO_TYPE (elem));
  
    while (virtuals)
      {


More information about the Gcc-patches mailing list