[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 Dec 16 21:43:42 PST 2025
https://github.com/ian-twilightcoder updated https://github.com/llvm/llvm-project/pull/172539
>From c6a969a0e9652d2e134f3639c6f193002a06ab26 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/2] [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/float.h | 95 +++++++++++++++++++
libcxx/include/__float/characteristics.h | 27 ++++++
libcxx/include/__float/header_macro.h | 19 ++++
libcxx/include/float.h | 49 ++++------
libcxx/include/module.modulemap.in | 5 +-
.../extensions/clang/need_macros.verify.cpp | 48 ++++++++++
libcxx/utils/generate_iwyu_mapping.py | 2 +
8 files changed, 218 insertions(+), 30 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 53ca1f7d3ded2..239f73918be16 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -380,6 +380,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
@@ -1618,6 +1620,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/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..a91bec2f1f4d0
--- /dev/null
+++ b/libcxx/include/__float/characteristics.h
@@ -0,0 +1,27 @@
+// -*- 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
+
+#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..c31eac4dfe11f 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) && __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 04be734e37384..d099b3e8b638e 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2425,8 +2425,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..382b0c7321217
--- /dev/null
+++ b/libcxx/test/extensions/clang/need_macros.verify.cpp
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// UNSUPPORTED: clang-21, apple-clang-20
+
+// 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 c204959ec0e31a3d440c70a885c45e6364e2a626 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 2/2] 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 382b0c7321217..80f0fdaee6937 100644
--- a/libcxx/test/extensions/clang/need_macros.verify.cpp
+++ b/libcxx/test/extensions/clang/need_macros.verify.cpp
@@ -23,7 +23,7 @@
// UNSUPPORTED: c++03
// Some of the __need macros are new in clang 22.x and Apple clang 21.x
-// UNSUPPORTED: clang-21, apple-clang-20
+// UNSUPPORTED: clang-21, clang-22, apple-clang-20
// float.h doesn't always define INFINITY and NAN.
#define __need_infinity_nan
More information about the libcxx-commits
mailing list