Skip to content

Commit 51d1c72

Browse files
authored
[libc] Added support for fixed-points in is_signed and is_unsigned. (#133371)
Fixes #133365 ## Changes Done - Changed the signed checking to ```cpp struct is_signed : bool_constant<((is_fixed_point<T> || is_arithmetic_v<T>) && (T(-1) < T(0)))> ``` in ``/libc/src/__support/CPP/type_traits/is_signed.h``. Added check for fixed-points. - But, got to know that this will fail for ``unsigned _Fract`` or any unsigned fixed-point because ``unsigned _Fract`` can’t represent -1 in T(-1), while ``unsigned int`` can handle it via wrapping. - That's why I explicity added ``is_signed`` check for ``unsigned`` fixed-points. - Same changes to ``/libc/src/__support/CPP/type_traits/is_unsigned.h``. - Added tests for ``is_signed`` and ``is_unsigned``.
1 parent 554859c commit 51d1c72

File tree

3 files changed

+113
-4
lines changed

3 files changed

+113
-4
lines changed

libc/src/__support/CPP/type_traits/is_signed.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,43 @@
88
#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SIGNED_H
99
#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_SIGNED_H
1010

11+
#include "include/llvm-libc-macros/stdfix-macros.h"
1112
#include "src/__support/CPP/type_traits/bool_constant.h"
1213
#include "src/__support/CPP/type_traits/is_arithmetic.h"
14+
#include "src/__support/CPP/type_traits/is_same.h"
15+
#include "src/__support/CPP/type_traits/remove_cv.h"
1316
#include "src/__support/macros/attributes.h"
1417
#include "src/__support/macros/config.h"
1518

1619
namespace LIBC_NAMESPACE_DECL {
1720
namespace cpp {
1821

19-
// is_signed
22+
#ifndef LIBC_COMPILER_HAS_FIXED_POINT
2023
template <typename T>
2124
struct is_signed : bool_constant<(is_arithmetic_v<T> && (T(-1) < T(0)))> {
2225
LIBC_INLINE constexpr operator bool() const { return is_signed::value; }
2326
LIBC_INLINE constexpr bool operator()() const { return is_signed::value; }
2427
};
28+
#else
29+
template <typename T> struct is_signed {
30+
private:
31+
template <typename Head, typename... Args>
32+
LIBC_INLINE static constexpr bool __is_unqualified_any_of() {
33+
return (... || is_same_v<remove_cv_t<Head>, Args>);
34+
}
35+
36+
public:
37+
LIBC_INLINE_VAR static constexpr bool value =
38+
(is_arithmetic_v<T> && (T(-1) < T(0))) ||
39+
__is_unqualified_any_of<T, short fract, fract, long fract, short accum,
40+
accum, long accum, short sat fract, sat fract,
41+
long sat fract, short sat accum, sat accum,
42+
long sat accum>();
43+
LIBC_INLINE constexpr operator bool() const { return is_signed::value; }
44+
LIBC_INLINE constexpr bool operator()() const { return is_signed::value; }
45+
};
46+
#endif // LIBC_COMPILER_HAS_FIXED_POINT
47+
2548
template <typename T>
2649
LIBC_INLINE_VAR constexpr bool is_signed_v = is_signed<T>::value;
2750

libc/src/__support/CPP/type_traits/is_unsigned.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,45 @@
88
#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_UNSIGNED_H
99
#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_UNSIGNED_H
1010

11+
#include "include/llvm-libc-macros/stdfix-macros.h"
1112
#include "src/__support/CPP/type_traits/bool_constant.h"
1213
#include "src/__support/CPP/type_traits/is_arithmetic.h"
14+
#include "src/__support/CPP/type_traits/is_same.h"
15+
#include "src/__support/CPP/type_traits/remove_cv.h"
1316
#include "src/__support/macros/attributes.h"
1417
#include "src/__support/macros/config.h"
1518

1619
namespace LIBC_NAMESPACE_DECL {
1720
namespace cpp {
1821

19-
// is_unsigned
22+
#ifndef LIBC_COMPILER_HAS_FIXED_POINT
2023
template <typename T>
2124
struct is_unsigned : bool_constant<(is_arithmetic_v<T> && (T(-1) > T(0)))> {
2225
LIBC_INLINE constexpr operator bool() const { return is_unsigned::value; }
2326
LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; }
2427
};
28+
#else
29+
template <typename T> struct is_unsigned {
30+
private:
31+
template <typename Head, typename... Args>
32+
LIBC_INLINE static constexpr bool __is_unqualified_any_of() {
33+
return (... || is_same_v<remove_cv_t<Head>, Args>);
34+
}
35+
36+
public:
37+
LIBC_INLINE_VAR static constexpr bool value =
38+
(is_arithmetic_v<T> && (T(-1) > T(0))) ||
39+
__is_unqualified_any_of<T, unsigned short fract, unsigned fract,
40+
unsigned long fract, unsigned short accum,
41+
unsigned accum, unsigned long accum,
42+
unsigned short sat fract, unsigned sat fract,
43+
unsigned long sat fract, unsigned short sat accum,
44+
unsigned sat accum, unsigned long sat accum>();
45+
LIBC_INLINE constexpr operator bool() const { return is_unsigned::value; }
46+
LIBC_INLINE constexpr bool operator()() const { return is_unsigned::value; }
47+
};
48+
#endif // LIBC_COMPILER_HAS_FIXED_POINT
49+
2550
template <typename T>
2651
LIBC_INLINE_VAR constexpr bool is_unsigned_v = is_unsigned<T>::value;
2752

libc/test/src/__support/CPP/type_traits_test.cpp

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "include/llvm-libc-macros/stdfix-macros.h"
910
#include "src/__support/CPP/type_traits.h"
1011
#include "src/__support/macros/config.h"
1112
#include "test/UnitTest/Test.h"
@@ -409,7 +410,37 @@ TEST(LlvmLibcTypeTraitsTest, is_object) {
409410

410411
// TODO is_scalar
411412

412-
// TODO is_signed
413+
TEST(LlvmLibcTypeTraitsTest, is_signed) {
414+
EXPECT_TRUE((is_signed_v<int>));
415+
EXPECT_TRUE((is_signed_v<long>));
416+
EXPECT_TRUE((is_signed_v<long long>));
417+
EXPECT_FALSE((is_signed_v<unsigned int>));
418+
EXPECT_FALSE((is_signed_v<unsigned long>));
419+
EXPECT_FALSE((is_signed_v<unsigned long long>));
420+
EXPECT_TRUE((is_signed_v<float>));
421+
EXPECT_TRUE((is_signed_v<double>));
422+
EXPECT_TRUE((is_signed_v<long double>));
423+
424+
#ifdef LIBC_COMPILER_HAS_FIXED_POINT
425+
// for fixed point types
426+
EXPECT_TRUE((is_signed_v<fract>));
427+
EXPECT_FALSE((is_signed_v<unsigned fract>));
428+
EXPECT_TRUE((is_signed_v<accum>));
429+
EXPECT_FALSE((is_signed_v<unsigned accum>));
430+
EXPECT_TRUE((is_signed_v<sat fract>));
431+
EXPECT_FALSE((is_signed_v<unsigned sat fract>));
432+
EXPECT_TRUE((is_signed_v<sat accum>));
433+
EXPECT_FALSE((is_signed_v<unsigned sat accum>));
434+
EXPECT_TRUE((is_signed_v<short fract>));
435+
EXPECT_FALSE((is_signed_v<unsigned short fract>));
436+
EXPECT_TRUE((is_signed_v<short accum>));
437+
EXPECT_FALSE((is_signed_v<unsigned short accum>));
438+
EXPECT_TRUE((is_signed_v<long fract>));
439+
EXPECT_FALSE((is_signed_v<unsigned long fract>));
440+
EXPECT_TRUE((is_signed_v<long accum>));
441+
EXPECT_FALSE((is_signed_v<unsigned long accum>));
442+
#endif
443+
}
413444

414445
// TODO is_trivially_constructible
415446

@@ -419,7 +450,37 @@ TEST(LlvmLibcTypeTraitsTest, is_object) {
419450

420451
// TODO is_union
421452

422-
// TODO is_unsigned
453+
TEST(LlvmLibcTypeTraitsTest, is_unsigned) {
454+
EXPECT_FALSE((is_unsigned_v<int>));
455+
EXPECT_FALSE((is_unsigned_v<long>));
456+
EXPECT_FALSE((is_unsigned_v<long long>));
457+
EXPECT_TRUE((is_unsigned_v<unsigned int>));
458+
EXPECT_TRUE((is_unsigned_v<unsigned long>));
459+
EXPECT_TRUE((is_unsigned_v<unsigned long long>));
460+
EXPECT_FALSE((is_unsigned_v<float>));
461+
EXPECT_FALSE((is_unsigned_v<double>));
462+
EXPECT_FALSE((is_unsigned_v<long double>));
463+
464+
#ifdef LIBC_COMPILER_HAS_FIXED_POINT
465+
// for fixed point types
466+
EXPECT_FALSE((is_unsigned_v<fract>));
467+
EXPECT_TRUE((is_unsigned_v<unsigned fract>));
468+
EXPECT_FALSE((is_unsigned_v<accum>));
469+
EXPECT_TRUE((is_unsigned_v<unsigned accum>));
470+
EXPECT_FALSE((is_unsigned_v<sat fract>));
471+
EXPECT_TRUE((is_unsigned_v<unsigned sat fract>));
472+
EXPECT_FALSE((is_unsigned_v<sat accum>));
473+
EXPECT_TRUE((is_unsigned_v<unsigned sat accum>));
474+
EXPECT_FALSE((is_unsigned_v<short fract>));
475+
EXPECT_TRUE((is_unsigned_v<unsigned short fract>));
476+
EXPECT_FALSE((is_unsigned_v<short accum>));
477+
EXPECT_TRUE((is_unsigned_v<unsigned short accum>));
478+
EXPECT_FALSE((is_unsigned_v<long fract>));
479+
EXPECT_TRUE((is_unsigned_v<unsigned long fract>));
480+
EXPECT_FALSE((is_unsigned_v<long accum>));
481+
EXPECT_TRUE((is_unsigned_v<unsigned long accum>));
482+
#endif
483+
}
423484

424485
// TODO is_void
425486

0 commit comments

Comments
 (0)