OSDN Git Service

86th Cygnus<->FSF quick merge
authormrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 12 Apr 1996 23:55:07 +0000 (23:55 +0000)
committermrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 12 Apr 1996 23:55:07 +0000 (23:55 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@11710 138bc75d-0d04-0410-961f-82ee72b054a4

13 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/lex.c
gcc/cp/method.c
gcc/cp/pt.c
gcc/cp/rtti.c
gcc/cp/search.c
gcc/cp/typeck.c

index 80d94b4..8cfe37d 100644 (file)
@@ -1,3 +1,190 @@
+Fri Apr 12 09:08:27 1996  Bob Manson  <manson@charmed.cygnus.com>
+
+       * search.c (expand_upcast_fixups): Mark the new fixup as
+       DECL_ARTIFICIAL.
+
+Thu Apr 11 03:57:09 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * init.c (build_new): Use a TARGET_EXPR for alloc_expr.
+
+       * class.c (set_rtti_entry): Fix for thunks.
+
+       * decl2.c (import_export_decl): Still emit typeinfo fns for
+       cv-variants of builtin types.
+
+       * rtti.c (expand_class_desc): Set up base_info_type_node here.
+       (init_rtti_processing): Instead of here.
+
+Wed Apr 10 14:17:13 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * rtti.c (init_rtti_processing): Do init regardless of -frtti.
+       (build_typeid): Only complain about taking dynamic typeid without
+       -frtti.
+
+       * decl2.c: flag_rtti defaults to 1.
+
+       * rtti.c (get_tinfo_var): The general class case is now smaller.
+       (init_rtti_processing): Pack the latter three fields of base_info
+       into 32 bits.
+
+Wed Apr 10 13:50:14 1996  Mike Stump  <mrs@cygnus.com>
+
+       * init.c (expand_member_init): Don't dump if name is NULL_TREE.
+
+Wed Apr 10 12:56:02 1996  Mike Stump  <mrs@cygnus.com>
+
+       * search.c (make_memoized_table_entry): Undefer the pop, if necessary.
+       (push_memoized_context): Split out code to undefer pop_type_level to
+       (clear_memoized_cache): here.
+       (pop_memoized_context): We can only handle one layer of deferral of
+       pop_type_level so clear the cache, if there was a previous level.
+
+Tue Apr  9 23:06:09 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * rtti.c (init_rtti_processing): Build up base_info_type_node.
+       (expand_class_desc): Use one pointer to an array of base_info
+       structs, passed using a CONSTRUCTOR.
+
+Tue Apr  9 14:20:57 1996  Mike Stump  <mrs@cygnus.com>
+
+       * class.c (build_vbase_path): Remove block extern for
+       flag_assume_nonnull_objects here.
+       (build_vfn_ref): Split out functionality into build_vtbl_ref.
+       (build_vtbl_ref): New routine.
+       (build_vtable): Set up rtti info here.
+       (add_virtual_function): Note in CLASSTYPE_RTTI the best
+       place where we can get the rtti pointers from to avoid having to
+       search around for a place.
+       (finish_base_struct): Ditto.
+       (finish_struct_1): Ditto.  Never create totally new vtables with totally
+       new vtable pointers for rtti.  Disable code to layout vtable pointers
+       better until we want to break binary compatibility.
+       * rtti.c (build_headof_sub): New routine to convert down to a
+       sub-object that has an rtti pointer in the vtable.
+       (build_headof): Use it.  Also, use build_vtbl_ref now to be more
+       maintainable.
+       (build_dynamic_cast): Make sure we have saved it, if we need to.
+       * search.c (dfs_init_vbase_pointers): Disable code that deals with
+       a more efficient vtable layout, enable later.
+       * call.c (flag_assume_nonnull_objects): Moved declaration to
+       * cp-tree.h: here.  Declare build_vtbl_ref.
+       * pt.c (instantiate_class_template): Use NULL_TREE instead of 0 in
+       function calls that want a tree.
+
+Tue Apr  9 12:10:26 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * rtti.c (build_dynamic_cast): Handle downcasting to X* given
+       other X subobjects in the most derived type.  Ack.
+
+       * rtti.c (build_dynamic_cast): No need to strip cv-quals here,
+       get_typeid will do it for us.
+       (get_typeid_1): Break out call-building for expand_*_desc to use.
+       (get_typeid): Call it.
+       (expand_*_desc): Ditto.
+       * decl.c (init_decl_processing): Don't set TYPE_BUILT_IN on char *
+       and void *.
+       (init_decl_processing): Lose builtin_type_tdescs lossage.
+       * decl2.c (finish_vtable_vardecl): Remove obsolete code.
+
+Mon Apr  8 17:23:23 1996  Bob Manson  <manson@charmed.cygnus.com>
+
+       * pt.c (tsubst): When calling set_nested_typename, use
+       TYPE_NESTED_NAME (current_class_type) instead of
+       current_class_name.
+
+       * decl.c (pushdecl): Ditto.
+       (pushdecl_class_level): Ditto.
+       (grokdeclarator): Use NULL_TREE instead of 0 in the call to
+       set_nested_typename.
+
+Sun Apr  7 10:44:31 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * rtti.c (synthesize_tinfo_fn): Handle arrays.
+
+       * cp-tree.h (DECL_REALLY_EXTERN): New macro.
+
+Sat Apr  6 13:56:27 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * rtti.c (throw_bad_cast): Use entry point __throw_bad_cast.
+       (init_rtti_processing): Lose bad_cast_type.
+       (build_dynamic_cast): Use throw_bad_cast.
+
+       * rtti.c (synthesize_tinfo_fn): Handle enums and pmfs.
+
+       * decl2.c (finish_file): Don't synthesize artificial functions
+       that are external and not inline.
+
+       * rtti.c (get_tinfo_fn): If at_eof, call import_export_decl.
+
+       * decl2.c (finish_file): Handle having new inlines added to
+       saved_inlines by synthesis.
+
+       * rtti.c (get_bad_cast_node): Don't require <typeinfo>.
+
+Fri Apr  5 17:02:09 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       RTTI rewrite to initialize nodes as needed, not require that
+       users #include <typeinfo>, complete functionality and reduce wasted 
+       space.
+       * rtti.c (init_rtti_processing): New fn.
+       (build_typeid): The vtable entry is now a function.
+       (get_tinfo_var): New fn.
+       (get_tinfo_fn): Ditto.
+       (get_typeid): Use it.
+       (build_dynamic_cast): Declare and use entry point __dynamic_cast.
+       (build_*_desc): Rename to expand_*_desc and rewrite to use entry
+       points __rtti_*.
+       (add_uninstantiated_desc, get_def_to_follow, build_t_desc): Lose.
+       (synthesize_tinfo_fn): New fn.
+       * method.c (build_t_desc_overload): Lose.
+       (build_overload_with_type): More generic.
+       * decl.c (init_decl_processing): Call init_rtti_processing.
+       * class.c (set_rtti_entry): Use get_tinfo_fn.
+       * decl2.c (mark_vtable_entries): Mark the rtti function.
+       (finish_prevtable_vardecl): Don't build_t_desc.
+       (import_export_decl): Handle tinfo functions.
+       (finish_file): Ditto.
+       * typeck.c (inline_conversion): New fn.
+       (build_function_call_real): Use it.
+       * cp-tree.h: Add decls.
+
+       * method.c (hack_identifier): Also convert component_refs from
+       references.
+
+       * lex.c (cons_up_default_function): Use the type, not the name, in
+       declspecs.
+
+       * decl2.c (import_export_vtable): Fix weak vtables.
+
+Fri Apr  5 13:30:17 1996  Bob Manson  <manson@charmed.cygnus.com>
+
+       * search.c (get_base_distance_recursive): Fix access checks for
+       protected bases.
+
+Fri Apr  5 11:02:06 1996  Brendan Kehoe  <brendan@lisa.cygnus.com>
+
+       * call.c (unary_complex_lvalue): Delete unneeded decl, it's in
+       cp-tree.h.
+       (convert_harshness): Add prototypes wrapped by PROTO.
+       * decl2.c (grok_function_init): Likewise.
+       (do_toplevel_using_decl): Change to void return type.
+       * class.c (build_vtable_entry): Remove decl of make_thunk.
+       (merge_overrides): Fix order of arg definitions.
+       (finish_vtbls): Likewise.
+       (fixup_vtable_deltas): Likewise.
+       (modify_all_direct_vtables): Likewise.
+       (modify_all_indirect_vtables): Likewise.
+       * search.c (get_base_distance_recursive): Likewise.
+       (get_abstract_virtuals_1): Likewise.
+       (fixup_virtual_upcast_offsets): Likewise.
+       (lookup_fnfields_1): Add prototypes wrapped by PROTO.
+       * init.c (perform_member_init): Fix order of arg definitions.
+       (expand_aggr_init_1): Add prototypes wrapped by PROTO.
+       * cp-tree.h (make_thunk): Add decl.
+       (overload_template_name, push_template_decl): Add decls.
+       (do_toplevel_using_decl): Change to void return type.
+       (vec_binfo_member): Add decl.
+
 Thu Apr  4 13:33:10 1996  Brendan Kehoe  <brendan@lisa.cygnus.com>
 
        * typeck.c (mark_addressable, convert_for_assignment,
index 55994c6..7afd319 100644 (file)
@@ -38,15 +38,11 @@ Boston, MA 02111-1307, USA.  */
 extern void sorry ();
 
 extern int inhibit_warnings;
-extern int flag_assume_nonnull_objects;
 extern tree ctor_label, dtor_label;
 
-/* From typeck.c:  */
-extern tree unary_complex_lvalue ();
-
 /* Compute the ease with which a conversion can be performed
    between an expected and the given type.  */
-static struct harshness_code convert_harshness ();
+static struct harshness_code convert_harshness PROTO((register tree, register tree, tree));
 
 #define EVIL_RETURN(ARG)       ((ARG).code = EVIL_CODE, (ARG))
 #define STD_RETURN(ARG)                ((ARG).code = STD_CODE, (ARG))
index 76377e1..bbf259c 100644 (file)
@@ -240,7 +240,6 @@ build_vbase_path (code, type, expr, path, alias_this)
 
              if (changed)
                {
-                 extern int flag_assume_nonnull_objects;
                  tree ind;
 
                  /* We already check for ambiguous things in the caller, just
@@ -377,7 +376,6 @@ build_vtable_entry (delta, pfn)
   if (flag_vtable_thunks)
     {
       HOST_WIDE_INT idelta = TREE_INT_CST_LOW (delta);
-      extern tree make_thunk ();
       if (idelta)
        {
          pfn = build1 (ADDR_EXPR, vtable_entry_type,
@@ -425,13 +423,12 @@ build_vtable_entry (delta, pfn)
 }
 
 /* Given an object INSTANCE, return an expression which yields the
-   virtual function corresponding to INDEX.  There are many special
-   cases for INSTANCE which we take care of here, mainly to avoid
-   creating extra tree nodes when we don't have to.  */
+   virtual function vtable element corresponding to INDEX.  There are
+   many special cases for INSTANCE which we take care of here, mainly
+   to avoid creating extra tree nodes when we don't have to.  */
 tree
-build_vfn_ref (ptr_to_instptr, instance, idx)
-     tree *ptr_to_instptr, instance;
-     tree idx;
+build_vtbl_ref (instance, idx)
+     tree instance, idx;
 {
   tree vtbl, aref;
   tree basetype = TREE_TYPE (instance);
@@ -487,23 +484,40 @@ build_vfn_ref (ptr_to_instptr, instance, idx)
   assemble_external (vtbl);
   aref = build_array_ref (vtbl, idx);
 
-  /* Save the intermediate result in a SAVE_EXPR so we don't have to
-     compute each component of the virtual function pointer twice.  */ 
-  if (TREE_CODE (aref) == INDIRECT_REF)
-    TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
+  return aref;
+}
+
+/* Given an object INSTANCE, return an expression which yields the
+   virtual function corresponding to INDEX.  There are many special
+   cases for INSTANCE which we take care of here, mainly to avoid
+   creating extra tree nodes when we don't have to.  */
+tree
+build_vfn_ref (ptr_to_instptr, instance, idx)
+     tree *ptr_to_instptr, instance;
+     tree idx;
+{
+  tree aref = build_vtbl_ref (instance, idx);
 
+  /* When using thunks, there is no extra delta, and we get the pfn
+     directly.  */
   if (flag_vtable_thunks)
     return aref;
-  else
+
+  if (ptr_to_instptr)
     {
-      if (ptr_to_instptr)
-       *ptr_to_instptr
-         = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
-                  *ptr_to_instptr,
-                  convert (ptrdiff_type_node,
-                           build_component_ref (aref, delta_identifier, 0, 0)));
-      return build_component_ref (aref, pfn_identifier, 0, 0);
+      /* Save the intermediate result in a SAVE_EXPR so we don't have to
+        compute each component of the virtual function pointer twice.  */ 
+      if (TREE_CODE (aref) == INDIRECT_REF)
+       TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
+
+      *ptr_to_instptr
+       = build (PLUS_EXPR, TREE_TYPE (*ptr_to_instptr),
+                *ptr_to_instptr,
+                convert (ptrdiff_type_node,
+                         build_component_ref (aref, delta_identifier, NULL_TREE, 0)));
     }
+
+  return build_component_ref (aref, pfn_identifier, NULL_TREE, 0);
 }
 
 /* Return the name of the virtual function table (as an IDENTIFIER_NODE)
@@ -530,6 +544,70 @@ get_vtable_name (type)
   return get_identifier (buf);
 }
 
+/* Return the offset to the main vtable for a given base BINFO.  */
+tree
+get_vfield_offset (binfo)
+     tree binfo;
+{
+  return size_binop (PLUS_EXPR,
+                    size_binop (FLOOR_DIV_EXPR,
+                                DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))),
+                                size_int (BITS_PER_UNIT)),
+                    BINFO_OFFSET (binfo));
+}
+
+/* Get the offset to the start of the original binfo that we derived
+   this binfo from.  If we find TYPE first, return the offset only
+   that far.  The shortened search is useful because the this pointer
+   on method calling is expected to point to a DECL_CONTEXT (fndecl)
+   object, and not a baseclass of it.  */
+static tree
+get_derived_offset (binfo, type)
+     tree binfo, type;
+{
+  tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
+  tree offset2;
+  int i;
+  while (BINFO_BASETYPES (binfo)
+        && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
+    {
+      tree binfos = BINFO_BASETYPES (binfo);
+      if (BINFO_TYPE (binfo) == type)
+       break;
+      binfo = TREE_VEC_ELT (binfos, i);
+    }
+  offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
+  return size_binop (MINUS_EXPR, offset1, offset2);
+}
+
+/* Update the rtti info for this class.  */
+static void
+set_rtti_entry (virtuals, offset, type)
+     tree virtuals, offset, type;
+{
+  tree vfn;
+
+  if (flag_rtti)
+    vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, get_tinfo_fn (type));
+  else
+    vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, integer_zero_node);
+  TREE_CONSTANT (vfn) = 1;
+
+  if (! flag_vtable_thunks)
+    TREE_VALUE (virtuals) = build_vtable_entry (offset, vfn);
+  else
+    {
+      tree voff = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
+      TREE_CONSTANT (voff) = 1;
+
+      TREE_VALUE (virtuals) = build_vtable_entry (integer_zero_node, voff);
+
+      /* The second slot is for the tdesc pointer when thunks are used.  */
+      TREE_VALUE (TREE_CHAIN (virtuals))
+       = build_vtable_entry (integer_zero_node, vfn);
+    }
+}
+
 /* Build a virtual function for type TYPE.
    If BINFO is non-NULL, build the vtable starting with the initial
    approximation that it is the same as the one which is the head of
@@ -543,8 +621,15 @@ build_vtable (binfo, type)
 
   if (binfo)
     {
+      tree offset;
+
       virtuals = copy_list (BINFO_VIRTUALS (binfo));
       decl = build_decl (VAR_DECL, name, TREE_TYPE (BINFO_VTABLE (binfo)));
+
+      /* Now do rtti stuff.  */
+      offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE);
+      offset = size_binop (MINUS_EXPR, integer_zero_node, offset);
+      set_rtti_entry (virtuals, offset, type);
     }
   else
     {
@@ -649,36 +734,6 @@ build_type_pathname (format, parent, type)
   return id;
 }
 
