[C++ PATCH] new abi incomplete pointers

Nathan Sidwell nathan@codesourcery.com
Thu Apr 20 07:30:00 GMT 2000


Hi,
I've installed the attached patch which implements the newabi's
updated type_info NTBS linkage and deals with incomplete pointer
chains.

No change in old-abi.

nathan
-- 
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2000-04-16  Nathan Sidwell  <nathan@codesourcery.com>

	* rtti.c (init_rtti_processing): Set tinfo_var_id in new-abi.
	(target_incomplete_p): New function.
	(tinfo_base_init): Create comdat NTBS name variable.
	(ptr_initializer): Add non_public parameter. Calculate it.
	(ptmd_initializer): Likewise.
	(synthesize_tinfo_var): Adjust. Emit incomplete class tinfo.
	(create_real_tinfo_var): Add non_public parameter. Use it.
	Push proxy into global namespace.
	* inc/cxxabi.h (__pointer_type_info::incomplete_class_mask):
	New enumeration.
	* inc/typeinfo (type_info::before, type_info::operator==):
	Compare __name addresses.
	
	* tinfo2.cc: Remove new-abi builtins comment.

Index: cp/rtti.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/rtti.c,v
retrieving revision 1.86
diff -c -3 -p -r1.86 rtti.c
*** rtti.c	2000/04/11 16:27:42	1.86
--- rtti.c	2000/04/16 09:09:12
*************** static tree throw_bad_typeid PARAMS((voi
*** 62,77 ****
  static tree get_tinfo_decl_dynamic PARAMS((tree));
  static tree tinfo_from_decl PARAMS((tree));
  static int qualifier_flags PARAMS((tree));
  static tree tinfo_base_init PARAMS((tree, tree));
  static tree generic_initializer PARAMS((tree, tree));
! static tree ptr_initializer PARAMS((tree, tree));
! static tree ptmd_initializer PARAMS((tree, tree));
  static tree dfs_class_hint_mark PARAMS ((tree, void *));
  static tree dfs_class_hint_unmark PARAMS ((tree, void *));
  static int class_hint_flags PARAMS((tree));
  static tree class_initializer PARAMS((tree, tree, tree));
  static tree synthesize_tinfo_var PARAMS((tree, tree));
! static tree create_real_tinfo_var PARAMS((tree, tree, tree));
  static tree create_pseudo_type_info PARAMS((const char *, int, ...));
  static tree get_vmi_pseudo_type_info PARAMS((int));
  static void create_tinfo_types PARAMS((void));
--- 62,78 ----
  static tree get_tinfo_decl_dynamic PARAMS((tree));
  static tree tinfo_from_decl PARAMS((tree));
  static int qualifier_flags PARAMS((tree));
+ static int target_incomplete_p PARAMS((tree));
  static tree tinfo_base_init PARAMS((tree, tree));
  static tree generic_initializer PARAMS((tree, tree));
! static tree ptr_initializer PARAMS((tree, tree, int *));
! static tree ptmd_initializer PARAMS((tree, tree, int *));
  static tree dfs_class_hint_mark PARAMS ((tree, void *));
  static tree dfs_class_hint_unmark PARAMS ((tree, void *));
  static int class_hint_flags PARAMS((tree));
  static tree class_initializer PARAMS((tree, tree, tree));
  static tree synthesize_tinfo_var PARAMS((tree, tree));
! static tree create_real_tinfo_var PARAMS((tree, tree, tree, int));
  static tree create_pseudo_type_info PARAMS((const char *, int, ...));
  static tree get_vmi_pseudo_type_info PARAMS((int));
  static void create_tinfo_types PARAMS((void));
*************** init_rtti_processing ()
*** 95,108 ****
            (build_qualified_type
              (type_info_type_node, TYPE_QUAL_CONST)),
           void_list_node);
      }
    else
      {
        tinfo_decl_id = get_identifier ("__ti");
        tinfo_decl_type = build_qualified_type
                            (type_info_type_node, TYPE_QUAL_CONST);
      }
