Make rtti lazier
authorNathan Sidwell <nathan@acm.org>
Fri, 16 Jun 2017 14:16:20 +0000 (14:16 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Fri, 16 Jun 2017 14:16:20 +0000 (14:16 +0000)
Make rtti lazier
* rtti.c (enum tinfo_kind): Add TK_DERIVED_TYPES,
TK_VMI_CLASS_TYPES, TK_MAX.  Delete TK_FIXED.
(tinfo_names): New.
(typeid_ok_p): Add quotes to error messages.  Use get_tinfo_desc.
(get_tinfo_decl): Use get_tinfo_desc.
(get_pseudo_ti_init): Likewise. Adjust VMI construction.
(create_pseudo_type_info): Delete.
(get_pseudo_ti_index): Just determine the index.
(get_tinfo_desc): New.  Create all types lazily.
(create_tinfo_types): Just allocate the descriptor array.
(emit_support_tinfos): Use non-inserting type lookup.  Set builtin
location.

From-SVN: r249258

gcc/cp/ChangeLog
gcc/cp/rtti.c

index ed307b6278e0426257829b35f3cbb971ad36a440..7bf7ed1865e333d25db5c92037a56d75b5ea3802 100644 (file)
@@ -1,3 +1,19 @@
+2017-06-16  Nathan Sidwell  <nathan@acm.org>
+
+       Make rtti lazier
+       * rtti.c (enum tinfo_kind): Add TK_DERIVED_TYPES,
+       TK_VMI_CLASS_TYPES, TK_MAX.  Delete TK_FIXED.
+       (tinfo_names): New.
+       (typeid_ok_p): Add quotes to error messages.  Use get_tinfo_desc.
+       (get_tinfo_decl): Use get_tinfo_desc.
+       (get_pseudo_ti_init): Likewise. Adjust VMI construction.
+       (create_pseudo_type_info): Delete.
+       (get_pseudo_ti_index): Just determine the index.
+       (get_tinfo_desc): New.  Create all types lazily.
+       (create_tinfo_types): Just allocate the descriptor array.
+       (emit_support_tinfos): Use non-inserting type lookup.  Set builtin
+       location.
+
 2017-06-15  Martin Sebor  <msebor@redhat.com>
 
        PR c++/80560
index 89d18914adfe6d87d80225ce250fab3aec483b70..6d0316f9ee3b2670786ea9bdb2fcfd85996c68d1 100644 (file)
@@ -75,7 +75,8 @@ enum tinfo_kind
 {
   TK_TYPE_INFO_TYPE,    /* abi::__type_info_pseudo */
   TK_BASE_TYPE,                /* abi::__base_class_type_info */
-  TK_BUILTIN_TYPE,     /* abi::__fundamental_type_info */
+  TK_DERIVED_TYPES,    /* Start of types derived from abi::__type_info  */
+  TK_BUILTIN_TYPE = TK_DERIVED_TYPES,  /* abi::__fundamental_type_info */
   TK_ARRAY_TYPE,       /* abi::__array_type_info */
   TK_FUNCTION_TYPE,    /* abi::__function_type_info */
   TK_ENUMERAL_TYPE,    /* abi::__enum_type_info */
@@ -83,8 +84,26 @@ enum tinfo_kind
   TK_POINTER_MEMBER_TYPE, /* abi::__pointer_to_member_type_info */
   TK_CLASS_TYPE,       /* abi::__class_type_info */
   TK_SI_CLASS_TYPE,    /* abi::__si_class_type_info */
-  TK_FIXED             /* end of fixed descriptors. */
-  /* ...                  abi::__vmi_type_info<I> */
+  TK_VMI_CLASS_TYPES,  /* abi::__vmi_class_type_info<int> */
+  TK_MAX
+};
+
+/* Names of the tinfo types.  Must be same order as TK enumeration
+   above.  */
+
+static const char *const tinfo_names[TK_MAX] =
+{
+  "__type_info",
+  "__base_class_type_info",
+  "__fundamental_type_info",
+  "__array_type_info",
+  "__function_type_info",
+  "__enum_type_info",
+  "__pointer_type_info",
+  "__pointer_to_member_type_info",
+  "__class_type_info",
+  "__si_class_type_info",
+  "__vmi_class_type_info"
 };
 
 /* Helper macro to get maximum scalar-width of pointer or of the 'long'-type.
@@ -115,9 +134,9 @@ static tree generic_initializer (tinfo_s *, tree);
 static tree ptr_initializer (tinfo_s *, tree);
 static tree ptm_initializer (tinfo_s *, tree);
 static tree class_initializer (tinfo_s *, tree, unsigned, ...);
-static void create_pseudo_type_info (int, const char *, ...);
 static tree get_pseudo_ti_init (tree, unsigned);
 static unsigned get_pseudo_ti_index (tree);
+static tinfo_s *get_tinfo_desc (unsigned);
 static void create_tinfo_types (void);
 static bool typeinfo_in_lib_p (tree);
 
@@ -289,30 +308,27 @@ get_tinfo_decl_dynamic (tree exp, tsubst_flags_t complain)
 static bool
 typeid_ok_p (void)
 {
-  tree pseudo_type_info, type_info_type;
-
   if (! flag_rtti)
     {
-      error ("cannot use typeid with -fno-rtti");
+      error ("cannot use %<typeid%> with -fno-rtti");
       return false;
     }
 
   if (!COMPLETE_TYPE_P (const_type_info_type_node))
     {
-      error ("must #include <typeinfo> before using typeid");
+      error ("must %<#include <typeinfo>%> before using %<typeid%>");
       return false;
     }
 
-  pseudo_type_info = (*tinfo_descs)[TK_TYPE_INFO_TYPE].type;
-  type_info_type = TYPE_MAIN_VARIANT (const_type_info_type_node);
+  tree pseudo = TYPE_MAIN_VARIANT (get_tinfo_desc (TK_TYPE_INFO_TYPE)->type);
+  tree real = TYPE_MAIN_VARIANT (const_type_info_type_node);
 
   /* Make sure abi::__type_info_pseudo has the same alias set
      as std::type_info.  */
-  if (! TYPE_ALIAS_SET_KNOWN_P (pseudo_type_info))
-    TYPE_ALIAS_SET (pseudo_type_info) = get_alias_set (type_info_type);
+  if (! TYPE_ALIAS_SET_KNOWN_P (pseudo))
+    TYPE_ALIAS_SET (pseudo) = get_alias_set (real);
   else
-    gcc_assert (TYPE_ALIAS_SET (pseudo_type_info)
-               == get_alias_set (type_info_type));
+    gcc_assert (TYPE_ALIAS_SET (pseudo) == get_alias_set (real));
 
   return true;
 }