-/* Update the rtti info for this class.  */
-static void
-set_rtti_entry (virtuals, offset, type)
-     tree virtuals, offset, type;
-{
-  if (! flag_vtable_thunks)
-    TREE_VALUE (virtuals)
-      = build_vtable_entry (offset,
-                           (flag_rtti
-                            ? build_t_desc (type, 0)
-                            : integer_zero_node));
-  else
-    {
-      tree vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
-      TREE_CONSTANT (vfn) = 1;
-
-      TREE_VALUE (virtuals)
-       = build_vtable_entry (integer_zero_node, vfn);
-      /* The second slot is for the tdesc pointer when thunks are used.  */
-      vfn = flag_rtti
-            ? build_t_desc (type, 0)
-            : integer_zero_node;
-      vfn = build1 (NOP_EXPR, vfunc_ptr_type_node, vfn);
-      TREE_CONSTANT (vfn) = 1;
-
-      TREE_VALUE (TREE_CHAIN (virtuals))
-       = build_vtable_entry (integer_zero_node, vfn);
-    }
-}
-
 /* Give TYPE a new virtual function table which is initialized
    with a skeleton-copy of its original initialization.  The only
    entry that changes is the `delta' entry, so we can really
@@ -716,8 +771,18 @@ prepare_fresh_vtable (binfo, for_type)
   BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));
 
   if (TREE_VIA_VIRTUAL (binfo))
-    offset = BINFO_OFFSET (binfo_member (BINFO_TYPE (binfo), 
-                           CLASSTYPE_VBASECLASSES (for_type)));
+    {
+      tree binfo1 = binfo_member (BINFO_TYPE (binfo), 
+                                 CLASSTYPE_VBASECLASSES (for_type));
+
+      /* XXX - This should never happen, if it does, the caller should
+        ensure that the binfo is from for_type's binfos, not from any
+        base type's.  We can remove all this code after a while.  */
+      if (binfo1 != binfo)
+       warning ("internal inconsistency: binfo offset error for rtti");
+
+      offset = BINFO_OFFSET (binfo1);
+    }
   else
     offset = BINFO_OFFSET (binfo);
 
@@ -844,11 +909,8 @@ add_virtual_function (pending_virtuals, has_virtual, fndecl, t)
     {
       tree entry;
 
-      if (flag_rtti && *has_virtual == 0)
-       {
-         /* CLASSTYPE_RTTI is only used as a Boolean (NULL or not). */
-         CLASSTYPE_RTTI (t) = integer_one_node;
-        }
+      /* We remember that this was the base sub-object for rtti.  */
+      CLASSTYPE_RTTI (t) = t;
 
       /* If we are using thunks, use two slots at the front, one
         for the offset pointer, one for the tdesc pointer.  */
@@ -1177,42 +1239,6 @@ alter_access (t, fdecl, access)
   return 0;
 }
 
-/* Return the offset to the main vtable for a given base BINFO.  */
-tree
-get_vfield_offset (binfo)
-     tree binfo;
-{
-  return size_binop (PLUS_EXPR,
-                    size_binop (FLOOR_DIV_EXPR,
-                                DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))),
-                                size_int (BITS_PER_UNIT)),
-                    BINFO_OFFSET (binfo));
-}
-
-/* Get the offset to the start of the original binfo that we derived
-   this binfo from.  If we find TYPE first, return the offset only
-   that far.  The shortened search is useful because the this pointer
-   on method calling is expected to point to a DECL_CONTEXT (fndecl)
-   object, and not a baseclass of it.  */
-static tree
-get_derived_offset (binfo, type)
-     tree binfo, type;
-{
-  tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
-  tree offset2;
-  int i;
-  while (BINFO_BASETYPES (binfo)
-        && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)
-    {
-      tree binfos = BINFO_BASETYPES (binfo);
-      if (BINFO_TYPE (binfo) == type)
-       break;
-      binfo = TREE_VEC_ELT (binfos, i);
-    }
-  offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));
-  return size_binop (MINUS_EXPR, offset1, offset2);
-}
-
 /* If FOR_TYPE needs to reinitialize virtual function table pointers
    for TYPE's sub-objects, add such reinitializations to BASE_INIT_LIST.
    Returns BASE_INIT_LIST appropriately modified.  */
@@ -1379,6 +1405,7 @@ struct base_info
   int n_ancestors;
   tree vfield;
   tree vfields;
+  tree rtti;
   char cant_have_default_ctor;
   char cant_have_const_ctor;
   char cant_synth_copy_ctor;
@@ -1478,14 +1505,6 @@ finish_base_struct (t, b, t_binfo)
       TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype);
 
       if (! TREE_VIA_VIRTUAL (base_binfo)
-#if 0
-         /* This cannot be done, as prepare_fresh_vtable wants to modify
-            binfos associated with vfields anywhere in the hierarchy, not
-            just immediate base classes.  Due to unsharing, the compiler
-            might consume 3% more memory on a real program.
-            */
-         && ! BINFO_OFFSET_ZEROP (base_binfo)
-#endif
          && BINFO_BASETYPES (base_binfo))
        {
          tree base_binfos = BINFO_BASETYPES (base_binfo);
@@ -1523,6 +1542,11 @@ finish_base_struct (t, b, t_binfo)
          /* Remember that the baseclass has virtual members. */
          b->base_has_virtual = 1;
 
+         /* Ensure that this is set from at least a virtual base
+             class.  */
+         if (b->rtti == NULL_TREE)
+           b->rtti = CLASSTYPE_RTTI (basetype);
+
          /* Don't borrow virtuals from virtual baseclasses.  */
          if (TREE_VIA_VIRTUAL (base_binfo))
            continue;
@@ -1658,6 +1682,11 @@ finish_base_struct (t, b, t_binfo)
   if (b->vfield == 0)
     /* If all virtual functions come only from virtual baseclasses.  */
     return -1;
+
+  /* Update the rtti base if we have a non-virtual base class version
+     of it.  */
+  b->rtti = CLASSTYPE_RTTI (BINFO_TYPE (TREE_VEC_ELT (binfos, first_vfn_base_index)));
+
   return first_vfn_base_index;
 }
 
@@ -2084,8 +2113,9 @@ duplicate_tag_error (t)
 /* finish up all new vtables. */
 static void
 finish_vtbls (binfo, do_self, t)
-     tree binfo, t;
+     tree binfo;
      int do_self;
+     tree t;
 {
   tree binfos = BINFO_BASETYPES (binfo);
   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2346,8 +2376,9 @@ modify_one_vtable (binfo, t, fndecl, pfn)
 /* These are the ones that are not through virtual base classes. */
 static void
 modify_all_direct_vtables (binfo, do_self, t, fndecl, pfn)
-     tree binfo, t, fndecl, pfn;
+     tree binfo;
      int do_self;
+     tree t, fndecl, pfn;
 {
   tree binfos = BINFO_BASETYPES (binfo);
   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2445,8 +2476,9 @@ fixup_vtable_deltas1 (binfo, t)
    hierarchy, because the layout of the virtual bases has changed.  */
 static void
 fixup_vtable_deltas (binfo, init_self, t)
-     tree binfo, t;
+     tree binfo;
      int init_self;
+     tree t;
 {
   tree binfos = BINFO_BASETYPES (binfo);
   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2469,8 +2501,9 @@ fixup_vtable_deltas (binfo, init_self, t)
 /* These are the ones that are through virtual base classes. */
 static void
 modify_all_indirect_vtables (binfo, do_self, via_virtual, t, fndecl, pfn)
-     tree binfo, t, fndecl, pfn;
+     tree binfo;
      int do_self, via_virtual;
+     tree t, fndecl, pfn;
 {
   tree binfos = BINFO_BASETYPES (binfo);
   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2643,8 +2676,9 @@ override_one_vtable (binfo, old, t)
    overrides.  */
 static void
 merge_overrides (binfo, old, do_self, t)
-     tree binfo, old, t;
+     tree binfo, old;
      int do_self;
+     tree t;
 {
   tree binfos = BINFO_BASETYPES (binfo);
   tree old_binfos = BINFO_BASETYPES (old);
@@ -3070,13 +3104,14 @@ finish_struct_1 (t, attributes, warn_anon)
       fields = chainon (vf, fields);
 
       first_vfn_base_index = finish_base_struct (t, &base_info, t_binfo);
-      /* Remember where we got our vfield from */
+      /* Remember where we got our vfield from. */
       CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index;
       has_virtual = base_info.has_virtual;
       max_has_virtual = base_info.max_has_virtual;
       CLASSTYPE_N_SUPERCLASSES (t) += base_info.n_ancestors;
       vfield = base_info.vfield;
       vfields = base_info.vfields;
+      CLASSTYPE_RTTI (t) = base_info.rtti;
       cant_have_default_ctor = base_info.cant_have_default_ctor;
       cant_have_const_ctor = base_info.cant_have_const_ctor;
       cant_synth_copy_ctor = base_info.cant_synth_copy_ctor;
@@ -3093,6 +3128,7 @@ finish_struct_1 (t, attributes, warn_anon)
       max_has_virtual = has_virtual;
       vfield = NULL_TREE;
       vfields = NULL_TREE;
+      CLASSTYPE_RTTI (t) = NULL_TREE;
       last_x = NULL_TREE;
       cant_have_default_ctor = 0;
       cant_have_const_ctor = 0;
@@ -3560,9 +3596,6 @@ finish_struct_1 (t, attributes, warn_anon)
     }
 
   TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
-  if (flag_rtti && (max_has_virtual > 0 || base_has_virtual) && 
-       has_virtual == 0)
-    has_virtual = 1;
 
   TYPE_HAS_COMPLEX_INIT_REF (t)
     |= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t)
@@ -3728,13 +3761,15 @@ finish_struct_1 (t, attributes, warn_anon)
       DECL_SAVED_INSNS (vfield) = NULL_RTX;
       DECL_FIELD_SIZE (vfield) = 0;
       DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node);
-      if (CLASSTYPE_RTTI (t))
-       {
-         /* vfield is always first entry in structure.  */
-         TREE_CHAIN (vfield) = fields;
-         fields = vfield;
-       }
-      else if (last_x)
+#if 0
+      /* This is more efficient, but breaks binary compatibility, turn
+        it on sometime when we don't care.  If we turn it on, we also
+        have to enable the code in dfs_init_vbase_pointers.  */
+      /* vfield is always first entry in structure.  */
+      TREE_CHAIN (vfield) = fields;
+      fields = vfield;
+#else
+      if (last_x)
        {
          my_friendly_assert (TREE_CHAIN (last_x) == NULL_TREE, 175);
          TREE_CHAIN (last_x) = vfield;
@@ -3742,6 +3777,7 @@ finish_struct_1 (t, attributes, warn_anon)
        }
       else
        fields = vfield;
+#endif
       vfields = chainon (vfields, CLASSTYPE_AS_LIST (t));
     }
 
@@ -3843,17 +3879,6 @@ finish_struct_1 (t, attributes, warn_anon)
       vbases = CLASSTYPE_VBASECLASSES (t);
       CLASSTYPE_N_VBASECLASSES (t) = list_length (vbases);
 
-      /* The rtti code should do this.  (mrs) */
-#if 0 
-      while (vbases)
-       {
-         /* Update rtti info with offsets for virtual baseclasses.  */
-         if (flag_rtti && ! BINFO_NEW_VTABLE_MARKED (vbases))
-           prepare_fresh_vtable (vbases, t);
-         vbases = TREE_CHAIN (vbases);
-       }
-#endif
-
       {
        /* Now fixup overrides of all functions in vtables from all
           direct or indirect virtual base classes.  */
@@ -3941,34 +3966,29 @@ finish_struct_1 (t, attributes, warn_anon)
 
   /* Under our model of GC, every C++ class gets its own virtual
      function table, at least virtually.  */
-  if (pending_virtuals || (flag_rtti && TYPE_VIRTUAL_P (t)))
+  if (pending_virtuals)
     {
       pending_virtuals = nreverse (pending_virtuals);
       /* We must enter these virtuals into the table.  */
       if (first_vfn_base_index < 0)
        {
-         /* The first slot is for the rtti offset.  */
-         pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
-
          /* The second slot is for the tdesc pointer when thunks are used.  */
          if (flag_vtable_thunks)
            pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
 
+         /* The first slot is for the rtti offset.  */
+         pending_virtuals = tree_cons (NULL_TREE, NULL_TREE, pending_virtuals);
+
          set_rtti_entry (pending_virtuals, integer_zero_node, t);
          build_vtable (NULL_TREE, t);
        }
       else
        {
-         tree offset;
          /* Here we know enough to change the type of our virtual
             function table, but we will wait until later this function.  */
 
          if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t)))
            build_vtable (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (t), first_vfn_base_index), t);
