[libc-commits] [libc] [llvm] [libc] Add the digit property to numeric_limits (PR #73926)
Guillaume Chatelet via libc-commits
libc-commits at lists.llvm.org
Thu Nov 30 04:13:38 PST 2023
https://github.com/gchatelet updated https://github.com/llvm/llvm-project/pull/73926
>From 3785df68a933e76c894e6b38824b60cd046287a0 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Thu, 30 Nov 2023 11:51:09 +0000
Subject: [PATCH 1/2] [libc] Add the digit property to numeric_limits
---
libc/src/__support/CPP/CMakeLists.txt | 2 +
libc/src/__support/CPP/limits.h | 122 +++++++++---------
.../llvm-project-overlay/libc/BUILD.bazel | 1 +
3 files changed, 62 insertions(+), 63 deletions(-)
diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt
index 10bcebf9b04f61d..6a81717fd0ec513 100644
--- a/libc/src/__support/CPP/CMakeLists.txt
+++ b/libc/src/__support/CPP/CMakeLists.txt
@@ -45,6 +45,8 @@ add_header_library(
limits
HDRS
limits.h
+ DEPENDS
+ .type_traits
)
add_header_library(
diff --git a/libc/src/__support/CPP/limits.h b/libc/src/__support/CPP/limits.h
index b1a1203df79674a..3126b38ec48e612 100644
--- a/libc/src/__support/CPP/limits.h
+++ b/libc/src/__support/CPP/limits.h
@@ -9,9 +9,10 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_LIMITS_H
#define LLVM_LIBC_SRC___SUPPORT_CPP_LIMITS_H
+#include "src/__support/CPP/type_traits/is_signed.h"
#include "src/__support/macros/attributes.h" // LIBC_INLINE
-#include <limits.h>
+#include <limits.h> // CHAR_BIT
namespace LIBC_NAMESPACE {
namespace cpp {
@@ -24,77 +25,72 @@ constexpr long long LLONG_MIN = 1LL << (LLONG_BIT_WIDTH - 1);
constexpr unsigned long long ULLONG_MAX = ~0ULL;
#endif
-template <class T> class numeric_limits {
-public:
- LIBC_INLINE static constexpr T max();
- LIBC_INLINE static constexpr T min();
+namespace internal {
+
+template <typename T, T min_value, T max_value> struct numeric_limits_impl {
+ LIBC_INLINE static constexpr T max() { return max_value; }
+ LIBC_INLINE static constexpr T min() { return min_value; }
+ LIBC_INLINE_VAR static constexpr int digits =
+ CHAR_BIT * sizeof(T) - cpp::is_signed_v<T>;
};
+} // namespace internal
+
+template <class T> struct numeric_limits {};
+
// TODO: Add numeric_limits specializations as needed for new types.
+template <>
+struct numeric_limits<short>
+ : public internal::numeric_limits_impl<short, SHRT_MIN, SHRT_MAX> {};
-template <> class numeric_limits<int> {
-public:
- LIBC_INLINE static constexpr int max() { return INT_MAX; }
- LIBC_INLINE static constexpr int min() { return INT_MIN; }
-};
-template <> class numeric_limits<unsigned int> {
-public:
- LIBC_INLINE static constexpr unsigned int max() { return UINT_MAX; }
- LIBC_INLINE static constexpr unsigned int min() { return 0; }
-};
-template <> class numeric_limits<long> {
-public:
- LIBC_INLINE static constexpr long max() { return LONG_MAX; }
- LIBC_INLINE static constexpr long min() { return LONG_MIN; }
-};
-template <> class numeric_limits<unsigned long> {
-public:
- LIBC_INLINE static constexpr unsigned long max() { return ULONG_MAX; }
- LIBC_INLINE static constexpr unsigned long min() { return 0; }
-};
-template <> class numeric_limits<long long> {
-public:
- LIBC_INLINE static constexpr long long max() { return LLONG_MAX; }
- LIBC_INLINE static constexpr long long min() { return LLONG_MIN; }
-};
-template <> class numeric_limits<unsigned long long> {
-public:
- LIBC_INLINE static constexpr unsigned long long max() { return ULLONG_MAX; }
- LIBC_INLINE static constexpr unsigned long long min() { return 0; }
-};
-template <> class numeric_limits<short> {
-public:
- LIBC_INLINE static constexpr short max() { return SHRT_MAX; }
- LIBC_INLINE static constexpr short min() { return SHRT_MIN; }
-};
-template <> class numeric_limits<unsigned short> {
-public:
- LIBC_INLINE static constexpr unsigned short max() { return USHRT_MAX; }
- LIBC_INLINE static constexpr unsigned short min() { return 0; }
-};
-template <> class numeric_limits<char> {
-public:
- LIBC_INLINE static constexpr char max() { return CHAR_MAX; }
- LIBC_INLINE static constexpr char min() { return CHAR_MIN; }
-};
-template <> class numeric_limits<signed char> {
-public:
- LIBC_INLINE static constexpr signed char max() { return SCHAR_MAX; }
- LIBC_INLINE static constexpr signed char min() { return SCHAR_MIN; }
+template <>
+struct numeric_limits<unsigned short>
+ : public internal::numeric_limits_impl<unsigned short, 0, USHRT_MAX> {};
+
+template <>
+struct numeric_limits<int>
+ : public internal::numeric_limits_impl<int, INT_MIN, INT_MAX> {};
+
+template <>
+struct numeric_limits<unsigned int>
+ : public internal::numeric_limits_impl<unsigned int, 0, UINT_MAX> {};
+
+template <>
+struct numeric_limits<long>
+ : public internal::numeric_limits_impl<long, LONG_MIN, LONG_MAX> {};
+
+template <>
+struct numeric_limits<unsigned long>
+ : public internal::numeric_limits_impl<unsigned long, 0, ULONG_MAX> {};
+
+template <>
+struct numeric_limits<long long>
+ : public internal::numeric_limits_impl<long long, LLONG_MIN, LLONG_MAX> {};
+
+template <>
+struct numeric_limits<unsigned long long>
+ : public internal::numeric_limits_impl<unsigned long long, 0, ULLONG_MAX> {
};
-template <> class numeric_limits<unsigned char> {
-public:
- LIBC_INLINE static constexpr unsigned char max() { return UCHAR_MAX; }
- LIBC_INLINE static constexpr unsigned char min() { return 0; }
+
+template <>
+struct numeric_limits<char>
+ : public internal::numeric_limits_impl<char, CHAR_MIN, CHAR_MAX> {};
+
+template <>
+struct numeric_limits<signed char>
+ : public internal::numeric_limits_impl<signed char, SCHAR_MIN, SCHAR_MAX> {
};
+
+template <>
+struct numeric_limits<unsigned char>
+ : public internal::numeric_limits_impl<unsigned char, 0, UCHAR_MAX> {};
+
#ifdef __SIZEOF_INT128__
// On platform where UInt128 resolves to __uint128_t, this specialization
// provides the limits of UInt128.
-template <> class numeric_limits<__uint128_t> {
-public:
- LIBC_INLINE static constexpr __uint128_t max() { return ~__uint128_t(0); }
- LIBC_INLINE static constexpr __uint128_t min() { return 0; }
-};
+template <>
+struct numeric_limits<__uint128_t>
+ : public internal::numeric_limits_impl<__uint128_t, 0, ~__uint128_t(0)> {};
#endif
} // namespace cpp
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index ffb2652ed1419d0..365fbd1cbc4d7b4 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -206,6 +206,7 @@ libc_support_library(
name = "__support_cpp_limits",
hdrs = ["src/__support/CPP/limits.h"],
deps = [
+ "__support_cpp_type_traits",
"__support_macros_attributes",
],
)
>From 26fd2d57ee1403eefa7641234990401d2927d0ed Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Thu, 30 Nov 2023 12:13:18 +0000
Subject: [PATCH 2/2] restrict implementation to integral values
---
libc/src/__support/CPP/limits.h | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/libc/src/__support/CPP/limits.h b/libc/src/__support/CPP/limits.h
index 3126b38ec48e612..4503c009b53fdaa 100644
--- a/libc/src/__support/CPP/limits.h
+++ b/libc/src/__support/CPP/limits.h
@@ -10,6 +10,7 @@
#define LLVM_LIBC_SRC___SUPPORT_CPP_LIMITS_H
#include "src/__support/CPP/type_traits/is_signed.h"
+#include "src/__support/CPP/type_traits/is_integral.h"
#include "src/__support/macros/attributes.h" // LIBC_INLINE
#include <limits.h> // CHAR_BIT
@@ -27,7 +28,8 @@ constexpr unsigned long long ULLONG_MAX = ~0ULL;
namespace internal {
-template <typename T, T min_value, T max_value> struct numeric_limits_impl {
+template <typename T, T min_value, T max_value> struct integer_impl {
+ static_assert(cpp::is_integral_v<T>);
LIBC_INLINE static constexpr T max() { return max_value; }
LIBC_INLINE static constexpr T min() { return min_value; }
LIBC_INLINE_VAR static constexpr int digits =
@@ -41,56 +43,54 @@ template <class T> struct numeric_limits {};
// TODO: Add numeric_limits specializations as needed for new types.
template <>
struct numeric_limits<short>
- : public internal::numeric_limits_impl<short, SHRT_MIN, SHRT_MAX> {};
+ : public internal::integer_impl<short, SHRT_MIN, SHRT_MAX> {};
template <>
struct numeric_limits<unsigned short>
- : public internal::numeric_limits_impl<unsigned short, 0, USHRT_MAX> {};
+ : public internal::integer_impl<unsigned short, 0, USHRT_MAX> {};
template <>
struct numeric_limits<int>
- : public internal::numeric_limits_impl<int, INT_MIN, INT_MAX> {};
+ : public internal::integer_impl<int, INT_MIN, INT_MAX> {};
template <>
struct numeric_limits<unsigned int>
- : public internal::numeric_limits_impl<unsigned int, 0, UINT_MAX> {};
+ : public internal::integer_impl<unsigned int, 0, UINT_MAX> {};
template <>
struct numeric_limits<long>
- : public internal::numeric_limits_impl<long, LONG_MIN, LONG_MAX> {};
+ : public internal::integer_impl<long, LONG_MIN, LONG_MAX> {};
template <>
struct numeric_limits<unsigned long>
- : public internal::numeric_limits_impl<unsigned long, 0, ULONG_MAX> {};
+ : public internal::integer_impl<unsigned long, 0, ULONG_MAX> {};
template <>
struct numeric_limits<long long>
- : public internal::numeric_limits_impl<long long, LLONG_MIN, LLONG_MAX> {};
+ : public internal::integer_impl<long long, LLONG_MIN, LLONG_MAX> {};
template <>
struct numeric_limits<unsigned long long>
- : public internal::numeric_limits_impl<unsigned long long, 0, ULLONG_MAX> {
-};
+ : public internal::integer_impl<unsigned long long, 0, ULLONG_MAX> {};
template <>
struct numeric_limits<char>
- : public internal::numeric_limits_impl<char, CHAR_MIN, CHAR_MAX> {};
+ : public internal::integer_impl<char, CHAR_MIN, CHAR_MAX> {};
template <>
struct numeric_limits<signed char>
- : public internal::numeric_limits_impl<signed char, SCHAR_MIN, SCHAR_MAX> {
-};
+ : public internal::integer_impl<signed char, SCHAR_MIN, SCHAR_MAX> {};
template <>
struct numeric_limits<unsigned char>
- : public internal::numeric_limits_impl<unsigned char, 0, UCHAR_MAX> {};
+ : public internal::integer_impl<unsigned char, 0, UCHAR_MAX> {};
#ifdef __SIZEOF_INT128__
// On platform where UInt128 resolves to __uint128_t, this specialization
// provides the limits of UInt128.
template <>
struct numeric_limits<__uint128_t>
- : public internal::numeric_limits_impl<__uint128_t, 0, ~__uint128_t(0)> {};
+ : public internal::integer_impl<__uint128_t, 0, ~__uint128_t(0)> {};
#endif
} // namespace cpp
More information about the libc-commits
mailing list