@@ -428,8 +444,8 @@ get_tinfo_decl (tree type)
   if (!d)
     {
       int ix = get_pseudo_ti_index (type);
-      tinfo_s *ti = &(*tinfo_descs)[ix];
-
+      const tinfo_s *ti = get_tinfo_desc (ix);
+      
       d = build_lang_decl (VAR_DECL, name, ti->type);
       SET_DECL_ASSEMBLER_NAME (d, name);
       /* Remember the type it is for.  */
@@ -1105,7 +1121,7 @@ typeinfo_in_lib_p (tree type)
 static tree
 get_pseudo_ti_init (tree type, unsigned tk_index)
 {
-  tinfo_s *ti = &(*tinfo_descs)[tk_index];
+  tinfo_s *ti = get_tinfo_desc (tk_index);
 
   gcc_assert (at_eof);
   switch (tk_index)
@@ -1140,22 +1156,18 @@ get_pseudo_ti_init (tree type, unsigned tk_index)
        int hint = ((CLASSTYPE_REPEATED_BASE_P (type) << 0)
                    | (CLASSTYPE_DIAMOND_SHAPED_P (type) << 1));
        tree binfo = TYPE_BINFO (type);
-       int nbases = BINFO_N_BASE_BINFOS (binfo);
+       unsigned nbases = BINFO_N_BASE_BINFOS (binfo);
        vec<tree, va_gc> *base_accesses = BINFO_BASE_ACCESSES (binfo);
        tree offset_type = LONGPTR_T;
-       tree base_inits = NULL_TREE;
-       int ix;
        vec<constructor_elt, va_gc> *init_vec = NULL;
-       constructor_elt *e;
 
-       gcc_assert (tk_index >= TK_FIXED);
+       gcc_assert (tk_index - TK_VMI_CLASS_TYPES + 1 == nbases);
 
        vec_safe_grow (init_vec, nbases);
        /* Generate the base information initializer.  */
-       for (ix = nbases; ix--;)
+       for (unsigned ix = nbases; ix--;)
          {
            tree base_binfo = BINFO_BASE_BINFO (binfo, ix);
-           tree base_init;
            int flags = 0;
            tree tinfo;
            tree offset;
@@ -1185,12 +1197,12 @@ get_pseudo_ti_init (tree type, unsigned tk_index)
            vec_alloc (v, 2);
            CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, tinfo);
            CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, offset);
-           base_init = build_constructor (init_list_type_node, v);
-           e = &(*init_vec)[ix];
+           tree base_init = build_constructor (init_list_type_node, v);
+           constructor_elt *e = &(*init_vec)[ix];
            e->index = NULL_TREE;
            e->value = base_init;
          }