-   tinfo_var_id = get_identifier ("__ti");
  }
  
  /* Given a pointer to an object with at least one virtual table
--- 96,111 ----
            (build_qualified_type
              (type_info_type_node, TYPE_QUAL_CONST)),
           void_list_node);
+       tinfo_var_id = get_identifier ("__ti");
      }
    else
      {
+       /* FIXME: These identifier prefixes are not set in stone yet.  */
        tinfo_decl_id = get_identifier ("__ti");
+       tinfo_var_id = get_identifier ("__tn");
        tinfo_decl_type = build_qualified_type
                            (type_info_type_node, TYPE_QUAL_CONST);
      }
  }
  
  /* Given a pointer to an object with at least one virtual table
*************** qualifier_flags (type)
*** 1296,1311 ****
    return flags;
  }
  
  /* Return a CONSTRUCTOR for the common part of the type_info objects. This
!    is the vtable pointer and NTBS name.  */
  
  static tree
  tinfo_base_init (desc, target)
       tree desc;
       tree target;
  {
-   tree name_string = tinfo_name (target);
    tree init = NULL_TREE;
    
    if (TINFO_VTABLE_DECL (desc))
      {
--- 1299,1359 ----
    return flags;
  }
  
+ /* Return non-zero, if the pointer chain TYPE ends at an incomplete type, or
+    contains a pointer to member of an incomplete class.  */
+ 
+ static int
+ target_incomplete_p (type)
+      tree type;
+ {
+   while (TREE_CODE (type) == POINTER_TYPE)
+     if (TYPE_PTRMEM_P (type))
+       {
+         if (!COMPLETE_TYPE_P (TYPE_PTRMEM_CLASS_TYPE (type)))
+           return 1;
+         type = TYPE_PTRMEM_POINTED_TO_TYPE (type);
+       }
+     else
+       type = TREE_TYPE (type);
+   if (!COMPLETE_OR_VOID_TYPE_P (type))
+     return 1;
+   
+   return 0;
+ }
+ 
  /* Return a CONSTRUCTOR for the common part of the type_info objects. This
!    is the vtable pointer and NTBS name.  The NTBS name is emitted as a
!    comdat const char array, so it becomes a unique key for the type. Generate
!    and emit that VAR_DECL here.  (We can't always emit the type_info itself
!    as comdat, because of pointers to incomplete.) */
  
  static tree
  tinfo_base_init (desc, target)
       tree desc;
       tree target;
  {
    tree init = NULL_TREE;
+   tree name_decl;
+   
+   {
+     /* Generate the NTBS array variable.  */
+     tree name_name = build_overload_with_type (tinfo_var_id, target);
+     tree name_type = build_cplus_array_type
+                      (build_qualified_type (char_type_node, TYPE_QUAL_CONST),
+                      NULL_TREE);
+     tree name_string = tinfo_name (target);
+     name_decl = build_lang_decl (VAR_DECL, name_name, name_type);
+     
+     DECL_ARTIFICIAL (name_decl) = 1;
+     TREE_READONLY (name_decl) = 1;
+     TREE_STATIC (name_decl) = 1;
+     DECL_EXTERNAL (name_decl) = 0;
+     TREE_PUBLIC (name_decl) = 1;
+     comdat_linkage (name_decl);
+     DECL_ASSEMBLER_NAME (name_decl) = DECL_NAME (name_decl);
+     DECL_INITIAL (name_decl) = name_string;
+     cp_finish_decl (name_decl, name_string, NULL_TREE, 0);
+   }
    
    if (TINFO_VTABLE_DECL (desc))
      {
*************** tinfo_base_init (desc, target)
*** 1313,1319 ****
        init = tree_cons (NULL_TREE, vtbl_ptr, init);
      }
    
!   init = tree_cons (NULL_TREE, decay_conversion (name_string), init);
    
    init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, nreverse (init));
    TREE_HAS_CONSTRUCTOR (init) = TREE_CONSTANT (init) = TREE_STATIC (init) = 1;
--- 1361,1367 ----
        init = tree_cons (NULL_TREE, vtbl_ptr, init);
      }
    
