// 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
template<class _Tp>
struct _LIBCPP_TEMPLATE_VIS is_unsigned : _BoolConstant<__is_unsigned(_Tp)> { };
_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_unsigned_v = __is_unsigned(_Tp);
#endif
-#else // __has_keyword(__is_unsigned)
+#else // __has_keyword(__is_unsigned) && _LIBCPP_CLANG_VER >= 1300
template <class _Tp, bool = is_integral<_Tp>::value>
struct __libcpp_is_unsigned_impl : public _LIBCPP_BOOL_CONSTANT(_Tp(0) < _Tp(-1)) {};
= is_unsigned<_Tp>::value;
#endif
-#endif // __has_keyword(__is_unsigned)
+#endif // __has_keyword(__is_unsigned) && _LIBCPP_CLANG_VER >= 1300
// rank
enum Enum {zero, one};
+enum EnumSigned : int { two };
+
+enum EnumUnsigned : unsigned { three };
+
+enum class EnumClass { zero, one };
+
typedef void (*FunctionPtr)();
test_is_not_arithmetic<char[]>();
test_is_not_arithmetic<Union>();
test_is_not_arithmetic<Enum>();
+ test_is_not_arithmetic<EnumSigned>();
+ test_is_not_arithmetic<EnumUnsigned>();
+ test_is_not_arithmetic<EnumClass>();
test_is_not_arithmetic<FunctionPtr>();
test_is_not_arithmetic<Empty>();
test_is_not_arithmetic<incomplete_type>();
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<void>();
- test_is_not_signed<int&>();
- test_is_not_signed<Class>();
- test_is_not_signed<int*>();
- test_is_not_signed<const int*>();
- test_is_not_signed<char[3]>();
- test_is_not_signed<char[]>();
- test_is_not_signed<bool>();
- test_is_not_signed<unsigned>();
- test_is_not_signed<A>();
-
- test_is_signed<int>();
- test_is_signed<double>();
+ // Cases where !is_arithmetic implies !is_signed
+ test_is_not_signed<std::nullptr_t>();
+ test_is_not_signed<void>();
+ test_is_not_signed<int&>();
+ test_is_not_signed<int&&>();
+ test_is_not_signed<Class>();
+ test_is_not_signed<int*>();
+ test_is_not_signed<const int*>();
+ test_is_not_signed<char[3]>();
+ test_is_not_signed<char[]>();
+ test_is_not_signed<Union>();
+ test_is_not_signed<Enum>();
+ test_is_not_signed<EnumSigned>();
+ test_is_not_signed<EnumUnsigned>();
+ test_is_not_signed<EnumClass>();
+ test_is_not_signed<FunctionPtr>();
+ test_is_not_signed<Empty>();
+ test_is_not_signed<incomplete_type>();
+ test_is_not_signed<A>();
+ test_is_not_signed<bit_zero>();
+ test_is_not_signed<NotEmpty>();
+ test_is_not_signed<Abstract>();
+
+ test_is_signed<signed char>();
+ test_is_signed<short>();
+ test_is_signed<int>();
+ test_is_signed<long>();
+ test_is_signed<float>();
+ test_is_signed<double>();
+
+ test_is_not_signed<unsigned char>();
+ test_is_not_signed<unsigned short>();
+ test_is_not_signed<unsigned int>();
+ test_is_not_signed<unsigned long>();
+
+ test_is_not_signed<bool>();
+ test_is_not_signed<unsigned>();
#ifndef _LIBCPP_HAS_NO_INT128
test_is_signed<__int128_t>();
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<void>();
- test_is_not_unsigned<int&>();
- test_is_not_unsigned<Class>();
- test_is_not_unsigned<int*>();
- test_is_not_unsigned<const int*>();
- test_is_not_unsigned<char[3]>();
- test_is_not_unsigned<char[]>();
- test_is_not_unsigned<int>();
- test_is_not_unsigned<double>();
- test_is_not_unsigned<A>();
-
- test_is_unsigned<bool>();
- test_is_unsigned<unsigned>();
+ // Cases where !is_arithmetic implies !is_unsigned
+ test_is_not_unsigned<std::nullptr_t>();
+ test_is_not_unsigned<void>();
+ test_is_not_unsigned<int&>();
+ test_is_not_unsigned<int&&>();
+ test_is_not_unsigned<Class>();
+ test_is_not_unsigned<int*>();
+ test_is_not_unsigned<const int*>();
+ test_is_not_unsigned<char[3]>();
+ test_is_not_unsigned<char[]>();
+ test_is_not_unsigned<Union>();
+ test_is_not_unsigned<Enum>();
+ test_is_not_unsigned<EnumSigned>();
+ test_is_not_unsigned<EnumUnsigned>();
+ test_is_not_unsigned<EnumClass>();
+ test_is_not_unsigned<FunctionPtr>();
+ test_is_not_unsigned<Empty>();
+ test_is_not_unsigned<incomplete_type>();
+ test_is_not_unsigned<A>();
+ test_is_not_unsigned<bit_zero>();
+ test_is_not_unsigned<NotEmpty>();
+ test_is_not_unsigned<Abstract>();
+
+ test_is_not_unsigned<signed char>();
+ test_is_not_unsigned<short>();
+ test_is_not_unsigned<int>();
+ test_is_not_unsigned<long>();
+ test_is_not_unsigned<float>();
+ test_is_not_unsigned<double>();
+
+ test_is_unsigned<unsigned char>();
+ test_is_unsigned<unsigned short>();
+ test_is_unsigned<unsigned int>();
+ test_is_unsigned<unsigned long>();
+
+ test_is_unsigned<bool>();
+ test_is_unsigned<unsigned>();
#ifndef _LIBCPP_HAS_NO_INT128
test_is_unsigned<__uint128_t>();