-       base_inits = build_constructor (init_list_type_node, init_vec);
+       tree base_inits = build_constructor (init_list_type_node, init_vec);
 
        /* get_tinfo_ptr might have reallocated the tinfo_descs vector.  */
        ti = &(*tinfo_descs)[tk_index];
@@ -1202,69 +1214,6 @@ get_pseudo_ti_init (tree type, unsigned tk_index)
     }
 }
 
-/* Generate the RECORD_TYPE containing the data layout of a type_info
-   derivative as used by the runtime. This layout must be consistent with
-   that defined in the runtime support. Also generate the VAR_DECL for the
-   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
-   NULL.  */
-
-static void
-create_pseudo_type_info (int tk, const char *real_name, ...)
-{
-  tinfo_s *ti;
-  tree pseudo_type;
-  char *pseudo_name;
-  tree fields;
-  tree field_decl;
-  va_list ap;
-
-  va_start (ap, real_name);
-
-  /* Generate the pseudo type name.  */
-  pseudo_name = (char *) alloca (strlen (real_name) + 30);
-  strcpy (pseudo_name, real_name);
-  strcat (pseudo_name, "_pseudo");
-  if (tk >= TK_FIXED)
-    sprintf (pseudo_name + strlen (pseudo_name), "%d", tk - TK_FIXED);
-
-  /* First field is the pseudo type_info base class.  */
-  fields = build_decl (input_location,
-                      FIELD_DECL, NULL_TREE,
-                      (*tinfo_descs)[TK_TYPE_INFO_TYPE].type);
-
-  /* Now add the derived fields.  */
-  while ((field_decl = va_arg (ap, tree)))
-    {
-      DECL_CHAIN (field_decl) = fields;
-      fields = field_decl;
-    }
-
-  /* Create the pseudo type.  */
-  pseudo_type = make_class_type (RECORD_TYPE);
-  finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE);
-  CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;
-
-  ti = &(*tinfo_descs)[tk];
-  ti->type = cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST);
-  ti->name = get_identifier (real_name);
-  ti->vtable = NULL_TREE;
-
-  /* Pretend this is public so determine_visibility doesn't give vtables
-     internal linkage.  */
-  TREE_PUBLIC (TYPE_MAIN_DECL (ti->type)) = 1;
-
-  va_end (ap);
-}
-
 /* Return the index of 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.  */