-
-         offset = get_derived_offset (TYPE_BINFO (t), NULL_TREE);
-         offset = size_binop (MINUS_EXPR, integer_zero_node, offset);
-         set_rtti_entry (TYPE_BINFO_VIRTUALS (t), offset, t);
        }
 
       /* If this type has basetypes with constructors, then those
index 4f3212c..c8c9fd1 100644 (file)
@@ -1403,6 +1403,9 @@ extern int flag_new_for_scope;
 #define DECL_NOT_REALLY_EXTERN(NODE) \
   (DECL_LANG_SPECIFIC (NODE)->decl_flags.not_really_extern)
 
+#define DECL_REALLY_EXTERN(NODE) \
+  (DECL_EXTERNAL (NODE) && ! DECL_NOT_REALLY_EXTERN (NODE))
+
 #define DECL_PUBLIC(NODE) \
   (TREE_CODE (NODE) == FUNCTION_DECL \
    ? ! DECL_C_STATIC (NODE) : TREE_PUBLIC (NODE))
@@ -1947,6 +1950,7 @@ extern char *dont_allow_type_definitions;
 extern tree build_vbase_pointer                        PROTO((tree, tree));
 extern tree build_vbase_path                   PROTO((enum tree_code, tree, tree, tree, int));
 extern tree build_vtable_entry                 PROTO((tree, tree));
+extern tree build_vtbl_ref                     PROTO((tree, tree));
 extern tree build_vfn_ref                      PROTO((tree *, tree, tree));
 extern void add_method                         PROTO((tree, tree *, tree));
 extern tree get_vfield_offset                  PROTO((tree));
@@ -2074,6 +2078,8 @@ extern void pop_cp_function_context               PROTO((tree));
 extern void grok_op_properties                 PROTO((tree, int, int));
 
 /* in decl2.c */
+extern int flag_assume_nonnull_objects;
+
 extern int lang_decode_option                  PROTO((char *));
 extern tree grok_method_quals                  PROTO((tree, tree, tree));
 extern void grokclassfn                                PROTO((tree, tree, tree, enum overload_flags, tree));
@@ -2112,7 +2118,7 @@ extern tree reparse_decl_as_expr          PROTO((tree, tree));
 extern tree finish_decl_parsing                        PROTO((tree));
 extern tree lookup_name_nonclass               PROTO((tree));
 extern tree check_cp_case_value                        PROTO((tree));
-extern tree do_toplevel_using_decl             PROTO((tree));
+extern void do_toplevel_using_decl             PROTO((tree));
 extern tree do_class_using_decl                        PROTO((tree));
 extern tree current_namespace_id               PROTO((tree));
 extern tree get_namespace_id                   PROTO((void));
@@ -2152,10 +2158,7 @@ extern void init_repo                            PROTO((char*));
 extern void finish_repo                                PROTO((void));
 
 /* in rtti.c */
-extern tree build_classof                      PROTO((tree));
-extern tree build_t_desc                       PROTO((tree, int));
-extern tree build_i_desc                       PROTO((tree));
-extern tree build_m_desc                       PROTO((tree));
+extern tree get_tinfo_fn                       PROTO((tree));
 extern tree build_typeid                       PROTO((tree));
 extern tree get_typeid                         PROTO((tree));
 extern tree build_dynamic_cast                 PROTO((tree, tree));
@@ -2269,7 +2272,7 @@ extern tree build_static_name                     PROTO((tree, tree));
 extern tree cplus_exception_name               PROTO((tree));
 extern tree build_decl_overload                        PROTO((tree, tree, int));
 extern tree build_typename_overload            PROTO((tree));
-extern tree build_t_desc_overload              PROTO((tree));
+extern tree build_overload_with_type           PROTO((tree, tree));
 extern void declare_overloaded                 PROTO((tree));
 #ifdef NO_AUTO_OVERLOAD
 extern int is_overloaded                       PROTO((tree));
@@ -2277,6 +2280,7 @@ extern int is_overloaded                  PROTO((tree));
 extern tree build_opfncall                     PROTO((enum tree_code, int, tree, tree, tree));
 extern tree hack_identifier                    PROTO((tree, tree));
 extern tree build_component_type_expr          PROTO((tree, tree, tree, int));
+extern tree make_thunk                         PROTO((tree, int));
 extern void synthesize_method                  PROTO((tree));
 
 /* in pt.c */
@@ -2288,10 +2292,12 @@ extern void begin_template_parm_list            PROTO((void));
 extern tree process_template_parm              PROTO((tree, tree));
 extern tree end_template_parm_list             PROTO((tree));
 extern void end_template_decl                  PROTO((void));
+extern void push_template_decl                 PROTO((tree));
 extern tree lookup_template_class              PROTO((tree, tree, tree));
 extern int uses_template_parms                 PROTO((tree));
 extern tree instantiate_class_template         PROTO((tree));
 extern tree instantiate_template               PROTO((tree, tree *));
+extern void overload_template_name             PROTO((tree));
 extern int type_unification                    PROTO((tree, tree *, tree, tree, int *, int));
 struct tinst_level *tinst_for_decl             PROTO((void));
 extern void mark_decl_instantiated             PROTO((tree, int));
@@ -2402,6 +2408,7 @@ extern tree build_unsave_expr                     PROTO((tree));
 extern tree unsave_expr                                PROTO((tree));
 extern int cp_expand_decl_cleanup              PROTO((tree, tree));
 extern tree get_type_decl                      PROTO((tree));
+extern tree vec_binfo_member                   PROTO((tree, tree));
 extern tree hack_decl_function_context                 PROTO((tree));
 
 /* in typeck.c */
@@ -2428,6 +2435,7 @@ extern tree expr_sizeof                           PROTO((tree));
 extern tree c_sizeof                           PROTO((tree));
 extern tree c_sizeof_nowarn                    PROTO((tree));
 extern tree c_alignof                          PROTO((tree));
+extern tree inline_conversion                  PROTO((tree));
 extern tree decay_conversion                   PROTO((tree));
 extern tree default_conversion                 PROTO((tree));
 extern tree build_object_ref                   PROTO((tree, tree, tree));
index c5274b4..d32431b 100644 (file)
@@ -3164,7 +3164,7 @@ pushdecl (x)
             Any artificial decls that need DECL_NESTED_TYPENAME will have it
             set in pushtag.  */
          if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x))
-           set_nested_typename (x, current_class_name, DECL_NAME (x), type);
+           set_nested_typename (x, current_class_type != NULL_TREE ? TYPE_NESTED_NAME (current_class_type) : current_class_name, DECL_NAME (x), type);
 
          if (type != error_mark_node
              && TYPE_NAME (type)
@@ -3491,7 +3491,7 @@ pushdecl_class_level (x)
             Any artificial decls that need DECL_NESTED_TYPENAME will have it
             set in pushtag.  */
          if (! DECL_NESTED_TYPENAME (x) && ! DECL_ARTIFICIAL (x))
-           set_nested_typename (x, current_class_name, name, TREE_TYPE (x));
+           set_nested_typename (x, current_class_type != NULL_TREE ? TYPE_NESTED_NAME (current_class_type) : current_class_name, name, TREE_TYPE (x));
        }
     }
   return x;
@@ -4655,32 +4655,6 @@ record_builtin_type (rid_index, name, type)
          set_identifier_type_value (rname, NULL_TREE);
        }
     }
-
-  if (flag_rtti)
-    {
-      if (builtin_type_tdescs_len+5 >= builtin_type_tdescs_max)
-       {
-         builtin_type_tdescs_max *= 2;
-         builtin_type_tdescs_arr
-           = (tree *)xrealloc (builtin_type_tdescs_arr,
-                               builtin_type_tdescs_max * sizeof (tree));
-       }
-      builtin_type_tdescs_arr[builtin_type_tdescs_len++] = type;
-      if (TREE_CODE (type) != POINTER_TYPE)
-       {
-         builtin_type_tdescs_arr[builtin_type_tdescs_len++]
-           = build_pointer_type (type);
-         builtin_type_tdescs_arr[builtin_type_tdescs_len++]
-           = build_pointer_type (build_type_variant (type, 1, 0));
-       }
-      if (TREE_CODE (type) != VOID_TYPE)
-       {
-         builtin_type_tdescs_arr[builtin_type_tdescs_len++]
-           = build_reference_type (type);
-         builtin_type_tdescs_arr[builtin_type_tdescs_len++]
-           = build_reference_type (build_type_variant (type, 1, 0));
-       }
-    }
 }
 
 /* Push overloaded decl, in global scope, with one argument so it
@@ -4695,7 +4669,8 @@ push_overloaded_decl_1 (x)
 #ifdef __GNUC__
 __inline
 #endif
-tree auto_function (name, type, code)
+tree
+auto_function (name, type, code)
      tree name, type;
      enum built_in_function code;
 {
@@ -4772,11 +4747,6 @@ init_decl_processing ()
 #endif
 
   gcc_obstack_init (&decl_obstack);
-  if (flag_rtti)
-    {
-      builtin_type_tdescs_max = 100;
-      builtin_type_tdescs_arr = (tree *)xmalloc (100 * sizeof (tree));
-    }
 
   /* Must lay these out before anything else gets laid out.  */
   error_mark_node = make_node (ERROR_MARK);
@@ -4944,7 +4914,9 @@ init_decl_processing ()
   string_type_node = build_pointer_type (char_type_node);
   const_string_type_node =
     build_pointer_type (build_type_variant (char_type_node, 1, 0));
+#if 0
   record_builtin_type (RID_MAX, NULL_PTR, string_type_node);
+#endif
 
   /* Make a type to be the domain of a few array types
      whose domains don't really matter.
@@ -4972,7 +4944,9 @@ init_decl_processing ()
   ptr_type_node = build_pointer_type (void_type_node);
   const_ptr_type_node =
     build_pointer_type (build_type_variant (void_type_node, 1, 0));
+#if 0
   record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node);
+#endif
   endlink = void_list_node;
   int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink);
   double_endlink = tree_cons (NULL_TREE, double_type_node, endlink);
@@ -5471,17 +5445,6 @@ init_decl_processing ()
       finish_builtin_type (__m_desc_type_node, "__m_desc", fields, 7,
                           integer_type_node);
     }
-
-  if (flag_rtti)
-    {
-      int i = builtin_type_tdescs_len;
-      while (i > 0)
-       {
-         tree tdesc = build_t_desc (builtin_type_tdescs_arr[--i], 0);
-         TREE_ASM_WRITTEN (tdesc) = 1;
-         TREE_PUBLIC (TREE_OPERAND (tdesc, 0)) = 1;
-       }
-    }
 #endif /*flag_rtti*/
 
   /* Now, C++.  */
@@ -5517,6 +5480,7 @@ init_decl_processing ()
   init_class_processing ();
   init_init_processing ();
   init_search_processing ();
+  init_rtti_processing ();
 
   if (flag_handle_exceptions)
     init_exception_processing ();
@@ -9029,7 +8993,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises, attrli
            tree d = TYPE_NAME (type), c = DECL_CONTEXT (d);
 
            if (!c)
