cp-tree.h (new_abi_rtti_p): Use flag_new_abi.
* 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
This commit is contained in:
parent
ab5cffc5e8
commit
808c61c8d3
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
/* Language-dependent contents of an identifier. */
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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); }
|
||||
|
||||
inline bool type_info::
|
||||
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
|
||||
|
||||
// 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:
|
||||
|
|
602
gcc/cp/tinfo.cc
602
gcc/cp/tinfo.cc
|
@ -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
|
||||
|
|
234
gcc/cp/tinfo.h
234
gcc/cp/tinfo.h
|
@ -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
|
||||
|
|
269
gcc/cp/tinfo2.cc
269
gcc/cp/tinfo2.cc
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue