public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Fwd: [C++ PATCH]: Rework typeinfo objects
@ 2002-07-22  3:26 Jason Merrill
  0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2002-07-22  3:26 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 116 bytes --]

I just went looking for this patch on gcc-patches, and didn't find it;
fortunately I still had it in my mail file.


[-- Attachment #2: Type: message/rfc822, Size: 50483 bytes --]

[-- Attachment #2.1.1: Type: text/plain, Size: 761 bytes --]

Jason,
here's that rtti.c patch which reworks the typeinfo objects. Now
when a typeinfo is required, we generate an extern decl of the
ABI-defined type and reinterpret_cast it to std::type_info. At the
end of translation, we generate the appropriate initializers and emit
them.

I broke import_export_tinfo out of import_export_decl. All the
linkage determination code is now either there or in emit_tinfo_decl.
It might be wise to check this patch is ok on a comdat-difficult
host (HPUX?)

built & tested on i686-pc-linux-gnu, ok?

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

[-- Attachment #2.1.2: rtti-8.patch --]
[-- Type: text/plain, Size: 49212 bytes --]

2002-06-20  Nathan Sidwell  <nathan@codesourcery.com>

	* cp-tree.h (CPTI_TINFO_DECL_TYPE): Replace with ...
	(CPTI_TYPE_INFO_PTR_TYPE): ... this.
	(tinfo_decl_type): Replace with ...
	(type_info_ptr_type): ... this.
	(import_export_tinfo): Declare.
	(tinfo_decl_p): Rename to ...
	(unemitted_tinfo_decl_p): ... this.
	* decl2.c (import_export_decl): Break out tinfo handling into ...
	(import_export_tinfo): ... here. New function.
	(finish_file): Adjust.
	* rtti.c (TINFO_REAL_NAME): New macro.
	(init_rtti_processing): Create the tinfo types.
	(get_tinfo_decl_dynamic): Use type_info_ptr_type, get_tinfo_ptr.
	(get_tinfo_decl): Adjust.
	(get_tinfo_ptr): New function.
	(get_type_id): Use it.
	(tinfo_base_init): Create vtable decl here, if it doesn't exist.
	(ptr_initializer): Use get_tinfo_ptr.
	(ptm_initializer): Likewise.
	(synthesize_tinfo_var): Break into ...
	(get_pseudo_ti_init): ... this. Just create the initializer.
	(get_pseudo_ti_desc): .. and this.
	(create_real_tinfo_var): Remove.
	(create_pseudo_type_info): Don't create the vtable decl here.
	(get_vmi_pseudo_type_info): Remove.
	(create_tinfo_types): Adjust.
	(tinfo_decl_p): Rename to ...
	(unemitted_tinfo_decl_p): ... here. Adjust.
	(emit_tinfo_decl): Adjust. Create the initializer.

Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.719
diff -c -3 -p -r1.719 cp-tree.h
*** cp/cp-tree.h	16 Jun 2002 19:09:25 -0000	1.719
--- cp/cp-tree.h	21 Jun 2002 11:16:07 -0000
*************** enum cp_tree_index
*** 563,569 ****
      CPTI_STD,
      CPTI_ABI,
      CPTI_TYPE_INFO_TYPE,
!     CPTI_TINFO_DECL_TYPE,
      CPTI_ABORT_FNDECL,
      CPTI_GLOBAL_DELETE_FNDECL,
      CPTI_AGGR_TAG,
--- 563,569 ----
      CPTI_STD,
      CPTI_ABI,
      CPTI_TYPE_INFO_TYPE,
!     CPTI_TYPE_INFO_PTR_TYPE,
      CPTI_ABORT_FNDECL,
      CPTI_GLOBAL_DELETE_FNDECL,
      CPTI_AGGR_TAG,
*************** extern GTY(()) tree cp_global_trees[CPTI
*** 650,656 ****
  #define std_node			cp_global_trees[CPTI_STD]
  #define abi_node                        cp_global_trees[CPTI_ABI]
  #define type_info_type_node		cp_global_trees[CPTI_TYPE_INFO_TYPE]
! #define tinfo_decl_type			cp_global_trees[CPTI_TINFO_DECL_TYPE]
  #define abort_fndecl			cp_global_trees[CPTI_ABORT_FNDECL]
  #define global_delete_fndecl		cp_global_trees[CPTI_GLOBAL_DELETE_FNDECL]
  #define current_aggr			cp_global_trees[CPTI_AGGR_TAG]
--- 650,656 ----
  #define std_node			cp_global_trees[CPTI_STD]
  #define abi_node                        cp_global_trees[CPTI_ABI]
  #define type_info_type_node		cp_global_trees[CPTI_TYPE_INFO_TYPE]
! #define type_info_ptr_type		cp_global_trees[CPTI_TYPE_INFO_PTR_TYPE]
  #define abort_fndecl			cp_global_trees[CPTI_ABORT_FNDECL]
  #define global_delete_fndecl		cp_global_trees[CPTI_GLOBAL_DELETE_FNDECL]
  #define current_aggr			cp_global_trees[CPTI_AGGR_TAG]
*************** extern tree coerce_delete_type			PARAMS 
*** 3919,3924 ****
--- 3919,3925 ----
  extern void comdat_linkage			PARAMS ((tree));
  extern void import_export_vtable		PARAMS ((tree, tree, int));
  extern void import_export_decl			PARAMS ((tree));
+ extern void import_export_tinfo			PARAMS ((tree, tree));
  extern tree build_cleanup			PARAMS ((tree));
  extern void finish_file				PARAMS ((void));
  extern tree reparse_absdcl_as_expr		PARAMS ((tree, tree));
*************** extern tree get_tinfo_decl              
*** 4147,4153 ****
  extern tree get_typeid				PARAMS((tree));
  extern tree build_dynamic_cast			PARAMS((tree, tree));
  extern void emit_support_tinfos                 PARAMS((void));
! extern int tinfo_decl_p                         PARAMS((tree, void *));
  extern int emit_tinfo_decl                      PARAMS((tree *, void *));
  
  /* in search.c */
--- 4148,4154 ----
  extern tree get_typeid				PARAMS((tree));
  extern tree build_dynamic_cast			PARAMS((tree, tree));
  extern void emit_support_tinfos                 PARAMS((void));
! extern int unemitted_tinfo_decl_p    	        PARAMS((tree, void *));
  extern int emit_tinfo_decl                      PARAMS((tree *, void *));
  
  /* in search.c */
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.540
diff -c -3 -p -r1.540 decl2.c
*** cp/decl2.c	16 Jun 2002 19:09:26 -0000	1.540
--- cp/decl2.c	21 Jun 2002 11:16:08 -0000
*************** import_export_decl (decl)
*** 2509,2555 ****
        else
  	comdat_linkage (decl);
      }
-   else if (tinfo_decl_p (decl, 0))
-     {
-       /* Here, we only decide whether or not the tinfo node should be
- 	 emitted with the vtable.  The decl we're considering isn't
- 	 actually the one which gets emitted; that one is generated in
- 	 create_real_tinfo_var.  */
- 
-       tree ctype = TREE_TYPE (DECL_NAME (decl));
- 
-       if (IS_AGGR_TYPE (ctype))
- 	import_export_class (ctype);
- 
-       if (IS_AGGR_TYPE (ctype) && CLASSTYPE_INTERFACE_KNOWN (ctype)
- 	  && TYPE_POLYMORPHIC_P (ctype)
- 	  /* If -fno-rtti, we're not necessarily emitting this stuff with
- 	     the class, so go ahead and emit it now.  This can happen
- 	     when a class is used in exception handling.  */
- 	  && flag_rtti
- 	  /* If the type is a cv-qualified variant of a type, then we
- 	     must emit the tinfo function in this translation unit
- 	     since it will not be emitted when the vtable for the type
- 	     is output (which is when the unqualified version is
- 	     generated).  */
- 	  && same_type_p (ctype, TYPE_MAIN_VARIANT (ctype)))
- 	{
- 	  DECL_NOT_REALLY_EXTERN (decl)
- 	    = ! CLASSTYPE_INTERFACE_ONLY (ctype);
- 	  DECL_COMDAT (decl) = 0;
- 	}
-       else
- 	{
- 	  DECL_NOT_REALLY_EXTERN (decl) = 1;
- 	  DECL_COMDAT (decl) = 1;
- 	}
-     } 
    else
      comdat_linkage (decl);
  
    DECL_INTERFACE_KNOWN (decl) = 1;
  }
  
  tree
  build_cleanup (decl)
       tree decl;
--- 2509,2552 ----
        else
  	comdat_linkage (decl);
      }
    else
      comdat_linkage (decl);
  
    DECL_INTERFACE_KNOWN (decl) = 1;
  }
  