-             set_nested_typename (d, 0, declarator, type);
+             set_nested_typename (d, NULL_TREE, declarator, type);
            else if (TREE_CODE (c) == FUNCTION_DECL)
              set_nested_typename (d, DECL_ASSEMBLER_NAME (c),
                                   declarator, type);
index 8077b5b..039b427 100644 (file)
@@ -39,7 +39,7 @@ Boston, MA 02111-1307, USA.  */
 
 extern tree get_file_function_name ();
 extern tree cleanups_this_call;
-static void grok_function_init ();
+static void grok_function_init PROTO((tree, tree));
 void import_export_decl ();
 extern int current_class_depth;
 
@@ -318,7 +318,7 @@ int flag_int_enum_equivalence;
 
 /* Controls whether compiler generates 'type descriptor' that give
    run-time type information.  */
-int flag_rtti;
+int flag_rtti = 1;
 
 /* Nonzero if we wish to output cross-referencing information
    for the GNU class browser.  */
@@ -2430,6 +2430,14 @@ mark_vtable_entries (decl)
 {
   tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL (decl));
 
+  if (flag_rtti)
+    {
+      tree fnaddr = (flag_vtable_thunks ? TREE_VALUE (TREE_CHAIN (entries))
+                    : FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
+      tree fn = TREE_OPERAND (fnaddr, 0);
+      TREE_ADDRESSABLE (fn) = 1;
+      mark_used (fn);
+    }
   skip_rtti_stuff (&entries);
 
   for (; entries; entries = TREE_CHAIN (entries))
@@ -2500,7 +2508,10 @@ import_export_vtable (decl, type, final)
            cp_error ("all virtual functions redeclared inline");
 #endif
          if (flag_weak)
-           DECL_WEAK (decl) = 1;
+           {
+             TREE_PUBLIC (decl) = 1;
+             DECL_WEAK (decl) = 1;
+           }
          else
            TREE_PUBLIC (decl) = 0;
          DECL_EXTERNAL (decl) = 0;
@@ -2557,21 +2568,6 @@ finish_prevtable_vardecl (prev, vars)
     }
 
   import_export_vtable (vars, ctype, 1);
-
-  /* We cannot use TREE_USED here, as it may be set by the expanding of a
-     ctor that is used to build a global object.  The long term plan is to
-     make the TD entries statically initialized and move this to
-     finish_vtable_vardecl time.  */
-  if (flag_rtti && write_virtuals >= 0
-      && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || 1 || TREE_USED (vars)))
-    {
-      /* Kick out the type descriptor before we dump out global
-        initializers, as they are initialized at run time and
-        we have to find them when we scan for things that need initialized
-        at the top level.  */
-      build_t_desc (ctype, 1);
-    }
-
   return 1;
 }
     
@@ -2583,15 +2579,6 @@ finish_vtable_vardecl (prev, vars)
       && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars))
       && ! TREE_ASM_WRITTEN (vars))
     {
-#if 0
-      /* The long term plan it to make the TD entries statically initialized,
-        have the entries built and emitted here.  When that happens, this
-        can be enabled, and the other call to build_t_desc removed.  */
-      /* Kick out the type descriptor before writing out the vtable.  */
-      if (flag_rtti)
-       build_t_desc (DECL_CONTEXT (vars), 1);
-#endif
-
       /* Write it out.  */
       mark_vtable_entries (vars);
       if (TREE_TYPE (DECL_INITIAL (vars)) == 0)
@@ -2763,6 +2750,23 @@ import_export_decl (decl)
       else
        TREE_PUBLIC (decl) = 0;
     }
+  /* tinfo function */
+  else if (DECL_ARTIFICIAL (decl) && DECL_MUTABLE_P (decl))
+    {
+      tree ctype = TREE_TYPE (DECL_NAME (decl));
+      if (IS_AGGR_TYPE (ctype) && CLASSTYPE_INTERFACE_KNOWN (ctype))
+       {
+         DECL_NOT_REALLY_EXTERN (decl)
+           = ! (CLASSTYPE_INTERFACE_ONLY (ctype)
+                || (DECL_THIS_INLINE (decl) && ! flag_implement_inlines));
+       }
+      else if (TYPE_BUILT_IN (ctype) && ctype == TYPE_MAIN_VARIANT (ctype))
+       DECL_NOT_REALLY_EXTERN (decl) = 0;
+      else if (flag_weak)
+       DECL_WEAK (decl) = 1;
+      else
+       TREE_PUBLIC (decl) = 0;
+    } 
   else if (DECL_C_STATIC (decl))
     TREE_PUBLIC (decl) = 0;
   else if (flag_weak)
@@ -3095,10 +3099,6 @@ finish_file ()
     {
       tree decl = TREE_VALUE (fnname);
       import_export_decl (decl);
-      if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
-         && TREE_PUBLIC (decl) && ! DECL_WEAK (decl)
-         && DECL_NOT_REALLY_EXTERN (decl))
-       synthesize_method (decl);
     }
 
   /* Now write out inline functions which had their addresses taken and
@@ -3126,14 +3126,21 @@ finish_file ()
            tree decl = TREE_VALUE (*p);
 
            if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
-               && TREE_USED (decl))
+               && TREE_USED (decl)
+               && (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl)))
              {
-               synthesize_method (decl);
+               if (DECL_MUTABLE_P (decl))
+                 synthesize_tinfo_fn (decl);
+               else
+                 synthesize_method (decl);
                reconsider = 1;
              }
 
-           if (TREE_ASM_WRITTEN (decl)
-               || (DECL_SAVED_INSNS (decl) == 0 && ! DECL_ARTIFICIAL (decl)))
+           if (decl != TREE_VALUE (*p))
+             ;
+           else if (TREE_ASM_WRITTEN (decl)
+                    || (DECL_SAVED_INSNS (decl) == 0
+                        && ! DECL_ARTIFICIAL (decl)))
              *p = TREE_CHAIN (*p);
            else
              p = &TREE_CHAIN (*p);
@@ -3619,7 +3626,7 @@ do_namespace_alias (alias, namespace)
   sorry ("namespace alias");
 }
 
-tree
+void
 do_toplevel_using_decl (decl)
      tree decl;
 {
index b8d0dad..e5e186e 100644 (file)
@@ -51,7 +51,7 @@ static void expand_aggr_vbase_init ();
 void expand_member_init ();
 void expand_aggr_init ();
 
-static void expand_aggr_init_1 ();
+static void expand_aggr_init_1 PROTO((tree, tree, tree, tree, int, int));
 static void expand_virtual_init PROTO((tree, tree));
 tree expand_vec_init ();
 
@@ -152,8 +152,9 @@ expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
 /* Subroutine of emit_base_init.  */
 static void
 perform_member_init (member, name, init, explicit, protect_list)
-     tree member, name, init, *protect_list;
+     tree member, name, init;
      int explicit;
+     tree *protect_list;
 {
   tree decl;
   tree type = TREE_TYPE (member);
@@ -941,7 +942,7 @@ expand_member_init (exp, name, init)
 
   type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
 
-  if (TREE_CODE (name) == TYPE_DECL)
+  if (name && TREE_CODE (name) == TYPE_DECL)
     {
       basetype = TREE_TYPE (name);
       name = DECL_NAME (name);
@@ -2827,8 +2828,9 @@ build_new (placement, decl, init, use_global_new)
         not expanded as part of the RTL_EXPR for the initialization,
         so we can't just use save_expr here.  */
 
-      alloc_temp = get_temp_name (TREE_TYPE (rval), 0);
-      alloc_expr = build (MODIFY_EXPR, TREE_TYPE (rval), alloc_temp, rval);
+      alloc_temp = build (VAR_DECL, TREE_TYPE (rval));
+      layout_decl (alloc_temp, 0);
+      alloc_expr = build (TARGET_EXPR, TREE_TYPE (rval), alloc_temp, rval, 0);
       TREE_SIDE_EFFECTS (alloc_expr) = 1;
       rval = alloc_temp;
     }
index a1b841b..bbc8b04 100644 (file)
@@ -1650,7 +1650,7 @@ cons_up_default_function (type, full_name, kind)
       /* Fall through...  */
     case 6:
       retref = 1;
-      declspecs = build_decl_list (NULL_TREE, full_name);
+      declspecs = build_decl_list (NULL_TREE, type);
 
       name = ansi_opname [(int) MODIFY_EXPR];
 
index a417e1c..8d1bba7 100644 (file)
@@ -1073,49 +1073,14 @@ build_typename_overload (type)
   return id;
 }
 
-#ifndef NO_DOLLAR_IN_LABEL
-#define T_DESC_FORMAT "TD$"
-#define I_DESC_FORMAT "ID$"
-#define M_DESC_FORMAT "MD$"
-#else
-#if !defined(NO_DOT_IN_LABEL)
-#define T_DESC_FORMAT "TD."
-#define I_DESC_FORMAT "ID."
-#define M_DESC_FORMAT "MD."
-#else
-#define T_DESC_FORMAT "__t_desc_"
-#define I_DESC_FORMAT "__i_desc_"
-#define M_DESC_FORMAT "__m_desc_"
-#endif
-#endif
-
-/* Build an overload name for the type expression TYPE.  */
 tree
-build_t_desc_overload (type)
-     tree type;
+build_overload_with_type (name, type)
+     tree name, type;
 {
   OB_INIT ();
-  OB_PUTS (T_DESC_FORMAT);
+  OB_PUTID (name);
   nofold = 1;
 
-#if 0
-  /* Use a different format if the type isn't defined yet.  */
-  if (TYPE_SIZE (type) == NULL_TREE)
-    {
-      char *p;
-      int changed;
-
-      for (p = tname; *p; p++)
-       if (isupper (*p))
-         {
-           changed = 1;
-           *p = tolower (*p);
-         }
-      /* If there's no change, we have an inappropriate T_DESC_FORMAT.  */
-      my_friendly_assert (changed != 0, 249);
-    }
-#endif
-
   build_overload_name (type, 0, 1);
   return get_identifier (obstack_base (&scratch_obstack));
 }
@@ -1580,10 +1545,9 @@ hack_identifier (value, name)
         this field was initialized by a base initializer,
         we can emit an error message.  */
       TREE_USED (value) = 1;
-      return build_component_ref (C_C_D, name, 0, 1);
+      value = build_component_ref (C_C_D, name, 0, 1);
     }
-
-  if (really_overloaded_fn (value))
+  else if (really_overloaded_fn (value))
     {
 #if 0
       tree t = get_first_fn (value);
@@ -1668,12 +1632,7 @@ hack_identifier (value, name)
     }
 
   if (TREE_CODE (type) == REFERENCE_TYPE && ! current_template_parms)
-    {
-      my_friendly_assert (TREE_CODE (value) == VAR_DECL
-                         || TREE_CODE (value) == PARM_DECL
-                         || TREE_CODE (value) == RESULT_DECL, 252);
-      return convert_from_reference (value);
-    }
+    value = convert_from_reference (value);
   return value;
 }
 
index c4b58a4..c1e422b 100644 (file)
@@ -1185,7 +1185,7 @@ instantiate_class_template (type)
          require_complete_type (tmp);
 
       /* XXX handle attributes */
-      type = finish_struct_1 (type, 0, 0);
+      type = finish_struct_1 (type, NULL_TREE, 0);
     }
   else
     {
@@ -1578,7 +1578,7 @@ tsubst (t, args, nargs, in_decl)
        tree r = copy_node (t);
        TREE_TYPE (r) = type;
        DECL_CONTEXT (r) = current_class_type;
-       set_nested_typename (r, current_class_name, DECL_NAME (r), type);
+       set_nested_typename (r, current_class_type != NULL_TREE ? TYPE_NESTED_NAME (current_class_type) : current_class_name, DECL_NAME (r), type);
        TREE_CHAIN (r) = NULL_TREE;
        return r;
       }          
index bd6a0ac..75eff1d 100644 (file)
@@ -1,5 +1,6 @@
 /* RunTime Type Identification
    Copyright (C) 1995, 1996 Free Software Foundation, Inc.
+   Mostly written by Jason Merrill (jason@cygnus.com).
 
 This file is part of GNU CC.
 
@@ -32,16 +33,50 @@ extern tree define_function ();
 extern tree build_t_desc_overload ();
 extern struct obstack *permanent_obstack;
 
+tree type_info_type_node;
+tree tinfo_fn_id;
+tree tinfo_fn_type;
+
 /* in c-common.c */
 extern tree combine_strings PROTO((tree));
 \f
-/* Given the expression EXP of type `class *', return the head
-   of the object pointed to by EXP.  */
+void
+init_rtti_processing ()
+{
+  type_info_type_node = xref_tag
+    (class_type_node, get_identifier ("type_info"), NULL_TREE, 1);
+  tinfo_fn_id = get_identifier ("__tf");
+  tinfo_fn_type = build_function_type
+    (build_reference_type (build_type_variant (type_info_type_node, 1, 0)),
+     void_list_node);
+}
+
+/* Given a pointer to an object with at least one virtual table
+   pointer somewhere, return a pointer to a possible sub-object that
+   has a virtual table pointer in it that is the vtable parent for
+   that sub-object.  */
+static tree
+build_headof_sub (exp)
+     tree exp;
+{
+  tree type = TREE_TYPE (TREE_TYPE (exp));
+  tree basetype = CLASSTYPE_RTTI (type);
+  tree binfo = get_binfo (basetype, type, 0);
+
+  exp = convert_pointer_to_real (binfo, exp);
+  return exp;
+}
+
+/* Given the expression EXP of type `class *', return the head of the
+   object pointed to by EXP with type cv void*, if the class has any
+   virtual functions (TYPE_VIRTUAL_P), else just return the
+   expression.  */
 static tree
 build_headof (exp)
      tree exp;
 {
   tree type = TREE_TYPE (exp);
+  tree aref;
   tree vptr, offset;
 
   if (TREE_CODE (type) != POINTER_TYPE)
@@ -51,22 +86,22 @@ build_headof (exp)
     }
   type = TREE_TYPE (type);
 
