Author: ericwf Date: Mon May 2 23:26:02 2016 New Revision: 268359 URL: http://llvm.org/viewvc/llvm-project?rev=268359&view=rev Log: Fix PR27538. Remove __is_convertible specializations for array and function types.
This patch fixes a bunch of bugs in the fallback implementation of is_convertible, which is used by GCC. Removing the "__is_convertible" specializations for array/function types we fallback on the SFINAE test, which is more correct. See https://llvm.org/bugs/show_bug.cgi?id=27538 Modified: libcxx/trunk/include/type_traits libcxx/trunk/test/std/utilities/meta/meta.rel/is_convertible.pass.cpp Modified: libcxx/trunk/include/type_traits URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/type_traits?rev=268359&r1=268358&r2=268359&view=diff ============================================================================== --- libcxx/trunk/include/type_traits (original) +++ libcxx/trunk/include/type_traits Mon May 2 23:26:02 2016 @@ -1423,41 +1423,6 @@ struct __is_convertible > {}; -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 1, 0> : false_type {}; - -template <class _T1> struct __is_convertible<_T1, const _T1&, 1, 0> : true_type {}; -template <class _T1> struct __is_convertible<const _T1, const _T1&, 1, 0> : true_type {}; -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES -template <class _T1> struct __is_convertible<_T1, _T1&&, 1, 0> : true_type {}; -template <class _T1> struct __is_convertible<_T1, const _T1&&, 1, 0> : true_type {}; -template <class _T1> struct __is_convertible<_T1, volatile _T1&&, 1, 0> : true_type {}; -template <class _T1> struct __is_convertible<_T1, const volatile _T1&&, 1, 0> : true_type {}; -#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES - -template <class _T1, class _T2> struct __is_convertible<_T1, _T2*, 1, 0> - : public integral_constant<bool, __is_convertible<typename remove_all_extents<_T1>::type*, _T2*>::value> {}; - -template <class _T1, class _T2> struct __is_convertible<_T1, _T2* const, 1, 0> - : public integral_constant<bool, __is_convertible<typename remove_all_extents<_T1>::type*, _T2*const>::value> {}; - -template <class _T1, class _T2> struct __is_convertible<_T1, _T2* volatile, 1, 0> - : public integral_constant<bool, __is_convertible<typename remove_all_extents<_T1>::type*, _T2*volatile>::value> {}; - -template <class _T1, class _T2> struct __is_convertible<_T1, _T2* const volatile, 1, 0> - : public integral_constant<bool, __is_convertible<typename remove_all_extents<_T1>::type*, _T2*const volatile>::value> {}; - -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 2, 0> : public false_type {}; -#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES -template <class _T1> struct __is_convertible<_T1, _T1&&, 2, 0> : public true_type {}; -#endif -template <class _T1> struct __is_convertible<_T1, _T1&, 2, 0> : public true_type {}; -template <class _T1> struct __is_convertible<_T1, _T1*, 2, 0> : public true_type {}; -template <class _T1> struct __is_convertible<_T1, _T1*const, 2, 0> : public true_type {}; -template <class _T1> struct __is_convertible<_T1, _T1*volatile, 2, 0> : public true_type {}; -template <class _T1> struct __is_convertible<_T1, _T1*const volatile, 2, 0> : public true_type {}; - -template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 3, 0> : public false_type {}; - template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 0, 1> : public false_type {}; template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 1, 1> : public false_type {}; template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 2, 1> : public false_type {}; Modified: libcxx/trunk/test/std/utilities/meta/meta.rel/is_convertible.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/meta/meta.rel/is_convertible.pass.cpp?rev=268359&r1=268358&r2=268359&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/meta/meta.rel/is_convertible.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/meta/meta.rel/is_convertible.pass.cpp Mon May 2 23:26:02 2016 @@ -12,7 +12,6 @@ // is_convertible #include <type_traits> - #include "test_macros.h" template <class T, class U> @@ -46,8 +45,13 @@ void test_is_not_convertible() } typedef void Function(); +typedef void ConstFunction() const; typedef char Array[1]; +struct StringType { + StringType(const char*) {} +}; + class NonCopyable { NonCopyable(NonCopyable&); }; @@ -69,12 +73,19 @@ int main() test_is_not_convertible<void,char> (); test_is_not_convertible<void,char&> (); test_is_not_convertible<void,char*> (); + test_is_not_convertible<char, void>(); // Function test_is_not_convertible<Function, void> (); test_is_not_convertible<Function, Function> (); test_is_convertible<Function, Function&> (); test_is_convertible<Function, Function*> (); + test_is_convertible<Function, Function*const> (); + +#if TEST_STD_VER >= 11 + static_assert(( std::is_convertible<Function, Function&&>::value), ""); +#endif + test_is_not_convertible<Function, Array> (); test_is_not_convertible<Function, Array&> (); test_is_not_convertible<Function, char> (); @@ -105,6 +116,16 @@ int main() test_is_not_convertible<Function*, char&> (); test_is_not_convertible<Function*, char*> (); + // Non-referencable function type + static_assert((!std::is_convertible<ConstFunction, Function>::value), ""); + static_assert((!std::is_convertible<ConstFunction, Function*>::value), ""); + static_assert((!std::is_convertible<ConstFunction, Function&>::value), ""); + static_assert((!std::is_convertible<ConstFunction, Function>::value), ""); + static_assert((!std::is_convertible<Function*, ConstFunction>::value), ""); + static_assert((!std::is_convertible<Function&, ConstFunction>::value), ""); + static_assert((!std::is_convertible<ConstFunction, ConstFunction>::value), ""); + static_assert((!std::is_convertible<ConstFunction, void>::value), ""); + // Array test_is_not_convertible<Array, void> (); test_is_not_convertible<Array, Function> (); @@ -114,17 +135,37 @@ int main() static_assert((!std::is_convertible<Array, Array&>::value), ""); static_assert(( std::is_convertible<Array, const Array&>::value), ""); + static_assert((!std::is_convertible<Array, const volatile Array&>::value), ""); + static_assert((!std::is_convertible<const Array, Array&>::value), ""); static_assert(( std::is_convertible<const Array, const Array&>::value), ""); + static_assert((!std::is_convertible<Array, volatile Array&>::value), ""); + static_assert((!std::is_convertible<Array, const volatile Array&>::value), ""); + +#if TEST_STD_VER >= 11 + static_assert(( std::is_convertible<Array, Array&&>::value), ""); + static_assert(( std::is_convertible<Array, const Array&&>::value), ""); + static_assert(( std::is_convertible<Array, volatile Array&&>::value), ""); + static_assert(( std::is_convertible<Array, const volatile Array&&>::value), ""); + static_assert(( std::is_convertible<const Array, const Array&&>::value), ""); + static_assert((!std::is_convertible<Array&, Array&&>::value), ""); + static_assert((!std::is_convertible<Array&&, Array&>::value), ""); +#endif test_is_not_convertible<Array, char> (); test_is_not_convertible<Array, char&> (); static_assert(( std::is_convertible<Array, char*>::value), ""); static_assert(( std::is_convertible<Array, const char*>::value), ""); + static_assert(( std::is_convertible<Array, char* const>::value), ""); + static_assert(( std::is_convertible<Array, char* const volatile>::value), ""); + static_assert((!std::is_convertible<const Array, char*>::value), ""); static_assert(( std::is_convertible<const Array, const char*>::value), ""); + static_assert((!std::is_convertible<char[42][42], char*>::value), ""); + static_assert((!std::is_convertible<char[][1], char*>::value), ""); + // Array& test_is_not_convertible<Array&, void> (); test_is_not_convertible<Array&, Function> (); @@ -145,6 +186,9 @@ int main() static_assert((!std::is_convertible<const Array&, char*>::value), ""); static_assert(( std::is_convertible<const Array&, const char*>::value), ""); + static_assert((std::is_convertible<Array, StringType>::value), ""); + static_assert((std::is_convertible<char(&)[], StringType>::value), ""); + // char test_is_not_convertible<char, void> (); test_is_not_convertible<char, Function> (); @@ -207,7 +251,7 @@ int main() static_assert((!std::is_convertible<const NonCopyable&, NonCopyable&>::value), ""); // This test requires Access control SFINAE which we only have in C++11 or when // we are using the compiler builtin for is_convertible. -#if __cplusplus >= 201103L || !defined(_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK) +#if TEST_STD_VER >= 11 || !defined(_LIBCPP_USE_IS_CONVERTIBLE_FALLBACK) test_is_not_convertible<NonCopyable&, NonCopyable>(); #endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits