[libcxx-commits] [libcxx] [libc++] __need_infinity_nan doesn't work in non-gnu c++ standards (PR #175849)
Ian Anderson via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jan 13 13:50:17 PST 2026
https://github.com/ian-twilightcoder created https://github.com/llvm/llvm-project/pull/175849
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 it can't have any declarations, but the ones it has are unnecessary because clang's float.h already defines FLT_EVAL_METHOD and DECIMAL_DIG.
>From 6b2f190b0bbba6f313d55e551a4d19dee93110fd 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 it can't have any declarations, but the ones it has are unnecessary because clang's float.h already defines FLT_EVAL_METHOD and DECIMAL_DIG.
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__cxx03/cfloat | 4 +-
libcxx/include/__cxx03/float.h | 95 +++++++++++++++++++
libcxx/include/float.h | 28 ++----
libcxx/include/module.modulemap.in | 3 +-
.../extensions/clang/need_macros.verify.cpp | 49 ++++++++++
6 files changed, 154 insertions(+), 26 deletions(-)
create mode 100644 libcxx/include/__cxx03/float.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 2ccc766f8109b..97d6c51f3913a 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -1622,6 +1622,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.h b/libcxx/include/float.h
index 9de29ec7392f3..5a43a48f9d8ef 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,16 @@
*/
#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__
+# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
# endif
-# ifndef DECIMAL_DIG
-# define DECIMAL_DIG __DECIMAL_DIG__
+# if __has_include_next(<float.h>)
+# include_next <float.h>
# endif
-#endif // __cplusplus
-
-#endif // _LIBCPP_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 cbe1e221844f8..57f018cbcdcd5 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2429,8 +2429,7 @@ module std_fenv_h [system] {
export *
}
module std_float_h [system] {
- header "float.h"
- export *
+ textual header "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
new file mode 100644
index 0000000000000..227de5a6a0547
--- /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 "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.
+//
+// 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 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)
+// 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), "");
>From 7e89b3cc88dd6dd6885a7d200704403fc07f2bb4 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 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