+ /* Here, we only decide whether or not the tinfo node should be
+    emitted with the vtable.  */
+ 
+ void
+ import_export_tinfo (decl, type)
+      tree decl;
+      tree type;
+ {
+   if (DECL_INTERFACE_KNOWN (decl))
+     return;
+   
+   if (IS_AGGR_TYPE (type))
+     import_export_class (type);
+       
+   if (IS_AGGR_TYPE (type) && CLASSTYPE_INTERFACE_KNOWN (type)
+       && TYPE_POLYMORPHIC_P (type)
+       /* If -fno-rtti, we're not necessarily emitting this stuff with
+ 	 the class, so go ahead and emit it now.  This can happen when
+ 	 a class is used in exception handling.  */
+       && flag_rtti)
+     {
+       DECL_NOT_REALLY_EXTERN (decl) = !CLASSTYPE_INTERFACE_ONLY (type);
+       DECL_COMDAT (decl) = 0;
+     }
+   else
+     {
+       DECL_NOT_REALLY_EXTERN (decl) = 1;
+       DECL_COMDAT (decl) = 1;
+     }
+   DECL_INTERFACE_KNOWN (decl) = 1;
+ }
+ 
  tree
  build_cleanup (decl)
       tree decl;
*************** finish_file ()
*** 3344,3350 ****
        
        /* Write out needed type info variables. Writing out one variable
           might cause others to be needed.  */
!       if (walk_globals (tinfo_decl_p, emit_tinfo_decl, /*data=*/0))
  	reconsider = 1;
  
        /* The list of objects with static storage duration is built up
--- 3341,3347 ----
        
        /* Write out needed type info variables. Writing out one variable
           might cause others to be needed.  */
!       if (walk_globals (unemitted_tinfo_decl_p, emit_tinfo_decl, /*data=*/0))
  	reconsider = 1;
  
        /* The list of objects with static storage duration is built up
Index: cp/rtti.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/rtti.c,v
retrieving revision 1.135
diff -c -3 -p -r1.135 rtti.c
*** cp/rtti.c	14 Jun 2002 00:50:32 -0000	1.135
--- cp/rtti.c	21 Jun 2002 11:16:09 -0000
***************
*** 1,5 ****
  /* RunTime Type Identification
!    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001
     Free Software Foundation, Inc.
     Mostly written by Jason Merrill (jason@cygnus.com).
  
--- 1,5 ----
  /* RunTime Type Identification
!    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
     Free Software Foundation, Inc.
     Mostly written by Jason Merrill (jason@cygnus.com).
  
*************** Boston, MA 02111-1307, USA.  */
*** 30,45 ****
  #include "assert.h"
  #include "toplev.h"
  
  /* Accessors for the type_info objects. We need to remember several things
     about each of the type_info types. The global tree nodes such as
     bltn_desc_type_node are TREE_LISTs, and these macros are used to access
     the required information. */
  /* The RECORD_TYPE of a type_info derived class. */
  #define TINFO_PSEUDO_TYPE(NODE) TREE_TYPE (NODE)
! /* The VAR_DECL of the vtable for the type_info derived class. */
  #define TINFO_VTABLE_DECL(NODE) TREE_VALUE (NODE)
! 
! extern struct obstack permanent_obstack;
  
  static tree build_headof PARAMS((tree));
  static tree ifnonnull PARAMS((tree, tree));
--- 30,75 ----
  #include "assert.h"
  #include "toplev.h"
  
+ /* C++ returns type information to the user in struct type_info
+    objects. We also use type information to implement dynamic_cast and
+    exception handlers. Type information for a particular type is
+    indicated with an ABI defined structure derived from type_info.
+    This would all be very straight forward, but for the fact that the
+    runtime library provides the definitions of the type_info structure
+    and the ABI defined derived classes. We cannot build declarations
+    of them directly in the compiler, but we need to layout objects of
+    their type.  Somewhere we have to lie.
+ 
+    We define layout compatible POD-structs with compiler-defined names
+    and generate the appropriate initializations for them (complete
+    with explicit mention of their vtable). When we have to provide a
+    type_info to the user we reinterpret_cast the internal compiler
+    type to type_info.  A well formed program can only explicitly refer
+    to the type_infos of complete types (& cv void).  However, we chain
+    pointer type_infos to the pointed-to-type, and that can be
+    incomplete.  We only need the addresses of such incomplete
+    type_info objects for static initialization.
+ 
+    The type information VAR_DECL of a type is held on the
+    IDENTIFIER_GLOBAL_VALUE of the type's mangled name. That VAR_DECL
+    will be the internal type.  It will usually have the correct
+    internal type reflecting the kind of type it represents (pointer,
+    array, function, class, inherited class, etc).  When the type it
+    represents is incomplete, it will have the internal type
+    corresponding to type_info.  That will only happen at the end of
+    translation, when we are emitting the type info objects.  */
+ 
  /* Accessors for the type_info objects. We need to remember several things
     about each of the type_info types. The global tree nodes such as
     bltn_desc_type_node are TREE_LISTs, and these macros are used to access
     the required information. */
  /* The RECORD_TYPE of a type_info derived class. */
  #define TINFO_PSEUDO_TYPE(NODE) TREE_TYPE (NODE)
