Import new version of libcxxrt. Now works correctly with libobjc2 to implement

the unified exception model for Objective-C++.

Approved by:	dim (mentor)
This commit is contained in:
David Chisnall 2012-03-20 17:58:15 +00:00
commit c725650d64
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=233235
5 changed files with 187 additions and 105 deletions

View File

@ -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*).

View File

@ -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;
}
/**

View File

@ -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;
};
}

View File

@ -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;
};
/**

View File

@ -301,6 +301,11 @@ CXXRT_1.0 {
"typeinfo name for std::exception";
"typeinfo name for std::type_info";
"std::type_info::__is_function_p() const";
"std::type_info::__do_upcast(__cxxabiv1::__class_type_info const*, void**) const";
"std::type_info::__is_pointer_p() const";
"operator delete[](void*)";
"operator delete(void*)";
"operator new[](unsigned long)";