-  if (!TYPE_VIRTUAL_P (type) || CLASSTYPE_VFIELD (type) == NULL_TREE)
+  if (!TYPE_VIRTUAL_P (type))
     return exp;
 
-  vptr = fold (size_binop (PLUS_EXPR, 
-          size_binop (FLOOR_DIV_EXPR, 
-            DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (type)),
-            size_int (BITS_PER_UNIT)),
-          exp)); 
-  vptr = build1 (INDIRECT_REF, build_pointer_type (vtable_entry_type), vptr);
+  /* If we don't have rtti stuff, get to a sub-object that does.  */
+  if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp))))
+    exp = build_headof_sub (exp);
+
+  /* We use this a couple of times below, protect it.  */
+  exp = save_expr (exp);
+
+  aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node);
 
   if (flag_vtable_thunks)
-    offset = build_array_ref (vptr, integer_zero_node);
+    offset = aref;
   else
-    offset = build_component_ref (build_array_ref (vptr, integer_zero_node),
-                                 delta_identifier,
-                                 NULL_TREE, 0);
+    offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0);
 
   type = build_type_variant (ptr_type_node, TREE_READONLY (exp),
                             TREE_THIS_VOLATILE (exp));
@@ -83,9 +118,6 @@ build_typeid (exp)
 {
   tree type;
 
-  if (!flag_rtti)
-    cp_error ("cannot take typeid of object when -frtti is not specified");
-
   if (exp == error_mark_node)
     return error_mark_node;
 
@@ -116,62 +148,181 @@ build_typeid (exp)
       /* build reference to type_info from vtable.  */
       tree t;
 
+      if (! flag_rtti)
+       warning ("taking dynamic typeid of object without -frtti");
+
+      /* If we don't have rtti stuff, get to a sub-object that does.  */
+      if (!CLASSTYPE_VFIELDS (TREE_TYPE (type)))
+       {
+         exp = build_unary_op (ADDR_EXPR, exp, 0);
+         exp = build_headof_sub (exp);
+         exp = build_indirect_ref (exp, NULL_PTR);
+       }
+
       if (flag_vtable_thunks)
-       t = build_vfn_ref ((tree *) NULL_TREE, exp, integer_one_node);
+       t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
       else
-       t = build_vfn_ref ((tree *) NULL_TREE, exp, integer_zero_node);
+       t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
+      TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);
 
-      TREE_TYPE (t) = build_pointer_type (__class_desc_type_node);
-      t = build_indirect_ref (t, NULL);
-      return t;
+      t = build (CALL_EXPR, TREE_TYPE (tinfo_fn_type), t, NULL_TREE, 0);
+      TREE_SIDE_EFFECTS (t) = 1;
+      return convert_from_reference (t);
     }
 
   /* otherwise return the type_info for the static type of the expr.  */
   return get_typeid (type);
 }
 
+tree
+get_tinfo_var (type)
+     tree type;
+{
+  tree tname = build_overload_with_type (get_identifier ("__ti"), type);
+  tree tdecl, arrtype;
+  int size;
+
+  if (IDENTIFIER_GLOBAL_VALUE (tname))
+    return IDENTIFIER_GLOBAL_VALUE (tname);
+    
+  /* Figure out how much space we need to allocate for the type_info object.
+     If our struct layout or the type_info classes are changed, this will
+     need to be modified.  */
+  if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
+    size = 4 * POINTER_SIZE;
+  else if (TREE_CODE (type) == POINTER_TYPE
+          && ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE
+                || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))
+    size = 3 * POINTER_SIZE;
+  else if (IS_AGGR_TYPE (type))
+    {
+      if (CLASSTYPE_N_BASECLASSES (type) == 0)
+       size = 2 * POINTER_SIZE;
+      else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
+              && (TREE_VIA_PUBLIC
+                  (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
+       size = 3 * POINTER_SIZE;
+      else
+       size = 4 * POINTER_SIZE;
+    }
+  else
+    size = 2 * POINTER_SIZE;
+
+  push_obstacks (&permanent_obstack, &permanent_obstack);
+
+  /* The type for a character array of the appropriate size.  */
+  arrtype = build_cplus_array_type
+    (unsigned_char_type_node,
+     build_index_type (size_int (size / BITS_PER_UNIT - 1)));
+
+  tdecl = build_decl (VAR_DECL, tname, arrtype);
+  TREE_PUBLIC (tdecl) = 1;
+  DECL_EXTERNAL (tdecl) = 1;
+  DECL_ARTIFICIAL (tdecl) = 1;
+  pushdecl_top_level (tdecl);
+  cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
+
+  pop_obstacks ();
+
+  return tdecl;
+}
+
+tree
+get_tinfo_fn (type)
+     tree type;
+{
+  tree name = build_overload_with_type (tinfo_fn_id, type);
+  tree d;
+
+  if (IDENTIFIER_GLOBAL_VALUE (name))
+    return IDENTIFIER_GLOBAL_VALUE (name);
+
+  push_obstacks (&permanent_obstack, &permanent_obstack);
+
+  d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type);
+  DECL_EXTERNAL (d) = 1;
+  TREE_PUBLIC (d) = 1;
+  DECL_ARTIFICIAL (d) = 1;
+  DECL_NOT_REALLY_EXTERN (d) = 1;
+  DECL_MUTABLE_P (d) = 1;
+  TREE_TYPE (name) = type;
+  pushdecl_top_level (d);
+  make_function_rtl (d);
+  mark_inline_for_output (d);
+  if (at_eof)
+    import_export_decl (d);
+
+  pop_obstacks ();
+
+  return d;
+}
+
+tree
+get_typeid_1 (type)
+     tree type;
+{
+  tree t = build (CALL_EXPR, TREE_TYPE (tinfo_fn_type),
+                 default_conversion (get_tinfo_fn (type)), NULL_TREE, 0);
+  TREE_SIDE_EFFECTS (t) = 1;
+  return convert_from_reference (t);
+}
+  
 /* Return the type_info object for TYPE, creating it if necessary.  */
 tree
 get_typeid (type)
      tree type;
 {
-  tree t, td;
+  tree t;
 
   if (type == error_mark_node)
     return error_mark_node;
   
-  /* Is it useful (and/or correct) to have different typeids for `T &'
-     and `T'?  */
+  /* If the type of the type-id is a reference type, the result of the
+     typeid expression refers to a type_info object representing the
+     referenced type.  */
   if (TREE_CODE (type) == REFERENCE_TYPE)
     type = TREE_TYPE (type);
 
-  td = build_t_desc (type, 1);
-  if (td == error_mark_node)
-    return error_mark_node;
+  /* The top-level cv-qualifiers of the lvalue expression or the type-id
+     that is the operand of typeid are always ignored. */
+  type = TYPE_MAIN_VARIANT (type);
 
-  t = TREE_OPERAND (td, 0);
-  return t;
+  return get_typeid_1 (type);
 }
 
 /* Get a bad_cast node for the program to throw...
 
-   See libstdc++::exception{,.cc} for __bad_cast_object */
+   See libstdc++/exception.cc for __throw_bad_cast */
+
 static tree
-get_bad_cast_node ()
+throw_bad_cast ()
 {
-  static tree t;
-  if (t == NULL_TREE
-      && (t = lookup_name (get_identifier ("__bad_cast_object"), 0))
-         == NULL_TREE)
-    {
-      error ("you must #include <typeinfo>");
-      return error_mark_node;
-    }
-  return t;
+  tree d = get_identifier ("__throw_bad_cast");
+  tree type;
+  
+  if (IDENTIFIER_GLOBAL_VALUE (d))
+    return IDENTIFIER_GLOBAL_VALUE (d);
+
+  push_obstacks (&permanent_obstack, &permanent_obstack);
+
+  type = build_function_type (void_type_node, void_list_node);
+  d = build_lang_decl (FUNCTION_DECL, d, type);
+  DECL_EXTERNAL (d) = 1;
+  TREE_PUBLIC (d) = 1;
+  DECL_ARTIFICIAL (d) = 1;
+  pushdecl_top_level (d);
+  make_function_rtl (d);
+
+  pop_obstacks ();
+
+  d = build (CALL_EXPR, void_type_node, default_conversion (d), NULL_TREE, 0);
+  TREE_SIDE_EFFECTS (d) = 1;
+  return d;
 }
 
 /* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working
    paper.  */
+
 tree
 build_dynamic_cast (type, expr)
      tree type, expr;
@@ -179,6 +330,7 @@ build_dynamic_cast (type, expr)
   enum tree_code tc = TREE_CODE (type);
   tree exprtype = TREE_TYPE (expr);
   enum tree_code ec = TREE_CODE (exprtype);
+  tree dcast_fn;
 
   if (type == error_mark_node || expr == error_mark_node)
     return error_mark_node;
@@ -264,12 +416,15 @@ build_dynamic_cast (type, expr)
              && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)
            return build1 (NOP_EXPR, type, expr);
 
-         return build_headof (expr);
+         expr = build_headof (expr);
+         if (TREE_TYPE (expr) != type)
+           expr = build1 (NOP_EXPR, type, expr);
+         return expr;
        }
       else
        {
          tree retval;
-          tree result, td1, td2, elems, expr1;
+          tree result, td1, td2, td3, elems, expr1, expr2;
 
          /* If we got here, we can't convert statically.  Therefore,
             dynamic_cast<D&>(b) (b an object) cannot succeed.  */
@@ -280,7 +435,7 @@ build_dynamic_cast (type, expr)
                {
                  cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",
                              expr, type);
-                 return build_throw (get_bad_cast_node ());
+                 return throw_bad_cast ();
                }
            }
          /* Ditto for dynamic_cast<D*>(&b).  */
@@ -298,29 +453,66 @@ build_dynamic_cast (type, expr)
                }
            }
 
+         /* Since expr is used twice below, save it.  */
+         expr = save_expr (expr);
+
          expr1 = expr;
          if (tc == REFERENCE_TYPE)
            expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
 
          /* Build run-time conversion.  */
-         expr1 = build_headof (expr1);
+         expr2 = build_headof (expr1);
 
          if (ec == POINTER_TYPE)
            td1 = build_typeid (build_indirect_ref (expr, NULL_PTR));
          else
            td1 = build_typeid (expr);
          