! /* The VAR_DECL of the vtable for the type_info derived class.
!    This is only filled in at the end of the translation. */
  #define TINFO_VTABLE_DECL(NODE) TREE_VALUE (NODE)
! /* The IDENTIFIER_NODE naming the real class. */
! #define TINFO_REAL_NAME(NODE) TREE_PURPOSE (NODE)
  
  static tree build_headof PARAMS((tree));
  static tree ifnonnull PARAMS((tree, tree));
*************** static tree build_dynamic_cast_1 PARAMS(
*** 48,54 ****
  static tree throw_bad_cast PARAMS((void));
  static tree throw_bad_typeid PARAMS((void));
  static tree get_tinfo_decl_dynamic PARAMS((tree));
! static bool typeid_ok_p PARAMS ((void));
  static int qualifier_flags PARAMS((tree));
  static int target_incomplete_p PARAMS((tree));
  static tree tinfo_base_init PARAMS((tree, tree));
--- 78,85 ----
  static tree throw_bad_cast PARAMS((void));
  static tree throw_bad_typeid PARAMS((void));
  static tree get_tinfo_decl_dynamic PARAMS((tree));
! static tree get_tinfo_ptr PARAMS((tree));
! static bool typeid_ok_p PARAMS((void));
  static int qualifier_flags PARAMS((tree));
  static int target_incomplete_p PARAMS((tree));
  static tree tinfo_base_init PARAMS((tree, tree));
*************** static tree dfs_class_hint_mark PARAMS (
*** 59,73 ****
  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));
- static tree create_real_tinfo_var PARAMS((tree, 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));
  static int typeinfo_in_lib_p PARAMS((tree));
  
  static int doing_runtime = 0;
  \f
  void
  init_rtti_processing ()
  {
--- 90,110 ----
  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 create_pseudo_type_info PARAMS((const char *, int, ...));
! static tree get_pseudo_ti_init PARAMS ((tree, tree, int *));
! static tree get_pseudo_ti_desc PARAMS((tree));
  static void create_tinfo_types PARAMS((void));
  static int typeinfo_in_lib_p PARAMS((tree));
  
  static int doing_runtime = 0;
  \f
+ 
+ /* Declare language defined type_info type and a pointer to const
+    type_info.  This is incomplete here, and will be completed when
+    the user #includes <typeinfo>.  There are language defined
+    restrictions on what can be done until that is included.  Create
+    the internal versions of the ABI types.  */
+ 
  void
  init_rtti_processing ()
  {
*************** init_rtti_processing ()
*** 75,82 ****
    type_info_type_node = xref_tag
      (class_type_node, get_identifier ("type_info"), 1);
    pop_namespace ();
!   tinfo_decl_type = 
!     build_qualified_type (type_info_type_node, TYPE_QUAL_CONST);
  }
  
  /* Given the expression EXP of type `class *', return the head of the
--- 112,122 ----
    type_info_type_node = xref_tag
      (class_type_node, get_identifier ("type_info"), 1);
    pop_namespace ();
!   type_info_ptr_type = 
!     build_pointer_type
!      (build_qualified_type (type_info_type_node, TYPE_QUAL_CONST));
! 
!   create_tinfo_types ();
  }
  
  /* Given the expression EXP of type `class *', return the head of the
*************** get_tinfo_decl_dynamic (exp)
*** 183,195 ****
        /* The RTTI information is at index -1.  */
        index = build_int_2 (-1 * TARGET_VTABLE_DATA_ENTRY_DISTANCE, -1);
        t = build_vtbl_ref (exp, index);
!       TREE_TYPE (t) = build_pointer_type (tinfo_decl_type);
        return t;
      }
  
!   /* otherwise return the type_info for the static type of the expr.  */
!   exp = get_tinfo_decl (TYPE_MAIN_VARIANT (type));
!   return build_unary_op (ADDR_EXPR, exp, 0);
  }
  
  static bool
--- 223,234 ----
        /* The RTTI information is at index -1.  */
        index = build_int_2 (-1 * TARGET_VTABLE_DATA_ENTRY_DISTANCE, -1);
        t = build_vtbl_ref (exp, index);
!       TREE_TYPE (t) = type_info_ptr_type;
        return t;
      }
  
!   /* Otherwise return the type_info for the static type of the expr.  */
!   return get_tinfo_ptr (TYPE_MAIN_VARIANT (type));
  }
  
  static bool
*************** tinfo_name (type)
*** 263,271 ****
    return name_string;
  }
  
! /* Returns a decl for the type_info variable for TYPE.  You must
!    arrange that the decl is mark_used, if actually use it --- decls in
!    vtables are only used if the vtable is output.  */ 
  
  tree
  get_tinfo_decl (type)
--- 302,310 ----
    return name_string;
  }
  
! /* Return a VAR_DECL for the internal ABI defined type_info object for
!    TYPE. You must arrange that the decl is mark_used, if actually use
!    it --- decls in vtables are only used if the vtable is output.  */ 
  
  tree
  get_tinfo_decl (type)
*************** get_tinfo_decl (type)
*** 278,284 ****
        && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
      {
        error ("cannot create type information for type `%T' because its size is variable", 
! 		type);
        return error_mark_node;
      }
  
--- 317,323 ----
        && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
      {
        error ("cannot create type information for type `%T' because its size is variable", 
! 	     type);
        return error_mark_node;
      }
  
*************** get_tinfo_decl (type)
*** 291,326 ****
    name = mangle_typeinfo_for_type (type);
  
    d = IDENTIFIER_GLOBAL_VALUE (name);
