diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-11-02 23:41:51 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-11-02 23:41:51 +0000 |
commit | c320e4c36c06bc0019fc06eaf00eb064727cfcc0 (patch) | |
tree | 0e19e37ba3da6ba3ca9006cf02789390097d3199 /src | |
parent | 8b9be6632eaacf36aa6f2f974d46a470403fcf68 (diff) |
[p0012] Implement ABI support for throwing a noexcept function pointer and
catching as non-noexcept
This implements the following proposal from cxx-abi-dev:
http://sourcerytools.com/pipermail/cxx-abi-dev/2016-October/002988.html
... which is necessary for complete support of http://wg21.link/p0012,
specifically throwing noexcept function and member function pointers and
catching them as non-noexcept pointers.
Differential Review: https://reviews.llvm.org/D26178
git-svn-id: https://llvm.org/svn/llvm-project/libcxxabi/trunk@285867 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'src')
-rw-r--r-- | src/private_typeinfo.cpp | 47 | ||||
-rw-r--r-- | src/private_typeinfo.h | 27 |
2 files changed, 73 insertions, 1 deletions
diff --git a/src/private_typeinfo.cpp b/src/private_typeinfo.cpp index 73ef362..6112a1f 100644 --- a/src/private_typeinfo.cpp +++ b/src/private_typeinfo.cpp @@ -105,6 +105,45 @@ __function_type_info::~__function_type_info() { } +// __qualified_function_type_info + +__qualified_function_type_info::~__qualified_function_type_info() +{ +} + +// Determine if a function pointer conversion can convert a pointer (or pointer +// to member) to type x into a pointer (or pointer to member) to type y. +static bool is_function_pointer_conversion(const std::type_info* x, + const std::type_info* y) +{ + const unsigned int discardable_quals = + __qualified_function_type_info::__noexcept_mask | + __qualified_function_type_info::__transaction_safe_mask | + __qualified_function_type_info::__noreturn_mask; + + // If x has only discardable qualifiers and y is unqualified, then + // conversion is permitted. + const __qualified_function_type_info* qual_x = + dynamic_cast<const __qualified_function_type_info *>(x); + if (!qual_x) + return false; + if ((qual_x->__qualifiers & ~discardable_quals) == 0 && + is_equal(qual_x->__base_type, y, false)) + return true; + + // Otherwise, x's qualifiers must be the same as y's, plus some discardable + // ones. + const __qualified_function_type_info* qual_y = + dynamic_cast<const __qualified_function_type_info *>(y); + if (!qual_y) + return false; + if (qual_y->__qualifiers & ~qual_x->__qualifiers) + return false; + if (qual_x->__qualifiers & ~qual_y->__qualifiers & ~discardable_quals) + return false; + return is_equal(qual_x->__base_type, qual_y->__base_type, false); +} + // __enum_type_info __enum_type_info::~__enum_type_info() @@ -395,6 +434,10 @@ __pointer_type_info::can_catch(const __shim_type_info* thrown_type, return false; if (is_equal(__pointee, thrown_pointer_type->__pointee, false)) return true; + // bullet 3C + if (is_function_pointer_conversion(thrown_pointer_type->__pointee, + __pointee)) + return true; // bullet 3A if (is_equal(__pointee, &typeid(void), false)) { // pointers to functions cannot be converted to void*. @@ -502,7 +545,9 @@ bool __pointer_to_member_type_info::can_catch( return false; if (thrown_pointer_type->__flags & ~__flags) return false; - if (!is_equal(__pointee, thrown_pointer_type->__pointee, false)) + if (!is_equal(__pointee, thrown_pointer_type->__pointee, false) && + !is_function_pointer_conversion(thrown_pointer_type->__pointee, + __pointee)) return false; if (is_equal(__context, thrown_pointer_type->__context, false)) return true; diff --git a/src/private_typeinfo.h b/src/private_typeinfo.h index ef98c3a..fa6bd63 100644 --- a/src/private_typeinfo.h +++ b/src/private_typeinfo.h @@ -49,6 +49,33 @@ public: void *&) const; }; +// This implements the following proposal from cxx-abi-dev (not yet part of the +// ABI document): +// +// http://sourcerytools.com/pipermail/cxx-abi-dev/2016-October/002988.html +// +// This is necessary for support of http://wg21.link/p0012, which permits throwing +// noexcept function and member function pointers and catching them as non-noexcept +// pointers. +class _LIBCXXABI_TYPE_VIS __qualified_function_type_info : public __shim_type_info { +public: + const __function_type_info* __base_type; + unsigned int __qualifiers; + + enum __qualifiers_mask { + __const_mask = 0x01, + __volatile_mask = 0x02, + __restrict_mask = 0x04, + __lval_ref_mask = 0x08, + __rval_ref_mask = 0x10, + __noexcept_mask = 0x20, + __transaction_safe_mask = 0x40, + __noreturn_mask = 0x80 + }; + + _LIBCXXABI_HIDDEN virtual ~__qualified_function_type_info(); +}; + class _LIBCXXABI_TYPE_VIS __enum_type_info : public __shim_type_info { public: _LIBCXXABI_HIDDEN virtual ~__enum_type_info(); |