Date: Tue, 20 Mar 2012 17:58:15 +0000 (UTC) From: David Chisnall <theraven@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r233235 - in head: contrib/libcxxrt lib/libcxxrt Message-ID: <201203201758.q2KHwFKC030826@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: theraven Date: Tue Mar 20 17:58:15 2012 New Revision: 233235 URL: http://svn.freebsd.org/changeset/base/233235 Log: Import new version of libcxxrt. Now works correctly with libobjc2 to implement the unified exception model for Objective-C++. Approved by: dim (mentor) Deleted: head/contrib/libcxxrt/typeinfo Modified: head/contrib/libcxxrt/dynamic_cast.cc head/contrib/libcxxrt/exception.cc head/contrib/libcxxrt/typeinfo.h head/lib/libcxxrt/Version.map Directory Properties: head/contrib/libcxxrt/ (props changed) Modified: head/contrib/libcxxrt/dynamic_cast.cc ============================================================================== --- head/contrib/libcxxrt/dynamic_cast.cc Tue Mar 20 17:43:30 2012 (r233234) +++ head/contrib/libcxxrt/dynamic_cast.cc Tue Mar 20 17:58:15 2012 (r233235) @@ -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 *o 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 } 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(voi // 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(voi } 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*). Modified: head/contrib/libcxxrt/exception.cc ============================================================================== --- head/contrib/libcxxrt/exception.cc Tue Mar 20 17:43:30 2012 (r233234) +++ head/contrib/libcxxrt/exception.cc Tue Mar 20 17:58:15 2012 (r233235) @@ -847,14 +847,11 @@ static bool check_type_signature(__cxa_e 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_e // // 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_e 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_e 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; } /** Modified: head/contrib/libcxxrt/typeinfo.h ============================================================================== --- head/contrib/libcxxrt/typeinfo.h Tue Mar 20 17:43:30 2012 (r233234) +++ head/contrib/libcxxrt/typeinfo.h Tue Mar 20 17:58:15 2012 (r233235) @@ -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; }; /** Modified: head/lib/libcxxrt/Version.map ============================================================================== --- head/lib/libcxxrt/Version.map Tue Mar 20 17:43:30 2012 (r233234) +++ head/lib/libcxxrt/Version.map Tue Mar 20 17:58:15 2012 (r233235) @@ -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)";
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203201758.q2KHwFKC030826>