[PATCH v4] math.h: Do not use __MATH_TG_BUILTIN_CLASSIFY for C++

Jonathan Wakely jwakely@redhat.com
Tue Jan 13 09:17:09 GMT 2026


On Wed, 07 Jan 2026 at 15:42 -0300, Adhemerval Zanella wrote:
>The __MATH_TG_BUILTIN_CLASSIFY macro can not be used in C++ mode because
>it might use __builtin_types_compatible_p, which is a C-only builtin.
>
>C++ code might use the math.h definitions in two different ways: either
>by including cmath or math.h.

No, those are the same way, there's only one way.

> For the former, the C++ library will
>usually disable and override math.h definitions,

To be more accurate, we undef macros (like fpclassify) and replace
them with functions.

We do use the non-macro functions (with additional overloads that we
add ourselves).

> and it usually expects
>fpclassify/isinf to be implemented as macros.  And switching to functions
>with overloaded arguments might break the libstdc++ bootstrap.

Yes, the C standard says they're macros and libstdc++ expects that to
be true.

>For the latter, we still need to provide an implementation, and the

Why? Libstdc++ math.h includes <cmath> so is exactly the same as the
former case.

Wouldn't it make sense to actually discuss this with libstdc++
maintainers instead of guessing what is desirable?

Libstdc++ does #undef fpclassify and #undef isinf etc so there's no
point defining them for C++ at all IMHO. But defining them as macros
should be harmless, because we'll just #undef them. As long as they're
not functions, we shouldn't care what your macros do.

>built-in is the straightforward one (as previously done before
>__MATH_TG_BUILTIN_CLASSIFY introduction).
>
>Checked with bmg targeting x86_64-linux-gnu and on x86_64-linux-gnu and
>aarch64 with gcc-15 and clang-18.
>--
>Changes from v3:
>* Only use __builtin if compiler supports it.
>Changes from v2:
>* Make test-builtin-denormal-cxx.cc xfail.
>* Fixed commit title.
>---
> include/array_length.h                       |   4 +
> math/Makefile                                |   4 +
> math/math.h                                  |  39 +++--
> math/test-math-fpclassify.cc                 | 149 +++++++++++++++++++
> math/test-math-isinf.cc                      | 145 ++++++++++++++++++
> scripts/sysd-rules.awk                       |  28 +++-
> sysdeps/x86/fpu/Makefile                     |   5 +
> sysdeps/x86/fpu/test-builtin-denormal-cxx.cc |   1 +
> sysdeps/x86/fpu/test-builtin-denormal.c      |  10 +-
> 9 files changed, 365 insertions(+), 20 deletions(-)
> create mode 100644 math/test-math-fpclassify.cc
> create mode 100644 math/test-math-isinf.cc
> create mode 100644 sysdeps/x86/fpu/test-builtin-denormal-cxx.cc
>
>diff --git a/include/array_length.h b/include/array_length.h
>index c37c1696dd..f7c2286d24 100644
>--- a/include/array_length.h
>+++ b/include/array_length.h
>@@ -21,6 +21,9 @@
>
> /* array_length (VAR) is the number of elements in the array VAR.  VAR
>    must evaluate to an array, not a pointer.  */
>+#ifdef __cplusplus
>+#define array_length(var) (sizeof (var) / sizeof ((var)[0]))

I would do that like this in C++:

template<typename T, size_t N>
__attribute__((__always_inline__)) inline size_t
array_length (const T (&)[N])
{ return N; }