@@ -1299,23 +1248,16 @@ get_pseudo_ti_index (tree type)
     case UNION_TYPE:
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_P (type))
-       {
-         ix = TK_POINTER_MEMBER_TYPE;
-         break;
-       }
+       ix = TK_POINTER_MEMBER_TYPE;
       else if (!COMPLETE_TYPE_P (type))
        {
          if (!at_eof)
            cxx_incomplete_type_error (NULL_TREE, type);
          ix = TK_CLASS_TYPE;
-         break;
        }
       else if (!TYPE_BINFO (type)
               || !BINFO_N_BASE_BINFOS (TYPE_BINFO (type)))
-       {
-         ix = TK_CLASS_TYPE;
-         break;
-       }
+       ix = TK_CLASS_TYPE;
       else
        {
          tree binfo = TYPE_BINFO (type);
@@ -1327,49 +1269,13 @@ get_pseudo_ti_index (tree type)
              && (*base_accesses)[0] == access_public_node
              && !BINFO_VIRTUAL_P (base_binfo)
              && integer_zerop (BINFO_OFFSET (base_binfo)))
-           {
-             /* single non-virtual public.  */
-             ix = TK_SI_CLASS_TYPE;
-             break;
-           }
+           /* single non-virtual public.  */
+           ix = TK_SI_CLASS_TYPE;
          else
-           {
-             tinfo_s *ti;
-             tree array_domain, base_array;
-
-             ix = TK_FIXED + num_bases;
-             if (vec_safe_length (tinfo_descs) <= ix)
-               {
-                 /* too short, extend.  */
-                 unsigned len = vec_safe_length (tinfo_descs);
-
-                 vec_safe_grow (tinfo_descs, ix + 1);
-                 while (tinfo_descs->iterate (len++, &ti))
-                   ti->type = ti->vtable = ti->name = NULL_TREE;
-               }
-             else if ((*tinfo_descs)[ix].type)
-               /* already created.  */
-               break;
-
-             /* Create the array of __base_class_type_info entries.  */
-             array_domain = build_index_type (size_int (num_bases - 1));
-             base_array = build_array_type ((*tinfo_descs)[TK_BASE_TYPE].type,
-                                            array_domain);
-
-             push_abi_namespace ();
-             create_pseudo_type_info
-               (ix, "__vmi_class_type_info",
-                build_decl (input_location,
-                            FIELD_DECL, NULL_TREE, integer_type_node),
-                build_decl (input_location,
-                            FIELD_DECL, NULL_TREE, integer_type_node),
-                build_decl (input_location,
-                            FIELD_DECL, NULL_TREE, base_array),
-                NULL);
-             pop_abi_namespace ();
-             break;
-           }
+           ix = TK_VMI_CLASS_TYPES + num_bases - 1;
        }
+      break;
+
     default:
       ix = TK_BUILTIN_TYPE;
       break;
@@ -1377,107 +1283,202 @@ get_pseudo_ti_index (tree type)
   return ix;
 }
 
-/* Make sure the required builtin types exist for generating the type_info
-   variable definitions.  */
+/* Return pointer to tinfo descriptor.  Possibly creating the tinfo
+   descriptor in the first place.  */
 