!   if (d)
!     /* OK */;
!   else
      {
!       /* The tinfo decl is the type_info object itself.  We make all
!          tinfo objects look as type_info, even though they will end up
!          being a subclass of that when emitted.  This means that we'll
!          erroneously think we know the dynamic type -- be careful in the
!          runtime.  */
!       d = build_lang_decl (VAR_DECL, name, tinfo_decl_type);
        
        DECL_ARTIFICIAL (d) = 1;
-       DECL_ALIGN (d) = TYPE_ALIGN (ptr_type_node);
-       DECL_USER_ALIGN (d) = 0;
        TREE_READONLY (d) = 1;
        TREE_STATIC (d) = 1;
        DECL_EXTERNAL (d) = 1;
-       TREE_PUBLIC (d) = 1;
        SET_DECL_ASSEMBLER_NAME (d, name);
-       DECL_COMDAT (d) = 1;
        cp_finish_decl (d, NULL_TREE, NULL_TREE, 0);
  
        pushdecl_top_level (d);
        /* Remember the type it is for.  */
        TREE_TYPE (name) = type;
-       TREE_USED (name) = 1;
      }
    return d;
  }
  
  /* Return the type_info object for TYPE.  */
  
  tree
--- 330,373 ----
    name = mangle_typeinfo_for_type (type);
  
    d = IDENTIFIER_GLOBAL_VALUE (name);
!   if (!d)
      {
!       tree var_desc = get_pseudo_ti_desc (type);
! 
!       d = build_lang_decl (VAR_DECL, name, TINFO_PSEUDO_TYPE (var_desc));
        
        DECL_ARTIFICIAL (d) = 1;
        TREE_READONLY (d) = 1;
        TREE_STATIC (d) = 1;
        DECL_EXTERNAL (d) = 1;
        SET_DECL_ASSEMBLER_NAME (d, name);
        cp_finish_decl (d, NULL_TREE, NULL_TREE, 0);
  
        pushdecl_top_level (d);
+ 
        /* Remember the type it is for.  */
        TREE_TYPE (name) = type;
      }
+ 
    return d;
  }
  
+ /* Return a pointer to a type_info object describing TYPE, suitably
+    cast to the language defined type.  */
+ 
+ static tree
+ get_tinfo_ptr (type)
+      tree type;
+ {
+   tree exp = get_tinfo_decl (type);
+   
+    /* Convert to type_info type.  */
+   exp = build_unary_op (ADDR_EXPR, exp, 0);
+   exp = ocp_convert (type_info_ptr_type, exp, CONV_REINTERPRET, 0);
+ 
+   return exp;
+ }
+ 
  /* Return the type_info object for TYPE.  */
  
  tree
*************** get_typeid (type)
*** 349,355 ****
    if (!type)
      return error_mark_node;
  
!   return get_tinfo_decl (type);
  }
  
  /* Check whether TEST is null before returning RESULT.  If TEST is used in
--- 396,402 ----
    if (!type)
      return error_mark_node;
  
!   return build_indirect_ref (get_tinfo_ptr (type), NULL);
  }
  
  /* Check whether TEST is null before returning RESULT.  If TEST is used in
*************** tinfo_base_init (desc, target)
*** 682,687 ****
--- 729,735 ----
  {
    tree init = NULL_TREE;
    tree name_decl;
+   tree vtable_ptr;
    
    {
      tree name_name;
*************** tinfo_base_init (desc, target)
*** 709,720 ****
      cp_finish_decl (name_decl, name_string, NULL_TREE, 0);
      pushdecl_top_level (name_decl);
    }
!   
!   if (TINFO_VTABLE_DECL (desc))
      {
!       tree vtbl_ptr = TINFO_VTABLE_DECL (desc);
!       init = tree_cons (NULL_TREE, vtbl_ptr, init);
      }
    
    init = tree_cons (NULL_TREE, decay_conversion (name_decl), init);
    
--- 757,794 ----
      cp_finish_decl (name_decl, name_string, NULL_TREE, 0);
      pushdecl_top_level (name_decl);
    }
! 
!   vtable_ptr = TINFO_VTABLE_DECL (desc);
!   if (!vtable_ptr)
      {
!       tree real_type;
!   
!       push_nested_namespace (abi_node);
!       real_type = xref_tag (class_type_node, TINFO_REAL_NAME (desc), 1);
!       pop_nested_namespace (abi_node);
!   
!       if (!COMPLETE_TYPE_P (real_type))
! 	{
!           /* We never saw a definition of this type, so we need to
! 	     tell the compiler that this is an exported class, as
! 	     indeed all of the __*_type_info classes are.  */
! 	  SET_CLASSTYPE_INTERFACE_KNOWN (real_type);
! 	  CLASSTYPE_INTERFACE_ONLY (real_type) = 1;
! 	}
! 
!       vtable_ptr = get_vtable_decl (real_type, /*complete=*/1);
!       vtable_ptr = build_unary_op (ADDR_EXPR, vtable_ptr, 0);
! 
!       /* We need to point into the middle of the vtable.  */
!       vtable_ptr = build (PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr,
! 			  size_binop (MULT_EXPR,
! 				      size_int (2),
! 			      TYPE_SIZE_UNIT (vtable_entry_type)));
!       TREE_CONSTANT (vtable_ptr) = 1;
! 
!       TINFO_VTABLE_DECL (desc) = vtable_ptr;
      }
+   init = tree_cons (NULL_TREE, vtable_ptr, init);
    
    init = tree_cons (NULL_TREE, decay_conversion (name_decl), init);
    
*************** ptr_initializer (desc, target, non_publi
*** 763,770 ****
      }
    init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init);
    init = tree_cons (NULL_TREE,
!                     build_unary_op (ADDR_EXPR,
!                                     get_tinfo_decl (TYPE_MAIN_VARIANT (to)), 0),
                      init);
    
    init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, nreverse (init));
--- 837,843 ----
      }
    init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init);
    init = tree_cons (NULL_TREE,
!                     get_tinfo_ptr (TYPE_MAIN_VARIANT (to)),
                      init);
    
    init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, nreverse (init));
*************** ptm_initializer (desc, target, non_publi
*** 801,812 ****
      }
    init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init);
    init = tree_cons (NULL_TREE,
!                     build_unary_op (ADDR_EXPR,
!                                     get_tinfo_decl (TYPE_MAIN_VARIANT (to)), 0),
                      init);
    init = tree_cons (NULL_TREE,
!                     build_unary_op (ADDR_EXPR, get_tinfo_decl (klass), 0),
!                     init);  
    
    init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, nreverse (init));
    TREE_HAS_CONSTRUCTOR (init) = TREE_CONSTANT (init) = TREE_STATIC (init) = 1;
--- 874,884 ----
      }
    init = tree_cons (NULL_TREE, build_int_2 (flags, 0), init);
    init = tree_cons (NULL_TREE,
! 		    get_tinfo_ptr (TYPE_MAIN_VARIANT (to)),
                      init);
    init = tree_cons (NULL_TREE,
! 		    get_tinfo_ptr (klass),
! 		    init);  
    
    init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, nreverse (init));
    TREE_HAS_CONSTRUCTOR (init) = TREE_CONSTANT (init) = TREE_STATIC (init) = 1;