>+#else
> #define array_length(var)                                               \
>   (sizeof (var) / sizeof ((var)[0])                                     \
>    + 0 * sizeof (struct {                                               \
>@@ -28,6 +31,7 @@
>                        (__typeof (var), __typeof (&(var)[0])),          \
>                        "argument must be an array");                    \
>    }))
>+#endif
>
> /* array_end (VAR) is a pointer one past the end of the array VAR.
>    VAR must evaluate to an array, not a pointer.  */
>diff --git a/math/Makefile b/math/Makefile
>index 69f80e143f..c9bcdfc1f6 100644
>--- a/math/Makefile
>+++ b/math/Makefile
>@@ -620,8 +620,10 @@ tests-static += \
> ifneq (,$(CXX))
> tests += \
>   test-math-cxx11 \
>+  test-math-fpclassify \
>   test-math-iscanonical \
>   test-math-iseqsig \
>+  test-math-isinf \
>   test-math-isinff \
>   test-math-issignaling \
>   test-math-iszero \
>@@ -1151,10 +1153,12 @@ CFLAGS-test-signgam-ullong-init-static.c += -std=c99
>
> CFLAGS-test-math-cxx11.cc += -std=c++11
>
>+CFLAGS-test-math-isinf.cc += -std=gnu++11
> CFLAGS-test-math-isinff.cc += -std=gnu++11
> CFLAGS-test-math-iszero.cc += -std=gnu++11
> CFLAGS-test-math-issignaling.cc += -std=gnu++11
> CFLAGS-test-math-iscanonical.cc += -std=gnu++11
>+CFLAGS-test-math-fpclassify.cc += -std=gnu++11
>
> CFLAGS-test-iszero-excess-precision.c += -fexcess-precision=standard
> CFLAGS-test-iseqsig-excess-precision.c += -fexcess-precision=standard
>diff --git a/math/math.h b/math/math.h
>index 1066113ca6..d98120eb1a 100644
>--- a/math/math.h
>+++ b/math/math.h
>@@ -1175,19 +1175,20 @@ enum
> # if ((__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__)		      \
>       || __glibc_clang_prereq (2,8))					      \
>      && (!defined __OPTIMIZE_SIZE__ || defined __cplusplus)
>-     /* The check for __cplusplus allows the use of the builtin, even
>-	when optimization for size is on.  This is provided for
>-	libstdc++, only to let its configure test work when it is built
>-	with -Os.  No further use of this definition of fpclassify is
>-	expected in C++ mode, since libstdc++ provides its own version
>-	of fpclassify in cmath (which undefines fpclassify).  */
>-#  define fpclassify(x)							      \
>-  __MATH_TG_BUILTIN_CLASSIFY ((x),					      \
>-			      __builtin_fpclassify, (FP_NAN, FP_INFINITE,     \
>-						     FP_NORMAL, FP_SUBNORMAL, \
>-						     FP_ZERO, x),	      \
>-			      fpclassify, (x),				      \
>-			      __FP_BUILTIN_FPCLASSIFY_DENORMAL)
>+/* The __MATH_TG_BUILTIN_CLASSIFY macro can not be used in C++ mode because
>+   it might use __builtin_types_compatible_p, which is C-only builtin.  */
>+#  ifndef __cplusplus
>+#   define fpclassify(x)                                                      \
>+  __MATH_TG_BUILTIN_CLASSIFY ((x),                                            \
>+                              __builtin_fpclassify, (FP_NAN, FP_INFINITE,     \
>+                                                     FP_NORMAL, FP_SUBNORMAL, \
>+                                                     FP_ZERO, x),             \
>+                              fpclassify, (x),                                \
>+                              __FP_BUILTIN_FPCLASSIFY_DENORMAL)
>+#  else
>+#   define fpclassify(x) __builtin_fpclassify (FP_NAN, FP_INFINITE, FP_NORMAL,\
>+					      FP_SUBNORMAL, FP_ZERO, x)
>+#  endif
> # else
> #  define fpclassify(x) __MATH_TG ((x), __fpclassify, (x))
> # endif
>@@ -1247,12 +1248,18 @@ enum
> #  define isinf(x) \
>     (__builtin_types_compatible_p (__typeof (x), _Float128) \
>      ? __isinff128 (x) : __builtin_isinf_sign (x))
>-# elif (__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \
>-       || __glibc_clang_prereq (3,7)
>-#  define isinf(x) __MATH_TG_BUILTIN_CLASSIFY ((x),			      \
>+  /* The __MATH_TG_BUILTIN_CLASSIFY macro can not be used in C++ mode because
>+     it might use __builtin_types_compatible_p, which is C-only builtin.  */
>+# elif ((__GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__) \
>+        || __glibc_clang_prereq (3,7))
>+#  ifndef __cplusplus
>+#   define isinf(x) __MATH_TG_BUILTIN_CLASSIFY ((x),			      \
> 					       __builtin_isinf_sign, (x),     \
> 					       isinf, (x),		      \
> 					       __FP_BUILTIN_ISINF_SIGN_DENORMAL)
>+#  else
>+#   define isinf(x) __builtin_isinf_sign (x)
>+#  endif
> # else
> #  define isinf(x) __MATH_TG ((x), __isinf, (x))
> # endif
>diff --git a/math/test-math-fpclassify.cc b/math/test-math-fpclassify.cc
>new file mode 100644
>index 0000000000..f8dbf4fe7d
>--- /dev/null
>+++ b/math/test-math-fpclassify.cc
>@@ -0,0 +1,149 @@
>+/* Test for the C++ implementation of fpclassify.
>+   Copyright (C) 2025 Free Software Foundation, Inc.
>+   This file is part of the GNU C Library.
>+
>+   The GNU C Library is free software; you can redistribute it and/or
>+   modify it under the terms of the GNU Lesser General Public
>+   License as published by the Free Software Foundation; either
>+   version 2.1 of the License, or (at your option) any later version.
>+
>+   The GNU C Library is distributed in the hope that it will be useful,
>+   but WITHOUT ANY WARRANTY; without even the implied warranty of
>+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>+   Lesser General Public License for more details.
>+
>+   You should have received a copy of the GNU Lesser General Public
>+   License along with the GNU C Library; if not, see
>+   <https://www.gnu.org/licenses/>.  */
>+
>+#define _GNU_SOURCE 1
>+#include <math.h>
>+#include <stdio.h>
>+#include <limits>
>+
>+#include <support/check.h>
>+
>+/* Support for _Float128 in std::numeric_limits is limited.

Is it? Which GCC version are you looking at?

>+   Include ieee754_float128.h and use the bitfields in the union
>+   ieee854_float128.ieee_nan to build corner-case inputs.  */
>+#if __HAVE_DISTINCT_FLOAT128
>+# include <ieee754_float128.h>
>+#endif
>+
>+template <class T>
>+static void
>+check_type ()
>+{
>+  typedef std::numeric_limits<T> limits;
>+  TEST_COMPARE (fpclassify (T{}), FP_ZERO);
>+  TEST_COMPARE (fpclassify (T{0}), FP_ZERO);
>+  TEST_COMPARE (fpclassify (T{-0.0}), FP_ZERO);
>+  TEST_COMPARE (fpclassify (T{1}), FP_NORMAL);
>+  TEST_COMPARE (fpclassify (T{-1}), FP_NORMAL);
>+  TEST_COMPARE (fpclassify (limits::min ()), FP_NORMAL);
>+  TEST_COMPARE (fpclassify (-limits::min ()), FP_NORMAL);
>+  TEST_COMPARE (fpclassify (limits::max ()), FP_NORMAL);
>+  TEST_COMPARE (fpclassify (-limits::max ()), FP_NORMAL);
>+  if (limits::has_infinity)
>+    {
>+      TEST_COMPARE (fpclassify (limits::infinity ()), FP_INFINITE);
>+      TEST_COMPARE (fpclassify (-limits::infinity ()), FP_INFINITE);
>+    }
>+  TEST_COMPARE (fpclassify (limits::epsilon ()), FP_NORMAL);
>+  TEST_COMPARE (fpclassify (-limits::epsilon ()), FP_NORMAL);
>+  if (limits::has_quiet_NaN)
>+    TEST_COMPARE (fpclassify (limits::quiet_NaN ()), FP_NAN);
>+  if (limits::has_signaling_NaN)
>+    TEST_COMPARE (fpclassify (limits::signaling_NaN ()), FP_NAN);
>+  if (limits::has_signaling_NaN)
>+    TEST_COMPARE (fpclassify (limits::signaling_NaN ()), FP_NAN);
>+  TEST_COMPARE (fpclassify (limits::denorm_min ()),
>+		std::numeric_limits<T>::has_denorm == std::denorm_absent
>+		? FP_NORMAL : FP_SUBNORMAL);
>+  TEST_COMPARE (fpclassify (-limits::denorm_min ()),
>+		std::numeric_limits<T>::has_denorm == std::denorm_absent
>+		? FP_NORMAL : FP_SUBNORMAL);
>+}
>+
>+#if __HAVE_DISTINCT_FLOAT128
>+static void
>+check_float128 ()
>+{
>+  ieee854_float128 q;
>+
>+  q.d = 0.0Q;
>+  TEST_COMPARE (fpclassify (q.d), FP_ZERO);
>+  q.d = -0.0Q;
>+  TEST_COMPARE (fpclassify (q.d), FP_ZERO);
>+  q.d = 1.0Q;
>+  TEST_COMPARE (fpclassify (q.d), FP_NORMAL);
>+  q.d = -1.0Q;
>+  TEST_COMPARE (fpclassify (q.d), FP_NORMAL);
>+
>+  /* Normal min.  */
>+  q.ieee.negative = 0;
>+  q.ieee.exponent = 0x0001;
>+  q.ieee.mantissa0 = 0x0000;
>+  q.ieee.mantissa1 = 0x00000000;
>+  q.ieee.mantissa2 = 0x00000000;
>+  q.ieee.mantissa3 = 0x00000000;
>+  TEST_COMPARE (fpclassify (q.d), FP_NORMAL);
>+  q.ieee.negative = 1;
>+  TEST_COMPARE (fpclassify (q.d), FP_NORMAL);
>+
>+  /* Normal max.  */
>+  q.ieee.negative = 0;
>+  q.ieee.exponent = 0x7FFE;
>+  q.ieee.mantissa0 = 0xFFFF;
>+  q.ieee.mantissa1 = 0xFFFFFFFF;
>+  q.ieee.mantissa2 = 0xFFFFFFFF;
>+  q.ieee.mantissa3 = 0xFFFFFFFF;
>+  TEST_COMPARE (fpclassify (q.d), FP_NORMAL);
>+  q.ieee.negative = 1;
>+  TEST_COMPARE (fpclassify (q.d), FP_NORMAL);
>+
>+  /* Infinity.  */
>+  q.ieee.negative = 0;
>+  q.ieee.exponent = 0x7FFF;
>+  q.ieee.mantissa0 = 0x0000;
>+  q.ieee.mantissa1 = 0x00000000;
>+  q.ieee.mantissa2 = 0x00000000;
>+  q.ieee.mantissa3 = 0x00000000;
>+  TEST_COMPARE (fpclassify (q.d), FP_INFINITE);
>+
>+  /* Quiet NaN.  */
>+  q.ieee_nan.quiet_nan = 1;
>+  q.ieee_nan.mantissa0 = 0x0000;
>+  TEST_COMPARE (fpclassify (q.d), FP_NAN);
>+
>+  /* Signaling NaN.  */
>+  q.ieee_nan.quiet_nan = 0;
>+  q.ieee_nan.mantissa0 = 0x4000;
>+  TEST_COMPARE (fpclassify (q.d), FP_NAN);
>+
>+  /* Denormal min.  */
>+  q.ieee.negative = 0;
>+  q.ieee.exponent = 0x0000;
>+  q.ieee.mantissa0 = 0x0000;
>+  q.ieee.mantissa1 = 0x00000000;
>+  q.ieee.mantissa2 = 0x00000000;
>+  q.ieee.mantissa3 = 0x00000001;
>+  TEST_COMPARE (fpclassify (q.d), FP_SUBNORMAL);
>+  q.ieee.negative = 1;
>+  TEST_COMPARE (fpclassify (q.d), FP_SUBNORMAL);
>+}
>+#endif
>+
>+static int
>+do_test (void)
>+{
>+  check_type<float> ();
>+  check_type<double> ();
>+  check_type<long double> ();
>+#if __HAVE_DISTINCT_FLOAT128
>+  check_float128 ();
>+#endif
>+  return 0;
>+}
>+
>+#include <support/test-driver.c>
>diff --git a/math/test-math-isinf.cc b/math/test-math-isinf.cc
>new file mode 100644
>index 0000000000..4cdc146583
>--- /dev/null
>+++ b/math/test-math-isinf.cc
>@@ -0,0 +1,145 @@
>+/* Test for the C++ implementation of isinf.
>+   Copyright (C) 2025 Free Software Foundation, Inc.
>+   This file is part of the GNU C Library.
>+
>+   The GNU C Library is free software; you can redistribute it and/or
>+   modify it under the terms of the GNU Lesser General Public
>+   License as published by the Free Software Foundation; either
>+   version 2.1 of the License, or (at your option) any later version.
>+
>+   The GNU C Library is distributed in the hope that it will be useful,
>+   but WITHOUT ANY WARRANTY; without even the implied warranty of
>+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>+   Lesser General Public License for more details.
>+
>+   You should have received a copy of the GNU Lesser General Public
>+   License along with the GNU C Library; if not, see
>+   <https://www.gnu.org/licenses/>.  */
>+
>+#define _GNU_SOURCE 1
>+#include <math.h>
>+#include <stdio.h>
>+#include <limits>
>+
>+#include <support/check.h>
>+
>+/* Support for _Float128 in std::numeric_limits is limited.
>+   Include ieee754_float128.h and use the bitfields in the union
>+   ieee854_float128.ieee_nan to build corner-case inputs.  */
>+#if __HAVE_DISTINCT_FLOAT128
>+# include <ieee754_float128.h>
>+#endif
>+
>+template <class T>
>+static void
>+check_type ()
>+{
>+  typedef std::numeric_limits<T> limits;
>+  TEST_COMPARE (isinf (T{}), 0);
>+  TEST_COMPARE (isinf (T{0}), 0);
>+  TEST_COMPARE (isinf (T{-0.0}), 0);
>+  TEST_COMPARE (isinf (T{1}), 0);
>+  TEST_COMPARE (isinf (T{-1}), 0);
>+  TEST_COMPARE (isinf (limits::min ()), 0);
>+  TEST_COMPARE (isinf (-limits::min ()), 0);
>+  TEST_COMPARE (isinf (limits::max ()), 0);
>+  TEST_COMPARE (isinf (-limits::max ()), 0);
>+  if (limits::has_infinity)
>+    {
>+      TEST_COMPARE (isinf (limits::infinity ()), 1);
>+      TEST_COMPARE (isinf (-limits::infinity ()), -1);
>+    }
>+  TEST_COMPARE (isinf (limits::epsilon ()), 0);
>+  TEST_COMPARE (isinf (-limits::epsilon ()), 0);
>+  if (limits::has_quiet_NaN)
>+    TEST_COMPARE (isinf (limits::quiet_NaN ()), 0);
>+  if (limits::has_signaling_NaN)
>+    TEST_COMPARE (isinf (limits::signaling_NaN ()), 0);
>+  if (limits::has_signaling_NaN)
>+    TEST_COMPARE (isinf (limits::signaling_NaN ()), 0);
>+  TEST_COMPARE (isinf (limits::denorm_min ()), 0);
>+  TEST_COMPARE (isinf (-limits::denorm_min ()), 0);
>+}
>+
>+#if __HAVE_DISTINCT_FLOAT128
>+static void
>+check_float128 ()
>+{
>+  ieee854_float128 q;
>+
>+  q.d = 0.0Q;
>+  TEST_COMPARE (isinf (q.d), 0);
>+  q.d = -0.0Q;
>+  TEST_COMPARE (isinf (q.d), 0);
>+  q.d = 1.0Q;
>+  TEST_COMPARE (isinf (q.d), 0);
>+  q.d = -1.0Q;
>+  TEST_COMPARE (isinf (q.d), 0);
>+
>+  /* Normal min.  */
>+  q.ieee.negative = 0;
>+  q.ieee.exponent = 0x0001;
>+  q.ieee.mantissa0 = 0x0000;
>+  q.ieee.mantissa1 = 0x00000000;
>+  q.ieee.mantissa2 = 0x00000000;
>+  q.ieee.mantissa3 = 0x00000000;
>+  TEST_COMPARE (isinf (q.d), 0);
>+  q.ieee.negative = 1;
>+  TEST_COMPARE (isinf (q.d), 0);
>+
>+  /* Normal max.  */
>+  q.ieee.negative = 0;
>+  q.ieee.exponent = 0x7FFE;
>+  q.ieee.mantissa0 = 0xFFFF;
>+  q.ieee.mantissa1 = 0xFFFFFFFF;
>+  q.ieee.mantissa2 = 0xFFFFFFFF;
>+  q.ieee.mantissa3 = 0xFFFFFFFF;
>+  TEST_COMPARE (isinf (q.d), 0);
>+  q.ieee.negative = 1;
>+  TEST_COMPARE (isinf (q.d), 0);
>+
>+  /* Infinity.  */
>+  q.ieee.negative = 0;
>+  q.ieee.exponent = 0x7FFF;
>+  q.ieee.mantissa0 = 0x0000;
>+  q.ieee.mantissa1 = 0x00000000;
>+  q.ieee.mantissa2 = 0x00000000;
>+  q.ieee.mantissa3 = 0x00000000;
>+  TEST_COMPARE (isinf (q.d), 1);
>+
>+  /* Quiet NaN.  */
>+  q.ieee_nan.quiet_nan = 1;
>+  q.ieee_nan.mantissa0 = 0x0000;
>+  TEST_COMPARE (isinf (q.d), 0);
>+
>+  /* Signaling NaN.  */
>+  q.ieee_nan.quiet_nan = 0;
>+  q.ieee_nan.mantissa0 = 0x4000;
>+  TEST_COMPARE (isinf (q.d), 0);
>+
>+  /* Denormal min.  */
>+  q.ieee.negative = 0;
>+  q.ieee.exponent = 0x0000;
>+  q.ieee.mantissa0 = 0x0000;
>+  q.ieee.mantissa1 = 0x00000000;
>+  q.ieee.mantissa2 = 0x00000000;
>+  q.ieee.mantissa3 = 0x00000001;
>+  TEST_COMPARE (isinf (q.d), 0);
>+  q.ieee.negative = 1;
>+  TEST_COMPARE (isinf (q.d), 0);
>+}
>+#endif
>+
>+static int
>+do_test (void)
>+{
>+  check_type<float> ();
>+  check_type<double> ();
>+  check_type<long double> ();
>+#if __HAVE_DISTINCT_FLOAT128
>+  check_float128 ();
>+#endif
>+  return 0;
>+}
>+
>+#include <support/test-driver.c>
>diff --git a/scripts/sysd-rules.awk b/scripts/sysd-rules.awk
>index c82e8fd607..cdc892b397 100644
>--- a/scripts/sysd-rules.awk
>+++ b/scripts/sysd-rules.awk
>@@ -35,6 +35,7 @@ BEGIN {
>
>   for (sysdir_idx = 1; sysdir_idx <= nsysdirs; ++sysdir_idx) {
>     dir = sysdirs[sysdir_idx];
>+    sysdep_dir = dir
>     if (dir !~ /^\//) dir = "$(..)" dir;
>     asm_rules = 1;
>     for (i = 1; i <= ninhibit_asm; ++i) {
>@@ -43,6 +44,20 @@ BEGIN {
>         break;
>       }
>     }
>+    # Check if there are any *.S files.
>+    if (asm_rules == 1 && system("ls " sysdep_dir "/*.S > /dev/null 2>&1") != 0) {
>+      asm_rules = 0;
>+    }
>+    # Check if there are any *.c files.
>+    c_rules = 1
>+    if (system("ls " sysdep_dir "/*.c > /dev/null 2>&1") != 0) {
>+      c_rules = 0;
>+    }
>+    # Check if there are any *.cc files.
>+    cc_rules = 1
>+    if (system("ls " sysdep_dir "/*.cc > /dev/null 2>&1") != 0) {
>+      cc_rules = 0;
>+    }
>     for (suffix_idx = 1; suffix_idx <= nsuffixes; ++suffix_idx) {
>       o = suffixes[suffix_idx];
>       for (pattern_idx = 1; pattern_idx <= npatterns; ++pattern_idx) {
>@@ -66,9 +81,16 @@ BEGIN {
>           print target, dep, "$(before-compile)";
>           print "\t$(compile-command.S)" command_suffix;
>         }
>-        dep = dir "/" dep_pattern ".c";
>-        print target, dep, "$(before-compile)";
>-        print "\t$(compile-command.c)" command_suffix;
>+        if (c_rules) {
>+          dep = dir "/" dep_pattern ".c";
>+          print target, dep, "$(before-compile)";
>+          print "\t$(compile-command.c)" command_suffix;
>+	}
>+        if (cc_rules) {
>+          dep = dir "/" dep_pattern ".cc";
>+          print target, dep, "$(before-compile)";
>+          print "\t$(compile-command.cc)" command_suffix;
>+	}
>       }
>     }
>     print "$(inst_includedir)/%.h:", dir "/%.h", "$(+force)";
>diff --git a/sysdeps/x86/fpu/Makefile b/sysdeps/x86/fpu/Makefile
>index 8566d3c80f..cb0879dd5f 100644
>--- a/sysdeps/x86/fpu/Makefile
>+++ b/sysdeps/x86/fpu/Makefile
>@@ -11,6 +11,11 @@ tests += \
>   test-fenv-x87 \
>   test-flt-eval-method-sse \
> # tests
>+ifneq (,$(CXX))
>+tests += \
>+  test-builtin-denormal-cxx \
>+# tests
>+endif
> ifeq ($(have-test-cc-cflags-mfpmath-387),yes)
> tests += test-flt-eval-method-387
> endif
>diff --git a/sysdeps/x86/fpu/test-builtin-denormal-cxx.cc b/sysdeps/x86/fpu/test-builtin-denormal-cxx.cc
>new file mode 100644
>index 0000000000..0b7e8e8728
>--- /dev/null
>+++ b/sysdeps/x86/fpu/test-builtin-denormal-cxx.cc
>@@ -0,0 +1 @@
>+#include "test-builtin-denormal.c"
>diff --git a/sysdeps/x86/fpu/test-builtin-denormal.c b/sysdeps/x86/fpu/test-builtin-denormal.c
>index 8856ebce80..27a8305983 100644
>--- a/sysdeps/x86/fpu/test-builtin-denormal.c
>+++ b/sysdeps/x86/fpu/test-builtin-denormal.c
>@@ -40,15 +40,23 @@ static const ieee_long_double_shape_type inputs[] = {
> static int
> do_test (void)
> {
>-  for (int i = 0; i < array_length (inputs); i++)
>+  for (unsigned int i = 0; i < array_length (inputs); i++)
>     {
>       TEST_COMPARE (feclearexcept (FE_INVALID), 0);
>       TEST_COMPARE (fpclassify (inputs[i].value), FP_NAN);
>+#ifndef __cplusplus
>+      /* C++ uses the builtin, which does not trigger FE_INVALID for
>+	 pseudo-numbers (GCC BZ 123161 and LLVM issue 172533.  */
>       TEST_COMPARE (fetestexcept (FE_INVALID), 0);
>+#endif
>
>       TEST_COMPARE (feclearexcept (FE_INVALID), 0);
>       TEST_COMPARE (isinf (inputs[i].value), 0);
>+#ifndef __cplusplus
>+      /* C++ uses the builtin, which does not trigger FE_INVALID for
>+	 pseudo-numbers (GCC BZ 123173 and LLVM issue 172651.  */
>       TEST_COMPARE (fetestexcept (FE_INVALID), 0);
>+#endif
>     }
>
>   return 0;
>-- 
>2.43.0
>
>



More information about the Libc-alpha mailing list