-static void
-create_tinfo_types (void)
+static tinfo_s *
+get_tinfo_desc (unsigned ix)
 {
-  tinfo_s *ti;
+  unsigned len = tinfo_descs->length ();
 
-  gcc_assert (!tinfo_descs);
+  if (len <= ix)
+    {
+      /* too short, extend.  */
+      len = ix + 1 - len;
+      vec_safe_reserve (tinfo_descs, len);
+      tinfo_s elt;
+      elt.type = elt.vtable = elt.name = NULL_TREE;
+      while (len--)
+       tinfo_descs->quick_push (elt);
+    }
 
-  vec_safe_grow (tinfo_descs, TK_FIXED);
+  tinfo_s *res = &(*tinfo_descs)[ix];
 
-  push_abi_namespace ();
+  if (res->type)
+    return res;
 
-  /* Create the internal type_info structure. This is used as a base for
-     the other structures.  */
-  {
-    tree field, fields;
-
-    field = build_decl (BUILTINS_LOCATION,
-                       FIELD_DECL, NULL_TREE, const_ptr_type_node);
-    fields = field;
-
-    field = build_decl (BUILTINS_LOCATION,
-                       FIELD_DECL, NULL_TREE, const_string_type_node);
-    DECL_CHAIN (field) = fields;
-    fields = field;
-
-    ti = &(*tinfo_descs)[TK_TYPE_INFO_TYPE];
-    ti->type = make_class_type (RECORD_TYPE);
-    ti->vtable = NULL_TREE;
-    ti->name = NULL_TREE;
-    finish_builtin_struct (ti->type, "__type_info_pseudo",
-                          fields, NULL_TREE);
-  }
+  /* Ok, we have to create it.  This layout must be consistent with
+     that defined in the runtime support.  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.  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.  */
 
-  /* Fundamental type_info */
-  create_pseudo_type_info (TK_BUILTIN_TYPE, "__fundamental_type_info", NULL);
+  /* Fields to add, chained in reverse order.  */
+  tree fields = NULL_TREE;
 
-  /* Array, function and enum type_info. No additional fields.  */
-  create_pseudo_type_info (TK_ARRAY_TYPE, "__array_type_info", NULL);
-  create_pseudo_type_info (TK_FUNCTION_TYPE, "__function_type_info", NULL);
-  create_pseudo_type_info (TK_ENUMERAL_TYPE, "__enum_type_info", NULL);
+  if (ix >= TK_DERIVED_TYPES)
+    {
+      /* First field is the pseudo type_info base class.  */
+      tree fld_base = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
+                                 get_tinfo_desc (TK_TYPE_INFO_TYPE)->type);
 
-  /* Class type_info.  No additional fields.  */
-  create_pseudo_type_info (TK_CLASS_TYPE, "__class_type_info", NULL);
+      DECL_CHAIN (fld_base) = fields;
+      fields = fld_base;
+    }
 
-  /* Single public non-virtual base class. Add pointer to base class.
-     This is really a descendant of __class_type_info.  */
-  create_pseudo_type_info (TK_SI_CLASS_TYPE, "__si_class_type_info",
-           build_decl (BUILTINS_LOCATION,
-                       FIELD_DECL, NULL_TREE, type_info_ptr_type),
-           NULL);
+  switch (ix)
+    {
+    case TK_TYPE_INFO_TYPE:
+      {
+       tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+                                  NULL_TREE, const_ptr_type_node);
+       fields = fld_ptr;
+
+       tree fld_str = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+                                  NULL_TREE, const_string_type_node);
+       DECL_CHAIN (fld_str) = fields;
+       fields = fld_str;
+       break;
+      }
 
-  /* Base class internal helper. Pointer to base type, offset to base,
-     flags.  */
-  {
-    tree field, fields;
+    case TK_BASE_TYPE:
+      {
+       /* Base class internal helper. Pointer to base type, offset to
+          base, flags.  */
+       tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+                                  NULL_TREE, type_info_ptr_type);
+       DECL_CHAIN (fld_ptr) = fields;
+       fields = fld_ptr;
+
+       tree fld_flag = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+                                   NULL_TREE, LONGPTR_T);
+       DECL_CHAIN (fld_flag) = fields;
+       fields = fld_flag;
+       break;
+      }
 
-    field = build_decl (BUILTINS_LOCATION,
-                       FIELD_DECL, NULL_TREE, type_info_ptr_type);
-    fields = field;
+    case TK_BUILTIN_TYPE:
+      /* Fundamental type_info */
+      break;
 
-    field = build_decl (BUILTINS_LOCATION,
-                       FIELD_DECL, NULL_TREE, LONGPTR_T);
-    DECL_CHAIN (field) = fields;
-    fields = field;
+    case TK_ARRAY_TYPE:
+      break;
 