*************** typeinfo_in_lib_p (type)
*** 927,1007 ****
      }
  }
  
! /* Generate a pseudo_type_info VAR_DECL suitable for the supplied
!    TARGET_TYPE and corresponding to PUBLIC_DECL. This is the structure expected by
!    the runtime, and therefore has additional fields.  If we need not emit a
!    definition (because the runtime must contain it), return NULL_TREE,
!    otherwise return the VAR_DECL.  */
  
  static tree
! synthesize_tinfo_var (public_decl)
!      tree public_decl;
  {
!   tree var_init = NULL_TREE;
!   tree var_type = NULL_TREE;
!   int non_public = 0;
!   tree target_type = TREE_TYPE (DECL_NAME (public_decl));
!   my_friendly_assert (target_type != NULL_TREE, 20000120);
!   
!   /* Say we've dealt with it.  */
!   TREE_TYPE (DECL_NAME (public_decl)) = NULL_TREE;
!   
!   switch (TREE_CODE (target_type))
      {
      case POINTER_TYPE:
!       if (TYPE_PTRMEM_P (target_type))
!         {
!           var_type = ptm_desc_type_node;
!           var_init = ptm_initializer (var_type, target_type, &non_public);
!         }
        else
!         {
!           if (typeinfo_in_lib_p (target_type) && !doing_runtime)
!             /* 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:
!       var_type = enum_desc_type_node;
!       var_init = generic_initializer (var_type, target_type);
        break;
      case FUNCTION_TYPE:
!       var_type = func_desc_type_node;
!       var_init = generic_initializer (var_type, target_type);
        break;
      case ARRAY_TYPE:
!       var_type = ary_desc_type_node;
!       var_init = generic_initializer (var_type, target_type);
        break;
      case UNION_TYPE:
      case RECORD_TYPE:
!       if (TYPE_PTRMEMFUNC_P (target_type))
!         {
!           var_type = ptm_desc_type_node;
!           var_init = ptm_initializer (var_type, target_type, &non_public);
!         }
!       else 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))
!         {
!           var_type = class_desc_type_node;
!           var_init = class_initializer (var_type, target_type, NULL_TREE);
          }
        else
          {
!           /* if this has a single public non-virtual base, it's easier */
!           tree binfo = TYPE_BINFO (target_type);
            int nbases = BINFO_N_BASETYPES (binfo);
            tree base_binfos = BINFO_BASETYPES (binfo);
            tree base_inits = NULL_TREE;
-           int is_simple = nbases == 1;
            int ix;
            
            /* Generate the base information initializer.  */
--- 999,1061 ----
      }
  }
  
! /* Generate the initializer for the type info describing
!    TYPE. VAR_DESC is a . NON_PUBLIC_P is set non-zero, if the VAR_DECL
!    should not be exported from this object file.  This should only be
!    called at the end of translation, when we know that no further
!    types will be completed.  */
  
  static tree
! get_pseudo_ti_init (type, var_desc, non_public_p)
!      tree type;
!      tree var_desc;
!      int *non_public_p;
  {
!   my_friendly_assert (at_eof, 20021120);
!   switch (TREE_CODE (type))
      {
      case POINTER_TYPE:
!       if (TYPE_PTRMEM_P (type))
! 	return ptm_initializer (var_desc, type, non_public_p);
        else
! 	return ptr_initializer (var_desc, type, non_public_p);
        break;
      case ENUMERAL_TYPE:
!       return generic_initializer (var_desc, type);
        break;
      case FUNCTION_TYPE:
!       return generic_initializer (var_desc, type);
        break;
      case ARRAY_TYPE:
!       return generic_initializer (var_desc, type);
        break;
      case UNION_TYPE:
      case RECORD_TYPE:
!       if (TYPE_PTRMEMFUNC_P (type))
! 	return ptm_initializer (var_desc, type, non_public_p);
!       else if (var_desc == class_desc_type_node)
          {
! 	  if (!COMPLETE_TYPE_P (type))
! 	    /* Emit a non-public class_type_info.  */
! 	    *non_public_p = 1;
! 	  return class_initializer (var_desc, type, NULL_TREE);
          }
+       else if (var_desc == si_class_desc_type_node)
+ 	{
+           tree base_binfos = BINFO_BASETYPES (TYPE_BINFO (type));
+ 	  tree base_binfo = TREE_VEC_ELT (base_binfos, 0);
+ 	  tree tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo));
+ 	  tree base_inits = tree_cons (NULL_TREE, tinfo, NULL_TREE);
+ 	  
+ 	  return class_initializer (var_desc, type, base_inits);
+ 	}
        else
          {
! 	  int hint = class_hint_flags (type);
! 	  tree binfo = TYPE_BINFO (type);
            int nbases = BINFO_N_BASETYPES (binfo);
            tree base_binfos = BINFO_BASETYPES (binfo);
            tree base_inits = NULL_TREE;
            int ix;
            
            /* Generate the base information initializer.  */
*************** synthesize_tinfo_var (public_decl)
*** 1015,1042 ****
                
                if (TREE_PUBLIC (base_binfo))
                  flags |= 2;
!               tinfo = get_tinfo_decl (BINFO_TYPE (base_binfo));
!               tinfo = build_unary_op (ADDR_EXPR, tinfo, 0);
  	      if (TREE_VIA_VIRTUAL (base_binfo))
  		{
  		   /* We store the vtable offset at which the virtual
         		      base offset can be found.  */
! 		  offset = BINFO_VPTR_FIELD (binfo_for_vbase (BINFO_TYPE (base_binfo),
! 							      target_type));
  		  offset = convert (sizetype, offset);
  		  flags |= 1;
  		}
  	      else
  		offset = BINFO_OFFSET (base_binfo);
                
-               /* is it a single public inheritance? */
-               if (is_simple && flags == 2 && integer_zerop (offset))
-                 {
-                   base_inits = tree_cons (NULL_TREE, tinfo, NULL_TREE);
-                   break;
-                 }
-               is_simple = 0;
-               
                /* combine offset and flags into one field */
                offset = cp_build_binary_op (LSHIFT_EXPR, offset,
  					   build_int_2 (8, 0));
--- 1069,1087 ----
                
                if (TREE_PUBLIC (base_binfo))
                  flags |= 2;
!               tinfo = get_tinfo_ptr (BINFO_TYPE (base_binfo));
  	      if (TREE_VIA_VIRTUAL (base_binfo))
  		{
  		   /* We store the vtable offset at which the virtual
         		      base offset can be found.  */
! 		  offset = BINFO_VPTR_FIELD
! 		    (binfo_for_vbase (BINFO_TYPE (base_binfo), type));
  		  offset = convert (sizetype, offset);
  		  flags |= 1;
  		}
  	      else
  		offset = BINFO_OFFSET (base_binfo);
                
                /* combine offset and flags into one field */
                offset = cp_build_binary_op (LSHIFT_EXPR, offset,
  					   build_int_2 (8, 0));
*************** synthesize_tinfo_var (public_decl)
*** 1047,1134 ****
                base_init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, base_init);
                base_inits = tree_cons (NULL_TREE, base_init, base_inits);
              }
