[libcxx-commits] [libcxx] [libc++] __need_infinity_nan doesn't work in non-gnu c++ standards (PR #172539)
Ian Anderson via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jan 6 14:29:48 PST 2026
https://github.com/ian-twilightcoder updated https://github.com/llvm/llvm-project/pull/172539
>From 8288bdb3065ba455c0ef21382c32e5934c4c1591 Mon Sep 17 00:00:00 2001
From: Ian Anderson <iana at apple.com>
Date: Tue, 16 Dec 2025 11:30:31 -0800
Subject: [PATCH 1/3] [libc++] __need_infinity_nan doesn't work in non-gnu c++
standards
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
https://github.com/llvm/llvm-project/pull/164348 adds a __need_infinity_nan macro to clang’s float.h. libc++’s float.h then needs to be a textual header to support it. That means we need to move all of the declarations out of float.h and into separate headers that can be normal modular so that their declarations don't get copied into all of the modules that include float.h.
---
libcxx/include/CMakeLists.txt | 3 +
libcxx/include/__cxx03/cfloat | 4 +-
libcxx/include/__cxx03/float.h | 95 +++++++++++++++++++
libcxx/include/__float/characteristics.h | 32 +++++++
libcxx/include/__float/header_macro.h | 19 ++++
libcxx/include/float.h | 49 ++++------
libcxx/include/module.modulemap.in | 5 +-
.../extensions/clang/need_macros.verify.cpp | 49 ++++++++++
libcxx/utils/generate_iwyu_mapping.py | 2 +
9 files changed, 226 insertions(+), 32 deletions(-)
create mode 100644 libcxx/include/__cxx03/float.h
create mode 100644 libcxx/include/__float/characteristics.h
create mode 100644 libcxx/include/__float/header_macro.h
create mode 100644 libcxx/test/extensions/clang/need_macros.verify.cpp
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index f9ae22accd687..0d07a0d3a55e2 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -382,6 +382,8 @@ set(files
__flat_set/flat_set.h
__flat_set/ra_iterator.h
__flat_set/utils.h
+ __float/characteristics.h
+ __float/header_macro.h
__format/buffer.h
__format/concepts.h
__format/container_adaptor.h
@@ -1622,6 +1624,7 @@ set(files
__cxx03/ext/__hash
__cxx03/ext/hash_map
__cxx03/ext/hash_set
+ __cxx03/float.h
__cxx03/forward_list
__cxx03/fstream
__cxx03/functional
diff --git a/libcxx/include/__cxx03/cfloat b/libcxx/include/__cxx03/cfloat
index a48a213f1669f..5d10db6a454a6 100644
--- a/libcxx/include/__cxx03/cfloat
+++ b/libcxx/include/__cxx03/cfloat
@@ -71,9 +71,9 @@ Macros:
#include <__cxx03/__config>
-#include <float.h>
+#include <__cxx03/float.h>
-#ifndef _LIBCPP_FLOAT_H
+#ifndef _LIBCPP___CXX03_FLOAT_H
# error <cfloat> tried including <float.h> but didn't find libc++'s <float.h> header. \
This usually means that your header search paths are not configured properly. \
The header search paths should contain the C++ Standard Library headers before \
diff --git a/libcxx/include/__cxx03/float.h b/libcxx/include/__cxx03/float.h
new file mode 100644
index 0000000000000..38f199067f411
--- /dev/null
+++ b/libcxx/include/__cxx03/float.h
@@ -0,0 +1,95 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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 _LIBCPP___CXX03_FLOAT_H
+#define _LIBCPP___CXX03_FLOAT_H
+
+/*
+ float.h synopsis
+
+Macros:
+
+ FLT_ROUNDS
+ FLT_EVAL_METHOD // C99
+ FLT_RADIX
+
+ FLT_MANT_DIG
+ DBL_MANT_DIG
+ LDBL_MANT_DIG
+
+ FLT_HAS_SUBNORM // C11
+ DBL_HAS_SUBNORM // C11
+ LDBL_HAS_SUBNORM // C11
+
+ DECIMAL_DIG // C99
+ FLT_DECIMAL_DIG // C11
+ DBL_DECIMAL_DIG // C11
+ LDBL_DECIMAL_DIG // C11
+
+ FLT_DIG
+ DBL_DIG
+ LDBL_DIG
+
+ FLT_MIN_EXP
+ DBL_MIN_EXP
+ LDBL_MIN_EXP
+
+ FLT_MIN_10_EXP
+ DBL_MIN_10_EXP
+ LDBL_MIN_10_EXP
+
+ FLT_MAX_EXP
+ DBL_MAX_EXP
+ LDBL_MAX_EXP
+
+ FLT_MAX_10_EXP
+ DBL_MAX_10_EXP
+ LDBL_MAX_10_EXP
+
+ FLT_MAX
+ DBL_MAX
+ LDBL_MAX
+
+ FLT_EPSILON
+ DBL_EPSILON
+ LDBL_EPSILON
+
+ FLT_MIN
+ DBL_MIN
+ LDBL_MIN
+
+ FLT_TRUE_MIN // C11
+ DBL_TRUE_MIN // C11
+ LDBL_TRUE_MIN // C11
+
+*/
+
+#include <__cxx03/__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#if __has_include_next(<float.h>)
+# include_next <float.h>
+#endif
+
+#ifdef __cplusplus
+
+# ifndef FLT_EVAL_METHOD
+# define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+# endif
+
+# ifndef DECIMAL_DIG
+# define DECIMAL_DIG __DECIMAL_DIG__
+# endif
+
+#endif // __cplusplus
+
+#endif // _LIBCPP___CXX03_FLOAT_H
diff --git a/libcxx/include/__float/characteristics.h b/libcxx/include/__float/characteristics.h
new file mode 100644
index 0000000000000..1e6469a72b61d
--- /dev/null
+++ b/libcxx/include/__float/characteristics.h
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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 _LIBCPP___FLOAT_CHARACTERISTICS_H
+#define _LIBCPP___FLOAT_CHARACTERISTICS_H
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+// Workround for https://github.com/llvm/llvm-project/issues/172800
+#define __need_next_float_after_libcpp
+#include <float.h>
+#undef __need_next_float_after_libcpp
+
+#ifndef FLT_EVAL_METHOD
+# define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+#endif
+
+#ifndef DECIMAL_DIG
+# define DECIMAL_DIG __DECIMAL_DIG__
+#endif
+
+#endif // _LIBCPP___FLOAT_CHARACTERISTICS_H
diff --git a/libcxx/include/__float/header_macro.h b/libcxx/include/__float/header_macro.h
new file mode 100644
index 0000000000000..0ca565d0d23d2
--- /dev/null
+++ b/libcxx/include/__float/header_macro.h
@@ -0,0 +1,19 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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 _LIBCPP_FLOAT_H
+#define _LIBCPP_FLOAT_H
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#endif // _LIBCPP_FLOAT_H
diff --git a/libcxx/include/float.h b/libcxx/include/float.h
index 9de29ec7392f3..3eccc4f019dd3 100644
--- a/libcxx/include/float.h
+++ b/libcxx/include/float.h
@@ -7,9 +7,6 @@
//
//===----------------------------------------------------------------------===//
-#ifndef _LIBCPP_FLOAT_H
-#define _LIBCPP_FLOAT_H
-
/*
float.h synopsis
@@ -71,29 +68,25 @@
*/
#if defined(__cplusplus) && __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
-# include <__cxx03/__config>
+# include <__cxx03/float.h>
#else
-# include <__config>
-#endif
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-# pragma GCC system_header
-#endif
-
-#if __has_include_next(<float.h>)
-# include_next <float.h>
-#endif
-
-#ifdef __cplusplus
-
-# ifndef FLT_EVAL_METHOD
-# define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
-# endif
-
-# ifndef DECIMAL_DIG
-# define DECIMAL_DIG __DECIMAL_DIG__
-# endif
-
-#endif // __cplusplus
-
-#endif // _LIBCPP_FLOAT_H
+# if (defined(__need_infinity_nan) || defined(__need_next_float_after_libcpp)) && __has_include_next(<float.h>)
+# include_next <float.h>
+# else
+# include <__float/header_macro.h>
+
+# include <__config>
+
+# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+# endif
+
+# if __has_include_next(<float.h>)
+# include_next <float.h>
+# endif
+
+# ifdef __cplusplus
+# include <__float/characteristics.h>
+# endif // __cplusplus
+# endif // defined(__need_infinity_nan) && __has_include_next(<float.h>)
+#endif // defined(__cplusplus) && __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 27178aa1f4378..ed9ec27d9aa55 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2429,8 +2429,9 @@ module std_fenv_h [system] {
export *
}
module std_float_h [system] {
- header "float.h"
- export *
+ textual header "float.h"
+ module characteristics { header "__float/characteristics.h" }
+ module header_macro { header "__float/header_macro.h" }
}
module std_inttypes_h [system] {
header "inttypes.h"
diff --git a/libcxx/test/extensions/clang/need_macros.verify.cpp b/libcxx/test/extensions/clang/need_macros.verify.cpp
new file mode 100644
index 0000000000000..a715355e48f49
--- /dev/null
+++ b/libcxx/test/extensions/clang/need_macros.verify.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// gcc supports "partitial inclusion" of some builtin headers via __need macros.
+// These are implemented in modules via textual headers, which are tricky to
+// support because libc++ needs to know about them and make its corresponding
+// headers textual too so that the macros are passed along.
+//
+// Another wrinkle is that __need macros can be used to force a type to be
+// when it wouldn't normally be. e.g. Apple platforms will use __need_rsize_t
+// to force the declaration of rsize_t to be visible even when
+// __STDC_WANT_LIB_EXT1__ isn't set.
+
+// gcc doesn't support all of the __need macros
+// UNSUPPORTED: gcc
+
+// The __need macros don't fully with in the frozen headers
+// UNSUPPORTED: c++03
+
+// Some of the __need macros are new in clang 22.x and Apple clang 21.x (there
+// isn't an Apple clang 18-20)
+// UNSUPPORTED: clang-20, clang-21, apple-clang-17
+
+// float.h doesn't always define INFINITY and NAN.
+#define __need_infinity_nan
+#include <float.h>
+constexpr float infinity = INFINITY;
+constexpr float nan = NAN;
+
+// Make sure that only the __need'ed interfaces are availbale. Note that the
+// C++ headers like <cstdarg> do -not- support partial inclusion, only the
+// "compatibility" headers.
+#define __need_va_list
+#include <stdarg.h>
+static void func(int param, ...) {
+ va_list args;
+ va_start(args, param); // expected-error {{use of undeclared identifier 'va_start'}}
+}
+
+// stddef.h doesn't always define max_align_t.
+#define __need_max_align_t
+#define __need_size_t
+#include <stddef.h>
+static_assert(alignof(max_align_t) >= alignof(long double), "");
diff --git a/libcxx/utils/generate_iwyu_mapping.py b/libcxx/utils/generate_iwyu_mapping.py
index ab3e3f14e14d8..e42947121fa15 100644
--- a/libcxx/utils/generate_iwyu_mapping.py
+++ b/libcxx/utils/generate_iwyu_mapping.py
@@ -25,6 +25,8 @@ def IWYU_mapping(header: str) -> typing.Optional[typing.List[str]]:
return ["bitset", "vector"]
elif re.match("__configuration/.+", header) or header == "__config":
return ["version"]
+ elif re.match("__float/.+", header):
+ return ["cfloat"]
elif header == "__hash_table":
return ["unordered_map", "unordered_set"]
elif header == "__locale":
>From 646771de6c3b99a3499bf8443f56c763bf711fdb Mon Sep 17 00:00:00 2001
From: Ian Anderson <iana at apple.com>
Date: Tue, 6 Jan 2026 14:28:41 -0800
Subject: [PATCH 2/3] Don't test the clang __need macro, always include all of
the libc++ float header, just split that into textual and non-textual
headers.
---
libcxx/include/CMakeLists.txt | 3 +-
libcxx/include/__float/characteristics.h | 32 -------------------
.../__float/{header_macro.h => float.h} | 17 ++++++++++
libcxx/include/float.h | 27 +++++++---------
libcxx/include/module.modulemap.in | 3 +-
.../extensions/clang/need_macros.verify.cpp | 6 ++--
6 files changed, 33 insertions(+), 55 deletions(-)
delete mode 100644 libcxx/include/__float/characteristics.h
rename libcxx/include/__float/{header_macro.h => float.h} (60%)
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 0d07a0d3a55e2..07f5c716eac74 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -382,8 +382,7 @@ set(files
__flat_set/flat_set.h
__flat_set/ra_iterator.h
__flat_set/utils.h
- __float/characteristics.h
- __float/header_macro.h
+ __float/float.h
__format/buffer.h
__format/concepts.h
__format/container_adaptor.h
diff --git a/libcxx/include/__float/characteristics.h b/libcxx/include/__float/characteristics.h
deleted file mode 100644
index 1e6469a72b61d..0000000000000
--- a/libcxx/include/__float/characteristics.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// 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 _LIBCPP___FLOAT_CHARACTERISTICS_H
-#define _LIBCPP___FLOAT_CHARACTERISTICS_H
-
-#include <__config>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-# pragma GCC system_header
-#endif
-
-// Workround for https://github.com/llvm/llvm-project/issues/172800
-#define __need_next_float_after_libcpp
-#include <float.h>
-#undef __need_next_float_after_libcpp
-
-#ifndef FLT_EVAL_METHOD
-# define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
-#endif
-
-#ifndef DECIMAL_DIG
-# define DECIMAL_DIG __DECIMAL_DIG__
-#endif
-
-#endif // _LIBCPP___FLOAT_CHARACTERISTICS_H
diff --git a/libcxx/include/__float/header_macro.h b/libcxx/include/__float/float.h
similarity index 60%
rename from libcxx/include/__float/header_macro.h
rename to libcxx/include/__float/float.h
index 0ca565d0d23d2..6140af80cfdeb 100644
--- a/libcxx/include/__float/header_macro.h
+++ b/libcxx/include/__float/float.h
@@ -16,4 +16,21 @@
# pragma GCC system_header
#endif
+#ifdef __cplusplus
+
+// Workround for https://github.com/llvm/llvm-project/issues/172800
+# define __need_next_float_after_libcpp
+# include <float.h>
+# undef __need_next_float_after_libcpp
+
+# ifndef FLT_EVAL_METHOD
+# define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+# endif
+
+# ifndef DECIMAL_DIG
+# define DECIMAL_DIG __DECIMAL_DIG__
+# endif
+
+#endif // __cplusplus
+
#endif // _LIBCPP_FLOAT_H
diff --git a/libcxx/include/float.h b/libcxx/include/float.h
index 3eccc4f019dd3..17d85497bf44e 100644
--- a/libcxx/include/float.h
+++ b/libcxx/include/float.h
@@ -70,23 +70,18 @@
#if defined(__cplusplus) && __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
# include <__cxx03/float.h>
#else
-# if (defined(__need_infinity_nan) || defined(__need_next_float_after_libcpp)) && __has_include_next(<float.h>)
-# include_next <float.h>
-# else
-# include <__float/header_macro.h>
+# include <__config>
-# include <__config>
+# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+# endif
-# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-# pragma GCC system_header
-# endif
+# if __has_include_next(<float.h>)
+# include_next <float.h>
+# endif
-# if __has_include_next(<float.h>)
-# include_next <float.h>
-# endif
+# ifndef __need_next_float_after_libcpp
+# include <__float/float.h>
+# endif
-# ifdef __cplusplus
-# include <__float/characteristics.h>
-# endif // __cplusplus
-# endif // defined(__need_infinity_nan) && __has_include_next(<float.h>)
-#endif // defined(__cplusplus) && __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+#endif // defined(__cplusplus) && __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index ed9ec27d9aa55..a19cc73789af2 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2430,8 +2430,7 @@ module std_fenv_h [system] {
}
module std_float_h [system] {
textual header "float.h"
- module characteristics { header "__float/characteristics.h" }
- module header_macro { header "__float/header_macro.h" }
+ module float { header "__float/float.h" }
}
module std_inttypes_h [system] {
header "inttypes.h"
diff --git a/libcxx/test/extensions/clang/need_macros.verify.cpp b/libcxx/test/extensions/clang/need_macros.verify.cpp
index a715355e48f49..227de5a6a0547 100644
--- a/libcxx/test/extensions/clang/need_macros.verify.cpp
+++ b/libcxx/test/extensions/clang/need_macros.verify.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// gcc supports "partitial inclusion" of some builtin headers via __need macros.
+// gcc supports "partial inclusion" of some builtin headers via __need macros.
// These are implemented in modules via textual headers, which are tricky to
// support because libc++ needs to know about them and make its corresponding
// headers textual too so that the macros are passed along.
@@ -19,8 +19,8 @@
// gcc doesn't support all of the __need macros
// UNSUPPORTED: gcc
-// The __need macros don't fully with in the frozen headers
-// UNSUPPORTED: c++03
+// The frozen C++03 headers don't support the __need macros tested here.
+// XFAIL: FROZEN-CXX03-HEADERS-FIXME
// Some of the __need macros are new in clang 22.x and Apple clang 21.x (there
// isn't an Apple clang 18-20)
>From 9ce8c563e86d114c111fb7805c95e4a64cb589ac Mon Sep 17 00:00:00 2001
From: Ian Anderson <iana at apple.com>
Date: Tue, 16 Dec 2025 17:18:08 -0800
Subject: [PATCH 3/3] Disable clang-22 on the new test
Probably the clang-22 on the builders isn't new enough that is has the new version of float.h
---
libcxx/test/extensions/clang/need_macros.verify.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/test/extensions/clang/need_macros.verify.cpp b/libcxx/test/extensions/clang/need_macros.verify.cpp
index 227de5a6a0547..d9e7f7899aa4b 100644
--- a/libcxx/test/extensions/clang/need_macros.verify.cpp
+++ b/libcxx/test/extensions/clang/need_macros.verify.cpp
@@ -24,7 +24,7 @@
// Some of the __need macros are new in clang 22.x and Apple clang 21.x (there
// isn't an Apple clang 18-20)
-// UNSUPPORTED: clang-20, clang-21, apple-clang-17
+// UNSUPPORTED: clang-20, clang-21, clang-22, apple-clang-17
// float.h doesn't always define INFINITY and NAN.
#define __need_infinity_nan
More information about the libcxx-commits
mailing list