-    ti = &(*tinfo_descs)[TK_BASE_TYPE];
+    case TK_FUNCTION_TYPE:
+      break;
 
-    ti->type = make_class_type (RECORD_TYPE);
-    ti->vtable = NULL_TREE;
-    ti->name = NULL_TREE;
-    finish_builtin_struct (ti->type, "__base_class_type_info_pseudo",
-                          fields, NULL_TREE);
-  }
+    case TK_ENUMERAL_TYPE:
+      break;
+
+    case TK_POINTER_TYPE:
+    case TK_POINTER_MEMBER_TYPE:
+      {
+       /* Pointer type_info. Adds two fields, qualification mask and
+          pointer to the pointed to type.  This is really a
+          descendant of __pbase_type_info.  */
+       tree fld_mask = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+                                   NULL_TREE, integer_type_node);
+       DECL_CHAIN (fld_mask) = fields;
+       fields = fld_mask;
+
+       tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+                                  NULL_TREE, type_info_ptr_type);
+       DECL_CHAIN (fld_ptr) = fields;
+       fields = fld_ptr;
+
+       if (ix == TK_POINTER_MEMBER_TYPE)
+         {
+           /* Add a pointer to the class too.  */
+           tree fld_cls = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+                                  NULL_TREE, type_info_ptr_type);
+           DECL_CHAIN (fld_cls) = fields;
+           fields = fld_cls;
+         }
+       break;
+      }
+
+    case TK_CLASS_TYPE:
+      /* Class type_info.  No additional fields.  */
+      break;
+
+    case TK_SI_CLASS_TYPE:
+      {
+       /* Single public non-virtual base class. Add pointer to base
+          class.  This is really a descendant of
+          __class_type_info.  */
+       tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+                                  NULL_TREE, type_info_ptr_type);
+       DECL_CHAIN (fld_ptr) = fields;
+       fields = fld_ptr;
+       break;
+      }
+
+    default: /* Multiple inheritance.  */
+      {
+       unsigned num_bases = ix - TK_VMI_CLASS_TYPES + 1;
+
+       tree fld_flg = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+                                  NULL_TREE, integer_type_node);
+       DECL_CHAIN (fld_flg) = fields;
+       fields = fld_flg;
+       
+       tree fld_cnt = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+                                  NULL_TREE, integer_type_node);
+       DECL_CHAIN (fld_cnt) = fields;
+       fields = fld_cnt;
+
+       /* Create the array of __base_class_type_info entries.  */
+       tree domain = build_index_type (size_int (num_bases - 1));
+       tree array = build_array_type (get_tinfo_desc (TK_BASE_TYPE)->type,
+                                      domain);
+       tree fld_ary = build_decl (BUILTINS_LOCATION, FIELD_DECL,
+                                  NULL_TREE, array);
+       DECL_CHAIN (fld_ary) = fields;
+       fields = fld_ary;
+       break;
+      }
+    }
+
+  push_abi_namespace ();
+
+  /* Generate the pseudo type name.  */
+  const char *real_name = tinfo_names[ix < TK_VMI_CLASS_TYPES
+                                     ? ix : unsigned (TK_VMI_CLASS_TYPES)];
+  size_t name_len = strlen (real_name);
+  char *pseudo_name = (char *) alloca (name_len + 30);
+  memcpy (pseudo_name, real_name, name_len);
+  /* Those >= TK_VMI_CLASS_TYPES need a discriminator, may as well
+     apply it to all.  See get_peudo_tinfo_index where we make use of
+     this.  */
+  sprintf (pseudo_name + name_len, "_pseudo_%d", ix);
 