!           
!           if (is_simple)
!             var_type = si_class_desc_type_node;
!           else
!             {
!               int hint = class_hint_flags (target_type);
!               
!               base_inits = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, base_inits);
!               base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE);
!               /* Prepend the number of bases.  */
!               base_inits = tree_cons (NULL_TREE,
!                                       build_int_2 (nbases, 0), base_inits);
!               /* Prepend the hint flags. */
!               base_inits = tree_cons (NULL_TREE,
!                                       build_int_2 (hint, 0), base_inits);
!               var_type = get_vmi_pseudo_type_info (nbases);
!             }
!           var_init = class_initializer (var_type, target_type, base_inits);
          }
        break;
  
      default:
!       if (typeinfo_in_lib_p (target_type))
! 	{
! 	  if (!doing_runtime)
! 	    /* These are guaranteed to be in the runtime.  */
! 	    return NULL_TREE;
! 	  var_type = bltn_desc_type_node;
! 	  var_init = generic_initializer (var_type, target_type);
! 	  break;
! 	}
!       abort ();
      }
-   
-   return create_real_tinfo_var (target_type,
- 				public_decl, 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 (target_type, public_decl, type, init, non_public)
-      tree target_type;
-      tree public_decl;
-      tree type;
-      tree init;
-      int non_public;
- {
-   static int count = 0;
-   tree decl;
-   tree hidden_name;
-   char hidden[30];
-   tree name = DECL_ASSEMBLER_NAME (public_decl);
- 
-   /* We cannot give this the name NAME, as that already is globally
-      bound to the tinfo_decl we originally created for this type in
-      get_tinfo_decl. */
-   sprintf (hidden, "__ti_%d", 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;
-       if (flag_weak
- 	  || (DECL_COMDAT (public_decl) && !typeinfo_in_lib_p (target_type)))
- 	comdat_linkage (decl);
-     }
-   SET_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;
  }
  
  /* Generate the RECORD_TYPE containing the data layout of a type_info
--- 1092,1114 ----
                base_init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, base_init);
                base_inits = tree_cons (NULL_TREE, base_init, base_inits);
              }
! 	  base_inits = build (CONSTRUCTOR,
! 			      NULL_TREE, NULL_TREE, base_inits);
! 	  base_inits = tree_cons (NULL_TREE, base_inits, NULL_TREE);
! 	  /* Prepend the number of bases.  */
! 	  base_inits = tree_cons (NULL_TREE,
! 				  build_int_2 (nbases, 0), base_inits);
! 	  /* Prepend the hint flags. */
! 	  base_inits = tree_cons (NULL_TREE,
! 				  build_int_2 (hint, 0), base_inits);
! 
!           return class_initializer (var_desc, type, base_inits);
          }
        break;
  
      default:
!       return generic_initializer (var_desc, type);
      }
  }
  
  /* Generate the RECORD_TYPE containing the data layout of a type_info
*************** create_real_tinfo_var (target_type, publ
*** 1137,1143 ****
     type's vtable. We explicitly manage the vtable member, and name it for
     real type as used in the runtime. The RECORD type has a different name,
     to avoid collisions.  Return a TREE_LIST who's TINFO_PSEUDO_TYPE
!    is the generated type and TINFO_VTABLE_DECL is the vtable decl.
     
     REAL_NAME is the runtime's name of the type. Trailing arguments are
     additional FIELD_DECL's for the structure. The final argument must be
--- 1117,1126 ----
     type's vtable. We explicitly manage the vtable member, and name it for
     real type as used in the runtime. The RECORD type has a different name,
     to avoid collisions.  Return a TREE_LIST who's TINFO_PSEUDO_TYPE
!    is the generated type and TINFO_VTABLE_NAME is the name of the
!    vtable.  We have to delay generating the VAR_DECL of the vtable
!    until the end of the translation, when we'll have seen the library
!    definition, if there was one.
     
     REAL_NAME is the runtime's name of the type. Trailing arguments are
     additional FIELD_DECL's for the structure. The final argument must be
*************** create_real_tinfo_var (target_type, publ
*** 1146,1154 ****
  static tree
  create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
  {
!   tree real_type, pseudo_type;
    char *pseudo_name;
-   tree vtable_decl;
    int ix;
    tree fields[10];
    tree field_decl;
--- 1129,1136 ----
  static tree
  create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
  {
!   tree pseudo_type;
    char *pseudo_name;
    int ix;
    tree fields[10];
    tree field_decl;
*************** create_pseudo_type_info VPARAMS((const c
*** 1165,1192 ****
    if (ident)
      sprintf (pseudo_name + strlen (pseudo_name), "%d", ident);
    
-   /* Get the vtable decl. */
-   real_type = xref_tag (class_type_node, get_identifier (real_name), 1);
-   if (! TYPE_SIZE (real_type))
-     {
-       /* We never saw a definition of this type, so we need to tell the
- 	 compiler that this is an exported class, as indeed all of the
- 	 __*_type_info classes are.  */
-       SET_CLASSTYPE_INTERFACE_KNOWN (real_type);
-       CLASSTYPE_INTERFACE_ONLY (real_type) = 1;
-     }
- 
-   vtable_decl = get_vtable_decl (real_type, /*complete=*/1);
-   vtable_decl = build_unary_op (ADDR_EXPR, vtable_decl, 0);
- 
-   /* We need to point into the middle of the vtable.  */
-   vtable_decl
-     = build (PLUS_EXPR, TREE_TYPE (vtable_decl), vtable_decl,
- 	     size_binop (MULT_EXPR,
- 			 size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE),
- 			 TYPE_SIZE_UNIT (vtable_entry_type)));
-   TREE_CONSTANT (vtable_decl) = 1;
- 
    /* First field is the pseudo type_info base class. */
    fields[0] = build_decl (FIELD_DECL, NULL_TREE, ti_desc_type_node);
    
