[libcxx-commits] [libcxx] 64595f9 - [libcxx][type_traits] add tests for is_signed and is_unsigned

Tomas Matheson via libcxx-commits libcxx-commits at lists.llvm.org
Tue Mar 16 09:36:43 PDT 2021


Author: Tomas Matheson
Date: 2021-03-16T16:36:10Z
New Revision: 64595f9b84fa77a130085260b1b4e26a2756dce8

URL: https://github.com/llvm/llvm-project/commit/64595f9b84fa77a130085260b1b4e26a2756dce8
DIFF: https://github.com/llvm/llvm-project/commit/64595f9b84fa77a130085260b1b4e26a2756dce8.diff

LOG: [libcxx][type_traits] add tests for is_signed and is_unsigned

In previous versions of clang, __is_signed and __is_unsigned builtins did not
correspond to is_signed and is_unsigned behaviour for enums.  The builtins were
fixed in D67897 and D98104.

* Disable the fast path of is_unsigned for clang versions < 13

* Add more tests for is_signed, is_unsigned and is_arithmetic

Differential Revision: https://reviews.llvm.org/D97283

Added: 
    

Modified: 
    libcxx/include/type_traits
    libcxx/test/std/utilities/meta/meta.unary/meta.unary.comp/is_arithmetic.pass.cpp
    libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_signed.pass.cpp
    libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_unsigned.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index efc5c41c5f9b..7477e6d143de 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -1451,7 +1451,8 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_signed_v
 
 // 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)> { };
@@ -1461,7 +1462,7 @@ template <class _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)) {};
@@ -1482,7 +1483,7 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_unsigned_v
     = is_unsigned<_Tp>::value;
 #endif
 
-#endif // __has_keyword(__is_unsigned)
+#endif // __has_keyword(__is_unsigned) && _LIBCPP_CLANG_VER >= 1300
 
 // 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
index 683e885e288d..a6fc44384c3b 100644
--- 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 @@ class Abstract
 
 enum Enum {zero, one};
 
+enum EnumSigned : int { two };
+
+enum EnumUnsigned : unsigned { three };
+
+enum class EnumClass { zero, one };
+
 typedef void (*FunctionPtr)();
 
 
@@ -97,6 +103,9 @@ int main(int, char**)
     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>();

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
index 4936cc788e25..29a259fb2588 100644
--- 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,73 @@ class Class
 
 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>();

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
index bc70a43b9bd5..3c200b8f3905 100644
--- 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,73 @@ class Class
 
 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>();


        


More information about the libcxx-commits mailing list