[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:08:57 PST 2025


https://github.com/ian-twilightcoder updated https://github.com/llvm/llvm-project/pull/172539

>From 82c7a3130eba692b9118ea6fb3279efdfe1e6a3e 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                 |  2 +
 libcxx/include/__float/characteristics.h      | 27 +++++++++++
 libcxx/include/__float/header_macro.h         | 19 ++++++++
 libcxx/include/float.h                        | 39 +++++++--------
 libcxx/include/module.modulemap.in            |  5 +-
 .../extensions/clang/need_macros.verify.cpp   | 48 +++++++++++++++++++
 libcxx/utils/generate_iwyu_mapping.py         |  2 +
 7 files changed, 117 insertions(+), 25 deletions(-)
 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..71c5c4786b1c9 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
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..db1255ecab417 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
 
@@ -70,30 +67,26 @@
 
 */
 
-#if defined(__cplusplus) && __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
-#  include <__cxx03/__config>
-#else
-#  include <__config>
-#endif
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#  pragma GCC system_header
-#endif
-
-#if __has_include_next(<float.h>)
+#if defined(__need_infinity_nan) && __has_include_next(<float.h>)
 #  include_next <float.h>
-#endif
-
-#ifdef __cplusplus
+#else
+#  include <__float/header_macro.h>
 
-#  ifndef FLT_EVAL_METHOD
-#    define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+#  if defined(__cplusplus) && __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+#    include <__cxx03/__config>
+#  else
+#    include <__config>
 #  endif
 
-#  ifndef DECIMAL_DIG
-#    define DECIMAL_DIG __DECIMAL_DIG__
+#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#    pragma GCC system_header
 #  endif
 
-#endif // __cplusplus
+#  if __has_include_next(<float.h>)
+#    include_next <float.h>
+#  endif
 
-#endif // _LIBCPP_FLOAT_H
+#  ifdef __cplusplus
+#    include <__float/characteristics.h>
+#  endif // __cplusplus
+#endif   // __need_infinity_nan
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 44062260d14a8d3d5ea97e90b7d3f58e693ce653 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