[libc-commits] [libc] [libc] Add C23 limits.h header. (PR #78887)

via libc-commits libc-commits at lists.llvm.org
Wed Jan 24 12:24:09 PST 2024


https://github.com/lntue updated https://github.com/llvm/llvm-project/pull/78887

>From 53df4d890f336c41bd2577709277106c83aac1fc Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Sun, 21 Jan 2024 02:25:26 -0500
Subject: [PATCH 01/11] [libc] Add limits.h header.

---
 libc/config/darwin/arm/headers.txt            |   1 +
 libc/config/darwin/x86_64/headers.txt         |   1 +
 libc/config/gpu/headers.txt                   |   1 +
 libc/config/linux/aarch64/headers.txt         |   1 +
 libc/config/linux/riscv/headers.txt           |   1 +
 libc/config/linux/x86_64/headers.txt          |   1 +
 libc/include/CMakeLists.txt                   |   8 +
 libc/include/limits.h.def                     |  14 ++
 libc/include/llvm-libc-macros/CMakeLists.txt  |   6 +
 libc/include/llvm-libc-macros/float-macros.h  |   9 +
 libc/include/llvm-libc-macros/limits-macros.h | 229 ++++++++++++++++++
 libc/spec/stdc.td                             |   3 +
 12 files changed, 275 insertions(+)
 create mode 100644 libc/include/limits.h.def
 create mode 100644 libc/include/llvm-libc-macros/limits-macros.h

diff --git a/libc/config/darwin/arm/headers.txt b/libc/config/darwin/arm/headers.txt
index 2dd54b7c1f5053..d80628445af5c5 100644
--- a/libc/config/darwin/arm/headers.txt
+++ b/libc/config/darwin/arm/headers.txt
@@ -4,6 +4,7 @@ set(TARGET_PUBLIC_HEADERS
     libc.include.fenv
     libc.include.float
     libc.include.inttypes
+    libc.include.limits
     libc.include.math
     libc.include.stdlib
     libc.include.string
diff --git a/libc/config/darwin/x86_64/headers.txt b/libc/config/darwin/x86_64/headers.txt
index 510d62688a45fa..1e81e303ddd6b4 100644
--- a/libc/config/darwin/x86_64/headers.txt
+++ b/libc/config/darwin/x86_64/headers.txt
@@ -5,6 +5,7 @@ set(TARGET_PUBLIC_HEADERS
     #libc.include.fenv
     libc.include.float
     libc.include.inttypes
+    libc.include.limits
     libc.include.math
     libc.include.stdlib
     libc.include.string
diff --git a/libc/config/gpu/headers.txt b/libc/config/gpu/headers.txt
index e68e18b87b10e2..3b04dd89fafe6f 100644
--- a/libc/config/gpu/headers.txt
+++ b/libc/config/gpu/headers.txt
@@ -4,6 +4,7 @@ set(TARGET_PUBLIC_HEADERS
     libc.include.string
     libc.include.float
     libc.include.inttypes
+    libc.include.limits
     libc.include.math
     libc.include.fenv
     libc.include.time
diff --git a/libc/config/linux/aarch64/headers.txt b/libc/config/linux/aarch64/headers.txt
index 709a8dbdedc98f..60d978bcaa76e4 100644
--- a/libc/config/linux/aarch64/headers.txt
+++ b/libc/config/linux/aarch64/headers.txt
@@ -6,6 +6,7 @@ set(TARGET_PUBLIC_HEADERS
     libc.include.fenv
     libc.include.float
     libc.include.inttypes
+    libc.include.limits
     libc.include.math
     libc.include.pthread
     libc.include.signal
diff --git a/libc/config/linux/riscv/headers.txt b/libc/config/linux/riscv/headers.txt
index dc1daa48f6c875..0ade63dc5933b5 100644
--- a/libc/config/linux/riscv/headers.txt
+++ b/libc/config/linux/riscv/headers.txt
@@ -8,6 +8,7 @@ set(TARGET_PUBLIC_HEADERS
     libc.include.fenv
     libc.include.float
     libc.include.inttypes
+    libc.include.limits
     libc.include.math
     libc.include.pthread
     libc.include.sched
diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt
index b0e0219a30e673..d103176897a74a 100644
--- a/libc/config/linux/x86_64/headers.txt
+++ b/libc/config/linux/x86_64/headers.txt
@@ -8,6 +8,7 @@ set(TARGET_PUBLIC_HEADERS
     libc.include.fenv
     libc.include.float
     libc.include.inttypes
+    libc.include.limits
     libc.include.math
     libc.include.pthread
     libc.include.sched
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index cec8b86516b51f..89fffd1022758e 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -83,6 +83,14 @@ add_gen_header(
     .llvm-libc-macros.float_macros
 )
 
+add_gen_header(
+  limits
+  DEF_FILE limits.h.def
+  GEN_HDR limits.h
+  DEPENDS
+    .llvm-libc-macros.limits_macros
+)
+
 add_gen_header(
   math
   DEF_FILE math.h.def
diff --git a/libc/include/limits.h.def b/libc/include/limits.h.def
new file mode 100644
index 00000000000000..de5f3490459ed8
--- /dev/null
+++ b/libc/include/limits.h.def
@@ -0,0 +1,14 @@
+//===-- C standard library header limits.h --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_LIMITS_H
+#define LLVM_LIBC_LIMITS_H
+
+#include <llvm-libc-macros/limits-macros.h>
+
+#endif // LLVM_LIBC_LIMITS_H
diff --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt
index d965a6a9443ed2..96ee29d7327224 100644
--- a/libc/include/llvm-libc-macros/CMakeLists.txt
+++ b/libc/include/llvm-libc-macros/CMakeLists.txt
@@ -73,6 +73,12 @@ add_macro_header(
     float-macros.h
 )
 
+add_macro_header(
+  limits_macros
+  HDR
+    limits-macros.h
+)
+
 add_macro_header(
   math_macros
   HDR
diff --git a/libc/include/llvm-libc-macros/float-macros.h b/libc/include/llvm-libc-macros/float-macros.h
index 8e4b91b9a0f557..16ccc8e806617a 100644
--- a/libc/include/llvm-libc-macros/float-macros.h
+++ b/libc/include/llvm-libc-macros/float-macros.h
@@ -9,8 +9,17 @@
 #ifndef __LLVM_LIBC_MACROS_FLOAT_MACROS_H
 #define __LLVM_LIBC_MACROS_FLOAT_MACROS_H
 
+#ifdef __clang__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wgnu-include-next"
+#endif //__clang__
+
 #include_next <float.h>
 
+#ifdef __clang__
+#pragma GCC diagnostic pop
+#endif //__clang__
+
 #ifndef FLT_RADIX
 #define FLT_RADIX __FLT_RADIX__
 #endif // FLT_RADIX
diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h
new file mode 100644
index 00000000000000..e561a95bf3a09a
--- /dev/null
+++ b/libc/include/llvm-libc-macros/limits-macros.h
@@ -0,0 +1,229 @@
+//===-- Definition of macros from limits.h --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef __LLVM_LIBC_MACROS_LIMITS_MACROS_H
+#define __LLVM_LIBC_MACROS_LIMITS_MACROS_H
+
+#ifdef __clang__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wgnu-include-next"
+#endif // __clang__
+
+#include_next <limits.h>
+
+#ifdef __clang__
+#pragma GCC diagnostic pop
+#endif // __clang__
+
+#ifndef CHAR_BIT
+#ifdef __CHAR_BIT__
+#define CHAR_BIT __CHAR_BIT__
+#else
+#define CHAR_BIT 8
+#endif // __CHAR_BIT__
+#endif // CHAR_BIT
+
+// TODO: define MB_LEN_MAX if missing
+//   clang: MB_LEN_MAX = 1 -
+//   https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/limits.h#L64
+//   glibc: MB_LEN_MAX = 16 -
+//   https://github.com/lattera/glibc/blob/master/include/limits.h#L32
+
+// *_WIDTH macros
+
+#ifndef CHAR_WIDTH
+#define CHAR_WIDTH CHAR_BIT
+#endif // CHAR_WIDTH
+
+#ifndef SCHAR_WIDTH
+#define SCHAR_WIDTH CHAR_BIT
+#endif // SCHAR_WIDTH
+
+#ifndef UCHAR_WIDTH
+#define UCHAR_WIDTH CHAR_BIT
+#endif // UCHAR_WIDTH
+
+#ifndef SHRT_WIDTH
+#ifdef __SHRT_WIDTH__
+#define SHRT_WIDTH __SHRT_WIDTH__
+#else
+#define SHRT_WIDTH 16
+#endif // __SHRT_WIDTH__
+#endif // SHRT_WIDTH
+
+#ifndef USHRT_WIDTH
+#define USHRT_WIDTH SHRT_WIDTH
+#endif // USHRT_WIDTH
+
+#ifndef INT_WIDTH
+#ifdef __INT_WIDTH__
+#define INT_WIDTH __INT_WIDTH__
+#else
+#define INT_WIDTH 32
+#endif // __INT_WIDTH__
+#endif // INT_WIDTH
+
+#ifndef UINT_WIDTH
+#define UINT_WIDTH INT_WIDTH
+#endif // UINT_WIDTH
+
+#ifndef LONG_WIDTH
+#ifdef __LONG_WIDTH__
+#define LONG_WIDTH __LONG_WIDTH__
+#elif defined(__WORDSIZE)
+#define LONG_WIDTH __WORDSIZE
+#else
+#error "Unknown WORDSIZE to define LONG_WIDTH."
+#endif // __LONG_WIDTH__
+#endif // LONG_WIDTH
+
+#ifndef ULONG_WIDTH
+#define ULONG_WIDTH LONG_WIDTH
+#endif // ULONG_WIDTH
+
+#ifndef LLONG_WIDTH
+#ifdef __LLONG_WIDTH__
+#define LLONG_WIDTH __LLONG_WIDTH__
+#else
+#define LLONG_WIDTH 64
+#endif // __LLONG_WIDTH__
+#endif // LLONG_WIDTH
+
+#ifndef ULLONG_WIDTH
+#define ULLONG_WIDTH LLONG_WIDTH
+#endif // ULLONG_WIDTH
+
+#ifndef BOOL_WIDTH
+#ifdef __BOOL_WIDTH__
+#define BOOL_WIDTH __BOOL_WIDTH__
+#else
+#define BOOL_WIDTH 1
+#endif // __BOOL_WIDTH__
+#endif // BOOL_WIDTH
+
+// *_MAX macros
+
+#ifndef SCHAR_MAX
+#ifdef __SCHAR_MAX__
+#define SCHAR_MAX __SCHAR_MAX__
+#else
+#define SCHAR_MAX 0x7f
+#endif // __SCHAR_MAX__
+#endif // SCHAR_MAX
+
+#ifndef UCHAR_MAX
+#define UCHAR_MAX (SCHAR_MAX * 2 + 1)
+#endif // UCHAR_MAX
+
+#ifndef CHAR_MAX
+#ifdef __CHAR_UNSIGNED__
+#define CHAR_MAX UCHAR_MAX
+#else
+#define CHAR_MAX SCHAR_MAX
+#endif // __CHAR_UNSIGNED__
+#endif // CHAR_MAX
+
+#ifndef SHRT_MAX
+#ifdef __SHRT_MAX__
+#define SHRT_MAX __SHRT_MAX__
+#else
+#define SHRT_MAX 0x7fff
+#endif // __SHRT_MAX__
+#endif // SHRT_MAX
+
+#ifndef USHRT_MAX
+#define USHRT_MAX (SHRT_MAX * 2U + 1U)
+#endif // USHRT_MAX
+
+#ifndef INT_MAX
+#ifdef __INT_MAX__
+#define INT_MAX __INT_MAX__
+#else
+#define INT_MAX (0 ^ (1 << (INT_WIDTH - 1)))
+#endif // __INT_MAX__
+#endif // INT_MAX
+
+#ifndef UINT_MAX
+#define UINT_MAX (~0U)
+#endif // UINT_MAX
+
+#ifndef LONG_MAX
+#ifdef __LONG_MAX__
+#define LONG_MAX __LONG_MAX__
+#else
+#define LONG_MAX (0L ^ (1L << (LONG_WIDTH - 1)))
+#endif // __LONG_MAX__
+#endif // LONG_MAX
+
+#ifndef ULONG_MAX
+#define ULONG_MAX (~0UL)
+#endif // ULONG_MAX
+
+#ifndef LLONG_MAX
+#ifdef __LONG_LONG_MAX__
+#define LLONG_MAX __LONG_LONG_MAX__
+#else
+#define LLONG_MAX (0LL ^ (1LL << (LLONG_WIDTH - 1)))
+#endif // __LONG_LONG_MAX__
+#endif // LLONG_MAX
+
+#ifndef ULLONG_MAX
+#define ULLONG_MAX (~0ULL)
+#endif // ULLONG_MAX
+
+// *_MIN macros
+
+#ifndef SCHAR_MIN
+#define SCHAR_MIN (-SCHAR_MAX - 1)
+#endif // SCHAR_MIN
+
+#ifndef UCHAR_MIN
+#define UCHAR_MIN 0
+#endif // UCHAR_MIN
+
+#ifndef CHAR_MIN
+#ifdef __CHAR_UNSIGNED__
+#define CHAR_MIN UCHAR_MIN
+#else
+#define CHAR_MIN SCHAR_MIN
+#endif // __CHAR_UNSIGNED__
+#endif // CHAR_MIN
+
+#ifndef SHRT_MIN
+#define SHRT_MIN (-SHRT_MAX - 1)
+#endif // SHRT_MIN
+
+#ifndef USHRT_MIN
+#define USHRT_MIN 0U
+#endif // USHRT_MIN
+
+#ifndef INT_MIN
+#define INT_MIN (-INT_MAX - 1)
+#endif // INT_MIN
+
+#ifndef UINT_MIN
+#define UINT_MIN 0U
+#endif // UINT_MIN
+
+#ifndef LONG_MIN
+#define LONG_MIN (-LONG_MAX - 1L)
+#endif // LONG_MIN
+
+#ifndef ULONG_MIN
+#define ULONG_MIN 0UL
+#endif // ULONG_MIN
+
+#ifndef LLONG_MIN
+#define LLONG_MIN (-LLONG_MAX - 1LL)
+#endif // LLONG_MIN
+
+#ifndef ULLONG_MIN
+#define ULLONG_MIN 0ULL
+#endif // ULLONG_MIN
+
+#endif // __LLVM_LIBC_MACROS_FLOAT_MACROS_H
diff --git a/libc/spec/stdc.td b/libc/spec/stdc.td
index 99e9b3ca65ca59..aa394d6c92f099 100644
--- a/libc/spec/stdc.td
+++ b/libc/spec/stdc.td
@@ -856,6 +856,8 @@ def StdC : StandardSpec<"stdc"> {
       ]
   >;
 
+  HeaderSpec Limits = HeaderSpec<"limits.h">;
+
   NamedType SigAtomicT = NamedType<"sig_atomic_t">;
   HeaderSpec Signal = HeaderSpec<
       "signal.h",
@@ -1159,6 +1161,7 @@ def StdC : StandardSpec<"stdc"> {
     Errno,
     Fenv,
     Float,
+    Limits,
     Math,
     String,
     StdIO,

>From 732feb48c42f05433afc912bca0bd365153f50b6 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Mon, 22 Jan 2024 00:47:56 -0500
Subject: [PATCH 02/11] Address comments.

---
 libc/include/llvm-libc-macros/float-macros.h  | 3 +++
 libc/include/llvm-libc-macros/limits-macros.h | 5 ++++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/libc/include/llvm-libc-macros/float-macros.h b/libc/include/llvm-libc-macros/float-macros.h
index 16ccc8e806617a..5884f4e4b47cf9 100644
--- a/libc/include/llvm-libc-macros/float-macros.h
+++ b/libc/include/llvm-libc-macros/float-macros.h
@@ -9,9 +9,12 @@
 #ifndef __LLVM_LIBC_MACROS_FLOAT_MACROS_H
 #define __LLVM_LIBC_MACROS_FLOAT_MACROS_H
 
+// Suppress `#include_next is a language extension` warnings.
 #ifdef __clang__
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wgnu-include-next"
+#else // gcc
+#pragma GCC system_header
 #endif //__clang__
 
 #include_next <float.h>
diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h
index e561a95bf3a09a..9f2d58b1d4cc80 100644
--- a/libc/include/llvm-libc-macros/limits-macros.h
+++ b/libc/include/llvm-libc-macros/limits-macros.h
@@ -9,9 +9,12 @@
 #ifndef __LLVM_LIBC_MACROS_LIMITS_MACROS_H
 #define __LLVM_LIBC_MACROS_LIMITS_MACROS_H
 
+// Suppress `#include_next is a language extension` warnings.
 #ifdef __clang__
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wgnu-include-next"
+#else // gcc
+#pragma GCC system_header
 #endif // __clang__
 
 #include_next <limits.h>
@@ -32,7 +35,7 @@
 //   clang: MB_LEN_MAX = 1 -
 //   https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/limits.h#L64
 //   glibc: MB_LEN_MAX = 16 -
-//   https://github.com/lattera/glibc/blob/master/include/limits.h#L32
+//   https://github.com/bminor/glibc/blob/master/include/limits.h#L32
 
 // *_WIDTH macros
 

>From 7f22474919e8e2af42bd8b8168c858ed848d753a Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Mon, 22 Jan 2024 01:09:23 -0500
Subject: [PATCH 03/11] Add extra check to see if char is unsigned.

---
 libc/include/llvm-libc-macros/limits-macros.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h
index 9f2d58b1d4cc80..cbfe7150eb0242 100644
--- a/libc/include/llvm-libc-macros/limits-macros.h
+++ b/libc/include/llvm-libc-macros/limits-macros.h
@@ -123,6 +123,11 @@
 #define UCHAR_MAX (SCHAR_MAX * 2 + 1)
 #endif // UCHAR_MAX
 
+// Check if char is unsigned.
+#ifndef __CHAR_UNSIGNED__ && ('\xff' > 0)
+#define __CHAR_UNSIGNED__
+#endif
+
 #ifndef CHAR_MAX
 #ifdef __CHAR_UNSIGNED__
 #define CHAR_MAX UCHAR_MAX

>From 38ac968c4e61dc7d393870a186b07849d156fcc9 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Mon, 22 Jan 2024 01:11:11 -0500
Subject: [PATCH 04/11] Fix unsigned char check condition.

---
 libc/include/llvm-libc-macros/limits-macros.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h
index cbfe7150eb0242..ec8545cf3ffa09 100644
--- a/libc/include/llvm-libc-macros/limits-macros.h
+++ b/libc/include/llvm-libc-macros/limits-macros.h
@@ -124,7 +124,7 @@
 #endif // UCHAR_MAX
 
 // Check if char is unsigned.
-#ifndef __CHAR_UNSIGNED__ && ('\xff' > 0)
+#if !defined(__CHAR_UNSIGNED__) && ('\xff' > 0)
 #define __CHAR_UNSIGNED__
 #endif
 

>From 5a5195a8852333432a9b164327a9f7082e8594c7 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Mon, 22 Jan 2024 14:04:24 -0500
Subject: [PATCH 05/11] Use pragma clang for clang-only diagnostic.

---
 libc/include/llvm-libc-macros/float-macros.h  | 6 +++---
 libc/include/llvm-libc-macros/limits-macros.h | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/libc/include/llvm-libc-macros/float-macros.h b/libc/include/llvm-libc-macros/float-macros.h
index 5884f4e4b47cf9..86ec4939393086 100644
--- a/libc/include/llvm-libc-macros/float-macros.h
+++ b/libc/include/llvm-libc-macros/float-macros.h
@@ -11,8 +11,8 @@
 
 // Suppress `#include_next is a language extension` warnings.
 #ifdef __clang__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wgnu-include-next"
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wgnu-include-next"
 #else // gcc
 #pragma GCC system_header
 #endif //__clang__
@@ -20,7 +20,7 @@
 #include_next <float.h>
 
 #ifdef __clang__
-#pragma GCC diagnostic pop
+#pragma clang diagnostic pop
 #endif //__clang__
 
 #ifndef FLT_RADIX
diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h
index ec8545cf3ffa09..31dc8f344b19b8 100644
--- a/libc/include/llvm-libc-macros/limits-macros.h
+++ b/libc/include/llvm-libc-macros/limits-macros.h
@@ -11,8 +11,8 @@
 
 // Suppress `#include_next is a language extension` warnings.
 #ifdef __clang__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wgnu-include-next"
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wgnu-include-next"
 #else // gcc
 #pragma GCC system_header
 #endif // __clang__
@@ -20,7 +20,7 @@
 #include_next <limits.h>
 
 #ifdef __clang__
-#pragma GCC diagnostic pop
+#pragma clang diagnostic pop
 #endif // __clang__
 
 #ifndef CHAR_BIT

>From fbcafe9a38ddd583ee59cbd9284389497a46d0fa Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Mon, 22 Jan 2024 17:37:00 -0500
Subject: [PATCH 06/11] Add extra checks for limits.h header when building with
 gcc.

---
 libc/include/llvm-libc-macros/limits-macros.h | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h
index 31dc8f344b19b8..91cffef6598af3 100644
--- a/libc/include/llvm-libc-macros/limits-macros.h
+++ b/libc/include/llvm-libc-macros/limits-macros.h
@@ -9,20 +9,30 @@
 #ifndef __LLVM_LIBC_MACROS_LIMITS_MACROS_H
 #define __LLVM_LIBC_MACROS_LIMITS_MACROS_H
 
+#if __has_include_next(<limits.h>)
+
 // Suppress `#include_next is a language extension` warnings.
 #ifdef __clang__
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wgnu-include-next"
-#else // gcc
+#elif defined(__GNUC__) // gcc
+#if !defined _GCC_LIMITS_H_
+#define _GCC_LIMITS_H_
+#endif
 #pragma GCC system_header
-#endif // __clang__
+#endif // __clang__, __GNUC__
 
+// Include compiler's header
 #include_next <limits.h>
 
 #ifdef __clang__
 #pragma clang diagnostic pop
 #endif // __clang__
 
+#endif // __has_include_next(<limits.h>)
+
+// Supplement missing macros.
+
 #ifndef CHAR_BIT
 #ifdef __CHAR_BIT__
 #define CHAR_BIT __CHAR_BIT__

>From d620a8890522b8b91f7cd3aa7da0e4c821a6c6a1 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Mon, 22 Jan 2024 18:05:14 -0500
Subject: [PATCH 07/11] Simplify macro checks.

---
 libc/include/llvm-libc-macros/limits-macros.h | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h
index 91cffef6598af3..9fdbb3d941dca6 100644
--- a/libc/include/llvm-libc-macros/limits-macros.h
+++ b/libc/include/llvm-libc-macros/limits-macros.h
@@ -15,13 +15,16 @@
 #ifdef __clang__
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wgnu-include-next"
-#elif defined(__GNUC__) // gcc
-#if !defined _GCC_LIMITS_H_
-#define _GCC_LIMITS_H_
-#endif
+#else // gcc
 #pragma GCC system_header
 #endif // __clang__, __GNUC__
 
+#if defined(__GNUC__) && !defined(_GCC_LIMITS_H_)
+// The system's limits.h may, in turn, try to #include_next GCC's limits.h.
+// Define the macro _GCC_LIMITS_H_ to stop its chains of #include_next.
+#define _GCC_LIMITS_H_
+#endif
+
 // Include compiler's header
 #include_next <limits.h>
 

>From 50db52437dc5be7140c948aadf0bf77275b9b958 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Mon, 22 Jan 2024 18:12:40 -0500
Subject: [PATCH 08/11] Update comments.

---
 libc/include/llvm-libc-macros/limits-macros.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h
index 9fdbb3d941dca6..b1edfe6b77d596 100644
--- a/libc/include/llvm-libc-macros/limits-macros.h
+++ b/libc/include/llvm-libc-macros/limits-macros.h
@@ -34,7 +34,7 @@
 
 #endif // __has_include_next(<limits.h>)
 
-// Supplement missing macros.
+// Supplement missing macros if there are any.
 
 #ifndef CHAR_BIT
 #ifdef __CHAR_BIT__

>From b03ddf3dd44e2321f6a2be5bfe49f433892e3141 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Mon, 22 Jan 2024 19:37:23 -0500
Subject: [PATCH 09/11] Distinguish clang and gcc before setting
 _GCC_LIMITS_H_.

---
 libc/include/llvm-libc-macros/limits-macros.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h
index b1edfe6b77d596..3ae9d76c59e137 100644
--- a/libc/include/llvm-libc-macros/limits-macros.h
+++ b/libc/include/llvm-libc-macros/limits-macros.h
@@ -19,8 +19,9 @@
 #pragma GCC system_header
 #endif // __clang__, __GNUC__
 
-#if defined(__GNUC__) && !defined(_GCC_LIMITS_H_)
-// The system's limits.h may, in turn, try to #include_next GCC's limits.h.
+#if defined(__GNUC__) && !defined(__clang__) && !defined(_GCC_LIMITS_H_)
+// The system's limits.h may, in turn, try to #include_next GCC's limits.h when
+// building with GCC.
 // Define the macro _GCC_LIMITS_H_ to stop its chains of #include_next.
 #define _GCC_LIMITS_H_
 #endif

>From 241f16eaa6dfd8be2c2898f229c215a03be56a2d Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Wed, 24 Jan 2024 00:05:25 -0500
Subject: [PATCH 10/11] Sync and remove all internal usage of `#include
 <limits.h>`.

---
 libc/cmake/modules/LLVMLibCLibraryRules.cmake     | 12 +++++++++++-
 libc/include/llvm-libc-macros/limits-macros.h     |  1 +
 libc/src/__support/CMakeLists.txt                 |  1 +
 libc/src/__support/CPP/CMakeLists.txt             |  1 +
 libc/src/__support/CPP/limits.h                   | 11 +----------
 libc/src/__support/FPUtil/CMakeLists.txt          |  1 +
 libc/src/__support/FPUtil/ManipulationFunctions.h |  2 +-
 libc/src/__support/math_extras.h                  |  3 +--
 libc/src/__support/str_to_integer.h               |  1 -
 libc/src/__support/threads/linux/CMakeLists.txt   |  1 +
 libc/src/__support/threads/linux/callonce.cpp     |  2 +-
 libc/src/time/CMakeLists.txt                      |  1 +
 libc/src/time/mktime.cpp                          |  2 --
 libc/src/time/time_utils.cpp                      |  3 +--
 libc/test/src/math/CMakeLists.txt                 |  6 ++++++
 libc/test/src/math/ILogbTest.h                    |  3 +--
 libc/test/src/math/LdExpTest.h                    |  2 +-
 libc/test/src/math/smoke/CMakeLists.txt           |  6 ++++++
 libc/test/src/math/smoke/ILogbTest.h              |  3 +--
 libc/test/src/math/smoke/LdExpTest.h              |  2 +-
 libc/test/src/stdlib/AtoiTest.h                   |  3 +--
 libc/test/src/stdlib/CMakeLists.txt               |  1 +
 libc/test/src/stdlib/StrtolTest.h                 |  1 -
 libc/test/src/stdlib/atof_test.cpp                |  1 -
 libc/test/src/stdlib/strtod_test.cpp              |  1 -
 libc/test/src/stdlib/strtof_test.cpp              |  1 -
 libc/test/src/stdlib/strtold_test.cpp             |  1 -
 libc/test/src/time/CMakeLists.txt                 |  2 ++
 libc/test/src/time/clock_test.cpp                 |  1 -
 libc/test/src/time/gmtime_test.cpp                |  3 +--
 libc/test/src/time/mktime_test.cpp                |  3 +--
 libc/test/src/time/time_test.cpp                  |  1 -
 32 files changed, 44 insertions(+), 39 deletions(-)

diff --git a/libc/cmake/modules/LLVMLibCLibraryRules.cmake b/libc/cmake/modules/LLVMLibCLibraryRules.cmake
index e6cfd79e65a085..adb3bdeea2cb3b 100644
--- a/libc/cmake/modules/LLVMLibCLibraryRules.cmake
+++ b/libc/cmake/modules/LLVMLibCLibraryRules.cmake
@@ -173,7 +173,17 @@ function(create_header_library fq_target_name)
   target_sources(${fq_target_name} INTERFACE ${ADD_HEADER_HDRS})
   if(ADD_HEADER_DEPENDS)
     add_dependencies(${fq_target_name} ${ADD_HEADER_DEPENDS})
-    target_link_libraries(${fq_target_name} INTERFACE ${ADD_HEADER_DEPENDS})
+
+    # `*.__copied_hdr__` is created only to copy the header files to the target
+    # location, not to be linked against.
+    set(link_lib "")
+    foreach(dep ${ADD_HEADER_DEPENDS})
+      if (NOT dep MATCHES "__copied_hdr__")
+        list(APPEND link_lib ${dep})
+      endif()
+    endforeach()
+
+    target_link_libraries(${fq_target_name} INTERFACE ${link_lib})
   endif()
   if(ADD_HEADER_COMPILE_OPTIONS)
     target_compile_options(${fq_target_name} INTERFACE ${ADD_HEADER_COMPILE_OPTIONS})
diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h
index 3ae9d76c59e137..933736a1e3450e 100644
--- a/libc/include/llvm-libc-macros/limits-macros.h
+++ b/libc/include/llvm-libc-macros/limits-macros.h
@@ -36,6 +36,7 @@
 #endif // __has_include_next(<limits.h>)
 
 // Supplement missing macros if there are any.
+// Making sure that we provide all C23 constants.
 
 #ifndef CHAR_BIT
 #ifdef __CHAR_BIT__
diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt
index 502bf72ae9906b..595124702763bb 100644
--- a/libc/src/__support/CMakeLists.txt
+++ b/libc/src/__support/CMakeLists.txt
@@ -34,6 +34,7 @@ add_header_library(
   HDRS
     math_extras.h
   DEPENDS
+    libc.src.__support.CPP.limits
     libc.src.__support.CPP.type_traits
     libc.src.__support.macros.attributes
     libc.src.__support.macros.config
diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt
index 1a31b4ecbe4740..f10bb936047eb9 100644
--- a/libc/src/__support/CPP/CMakeLists.txt
+++ b/libc/src/__support/CPP/CMakeLists.txt
@@ -48,6 +48,7 @@ add_header_library(
     limits.h
   DEPENDS
     .type_traits
+    libc.include.llvm-libc-macros.limits_macros
 )
 
 add_header_library(
diff --git a/libc/src/__support/CPP/limits.h b/libc/src/__support/CPP/limits.h
index d9e7090a0b7b19..1ffde5f9556f87 100644
--- a/libc/src/__support/CPP/limits.h
+++ b/libc/src/__support/CPP/limits.h
@@ -9,23 +9,14 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_LIMITS_H
 #define LLVM_LIBC_SRC___SUPPORT_CPP_LIMITS_H
 
+#include "include/llvm-libc-macros/limits-macros.h" // CHAR_BIT
 #include "src/__support/CPP/type_traits/is_integral.h"
 #include "src/__support/CPP/type_traits/is_signed.h"
 #include "src/__support/macros/attributes.h" // LIBC_INLINE
 
-#include <limits.h> // CHAR_BIT
-
 namespace LIBC_NAMESPACE {
 namespace cpp {
 
-// Some older gcc distributions don't define these for 32 bit targets.
-#ifndef LLONG_MAX
-constexpr unsigned int LLONG_BIT_WIDTH = sizeof(long long) * 8;
-constexpr long long LLONG_MAX = ~0LL ^ (1LL << (LLONG_BIT_WIDTH - 1));
-constexpr long long LLONG_MIN = 1LL << (LLONG_BIT_WIDTH - 1);
-constexpr unsigned long long ULLONG_MAX = ~0ULL;
-#endif
-
 namespace internal {
 
 template <typename T, T min_value, T max_value> struct integer_impl {
diff --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index ad2c4ad27bced3..50cc904f0cfada 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -84,6 +84,7 @@ add_header_library(
     .nearest_integer_operations
     .normal_float
     libc.src.__support.CPP.bit
+    libc.src.__support.CPP.limits
     libc.src.__support.CPP.type_traits
     libc.src.__support.common
     libc.src.__support.macros.optimization
diff --git a/libc/src/__support/FPUtil/ManipulationFunctions.h b/libc/src/__support/FPUtil/ManipulationFunctions.h
index 56e53e3d4f497c..9becbaa45eadeb 100644
--- a/libc/src/__support/FPUtil/ManipulationFunctions.h
+++ b/libc/src/__support/FPUtil/ManipulationFunctions.h
@@ -14,12 +14,12 @@
 #include "NormalFloat.h"
 
 #include "src/__support/CPP/bit.h"
+#include "src/__support/CPP/limits.h" // INT_MAX, INT_MIN
 #include "src/__support/CPP/type_traits.h"
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/macros/attributes.h"
 #include "src/__support/macros/optimization.h" // LIBC_UNLIKELY
 
-#include <limits.h>
 #include <math.h>
 
 namespace LIBC_NAMESPACE {
diff --git a/libc/src/__support/math_extras.h b/libc/src/__support/math_extras.h
index 89bd0b72669ea2..8ec30396ffdb46 100644
--- a/libc/src/__support/math_extras.h
+++ b/libc/src/__support/math_extras.h
@@ -10,12 +10,11 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H
 #define LLVM_LIBC_SRC___SUPPORT_MATH_EXTRAS_H
 
+#include "src/__support/CPP/limits.h"        // CHAR_BIT
 #include "src/__support/CPP/type_traits.h"   // is_unsigned_v
 #include "src/__support/macros/attributes.h" // LIBC_INLINE
 #include "src/__support/macros/config.h"     // LIBC_HAS_BUILTIN
 
-#include <limits.h> // CHAR_BIT
-
 namespace LIBC_NAMESPACE {
 
 // Create a bitmask with the count right-most bits set to 1, and all other bits
diff --git a/libc/src/__support/str_to_integer.h b/libc/src/__support/str_to_integer.h
index 4ee336ec9e2bbd..e83a508e086b18 100644
--- a/libc/src/__support/str_to_integer.h
+++ b/libc/src/__support/str_to_integer.h
@@ -15,7 +15,6 @@
 #include "src/__support/ctype_utils.h"
 #include "src/__support/str_to_num_result.h"
 #include "src/errno/libc_errno.h" // For ERANGE
-#include <limits.h>
 
 namespace LIBC_NAMESPACE {
 namespace internal {
diff --git a/libc/src/__support/threads/linux/CMakeLists.txt b/libc/src/__support/threads/linux/CMakeLists.txt
index 148a0ba061c577..87a7a66ac6ea57 100644
--- a/libc/src/__support/threads/linux/CMakeLists.txt
+++ b/libc/src/__support/threads/linux/CMakeLists.txt
@@ -52,5 +52,6 @@ add_object_library(
   DEPENDS
     libc.include.sys_syscall
     libc.src.__support.CPP.atomic
+    libc.src.__support.CPP.limits
     libc.src.__support.OSUtil.osutil
 )
diff --git a/libc/src/__support/threads/linux/callonce.cpp b/libc/src/__support/threads/linux/callonce.cpp
index de1e1008784f60..b6a5ab8c0d07a9 100644
--- a/libc/src/__support/threads/linux/callonce.cpp
+++ b/libc/src/__support/threads/linux/callonce.cpp
@@ -9,10 +9,10 @@
 #include "futex_word.h"
 
 #include "src/__support/CPP/atomic.h"
+#include "src/__support/CPP/limits.h"     // INT_MAX
 #include "src/__support/OSUtil/syscall.h" // For syscall functions.
 #include "src/__support/threads/callonce.h"
 
-#include <limits.h>
 #include <linux/futex.h>
 #include <sys/syscall.h> // For syscall numbers.
 
diff --git a/libc/src/time/CMakeLists.txt b/libc/src/time/CMakeLists.txt
index 210f3b23432b49..5680718715974e 100644
--- a/libc/src/time/CMakeLists.txt
+++ b/libc/src/time/CMakeLists.txt
@@ -10,6 +10,7 @@ add_object_library(
     time_utils.h
   DEPENDS
     libc.include.time
+    libc.src.__support.CPP.limits
     libc.src.errno.errno
 )
 
diff --git a/libc/src/time/mktime.cpp b/libc/src/time/mktime.cpp
index e57565f0d1fe01..8a4397e5eac7c2 100644
--- a/libc/src/time/mktime.cpp
+++ b/libc/src/time/mktime.cpp
@@ -10,8 +10,6 @@
 #include "src/__support/common.h"
 #include "src/time/time_utils.h"
 
-#include <limits.h>
-
 namespace LIBC_NAMESPACE {
 
 using LIBC_NAMESPACE::time_utils::TimeConstants;
diff --git a/libc/src/time/time_utils.cpp b/libc/src/time/time_utils.cpp
index 199a74cb168a2c..713ed21e3191d5 100644
--- a/libc/src/time/time_utils.cpp
+++ b/libc/src/time/time_utils.cpp
@@ -7,10 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/time/time_utils.h"
+#include "src/__support/CPP/limits.h" // INT_MIN, INT_MAX
 #include "src/__support/common.h"
 
-#include <limits.h>
-
 namespace LIBC_NAMESPACE {
 namespace time_utils {
 
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index fcb47449748dca..8c105515e3525c 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -767,6 +767,7 @@ if(NOT LIBC_GPU_TARGET_ARCHITECTURE_IS_NVPTX)
     DEPENDS
       libc.include.math
       libc.src.math.ilogb
+      libc.src.__support.CPP.limits
       libc.src.__support.FPUtil.fp_bits
       libc.src.__support.FPUtil.manipulation_functions
   )
@@ -782,6 +783,7 @@ if(NOT LIBC_GPU_TARGET_ARCHITECTURE_IS_NVPTX)
     DEPENDS
       libc.include.math
       libc.src.math.ilogbf
+      libc.src.__support.CPP.limits
       libc.src.__support.FPUtil.fp_bits
       libc.src.__support.FPUtil.manipulation_functions
   )
@@ -798,6 +800,7 @@ add_fp_unittest(
   DEPENDS
     libc.include.math
     libc.src.math.ilogbl
+    libc.src.__support.CPP.limits
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.manipulation_functions
 )
@@ -813,6 +816,7 @@ add_fp_unittest(
   DEPENDS
     libc.include.math
     libc.src.math.ldexp
+    libc.src.__support.CPP.limits
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.normal_float
 )
@@ -828,6 +832,7 @@ add_fp_unittest(
   DEPENDS
     libc.include.math
     libc.src.math.ldexpf
+    libc.src.__support.CPP.limits
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.normal_float
 )
@@ -843,6 +848,7 @@ add_fp_unittest(
   DEPENDS
     libc.include.math
     libc.src.math.ldexpl
+    libc.src.__support.CPP.limits
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.normal_float
 )
diff --git a/libc/test/src/math/ILogbTest.h b/libc/test/src/math/ILogbTest.h
index fb8d77093eba3c..5fb3a5ab8923bf 100644
--- a/libc/test/src/math/ILogbTest.h
+++ b/libc/test/src/math/ILogbTest.h
@@ -9,13 +9,12 @@
 #ifndef LLVM_LIBC_TEST_SRC_MATH_ILOGBTEST_H
 #define LLVM_LIBC_TEST_SRC_MATH_ILOGBTEST_H
 
+#include "src/__support/CPP/limits.h" // INT_MAX
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/ManipulationFunctions.h"
 #include "test/UnitTest/Test.h"
 #include <math.h>
 
-#include <limits.h>
-
 class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test {
 public:
   template <typename T> struct ILogbFunc {
diff --git a/libc/test/src/math/LdExpTest.h b/libc/test/src/math/LdExpTest.h
index 1d581f2c0a02fc..faa9149830adcc 100644
--- a/libc/test/src/math/LdExpTest.h
+++ b/libc/test/src/math/LdExpTest.h
@@ -9,12 +9,12 @@
 #ifndef LLVM_LIBC_TEST_SRC_MATH_LDEXPTEST_H
 #define LLVM_LIBC_TEST_SRC_MATH_LDEXPTEST_H
 
+#include "src/__support/CPP/limits.h" // INT_MAX
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/NormalFloat.h"
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 
-#include <limits.h>
 #include <math.h>
 #include <stdint.h>
 
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index 163fa924b243ac..25d6d7e6d8e2b8 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -761,6 +761,7 @@ if(NOT LIBC_GPU_TARGET_ARCHITECTURE_IS_NVPTX)
     DEPENDS
       libc.include.math
       libc.src.math.ilogb
+      libc.src.__support.CPP.limits
       libc.src.__support.FPUtil.fp_bits
       libc.src.__support.FPUtil.manipulation_functions
   )
@@ -776,6 +777,7 @@ if(NOT LIBC_GPU_TARGET_ARCHITECTURE_IS_NVPTX)
     DEPENDS
       libc.include.math
       libc.src.math.ilogbf
+      libc.src.__support.CPP.limits
       libc.src.__support.FPUtil.fp_bits
       libc.src.__support.FPUtil.manipulation_functions
   )
@@ -792,6 +794,7 @@ add_fp_unittest(
   DEPENDS
     libc.include.math
     libc.src.math.ilogbl
+    libc.src.__support.CPP.limits
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.manipulation_functions
 )
@@ -807,6 +810,7 @@ add_fp_unittest(
   DEPENDS
     libc.include.math
     libc.src.math.ldexp
+    libc.src.__support.CPP.limits
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.normal_float
 )
@@ -822,6 +826,7 @@ add_fp_unittest(
   DEPENDS
     libc.include.math
     libc.src.math.ldexpf
+    libc.src.__support.CPP.limits
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.normal_float
 )
@@ -837,6 +842,7 @@ add_fp_unittest(
   DEPENDS
     libc.include.math
     libc.src.math.ldexpl
+    libc.src.__support.CPP.limits
     libc.src.__support.FPUtil.fp_bits
     libc.src.__support.FPUtil.normal_float
 )
diff --git a/libc/test/src/math/smoke/ILogbTest.h b/libc/test/src/math/smoke/ILogbTest.h
index fb8d77093eba3c..5fb3a5ab8923bf 100644
--- a/libc/test/src/math/smoke/ILogbTest.h
+++ b/libc/test/src/math/smoke/ILogbTest.h
@@ -9,13 +9,12 @@
 #ifndef LLVM_LIBC_TEST_SRC_MATH_ILOGBTEST_H
 #define LLVM_LIBC_TEST_SRC_MATH_ILOGBTEST_H
 
+#include "src/__support/CPP/limits.h" // INT_MAX
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/ManipulationFunctions.h"
 #include "test/UnitTest/Test.h"
 #include <math.h>
 
-#include <limits.h>
-
 class LlvmLibcILogbTest : public LIBC_NAMESPACE::testing::Test {
 public:
   template <typename T> struct ILogbFunc {
diff --git a/libc/test/src/math/smoke/LdExpTest.h b/libc/test/src/math/smoke/LdExpTest.h
index 1d581f2c0a02fc..faa9149830adcc 100644
--- a/libc/test/src/math/smoke/LdExpTest.h
+++ b/libc/test/src/math/smoke/LdExpTest.h
@@ -9,12 +9,12 @@
 #ifndef LLVM_LIBC_TEST_SRC_MATH_LDEXPTEST_H
 #define LLVM_LIBC_TEST_SRC_MATH_LDEXPTEST_H
 
+#include "src/__support/CPP/limits.h" // INT_MAX
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/NormalFloat.h"
 #include "test/UnitTest/FPMatcher.h"
 #include "test/UnitTest/Test.h"
 
-#include <limits.h>
 #include <math.h>
 #include <stdint.h>
 
diff --git a/libc/test/src/stdlib/AtoiTest.h b/libc/test/src/stdlib/AtoiTest.h
index 85701828c0f6b7..5e86a738a3aef3 100644
--- a/libc/test/src/stdlib/AtoiTest.h
+++ b/libc/test/src/stdlib/AtoiTest.h
@@ -6,11 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/__support/CPP/limits.h" // INT_MAX, INT_MIN, LLONG_MAX, LLONG_MIN
 #include "src/__support/CPP/type_traits.h"
 #include "test/UnitTest/Test.h"
 
-#include <limits.h>
-
 using LIBC_NAMESPACE::cpp::is_same_v;
 
 template <typename ReturnT>
diff --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt
index 3c2eeeaa36926f..da07dbbe797720 100644
--- a/libc/test/src/stdlib/CMakeLists.txt
+++ b/libc/test/src/stdlib/CMakeLists.txt
@@ -17,6 +17,7 @@ add_header_library(
     AtoiTest.h
   DEPENDS
     libc.src.errno.errno
+    libc.src.__support.CPP.limits
     libc.src.__support.CPP.type_traits
 )
 
diff --git a/libc/test/src/stdlib/StrtolTest.h b/libc/test/src/stdlib/StrtolTest.h
index 11794c4bfe05f8..6aee049aa066a0 100644
--- a/libc/test/src/stdlib/StrtolTest.h
+++ b/libc/test/src/stdlib/StrtolTest.h
@@ -12,7 +12,6 @@
 #include "src/errno/libc_errno.h"
 #include "test/UnitTest/Test.h"
 
-#include <limits.h>
 #include <stddef.h>
 
 using LIBC_NAMESPACE::cpp::is_signed_v;
diff --git a/libc/test/src/stdlib/atof_test.cpp b/libc/test/src/stdlib/atof_test.cpp
index 613b56d05091ec..858ab326e38d01 100644
--- a/libc/test/src/stdlib/atof_test.cpp
+++ b/libc/test/src/stdlib/atof_test.cpp
@@ -13,7 +13,6 @@
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
 
-#include <limits.h>
 #include <stddef.h>
 
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
diff --git a/libc/test/src/stdlib/strtod_test.cpp b/libc/test/src/stdlib/strtod_test.cpp
index 452a180d70cea6..e68c8610b40704 100644
--- a/libc/test/src/stdlib/strtod_test.cpp
+++ b/libc/test/src/stdlib/strtod_test.cpp
@@ -14,7 +14,6 @@
 #include "test/UnitTest/RoundingModeUtils.h"
 #include "test/UnitTest/Test.h"
 
-#include <limits.h>
 #include <stddef.h>
 
 using LIBC_NAMESPACE::fputil::testing::ForceRoundingModeTest;
diff --git a/libc/test/src/stdlib/strtof_test.cpp b/libc/test/src/stdlib/strtof_test.cpp
index 31b3f69f63a0c7..f30c588c611b39 100644
--- a/libc/test/src/stdlib/strtof_test.cpp
+++ b/libc/test/src/stdlib/strtof_test.cpp
@@ -14,7 +14,6 @@
 #include "test/UnitTest/RoundingModeUtils.h"
 #include "test/UnitTest/Test.h"
 
-#include <limits.h>
 #include <stddef.h>
 
 using LIBC_NAMESPACE::fputil::testing::ForceRoundingModeTest;
diff --git a/libc/test/src/stdlib/strtold_test.cpp b/libc/test/src/stdlib/strtold_test.cpp
index 51f9975772aa5e..b7942ab66460b6 100644
--- a/libc/test/src/stdlib/strtold_test.cpp
+++ b/libc/test/src/stdlib/strtold_test.cpp
@@ -13,7 +13,6 @@
 
 #include "test/UnitTest/Test.h"
 
-#include <limits.h>
 #include <stddef.h>
 
 #if defined(LIBC_LONG_DOUBLE_IS_FLOAT64)
diff --git a/libc/test/src/time/CMakeLists.txt b/libc/test/src/time/CMakeLists.txt
index 10b63ce6f39d29..ebb0998feb23e9 100644
--- a/libc/test/src/time/CMakeLists.txt
+++ b/libc/test/src/time/CMakeLists.txt
@@ -71,6 +71,7 @@ add_libc_unittest(
     TmMatcher.h
   DEPENDS
     libc.src.time.gmtime
+    libc.src.__support.CPP.limits
 )
 
 add_libc_unittest(
@@ -98,6 +99,7 @@ add_libc_unittest(
     20
   DEPENDS
     libc.src.time.mktime
+    libc.src.__support.CPP.limits
 )
 
 # Sleeping is not supported on older NVPTX architectures.
diff --git a/libc/test/src/time/clock_test.cpp b/libc/test/src/time/clock_test.cpp
index a3dffc6bae3913..05082aa2338852 100644
--- a/libc/test/src/time/clock_test.cpp
+++ b/libc/test/src/time/clock_test.cpp
@@ -9,7 +9,6 @@
 #include "src/time/clock.h"
 #include "test/UnitTest/Test.h"
 
-#include <limits.h>
 #include <time.h>
 
 TEST(LlvmLibcClockTest, SmokeTest) {
diff --git a/libc/test/src/time/gmtime_test.cpp b/libc/test/src/time/gmtime_test.cpp
index 6b1d029a693c38..e59daf012d9b6c 100644
--- a/libc/test/src/time/gmtime_test.cpp
+++ b/libc/test/src/time/gmtime_test.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/__support/CPP/limits.h" // INT_MAX, INT_MIN
 #include "src/errno/libc_errno.h"
 #include "src/time/gmtime.h"
 #include "src/time/time_utils.h"
@@ -13,8 +14,6 @@
 #include "test/UnitTest/Test.h"
 #include "test/src/time/TmMatcher.h"
 
-#include <limits.h>
-
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
 using LIBC_NAMESPACE::time_utils::TimeConstants;
diff --git a/libc/test/src/time/mktime_test.cpp b/libc/test/src/time/mktime_test.cpp
index 6f179150953b7f..3142a4f3d06dd8 100644
--- a/libc/test/src/time/mktime_test.cpp
+++ b/libc/test/src/time/mktime_test.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/__support/CPP/limits.h" // INT_MAX
 #include "src/time/mktime.h"
 #include "src/time/time_utils.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
@@ -13,8 +14,6 @@
 #include "test/src/time/TmHelper.h"
 #include "test/src/time/TmMatcher.h"
 
-#include <limits.h>
-
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
 using LIBC_NAMESPACE::time_utils::Month;
diff --git a/libc/test/src/time/time_test.cpp b/libc/test/src/time/time_test.cpp
index 1d938e8dae7adb..d3d4dc9a285158 100644
--- a/libc/test/src/time/time_test.cpp
+++ b/libc/test/src/time/time_test.cpp
@@ -9,7 +9,6 @@
 #include "src/time/time_func.h"
 #include "test/UnitTest/Test.h"
 
-#include <limits.h>
 #include <time.h>
 
 TEST(LlvmLibcTimeTest, SmokeTest) {

>From 4635eaeb76d7602741b6957a194bab89f93b1ade Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Wed, 24 Jan 2024 15:23:04 -0500
Subject: [PATCH 11/11] Remove #include_next <limits.h>

---
 libc/include/llvm-libc-macros/limits-macros.h | 42 ++++---------------
 1 file changed, 8 insertions(+), 34 deletions(-)

diff --git a/libc/include/llvm-libc-macros/limits-macros.h b/libc/include/llvm-libc-macros/limits-macros.h
index 933736a1e3450e..fc21d1318a081b 100644
--- a/libc/include/llvm-libc-macros/limits-macros.h
+++ b/libc/include/llvm-libc-macros/limits-macros.h
@@ -9,34 +9,7 @@
 #ifndef __LLVM_LIBC_MACROS_LIMITS_MACROS_H
 #define __LLVM_LIBC_MACROS_LIMITS_MACROS_H
 
-#if __has_include_next(<limits.h>)
-
-// Suppress `#include_next is a language extension` warnings.
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wgnu-include-next"
-#else // gcc
-#pragma GCC system_header
-#endif // __clang__, __GNUC__
-
-#if defined(__GNUC__) && !defined(__clang__) && !defined(_GCC_LIMITS_H_)
-// The system's limits.h may, in turn, try to #include_next GCC's limits.h when
-// building with GCC.
-// Define the macro _GCC_LIMITS_H_ to stop its chains of #include_next.
-#define _GCC_LIMITS_H_
-#endif
-
-// Include compiler's header
-#include_next <limits.h>
-
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif // __clang__
-
-#endif // __has_include_next(<limits.h>)
-
-// Supplement missing macros if there are any.
-// Making sure that we provide all C23 constants.
+// Define all C23 macro constants of limits.h
 
 #ifndef CHAR_BIT
 #ifdef __CHAR_BIT__
@@ -46,11 +19,12 @@
 #endif // __CHAR_BIT__
 #endif // CHAR_BIT
 
-// TODO: define MB_LEN_MAX if missing
-//   clang: MB_LEN_MAX = 1 -
-//   https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/limits.h#L64
-//   glibc: MB_LEN_MAX = 16 -
-//   https://github.com/bminor/glibc/blob/master/include/limits.h#L32
+// TODO: https://github.com/llvm/llvm-project/issues/79358
+//   Define MB_LEN_MAX if missing.
+//     clang: MB_LEN_MAX = 1 -
+// https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/limits.h#L64
+//     glibc: MB_LEN_MAX = 16 -
+// https://github.com/bminor/glibc/blob/master/include/limits.h#L32
 
 // *_WIDTH macros
 
@@ -249,4 +223,4 @@
 #define ULLONG_MIN 0ULL
 #endif // ULLONG_MIN
 
-#endif // __LLVM_LIBC_MACROS_FLOAT_MACROS_H
+#endif // __LLVM_LIBC_MACROS_LIMITS_MACROS_H



More information about the libc-commits mailing list