-  /* Pointer type_info. Adds two fields, qualification mask
-     and pointer to the pointed to type.  This is really a descendant of
-     __pbase_type_info.  */
-  create_pseudo_type_info (TK_POINTER_TYPE, "__pointer_type_info",
-       build_decl (BUILTINS_LOCATION, 
-                  FIELD_DECL, NULL_TREE, integer_type_node),
-       build_decl (BUILTINS_LOCATION,
-                  FIELD_DECL, NULL_TREE, type_info_ptr_type),
-       NULL);
-
-  /* Pointer to member data type_info.  Add qualifications flags,
-     pointer to the member's type info and pointer to the class.
-     This is really a descendant of __pbase_type_info.  */
-  create_pseudo_type_info (TK_POINTER_MEMBER_TYPE,
-       "__pointer_to_member_type_info",
-       build_decl (BUILTINS_LOCATION,
-                   FIELD_DECL, NULL_TREE, integer_type_node),
-       build_decl (BUILTINS_LOCATION,
-                   FIELD_DECL, NULL_TREE, type_info_ptr_type),
-       build_decl (BUILTINS_LOCATION,
-                   FIELD_DECL, NULL_TREE, type_info_ptr_type),
-       NULL);
+  /* Create the pseudo type.  */
+  tree pseudo_type = make_class_type (RECORD_TYPE);
+  /* Pass the fields chained in reverse.  */
+  finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE);
+  CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type;
+
+  res->type = cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST);
+  res->name = get_identifier (real_name);
+
+  /* Pretend this is public so determine_visibility doesn't give vtables
+     internal linkage.  */
+  TREE_PUBLIC (TYPE_MAIN_DECL (res->type)) = 1;
 
   pop_abi_namespace ();
+  return res;
+}
+
+/* We lazily create the type info types.  */
+
+static void
+create_tinfo_types (void)
+{
+  gcc_assert (!tinfo_descs);
+
+  vec_alloc (tinfo_descs, TK_MAX + 20);
 }
 
 /* Helper for emit_support_tinfos. Emits the type_info descriptor of
@@ -1545,18 +1546,23 @@ emit_support_tinfos (void)
     0
   };
   int ix;
-  tree bltn_type, dtor;
 
-  push_abi_namespace ();
-  bltn_type = xref_tag (class_type,
-                       get_identifier ("__fundamental_type_info"),
-                       /*tag_scope=*/ts_current, false);
-  pop_abi_namespace ();
+  /* Look for a defined class.  */
+  tree bltn_type = lookup_qualified_name
+    (abi_node, get_identifier ("__fundamental_type_info"), true, false, false);
+  if (TREE_CODE (bltn_type) != TYPE_DECL)
+    return;
+
+  bltn_type = TREE_TYPE (bltn_type);
   if (!COMPLETE_TYPE_P (bltn_type))
     return;
-  dtor = CLASSTYPE_DESTRUCTORS (bltn_type);
+  tree dtor = CLASSTYPE_DESTRUCTORS (bltn_type);
   if (!dtor || DECL_EXTERNAL (dtor))
     return;
+
+  /* All these are really builtins.  So set the location.  */
+  location_t saved_loc = input_location;
+  input_location = BUILTINS_LOCATION;
   doing_runtime = 1;
   for (ix = 0; fundamentals[ix]; ix++)
     emit_support_tinfo_1 (*fundamentals[ix]);
@@ -1568,6 +1574,7 @@ emit_support_tinfos (void)
       }
   for (tree t = registered_builtin_types; t; t = TREE_CHAIN (t))
     emit_support_tinfo_1 (TREE_VALUE (t));
+  input_location = saved_loc;
 }
 
 /* Finish a type info decl. DECL_PTR is a pointer to an unemitted
@@ -1606,7 +1613,7 @@ emit_tinfo_decl (tree decl)
       TREE_PUBLIC (decl) = 0;
       DECL_EXTERNAL (decl) = 0;
       DECL_INTERFACE_KNOWN (decl) = 1;
-    }
+    }u
 
   import_export_decl (decl);
   if (DECL_NOT_REALLY_EXTERN (decl) && decl_needed_p (decl))