From 6afcab35887245f36751790ba33debaf74b0d2ee Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 2 Dec 2016 02:06:53 +0000 Subject: [PATCH] Update implementation of ABI support for throwing noexcept function pointers and catching as non-noexcept to match the final design per discusson on cxx-abi-dev. llvm-svn: 288457 --- libcxxabi/src/private_typeinfo.cpp | 57 +++---------------- libcxxabi/src/private_typeinfo.h | 44 ++++++-------- libcxxabi/test/catch_function_03.pass.cpp | 4 +- .../catch_member_function_pointer_02.pass.cpp | 4 +- libcxxabi/test/libcxxabi/test/config.py | 2 - 5 files changed, 30 insertions(+), 81 deletions(-) diff --git a/libcxxabi/src/private_typeinfo.cpp b/libcxxabi/src/private_typeinfo.cpp index 6112a1f92a94..e7995ed9fbfa 100644 --- a/libcxxabi/src/private_typeinfo.cpp +++ b/libcxxabi/src/private_typeinfo.cpp @@ -105,45 +105,6 @@ __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(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(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() @@ -429,15 +390,13 @@ __pointer_type_info::can_catch(const __shim_type_info* thrown_type, // Do the dereference adjustment if (adjustedPtr != NULL) adjustedPtr = *static_cast(adjustedPtr); - // bullet 3B - if (thrown_pointer_type->__flags & ~__flags) + // bullet 3B and 3C + if (thrown_pointer_type->__flags & ~__flags & __no_remove_flags_mask) + return false; + if (__flags & ~thrown_pointer_type->__flags & __no_add_flags_mask) 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*. @@ -543,11 +502,11 @@ bool __pointer_to_member_type_info::can_catch( dynamic_cast(thrown_type); if (thrown_pointer_type == 0) return false; - if (thrown_pointer_type->__flags & ~__flags) + if (thrown_pointer_type->__flags & ~__flags & __no_remove_flags_mask) return false; - if (!is_equal(__pointee, thrown_pointer_type->__pointee, false) && - !is_function_pointer_conversion(thrown_pointer_type->__pointee, - __pointee)) + if (__flags & ~thrown_pointer_type->__flags & __no_add_flags_mask) + return false; + if (!is_equal(__pointee, thrown_pointer_type->__pointee, false)) return false; if (is_equal(__context, thrown_pointer_type->__context, false)) return true; diff --git a/libcxxabi/src/private_typeinfo.h b/libcxxabi/src/private_typeinfo.h index fa6bd63eb096..f3d3e1dc3c95 100644 --- a/libcxxabi/src/private_typeinfo.h +++ b/libcxxabi/src/private_typeinfo.h @@ -49,33 +49,6 @@ 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(); @@ -233,7 +206,22 @@ public: __volatile_mask = 0x2, __restrict_mask = 0x4, __incomplete_mask = 0x8, - __incomplete_class_mask = 0x10 + __incomplete_class_mask = 0x10, + __transaction_safe_mask = 0x20, + // 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/002986.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. + __noexcept_mask = 0x40, + + // Flags that cannot be removed by a standard conversion. + __no_remove_flags_mask = __const_mask | __volatile_mask | __restrict_mask, + // Flags that cannot be added by a standard conversion. + __no_add_flags_mask = __transaction_safe_mask | __noexcept_mask }; _LIBCXXABI_HIDDEN virtual ~__pbase_type_info(); diff --git a/libcxxabi/test/catch_function_03.pass.cpp b/libcxxabi/test/catch_function_03.pass.cpp index 4118fde1d951..c0b33fd6b4ca 100644 --- a/libcxxabi/test/catch_function_03.pass.cpp +++ b/libcxxabi/test/catch_function_03.pass.cpp @@ -9,7 +9,7 @@ // Can a noexcept function pointer be caught by a non-noexcept catch clause? // UNSUPPORTED: c++98, c++03, c++11, c++14 -// UNSUPPORTED: libcxxabi-no-exceptions, libcxxabi-no-qualified-function-types +// UNSUPPORTED: libcxxabi-no-exceptions #include @@ -57,9 +57,11 @@ void check_deep() { int main() { +#ifdef __cpp_noexcept_function_type check(); check(); check(); check(); check_deep(); +#endif } diff --git a/libcxxabi/test/catch_member_function_pointer_02.pass.cpp b/libcxxabi/test/catch_member_function_pointer_02.pass.cpp index 860d8ed28f81..266337fd9452 100644 --- a/libcxxabi/test/catch_member_function_pointer_02.pass.cpp +++ b/libcxxabi/test/catch_member_function_pointer_02.pass.cpp @@ -10,7 +10,7 @@ // Can a noexcept member function pointer be caught by a non-noexcept catch // clause? // UNSUPPORTED: c++98, c++03, c++11, c++14 -// UNSUPPORTED: libcxxabi-no-exceptions, libcxxabi-no-qualified-function-types +// UNSUPPORTED: libcxxabi-no-exceptions #include @@ -60,9 +60,11 @@ void check_deep() { int main() { +#ifdef __cpp_noexcept_function_type check(); check(); check(); check(); check_deep(); +#endif } diff --git a/libcxxabi/test/libcxxabi/test/config.py b/libcxxabi/test/libcxxabi/test/config.py index 7cb1e9ba6c49..3d5a235df772 100644 --- a/libcxxabi/test/libcxxabi/test/config.py +++ b/libcxxabi/test/libcxxabi/test/config.py @@ -37,8 +37,6 @@ class Configuration(LibcxxConfiguration): super(Configuration, self).configure_features() if not self.get_lit_bool('enable_exceptions', True): self.config.available_features.add('libcxxabi-no-exceptions') - if not self.cxx.addCompileFlagIfSupported(['-Xclang', '-mqualified-function-type-info']): - self.config.available_features.add("libcxxabi-no-qualified-function-types") def configure_compile_flags(self): self.cxx.compile_flags += ['-DLIBCXXABI_NO_TIMER']