-         td2 = get_typeid (TYPE_MAIN_VARIANT (TREE_TYPE (type)));
-
-          elems = tree_cons (NULL_TREE, td2,
-            tree_cons (NULL_TREE, build_int_2 (1, 0),
-             tree_cons (NULL_TREE, expr1, NULL_TREE)));
-          result = build_method_call (td1,
-            get_identifier ("__rtti_match"), elems, NULL_TREE, LOOKUP_NORMAL);
+         td2 = get_typeid (TREE_TYPE (type));
+         td3 = get_typeid (TREE_TYPE (exprtype));
+
+          elems = tree_cons
+           (NULL_TREE, TREE_OPERAND (td1, 0), tree_cons
+            (NULL_TREE, TREE_OPERAND (td2, 0), tree_cons
+             (NULL_TREE, build_int_2 (1, 0), tree_cons
+              (NULL_TREE, expr2, tree_cons
+               (NULL_TREE, TREE_OPERAND (td3, 0), tree_cons
+                (NULL_TREE, expr1, NULL_TREE))))));
+
+         dcast_fn = get_identifier ("__dynamic_cast");
+         if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))
+           dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);
+         else
+           {
+             tree tmp;
+
+             push_obstacks (&permanent_obstack, &permanent_obstack);
+             tmp = build_reference_type
+               (build_type_variant (type_info_type_node, 1, 0));
+             tmp = tree_cons
+               (NULL_TREE, tmp, tree_cons
+                (NULL_TREE, tmp, tree_cons
+                 (NULL_TREE, integer_type_node, tree_cons
+                  (NULL_TREE, ptr_type_node, tree_cons
+                   (NULL_TREE, tmp, tree_cons
+                    (NULL_TREE, ptr_type_node, void_list_node))))));
+             tmp = build_function_type (ptr_type_node, tmp);
+             dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);
+             DECL_EXTERNAL (dcast_fn) = 1;
+             TREE_PUBLIC (dcast_fn) = 1;
+             DECL_ARTIFICIAL (dcast_fn) = 1;
+             pushdecl_top_level (dcast_fn);
+             make_function_rtl (dcast_fn);
+             pop_obstacks ();
+           }
+         
+          result = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (dcast_fn)),
+                         decay_conversion (dcast_fn), elems, 0);
+         TREE_SIDE_EFFECTS (result) = 1;
 
          if (tc == REFERENCE_TYPE)
            {
-             expr1 = build_throw (get_bad_cast_node ());
+             expr1 = throw_bad_cast ();
              expr1 = build_compound_expr (tree_cons (NULL_TREE, expr1,
                                                      build_tree_list (NULL_TREE, convert (type, integer_zero_node))));
              TREE_TYPE (expr1) = type;
@@ -354,129 +546,67 @@ build_dynamic_cast (type, expr)
    Note: these constructors always return the address of the descriptor
    info, since that is simplest for their mutual interaction.  */
 
-static tree
-build_generic_desc (tdecl, type, elems)
-     tree tdecl;
-     tree type;
-     tree elems;
-{
-  tree init = elems;
-  int toplev = global_bindings_p ();
+extern tree const_string_type_node;
 
-  TREE_CONSTANT (init) = 1;
-  TREE_STATIC (init) = 1;
-  TREE_READONLY (init) = 1;
+/* Build an initializer for a __si_type_info node.  */
 
-  TREE_TYPE (tdecl) = type;
-  DECL_INITIAL (tdecl) = init;
-  TREE_STATIC (tdecl) = 1;
-  DECL_SIZE (tdecl) = NULL_TREE;
-  layout_decl (tdecl, 0);
-  if (! toplev)
-    push_to_top_level ();
-  cp_finish_decl (tdecl, init, NULL_TREE, 0, 0);
-  if (! toplev)
-    pop_from_top_level ();
-
-  if (! TREE_USED (tdecl))
-    {
-      assemble_external (tdecl);
-      TREE_USED (tdecl) = 1;
-    }
-
-  return IDENTIFIER_AS_DESC (DECL_NAME (tdecl));
-}
-
-/* Build an initializer for a __bltn_desc node.  */
-static tree
-build_bltn_desc (tdecl, type)
+static void
+expand_si_desc (tdecl, type)
      tree tdecl;
      tree type;
 {
-  tree elems, t;
-
-  if (type == boolean_type_node)
-    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_BOOL"),
-                     0, 0);
-  else if (type == char_type_node)
-    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_CHAR"),
-                     0, 0);
-  else if (type == short_integer_type_node)
-    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_SHORT"),
-                     0, 0);
-  else if (type == integer_type_node)
-    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_INT"),
-                     0, 0);
-  else if (type == long_integer_type_node)
-    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_LONG"),
-                     0, 0);
-  else if (type == long_long_integer_type_node)
-    t = lookup_field (__bltn_desc_type_node, 
-                     get_identifier("_RTTI_BI_LONGLONG"), 0, 0);
-  else if (type == float_type_node)
-    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_FLOAT"),
-                     0, 0);
-  else if (type == double_type_node)
-    t = lookup_field (__bltn_desc_type_node, 
-                     get_identifier("_RTTI_BI_DOUBLE"), 0, 0);
-  else if (type == long_double_type_node)
-    t = lookup_field (__bltn_desc_type_node, 
-                     get_identifier("_RTTI_BI_LDOUBLE"), 0, 0);
-  else if (type == unsigned_char_type_node)
-    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_UCHAR"),
-                     0, 0);
-  else if (type == short_unsigned_type_node)
-    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_USHORT"),
-                     0, 0);
-  else if (type == unsigned_type_node)
-    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_UINT"),
-                     0, 0);
-  else if (type == long_unsigned_type_node)
-    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_ULONG"),
-                     0, 0);
-  else if (type == long_long_unsigned_type_node)
-    t = lookup_field (__bltn_desc_type_node, 
-                     get_identifier("_RTTI_BI_ULONGLONG"), 0, 0);
-  else if (type == signed_char_type_node)
-    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_SCHAR"),
-                     0, 0);
-  else if (type == wchar_type_node)
-    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_WCHAR"),
-                     0, 0);
-  else if (type == void_type_node)
-    t = lookup_field (__bltn_desc_type_node, get_identifier("_RTTI_BI_VOID"),
-                     0, 0);
+  tree t, elems, fn;
+  char *name = build_overload_name (type, 1, 1);
+  tree name_string = combine_strings (build_string (strlen (name), name));
+
+  type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));
+  expand_expr_stmt (get_typeid_1 (type));
+  t = decay_conversion (get_tinfo_var (type));
+  elems = tree_cons
+    (NULL_TREE, decay_conversion (tdecl), tree_cons
+     (NULL_TREE, decay_conversion (name_string), tree_cons
+      (NULL_TREE, t, NULL_TREE)));
+
+  fn = get_identifier ("__rtti_si");
+  if (IDENTIFIER_GLOBAL_VALUE (fn))
+    fn = IDENTIFIER_GLOBAL_VALUE (fn);
   else
     {
-      cp_compiler_error ("type `%T' not handled as a built-in type");
+      tree tmp;
+      push_obstacks (&permanent_obstack, &permanent_obstack);
+      tmp = tree_cons
+       (NULL_TREE, ptr_type_node, tree_cons
+        (NULL_TREE, const_string_type_node, tree_cons
+         (NULL_TREE, build_pointer_type (type_info_type_node),
+          void_list_node)));
+      tmp = build_function_type        (void_type_node, tmp);
+  
+      fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
+      DECL_EXTERNAL (fn) = 1;
+      TREE_PUBLIC (fn) = 1;
+      DECL_ARTIFICIAL (fn) = 1;
+      pushdecl_top_level (fn);
+      make_function_rtl (fn);
+      pop_obstacks ();
     }
 
