cp-tree.h (new_abi_rtti_p): Use flag_new_abi.
authorNathan Sidwell <sidwell@codesourcery.com>
Mon, 31 Jan 2000 10:21:47 +0000 (10:21 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Mon, 31 Jan 2000 10:21:47 +0000 (10:21 +0000)
* cp-tree.h (new_abi_rtti_p): Use flag_new_abi.

Runtime support for new-abi rtti.
* inc/typeinfo (type_info::operator!=): Define in class.
(type_info::before, type_info::name, type_info::operator==,
type_info::operator!=): Define new ABI implementations.
(type_info::is_pointer_p, type_info::is_function_p): Declare
new virtual functions.
(type_info::do_catch, type_info::do_upcast): Likewise.

* tinfo.h (__base_class_info): Define new class.
(__class_type_info): Likewise.
(__si_class_type_info): Likewise.
(__vmi_class_type_info): Likewise.
(__dynamic_cast): Prototype.

* tinfo.cc: Conditionalize old and new rtti mechanisms.
(type_info::is_pointer_p): Define new function.
(type_info::is_function_p): Likewise.
(type_info::do_catch): Likewise.
(type_info::do_upcast): Likewise.
(vtable_prefix): New structure for vtable access.
(adjust_pointer): Define new template function.
(contained_p, public_p, virtual_p, contained_public_p,
contained_nonpublic_p, contained_nonvirtual_p): Define new
functions.
(nonvirtual_base_type): New local variable.
(__class_type_info::~__class_type_info): Define.
(__si_class_type_info::~__si_class_type_info): Likewise.
(__vmi_class_type_info::~__vmi_class_type_info): Likewise.
(__class_type_info::do_catch): Define new function.
(__class_type_info::do_upcast): Likewise.
(__class_type_info::find_public_src): Likewise.
(__class_type_info::do_find_public_src): Likewise.
(__si_class_type_info::do_find_public_src): Likewise.
(__vmi_class_type_info::do_find_public_src): Likewise.
(__class_type_info::do_dyncast): Likewise.
(__si_class_type_info::do_dyncast): Likewise.
(__vmi_class_type_info::do_dyncast): Likewise.
(__class_type_info::do_upcast): Likewise.
(__si_class_type_info::do_upcast): Likewise.
(__vmi_class_type_info::do_upcast): Likewise.
(__dynamic_cast): Likewise.

* tinfo2.cc (__fundamental_type_info): Define new class.
(__pointer_type_info): Likewise.
(__reference_type_info): Likewise.
(__array_type_info): Likewise.
(__function_type_info): Likewise.
(__enum_type_info): Likewise.
(__ptr_to_member_type_info): Likewise.
(__fundamental_type_info::~__fundamental_type_info): Define.
(__pointer_type_info::~__pointer_type_info): Likewise.
(__reference_type_info::~__reference_type_info): Likewise.
(__array_type_info::~__array_type_info): Likewise.
(__function_type_info::~__function_type_info): Likewise.
(__enum_type_info::~__enum_type_info): Likewise.
(__ptr_to_member_type_info::~__ptr_to_member_type_info): Likewise.
(__pointer_type_info::do_catch): Define new function.
(__ptr_to_member_type_info::do_catch): Define new function.

(__throw_type_match_rtti_2): Use new ABI interface, if enabled.
(__is_pointer): Likewise.

* exception.cc (__cplus_type_matcher): Deal with new-abi rtti.

From-SVN: r31713

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/exception.cc
gcc/cp/inc/typeinfo
gcc/cp/tinfo.cc
gcc/cp/tinfo.h
gcc/cp/tinfo2.cc

index b5198b3daa4b6eaa2673be71d05d91f5ee643a07..192daf4e0a87bd1320aa712ce6467ed3c35f3c45 100644 (file)
@@ -1,3 +1,71 @@
+2000-01-31  Nathan Sidwell  <sidwell@codesourcery.com>
+
+       * cp-tree.h (new_abi_rtti_p): Use flag_new_abi.
+
+       Runtime support for new-abi rtti.
+       * inc/typeinfo (type_info::operator!=): Define in class.
+       (type_info::before, type_info::name, type_info::operator==,
+       type_info::operator!=): Define new ABI implementations.
+       (type_info::is_pointer_p, type_info::is_function_p): Declare
+       new virtual functions.
+       (type_info::do_catch, type_info::do_upcast): Likewise.
+       
+       * tinfo.h (__base_class_info): Define new class.
+       (__class_type_info): Likewise.
+       (__si_class_type_info): Likewise.
+       (__vmi_class_type_info): Likewise.
+       (__dynamic_cast): Prototype.
+       
+       * tinfo.cc: Conditionalize old and new rtti mechanisms.
+       (type_info::is_pointer_p): Define new function.
+       (type_info::is_function_p): Likewise.
+       (type_info::do_catch): Likewise.
+       (type_info::do_upcast): Likewise.
+       (vtable_prefix): New structure for vtable access.
+       (adjust_pointer): Define new template function.
+       (contained_p, public_p, virtual_p, contained_public_p,
+       contained_nonpublic_p, contained_nonvirtual_p): Define new
+       functions.
+       (nonvirtual_base_type): New local variable.
+       (__class_type_info::~__class_type_info): Define.
+       (__si_class_type_info::~__si_class_type_info): Likewise.
+       (__vmi_class_type_info::~__vmi_class_type_info): Likewise.
+       (__class_type_info::do_catch): Define new function.
+       (__class_type_info::do_upcast): Likewise.
+       (__class_type_info::find_public_src): Likewise.
+       (__class_type_info::do_find_public_src): Likewise.
+       (__si_class_type_info::do_find_public_src): Likewise.
+       (__vmi_class_type_info::do_find_public_src): Likewise.
+       (__class_type_info::do_dyncast): Likewise.
+       (__si_class_type_info::do_dyncast): Likewise.
+       (__vmi_class_type_info::do_dyncast): Likewise.
+       (__class_type_info::do_upcast): Likewise.
+       (__si_class_type_info::do_upcast): Likewise.
+       (__vmi_class_type_info::do_upcast): Likewise.
+       (__dynamic_cast): Likewise.
+       
+       * tinfo2.cc (__fundamental_type_info): Define new class.
+       (__pointer_type_info): Likewise.
+       (__reference_type_info): Likewise.
+       (__array_type_info): Likewise.
+       (__function_type_info): Likewise.
+       (__enum_type_info): Likewise.
+       (__ptr_to_member_type_info): Likewise.
+       (__fundamental_type_info::~__fundamental_type_info): Define.
+       (__pointer_type_info::~__pointer_type_info): Likewise.
+       (__reference_type_info::~__reference_type_info): Likewise.
+       (__array_type_info::~__array_type_info): Likewise.
+       (__function_type_info::~__function_type_info): Likewise.
+       (__enum_type_info::~__enum_type_info): Likewise.
+       (__ptr_to_member_type_info::~__ptr_to_member_type_info): Likewise.
+       (__pointer_type_info::do_catch): Define new function.
+       (__ptr_to_member_type_info::do_catch): Define new function.
+       
+       (__throw_type_match_rtti_2): Use new ABI interface, if enabled.
+       (__is_pointer): Likewise.
+
+       * exception.cc (__cplus_type_matcher): Deal with new-abi rtti.
+
 2000-01-30  Mark Mitchell  <mark@codesourcery.com>
 
        * cp/class.c (build_vtable): Rename to build_primary_vtable.
index d7aabbefc6af8dfc596d68fab4f427f505d283f8..f1d86e56f173a0d8dd922efc9833f8f9586f230f 100644 (file)
@@ -244,7 +244,7 @@ extern int flag_rtti;
 /* Nonzero if we use access type_info objects directly, and use the
    cross-vendor layout for them. Zero if we use an accessor function
    to get the type_info object address.  */
-#define new_abi_rtti_p() (0)
+#define new_abi_rtti_p() (flag_new_abi)
 
 \f
 /* Language-dependent contents of an identifier.  */
index d00e0f28a38fc7bf99613a4e626d0705b0616251..0c806e6cf00e19a7ae9ee0f78ed3946a131249ec 100644 (file)
@@ -184,7 +184,11 @@ __cplus_type_matcher (__eh_info *info_, void *match_info,
 
   /* we don't worry about version info yet, there is only one version! */
   
-  void *match_type = ((void *(*)())match_info) ();
+  void *match_type = match_info;
+  
+#if !defined (__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100
+  match_type  = ((void *(*)())match_type) ();
+#endif
 
   if (__throw_type_match_rtti_2 (match_type, info->type,
                                 info->original_value, &info->value))
index 934784968c54646799251597aef7c8e7d7f12e2c..b631d6e2d24101b29331d967bb202eb03dd3244f 100644 (file)
@@ -1,5 +1,10 @@
 // RTTI support for -*- C++ -*-
-// Copyright (C) 1994, 95-97, 1998 Free Software Foundation
+// Copyright (C) 1994, 95-97, 1998, 2000 Free Software Foundation
+
+// __GXX_ABI_VERSION distinguishes the ABI that is being used. Values <100
+// indicate the `old' abi, which grew as C++ was defined. Values >=100
+// indicate the `new' abi, which is a cross vendor C++ abi, documented at
+// `http://reality.sgi.com/dehnert_engr/cxx/'.
 
 #ifndef __TYPEINFO__
 #define __TYPEINFO__
@@ -12,33 +17,74 @@ extern "C++" {
 
 namespace std {
 
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
+class __class_type_info;
+#endif
+
 class type_info {
+public:
+  // Destructor. Being the first non-inline virtual function, this controls in
+  // which translation unit the vtable is emitted. The compiler makes use of
+  // that information to know where to emit the runtime-mandated type_info
+  // structures in the new-abi.
+  virtual ~type_info ();
+
 private:
-  // assigning type_info is not supported.  made private.
+  // Assigning type_info is not supported.  made private.
   type_info& operator= (const type_info&);
   type_info (const type_info&);
 
 protected:
-  explicit type_info (const char *n): _name (n) { }
-
   const char *_name;
 
+protected:
+  explicit type_info (const char *n): _name (n) { }
+
 public:
-  // destructor
-  virtual ~type_info ();
-    
+  // the public interface
+#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100
+  // In old abi, there can be multiple instances of a type_info object for one
+  // type. Uniqueness must use the _name value, not object address.
   bool before (const type_info& arg) const;
   const char* name () const
     { return _name; }
   bool operator== (const type_info& arg) const;
-  bool operator!= (const type_info& arg) const;
-};
+  bool operator!= (const type_info& arg) const
+    { return !operator== (arg); }
+
+#else
+  // In new abi we can rely on type_info's being unique,
+  // and therefore address comparisons are sufficient.
+  bool before (const type_info& arg) const
+    { return this < &arg; }
+  const char* name () const
+    { return _name; }
+  bool operator== (const type_info& arg) const
+    { return &arg == this; }
+  bool operator!= (const type_info& arg) const
+    { return !operator== (arg); }
+#endif
 
-inline bool type_info::
-operator!= (const type_info& arg) const
-{
-  return !operator== (arg);
-}
+  // the internal interface
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
+public:
+  // return true if this is a pointer type of some kind
+  virtual bool is_pointer_p () const;
+  // return true if this is a function type
+  virtual bool is_function_p () const;
+
+  // Try and catch a thrown type. Store an adjusted pointer to the caught type
+  // in THR_OBJ. If THR_TYPE is not a pointer type, then THR_OBJ points to the
+  // thrown object. If THR_TYPE is a pointer type, then THR_OBJ is the pointer
+  // itself. OUTER indicates the number of outer pointers, and whether they
+  // were const qualified.
+  virtual bool do_catch (const type_info *thr_type, void **thr_obj,
+                         unsigned outer) const;
+
+  // internally used during catch matching
+  virtual bool do_upcast (const __class_type_info *target, void **obj_ptr) const;
+#endif
+};
 
 class bad_cast : public exception {
 public:
index 292fb3c3ef384d8e097e23dca80142e9e6db8ea5..557c88c18073ae91972871886a29243b0dd723e0 100644 (file)
@@ -67,6 +67,9 @@ std::type_info::
 ~type_info ()
 { }
 
+#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100
+// original (old) abi
+
 // We can't rely on common symbols being shared between shared objects.
 bool std::type_info::
 operator== (const std::type_info& arg) const
@@ -539,3 +542,602 @@ do_find_public_subobj (int boff, const type_info &subtype, void *objptr, void *s
   
   return not_contained;
 }
+#else
+// new abi
+
+namespace std {
+
+// return true if this is a type_info for a pointer type
+bool type_info::
+is_pointer_p () const
+{
+  return false;
+}
+
+// return true if this is a type_info for a function type
+bool type_info::
+is_function_p () const
+{
+  return false;
+}
+
+// try and catch a thrown object.
+bool type_info::
+do_catch (const type_info *thr_type, void **, unsigned) const
+{
+  return *this == *thr_type;
+}
+
+// upcast from this type to the target. __class_type_info will override
+bool type_info::
+do_upcast (const __class_type_info *, void **) const
+{
+  return false;
+}
+
+};
+
+namespace {
+
+using namespace std;
+
+// initial part of a vtable, this structure is used with offsetof, so we don't
+// have to keep alignments consistent manually.
+struct vtable_prefix {
+  ptrdiff_t whole_object;           // offset to most derived object
+  const __class_type_info *whole_type;  // pointer to most derived type_info
+  const void *origin;               // what a class's vptr points to
+};
+
+template <typename T>
+inline const T *
+adjust_pointer (const void *base, ptrdiff_t offset)
+{
+  return reinterpret_cast <const T *>
+    (reinterpret_cast <const char *> (base) + offset);
+}
+
+// some predicate functions for __class_type_info::sub_kind
+inline bool contained_p (__class_type_info::sub_kind access_path)
+{
+  return access_path >= __class_type_info::contained_mask;
+}
+inline bool public_p (__class_type_info::sub_kind access_path)
+{
+  return access_path & __class_type_info::contained_public_mask;
+}
+inline bool virtual_p (__class_type_info::sub_kind access_path)
+{
+  return (access_path & __class_type_info::contained_virtual_mask);
+}
+inline bool contained_public_p (__class_type_info::sub_kind access_path)
+{
+  return (access_path & __class_type_info::contained_public) == __class_type_info::contained_public;
+}
+inline bool contained_nonpublic_p (__class_type_info::sub_kind access_path)
+{
+  return (access_path & __class_type_info::contained_public) == __class_type_info::contained_mask;
+}
+inline bool contained_nonvirtual_p (__class_type_info::sub_kind access_path)
+{
+  return (access_path & (__class_type_info::contained_mask | __class_type_info::contained_virtual_mask))
+         == __class_type_info::contained_mask;
+}
+
+static const __class_type_info *const nonvirtual_base_type =
+    static_cast <const __class_type_info *> (0) + 1;
+
+}; // namespace
+
+namespace std {
+
+__class_type_info::
+~__class_type_info ()
+{}
+
+__si_class_type_info::
+~__si_class_type_info ()
+{}
+
+__vmi_class_type_info::
+~__vmi_class_type_info ()
+{}
+
+bool __class_type_info::
+do_catch (const type_info *thr_type, void **thr_obj,
+          unsigned outer) const
+{
+  if (*this == *thr_type)
+    return true;
+  if (outer >= 4)
+    // Neither `A' nor `A *'.
+    return false;
+  return thr_type->do_upcast (this, thr_obj);
+}
+
+bool __class_type_info::
+do_upcast (const __class_type_info *dst_type, void **obj_ptr) const
+{
+  upcast_result result (details);
+  
+  if (do_upcast (contained_public, dst_type, *obj_ptr, result))
+    return false;
+  *obj_ptr = const_cast <void *> (result.dst_ptr);
+  return contained_public_p (result.whole2dst);
+}
+
+inline __class_type_info::sub_kind __class_type_info::
+find_public_src (ptrdiff_t src2dst,
+                 const void *obj_ptr,
+                 const __class_type_info *src_type,
+                 const void *src_ptr) const
+{
+  if (src2dst >= 0)
+    return adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
+            ? contained_public : not_contained;
+  if (src2dst == -2)
+    return not_contained;
+  return do_find_public_src (src2dst, obj_ptr, src_type, src_ptr);
+}
+
+__class_type_info::sub_kind __class_type_info::
+do_find_public_src (ptrdiff_t,
+                    const void *obj_ptr,
+                    const __class_type_info *,
+                    const void *src_ptr) const
+{
+  if (src_ptr == obj_ptr)
+    // Must be our type, as the pointers match.
+    return contained_public;
+  return not_contained;
+}
+
+__class_type_info::sub_kind __si_class_type_info::
+do_find_public_src (ptrdiff_t src2dst,
+                    const void *obj_ptr,
+                    const __class_type_info *src_type,
+                    const void *src_ptr) const
+{
+  if (src_ptr == obj_ptr && *this == *src_type)
+    return contained_public;
+  return base->do_find_public_src (src2dst, obj_ptr, src_type, src_ptr);
+}
+
+__class_type_info::sub_kind __vmi_class_type_info::
+do_find_public_src (ptrdiff_t src2dst,
+                    const void *obj_ptr,
+                    const __class_type_info *src_type,
+                    const void *src_ptr) const
+{
+  if (obj_ptr == src_ptr && *this == *src_type)
+    return contained_public;
+  
+  for (size_t i = n_bases; i--;)
+    {
+      if (!base_list[i].is_public_p ())
+        continue; // Not public, can't be here.
+      
+      const void *base = obj_ptr;
+      ptrdiff_t offset = base_list[i].offset;
+      
+      if (base_list[i].is_virtual_p ())
+        {
+          if (src2dst == -3)
+            continue; // Not a virtual base, so can't be here.
+         const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base);
+          
+         offset = vtable[offset];
+        }
+      base = adjust_pointer <void> (base, offset);
+      
+      sub_kind base_kind = base_list[i].type->do_find_public_src
+                              (src2dst, base, src_type, src_ptr);
+      if (contained_p (base_kind))
+        {
+          if (base_list[i].is_virtual_p ())
+            base_kind = sub_kind (base_kind | contained_virtual_mask);
+          return base_kind;
+        }
+    }
+  
+  return not_contained;
+}
+
+bool __class_type_info::
+do_dyncast (ptrdiff_t,
+            sub_kind access_path,
+            const __class_type_info *dst_type,
+            const void *obj_ptr,
+            const __class_type_info *src_type,
+            const void *src_ptr,
+            dyncast_result &__restrict result) const
+{
+  if (obj_ptr == src_ptr && *this == *src_type)
+    {
+      // The src object we started from. Indicate how we are accessible from
+      // the most derived object.
+      result.whole2src = access_path;
+      return false;
+    }
+  if (*this == *dst_type)
+    {
+      result.dst_ptr = obj_ptr;
+      result.whole2dst = access_path;
+      result.dst2src = not_contained;
+      return false;
+    }
+  return false;
+}
+
+bool __si_class_type_info::
+do_dyncast (ptrdiff_t src2dst,
+            sub_kind access_path,
+            const __class_type_info *dst_type,
+            const void *obj_ptr,
+            const __class_type_info *src_type,
+            const void *src_ptr,
+            dyncast_result &__restrict result) const
+{
+  if (*this == *dst_type)
+    {
+      result.dst_ptr = obj_ptr;
+      result.whole2dst = access_path;
+      if (src2dst >= 0)
+        result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
+              ? contained_public : not_contained;
+      else if (src2dst == -2)
+        result.dst2src = not_contained;
+      return false;
+    }
+  if (obj_ptr == src_ptr && *this == *src_type)
+    {
+      // The src object we started from. Indicate how we are accessible from
+      // the most derived object.
+      result.whole2src = access_path;
+      return false;
+    }
+  return base->do_dyncast (src2dst, access_path, dst_type, obj_ptr,
+                           src_type, src_ptr, result);
+}
+
+// This is a big hairy function. Although the run-time behaviour of
+// dynamic_cast is simple to describe, it gives rise to some non-obvious
+// behaviour. We also desire to determine as early as possible any definite
+// answer we can get. Because it is unknown what the run-time ratio of
+// succeeding to failing dynamic casts is, we do not know in which direction
+// to bias any optimizations. To that end we make no particular effort towards
+// early fail answers or early success answers. Instead we try to minimize
+// work by filling in things lazily (when we know we need the information),
+// and opportunisticly take early success or failure results.
+bool __vmi_class_type_info::
+do_dyncast (ptrdiff_t src2dst,
+            sub_kind access_path,
+            const __class_type_info *dst_type,
+            const void *obj_ptr,
+            const __class_type_info *src_type,
+            const void *src_ptr,
+            dyncast_result &__restrict result) const
+{
+  if (obj_ptr == src_ptr && *this == *src_type)
+    {
+      // The src object we started from. Indicate how we are accessible from
+      // the most derived object.
+      result.whole2src = access_path;
+      return false;
+    }
+  if (*this == *dst_type)
+    {
+      result.dst_ptr = obj_ptr;
+      result.whole2dst = access_path;
+      if (src2dst >= 0)
+        result.dst2src = adjust_pointer <void> (obj_ptr, src2dst) == src_ptr
+              ? contained_public : not_contained;
+      else if (src2dst == -2)
+        result.dst2src = not_contained;
+      return false;
+    }
+  bool result_ambig = false;
+  for (size_t i = n_bases; i--;)
+    {
+      dyncast_result result2;
+      void const *base = obj_ptr;
+      sub_kind base_access = access_path;
+      ptrdiff_t offset = base_list[i].offset;
+      
+      if (base_list[i].is_virtual_p ())
+        {
+          base_access = sub_kind (base_access | contained_virtual_mask);
+         const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base);
+          
+         offset = vtable[offset];
+       }
+      base = adjust_pointer <void> (base, offset);
+
+      if (!base_list[i].is_public_p ())
+        base_access = sub_kind (base_access & ~contained_public_mask);
+      
+      bool result2_ambig
+          = base_list[i].type->do_dyncast (src2dst, base_access,
+                                           dst_type, base,
+                                           src_type, src_ptr, result2);
+      result.whole2src = sub_kind (result.whole2src | result2.whole2src);
+      if (result2.dst2src == contained_public
+          || result2.dst2src == contained_ambig)
+        {
+          result.dst_ptr = result2.dst_ptr;
+          result.whole2dst = result2.whole2dst;
+          result.dst2src = result2.dst2src;
+          // Found a downcast which can't be bettered or an ambiguous downcast
+          // which can't be disambiguated
+          return result2_ambig;
+        }
+      
+      if (!result_ambig && !result.dst_ptr)
+        {
+          // Not found anything yet.
+          result.dst_ptr = result2.dst_ptr;
+          result.whole2dst = result2.whole2dst;
+          result_ambig = result2_ambig;
+        }
+      else if (result.dst_ptr && result.dst_ptr == result2.dst_ptr)
+        {
+          // Found at same address, must be via virtual.  Pick the most
+          // accessible path.
+          result.whole2dst =
+              sub_kind (result.whole2dst | result2.whole2dst);
+        }
+      else if ((result.dst_ptr && result2.dst_ptr)
+               || (result_ambig && result2.dst_ptr)
+               || (result2_ambig && result.dst_ptr))
+        {
+          // Found two different DST_TYPE bases, or a valid one and a set of
+          // ambiguous ones, must disambiguate. See whether SRC_PTR is
+          // contained publicly within one of the non-ambiguous choices. If it
+          // is in only one, then that's the choice. If it is in both, then
+          // we're ambiguous and fail. If it is in neither, we're ambiguous,
+          // but don't yet fail as we might later find a third base which does
+          // contain SRC_PTR.
+        
+          sub_kind new_sub_kind = result2.dst2src;
+          sub_kind old_sub_kind = result.dst2src;
+          
+          if (contained_nonvirtual_p (result.whole2src))
+            {
+              // We already found SRC_PTR as a non-virtual base of most
+              // derived. Therefore if it is in either choice, it can only be
+              // in one of them, and we will already know.
+              if (old_sub_kind == unknown)
+                old_sub_kind = not_contained;
+              if (new_sub_kind == unknown)
+                new_sub_kind = not_contained;
+            }
+          else
+            {
+              if (old_sub_kind >= not_contained)
+                ;// already calculated
+              else if (contained_nonvirtual_p (new_sub_kind))
+                // Already found non-virtually inside the other choice,
+                // cannot be in this.
+                old_sub_kind = not_contained;
+              else
+                old_sub_kind = dst_type->find_public_src
+                                (src2dst, result.dst_ptr, src_type, src_ptr);
+          
+              if (new_sub_kind >= not_contained)
+                ;// already calculated
+              else if (contained_nonvirtual_p (old_sub_kind))
+                // Already found non-virtually inside the other choice,
+                // cannot be in this.
+                new_sub_kind = not_contained;
+              else
+                new_sub_kind = dst_type->find_public_src
+                                (src2dst, result2.dst_ptr, src_type, src_ptr);
+            }
+          
+          // Neither sub_kind can be contained_ambig -- we bail out early
+          // when we find those.
+          if (contained_p (sub_kind (new_sub_kind ^ old_sub_kind)))
+            {
+              // Only on one choice, not ambiguous.
+              if (contained_p (new_sub_kind))
+                {
+                  // Only in new.
+                  result.dst_ptr = result2.dst_ptr;
+                  result.whole2dst = result2.whole2dst;
+                  result_ambig = false;
+                  old_sub_kind = new_sub_kind;
+                }
+              result.dst2src = old_sub_kind;
+              if (public_p (result.dst2src))
+                return false; // Can't be an ambiguating downcast for later discovery.
+              if (!virtual_p (result.dst2src))
+                return false; // Found non-virtually can't be bettered
+            }
+          else if (contained_p (sub_kind (new_sub_kind & old_sub_kind)))
+            {
+              // In both.
+              result.dst_ptr = NULL;
+              result.dst2src = contained_ambig;
+              return true;  // Fail.
+            }
+          else
+            {
+              // In neither publicly, ambiguous for the moment, but keep
+              // looking. It is possible that it was private in one or
+              // both and therefore we should fail, but that's just tough.
+              result.dst_ptr = NULL;
+              result.dst2src = not_contained;
+              result_ambig = true;
+            }
+        }
+      
+      if (result.whole2src == contained_private)
+        // We found SRC_PTR as a private non-virtual base, therefore all
+        // cross casts will fail. We have already found a down cast, if
+        // there is one.
+        return result_ambig;
+    }
+
+  return result_ambig;
+}
+
+bool __class_type_info::
+do_upcast (sub_kind access_path,
+           const __class_type_info *dst, const void *obj,
+           upcast_result &__restrict result) const
+{
+  if (*this == *dst)
+    {
+      result.dst_ptr = obj;
+      result.base_type = nonvirtual_base_type;
+      result.whole2dst = access_path;
+      return contained_nonpublic_p (access_path);
+    }
+  return false;
+}
+
+bool __si_class_type_info::
+do_upcast (sub_kind access_path,
+           const __class_type_info *dst, const void *obj_ptr,
+           upcast_result &__restrict result) const
+{
+  if (*this == *dst)
+    {
+      result.dst_ptr = obj_ptr;
+      result.base_type = nonvirtual_base_type;
+      result.whole2dst = access_path;
+      return contained_nonpublic_p (access_path);
+    }
+  return base->do_upcast (access_path, dst, obj_ptr, result);
+}
+
+bool __vmi_class_type_info::
+do_upcast (sub_kind access_path,
+           const __class_type_info *dst, const void *obj_ptr,
+           upcast_result &__restrict result) const
+{
+  if (*this == *dst)
+    {
+      result.dst_ptr = obj_ptr;
+      result.base_type = nonvirtual_base_type;
+      result.whole2dst = access_path;
+      return contained_nonpublic_p (access_path);
+    }
+  
+  for (size_t i = n_bases; i--;)
+    {
+      upcast_result result2 (result.src_details);
+      const void *base = obj_ptr;
+      sub_kind sub_access = access_path;
+      ptrdiff_t offset = base_list[i].offset;
+      
+      if (!base_list[i].is_public_p ())
+        {
+          if (!(result.src_details & multiple_base_mask))
+            // original cannot have an ambiguous base
+            continue;
+          sub_access = sub_kind (sub_access & ~contained_public_mask);
+        }
+      if (base_list[i].is_virtual_p ())
+        {
+         sub_access = sub_kind (sub_access | contained_virtual_mask);
+          
+          if (base)
+            {
+             const ptrdiff_t *vtable = *static_cast <const ptrdiff_t *const *> (base);
+             offset = vtable[offset];
+           }
+        }
+      if (base)
+        base = adjust_pointer <void> (base, offset);
+      
+      if (base_list[i].type->do_upcast (sub_access, dst, base, result2))
+        return true; // must fail
+      if (result2.base_type)
+        {
+          if (result2.base_type == nonvirtual_base_type
+              && base_list[i].is_virtual_p ())
+            result2.base_type = base_list[i].type;
+          if (!result.base_type)
+            {
+              result = result2;
+              if (!(details & multiple_base_mask))
+                // cannot have an ambiguous other base
+                return false;
+            }
+          else if (result.dst_ptr != result2.dst_ptr)
+            {
+              // Found an ambiguity.
+             result.dst_ptr = NULL;
+             result.whole2dst = contained_ambig;
+             return true;
+            }
+          else if (result.dst_ptr)
+            {
+              // Ok, found real object via a virtual path.
+              result.whole2dst
+                  = sub_kind (result.whole2dst | result2.whole2dst);
+            }
+          else
+            {
+              // Dealing with a null pointer, need to check vbase
+              // containing each of the two choices.
+              if (result2.base_type == nonvirtual_base_type
+                  || result.base_type == nonvirtual_base_type
+                  || !(*result2.base_type == *result.base_type))
+                {
+                  // Already ambiguous, not virtual or via different virtuals.
+                  // Cannot match.
+                  result.whole2dst = contained_ambig;
+                  return true;
+                }
+            }
+        }
+    }
+  return false;
+}
+
+// this is the external interface to the dynamic cast machinery
+void *
+__dynamic_cast (const void *src_ptr,    // object started from
+                const __class_type_info *src_type, // type of the starting object
+                const __class_type_info *dst_type, // desired target type
+                ptrdiff_t src2dst) // how src and dst are related
+{
+  const void *vtable = *static_cast <const void *const *> (src_ptr);
+  const vtable_prefix *prefix =
+      adjust_pointer <vtable_prefix> (vtable, 0);
+  // FIXME: the above offset should be -offsetof (vtable_prefix, origin));
+  // but we don't currently layout vtables correctly.
+  const void *whole_ptr =
+      adjust_pointer <void> (src_ptr, prefix->whole_object);
+  const __class_type_info *whole_type = prefix->whole_type;
+  __class_type_info::dyncast_result result;
+  
+  whole_type->do_dyncast (src2dst, __class_type_info::contained_public,
+                          dst_type, whole_ptr, src_type, src_ptr, result);
+  if (!result.dst_ptr)
+    return NULL;
+  if (contained_public_p (result.dst2src))
+    return const_cast <void *> (result.dst_ptr);
+  if (contained_public_p (__class_type_info::sub_kind (result.whole2src & result.whole2dst)))
+    // Found a valid cross cast
+    return const_cast <void *> (result.dst_ptr);
+  if (contained_nonvirtual_p (result.whole2src))
+    // Found an invalid cross cast, which cannot also be a down cast
+    return NULL;
+  if (!(whole_type->details & __class_type_info::private_base_mask))
+    // whole type has no private bases
+    return const_cast <void *> (result.dst_ptr);
+  if (result.dst2src == __class_type_info::unknown)
+    result.dst2src = dst_type->find_public_src (src2dst, result.dst_ptr,
+                                                src_type, src_ptr);
+  if (contained_public_p (result.dst2src))
+    // Found a valid down cast
+    return const_cast <void *> (result.dst_ptr);
+  // Must be an invalid down cast, or the cross cast wasn't bettered
+  return NULL;
+}
+
+}; // namespace std
+#endif
index 9bf06cab3d2e960d17b0a88c0ed0a15c3def00ab..2894ed6ca154756c766edd99afba8d8fd53099de 100644 (file)
@@ -5,6 +5,9 @@
 
 // Class declarations shared between the typeinfo implementation files.
 
+#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100
+// original (old) abi
+
 // type_info for a class with no base classes (or an enum).
 
 struct __user_type_info : public std::type_info {
@@ -167,11 +170,7 @@ public:
 
 // type_info for a general class.
 
-#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
 typedef int USItype __attribute__ ((mode (SI)));
-#else
-typedef unsigned int USItype   __attribute__ ((mode (SI)));
-#endif
 
 struct __class_type_info : public __user_type_info {
   enum access { PUBLIC = 1, PROTECTED = 2, PRIVATE = 3 };
@@ -200,3 +199,230 @@ struct __class_type_info : public __user_type_info {
   virtual sub_kind do_find_public_subobj (int boff, const type_info &subtype,
                                           void *objptr, void *subptr) const;
 };
+#else
+// new abi
+#include "stddef.h"
+
+typedef int USItype __attribute__ ((mode (SI)));
+
+namespace std {
+
+class __class_type_info;
+
+// helper class for __vmi_class_type
+struct __base_class_info {
+  const __class_type_info *type;  // base class type
+  ptrdiff_t offset;               // offset to the sub object
+  int vmi_flags;                  // about the base
+
+// implementation specific parts
+  enum vmi_masks {
+    virtual_mask = 0x1,
+    public_mask = 0x2,
+    hwm_bit = 2
+  };
+  
+public:
+  bool is_virtual_p () const
+    { return vmi_flags & virtual_mask; }
+  bool is_public_p () const
+    { return vmi_flags & public_mask; }
+};
+
+// type information for a class
+class __class_type_info : public type_info {
+protected:
+  virtual ~__class_type_info ();
+public:
+  int details;      // details about the class heirarchy
+
+// implementation specific parts
+  enum detail_masks {
+    multiple_base_mask = 0x1,   // multiple inheritance of the same base type
+    polymorphic_mask = 0x2,     // is a polymorphic type
+    virtual_base_mask = 0x4,    // has virtual bases (direct or indirect)
+    private_base_mask = 0x8     // has private bases (direct or indirect)
+  };
+
+public:
+  // sub_kind tells us about how a base object is contained within a derived
+  // object. We often do this lazily, hence the UNKNOWN value. At other times
+  // we may use NOT_CONTAINED to mean not publicly contained.
+  enum sub_kind
+  {
+    unknown = 0,              // we have no idea
+    not_contained,            // not contained within us (in some
+                              // circumstances this might mean not contained
+                              // publicly)
+    contained_ambig,          // contained ambiguously
+    
+    contained_virtual_mask = __base_class_info::virtual_mask, // via a virtual path
+    contained_public_mask = __base_class_info::public_mask,   // via a public path
+    contained_mask = 1 << __base_class_info::hwm_bit,         // contained within us
+    
+    contained_private = contained_mask,
+    contained_public = contained_mask | contained_public_mask
+  };
+
+public:  
+  struct upcast_result
+  {
+    const void *dst_ptr;        // pointer to caught object
+    sub_kind whole2dst;         // path from most derived object to target
+    int src_details;            // hints about the source type
+    const __class_type_info *base_type; // where we found the target,
+                                // if in vbase the __class_type_info of vbase
+                                // if a non-virtual base then 1
+                                // else NULL
+    public:
+    upcast_result (int d)
+      :dst_ptr (NULL), whole2dst (unknown), src_details (d), base_type (NULL)
+      {}
+  };
+
+public:
+  // dyncast_result is used to hold information during traversal of a class
+  // heirarchy when dynamic casting.
+  struct dyncast_result
+  {
+    const void *dst_ptr;        // pointer to target object or NULL
+    sub_kind whole2dst;         // path from most derived object to target
+    sub_kind whole2src;         // path from most derived object to sub object
+    sub_kind dst2src;           // path from target to sub object
+    
+    public:
+    dyncast_result ()
+      :dst_ptr (NULL), whole2dst (unknown),
+       whole2src (unknown), dst2src (unknown)
+      {}
+  };
+
+public:
+  explicit __class_type_info (const char *n,
+                              int details_)
+    : type_info (n), details (details_)
+    { }
+
+protected:
+  virtual bool do_upcast (const __class_type_info *dst_type, void **obj_ptr) const;
+
+protected:
+  virtual bool do_catch (const type_info *thr_type, void **thr_obj,
+                         unsigned outer) const;
+
+
+public:
+  // Helper for upcast. See if DST is us, or one of our bases. ACCESS_PATH
+  // gives the access from the start object. Return TRUE if we know the upcast
+  // fails.
+  virtual bool do_upcast (sub_kind access_path,
+                          const __class_type_info *dst, const void *obj,
+                          upcast_result &__restrict result) const;
+
+public:
+  // Indicate whether SRC_PTR of type SRC_TYPE is contained publicly within
+  // OBJ_PTR. OBJ_PTR points to a base object of our type, which is the
+  // destination type. SRC2DST indicates how SRC objects might be contained
+  // within this type.  If SRC_PTR is one of our SRC_TYPE bases, indicate the
+  // virtuality. Returns not_contained for non containment or private
+  // containment.
+  inline sub_kind find_public_src (ptrdiff_t src2dst, const void *obj_ptr,
+                                   const __class_type_info *src_type,
+                                   const void *src_ptr) const;
+
+public:
+  // dynamic cast helper. ACCESS_PATH gives the access from the most derived
+  // object to this base. DST_TYPE indicates the desired type we want. OBJ_PTR
+  // points to a base of our type within the complete object. SRC_TYPE
+  // indicates the static type started from and SRC_PTR points to that base
+  // within the most derived object. Fill in RESULT with what we find. Return
+  // true if we have located an ambiguous match.
+  virtual bool do_dyncast (ptrdiff_t src2dst, sub_kind access_path,
+                           const __class_type_info *dst_type, const void *obj_ptr,
+                           const __class_type_info *src_type, const void *src_ptr,
+                           dyncast_result &result) const;
+public:
+  // Helper for find_public_subobj. SRC2DST indicates how SRC_TYPE bases are
+  // inherited by the type started from -- which is not necessarily the
+  // current type. The current type will be a base of the destination type.
+  // OBJ_PTR points to the current base.
+  virtual sub_kind do_find_public_src (ptrdiff_t src2dst, const void *obj_ptr,
+                                       const __class_type_info *src_type,
+                                       const void *src_ptr) const;
+};
+
+// type information for a class with a single non-virtual base
+class __si_class_type_info : public __class_type_info {
+protected:
+  virtual ~__si_class_type_info ();
+protected:
+  const __class_type_info *base;    // base type
+
+public:
+  explicit __si_class_type_info (const char *n,
+                                 int details_,
+                                 const __class_type_info *base_)
+    : __class_type_info (n, details_), base (base_)
+    { }
+
+// implementation specific parts
+protected:
+  virtual bool do_dyncast (ptrdiff_t src2dst, sub_kind access_path,
+                           const __class_type_info *dst_type, const void *obj_ptr,
+                           const __class_type_info *src_type, const void *src_ptr,
+                           dyncast_result &result) const;
+  virtual sub_kind do_find_public_src (ptrdiff_t src2dst, const void *obj_ptr,
+                                       const __class_type_info *src_type,
+                                       const void *sub_ptr) const;
+  virtual bool do_upcast (sub_kind access_path,
+                          const __class_type_info *dst, const void *obj,
+                          upcast_result &__restrict result) const;
+};
+
+// type information for a class with multiple and/or virtual bases
+class __vmi_class_type_info : public __class_type_info {
+protected:
+  virtual ~__vmi_class_type_info ();
+protected:
+  int n_bases;      // number of direct bases
+  __base_class_info base_list[1]; // array of bases
+  // The array of bases uses the trailing array struct hack
+  // so this class is not constructable with a normal constructor. It is
+  // internally generated by the compiler.
+
+public:
+  explicit __vmi_class_type_info (const char *n,
+                                  int details_)
+    : __class_type_info (n, details_), n_bases (0)
+    { }
+
+// implementation specific parts
+protected:
+  virtual bool do_dyncast (ptrdiff_t src2dst, sub_kind access_path,
+                           const __class_type_info *dst_type, const void *obj_ptr,
+                           const __class_type_info *src_type, const void *src_ptr,
+                           dyncast_result &result) const;
+  virtual sub_kind do_find_public_src (ptrdiff_t src2dst, const void *obj_ptr,
+                                       const __class_type_info *src_type,
+                                       const void *src_ptr) const;
+  virtual bool do_upcast (sub_kind access_path,
+                          const __class_type_info *dst, const void *obj,
+                          upcast_result &__restrict result) const;
+};
+
+// dynamic cast runtime
+void *__dynamic_cast (const void *src_ptr,    // object started from
+                      const __class_type_info *src_type, // static type of object
+                      const __class_type_info *dst_type, // desired target type
+                      ptrdiff_t src2dst); // how src and dst are related
+
+    // src2dst has the following possible values
+    // >= 0: src_type is a unique public non-virtual base of dst_type
+    //       dst_ptr + src2dst == src_ptr
+    // -1: unspecified relationship
+    // -2: src_type is not a public base of dst_type
+    // -3: src_type is a multiple public non-virtual base of dst_type
+
+}; // namespace std
+
+#endif
index f1b9d92f8f5b63bdc3006e8da4a66b204da824ea..3f879c2e4b92085221cd4063e58728236e9f2529 100644 (file)
@@ -31,6 +31,7 @@
 
 using std::type_info;
 
+#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100
 bool
 type_info::before (const type_info &arg) const
 {
@@ -88,6 +89,248 @@ struct __array_type_info : public type_info {
   __array_type_info (const char *n): type_info (n) {}
 };
 
+#else
+
+namespace std {
+  
+// type information for int, float etc
+class __fundamental_type_info : public type_info {
+public:
+  virtual ~__fundamental_type_info ();
+public:
+  explicit __fundamental_type_info (const char *n)
+    : type_info (n)
+    { }
+};
+
+// type information for pointer to data or function, but not pointer to member
+class __pointer_type_info : public type_info {
+public:
+  virtual ~__pointer_type_info ();
+// external parts
+  int quals;                // qualification of the target object
+  const type_info *target;  // type of object being pointed to
+
+// internal parts
+  enum quals_masks {
+    const_mask = 0x1,
+    volatile_mask = 0x2
+  };
+  
+public:
+  explicit __pointer_type_info (const char *n,
+                                int quals_,
+                                const type_info *target_)
+    : type_info (n), quals (quals_), target (target_)
+    { }
+
+protected:
+  virtual bool is_pointer_p () const;
+  virtual bool do_catch (const type_info *thr_type, void **thr_obj,
+                         unsigned outer) const;
+};
+
+// type information for reference to data
+class __reference_type_info : public type_info {
+public:
+  virtual ~__reference_type_info ();
+  int quals;                // qualification of the target object
+  const type_info *target;  // type of object being referenced
+
+// internal parts
+  enum quals_masks {
+    const_mask = 0x1,
+    volatile_mask = 0x2
+  };
+  
+public:
+  explicit __reference_type_info (const char *n,
+                                  int quals_,
+                                  const type_info *target_)
+    : type_info (n), quals (quals_), target (target_)
+    { }
+};
+
+// type information for array objects
+class __array_type_info : public type_info {
+public:
+  virtual ~__array_type_info ();
+public:
+  explicit __array_type_info (const char *n)
+    : type_info (n)
+    { }
+};
+
+// type information for functions (both member and non-member)
+class __function_type_info : public type_info {
+public:
+  virtual ~__function_type_info ();
+public:
+  explicit __function_type_info (const char *n)
+    : type_info (n)
+    { }
+protected:
+  virtual bool is_function_p () const;
+};
+
+// type information for enumerations
+class __enum_type_info : public type_info {
+public:
+  virtual ~__enum_type_info ();
+public:
+  explicit __enum_type_info (const char *n)
+    : type_info (n)
+    { }
+};
+
+// type information for a pointer to member variable (not function)
+class __ptr_to_member_type_info : public type_info {
+public:
+  virtual ~__ptr_to_member_type_info ();
+// external parts
+  const __class_type_info *klass;   // class of the member
+  const type_info *type;            // type of the member
+  int quals;                        // qualifications of the pointed to type
+
+// internal parts
+  enum quals_masks {
+    const_mask = 0x1,
+    volatile_mask = 0x2
+  };
+
+public:
+  explicit __ptr_to_member_type_info (const char *n,
+                                      const __class_type_info *klass_,
+                                      const type_info *type_,
+                                      int quals_)
+    : type_info (n), klass (klass_), type (type_), quals (quals_)
+    { }
+
+protected:
+  virtual bool do_catch (const type_info *thr_type, void **thr_obj,
+                         unsigned outer) const;
+};
+
+}; // namespace std
+
+#endif
+
+#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
+namespace std {
+
+// This has special meaning to the compiler, and will cause it
+// to emit the type_info structures for the fundamental types which are
+// mandated to exist in the runtime.
+__fundamental_type_info::
+~__fundamental_type_info ()
+{}
+
+__pointer_type_info::
+~__pointer_type_info ()
+{}
+
+__reference_type_info::
+~__reference_type_info ()
+{}
+
+__array_type_info::
+~__array_type_info ()
+{}
+
+__function_type_info::
+~__function_type_info ()
+{}
+
+__enum_type_info::
+~__enum_type_info ()
+{}
+
+__ptr_to_member_type_info::
+~__ptr_to_member_type_info ()
+{}
+
+bool __pointer_type_info::
+is_pointer_p () const
+{
+  return true;
+}
+
+bool __function_type_info::
+is_function_p () const
+{
+  return true;
+}
+
+bool __pointer_type_info::
+do_catch (const type_info *thr_type,
+          void **thr_obj,
+          unsigned outer) const
+{
+  if (*this == *thr_type)
+    return true;      // same type
+  if (typeid (*this) != typeid (*thr_type))
+    return false;     // not both pointers
+  
+  if (!(outer & 1))
+    // We're not the same and our outer pointers are not all const qualified
+    // Therefore there must at least be a qualification conversion involved
+    // But for that to be valid, our outer pointers must be const qualified.
+    return false;
+  
+  const __pointer_type_info *thrown_type =
+    static_cast <const __pointer_type_info *> (thr_type);
+  
+  if (thrown_type->quals & ~quals)
+    // We're less qualified.
+    return false;
+  
+  if (!(quals & const_mask))
+    outer &= ~1;
+  
+  if (outer < 2 && *target == typeid (void))
+    {
+      // conversion to void
+      return !thrown_type->is_function_p ();
+    }
+  
+  return target->do_catch (thrown_type->target, thr_obj, outer + 2);
+}
+
+bool __ptr_to_member_type_info::
+do_catch (const type_info *thr_type,
+          void **thr_obj,
+          unsigned outer) const
+{
+  if (*this == *thr_type)
+    return true;      // same type
+  if (typeid (*this) != typeid (*thr_type))
+    return false;     // not both pointers to member
+  
+  if (!(outer & 1))
+    // We're not the same and our outer pointers are not all const qualified
+    // Therefore there must at least be a qualification conversion involved.
+    // But for that to be valid, our outer pointers must be const qualified.
+    return false;
+  
+  const __ptr_to_member_type_info *thrown_type =
+    static_cast <const __ptr_to_member_type_info *> (thr_type);
+  
+  if (thrown_type->quals & ~quals)
+    // We're less qualified.
+    return false;
+  
+  if (!(quals & const_mask))
+    outer &= ~1;
+  
+  if (*klass != *thrown_type->klass)
+    return false;     // not pointers to member of same class
+  
+  return type->do_catch (thrown_type->type, thr_obj, outer + 2);
+}
+
+} // namespace std
+#endif
+
 // Entry points for the compiler.
 
 /* Low level match routine used by compiler to match types of catch
@@ -102,6 +345,8 @@ __throw_type_match_rtti_2 (const void *catch_type_r, const void *throw_type_r,
 
   *valp = objptr;
 
+#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100
+// old abi
   if (catch_type == throw_type)
     return 1;
   
@@ -213,10 +458,15 @@ __throw_type_match_rtti_2 (const void *catch_type_r, const void *throw_type_r,
            }
        }
     }
-
+#else
+// new abi
+  
+  return catch_type.do_catch (&throw_type, valp, 1);
+#endif
   return 0;
 }
 
+#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100
 /* Backward compatibility wrapper.  */
 
 extern "C" void*
@@ -228,6 +478,7 @@ __throw_type_match_rtti (const void *catch_type_r, const void *throw_type_r,
     return ret;
   return NULL;
 }
+#endif
 
 /* Called from __cp_pop_exception.  Is P the type_info node for a pointer
    of some kind?  */
@@ -236,11 +487,20 @@ bool
 __is_pointer (void *p)
 {
   const type_info *t = reinterpret_cast <const type_info *>(p);
+#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100
+// old abi
   const __pointer_type_info *pt =
     dynamic_cast <const __pointer_type_info *> (t);
   return pt != 0;
+#else
+// new abi
+  return t->is_pointer_p ();
+#endif
 }
 
+#if !defined(__GXX_ABI_VERSION) || __GXX_ABI_VERSION < 100
+// old abi
+
 extern "C" void
 __rtti_ptr (void *addr, const char *n, const type_info *ti)
 { new (addr) __pointer_type_info (n, *ti); }
@@ -302,3 +562,10 @@ BUILTIN (v); BUILTIN (x); BUILTIN (l); BUILTIN (i); BUILTIN (s); BUILTIN (b);
 BUILTIN (c); BUILTIN (w); BUILTIN (r); BUILTIN (d); BUILTIN (f);
 BUILTIN (Ui); BUILTIN (Ul); BUILTIN (Ux); BUILTIN (Us); BUILTIN (Uc);
 BUILTIN (Sc);
+#else
+// new abi
+
+// we need to define the fundamental type type_info's, but the name mangling is
+// not yet defined.
+
+#endif