!   init = tree_cons (NULL_TREE, decay_conversion (name_decl), init);
    
    init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, nreverse (init));
    TREE_HAS_CONSTRUCTOR (init) = TREE_CONSTANT (init) = TREE_STATIC (init) = 1;
*************** generic_initializer (desc, target)
*** 1343,1356 ****
     which adds target type and qualifier flags members to the type_info base.  */
  
  static tree
! ptr_initializer (desc, target)
       tree desc;
       tree target;
  {
    tree init = tinfo_base_init (desc, target);
    tree to = TREE_TYPE (target);
    int flags = qualifier_flags (to);
    
    init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init);
    init = tree_cons (NULL_TREE,
                      build_unary_op (ADDR_EXPR,
--- 1391,1411 ----
     which adds target type and qualifier flags members to the type_info base.  */
  
  static tree
! ptr_initializer (desc, target, non_public_ptr)
       tree desc;
       tree target;
+      int *non_public_ptr;
  {
    tree init = tinfo_base_init (desc, target);
    tree to = TREE_TYPE (target);
    int flags = qualifier_flags (to);
+   int incomplete = target_incomplete_p (to);
    
+   if (incomplete)
+     {
+       flags |= 8;
+       *non_public_ptr = 1;
+     }
    init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init);
    init = tree_cons (NULL_TREE,
                      build_unary_op (ADDR_EXPR,
*************** ptr_initializer (desc, target)
*** 1364,1381 ****
  
  /* Return the CONSTRUCTOR expr for a type_info of pointer to member data TYPE.
     DESC provides information about the particular type_info derivation,
!    which adds target type and qualifier flags members to the type_info base.  */
  
  static tree
! ptmd_initializer (desc, target)
       tree desc;
       tree target;
  {
    tree init = tinfo_base_init (desc, target);
    tree to = TYPE_PTRMEM_POINTED_TO_TYPE (target);
    tree klass = TYPE_PTRMEM_CLASS_TYPE (target);
    int flags = qualifier_flags (to);
    
    init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init);
    init = tree_cons (NULL_TREE,
                      build_unary_op (ADDR_EXPR,
--- 1419,1446 ----
  
  /* Return the CONSTRUCTOR expr for a type_info of pointer to member data TYPE.
     DESC provides information about the particular type_info derivation,
!    which adds class, target type and qualifier flags members to the type_info
!    base.  */
  
  static tree
! ptmd_initializer (desc, target, non_public_ptr)
       tree desc;
       tree target;
+      int *non_public_ptr;
  {
    tree init = tinfo_base_init (desc, target);
    tree to = TYPE_PTRMEM_POINTED_TO_TYPE (target);
    tree klass = TYPE_PTRMEM_CLASS_TYPE (target);
    int flags = qualifier_flags (to);
+   int incomplete = target_incomplete_p (to);
    
+   if (incomplete)
+     {
+       flags |= 0x8;
+       *non_public_ptr = 1;
+     }
+   if (!COMPLETE_TYPE_P (klass))
+     flags |= 0x10;
    init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init);
    init = tree_cons (NULL_TREE,
                      build_unary_op (ADDR_EXPR,
*************** synthesize_tinfo_var (target_type, real_
*** 1489,1494 ****
--- 1554,1560 ----
  {
    tree var_init = NULL_TREE;
    tree var_type = NULL_TREE;
+   int non_public = 0;
    
    my_friendly_assert (new_abi_rtti_p (), 20000118);
  
*************** synthesize_tinfo_var (target_type, real_
*** 1498,1504 ****
        if (TYPE_PTRMEM_P (target_type))
          {
            var_type = ptmd_desc_type_node;
!           var_init = ptmd_initializer (var_type, target_type);
          }
        else
          {
--- 1564,1570 ----
        if (TYPE_PTRMEM_P (target_type))
          {
            var_type = ptmd_desc_type_node;
!           var_init = ptmd_initializer (var_type, target_type, &non_public);
          }
        else
          {
*************** synthesize_tinfo_var (target_type, real_
*** 1513,1519 ****
              /* These are in the runtime.  */
              return NULL_TREE;
            var_type = ptr_desc_type_node;
!           var_init = ptr_initializer (var_type, target_type);
          }
        break;
      case ENUMERAL_TYPE:
--- 1579,1585 ----
              /* These are in the runtime.  */
              return NULL_TREE;
            var_type = ptr_desc_type_node;
!           var_init = ptr_initializer (var_type, target_type, &non_public);
          }
        break;
      case ENUMERAL_TYPE:
*************** synthesize_tinfo_var (target_type, real_
*** 1532,1539 ****
      case RECORD_TYPE:
        if (!COMPLETE_TYPE_P (target_type))
          {
!           /* FIXME: incomplete type. Awaiting specification.  */
!           return NULL_TREE;
          }
        else if (!CLASSTYPE_N_BASECLASSES (target_type))
          {
--- 1598,1607 ----
      case RECORD_TYPE:
        if (!COMPLETE_TYPE_P (target_type))
          {
!           /* Emit a non-public class_type_info.  */
!           non_public = 1;
!           var_type = class_desc_type_node;
!           var_init = class_initializer (var_type, target_type, NULL_TREE);
          }
        else if (!CLASSTYPE_N_BASECLASSES (target_type))
          {
*************** synthesize_tinfo_var (target_type, real_
*** 1619,1651 ****
      default:
        my_friendly_abort (20000117);
      }
    
!   return create_real_tinfo_var (real_name, TINFO_PSEUDO_TYPE (var_type), var_init);
  }
  
! /* Create the real typeinfo variable.  */
  
  static tree
! create_real_tinfo_var (name, type, init)
       tree name;
       tree type;
       tree init;
  {
    tree decl;
    
!   decl = build_lang_decl (VAR_DECL, name,
                            build_qualified_type (type, TYPE_QUAL_CONST));
    DECL_ARTIFICIAL (decl) = 1;
    TREE_READONLY (decl) = 1;
    TREE_STATIC (decl) = 1;
-   TREE_PUBLIC (decl) = 1;
    DECL_EXTERNAL (decl) = 0;
    
!   comdat_linkage (decl);
    DECL_ASSEMBLER_NAME (decl) = name;
    DECL_INITIAL (decl) = init;
    cp_finish_decl (decl, init, NULL_TREE, 0);
!   
    return decl;
  }
  
--- 1687,1735 ----
      default:
        my_friendly_abort (20000117);
      }
+   
    
!   return create_real_tinfo_var (real_name, TINFO_PSEUDO_TYPE (var_type),
!                                 var_init, non_public);
  }
  
! /* Create the real typeinfo variable.  NON_PUBLIC indicates that we cannot
!    make this variable public (comdat). */
  
  static tree
! create_real_tinfo_var (name, type, init, non_public)
       tree name;
       tree type;
       tree init;
+      int non_public;
  {
+   static int count = 0;
    tree decl;
+   tree hidden_name;
+   char hidden[30];
+   
+   sprintf (hidden, "%.*s_%d",
+            IDENTIFIER_LENGTH (tinfo_decl_id), IDENTIFIER_POINTER (tinfo_decl_id),
+            count++);
+   hidden_name = get_identifier (hidden);
    
!   decl = build_lang_decl (VAR_DECL, hidden_name,
                            build_qualified_type (type, TYPE_QUAL_CONST));
    DECL_ARTIFICIAL (decl) = 1;
    TREE_READONLY (decl) = 1;
    TREE_STATIC (decl) = 1;
    DECL_EXTERNAL (decl) = 0;
    
!   if (!non_public)
!     {
!       TREE_PUBLIC (decl) = 1;
!       comdat_linkage (decl);
!     }
    DECL_ASSEMBLER_NAME (decl) = name;
    DECL_INITIAL (decl) = init;
    cp_finish_decl (decl, init, NULL_TREE, 0);
!   pushdecl_top_level (decl);
!   TREE_USED (decl) = 1;
    return decl;
  }
  
*************** tinfo_decl_p (t, data)
*** 1951,1957 ****
     actual type this is describing. The DECL_ASSEMBLER_NAME of the generated
     definition is set to that of the supplied decl, so that they can be tied
     up. Mark the supplied decl as having been dealt with. Emitting one
!    definitions might cause other declarations to be emitted.
     
     We need to do things this way, because we're trying to do something like
     
--- 2035,2041 ----
     actual type this is describing. The DECL_ASSEMBLER_NAME of the generated
     definition is set to that of the supplied decl, so that they can be tied
     up. Mark the supplied decl as having been dealt with. Emitting one
!    definition might cause other definitions to be required.
     
     We need to do things this way, because we're trying to do something like
     
Index: cp/tinfo2.cc
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/tinfo2.cc,v
retrieving revision 1.21
diff -c -3 -p -r1.21 tinfo2.cc
*** tinfo2.cc	2000/04/10 16:21:27	1.21
--- tinfo2.cc	2000/04/16 09:09:12
*************** BUILTIN (v); BUILTIN (x); BUILTIN (l); B
*** 438,447 ****
  BUILTIN (c); BUILTIN (w); BUILTIN (r); BUILTIN (d); BUILTIN (f);
  BUILTIN (Ui); BUILTIN (Ul); BUILTIN (Ux); BUILTIN (Us); BUILTIN (Uc);
  BUILTIN (Sc);
- #else
- // new abi
- 
- // we need to define the fundamental type type_info's, but the name mangling is
- // not yet defined.
  
  #endif
--- 438,442 ----
Index: cp/inc/cxxabi.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/inc/cxxabi.h,v
retrieving revision 1.7
diff -c -3 -p -r1.7 cxxabi.h
*** cxxabi.h	2000/04/13 11:14:29	1.7
--- cxxabi.h	2000/04/16 09:09:12
*************** public:
*** 68,74 ****
      const_mask = 0x1,
      volatile_mask = 0x2,
      restrict_mask = 0x4,
!     incomplete_mask = 0x8
    };
  
  /* implementation defined member functions */
--- 68,75 ----
      const_mask = 0x1,
      volatile_mask = 0x2,
      restrict_mask = 0x4,
!     incomplete_mask = 0x8,
!     incomplete_class_mask = 0x10
    };
  
  /* implementation defined member functions */
Index: cp/inc/typeinfo
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/inc/typeinfo,v
retrieving revision 1.11
diff -c -3 -p -r1.11 typeinfo
*** typeinfo	2000/04/09 15:59:16	1.11
--- typeinfo	2000/04/16 09:09:12
*************** public:
*** 56,69 ****
      { return !operator== (__arg); }
  
  #else
!   // In new abi we can rely on type_info's being unique,
    // and therefore address comparisons are sufficient.
    bool before (const type_info& __arg) const
!     { return this < &__arg; }
    const char* name () const
      { return __name; }
    bool operator== (const type_info& __arg) const
!     { return &__arg == this; }
    bool operator!= (const type_info& __arg) const
      { return !operator== (__arg); }
  #endif
--- 56,69 ----
      { return !operator== (__arg); }
  
  #else
!   // In new abi we can rely on type_info's NTBS being unique,
    // and therefore address comparisons are sufficient.
    bool before (const type_info& __arg) const
!     { return __name < __arg.__name; }
    const char* name () const
      { return __name; }
    bool operator== (const type_info& __arg) const
!     { return __name == __arg.__name; }
    bool operator!= (const type_info& __arg) const
      { return !operator== (__arg); }
  #endif


More information about the Gcc-patches mailing list