-  elems = tree_cons (NULL_TREE, t, NULL_TREE);
-  return build_generic_desc (tdecl, __bltn_desc_type_node, elems);
-}
-
-/* Build an initializer for a __user_desc node.  */
-static tree
-build_user_desc (tdecl)
-     tree tdecl;
-{
-  tree elems, name_string;
-  tree tname = DECL_NAME (tdecl);
-
-  name_string = combine_strings (build_string 
-    (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
-  elems = name_string;
-  return build_generic_desc (tdecl, __user_desc_type_node, elems);
+  fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+             decay_conversion (fn), elems, 0);
+  TREE_SIDE_EFFECTS (fn) = 1;
+  expand_expr_stmt (fn);
 }
 
 /* Build an initializer for a __class_type_info node. */
-static tree
-build_class_desc (tdecl, type)
+
+static void
+expand_class_desc (tdecl, type)
      tree tdecl;
      tree type;
 {
-  tree tname = DECL_NAME (tdecl);
+  tree tname = TYPE_NESTED_NAME (type);
   tree name_string;
+  tree fn, tmp;
+  char *name;
 
   int i = CLASSTYPE_N_BASECLASSES (type);
   int base_cnt = 0;
@@ -487,30 +617,50 @@ build_class_desc (tdecl, type)
   int n_base = i;
 #endif
   tree base, elems, access, offset, isvir;
-  tree base_list, off_list, acc_list, isvir_list;
-  static tree acc_pub = NULL_TREE;
-  static tree acc_pro = NULL_TREE;
-  static tree acc_pri = NULL_TREE;
+  tree elt, elts = NULL_TREE;
+  static tree base_info_type_node;
 
-  if (acc_pub == NULL_TREE) 
+  if (base_info_type_node == NULL_TREE)
     {
-      acc_pub = lookup_field (__class_desc_type_node, 
-                                get_identifier("_RTTI_ACCESS_PUBLIC"), 0, 0);
-      acc_pro = lookup_field (__class_desc_type_node,
-                                get_identifier("_RTTI_ACCESS_PROTECTED"), 0, 0);
-      acc_pri = lookup_field (__class_desc_type_node,
-                                get_identifier("_RTTI_ACCESS_PRIVATE"), 0, 0);
+      tree fields [4];
+
+      /* A reasonably close approximation of __class_type_info::base_info */
+
+      push_obstacks (&permanent_obstack, &permanent_obstack);
+      base_info_type_node = make_lang_type (RECORD_TYPE);
+
+      /* Actually const __user_type_info * */
+      fields [0] = build_lang_field_decl
+       (FIELD_DECL, NULL_TREE,
+        build_pointer_type (build_type_variant (type_info_type_node, 1, 0)));
+      fields [1] = build_lang_field_decl
+       (FIELD_DECL, NULL_TREE, sizetype);
+      DECL_BIT_FIELD (fields[1]) = 1;
+      DECL_FIELD_SIZE (fields[1]) = 29;
+
+      fields [2] = build_lang_field_decl
+       (FIELD_DECL, NULL_TREE, boolean_type_node);
+      DECL_BIT_FIELD (fields[2]) = 1;
+      DECL_FIELD_SIZE (fields[2]) = 1;
+
+      /* Actually enum access */
+      fields [3] = build_lang_field_decl
+       (FIELD_DECL, NULL_TREE, integer_type_node);
+      DECL_BIT_FIELD (fields[3]) = 1;
+      DECL_FIELD_SIZE (fields[3]) = 2;
+
+      finish_builtin_type (base_info_type_node, "__base_info", fields,
+                          3, ptr_type_node);
+      pop_obstacks ();
     }
 
-  base_list = build_tree_list (NULL_TREE, integer_zero_node);
-  off_list = build_tree_list (NULL_TREE, integer_zero_node);
-  acc_list = build_tree_list (NULL_TREE, integer_zero_node);
-  isvir_list = build_tree_list (NULL_TREE, integer_zero_node);
   while (--i >= 0)
     {
       tree binfo = TREE_VEC_ELT (binfos, i);
 
-      base = build_t_desc (BINFO_TYPE (binfo), 1);
+      expand_expr_stmt (get_typeid_1 (BINFO_TYPE (binfo)));
+      base = decay_conversion (get_tinfo_var (BINFO_TYPE (binfo)));
+
       if (TREE_VIA_VIRTUAL (binfo))
        {
          tree t = BINFO_TYPE (binfo);
@@ -527,20 +677,24 @@ build_class_desc (tdecl, type)
        offset = BINFO_OFFSET (binfo);
 
       if (TREE_VIA_PUBLIC (binfo))
-        access = acc_pub;
+        access = access_public_node;
       else if (TREE_VIA_PROTECTED (binfo))
-       access = acc_pro;
+       access = access_protected_node;
       else
-       access = acc_pri;
+       access = access_private_node;
       if (TREE_VIA_VIRTUAL (binfo))
-       isvir = build_int_2 (1, 0);
+       isvir = boolean_true_node;
       else
-       isvir = build_int_2 (0, 0);
-
-      base_list = tree_cons (NULL_TREE, base, base_list);
-      isvir_list = tree_cons (NULL_TREE, isvir, isvir_list);
-      acc_list = tree_cons (NULL_TREE, access, acc_list);
-      off_list = tree_cons (NULL_TREE, offset, off_list);
+       isvir = boolean_false_node;
+
+      elt = build
+       (CONSTRUCTOR, base_info_type_node, NULL_TREE, tree_cons
+        (NULL_TREE, base, tree_cons
+         (NULL_TREE, offset, tree_cons
+          (NULL_TREE, isvir, tree_cons
+           (NULL_TREE, access, NULL_TREE)))));
+      TREE_HAS_CONSTRUCTOR (elt) = TREE_CONSTANT (elt) = TREE_STATIC (elt) = 1;
+      elts = tree_cons (NULL_TREE, elt, elts);
       base_cnt++;
     }
 #if 0
@@ -548,18 +702,18 @@ build_class_desc (tdecl, type)
   while (vb)
     {
       tree b;
-      access = acc_pub;
+      access = access_public_node;
       while (--i >= 0)
        {
          b = TREE_VEC_ELT (binfos, i);
          if (BINFO_TYPE (vb) == BINFO_TYPE (b) && TREE_VIA_VIRTUAL (b))
            {
              if (TREE_VIA_PUBLIC (b))
-               access = acc_pub;
+               access = access_public_node;
              else if (TREE_VIA_PROTECTED (b))
-               access = acc_pro;
+               access = access_protected_node;
              else
-               access = acc_pri;
+               access = access_private_node;
              break;
            }
        }
@@ -576,278 +730,271 @@ build_class_desc (tdecl, type)
       vb = TREE_CHAIN (vb);
     }
 #endif
-  base_list = finish_table (NULL_TREE, build_pointer_type (__t_desc_type_node), 
-                           base_list, 0);
-  off_list = finish_table (NULL_TREE, integer_type_node, 
-                           off_list, 0);
-  isvir_list = finish_table (NULL_TREE, integer_type_node, 
-                           isvir_list, 0);
-  acc_list = finish_table (NULL_TREE, __access_mode_type_node, 
-                           acc_list, 0);
-
 
-  name_string = combine_strings (build_string (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
+  name = build_overload_name (type, 1, 1);
+  name_string = combine_strings (build_string (strlen (name), name));
 
-  elems = tree_cons (NULL_TREE, name_string,
-           tree_cons (NULL_TREE, default_conversion (base_list),
-             tree_cons (NULL_TREE, default_conversion (off_list),
-               tree_cons (NULL_TREE, default_conversion (isvir_list),
-                 tree_cons (NULL_TREE, default_conversion (acc_list),
-                   tree_cons (NULL_TREE, build_int_2 (base_cnt, 0), NULL_TREE))))));
+  {
+    tree arrtype = build_array_type (base_info_type_node, NULL_TREE);
+    elts = build (CONSTRUCTOR, arrtype, NULL_TREE, elts);
+    TREE_HAS_CONSTRUCTOR (elts) = TREE_CONSTANT (elts) =
+      TREE_STATIC (elts) = 1;
+    complete_array_type (arrtype, elts, 1);
+  }
 
-  return build_generic_desc (tdecl, __class_desc_type_node, elems);
-}
+  elems = tree_cons
+    (NULL_TREE, decay_conversion (tdecl), tree_cons
+     (NULL_TREE, decay_conversion (name_string), tree_cons
+      (NULL_TREE, decay_conversion (elts), tree_cons
+       (NULL_TREE, build_int_2 (base_cnt, 0), NULL_TREE))));
 
-/* Build an initializer for a __pointer_type_info node.  */
-static tree
-build_ptr_desc (tdecl, type)
-     tree tdecl;
-     tree type;
-{
-  tree t, elems;
+  fn = get_identifier ("__rtti_class");
+  if (IDENTIFIER_GLOBAL_VALUE (fn))
+    fn = IDENTIFIER_GLOBAL_VALUE (fn);
+  else
+    {
+      push_obstacks (&permanent_obstack, &permanent_obstack);
+      tmp = tree_cons
+       (NULL_TREE, ptr_type_node, tree_cons
+        (NULL_TREE, const_string_type_node, tree_cons
+         (NULL_TREE, build_pointer_type (base_info_type_node), tree_cons
+          (NULL_TREE, sizetype, void_list_node))));
+      tmp = build_function_type        (void_type_node, tmp);
+  
+      fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
+      DECL_EXTERNAL (fn) = 1;
+      TREE_PUBLIC (fn) = 1;
+      DECL_ARTIFICIAL (fn) = 1;
+      pushdecl_top_level (fn);
+      make_function_rtl (fn);
+      pop_obstacks ();
+    }
 
-  t = TREE_TYPE (type);
-  t = build_t_desc (t, 1);
-  t = build_indirect_ref (t, NULL);
-  elems = tree_cons (NULL_TREE, t, NULL_TREE);
-  return build_generic_desc (tdecl, __ptr_desc_type_node,  elems);
+  fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+             decay_conversion (fn), elems, 0);
+  TREE_SIDE_EFFECTS (fn) = 1;
+  expand_expr_stmt (fn);
 }
 
-/* Build an initializer for a __attr_type_info node.  */
-static tree
-build_attr_desc (tdecl, type)
+/* Build an initializer for a __pointer_type_info node.  */
+static void
+expand_ptr_desc (tdecl, type)
      tree tdecl;
      tree type;
 {
-  tree elems, t, attrval;
+  tree t, elems, fn;
+  char *name = build_overload_name (type, 1, 1);
+  tree name_string = combine_strings (build_string (strlen (name), name));
 
-  if (TYPE_READONLY (type))
-    {
-      if (TYPE_VOLATILE (type))
-       attrval = lookup_field (__attr_desc_type_node, 
-                               get_identifier("_RTTI_ATTR_CONSTVOL"), 0, 0);
-      else
-       attrval = lookup_field (__attr_desc_type_node, 
-                               get_identifier("_RTTI_ATTR_CONST"), 0, 0);
-    }
+  type = TREE_TYPE (type);
+  expand_expr_stmt (get_typeid_1 (type));
+  t = decay_conversion (get_tinfo_var (type));
+  elems = tree_cons
+    (NULL_TREE, decay_conversion (tdecl), tree_cons
+     (NULL_TREE, decay_conversion (name_string), tree_cons
+      (NULL_TREE, t, NULL_TREE)));
+
+  fn = get_identifier ("__rtti_ptr");
+  if (IDENTIFIER_GLOBAL_VALUE (fn))
+    fn = IDENTIFIER_GLOBAL_VALUE (fn);
   else
     {
-      if (TYPE_VOLATILE (type))
-       attrval = lookup_field (__attr_desc_type_node, 
-                               get_identifier("_RTTI_ATTR_VOLATILE"), 0, 0);
+      tree tmp;
+      push_obstacks (&permanent_obstack, &permanent_obstack);
+      tmp = tree_cons
+       (NULL_TREE, ptr_type_node, tree_cons
+        (NULL_TREE, const_string_type_node, tree_cons
+         (NULL_TREE, build_pointer_type (type_info_type_node),
+          void_list_node)));
+      tmp = build_function_type        (void_type_node, tmp);
+  
+      fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
+      DECL_EXTERNAL (fn) = 1;
+      TREE_PUBLIC (fn) = 1;
+      DECL_ARTIFICIAL (fn) = 1;
+      pushdecl_top_level (fn);
+      make_function_rtl (fn);
+      pop_obstacks ();
     }
-  t = build_t_desc (TYPE_MAIN_VARIANT (type), 1);
-  t = build_indirect_ref (t , NULL);
-  elems = tree_cons (NULL_TREE, attrval, tree_cons (NULL_TREE, t, NULL_TREE));
-  return build_generic_desc (tdecl, __attr_desc_type_node,  elems);
-}
-
-/* Build an initializer for a __func_type_info node.  */
-static tree
-build_func_desc (tdecl)
-     tree tdecl;
-{
-  tree elems, name_string;
-  tree tname = DECL_NAME (tdecl);
 
-  name_string = combine_strings (build_string 
-    (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
-  elems = name_string; 
-  return build_generic_desc (tdecl, __func_desc_type_node,  elems);
+  fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+             decay_conversion (fn), elems, 0);
+  TREE_SIDE_EFFECTS (fn) = 1;
+  expand_expr_stmt (fn);
 }
 
-/* Build an initializer for a __ptmf_type_info node.  */
-static tree
-build_ptmf_desc (tdecl)
-     tree tdecl;
-{ 
-  tree elems, name_string;
-  tree tname = DECL_NAME (tdecl);
-
-  name_string = combine_strings (build_string 
-    (IDENTIFIER_LENGTH (tname)+1, IDENTIFIER_POINTER (tname)));
-  elems = name_string; 
-  return build_generic_desc (tdecl, __ptmf_desc_type_node,  elems);
-}
-
-/* Build an initializer for a __ptmd_type_info node.  */
-static tree
-build_ptmd_desc (tdecl, type)
-     tree tdecl;
-     tree type;
-{
-  tree tc, t, elems;
-  tc = build_t_desc (TYPE_OFFSET_BASETYPE (type), 1);
-  tc = build_indirect_ref (tc , NULL);
-  t = build_t_desc (TREE_TYPE (type), 1);
-  t = build_indirect_ref (t , NULL);
-  elems = tree_cons (NULL_TREE, tc,
-           tree_cons (NULL_TREE, t, NULL_TREE));
-  return build_generic_desc (tdecl, __ptmd_desc_type_node,  elems);
-}
-
-struct uninst_st {
-  tree type;
-  struct uninst_st *next;
-};
-typedef struct uninst_st uninst_node;
-static uninst_node * uninst_desc = (uninst_node *)NULL;
+/* Build an initializer for a __attr_type_info node.  */
 
 static void
-add_uninstantiated_desc (type)
+expand_attr_desc (tdecl, type)
+     tree tdecl;
      tree type;
 {
-  uninst_node *t;
+  tree elems, t, fn;
+  char *name = build_overload_name (type, 1, 1);
+  tree name_string = combine_strings (build_string (strlen (name), name));
+  tree attrval = build_int_2
+    (TYPE_READONLY (type) | TYPE_VOLATILE (type) * 2, 0);
+
+  expand_expr_stmt (get_typeid_1 (TYPE_MAIN_VARIANT (type)));
+  t = decay_conversion (get_tinfo_var (TYPE_MAIN_VARIANT (type)));
+  elems = tree_cons
+    (NULL_TREE, decay_conversion (tdecl), tree_cons
+     (NULL_TREE, decay_conversion (name_string), tree_cons
+      (NULL_TREE, attrval, tree_cons (NULL_TREE, t, NULL_TREE))));
+
+  fn = get_identifier ("__rtti_attr");
+  if (IDENTIFIER_GLOBAL_VALUE (fn))
+    fn = IDENTIFIER_GLOBAL_VALUE (fn);
+  else
+    {
+      tree tmp;
+      push_obstacks (&permanent_obstack, &permanent_obstack);
+      tmp = tree_cons
+       (NULL_TREE, ptr_type_node, tree_cons
+        (NULL_TREE, const_string_type_node, tree_cons
+         (NULL_TREE, integer_type_node, tree_cons
+          (NULL_TREE, build_pointer_type (type_info_type_node),
+           void_list_node))));
+      tmp = build_function_type        (void_type_node, tmp);
+  
+      fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
+      DECL_EXTERNAL (fn) = 1;
+      TREE_PUBLIC (fn) = 1;
+      DECL_ARTIFICIAL (fn) = 1;
+      pushdecl_top_level (fn);
+      make_function_rtl (fn);
+      pop_obstacks ();
+    }
 
-  t = (uninst_node *) xmalloc (sizeof (struct uninst_st));
-  t->type = type;
-  t->next = uninst_desc;
-  uninst_desc = t;
+  fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+             decay_conversion (fn), elems, 0);
+  TREE_SIDE_EFFECTS (fn) = 1;
+  expand_expr_stmt (fn);
 }
 
-/* We may choose to link the emitting of certain high use TDs for certain
-   objects, we do that here.  Return the type to link against if such a
-   link exists, otherwise just return TYPE.  */
+/* Build an initializer for a type_info node that just has a name.  */
 
-static tree
-get_def_to_follow (type)
-     tree type;
-{
-#if 0
-  /* For now we don't lay out T&, T* TDs with the main TD for the object.  */
-  /* Let T* and T& be written only when T is written (if T is an aggr).
-     We do this for const, but not for volatile, since volatile
-     is rare and const is not.  */
-  if (!TYPE_VOLATILE (taggr)
-      && (TREE_CODE (taggr) == POINTER_TYPE
-         || TREE_CODE (taggr) == REFERENCE_TYPE)
-      && IS_AGGR_TYPE (TREE_TYPE (taggr)))
-    taggr = TREE_TYPE (taggr);
-#endif
-  return type;
-}
-
-/* build a general type_info node. */
-tree
-build_t_desc (type, definition)
+static void
+expand_generic_desc (tdecl, type, fnname)
+     tree tdecl;
      tree type;
-     int definition;
+     char *fnname;
 {
-  tree tdecl, tname;
-  tree t, taggr;
-
-  if (__ptmd_desc_type_node == NULL_TREE)
-    {
-      init_type_desc();
-      if (__ptmd_desc_type_node)
-       {
-          for ( ; uninst_desc; uninst_desc = uninst_desc->next )
-           build_t_desc (uninst_desc->type, 1);
-       }
-    }
-  if (__t_desc_type_node == NULL_TREE)
-    {
-      static int warned = 0;
-      if (! warned)
-       {
-         cp_error ("failed to build type descriptor node of '%T', maybe <typeinfo> not included", type);
-       }
-      warned = 1;
-      return error_mark_node;
-    }
-  if (__ptmd_desc_type_node == NULL_TREE)
-    {
-      add_uninstantiated_desc (type);
-      definition = 0;
-    }
-
-  push_obstacks (&permanent_obstack, &permanent_obstack);
-  tname = build_t_desc_overload (type);
-
-  if (!IDENTIFIER_AS_DESC (tname))
+  char *name = build_overload_name (type, 1, 1);
+  tree name_string = combine_strings (build_string (strlen (name), name));
+  tree elems = tree_cons
+    (NULL_TREE, decay_conversion (tdecl), tree_cons
+     (NULL_TREE, decay_conversion (name_string), NULL_TREE));
+
+  tree fn = get_identifier (fnname);
+  if (IDENTIFIER_GLOBAL_VALUE (fn))
+    fn = IDENTIFIER_GLOBAL_VALUE (fn);
+  else
     {
-      tdecl = build_decl (VAR_DECL, tname, __t_desc_type_node);
-      DECL_EXTERNAL (tdecl) = 1;
-      TREE_PUBLIC (tdecl) = 1;
-      tdecl = pushdecl_top_level (tdecl);
-      SET_IDENTIFIER_AS_DESC (tname, build_unary_op (ADDR_EXPR, tdecl, 0));
-      if (!definition)
-       cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
+      tree tmp;
+      push_obstacks (&permanent_obstack, &permanent_obstack);
+      tmp = tree_cons
+       (NULL_TREE, ptr_type_node, tree_cons
+        (NULL_TREE, const_string_type_node, void_list_node));
+      tmp = build_function_type (void_type_node, tmp);
+  
+      fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
+      DECL_EXTERNAL (fn) = 1;
+      TREE_PUBLIC (fn) = 1;
+      DECL_ARTIFICIAL (fn) = 1;
+      pushdecl_top_level (fn);
+      make_function_rtl (fn);
+      pop_obstacks ();
     }
-  else
-    tdecl = TREE_OPERAND (IDENTIFIER_AS_DESC (tname), 0);
 
-  /* If it's not a definition, don't do anything more.  */
-  if (!definition)
-    return IDENTIFIER_AS_DESC (tname);
+  fn = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+             decay_conversion (fn), elems, 0);
+  TREE_SIDE_EFFECTS (fn) = 1;
+  expand_expr_stmt (fn);
+}
 
-  /* If it has already been written, don't to anything more.  */
-  /* Should this be on tdecl? */
-  if (TREE_ASM_WRITTEN (IDENTIFIER_AS_DESC (tname)))
-    return IDENTIFIER_AS_DESC (tname);
+/* Generate the code for a type_info initialization function.
+   Note that we take advantage of the passage
 
-  /* If we previously defined it, return the defined result.  */
-  if (DECL_INITIAL (tdecl))
-    return IDENTIFIER_AS_DESC (tname);
-    
-  taggr = get_def_to_follow (type);
+   5.2.7  Type identification                               [expr.typeid]
+   
+   Whether or not the destructor is called for the type_info object at the
+   end of the program is unspecified.
 
-  /* If we know that we don't need to write out this type's
-     vtable, then don't write out it's type_info.  Somebody
-     else will take care of that.  */
-  if (IS_AGGR_TYPE (taggr) && CLASSTYPE_VFIELD (taggr))
-    {
-      /* Let's play follow the vtable. */
-      TREE_PUBLIC (tdecl) = CLASSTYPE_INTERFACE_KNOWN (taggr);
-      DECL_EXTERNAL (tdecl) = CLASSTYPE_INTERFACE_ONLY (taggr);
-    }
-  else
-    {
-      DECL_EXTERNAL (tdecl) = 0;
-      TREE_PUBLIC (tdecl) = (definition > 1);
-    }
+   and don't bother to arrange for these objects to be destroyed.  It
+   doesn't matter, anyway, since the destructors don't do anything.
+       
+   This must only be called from toplevel (i.e. from finish_file)!  */
 
-  if (DECL_EXTERNAL (tdecl))
-    return IDENTIFIER_AS_DESC (tname);
+void
+synthesize_tinfo_fn (fndecl)
+     tree fndecl;
+{
+  tree type = TREE_TYPE (DECL_NAME (fndecl));
+  tree tmp, addr;
 
-  /* Show that we are defining the t_desc for this type.  */
-  DECL_INITIAL (tdecl) = error_mark_node;
-  t = DECL_CONTEXT (tdecl);
-  if ( t && TREE_CODE_CLASS (TREE_CODE (t)) == 't') 
-    pushclass (t, 2);
+  tree tdecl = get_tinfo_var (type);
+  DECL_EXTERNAL (tdecl) = 0;
+  TREE_STATIC (tdecl) = 1;
+  DECL_COMMON (tdecl) = 1;
+  TREE_USED (tdecl) = 1;
+  DECL_ALIGN (tdecl) = TYPE_ALIGN (ptr_type_node);
+  cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);
+
+  start_function (NULL_TREE, fndecl, NULL_TREE, NULL_TREE, 1);
+  store_parm_decls ();
+  clear_last_expr ();
+  push_momentary ();
+
+  /* If the first word of the array (the vtable) is non-zero, we've already
+     initialized the object, so don't do it again.  */
+  addr = decay_conversion (tdecl);
+  tmp = convert (build_pointer_type (ptr_type_node), addr);
+  tmp = build_indirect_ref (tmp, 0);
+  tmp = build_binary_op (EQ_EXPR, tmp, integer_zero_node, 1);
+  expand_start_cond (tmp, 0);
 
   if (TYPE_VOLATILE (type) || TYPE_READONLY (type))
-    t = build_attr_desc (tdecl, type);
+    expand_attr_desc (tdecl, type);
   else if (TREE_CODE (type) == ARRAY_TYPE)
-    t = build_ptr_desc (tdecl, type);
+    expand_generic_desc (tdecl, type, "__rtti_array");
   else if (TREE_CODE (type) == POINTER_TYPE)
     {
       if (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE)
-       {
-         type = TREE_TYPE (type);
-         t = build_ptmd_desc (tdecl, type);
-       }
+       expand_generic_desc (tdecl, type, "__rtti_ptmd");
+      else if (TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
+       expand_generic_desc (tdecl, type, "__rtti_ptmf");
       else
-       {
-         t = build_ptr_desc (tdecl, type);
-       }
+       expand_ptr_desc (tdecl, type);
     }
-  else if (TYPE_BUILT_IN (type))
-    t = build_bltn_desc (tdecl, type);
+  else if (TYPE_PTRMEMFUNC_P (type))
+    expand_generic_desc (tdecl, type, "__rtti_ptmf");
   else if (IS_AGGR_TYPE (type))
     {
-      if (TYPE_PTRMEMFUNC_P (type))
-       t = build_ptmf_desc (tdecl);
+      if (CLASSTYPE_N_BASECLASSES (type) == 0)
+       expand_generic_desc (tdecl, type, "__rtti_user");
+      else if (! TYPE_USES_COMPLEX_INHERITANCE (type)
+              && (TREE_VIA_PUBLIC
+                  (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))
+       expand_si_desc (tdecl, type);
       else
-       t = build_class_desc (tdecl, type);
+       expand_class_desc (tdecl, type);
     }
+  else if (TREE_CODE (type) == ENUMERAL_TYPE)
+    expand_generic_desc (tdecl, type, "__rtti_user");
   else if (TREE_CODE (type) == FUNCTION_TYPE)
-    t = build_func_desc (tdecl);
-  else 
-    t = build_user_desc (tdecl);
+    expand_generic_desc (tdecl, type, "__rtti_func");
+  else
+    my_friendly_abort (252);
 
-  pop_obstacks ();
-  return t;
+  expand_end_cond ();
+
+  /* OK, now return the type_info object.  */
+  tmp = convert (build_pointer_type (type_info_type_node), addr);
+  tmp = build_indirect_ref (tmp, 0);
+  c_expand_return (tmp);
+  finish_function (lineno, 0, 0);
 }
 
 #if 0
index 588d823..ed97fc3 100644 (file)
@@ -74,7 +74,7 @@ pop_stack_level (stack)
 static struct search_level *search_stack;
 
 static tree lookup_field_1 ();
-static int lookup_fnfields_1 ();
+static int lookup_fnfields_1 PROTO((tree, tree));
 static void dfs_walk ();
 static int markedp ();
 static void dfs_unmark ();
@@ -246,6 +246,18 @@ my_new_memoized_entry (chain)
   return p;
 }
 
+/* Clears the deferred pop from pop_memoized_context, if any.  */
+static void
+clear_memoized_cache ()
+{
+  if (prev_type_stack)
+    {
+      type_stack = pop_type_level (prev_type_stack);
+      prev_type_memoized = 0;
+      prev_type_stack = 0;
+    }
+}
+
 /* Make an entry in the memoized table for type TYPE
    that the entry for NAME is FIELD.  */
 
@@ -257,6 +269,10 @@ make_memoized_table_entry (type, name, function_p)
   int index = MEMOIZED_HASH_FN (name);
   tree entry, *prev_entry;
 
+  /* Since we allocate from the type_obstack, we must pop any deferred
+     levels.  */
+   clear_memoized_cache ();
+
   memoized_adds[function_p] += 1;
   if (CLASSTYPE_MTABLE_ENTRY (type) == 0)
     {
@@ -334,9 +350,7 @@ push_memoized_context (type, use_old)
          return;
        }
       /* Otherwise, need to pop old stack here.  */
-      type_stack = pop_type_level (prev_type_stack);
-      prev_type_memoized = 0;
-      prev_type_stack = 0;
+      clear_memoized_cache ();
     }
 
   type_stack = push_type_level ((struct stack_level *)type_stack,
@@ -364,6 +378,9 @@ pop_memoized_context (use_old)
       while (len--)
        tem[len*2+1] = (tree)CLASSTYPE_MTABLE_ENTRY (tem[len*2]);
 
+      /* If there was a deferred pop, we need to pop it now.  */
+      clear_memoized_cache ();
+
       prev_type_stack = type_stack;
       prev_type_memoized = type_stack->type;
     }
@@ -494,14 +511,23 @@ get_binfo (parent, binfo, protect)
 static int
 get_base_distance_recursive (binfo, depth, is_private, rval,
                             rval_private_ptr, new_binfo_ptr, parent, path_ptr,
-                            protect, via_virtual_ptr, via_virtual)
-     tree binfo, *new_binfo_ptr, parent, *path_ptr;
-     int *rval_private_ptr, depth, is_private, rval, protect, *via_virtual_ptr,
-       via_virtual;
+                            protect, via_virtual_ptr, via_virtual,
+                            current_scope_in_chain)
+     tree binfo;
+     int depth, is_private, rval;
+     int *rval_private_ptr;
+     tree *new_binfo_ptr, parent, *path_ptr;
+     int protect, *via_virtual_ptr, via_virtual;
+     int current_scope_in_chain;
 {
   tree binfos;
   int i, n_baselinks;
 
+  if (protect
+      && !current_scope_in_chain
+      && is_friend (BINFO_TYPE (binfo), current_scope ()))
+    current_scope_in_chain = 1;
+
   if (BINFO_TYPE (binfo) == parent || binfo == parent)
     {
       if (rval == -1)
@@ -556,6 +582,8 @@ get_base_distance_recursive (binfo, depth, is_private, rval,
            = (protect
               && (is_private
                   || (!TREE_VIA_PUBLIC (base_binfo)
+                      && !(TREE_VIA_PROTECTED (base_binfo)
+                           && current_scope_in_chain)
                       && !is_friend (BINFO_TYPE (binfo), current_scope ()))));
          int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo);
          int was;
@@ -572,7 +600,8 @@ get_base_distance_recursive (binfo, depth, is_private, rval,
                                              rval, rval_private_ptr,
                                              new_binfo_ptr, parent, path_ptr,
                                              protect, via_virtual_ptr,
-                                             this_virtual);
+                                             this_virtual,
+                                             current_scope_in_chain);
          /* watch for updates; only update if path is good. */
          if (path_ptr && WATCH_VALUES (rval, *via_virtual_ptr) != was)
            BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
@@ -652,7 +681,8 @@ get_base_distance (parent, binfo, protect, path_ptr)
 
   rval = get_base_distance_recursive (binfo, 0, 0, -1,
                                      &rval_private, &new_binfo, parent,
-                                     path_ptr, watch_access, &via_virtual, 0);
+                                     path_ptr, watch_access, &via_virtual, 0,
+                                     0);
 
   dfs_walk (binfo, dfs_unmark, markedp);
 
