diff mbox series

Update _FloatN header support for C++ in GCC 13

Message ID alpine.DEB.2.22.394.2209280022150.425621@digraph.polyomino.org.uk
State New
Headers show
Series Update _FloatN header support for C++ in GCC 13 | expand

Commit Message

Joseph Myers Sept. 28, 2022, 12:23 a.m. UTC
GCC 13 adds support for _FloatN and _FloatNx types in C++, so breaking
the installed glibc headers that assume such support is not present.
GCC mostly works around this with fixincludes, but that doesn't help
for building glibc and its tests (glibc doesn't itself contain C++
code, but there's C++ code built for tests).  Update glibc's
bits/floatn-common.h and bits/floatn.h headers to handle the GCC 13
support directly.

In general the changes match those made by fixincludes, though I think
the ones in sysdeps/powerpc/bits/floatn.h, where the header tests
__LDBL_MANT_DIG__ == 113 or uses #elif, wouldn't match the existing
fixincludes patterns.

Some places involving special C++ handling in relation to _FloatN
support are not changed.  There's no need to change the
__HAVE_FLOATN_NOT_TYPEDEF definition (also in a form that wouldn't be
matched by the fixincludes fixes) because it's only used in relation
to macro definitions using features not supported for C++
(__builtin_types_compatible_p and _Generic).  And there's no need to
change the inline function overloads for issignaling, iszero and
iscanonical in C++ because cases where types have the same format but
are no longer compatible types are handled automatically by the C++
overload resolution rules.

This patch also does not change the overload handling for iseqsig, and
there I think changes *are* needed, beyond those in this patch or made
by fixincludes.  The way that overload is defined, via a template
parameter to a structure type, requires overloads whenever the types
are incompatible, even if they have the same format.  So I think we
need to add overloads with GCC 13 for every supported _FloatN and
_FloatNx type, rather than just having one for _Float128 when it has a
different ABI to long double as at present (but for older GCC, such
overloads must not be defined for types that end up defined as
typedefs for another type).

Tested with build-many-glibcs.py: compilers build for
aarch64-linux-gnu ia64-linux-gnu mips64-linux-gnu powerpc-linux-gnu
powerpc64le-linux-gnu x86_64-linux-gnu; glibcs build for
aarch64-linux-gnu ia64-linux-gnu i686-linux-gnu mips-linux-gnu
mips64-linux-gnu-n32 powerpc-linux-gnu powerpc64le-linux-gnu
x86_64-linux-gnu.

---

I am seeking review of this patch, not applying it as a math
maintainer.

Comments

Jakub Jelinek Sept. 28, 2022, 6:28 p.m. UTC | #1
On Wed, Sep 28, 2022 at 12:23:31AM +0000, Joseph Myers wrote:
> GCC 13 adds support for _FloatN and _FloatNx types in C++, so breaking
> the installed glibc headers that assume such support is not present.
> GCC mostly works around this with fixincludes, but that doesn't help
> for building glibc and its tests (glibc doesn't itself contain C++
> code, but there's C++ code built for tests).  Update glibc's
> bits/floatn-common.h and bits/floatn.h headers to handle the GCC 13
> support directly.
> 
> In general the changes match those made by fixincludes, though I think
> the ones in sysdeps/powerpc/bits/floatn.h, where the header tests
> __LDBL_MANT_DIG__ == 113 or uses #elif, wouldn't match the existing
> fixincludes patterns.
> 
> Some places involving special C++ handling in relation to _FloatN
> support are not changed.  There's no need to change the
> __HAVE_FLOATN_NOT_TYPEDEF definition (also in a form that wouldn't be
> matched by the fixincludes fixes) because it's only used in relation
> to macro definitions using features not supported for C++
> (__builtin_types_compatible_p and _Generic).  And there's no need to
> change the inline function overloads for issignaling, iszero and
> iscanonical in C++ because cases where types have the same format but
> are no longer compatible types are handled automatically by the C++
> overload resolution rules.
> 
> This patch also does not change the overload handling for iseqsig, and
> there I think changes *are* needed, beyond those in this patch or made
> by fixincludes.  The way that overload is defined, via a template
> parameter to a structure type, requires overloads whenever the types
> are incompatible, even if they have the same format.  So I think we
> need to add overloads with GCC 13 for every supported _FloatN and
> _FloatNx type, rather than just having one for _Float128 when it has a
> different ABI to long double as at present (but for older GCC, such
> overloads must not be defined for types that end up defined as
> typedefs for another type).
> 
> Tested with build-many-glibcs.py: compilers build for
> aarch64-linux-gnu ia64-linux-gnu mips64-linux-gnu powerpc-linux-gnu
> powerpc64le-linux-gnu x86_64-linux-gnu; glibcs build for
> aarch64-linux-gnu ia64-linux-gnu i686-linux-gnu mips-linux-gnu
> mips64-linux-gnu-n32 powerpc-linux-gnu powerpc64le-linux-gnu
> x86_64-linux-gnu.
> 
> ---
> 
> I am seeking review of this patch, not applying it as a math
> maintainer.

Went through all these and compared them to my include-fixed
of whole libc tree and the only changes are the _Float128x errors
which is desirable.
So, LGTM.

Reviewed-by: Jakub Jelinek <jakub@redhat.com>

	Jakub
Andreas Schwab Sept. 29, 2022, 11:49 a.m. UTC | #2
That appears to create a bootstrap problem:

https://build.opensuse.org/package/live_build_log/devel:gcc:next/gcc13/openSUSE_Factory_zSystems/s390x

make[3]: Entering directory '/home/abuild/rpmbuild/BUILD/gcc-13.0.0+git195654/obj-s390x-suse-linux/libcody'
g++ -std=c++11 -g -O2 -fPIC -fno-exceptions -fno-rtti -include config.h -I../../libcody \
  -MMD -MP -MF buffer.d -c -o buffer.o ../../libcody/buffer.cc
In file included from /usr/include/c++/13/cwchar:44,
                 from /usr/include/c++/13/bits/postypes.h:40,
                 from /usr/include/c++/13/iosfwd:40,
                 from /usr/include/c++/13/bits/shared_ptr.h:52,
                 from /usr/include/c++/13/memory:77,
                 from ../../libcody/cody.hh:24,
                 from ../../libcody/internal.hh:5,
                 from ../../libcody/buffer.cc:6:
/usr/include/wchar.h:397:8: error: '_Float32' does not name a type
  397 | extern _Float32 wcstof32 (const wchar_t *__restrict __nptr,
      |        ^~~~~~~~
/usr/include/wchar.h:402:8: error: '_Float64' does not name a type
  402 | extern _Float64 wcstof64 (const wchar_t *__restrict __nptr,
      |        ^~~~~~~~
/usr/include/wchar.h:407:8: error: '_Float128' does not name a type
  407 | extern _Float128 wcstof128 (const wchar_t *__restrict __nptr,
      |        ^~~~~~~~~
/usr/include/wchar.h:412:8: error: '_Float32x' does not name a type
  412 | extern _Float32x wcstof32x (const wchar_t *__restrict __nptr,
      |        ^~~~~~~~~
/usr/include/wchar.h:417:8: error: '_Float64x' does not name a type
  417 | extern _Float64x wcstof64x (const wchar_t *__restrict __nptr,
      |        ^~~~~~~~~
/usr/include/wchar.h:512:8: error: '_Float32' does not name a type
  512 | extern _Float32 wcstof32_l (const wchar_t *__restrict __nptr,
      |        ^~~~~~~~
/usr/include/wchar.h:518:8: error: '_Float64' does not name a type
  518 | extern _Float64 wcstof64_l (const wchar_t *__restrict __nptr,
      |        ^~~~~~~~
/usr/include/wchar.h:524:8: error: '_Float128' does not name a type
  524 | extern _Float128 wcstof128_l (const wchar_t *__restrict __nptr,
      |        ^~~~~~~~~
/usr/include/wchar.h:530:8: error: '_Float32x' does not name a type
  530 | extern _Float32x wcstof32x_l (const wchar_t *__restrict __nptr,
      |        ^~~~~~~~~
/usr/include/wchar.h:536:8: error: '_Float64x' does not name a type
  536 | extern _Float64x wcstof64x_l (const wchar_t *__restrict __nptr,
      |        ^~~~~~~~~
In file included from /usr/include/c++/13/cstdlib:75,
                 from /usr/include/c++/13/ext/string_conversions.h:41,
                 from /usr/include/c++/13/bits/basic_string.h:4040,
                 from /usr/include/c++/13/string:52,
                 from ../../libcody/cody.hh:25:
/usr/include/stdlib.h:141:8: error: '_Float32' does not name a type
  141 | extern _Float32 strtof32 (const char *__restrict __nptr,
      |        ^~~~~~~~
/usr/include/stdlib.h:147:8: error: '_Float64' does not name a type
  147 | extern _Float64 strtof64 (const char *__restrict __nptr,
      |        ^~~~~~~~
/usr/include/stdlib.h:153:8: error: '_Float128' does not name a type
  153 | extern _Float128 strtof128 (const char *__restrict __nptr,
      |        ^~~~~~~~~
/usr/include/stdlib.h:159:8: error: '_Float32x' does not name a type
  159 | extern _Float32x strtof32x (const char *__restrict __nptr,
      |        ^~~~~~~~~
/usr/include/stdlib.h:165:8: error: '_Float64x' does not name a type
  165 | extern _Float64x strtof64x (const char *__restrict __nptr,
      |        ^~~~~~~~~
/usr/include/stdlib.h:234:24: error: '_Float32' has not been declared
  234 |                        _Float32 __f)
      |                        ^~~~~~~~
/usr/include/stdlib.h:240:24: error: '_Float64' has not been declared
  240 |                        _Float64 __f)
      |                        ^~~~~~~~
/usr/include/stdlib.h:246:25: error: '_Float128' has not been declared
  246 |                         _Float128 __f)
      |                         ^~~~~~~~~
/usr/include/stdlib.h:252:25: error: '_Float32x' has not been declared
  252 |                         _Float32x __f)
      |                         ^~~~~~~~~
/usr/include/stdlib.h:258:25: error: '_Float64x' has not been declared
  258 |                         _Float64x __f)
      |                         ^~~~~~~~~
/usr/include/stdlib.h:317:8: error: '_Float32' does not name a type
  317 | extern _Float32 strtof32_l (const char *__restrict __nptr,
      |        ^~~~~~~~
/usr/include/stdlib.h:324:8: error: '_Float64' does not name a type
  324 | extern _Float64 strtof64_l (const char *__restrict __nptr,
      |        ^~~~~~~~
/usr/include/stdlib.h:331:8: error: '_Float128' does not name a type
  331 | extern _Float128 strtof128_l (const char *__restrict __nptr,
      |        ^~~~~~~~~
/usr/include/stdlib.h:338:8: error: '_Float32x' does not name a type
  338 | extern _Float32x strtof32x_l (const char *__restrict __nptr,
      |        ^~~~~~~~~
/usr/include/stdlib.h:345:8: error: '_Float64x' does not name a type
  345 | extern _Float64x strtof64x_l (const char *__restrict __nptr,
      |        ^~~~~~~~~
make[3]: *** [Makefile:57: buffer.o] Error 1
make[3]: Leaving directory '/home/abuild/rpmbuild/BUILD/gcc-13.0.0+git195654/obj-s390x-suse-linux/libcody'
make[2]: *** [Makefile:10323: all-stage1-libcody] Error 2

The bootstrap compiler is gcc13-13.0.0+git195356, and glibc is
2.36.9000.155.g3e5760fcb4
Andreas Schwab Sept. 29, 2022, 3:12 p.m. UTC | #3
I have now worked around that by building gcc once against the last
glibc release.  I guess nothing can be done about that anyway.
diff mbox series

Patch

diff --git a/bits/floatn-common.h b/bits/floatn-common.h
index 92982d6460..67519dbb74 100644
--- a/bits/floatn-common.h
+++ b/bits/floatn-common.h
@@ -78,7 +78,7 @@ 
    or _FloatNx types, if __HAVE_<type> is 1.  The corresponding
    literal suffixes exist since GCC 7, for C only.  */
 # if __HAVE_FLOAT16
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 /* No corresponding suffix available for this type.  */
 #   define __f16(x) ((_Float16) x##f)
 #  else
@@ -87,7 +87,7 @@ 
 # endif
 
 # if __HAVE_FLOAT32
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 #   define __f32(x) x##f
 #  else
 #   define __f32(x) x##f32
@@ -95,7 +95,7 @@ 
 # endif
 
 # if __HAVE_FLOAT64
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 #   ifdef __NO_LONG_DOUBLE_MATH
 #    define __f64(x) x##l
 #   else
@@ -107,7 +107,7 @@ 
 # endif
 
 # if __HAVE_FLOAT32X
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 #   define __f32x(x) x
 #  else
 #   define __f32x(x) x##f32x
@@ -115,7 +115,7 @@ 
 # endif
 
 # if __HAVE_FLOAT64X
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 #   if __HAVE_FLOAT64X_LONG_DOUBLE
 #    define __f64x(x) x##l
 #   else
@@ -127,7 +127,7 @@ 
 # endif
 
 # if __HAVE_FLOAT128X
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 #   error "_Float128X supported but no constant suffix"
 #  else
 #   define __f128x(x) x##f128x
@@ -136,7 +136,7 @@ 
 
 /* Defined to a complex type if __HAVE_<type> is 1.  */
 # if __HAVE_FLOAT16
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 typedef _Complex float __cfloat16 __attribute__ ((__mode__ (__HC__)));
 #   define __CFLOAT16 __cfloat16
 #  else
@@ -145,7 +145,7 @@  typedef _Complex float __cfloat16 __attribute__ ((__mode__ (__HC__)));
 # endif
 
 # if __HAVE_FLOAT32
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 #   define __CFLOAT32 _Complex float
 #  else
 #   define __CFLOAT32 _Complex _Float32
@@ -153,7 +153,7 @@  typedef _Complex float __cfloat16 __attribute__ ((__mode__ (__HC__)));
 # endif
 
 # if __HAVE_FLOAT64
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 #   ifdef __NO_LONG_DOUBLE_MATH
 #    define __CFLOAT64 _Complex long double
 #   else
@@ -165,7 +165,7 @@  typedef _Complex float __cfloat16 __attribute__ ((__mode__ (__HC__)));
 # endif
 
 # if __HAVE_FLOAT32X
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 #   define __CFLOAT32X _Complex double
 #  else
 #   define __CFLOAT32X _Complex _Float32x
@@ -173,7 +173,7 @@  typedef _Complex float __cfloat16 __attribute__ ((__mode__ (__HC__)));
 # endif
 
 # if __HAVE_FLOAT64X
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 #   if __HAVE_FLOAT64X_LONG_DOUBLE
 #    define __CFLOAT64X _Complex long double
 #   else
@@ -185,7 +185,7 @@  typedef _Complex float __cfloat16 __attribute__ ((__mode__ (__HC__)));
 # endif
 
 # if __HAVE_FLOAT128X
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 #   error "_Float128X supported but no complex type"
 #  else
 #   define __CFLOAT128X _Complex _Float128x
@@ -195,7 +195,7 @@  typedef _Complex float __cfloat16 __attribute__ ((__mode__ (__HC__)));
 /* The remaining of this file provides support for older compilers.  */
 # if __HAVE_FLOAT16
 
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 typedef float _Float16 __attribute__ ((__mode__ (__HF__)));
 #  endif
 
@@ -210,7 +210,7 @@  typedef float _Float16 __attribute__ ((__mode__ (__HF__)));
 
 # if __HAVE_FLOAT32
 
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 typedef float _Float32;
 #  endif
 
@@ -234,7 +234,7 @@  typedef float _Float32;
 
 #  ifdef __NO_LONG_DOUBLE_MATH
 
-#   if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#   if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 typedef long double _Float64;
 #   endif
 
@@ -247,7 +247,7 @@  typedef long double _Float64;
 
 #  else
 
-#   if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#   if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 typedef double _Float64;
 #   endif
 
@@ -264,7 +264,7 @@  typedef double _Float64;
 
 # if __HAVE_FLOAT32X
 
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 typedef double _Float32x;
 #  endif
 
@@ -281,7 +281,7 @@  typedef double _Float32x;
 
 #  if __HAVE_FLOAT64X_LONG_DOUBLE
 
-#   if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#   if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 typedef long double _Float64x;
 #   endif
 
@@ -294,7 +294,7 @@  typedef long double _Float64x;
 
 #  else
 
-#   if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#   if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 typedef _Float128 _Float64x;
 #   endif
 
@@ -311,7 +311,7 @@  typedef _Float128 _Float64x;
 
 # if __HAVE_FLOAT128X
 
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 #   error "_Float128x supported but no type"
 #  endif
 
diff --git a/sysdeps/ia64/bits/floatn.h b/sysdeps/ia64/bits/floatn.h
index 5507038bc7..75f7547045 100644
--- a/sysdeps/ia64/bits/floatn.h
+++ b/sysdeps/ia64/bits/floatn.h
@@ -56,7 +56,7 @@ 
 /* Defined to concatenate the literal suffix to be used with _Float128
    types, if __HAVE_FLOAT128 is 1. */
 # if __HAVE_FLOAT128
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 /* The literal suffix f128 exists only since GCC 7.0.  */
 #   define __f128(x) x##q
 #  else
@@ -66,7 +66,7 @@ 
 
 /* Defined to a complex binary128 type if __HAVE_FLOAT128 is 1.  */
 # if __HAVE_FLOAT128
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 /* Add a typedef for older GCC compilers which don't natively support
    _Complex _Float128.  */
 typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
@@ -80,7 +80,7 @@  typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
 # if __HAVE_FLOAT128
 
 /* The type _Float128 exists only since GCC 7.0.  */
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 typedef __float128 _Float128;
 #  endif
 
diff --git a/sysdeps/ieee754/ldbl-128/bits/floatn.h b/sysdeps/ieee754/ldbl-128/bits/floatn.h
index 9ae7b30373..6ef60a3c9b 100644
--- a/sysdeps/ieee754/ldbl-128/bits/floatn.h
+++ b/sysdeps/ieee754/ldbl-128/bits/floatn.h
@@ -55,7 +55,7 @@ 
 /* Defined to concatenate the literal suffix to be used with _Float128
    types, if __HAVE_FLOAT128 is 1. */
 # if __HAVE_FLOAT128
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 /* The literal suffix f128 exists only since GCC 7.0.  */
 #   define __f128(x) x##l
 #  else
@@ -65,7 +65,7 @@ 
 
 /* Defined to a complex binary128 type if __HAVE_FLOAT128 is 1.  */
 # if __HAVE_FLOAT128
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 #   define __CFLOAT128 _Complex long double
 #  else
 #   define __CFLOAT128 _Complex _Float128
@@ -76,7 +76,7 @@ 
 # if __HAVE_FLOAT128
 
 /* The type _Float128 exists only since GCC 7.0.  */
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 typedef long double _Float128;
 #  endif
 
diff --git a/sysdeps/mips/ieee754/bits/floatn.h b/sysdeps/mips/ieee754/bits/floatn.h
index 1d51db04c7..f0321eb010 100644
--- a/sysdeps/mips/ieee754/bits/floatn.h
+++ b/sysdeps/mips/ieee754/bits/floatn.h
@@ -55,7 +55,7 @@ 
 /* Defined to concatenate the literal suffix to be used with _Float128
    types, if __HAVE_FLOAT128 is 1. */
 # if __HAVE_FLOAT128
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 /* The literal suffix f128 exists only since GCC 7.0.  */
 #   define __f128(x) x##l
 #  else
@@ -65,7 +65,7 @@ 
 
 /* Defined to a complex binary128 type if __HAVE_FLOAT128 is 1.  */
 # if __HAVE_FLOAT128
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 #   define __CFLOAT128 _Complex long double
 #  else
 #   define __CFLOAT128 _Complex _Float128
@@ -76,7 +76,7 @@ 
 # if __HAVE_FLOAT128
 
 /* The type _Float128 exists only since GCC 7.0.  */
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 typedef long double _Float128;
 #  endif
 
diff --git a/sysdeps/powerpc/bits/floatn.h b/sysdeps/powerpc/bits/floatn.h
index 23db8be5a3..3c756dfc9d 100644
--- a/sysdeps/powerpc/bits/floatn.h
+++ b/sysdeps/powerpc/bits/floatn.h
@@ -57,7 +57,7 @@ 
 /* Defined to concatenate the literal suffix to be used with _Float128
    types, if __HAVE_FLOAT128 is 1. */
 # if __HAVE_FLOAT128
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 /* The literal suffix (f128) exist for powerpc only since GCC 7.0.  */
 #   if __LDBL_MANT_DIG__ == 113
 #    define __f128(x) x##l
@@ -71,10 +71,10 @@ 
 
 /* Defined to a complex binary128 type if __HAVE_FLOAT128 is 1.  */
 # if __HAVE_FLOAT128
-#  if __LDBL_MANT_DIG__ == 113 && defined __cplusplus
+#  if __LDBL_MANT_DIG__ == 113 && defined __cplusplus && !__GNUC_PREREQ (13, 0)
 typedef long double _Float128;
 #   define __CFLOAT128 _Complex long double
-#  elif !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  elif !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 /* The type _Float128 exist for powerpc only since GCC 7.0.  */
 typedef __float128 _Float128;
 /* Add a typedef for older GCC and C++ compilers which don't natively support
diff --git a/sysdeps/x86/bits/floatn.h b/sysdeps/x86/bits/floatn.h
index 34a6fdc864..4ff39457b5 100644
--- a/sysdeps/x86/bits/floatn.h
+++ b/sysdeps/x86/bits/floatn.h
@@ -58,7 +58,7 @@ 
 /* Defined to concatenate the literal suffix to be used with _Float128
    types, if __HAVE_FLOAT128 is 1. */
 # if __HAVE_FLOAT128
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 /* The literal suffix f128 exists only since GCC 7.0.  */
 #   define __f128(x) x##q
 #  else
@@ -68,7 +68,7 @@ 
 
 /* Defined to a complex binary128 type if __HAVE_FLOAT128 is 1.  */
 # if __HAVE_FLOAT128
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 /* Add a typedef for older GCC compilers which don't natively support
    _Complex _Float128.  */
 typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
@@ -82,7 +82,7 @@  typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
 # if __HAVE_FLOAT128
 
 /* The type _Float128 exists only since GCC 7.0.  */
-#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0))
 typedef __float128 _Float128;
 #  endif