diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -1451,17 +1451,28 @@ // is_unsigned -#if __has_keyword(__is_unsigned) +// Before clang 13 __is_unsigned returned true for enums with signed underlying type +#if __has_keyword(__is_unsigned) && \ + (_LIBCPP_CLANG_VER >= 1300 || __has_keyword(__is_enum)) -template -struct _LIBCPP_TEMPLATE_VIS is_unsigned : _BoolConstant<__is_unsigned(_Tp)> { }; +template +struct _LIBCPP_TEMPLATE_VIS is_unsigned + : _BoolConstant< +#if _LIBCPP_CLANG_VER < 1300 + __is_unsigned(_Tp) && !__is_enum(_Tp) +#else + __is_unsigned(_Tp) +#endif + > { +}; #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template -_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_unsigned_v = __is_unsigned(_Tp); +_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_unsigned_v = __is_unsigned(_Tp) && + !__is_enum(_Tp); #endif -#else // __has_keyword(__is_unsigned) +#else // __has_keyword(__is_unsigned) && (_LIBCPP_CLANG_VER >= 1300 || __has_keyword(__is_enum)) template ::value> struct __libcpp_is_unsigned_impl : public _LIBCPP_BOOL_CONSTANT(_Tp(0) < _Tp(-1)) {}; @@ -1482,7 +1493,7 @@ = is_unsigned<_Tp>::value; #endif -#endif // __has_keyword(__is_unsigned) +#endif // __has_keyword(__is_unsigned) && (_LIBCPP_CLANG_VER >= 1300 || __has_keyword(__is_enum)) // rank diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.comp/is_arithmetic.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.comp/is_arithmetic.pass.cpp --- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.comp/is_arithmetic.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.comp/is_arithmetic.pass.cpp @@ -69,6 +69,12 @@ enum Enum {zero, one}; +enum EnumSigned : int { two }; + +enum EnumUnsigned : unsigned { three }; + +enum class EnumClass { zero, one }; + typedef void (*FunctionPtr)(); @@ -97,6 +103,9 @@ test_is_not_arithmetic(); test_is_not_arithmetic(); test_is_not_arithmetic(); + test_is_not_arithmetic(); + test_is_not_arithmetic(); + test_is_not_arithmetic(); test_is_not_arithmetic(); test_is_not_arithmetic(); test_is_not_arithmetic(); diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_signed.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_signed.pass.cpp --- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_signed.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_signed.pass.cpp @@ -51,21 +51,75 @@ struct A; // incomplete +class incomplete_type; + +class Empty {}; + +class NotEmpty { + virtual ~NotEmpty(); +}; + +union Union {}; + +struct bit_zero { + int : 0; +}; + +class Abstract { + virtual ~Abstract() = 0; +}; + +enum Enum { zero, one }; + +enum EnumSigned : int { two }; + +enum EnumUnsigned : unsigned { three }; + +enum class EnumClass { zero, one }; + +typedef void (*FunctionPtr)(); + int main(int, char**) { - test_is_not_signed(); - test_is_not_signed(); - test_is_not_signed(); - test_is_not_signed(); - test_is_not_signed(); - test_is_not_signed(); - test_is_not_signed(); - test_is_not_signed(); - test_is_not_signed(); - test_is_not_signed(); - - test_is_signed(); - test_is_signed(); + // Cases where !is_arithmetic implies !is_signed + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + + test_is_signed(); + test_is_signed(); + test_is_signed(); + test_is_signed(); + test_is_signed(); + test_is_signed(); + test_is_signed(); + test_is_signed(); + + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + test_is_not_signed(); + + test_is_not_signed(); + test_is_not_signed(); #ifndef _LIBCPP_HAS_NO_INT128 test_is_signed<__int128_t>(); diff --git a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_unsigned.pass.cpp b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_unsigned.pass.cpp --- a/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_unsigned.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_unsigned.pass.cpp @@ -51,21 +51,75 @@ struct A; // incomplete +class incomplete_type; + +class Empty {}; + +class NotEmpty { + virtual ~NotEmpty(); +}; + +union Union {}; + +struct bit_zero { + int : 0; +}; + +class Abstract { + virtual ~Abstract() = 0; +}; + +enum Enum { zero, one }; + +enum EnumSigned : int { two }; + +enum EnumUnsigned : unsigned { three }; + +enum class EnumClass { zero, one }; + +typedef void (*FunctionPtr)(); + int main(int, char**) { - test_is_not_unsigned(); - test_is_not_unsigned(); - test_is_not_unsigned(); - test_is_not_unsigned(); - test_is_not_unsigned(); - test_is_not_unsigned(); - test_is_not_unsigned(); - test_is_not_unsigned(); - test_is_not_unsigned(); - test_is_not_unsigned(); - - test_is_unsigned(); - test_is_unsigned(); + // Cases where !is_arithmetic implies !is_unsigned + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + test_is_not_unsigned(); + + test_is_unsigned(); + test_is_unsigned(); + test_is_unsigned(); + test_is_unsigned(); + + test_is_unsigned(); + test_is_unsigned(); #ifndef _LIBCPP_HAS_NO_INT128 test_is_unsigned<__uint128_t>();