--- 1147,1152 ----
*************** create_pseudo_type_info VPARAMS((const c
*** 1200,1252 ****
    TYPE_HAS_CONSTRUCTOR (pseudo_type) = 1;
  
    result = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
!   TINFO_VTABLE_DECL (result) = vtable_decl;
!   TINFO_PSEUDO_TYPE (result) = pseudo_type;
    
    VA_CLOSE (ap);
    return result;
  }
  
! /* Return a descriptor for a vmi type with NUM_BASES bases.  */
  
  static tree
! get_vmi_pseudo_type_info (num_bases)
!      int num_bases;
  {
!   tree desc;
!   tree array_domain, base_array;
!   
!   if (TREE_VEC_LENGTH (vmi_class_desc_type_node) <= num_bases)
      {
!       int ix;
!       tree extend = make_tree_vec (num_bases + 5);
!       
!       for (ix = TREE_VEC_LENGTH (vmi_class_desc_type_node); ix--;)
!         TREE_VEC_ELT (extend, ix) = TREE_VEC_ELT (vmi_class_desc_type_node, ix);
!       vmi_class_desc_type_node = extend;
!     }
!   desc = TREE_VEC_ELT (vmi_class_desc_type_node, num_bases);
!   
!   if (desc)
!     return desc;
!   
!   /* Add number of bases and trailing array of base_class_type_info.  */
!   array_domain = build_index_type (size_int (num_bases));
!   base_array = build_array_type (base_desc_type_node, array_domain);
! 
!   push_nested_namespace (abi_node);
! 
!   desc = create_pseudo_type_info
!             ("__vmi_class_type_info", num_bases,
!              build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
!              build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
!              build_decl (FIELD_DECL, NULL_TREE, base_array),
!              NULL);
! 
!   pop_nested_namespace (abi_node);
  
!   TREE_VEC_ELT (vmi_class_desc_type_node, num_bases) = desc;
!   return desc;
  }
  
  /* Make sure the required builtin types exist for generating the type_info
--- 1160,1255 ----
    TYPE_HAS_CONSTRUCTOR (pseudo_type) = 1;
  
    result = tree_cons (NULL_TREE, NULL_TREE, NULL_TREE);
!   TINFO_REAL_NAME (result) = get_identifier (real_name);
!   TINFO_PSEUDO_TYPE (result) =
!     cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST);
    
    VA_CLOSE (ap);
    return result;
  }
  
! /* Return a pseudo type info type node used to describe TYPE.  TYPE
!    must be a complete type (or cv void), except at the end of the
!    translation unit.  */
  
  static tree
! get_pseudo_ti_desc (type)
!      tree type;
  {
!   switch (TREE_CODE (type))
      {
!     case POINTER_TYPE:
!       return TYPE_PTRMEM_P (type) ? ptm_desc_type_node : ptr_desc_type_node;
!     case ENUMERAL_TYPE:
!       return enum_desc_type_node;
!     case FUNCTION_TYPE:
!       return func_desc_type_node;
!     case ARRAY_TYPE:
!       return ary_desc_type_node;
!     case UNION_TYPE:
!     case RECORD_TYPE:
!       if (TYPE_PTRMEMFUNC_P (type))
! 	return ptm_desc_type_node;
!       else if (!COMPLETE_TYPE_P (type))
! 	{
! 	  my_friendly_assert (at_eof, 20020609);
! 	  return class_desc_type_node;
! 	}
!       else if (!CLASSTYPE_N_BASECLASSES (type))
! 	return class_desc_type_node;
!       else
! 	{
! 	  tree base_binfo =
! 	    TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), 0);
! 	  int num_bases = BINFO_N_BASETYPES (TYPE_BINFO (type));
! 	  
! 	  if (num_bases == 1
! 	      && TREE_PUBLIC (base_binfo)
! 	      && !TREE_VIA_VIRTUAL (base_binfo)
! 	      && integer_zerop (BINFO_OFFSET (base_binfo)))
! 	    /* single non-virtual public. */
! 	    return si_class_desc_type_node;
! 	  else
! 	    {
! 	      tree var_desc;
! 	      tree array_domain, base_array;
! 	      
! 	      if (TREE_VEC_LENGTH (vmi_class_desc_type_node) <= num_bases)
! 		{
! 		  int ix;
! 		  tree extend = make_tree_vec (num_bases + 5);
! 		  
! 		  for (ix = TREE_VEC_LENGTH (vmi_class_desc_type_node); ix--;)
! 		    TREE_VEC_ELT (extend, ix)
! 		      = TREE_VEC_ELT (vmi_class_desc_type_node, ix);
! 		  vmi_class_desc_type_node = extend;
! 		}
! 	      var_desc = TREE_VEC_ELT (vmi_class_desc_type_node, num_bases);
! 	      if (var_desc)
! 		return var_desc;
!   
! 	      /* Add number of bases and trailing array of
! 		 base_class_type_info.  */
! 	      array_domain = build_index_type (size_int (num_bases));
! 	      base_array =
! 		build_array_type (base_desc_type_node, array_domain);
! 
! 	      push_nested_namespace (abi_node);
! 	      var_desc = create_pseudo_type_info
! 		("__vmi_class_type_info", num_bases,
! 		 build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
! 		 build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
! 		 build_decl (FIELD_DECL, NULL_TREE, base_array),
! 		 NULL);
! 	      pop_nested_namespace (abi_node);
  
! 	      TREE_VEC_ELT (vmi_class_desc_type_node, num_bases) = var_desc;
! 	      return var_desc;
! 	    }
! 	}
!     default:
!       return bltn_desc_type_node;
!     }
  }
  
  /* Make sure the required builtin types exist for generating the type_info
*************** get_vmi_pseudo_type_info (num_bases)
*** 1255,1269 ****
  static void
  create_tinfo_types ()
  {
!   tree ptr_type_info;
!   
!   if (bltn_desc_type_node)
!     return;
!   push_nested_namespace (abi_node);
  
!   ptr_type_info = build_pointer_type
!                     (build_qualified_type
!                       (type_info_type_node, TYPE_QUAL_CONST));
    
    /* Create the internal type_info structure. This is used as a base for
       the other structures.  */