@@ -2106,8 +2136,9 @@ get_matching_virtual (binfo, fndecl, dtorp)
    expand_direct_vtbls_init for the style of search we do.  */
 static tree
 get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
-     tree binfo, abstract_virtuals;
+     tree binfo;
      int do_self;
+     tree abstract_virtuals;
 {
   tree binfos = BINFO_BASETYPES (binfo);
   int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
@@ -2559,12 +2590,12 @@ dfs_init_vbase_pointers (binfo)
 
   CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
 
-  /* If there is a rtti, it is the first field, though perhaps from
-     the base class.  Otherwise, the first fields are virtual base class
-     pointer fields.  */
-  if (CLASSTYPE_RTTI (type) && VFIELD_NAME_P (DECL_NAME (fields)))
-    /* Get past vtable for the object.  */
+#if 0
+  /* See finish_struct_1 for when we can enable this.  */
+  /* If we have a vtable pointer first, skip it.  */
+  if (VFIELD_NAME_P (DECL_NAME (fields)))
     fields = TREE_CHAIN (fields);
+#endif
 
   if (fields == NULL_TREE
       || DECL_NAME (fields) == NULL_TREE
@@ -2736,6 +2767,7 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
              DECL_ALIGN (nvtbl) = MAX (TYPE_ALIGN (double_type_node),
                                        DECL_ALIGN (nvtbl));
              TREE_READONLY (nvtbl) = 0;
+             DECL_ARTIFICIAL (nvtbl) = 1;
              nvtbl = pushdecl (nvtbl);
              init = NULL_TREE;
              cp_finish_decl (nvtbl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
@@ -2796,8 +2828,9 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
    expand_direct_vtbls_init.  */
 static void
 fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, orig_addr, type, vbase, vbase_offsets)
-     tree real_binfo, binfo, addr, orig_addr, type, vbase, *vbase_offsets;
+     tree real_binfo, binfo;
      int init_self, can_elide;
+     tree addr, orig_addr, type, vbase, *vbase_offsets;
 {
   tree real_binfos = BINFO_BASETYPES (real_binfo);
   tree binfos = BINFO_BASETYPES (binfo);
index 762a0aa..a2c79b4 100644 (file)
@@ -1572,6 +1572,22 @@ default_conversion (exp)
 
   return exp;
 }
+
+/* Take the address of an inline function without setting TREE_ADDRESSABLE
+   or TREE_USED.  */
+
+tree
+inline_conversion (exp)
+     tree exp;
+{
+  if (TREE_CODE (exp) == FUNCTION_DECL)
+    {
+      tree type = build_type_variant
+       (TREE_TYPE (exp), TREE_READONLY (exp), TREE_THIS_VOLATILE (exp));
+      exp = build1 (ADDR_EXPR, build_pointer_type (type), exp);
+    }
+  return exp;
+}
 \f
 tree
 build_object_ref (datum, basetype, field)
@@ -2489,11 +2505,6 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
        {
          aref = save_expr (aref);
 
-         /* Save the intermediate result in a SAVE_EXPR so we don't have to
-            compute each component of the virtual function pointer twice.  */ 
-         if (TREE_CODE (aref) == INDIRECT_REF)
-           TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0));
-      
          delta = build_binary_op (PLUS_EXPR,
                                   build_conditional_expr (e1, build_component_ref (aref, delta_identifier, 0, 0), integer_zero_node),
                                   delta, 1);
@@ -2575,10 +2586,7 @@ build_function_call_real (function, params, require_complete, flags)
              && current_function_decl)
            synthesize_method (function);
 
-         fntype = build_type_variant (TREE_TYPE (function),
-                                      TREE_READONLY (function),
-                                      TREE_THIS_VOLATILE (function));
-         function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);
+         function = inline_conversion (function);
        }
       else
        function = default_conversion (function);