Import new version of libcxxrt to vendor branch.
Approved by: dim (mentor)
This commit is contained in:
parent
c28183e940
commit
60e0399a08
107
dynamic_cast.cc
107
dynamic_cast.cc
@ -46,9 +46,65 @@ struct vtable_header
|
||||
*/
|
||||
#define ADD_TO_PTR(x, off) (__typeof__(x))(((char*)x) + off)
|
||||
|
||||
bool __class_type_info::can_cast_to(const struct __class_type_info *other) const
|
||||
bool std::type_info::__do_catch(std::type_info const *ex_type,
|
||||
void **exception_object,
|
||||
unsigned int outer) const
|
||||
{
|
||||
return this == other;
|
||||
const type_info *type = this;
|
||||
|
||||
if (type == ex_type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (const __class_type_info *cti = dynamic_cast<const __class_type_info *>(type))
|
||||
{
|
||||
return ex_type->__do_upcast(cti, exception_object);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool __pbase_type_info::__do_catch(std::type_info const *ex_type,
|
||||
void **exception_object,
|
||||
unsigned int outer) const
|
||||
{
|
||||
if (ex_type == this)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!ex_type->__is_pointer_p())
|
||||
{
|
||||
// Can't catch a non-pointer type in a pointer catch
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(outer & 1))
|
||||
{
|
||||
// If the low bit is cleared on this means that we've gone
|
||||
// through a pointer that is not const qualified.
|
||||
return false;
|
||||
}
|
||||
// Clear the low bit on outer if we're not const qualified.
|
||||
if (!(__flags & __const_mask))
|
||||
{
|
||||
outer &= ~1;
|
||||
}
|
||||
|
||||
const __pbase_type_info *ptr_type =
|
||||
static_cast<const __pbase_type_info*>(ex_type);
|
||||
|
||||
if (ptr_type->__flags & ~__flags)
|
||||
{
|
||||
// Handler pointer is less qualified
|
||||
return false;
|
||||
}
|
||||
|
||||
// Special case for void* handler.
|
||||
if(*__pointee == typeid(void))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return __pointee->__do_catch(ptr_type->__pointee, exception_object, outer);
|
||||
}
|
||||
|
||||
void *__class_type_info::cast_to(void *obj, const struct __class_type_info *other) const
|
||||
@ -60,12 +116,6 @@ void *__class_type_info::cast_to(void *obj, const struct __class_type_info *othe
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool __si_class_type_info::can_cast_to(const struct __class_type_info *other) const
|
||||
{
|
||||
return this == other || __base_type->can_cast_to(other);
|
||||
}
|
||||
|
||||
void *__si_class_type_info::cast_to(void *obj, const struct __class_type_info *other) const
|
||||
{
|
||||
if (this == other)
|
||||
@ -74,31 +124,32 @@ void *__si_class_type_info::cast_to(void *obj, const struct __class_type_info *o
|
||||
}
|
||||
return __base_type->cast_to(obj, other);
|
||||
}
|
||||
|
||||
|
||||
bool __vmi_class_type_info::can_cast_to(const struct __class_type_info *other) const
|
||||
bool __si_class_type_info::__do_upcast(const __class_type_info *target,
|
||||
void **thrown_object) const
|
||||
{
|
||||
if (this == other)
|
||||
if (this == target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
for (unsigned int i=0 ; i<__base_count ; i++)
|
||||
{
|
||||
const __base_class_type_info *info = &__base_info[i];
|
||||
if(info->isPublic() && info->__base_type->can_cast_to(other))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return __base_type->__do_upcast(target, thrown_object);
|
||||
}
|
||||
|
||||
void *__vmi_class_type_info::cast_to(void *obj, const struct __class_type_info *other) const
|
||||
{
|
||||
if (this == other)
|
||||
if (__do_upcast(other, &obj))
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool __vmi_class_type_info::__do_upcast(const __class_type_info *target,
|
||||
void **thrown_object) const
|
||||
{
|
||||
if (this == target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
for (unsigned int i=0 ; i<__base_count ; i++)
|
||||
{
|
||||
const __base_class_type_info *info = &__base_info[i];
|
||||
@ -111,6 +162,7 @@ void *__vmi_class_type_info::cast_to(void *obj, const struct __class_type_info *
|
||||
// virtual table of the virtual base offset for the virtual base
|
||||
// referenced (negative).'
|
||||
|
||||
void *obj = *thrown_object;
|
||||
if (info->isVirtual())
|
||||
{
|
||||
// Object's vtable
|
||||
@ -121,18 +173,17 @@ void *__vmi_class_type_info::cast_to(void *obj, const struct __class_type_info *
|
||||
}
|
||||
void *cast = ADD_TO_PTR(obj, offset);
|
||||
|
||||
if (info->__base_type == other)
|
||||
if (info->__base_type == target ||
|
||||
(info->__base_type->__do_upcast(target, &cast)))
|
||||
{
|
||||
return cast;
|
||||
}
|
||||
if ((cast = info->__base_type->cast_to(cast, other)))
|
||||
{
|
||||
return cast;
|
||||
*thrown_object = cast;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ABI function used to implement the dynamic_cast<> operator. Some cases of
|
||||
* this operator are implemented entirely in the compiler (e.g. to void*).
|
||||
|
47
exception.cc
47
exception.cc
@ -847,14 +847,11 @@ static bool check_type_signature(__cxa_exception *ex,
|
||||
const std::type_info *type,
|
||||
void *&adjustedPtr)
|
||||
{
|
||||
// TODO: For compatibility with the GNU implementation, we should move this
|
||||
// out into a __do_catch() virtual function in std::type_info
|
||||
void *exception_ptr = (void*)(ex+1);
|
||||
const std::type_info *ex_type = ex->exceptionType;
|
||||
const std::type_info *ex_type = ex->exceptionType;
|
||||
|
||||
const __pointer_type_info *ptr_type =
|
||||
dynamic_cast<const __pointer_type_info*>(ex_type);
|
||||
if (0 != ptr_type)
|
||||
bool is_ptr = ex_type->__is_pointer_p();
|
||||
if (is_ptr)
|
||||
{
|
||||
exception_ptr = *(void**)exception_ptr;
|
||||
}
|
||||
@ -862,11 +859,6 @@ static bool check_type_signature(__cxa_exception *ex,
|
||||
//
|
||||
// Note: A 0 here is a catchall, not a cleanup, so we return true to
|
||||
// indicate that we found a catch.
|
||||
//
|
||||
// TODO: Provide a class for matching against foreign exceptions. This is
|
||||
// already done in libobjc2, allowing C++ exceptions to be boxed as
|
||||
// Objective-C objects. We should do something similar, allowing foreign
|
||||
// exceptions to be wrapped in a C++ exception and delivered.
|
||||
if (0 == type)
|
||||
{
|
||||
if (ex)
|
||||
@ -878,28 +870,6 @@ static bool check_type_signature(__cxa_exception *ex,
|
||||
|
||||
if (0 == ex) { return false; }
|
||||
|
||||
const __pointer_type_info *target_ptr_type =
|
||||
dynamic_cast<const __pointer_type_info*>(type);
|
||||
|
||||
if (0 != ptr_type && 0 != target_ptr_type)
|
||||
{
|
||||
if (ptr_type->__flags & ~target_ptr_type->__flags)
|
||||
{
|
||||
// Handler pointer is less qualified
|
||||
return false;
|
||||
}
|
||||
|
||||
// Special case for void* handler.
|
||||
if(*target_ptr_type->__pointee == typeid(void))
|
||||
{
|
||||
adjustedPtr = exception_ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
ex_type = ptr_type->__pointee;
|
||||
type = target_ptr_type->__pointee;
|
||||
}
|
||||
|
||||
// If the types are the same, no casting is needed.
|
||||
if (*type == *ex_type)
|
||||
{
|
||||
@ -907,18 +877,13 @@ static bool check_type_signature(__cxa_exception *ex,
|
||||
return true;
|
||||
}
|
||||
|
||||
const __class_type_info *cls_type =
|
||||
dynamic_cast<const __class_type_info*>(ex_type);
|
||||
const __class_type_info *target_cls_type =
|
||||
dynamic_cast<const __class_type_info*>(type);
|
||||
|
||||
if (0 != cls_type &&
|
||||
0 != target_cls_type &&
|
||||
cls_type->can_cast_to(target_cls_type))
|
||||
if (type->__do_catch(ex_type, &exception_ptr, 1))
|
||||
{
|
||||
adjustedPtr = cls_type->cast_to(exception_ptr, target_cls_type);
|
||||
adjustedPtr = exception_ptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
|
26
typeinfo
26
typeinfo
@ -1,26 +0,0 @@
|
||||
namespace std
|
||||
{
|
||||
/**
|
||||
* Standard type info class. The layout of this class is specified by the
|
||||
* ABI.
|
||||
*/
|
||||
class type_info
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Virtual destructor. This class must have one virtual function to
|
||||
* ensure that it has a vtable.
|
||||
*/
|
||||
virtual ~type_info();
|
||||
bool operator==(const type_info &) const;
|
||||
bool operator!=(const type_info &) const;
|
||||
bool before(const type_info &) const;
|
||||
const char* name() const;
|
||||
type_info();
|
||||
private:
|
||||
type_info(const type_info& rhs);
|
||||
type_info& operator= (const type_info& rhs);
|
||||
const char *__type_name;
|
||||
};
|
||||
}
|
||||
|
107
typeinfo.h
107
typeinfo.h
@ -26,7 +26,86 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include "abi_namespace.h"
|
||||
#include "typeinfo"
|
||||
|
||||
namespace ABI_NAMESPACE
|
||||
{
|
||||
struct __class_type_info;
|
||||
}
|
||||
namespace std
|
||||
{
|
||||
/**
|
||||
* Standard type info class. The layout of this class is specified by the
|
||||
* ABI. The layout of the vtable is not, but is intended to be
|
||||
* compatible with the GNU ABI.
|
||||
*
|
||||
* Unlike the GNU version, the vtable layout is considered semi-private.
|
||||
*/
|
||||
class type_info
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Virtual destructor. This class must have one virtual function to
|
||||
* ensure that it has a vtable.
|
||||
*/
|
||||
virtual ~type_info();
|
||||
bool operator==(const type_info &) const;
|
||||
bool operator!=(const type_info &) const;
|
||||
bool before(const type_info &) const;
|
||||
const char* name() const;
|
||||
type_info();
|
||||
private:
|
||||
type_info(const type_info& rhs);
|
||||
type_info& operator= (const type_info& rhs);
|
||||
const char *__type_name;
|
||||
/*
|
||||
* The following functions are in this order to match the
|
||||
* vtable layout of libsupc++. This allows libcxxrt to be used
|
||||
* with libraries that depend on this.
|
||||
*
|
||||
* These functions are in the public headers for libstdc++, so
|
||||
* we have to assume that someone will probably call them and
|
||||
* expect them to work. Their names must also match the names used in
|
||||
* libsupc++, so that code linking against this library can subclass
|
||||
* type_info and correctly fill in the values in the vtables.
|
||||
*/
|
||||
public:
|
||||
/**
|
||||
* Catch function. Allows external libraries to implement
|
||||
* their own basic types. This is used, for example, in the
|
||||
* GNUstep Objective-C runtime to allow Objective-C types to be
|
||||
* caught in G++ catch blocks.
|
||||
*
|
||||
* The outer parameter indicates the number of outer pointers
|
||||
* in the high bits. The low bit indicates whether the
|
||||
* pointers are const qualified.
|
||||
*/
|
||||
virtual bool __do_catch(const type_info *thrown_type,
|
||||
void **thrown_object,
|
||||
unsigned outer) const;
|
||||
/**
|
||||
* Performs an upcast. This is used in exception handling to
|
||||
* cast from subclasses to superclasses. If the upcast is
|
||||
* possible, it returns true and adjusts the pointer. If the
|
||||
* upcast is not possible, it returns false and does not adjust
|
||||
* the pointer.
|
||||
*/
|
||||
virtual bool __do_upcast(
|
||||
const ABI_NAMESPACE::__class_type_info *target,
|
||||
void **thrown_object) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns true if this is some pointer type, false otherwise.
|
||||
*/
|
||||
virtual bool __is_pointer_p() const { return false; }
|
||||
/**
|
||||
* Returns true if this is some function type, false otherwise.
|
||||
*/
|
||||
virtual bool __is_function_p() const { return false; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
namespace ABI_NAMESPACE
|
||||
{
|
||||
@ -50,6 +129,7 @@ namespace ABI_NAMESPACE
|
||||
struct __function_type_info : public std::type_info
|
||||
{
|
||||
virtual ~__function_type_info();
|
||||
virtual bool __is_function_p() const { return true; }
|
||||
};
|
||||
/**
|
||||
* Type info for enums.
|
||||
@ -68,13 +148,12 @@ namespace ABI_NAMESPACE
|
||||
/**
|
||||
* Function implementing dynamic casts.
|
||||
*/
|
||||
virtual void *cast_to(void *obj,
|
||||
const struct __class_type_info *other) const;
|
||||
/**
|
||||
* Function returning whether a cast from this type to another type is
|
||||
* possible.
|
||||
*/
|
||||
virtual bool can_cast_to(const struct __class_type_info *other) const;
|
||||
virtual void *cast_to(void *obj, const struct __class_type_info *other) const;
|
||||
virtual bool __do_upcast(const __class_type_info *target,
|
||||
void **thrown_object) const
|
||||
{
|
||||
return this == target;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -85,8 +164,10 @@ namespace ABI_NAMESPACE
|
||||
{
|
||||
virtual ~__si_class_type_info();
|
||||
const __class_type_info *__base_type;
|
||||
virtual bool __do_upcast(
|
||||
const ABI_NAMESPACE::__class_type_info *target,
|
||||
void **thrown_object) const;
|
||||
virtual void *cast_to(void *obj, const struct __class_type_info *other) const;
|
||||
virtual bool can_cast_to(const struct __class_type_info *other) const;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -166,8 +247,10 @@ namespace ABI_NAMESPACE
|
||||
/** The class is diamond shaped. */
|
||||
__diamond_shaped_mask = 0x2
|
||||
};
|
||||
virtual bool __do_upcast(
|
||||
const ABI_NAMESPACE::__class_type_info *target,
|
||||
void **thrown_object) const;
|
||||
virtual void *cast_to(void *obj, const struct __class_type_info *other) const;
|
||||
virtual bool can_cast_to(const struct __class_type_info *other) const;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -201,6 +284,10 @@ namespace ABI_NAMESPACE
|
||||
/** Pointer is a pointer to a member of an incomplete class. */
|
||||
__incomplete_class_mask = 0x10
|
||||
};
|
||||
virtual bool __is_pointer_p() const { return true; }
|
||||
virtual bool __do_catch(const type_info *thrown_type,
|
||||
void **thrown_object,
|
||||
unsigned outer) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user