--- 1258,1266 ----
  static void
  create_tinfo_types ()
  {
!   my_friendly_assert (!ti_desc_type_node, 20020609);
  
!   push_nested_namespace (abi_node);
    
    /* Create the internal type_info structure. This is used as a base for
       the other structures.  */
*************** create_tinfo_types ()
*** 1303,1309 ****
       This is really a descendant of __class_type_info.  */
    si_class_desc_type_node = create_pseudo_type_info
             ("__si_class_type_info", 0,
!             build_decl (FIELD_DECL, NULL_TREE, ptr_type_info),
              NULL);
    
    /* Base class internal helper. Pointer to base type, offset to base,
--- 1300,1306 ----
       This is really a descendant of __class_type_info.  */
    si_class_desc_type_node = create_pseudo_type_info
             ("__si_class_type_info", 0,
!             build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type),
              NULL);
    
    /* Base class internal helper. Pointer to base type, offset to base,
*************** create_tinfo_types ()
*** 1311,1317 ****
    {
      tree fields[2];
      
!     fields[0] = build_decl (FIELD_DECL, NULL_TREE, ptr_type_info);
      fields[1] = build_decl (FIELD_DECL, NULL_TREE, integer_types[itk_long]);
      base_desc_type_node = make_aggr_type (RECORD_TYPE);
      finish_builtin_type (base_desc_type_node, "__base_class_type_info_pseudo",
--- 1308,1314 ----
    {
      tree fields[2];
      
!     fields[0] = build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type);
      fields[1] = build_decl (FIELD_DECL, NULL_TREE, integer_types[itk_long]);
      base_desc_type_node = make_aggr_type (RECORD_TYPE);
      finish_builtin_type (base_desc_type_node, "__base_class_type_info_pseudo",
*************** create_tinfo_types ()
*** 1328,1334 ****
    ptr_desc_type_node = create_pseudo_type_info
        ("__pointer_type_info", 0,
         build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
!        build_decl (FIELD_DECL, NULL_TREE, ptr_type_info),
         NULL);
  
    /* Pointer to member data type_info.  Add qualifications flags,
--- 1325,1331 ----
    ptr_desc_type_node = create_pseudo_type_info
        ("__pointer_type_info", 0,
         build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
!        build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type),
         NULL);
  
    /* Pointer to member data type_info.  Add qualifications flags,
*************** create_tinfo_types ()
*** 1337,1344 ****
    ptm_desc_type_node = create_pseudo_type_info
         ("__pointer_to_member_type_info", 0,
          build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
!         build_decl (FIELD_DECL, NULL_TREE, ptr_type_info),
!         build_decl (FIELD_DECL, NULL_TREE, ptr_type_info),
          NULL);
  
    pop_nested_namespace (abi_node);
--- 1334,1341 ----
    ptm_desc_type_node = create_pseudo_type_info
         ("__pointer_to_member_type_info", 0,
          build_decl (FIELD_DECL, NULL_TREE, integer_type_node),
!         build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type),
!         build_decl (FIELD_DECL, NULL_TREE, type_info_ptr_type),
          NULL);
  
    pop_nested_namespace (abi_node);
*************** emit_support_tinfos ()
*** 1405,1476 ****
     definition emitted for it.  */
  
  int
! tinfo_decl_p (t, data)
       tree t;
       void *data ATTRIBUTE_UNUSED;
  {
!   return TREE_CODE (t) == VAR_DECL
!          && IDENTIFIER_GLOBAL_VALUE (DECL_NAME (t)) == (t)
!          && TREE_TYPE (t) == tinfo_decl_type
!          && TREE_TYPE (DECL_NAME (t));
  }
  
! /* Emit a suitable type_info definition for the type_info decl pointed to by
!    DECL_PTR. We emit a completely new variable, of the correct type for the
!    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
!    
!       struct B : A {
!         ...
!       };
!    
!       extern const A tinfo_var;
!    
!       const B tinfo_var = {...};
!    
!    which is not permitted. Also, we've not necessarily seen the definition of B.
!    So we do something like the following,
!    
!       extern const A tinfo_var;
!    
!       struct pseudo_A {
!         const void *vtable_ptr;
!         const char *name;
!       };
!       struct pseudo_B {
!         pseudo_A base;
!         ...
!       };
!       
!       const pseudo_B proxy_tinfo_var attribute((assembler_name="tinfo_var")) =
!       {
!         {&B::vtable, "..."},
!         ...
!       };
!    
!    pseudo_A and pseudo_B must be layout equivalent to the real definitions in
!    the runtime.  */
  
  int
  emit_tinfo_decl (decl_ptr, data)
       tree *decl_ptr;
       void *data ATTRIBUTE_UNUSED;
  {
!   tree tinfo_decl = *decl_ptr;
!   tree decl;
    
!   my_friendly_assert (TREE_TYPE (tinfo_decl) == tinfo_decl_type, 20000121);
  
!   import_export_decl (tinfo_decl);
!   if (DECL_REALLY_EXTERN (tinfo_decl) || !DECL_NEEDED_P (tinfo_decl))
      return 0;
  
!   create_tinfo_types ();
!   decl = synthesize_tinfo_var (tinfo_decl);
    
!   return decl != 0;
  }
--- 1402,1460 ----
     definition emitted for it.  */
  
  int
! unemitted_tinfo_decl_p (t, data)
       tree t;
       void *data ATTRIBUTE_UNUSED;
  {
!   if (/* It's a var decl */
!       TREE_CODE (t) == VAR_DECL
!       /* whos name points back to itself */
!       && IDENTIFIER_GLOBAL_VALUE (DECL_NAME (t)) == t
!       /* whos name's type is non-null */
!       && TREE_TYPE (DECL_NAME (t))
!       /* and whos type is a struct */
!       && TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
!       /* with a first field of our pseudo type info */
!       && TREE_TYPE (TYPE_FIELDS (TREE_TYPE (t))) == ti_desc_type_node)
!     return 1;
!   return 0;
  }
  
! /* Finish a type info decl. DECL_PTR is a pointer to an unemitted
!    tinfo decl.  Determine whether it needs emitting, and if so
!    generate the initializer.  */
  
  int
  emit_tinfo_decl (decl_ptr, data)
       tree *decl_ptr;
       void *data ATTRIBUTE_UNUSED;
  {
!   tree decl = *decl_ptr;
!   tree type = TREE_TYPE (DECL_NAME (decl));
!   int non_public;
!   tree var_desc, var_init;
    
!   import_export_tinfo (decl, type);
!   if (DECL_REALLY_EXTERN (decl) || !DECL_NEEDED_P (decl))
!     return 0;
  
!   if (!doing_runtime && typeinfo_in_lib_p (type))
      return 0;
  
!   non_public = 0;
!   var_desc = get_pseudo_ti_desc (type);
!   var_init = get_pseudo_ti_init (type, var_desc, &non_public);
!   DECL_EXTERNAL (decl) = 0;
!   TREE_PUBLIC (decl) = !non_public;
!   if (!non_public
!       && (flag_weak || (DECL_COMDAT (decl) && !typeinfo_in_lib_p (type))))
!     comdat_linkage (decl);
    
!   DECL_INITIAL (decl) = var_init;
!   cp_finish_decl (decl, var_init, NULL_TREE, 0);
!   
!   /* Say we've dealt with it.  */
!   TREE_TYPE (DECL_NAME (decl)) = NULL_TREE;
! 
!   return 1;
  }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-07-22 10:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-07-22  3:26 Fwd: [C++ PATCH]: Rework typeinfo objects Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).