[libc] [llvm] [libc] Add the digit property to numeric_limits (PR #73926)

Guillaume Chatelet via llvm-commits llvm-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 llvm-commits mailing list