From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-yb1-xb36.google.com (mail-yb1-xb36.google.com [IPv6:2607:f8b0:4864:20::b36]) by sourceware.org (Postfix) with ESMTPS id 85BE33858D37 for ; Tue, 20 Sep 2022 07:14:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 85BE33858D37 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-yb1-xb36.google.com with SMTP id b136so2113215yba.2 for ; Tue, 20 Sep 2022 00:14:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date; bh=m6kuPocyifkxhYtmkkx2IVS5s6xBauf1sNOak+UUxGo=; b=T/c9TiAlFvin7PH/klZIbaeYUe5td7wHE+StB1T5573sOr2sIhK4YvEsoKh4VI9wjO bnzOuy6EUMhXh474qSWV0voMF+NEGOmXV38GYdjhNiFYWRqW8xqA8AzJ2LaYAHzIoo7H 6lM4Ide8rreTh0sH/BAk+QF8plegFJkMvbk5ugDKan6PXN9e7zkI0KQaJzhiwVN58y0A zGbwTUDTl5tiJYhtyXDlG/UjzfmU3GePa19R/4I5uQYbpLyqCE8O+Te4p7IVmyQKMjzM 63CI5ngUQ70rZOZIJRQb78aLAxvHTgWH+MU+UDo1EiNEe0DTiuvwpVau1DlM5AsZGHx6 iJOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date; bh=m6kuPocyifkxhYtmkkx2IVS5s6xBauf1sNOak+UUxGo=; b=yUehPfhxsVZl4edaGSRYg4ey9YLUqQmCSK9Kd/c+1HhLdczechS/I/8ihta1fdL1Bb VSu0j4ARsoiRoFBkOyDHtpxfy0A9j24MygMKksFyud7PskPOvXO3tNw3KL4XZt+6HNup a27J5ZP0PZr8JwHBIZSM4Yx5JBLQdqVF9Uc52f/1RfVh5u3bB1m7qg5hs0g4tlgrd5kZ 2A3e+4PiNhM1anOG/5LkGPq/ivg6gx+wlKKCTwJQPiqN/+Bv9uL+nfVnbk1TdzhfNMej 4JJuxqWGXiJhHnjBOcakKfcBZmJYKh39zYi8T7l2RVdtLS5NrkMwz3jA1gbJrZXfte7s jNpg== X-Gm-Message-State: ACrzQf110i2Y2xNYqR6CtidvhqXmNMWie1MO6oBGcuzWJgwO3z+0wCZz fyArZPlg3ulPpVohGhTN2hkxVVwCfA8EsMUMAxtqOHFBOic= X-Google-Smtp-Source: AMsMyM4WLye7GJIuIikAJHPGrOOsTw4Zgh8SPJ3f5Sx9tXMo3UyBzxlMnfdhWK6NyGG4Ib+sIritxmM82m38y0tQD6Y= X-Received: by 2002:a25:d4cf:0:b0:6a9:3a2d:66c0 with SMTP id m198-20020a25d4cf000000b006a93a2d66c0mr17910497ybf.107.1663658096188; Tue, 20 Sep 2022 00:14:56 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Hongtao Liu Date: Tue, 20 Sep 2022 15:14:44 +0800 Message-ID: Subject: Re: [PATCH] c++: Implement P1467R9 - Extended floating-point types and standard names compiler part except for bfloat16 [PR106652] To: phoebe.wang@intel.com Cc: gcc-patches@gcc.gnu.org Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-0.6 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP,URIBL_BLACK autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: +My intel folk phoebe working for llvm side. On Tue, Sep 20, 2022 at 11:35 AM Hongtao Liu wrote: > > On Mon, Sep 12, 2022 at 4:06 PM Jakub Jelinek via Gcc-patches > wrote: > > > > Hi! > > > > The following patch implements the compiler part of C++23 > > P1467R9 - Extended floating-point types and standard names compiler part > > by introducing _Float{16,32,64,128} as keywords and builtin types > > like they are implemented for C already since GCC 7. > > It doesn't introduce _Float{32,64,128}x for C++, those remain C only > > for now, mainly because https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling > > has mangling for: > > ::= DF _ # ISO/IEC TS 18661 binary floating point type _FloatN (N bits) > > but doesn't for _FloatNx. And it doesn't add anything for bfloat16_t > > support, see below. > > Regarding mangling, I think mangling _FloatNx as DF x _ would be > > possible, but would need to be discussed and voted in. > > As there is no _FloatNx support for C++, I think it is wrong to announce > > it through __FLT{32,64,128}X_*__ predefined macros (so the patch disables > > those for C++; unfortunately g++ 7 to 12 will predefine those and also > > __FLT{32,64,128}_*__ even when _FloatN support isn't implemented). > > The patch wants to keep backwards compatibility with how __float128 has > > been handled in C++ before, both for mangling and behavior in binary > > operations, overload resolution etc. So, there are some backend changes > > where for C __float128 and _Float128 are the same type (float128_type_node > > and float128t_type_node are the same pointer), but for C++ they are distinct > > types which mangle differently and _Float128 is treated as extended > > floating-point type while __float128 is treated as non-standard floating > > point type. The various C++23 changes about how floating-point types > > are changed are actually implemented as written in the spec only if at least > > one of the types involved is _Float{16,32,64,128} and kept previous behavior > > otherwise. For float/double/long double the rules are actually written that > > they behave the same as before. > > There is some backwards incompatibility at least on x86 regarding _Float16, > > because that type was already used by that name and with the DF16_ mangling > > (but only since GCC 12 and I think it isn't that widely used in the wild > > yet). E.g. config/i386/avx512fp16intrin.h shows the issues, where > > in C or in GCC 12 in C++ one could pass 0.0f to a builtin taking _Float16 > > argument, but with the changes that is not possible anymore, one needs > > to either use 0.0f16 or (_Float16) 0.0f. > > We have also a problem with glibc headers, where since glibc 2.27 > > math.h and complex.h aren't compilable with these changes. One gets > > errors like: > > In file included from /usr/include/math.h:43, > > from abc.c:1: > > /usr/include/bits/floatn.h:86:9: error: multiple types in one declaration > > 86 | typedef __float128 _Float128; > > | ^~~~~~~~~~ > > /usr/include/bits/floatn.h:86:20: error: declaration does not declare anything [-fpermissive] > > 86 | typedef __float128 _Float128; > > | ^~~~~~~~~ > > In file included from /usr/include/bits/floatn.h:119: > > /usr/include/bits/floatn-common.h:214:9: error: multiple types in one declaration > > 214 | typedef float _Float32; > > | ^~~~~ > > /usr/include/bits/floatn-common.h:214:15: error: declaration does not declare anything [-fpermissive] > > 214 | typedef float _Float32; > > | ^~~~~~~~ > > /usr/include/bits/floatn-common.h:251:9: error: multiple types in one declaration > > 251 | typedef double _Float64; > > | ^~~~~~ > > /usr/include/bits/floatn-common.h:251:16: error: declaration does not declare anything [-fpermissive] > > 251 | typedef double _Float64; > > | ^~~~~~~~ > > This is from snippets like: > > /* The remaining of this file provides support for older compilers. */ > > # if __HAVE_FLOAT128 > > > > /* The type _Float128 exists only since GCC 7.0. */ > > # if !__GNUC_PREREQ (7, 0) || defined __cplusplus > > typedef __float128 _Float128; > > # endif > > where it hardcodes that C++ doesn't have _Float{16,32,64,128} support nor > > {f,F}{16,32,64,128} literal suffixes nor _Complex _Float{16,32,64,128}. > > The patch fixincludes this for now and hopefully if this is committed, then > > glibc can change those. Right now the patch changes those > > # if !__GNUC_PREREQ (7, 0) || defined __cplusplus > > conditions to > > # if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__) > > where it relies on __FLT32X_*__ macros no longer being predefined for C++. > > Now, I guess for the fixincludes it could also use > > # if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 0)) > > where earlier GCC 13 snapshots would not be doing the fixincludes, > > but the question is what to use for upstream glibc, because > > there will be 13.0 snapshots where C++ doesn't support _Float{16,32,64,128} > > and where it is essential to use what glibc has been doing previously > > and using the #else would fail miserably, and then 13.0 snapshots where it > > does support it and where using the if would fail miserably. > > One option is to use > > # if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1)) > > in glibc and rely on fixincludes for 13.0 snapshots (or of course later when > > using 13.1+ with older glibc). > > Another thing is mangling, as said above, Itanium C++ ABI specifies > > DF _ as _Float{16,32,64,128} mangling, but GCC was implementing > > a mangling incompatible with that starting with DF for fixed point types. > > Fixed point was never supported in C++ though, I believe the reason why > > the mangling has been added was that due to a bug it would leak into the > > C++ FE through decltype (0.0r) etc. But that has been shortly after the > > mangling was added fixed (I think in the same GCC release cycle), so we > > now reject 0.0r etc. in C++. If we ever need the fixed point mangling, > > I think it can be readded but better with a different prefix so that it > > doesn't conflict with the published standard manglings. So, this patch > > also kills the fixed point mangling and implements the DF _ > > demangling. > > The patch predefines __STDCPP_FLOAT{16,32,64,128}_T__ macros when > > those types are available, but only for C++23, while the underlying types > > are available in C++98 and later including the {f,F}{16,32,64,128} literal > > suffixes (but those with a pedwarn for C++20 and earlier). My understanding > > is that it needs to be predefined by the compiler, on the other side > > predefining even for older modes when is a new C++23 header > > would be weird. One can find out if _Float{16,32,64,128} is supported in > > C++ by > > defined(__FLT{16,32,64,128}_MANT_DIG__) && !defined(__FLT32X_MANT_DIG__) > > (unfortunately not just the former because GCC 7-12 predefined those too) > > or perhaps __GNUC__ >= 13 && defined(__FLT{16,32,64,128}_MANT_DIG__) > > (but that doesn't work well with older G++ 13 snapshots). > > > > As for std::bfloat16_t, three targets (aarch64, arm and x86) apparently > > "support" __bf16 type which has the bfloat16 format, but isn't really > > usable, e.g. {aarch64,arm,ix86}_invalid_conversion disallow any conversions > > from or to type with BFmode, {aarch64,arm,ix86}_invalid_unary_op disallows > > any unary operations on those except for ADDR_EXPR and > > {aarch64,arm,ix86}_invalid_binary_op disallows any binary operation on > > those. So, I think we satisfy: > > "If the implementation supports an extended floating-point type with the > > properties, as specified by ISO/IEC/IEEE 60559, of radix (b) of 2, storage > > width in bits (k) of 16, precision in bits (p) of 8, maximum exponent (emax) > > of 127, and exponent field width in bits (w) of 8, then the typedef-name > > std::bfloat16_t is defined in the header and names such a type, > > the macro __STDCPP_BFLOAT16_T__ is defined, and the floating-point literal > > suffixes bf16 and BF16 are supported." > > because we don't really support those right now. > > The question is (mainly for aarch64, arm and x86 backend maintainers) if we > > shouldn't support it, in the PR there is a partial patch to do so, but > > the big question is if it should be supported as the __bf16 type those > > 3 targets use with u6__bf16 mangling and remove those *_invalid_* cases > > and add conversions to/from at least SFmode but probably also DFmode, TFmode > > and XFmode on x86 and implement arithmetics on those through conversion to > > SFmode, performing arithmetics there and conversion back. > > Conversion from BFmode to SFmode is easy, left shift by 16 and ought to be > > implemented inline, SFmode -> BFmode conversion is harder, > > I think it is roughly: > I'm not sure if there should be any floating point exceptions for > BFmode operation. > For x86, there's no floating point exceptions for AVX512_BF16 related > instructions > > __bf16 > > __truncsfbf2 (_Float32 x) > > { > > unsigned int y; > > memcpy (&y, &x, sizeof (y)); > > unsigned int z = x & 0x7fffffff; > > unsigned short r; > > __bf16 ret; > > if (z < 0x800000) > > // Zero or denormal, flush to zero. > > r = (x & 0x80000000) >> 16; > > else if (z < 0x7f800000) > > // Normal, round to nearest. > > r = (x + 0x7fff + ((x >> 16) & 1)) >> 16; > > else if (z == 0x7f800000) > > // Inf. > > r = x >> 16; > > else > > // NaN. > > r = (x >> 16) | (1 << 6); > > memcpy (&ret, &r, sizeof (r)); > > return ret; > > } > > (untested) and the question is if it should be implemented in libgcc > > (and using soft-fp or not), or inline, or both depending on -Os. > > Or there is the possibility to keep __bf16 a lame type one can't convert > > to/from or perform most unary and all binary ops on it, and add for C++ > > a new type (say __bfloat16_t or whatever else), agree on mangling in > > Itanium ABI and implement full support just for that type. > > > > Bootstrapped/regtested on x86_64-linux and i686-linux and additionally > > tested on some of the testcases on crosses to powerpc64le-linux (various > > cases including -mabi=ieeelongdouble and -mabi=ibmlongdouble), aarch64-linux > > and s390x-linux. > > > > Ok for trunk? > > > > 2022-09-12 Jakub Jelinek > > > > PR c++/106652 > > gcc/ > > * tree-core.h (enum tree_index): Add TI_FLOAT128T_TYPE > > enumerator. > > * tree.h (float128t_type_node): Define. > > * tree.cc (build_common_tree_nodes): Initialize float128t_type_node. > > * builtins.def (DEF_FLOATN_BUILTIN): Adjust comment now that > > _Float is supported in C++ too. > > * config/i386/i386.cc (ix86_mangle_type): Only mangle as "g" > > float128t_type_node. > > * config/i386/i386-builtins.cc (ix86_init_builtin_types): Use > > float128t_type_node for __float128 instead of float128_type_node > > and create it if NULL. > > * config/i386/avx512fp16intrin.h (_mm_setzero_ph, _mm256_setzero_ph, > > _mm512_setzero_ph, _mm_set_sh, _mm_load_sh): Use 0.0f16 instead of > > 0.0f. > > * config/ia64/ia64.cc (ia64_init_builtins): Use > > float128t_type_node for __float128 instead of float128_type_node > > and create it if NULL. > > * config/rs6000/rs6000-c.cc (is_float128_p): Also return true > > for float128t_type_node if non-NULL. > > * config/rs6000/rs6000.cc (rs6000_mangle_type): Don't mangle > > float128_type_node as "u9__ieee128". > > * config/rs6000/rs6000-builtin.cc (rs6000_init_builtins): Use > > float128t_type_node for __float128 instead of float128_type_node > > and create it if NULL. > > gcc/c-family/ > > * c-common.cc (c_common_reswords): Change _Float{16,32,64,128} flags > > from D_CONLY to 0. > > (shorten_binary_op): Punt if common_type returns error_mark_node. > > (shorten_compare): Likewise. > > (c_common_nodes_and_builtins): For C++ record _Float{16,32,64,128} > > builtin types if available but not _Float{32,64,128}x. For C++ > > clear float128t_type_node. > > * c-cppbuiltin.cc (c_cpp_builtins): For C++ don't predefine > > __FLT{32,64,128}X_*__ macros, on the other side predefine > > __STDCPP_FLOAT{16,32,64,128}_T__ for C++23 if supported. > > * c-common.h (CASE_RID_FLOATN): Define. > > (CASE_RID_FLOATN_NX): Use it. > > * c-lex.cc (interpret_float): For q/Q suffixes prefer > > float128t_type_node over float128_type_node. Allow > > {f,F}{16,32,64,128} suffixes for C++ if supported with pedwarn > > for C++20 and older. Don't call excess_precision_type for C++. > > gcc/cp/ > > * cp-tree.h (cp_compare_floating_point_conversion_ranks): Implement > > P1467R9 - Extended floating-point types and standard names except > > for std::bfloat16_t for now. Declare. > > (extended_float_type_p): New inline function. > > * mangle.cc (write_builtin_type): Mangle float{16,32,64,128}_type_node > > as DF{16,32,64,128}_. Remove FIXED_POINT_TYPE mangling that conflicts > > with that. > > * typeck2.cc (check_narrowing): If one of ftype or type is extended > > floating-point type, compare floating-point conversion ranks. > > * parser.cc (cp_keyword_starts_decl_specifier_p): Handle > > CASE_RID_FLOATN. > > (cp_parser_simple_type_specifier): Likewise and diagnose missing > > _Float support if not supported by target. > > * typeck.cc (cp_compare_floating_point_conversion_ranks): New function. > > (cp_common_type): If both types are REAL_TYPE and one or both are > > extended floating-point types, select common type based on comparison > > of floating-point conversion ranks and subranks. > > (cp_build_binary_op): Diagnose operation with floating point arguments > > with unordered conversion ranks. > > * call.cc (standard_conversion): For floating-point conversion, if > > either from or to are extended floating-point types reject implicit > > conversion from larger to smaller conversion rank or with unordered > > conversion ranks. > > (build_conditional_expr): Diagnose operation with floating point > > arguments with unordered conversion ranks. > > (convert_arg_to_ellipsis): Don't promote extended floating-point types > > narrower than double to double. > > (compare_ics): Implement P1467R9 [over.ics.rank]/4 changes. > > gcc/testsuite/ > > * g++.dg/cpp23/ext-floating1.C: New test. > > * g++.dg/cpp23/ext-floating2.C: New test. > > * g++.dg/cpp23/ext-floating3.C: New test. > > * g++.dg/cpp23/ext-floating4.C: New test. > > * g++.dg/cpp23/ext-floating5.C: New test. > > * g++.dg/cpp23/ext-floating6.C: New test. > > * g++.dg/cpp23/ext-floating7.C: New test. > > * g++.dg/cpp23/ext-floating8.C: New test. > > * g++.dg/cpp23/ext-floating9.C: New test. > > * g++.dg/cpp23/ext-floating10.C: New test. > > * g++.dg/cpp23/ext-floating.h: New file. > > * g++.target/i386/float16-1.C: Adjust expected diagnostics. > > libcpp/ > > * expr.cc (interpret_float_suffix): Allow {f,F}{16,32,64,128} suffixes > > for C++, but not {f,F}{32,64,128}x. > > include/ > > * demangle.h (enum demangle_component_type): Add > > DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE. > > (struct demangle_component): Add u.s_extended_builtin member. > > libiberty/ > > * cp-demangle.c (d_dump): Handle > > DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE. Don't handle > > DEMANGLE_COMPONENT_FIXED_TYPE. > > (d_make_extended_builtin_type): New function. > > (cplus_demangle_builtin_types): Add _Float entry. > > (cplus_demangle_type): For DF demangle it as _Float rather > > than fixed point which conflicts with it. > > (d_count_templates_scopes): Handle > > DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE. Just break; for > > DEMANGLE_COMPONENT_FIXED_TYPE. > > (d_find_pack): Handle DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE. > > Don't handle DEMANGLE_COMPONENT_FIXED_TYPE. > > (d_print_comp_inner): Likewise. > > * cp-demangle.h (D_BUILTIN_TYPE_COUNT): Bump. > > * testsuite/demangle-expected: Replace _Z3xxxDFyuVb test > > with _Z3xxxDF16_DF32_DF64_DF128_CDF16_Vb. > > fixincludes/ > > * inclhack.def (glibc_cxx_floatn_1, glibc_cxx_floatn_2, > > glibc_cxx_floatn_3): New fixes. > > * tests/base/bits/floatn.h: New file. > > * fixincl.x: Regenerated. > > > > --- gcc/tree-core.h.jj 2022-09-09 12:27:23.180736449 +0200 > > +++ gcc/tree-core.h 2022-09-09 18:46:07.257922609 +0200 > > @@ -690,6 +690,10 @@ enum tree_index { > > - TI_FLOATN_NX_TYPE_FIRST \ > > + 1) > > > > + /* Type used by certain backends for __float128, which in C++ should be > > + distinct type from _Float128 for backwards compatibility reasons. */ > > + TI_FLOAT128T_TYPE, > > + > > /* Put the complex types after their component types, so that in (sequential) > > tree streaming we can assert that their component types have already been > > handled (see tree-streamer.cc:record_common_node). */ > > --- gcc/tree.h.jj 2022-09-09 12:27:23.183736409 +0200 > > +++ gcc/tree.h 2022-09-09 18:46:07.258922596 +0200 > > @@ -4302,6 +4302,10 @@ tree_strip_any_location_wrapper (tree ex > > #define float64x_type_node global_trees[TI_FLOAT64X_TYPE] > > #define float128x_type_node global_trees[TI_FLOAT128X_TYPE] > > > > +/* Type used by certain backends for __float128, which in C++ should be > > + distinct type from _Float128 for backwards compatibility reasons. */ > > +#define float128t_type_node global_trees[TI_FLOAT128T_TYPE] > > + > > #define float_ptr_type_node global_trees[TI_FLOAT_PTR_TYPE] > > #define double_ptr_type_node global_trees[TI_DOUBLE_PTR_TYPE] > > #define long_double_ptr_type_node global_trees[TI_LONG_DOUBLE_PTR_TYPE] > > --- gcc/tree.cc.jj 2022-09-09 18:44:27.153255900 +0200 > > +++ gcc/tree.cc 2022-09-09 18:46:07.260922569 +0200 > > @@ -9459,6 +9459,7 @@ build_common_tree_nodes (bool signed_cha > > layout_type (FLOATN_NX_TYPE_NODE (i)); > > SET_TYPE_MODE (FLOATN_NX_TYPE_NODE (i), mode); > > } > > + float128t_type_node = float128_type_node; > > > > float_ptr_type_node = build_pointer_type (float_type_node); > > double_ptr_type_node = build_pointer_type (double_type_node); > > --- gcc/builtins.def.jj 2022-09-09 12:27:23.136737041 +0200 > > +++ gcc/builtins.def 2022-09-09 18:46:07.261922555 +0200 > > @@ -115,8 +115,8 @@ along with GCC; see the file COPYING3. > > we are compiling for the C language with GNU extensions, we enable the name > > without the __builtin_ prefix as well as the name with the __builtin_ > > prefix. C++ does not enable these names by default because they don't have > > - the _Float and _FloatX keywords, and a class based library should use > > - the __builtin_ names. */ > > + the _Floatx keywords, and a class based library should use the __builtin_ > > + names. */ > > #undef DEF_FLOATN_BUILTIN > > #define DEF_FLOATN_BUILTIN(ENUM, NAME, TYPE, ATTRS) \ > > DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \ > > --- gcc/config/i386/i386.cc.jj 2022-09-09 12:27:23.141736974 +0200 > > +++ gcc/config/i386/i386.cc 2022-09-10 11:21:26.997205883 +0200 > > @@ -22711,7 +22711,10 @@ ix86_mangle_type (const_tree type) > > return "DF16_"; > > case E_TFmode: > > /* __float128 is "g". */ > > - return "g"; > > + if (type == float128t_type_node) > > + return "g"; > > + /* _Float128 should mangle as "DF128_" done in generic code. */ > > + return NULL; > > case E_XFmode: > > /* "long double" or __float80 is "e". */ > > return "e"; > > --- gcc/config/i386/i386-builtins.cc.jj 2022-09-09 12:27:23.138737014 +0200 > > +++ gcc/config/i386/i386-builtins.cc 2022-09-09 18:46:07.264922515 +0200 > > @@ -1409,9 +1409,18 @@ ix86_init_builtin_types (void) > > lang_hooks.types.register_builtin_type (float80_type_node, "__float80"); > > > > /* The __float128 type. The node has already been created as > > - _Float128, so we only need to register the __float128 name for > > - it. */ > > - lang_hooks.types.register_builtin_type (float128_type_node, "__float128"); > > + _Float128, so for C we only need to register the __float128 name for > > + it. For C++, we create a distinct type which will mangle differently > > + (g) vs. _Float128 (DF128_) and behave backwards compatibly. */ > > + if (float128t_type_node == NULL_TREE) > > + { > > + float128t_type_node = make_node (REAL_TYPE); > > + TYPE_PRECISION (float128t_type_node) > > + = TYPE_PRECISION (float128_type_node); > > + SET_TYPE_MODE (float128t_type_node, TYPE_MODE (float128_type_node)); > > + layout_type (float128t_type_node); > > + } > > + lang_hooks.types.register_builtin_type (float128t_type_node, "__float128"); > > > > ix86_register_float16_builtin_type (); > > > > --- gcc/config/i386/avx512fp16intrin.h.jj 2022-01-11 22:31:40.696768297 +0100 > > +++ gcc/config/i386/avx512fp16intrin.h 2022-09-11 23:23:28.617437158 +0200 > > @@ -183,21 +183,21 @@ extern __inline __m128h > > __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) > > _mm_setzero_ph (void) > > { > > - return _mm_set1_ph (0.0f); > > + return _mm_set1_ph (0.0f16); > > } > > > > extern __inline __m256h > > __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) > > _mm256_setzero_ph (void) > > { > > - return _mm256_set1_ph (0.0f); > > + return _mm256_set1_ph (0.0f16); > > } > > > > extern __inline __m512h > > __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) > > _mm512_setzero_ph (void) > > { > > - return _mm512_set1_ph (0.0f); > > + return _mm512_set1_ph (0.0f16); > > } > > > > extern __inline __m128h > > @@ -358,7 +358,8 @@ extern __inline __m128h > > __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) > > _mm_set_sh (_Float16 __F) > > { > > - return _mm_set_ph (0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, __F); > > + return _mm_set_ph (0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, > > + __F); > > } > > > > /* Create a vector with element 0 as *P and the rest zero. */ > > @@ -366,7 +367,7 @@ extern __inline __m128h > > __attribute__ ((__gnu_inline__, __always_inline__, __artificial__)) > > _mm_load_sh (void const *__P) > > { > > - return _mm_set_ph (0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, > > + return _mm_set_ph (0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, > > *(_Float16 const *) __P); > > } > > > > --- gcc/config/ia64/ia64.cc.jj 2022-09-09 12:27:23.143736947 +0200 > > +++ gcc/config/ia64/ia64.cc 2022-09-09 18:46:07.265922502 +0200 > > @@ -10466,11 +10466,19 @@ ia64_init_builtins (void) > > = build_pointer_type (build_qualified_type > > (char_type_node, TYPE_QUAL_CONST)); > > > > - (*lang_hooks.types.register_builtin_type) (float128_type_node, > > + if (float128t_type_node == NULL_TREE) > > + { > > + float128t_type_node = make_node (REAL_TYPE); > > + TYPE_PRECISION (float128t_type_node) > > + = TYPE_PRECISION (float128_type_node); > > + layout_type (float128t_type_node); > > + SET_TYPE_MODE (float128t_type_node, TYPE_MODE (float128_type_node)); > > + } > > + (*lang_hooks.types.register_builtin_type) (float128t_type_node, > > "__float128"); > > > > /* TFmode support builtins. */ > > - ftype = build_function_type_list (float128_type_node, NULL_TREE); > > + ftype = build_function_type_list (float128t_type_node, NULL_TREE); > > decl = add_builtin_function ("__builtin_infq", ftype, > > IA64_BUILTIN_INFQ, BUILT_IN_MD, > > NULL, NULL_TREE); > > @@ -10481,7 +10489,7 @@ ia64_init_builtins (void) > > NULL, NULL_TREE); > > ia64_builtins[IA64_BUILTIN_HUGE_VALQ] = decl; > > > > - ftype = build_function_type_list (float128_type_node, > > + ftype = build_function_type_list (float128t_type_node, > > const_string_type, > > NULL_TREE); > > decl = add_builtin_function ("__builtin_nanq", ftype, > > @@ -10496,8 +10504,8 @@ ia64_init_builtins (void) > > TREE_READONLY (decl) = 1; > > ia64_builtins[IA64_BUILTIN_NANSQ] = decl; > > > > - ftype = build_function_type_list (float128_type_node, > > - float128_type_node, > > + ftype = build_function_type_list (float128t_type_node, > > + float128t_type_node, > > NULL_TREE); > > decl = add_builtin_function ("__builtin_fabsq", ftype, > > IA64_BUILTIN_FABSQ, BUILT_IN_MD, > > @@ -10505,9 +10513,9 @@ ia64_init_builtins (void) > > TREE_READONLY (decl) = 1; > > ia64_builtins[IA64_BUILTIN_FABSQ] = decl; > > > > - ftype = build_function_type_list (float128_type_node, > > - float128_type_node, > > - float128_type_node, > > + ftype = build_function_type_list (float128t_type_node, > > + float128t_type_node, > > + float128t_type_node, > > NULL_TREE); > > decl = add_builtin_function ("__builtin_copysignq", ftype, > > IA64_BUILTIN_COPYSIGNQ, BUILT_IN_MD, > > --- gcc/config/rs6000/rs6000-c.cc.jj 2022-09-09 12:27:23.144736933 +0200 > > +++ gcc/config/rs6000/rs6000-c.cc 2022-09-10 11:21:53.958838545 +0200 > > @@ -808,6 +808,7 @@ static inline bool > > is_float128_p (tree t) > > { > > return (t == float128_type_node > > + || (t && t == float128t_type_node) > > || (TARGET_IEEEQUAD > > && TARGET_LONG_DOUBLE_128 > > && t == long_double_type_node)); > > --- gcc/config/rs6000/rs6000.cc.jj 2022-09-09 12:27:23.147736893 +0200 > > +++ gcc/config/rs6000/rs6000.cc 2022-09-09 18:46:07.269922448 +0200 > > @@ -20118,7 +20118,11 @@ rs6000_mangle_type (const_tree type) > > > > if (SCALAR_FLOAT_TYPE_P (type) && FLOAT128_IBM_P (TYPE_MODE (type))) > > return "g"; > > - if (SCALAR_FLOAT_TYPE_P (type) && FLOAT128_IEEE_P (TYPE_MODE (type))) > > + if (SCALAR_FLOAT_TYPE_P (type) > > + && FLOAT128_IEEE_P (TYPE_MODE (type)) > > + /* _Float128 should mangle as DF128_ (done in generic code) > > + rather than u9__ieee128 (used for __ieee128 and __float128). */ > > + && type != float128_type_node) > > return "u9__ieee128"; > > > > if (type == vector_pair_type_node) > > --- gcc/config/rs6000/rs6000-builtin.cc.jj 2022-09-09 12:27:23.143736947 +0200 > > +++ gcc/config/rs6000/rs6000-builtin.cc 2022-09-09 18:46:07.270922435 +0200 > > @@ -733,7 +733,22 @@ rs6000_init_builtins (void) > > if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128) > > ieee128_float_type_node = long_double_type_node; > > else > > - ieee128_float_type_node = float128_type_node; > > + { > > + /* For C we only need to register the __ieee128 name for > > + it. For C++, we create a distinct type which will mangle > > + differently (u9__ieee128) vs. _Float128 (DF128_) and behave > > + backwards compatibly. */ > > + if (float128t_type_node == NULL_TREE) > > + { > > + float128t_type_node = make_node (REAL_TYPE); > > + TYPE_PRECISION (float128t_type_node) > > + = TYPE_PRECISION (float128_type_node); > > + layout_type (float128t_type_node); > > + SET_TYPE_MODE (float128t_type_node, > > + TYPE_MODE (float128_type_node)); > > + } > > + ieee128_float_type_node = float128t_type_node; > > + } > > t = build_qualified_type (ieee128_float_type_node, TYPE_QUAL_CONST); > > lang_hooks.types.register_builtin_type (ieee128_float_type_node, > > "__ieee128"); > > --- gcc/c-family/c-common.cc.jj 2022-09-09 12:27:23.137737028 +0200 > > +++ gcc/c-family/c-common.cc 2022-09-09 19:43:50.730802597 +0200 > > @@ -352,10 +352,10 @@ const struct c_common_resword c_common_r > > { "_Bool", RID_BOOL, D_CONLY }, > > { "_Complex", RID_COMPLEX, 0 }, > > { "_Imaginary", RID_IMAGINARY, D_CONLY }, > > - { "_Float16", RID_FLOAT16, D_CONLY }, > > - { "_Float32", RID_FLOAT32, D_CONLY }, > > - { "_Float64", RID_FLOAT64, D_CONLY }, > > - { "_Float128", RID_FLOAT128, D_CONLY }, > > + { "_Float16", RID_FLOAT16, 0 }, > > + { "_Float32", RID_FLOAT32, 0 }, > > + { "_Float64", RID_FLOAT64, 0 }, > > + { "_Float128", RID_FLOAT128, 0 }, > > { "_Float32x", RID_FLOAT32X, D_CONLY }, > > { "_Float64x", RID_FLOAT64X, D_CONLY }, > > { "_Float128x", RID_FLOAT128X, D_CONLY }, > > @@ -1429,8 +1429,11 @@ shorten_binary_op (tree result_type, tre > > == TYPE_PRECISION (TREE_TYPE (arg0))) > > && unsigned0 == unsigned1 > > && (unsigned0 || !uns)) > > - return c_common_signed_or_unsigned_type > > - (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1))); > > + { > > + tree ctype = common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)); > > + if (ctype != error_mark_node) > > + return c_common_signed_or_unsigned_type (unsigned0, ctype); > > + } > > > > else if (TREE_CODE (arg0) == INTEGER_CST > > && (unsigned1 || !uns) > > @@ -3202,9 +3205,10 @@ shorten_compare (location_t loc, tree *o > > > > else if (unsignedp0 == unsignedp1 && real1 == real2 > > && TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (*restype_ptr) > > - && TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (*restype_ptr)) > > + && TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (*restype_ptr) > > + && (type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1))) > > + != error_mark_node) > > { > > - type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1)); > > type = c_common_signed_or_unsigned_type (unsignedp0 > > || TYPE_UNSIGNED (*restype_ptr), > > type); > > @@ -4378,11 +4382,21 @@ c_common_nodes_and_builtins (void) > > record_builtin_type (RID_DOUBLE, NULL, double_type_node); > > record_builtin_type (RID_MAX, "long double", long_double_type_node); > > > > - if (!c_dialect_cxx ()) > > - for (i = 0; i < NUM_FLOATN_NX_TYPES; i++) > > + for (i = 0; i < NUM_FLOATN_NX_TYPES; i++) > > + { > > if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE) > > record_builtin_type ((enum rid) (RID_FLOATN_NX_FIRST + i), NULL, > > FLOATN_NX_TYPE_NODE (i)); > > + /* Don't register _FloatNX types for C++, just _FloatN. */ > > + if (i == NUM_FLOATN_TYPES && c_dialect_cxx ()) > > + break; > > + } > > + > > + /* For C, let float128t_type_node (__float128 in some backends) be the > > + same type as float128_type_node (_Float128), for C++ let those > > + be distinct types that mangle and behave differently. */ > > + if (c_dialect_cxx ()) > > + float128t_type_node = NULL_TREE; > > > > /* Only supported decimal floating point extension if the target > > actually supports underlying modes. */ > > --- gcc/c-family/c-cppbuiltin.cc.jj 2022-09-09 12:27:23.138737014 +0200 > > +++ gcc/c-family/c-cppbuiltin.cc 2022-09-09 18:46:07.271922421 +0200 > > @@ -1246,6 +1246,14 @@ c_cpp_builtins (cpp_reader *pfile) > > { > > if (FLOATN_NX_TYPE_NODE (i) == NULL_TREE) > > continue; > > + if (floatn_nx_types[i].extended && c_dialect_cxx ()) > > + continue; > > + if (c_dialect_cxx () && cxx_dialect > cxx20) > > + { > > + char name[sizeof ("__STDCPP_FLOAT128_T__=1")]; > > + sprintf (name, "__STDCPP_FLOAT%d_T__=1", floatn_nx_types[i].n); > > + cpp_define (pfile, name); > > + } > > char prefix[20], csuffix[20]; > > sprintf (prefix, "FLT%d%s", floatn_nx_types[i].n, > > floatn_nx_types[i].extended ? "X" : ""); > > --- gcc/c-family/c-common.h.jj 2022-09-09 12:27:23.137737028 +0200 > > +++ gcc/c-family/c-common.h 2022-09-09 18:46:07.271922421 +0200 > > @@ -120,8 +120,10 @@ enum rid > > RID_FLOAT32X, > > RID_FLOAT64X, > > RID_FLOAT128X, > > +#define CASE_RID_FLOATN \ > > + case RID_FLOAT16: case RID_FLOAT32: case RID_FLOAT64: case RID_FLOAT128 > > #define CASE_RID_FLOATN_NX \ > > - case RID_FLOAT16: case RID_FLOAT32: case RID_FLOAT64: case RID_FLOAT128: \ > > + CASE_RID_FLOATN: \ > > case RID_FLOAT32X: case RID_FLOAT64X: case RID_FLOAT128X > > > > RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN, > > --- gcc/c-family/c-lex.cc.jj 2022-09-09 12:27:23.138737014 +0200 > > +++ gcc/c-family/c-lex.cc 2022-09-09 18:46:07.271922421 +0200 > > @@ -960,6 +960,10 @@ interpret_float (const cpp_token *token, > > pedwarn (input_location, OPT_Wpedantic, "non-standard suffix on floating constant"); > > > > type = c_common_type_for_mode (mode, 0); > > + /* For Q suffix, prefer float128t_type_node (__float128) type > > + over float128_type_node (_Float128) type if they are distinct. */ > > + if (type == float128_type_node && float128t_type_node) > > + type = float128t_type_node; > > gcc_assert (type); > > } > > else if ((flags & (CPP_N_FLOATN | CPP_N_FLOATNX)) != 0) > > @@ -979,8 +983,17 @@ interpret_float (const cpp_token *token, > > error ("unsupported non-standard suffix on floating constant"); > > return error_mark_node; > > } > > + else if (c_dialect_cxx ()) > > + { > > + if (cxx_dialect < cxx23) > > + pedwarn (input_location, OPT_Wpedantic, > > + "% or % suffix on floating constant only " > > + "available with %<-std=c++2b%> or %<-std=gnu++2b%>", > > + n, n); > > + } > > else > > - pedwarn (input_location, OPT_Wpedantic, "non-standard suffix on floating constant"); > > + pedwarn (input_location, OPT_Wpedantic, > > + "non-standard suffix on floating constant"); > > } > > else if ((flags & CPP_N_WIDTH) == CPP_N_LARGE) > > type = long_double_type_node; > > @@ -990,7 +1003,10 @@ interpret_float (const cpp_token *token, > > else > > type = double_type_node; > > > > - const_type = excess_precision_type (type); > > + if (c_dialect_cxx ()) > > + const_type = NULL_TREE; > > + else > > + const_type = excess_precision_type (type); > > if (!const_type) > > const_type = type; > > > > --- gcc/cp/cp-tree.h.jj 2022-09-09 12:27:23.170736583 +0200 > > +++ gcc/cp/cp-tree.h 2022-09-10 11:22:11.612598030 +0200 > > @@ -7942,6 +7942,7 @@ extern tree require_complete_type_sfinae > > extern tree complete_type (tree); > > extern tree complete_type_or_else (tree, tree); > > extern tree complete_type_or_maybe_complain (tree, tree, tsubst_flags_t); > > +extern int cp_compare_floating_point_conversion_ranks (tree, tree); > > inline bool type_unknown_p (const_tree); > > enum { ce_derived, ce_type, ce_normal, ce_exact }; > > extern bool comp_except_specs (const_tree, const_tree, int); > > @@ -8682,6 +8683,18 @@ struct push_access_scope_guard > > } > > }; > > > > +/* True if TYPE is an extended floating-point type. */ > > + > > +inline bool > > +extended_float_type_p (tree type) > > +{ > > + type = TYPE_MAIN_VARIANT (type); > > + for (int i = 0; i < NUM_FLOATN_TYPES; ++i) > > + if (type == FLOATN_TYPE_NODE (i)) > > + return true; > > + return false; > > +} > > + > > #if CHECKING_P > > namespace selftest { > > extern void run_cp_tests (void); > > --- gcc/cp/mangle.cc.jj 2022-09-09 12:27:23.171736570 +0200 > > +++ gcc/cp/mangle.cc 2022-09-09 18:46:07.273922394 +0200 > > @@ -2648,63 +2648,18 @@ write_builtin_type (tree type) > > write_string ("Dd"); > > else if (type == dfloat128_type_node || type == fallback_dfloat128_type) > > write_string ("De"); > > + else if (type == float16_type_node) > > + write_string ("DF16_"); > > + else if (type == float32_type_node) > > + write_string ("DF32_"); > > + else if (type == float64_type_node) > > + write_string ("DF64_"); > > + else if (type == float128_type_node) > > + write_string ("DF128_"); > > else > > gcc_unreachable (); > > break; > > > > - case FIXED_POINT_TYPE: > > - write_string ("DF"); > > - if (GET_MODE_IBIT (TYPE_MODE (type)) > 0) > > - write_unsigned_number (GET_MODE_IBIT (TYPE_MODE (type))); > > - if (type == fract_type_node > > - || type == sat_fract_type_node > > - || type == accum_type_node > > - || type == sat_accum_type_node) > > - write_char ('i'); > > - else if (type == unsigned_fract_type_node > > - || type == sat_unsigned_fract_type_node > > - || type == unsigned_accum_type_node > > - || type == sat_unsigned_accum_type_node) > > - write_char ('j'); > > - else if (type == short_fract_type_node > > - || type == sat_short_fract_type_node > > - || type == short_accum_type_node > > - || type == sat_short_accum_type_node) > > - write_char ('s'); > > - else if (type == unsigned_short_fract_type_node > > - || type == sat_unsigned_short_fract_type_node > > - || type == unsigned_short_accum_type_node > > - || type == sat_unsigned_short_accum_type_node) > > - write_char ('t'); > > - else if (type == long_fract_type_node > > - || type == sat_long_fract_type_node > > - || type == long_accum_type_node > > - || type == sat_long_accum_type_node) > > - write_char ('l'); > > - else if (type == unsigned_long_fract_type_node > > - || type == sat_unsigned_long_fract_type_node > > - || type == unsigned_long_accum_type_node > > - || type == sat_unsigned_long_accum_type_node) > > - write_char ('m'); > > - else if (type == long_long_fract_type_node > > - || type == sat_long_long_fract_type_node > > - || type == long_long_accum_type_node > > - || type == sat_long_long_accum_type_node) > > - write_char ('x'); > > - else if (type == unsigned_long_long_fract_type_node > > - || type == sat_unsigned_long_long_fract_type_node > > - || type == unsigned_long_long_accum_type_node > > - || type == sat_unsigned_long_long_accum_type_node) > > - write_char ('y'); > > - else > > - sorry ("mangling unknown fixed point type"); > > - write_unsigned_number (GET_MODE_FBIT (TYPE_MODE (type))); > > - if (TYPE_SATURATING (type)) > > - write_char ('s'); > > - else > > - write_char ('n'); > > - break; > > - > > default: > > gcc_unreachable (); > > } > > --- gcc/cp/typeck2.cc.jj 2022-09-09 12:27:23.179736463 +0200 > > +++ gcc/cp/typeck2.cc 2022-09-09 18:46:07.273922394 +0200 > > @@ -1010,12 +1010,25 @@ check_narrowing (tree type, tree init, t > > else if (TREE_CODE (ftype) == REAL_TYPE > > && TREE_CODE (type) == REAL_TYPE) > > { > > - if ((same_type_p (ftype, long_double_type_node) > > - && (same_type_p (type, double_type_node) > > - || same_type_p (type, float_type_node))) > > - || (same_type_p (ftype, double_type_node) > > - && same_type_p (type, float_type_node)) > > - || (TYPE_PRECISION (type) < TYPE_PRECISION (ftype))) > > + if ((extended_float_type_p (ftype) || extended_float_type_p (type)) > > + ? /* "from a floating-point type T to another floating-point type > > + whose floating-point conversion rank is neither greater than > > + nor equal to that of T". > > + So, it is ok if > > + cp_compare_floating_point_conversion_ranks (ftype, type) > > + returns -2 (type has greater conversion rank than ftype) > > + or [-1..1] (type has equal conversion rank as ftype, possibly > > + different subrank. Only do this if at least one of the > > + types is extended floating-point type, otherwise keep doing > > + what we did before (for the sake of non-standard > > + backend types). */ > > + cp_compare_floating_point_conversion_ranks (ftype, type) >= 2 > > + : ((same_type_p (ftype, long_double_type_node) > > + && (same_type_p (type, double_type_node) > > + || same_type_p (type, float_type_node))) > > + || (same_type_p (ftype, double_type_node) > > + && same_type_p (type, float_type_node)) > > + || (TYPE_PRECISION (type) < TYPE_PRECISION (ftype)))) > > { > > if (TREE_CODE (init) == REAL_CST) > > { > > --- gcc/cp/parser.cc.jj 2022-09-09 12:27:23.177736489 +0200 > > +++ gcc/cp/parser.cc 2022-09-09 18:46:07.278922327 +0200 > > @@ -1129,6 +1129,7 @@ cp_keyword_starts_decl_specifier_p (enum > > case RID_UNSIGNED: > > case RID_FLOAT: > > case RID_DOUBLE: > > + CASE_RID_FLOATN: > > case RID_VOID: > > /* CV qualifiers. */ > > case RID_CONST: > > @@ -19706,6 +19707,12 @@ cp_parser_simple_type_specifier (cp_pars > > case RID_DOUBLE: > > type = double_type_node; > > break; > > + CASE_RID_FLOATN: > > + type = FLOATN_TYPE_NODE (token->keyword - RID_FLOATN_NX_FIRST); > > + if (type == NULL_TREE) > > + error ("%<_Float%d%> is not supported on this target", > > + floatn_nx_types[token->keyword - RID_FLOATN_NX_FIRST].n); > > + break; > > case RID_VOID: > > type = void_type_node; > > break; > > --- gcc/cp/typeck.cc.jj 2022-09-09 12:27:23.179736463 +0200 > > +++ gcc/cp/typeck.cc 2022-09-09 19:54:17.360423639 +0200 > > @@ -272,6 +272,116 @@ merge_type_attributes_from (tree type, t > > return cp_build_type_attribute_variant (type, attrs); > > } > > > > +/* Compare floating point conversion ranks and subranks of T1 and T2 > > + types. If T1 and T2 have unordered conversion ranks, return 3. > > + If T1 has greater conversion rank than T2, return 2. > > + If T2 has greater conversion rank than T1, return -2. > > + If T1 has equal conversion rank as T2, return -1, 0 or 1 depending > > + on if T1 has smaller, equal or greater conversion subrank than > > + T2. */ > > + > > +int > > +cp_compare_floating_point_conversion_ranks (tree t1, tree t2) > > +{ > > + tree mv1 = TYPE_MAIN_VARIANT (t1); > > + tree mv2 = TYPE_MAIN_VARIANT (t2); > > + bool extended1 = false; > > + bool extended2 = false; > > + > > + if (mv1 == mv2) > > + return 0; > > + > > + for (int i = 0; i < NUM_FLOATN_TYPES; ++i) > > + { > > + if (mv1 == FLOATN_TYPE_NODE (i)) > > + extended1 = true; > > + if (mv2 == FLOATN_TYPE_NODE (i)) > > + extended2 = true; > > + } > > + if (extended2 && !extended1) > > + { > > + int ret = cp_compare_floating_point_conversion_ranks (t2, t1); > > + return ret == 3 ? 3 : -ret; > > + } > > + > > + const struct real_format *fmt1 = REAL_MODE_FORMAT (TYPE_MODE (t1)); > > + const struct real_format *fmt2 = REAL_MODE_FORMAT (TYPE_MODE (t2)); > > + gcc_assert (fmt1->b == 2 && fmt2->b == 2); > > + /* For {ibm,mips}_extended_format formats, the type has variable > > + precision up to ~2150 bits when the first double is around maximum > > + representable double and second double is subnormal minimum. > > + So, e.g. for __ibm128 vs. std::float128_t, they have unordered > > + ranks. */ > > + int p1 = (MODE_COMPOSITE_P (TYPE_MODE (t1)) > > + ? fmt1->emax - fmt1->emin + fmt1->p - 1 : fmt1->p); > > + int p2 = (MODE_COMPOSITE_P (TYPE_MODE (t2)) > > + ? fmt2->emax - fmt2->emin + fmt2->p - 1 : fmt2->p); > > + /* The rank of a floating point type T is greater than the rank of > > + any floating-point type whose set of values is a proper subset > > + of the set of values of T. */ > > + if ((p1 > p2 && fmt1->emax >= fmt2->emax) > > + || (p1 == p2 && fmt1->emax > fmt2->emax)) > > + return 2; > > + if ((p1 < p2 && fmt1->emax <= fmt2->emax) > > + || (p1 == p2 && fmt1->emax < fmt2->emax)) > > + return -2; > > + if ((p1 > p2 && fmt1->emax < fmt2->emax) > > + || (p1 < p2 && fmt1->emax > fmt2->emax)) > > + return 3; > > + if (!extended1 && !extended2) > > + { > > + /* The rank of long double is greater than the rank of double, which > > + is greater than the rank of float. */ > > + if (t1 == long_double_type_node) > > + return 2; > > + else if (t2 == long_double_type_node) > > + return -2; > > + if (t1 == double_type_node) > > + return 2; > > + else if (t2 == double_type_node) > > + return -2; > > + if (t1 == float_type_node) > > + return 2; > > + else if (t2 == float_type_node) > > + return -2; > > + return 0; > > + } > > + /* Two extended floating-point types with the same set of values have equal > > + ranks. */ > > + if (extended1 && extended2) > > + /* We shouldn't have multiple different extended floating-point types > > + with the same set of values. */ > > + gcc_unreachable (); > > + > > + tree *p; > > + int cnt = 0; > > + for (p = &float_type_node; p <= &long_double_type_node; ++p) > > + { > > + const struct real_format *fmt3 = REAL_MODE_FORMAT (TYPE_MODE (*p)); > > + gcc_assert (fmt3->b == 2); > > + int p3 = (MODE_COMPOSITE_P (TYPE_MODE (*p)) > > + ? fmt3->emax - fmt3->emin + fmt3->p - 1 : fmt3->p); > > + if (p1 == p3 && fmt1->emax == fmt3->emax) > > + ++cnt; > > + } > > + /* An extended floating-point type with the same set of values > > + as exactly one cv-unqualified standard floating-point type > > + has a rank equal to the rank of that standard floating-point > > + type. > > + > > + An extended floating-point type with the same set of values > > + as more than one cv-unqualified standard floating-point type > > + has a rank equal to the rank of double. > > + > > + Thus, if the latter is true and t2 is long double, t2 > > + has higher rank. */ > > + if (cnt > 1 && mv2 == long_double_type_node) > > + return -2; > > + /* Otherwise, they have equal rank, but extended types > > + (other than std::bfloat16_t) have higher subrank. */ > > + return 1; > > +} > > + > > /* Return the common type for two arithmetic types T1 and T2 under the > > usual arithmetic conversions. The default conversions have already > > been applied, and enumerated types converted to their compatible > > @@ -342,6 +452,23 @@ cp_common_type (tree t1, tree t2) > > if (code2 == REAL_TYPE && code1 != REAL_TYPE) > > return build_type_attribute_variant (t2, attributes); > > > > + if (code1 == REAL_TYPE > > + && (extended_float_type_p (t1) || extended_float_type_p (t2))) > > + { > > + tree mv1 = TYPE_MAIN_VARIANT (t1); > > + tree mv2 = TYPE_MAIN_VARIANT (t2); > > + if (mv1 == mv2) > > + return build_type_attribute_variant (t1, attributes); > > + > > + int cmpret = cp_compare_floating_point_conversion_ranks (mv1, mv2); > > + if (cmpret == 3) > > + return error_mark_node; > > + else if (cmpret >= 0) > > + return build_type_attribute_variant (t1, attributes); > > + else > > + return build_type_attribute_variant (t2, attributes); > > + } > > + > > /* Both real or both integers; use the one with greater precision. */ > > if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2)) > > return build_type_attribute_variant (t1, attributes); > > @@ -5041,7 +5168,20 @@ cp_build_binary_op (const op_location_t > > = targetm.invalid_binary_op (code, type0, type1))) > > { > > if (complain & tf_error) > > - error (invalid_op_diag); > > + { > > + if (code0 == REAL_TYPE > > + && code1 == REAL_TYPE > > + && (extended_float_type_p (type0) > > + || extended_float_type_p (type1)) > > + && cp_compare_floating_point_conversion_ranks (type0, > > + type1) == 3) > > + { > > + rich_location richloc (line_table, location); > > + binary_op_error (&richloc, code, type0, type1); > > + } > > + else > > + error (invalid_op_diag); > > + } > > return error_mark_node; > > } > > > > @@ -5911,6 +6051,19 @@ cp_build_binary_op (const op_location_t > > && (shorten || common || short_compare)) > > { > > result_type = cp_common_type (type0, type1); > > + if (result_type == error_mark_node > > + && code0 == REAL_TYPE > > + && code1 == REAL_TYPE > > + && (extended_float_type_p (type0) || extended_float_type_p (type1)) > > + && cp_compare_floating_point_conversion_ranks (type0, type1) == 3) > > + { > > + if (complain & tf_error) > > + { > > + rich_location richloc (line_table, location); > > + binary_op_error (&richloc, code, type0, type1); > > + } > > + return error_mark_node; > > + } > > if (complain & tf_warning) > > { > > do_warn_double_promotion (result_type, type0, type1, > > --- gcc/cp/call.cc.jj 2022-09-09 12:27:23.169736597 +0200 > > +++ gcc/cp/call.cc 2022-09-10 11:14:41.361732371 +0200 > > @@ -1519,6 +1519,22 @@ standard_conversion (tree to, tree from, > > || SCOPED_ENUM_P (from)) > > return NULL; > > > > + /* A prvalue of floating-point type can be converted to a prvalue of > > + another floating-point type with a greater or equal conversion > > + rank ([conv.rank]). A prvalue of standard floating-point type can > > + be converted to a prvalue of another standard floating-point type. > > + For backwards compatibility with handling __float128 and other > > + non-standard floating point types, allow all implicit floating > > + point conversions if neither type is extended floating-point > > + type and if at least one of them is, fail if they have unordered > > + conversion rank or from has higher conversion rank. */ > > + if (fcode == REAL_TYPE > > + && tcode == REAL_TYPE > > + && (extended_float_type_p (from) > > + || extended_float_type_p (to)) > > + && cp_compare_floating_point_conversion_ranks (from, to) >= 2) > > + return NULL; > > + > > /* If we're parsing an enum with no fixed underlying type, we're > > dealing with an incomplete type, which renders the conversion > > ill-formed. */ > > @@ -5842,6 +5858,21 @@ build_conditional_expr (const op_locatio > > /* In this case, there is always a common type. */ > > result_type = type_after_usual_arithmetic_conversions (arg2_type, > > arg3_type); > > + if (result_type == error_mark_node > > + && TREE_CODE (arg2_type) == REAL_TYPE > > + && TREE_CODE (arg3_type) == REAL_TYPE > > + && (extended_float_type_p (arg2_type) > > + || extended_float_type_p (arg3_type)) > > + && cp_compare_floating_point_conversion_ranks (arg2_type, > > + arg3_type) == 3) > > + { > > + if (complain & tf_error) > > + error_at (loc, "operands to % have unordered conversion rank " > > + "of types %qT and %qT", > > + arg2_type, arg3_type); > > + return error_mark_node; > > + } > > + > > if (complain & tf_warning) > > do_warn_double_promotion (result_type, arg2_type, arg3_type, > > "implicit conversion from %qH to %qI to " > > @@ -8531,7 +8562,8 @@ convert_arg_to_ellipsis (tree arg, tsubs > > if (TREE_CODE (arg_type) == REAL_TYPE > > && (TYPE_PRECISION (arg_type) > > < TYPE_PRECISION (double_type_node)) > > - && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (arg_type))) > > + && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (arg_type)) > > + && !extended_float_type_p (arg_type)) > > { > > if ((complain & tf_warning) > > && warn_double_promotion && !c_inhibit_evaluation_warnings) > > @@ -11719,6 +11751,75 @@ compare_ics (conversion *ics1, conversio > > return 1; > > } > > > > + { > > + /* A conversion in either direction between floating-point type FP1 and > > + floating-point type FP2 is better than a conversion in the same > > + direction between FP1 and arithmetic type T3 if > > + - the floating-point conversion rank of FP1 is equal to the rank of > > + FP2, and > > + - T3 is not a floating-point type, or T3 is a floating-point type > > + whose rank is not equal to the rank of FP1, or the floating-point > > + conversion subrank of FP2 is greater than the subrank of T3. */ > > + tree fp1 = from_type1; > > + tree fp2 = to_type1; > > + tree fp3 = from_type2; > > + tree t3 = to_type2; > > + int ret = 1; > > + if (TYPE_MAIN_VARIANT (fp2) == TYPE_MAIN_VARIANT (t3)) > > + { > > + std::swap (fp1, fp2); > > + std::swap (fp3, t3); > > + } > > + if (TYPE_MAIN_VARIANT (fp1) == TYPE_MAIN_VARIANT (fp3) > > + && TREE_CODE (fp1) == REAL_TYPE > > + /* Only apply this rule if at least one of the 3 types is > > + extended floating-point type, otherwise keep them as > > + before for compatibility reasons with types like __float128. > > + float, double and long double alone have different conversion > > + ranks and so when just those 3 types are involved, this > > + rule doesn't trigger. */ > > + && (extended_float_type_p (fp1) > > + || (TREE_CODE (fp2) == REAL_TYPE && extended_float_type_p (fp2)) > > + || (TREE_CODE (t3) == REAL_TYPE && extended_float_type_p (t3)))) > > + { > > + if (TREE_CODE (fp2) != REAL_TYPE) > > + { > > + ret = -ret; > > + std::swap (fp2, t3); > > + } > > + if (TREE_CODE (fp2) == REAL_TYPE) > > + { > > + if (cp_compare_floating_point_conversion_ranks (fp1, fp2) + 1U > > + <= 2U) > > + { > > + /* Conversion ranks of FP1 and FP2 are equal. */ > > + if (TREE_CODE (t3) != REAL_TYPE > > + || (cp_compare_floating_point_conversion_ranks (fp1, t3) > > + + 1U > 2U)) > > + /* FP1 <-> FP2 conversion is better. */ > > + return ret; > > + int c = cp_compare_floating_point_conversion_ranks (fp2, t3); > > + gcc_assert (c + 1U <= 2U); > > + if (c == 1) > > + /* Conversion subrank of FP2 is greater than subrank of T3. > > + FP1 <-> FP2 conversion is better. */ > > + return ret; > > + else if (c == -1) > > + /* Conversion subrank of FP2 is less than subrank of T3. > > + FP1 <-> T3 conversion is better. */ > > + return -ret; > > + } > > + else if (TREE_CODE (t3) == REAL_TYPE > > + && (cp_compare_floating_point_conversion_ranks (fp1, t3) > > + + 1U <= 2U)) > > + /* Conversion ranks of FP1 and FP2 are not equal, conversion > > + ranks of FP1 and T3 are equal. > > + FP1 <-> T3 conversion is better. */ > > + return -ret; > > + } > > + } > > + } > > + > > if (TYPE_PTR_P (from_type1) > > && TYPE_PTR_P (from_type2) > > && TYPE_PTR_P (to_type1) > > --- gcc/testsuite/g++.dg/cpp23/ext-floating1.C.jj 2022-09-09 18:46:07.281922287 +0200 > > +++ gcc/testsuite/g++.dg/cpp23/ext-floating1.C 2022-09-09 18:46:07.281922287 +0200 > > @@ -0,0 +1,248 @@ > > +// P1467R9 - Extended floating-point types and standard names. > > +// { dg-do compile { target c++23 } } > > +// { dg-options "" } > > + > > +#include "ext-floating.h" > > + > > +#ifdef __STRICT_ANSI__ > > +#undef __SIZEOF_FLOAT128__ > > +#endif > > + > > +using namespace std; > > + > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#ifdef __SIZEOF_FLOAT128__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#ifdef __STDCPP_FLOAT16_T__ > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#ifdef __STDCPP_FLOAT32_T__ > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#ifdef __STDCPP_FLOAT64_T__ > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#ifdef __STDCPP_FLOAT128_T__ > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#ifdef __SIZEOF_FLOAT128__ > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +#endif > > +#endif > > +#ifdef __STDCPP_BFLOAT16_T__ > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#if defined(__STDCPP_FLOAT16_T__) && defined(__STDCPP_FLOAT32_T__) > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if defined(__STDCPP_FLOAT16_T__) && defined(__STDCPP_FLOAT64_T__) > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if defined(__STDCPP_FLOAT16_T__) && defined(__STDCPP_FLOAT128_T__) > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__) > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT128_T__) > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if defined(__STDCPP_FLOAT64_T__) && defined(__STDCPP_FLOAT128_T__) > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if defined(__STDCPP_BFLOAT16_T__) && defined(__STDCPP_FLOAT32_T__) > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if defined(__STDCPP_BFLOAT16_T__) && defined(__STDCPP_FLOAT64_T__) > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if defined(__STDCPP_BFLOAT16_T__) && defined(__STDCPP_FLOAT128_T__) > > +static_assert (!is_same::value); > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#ifdef __STDCPP_FLOAT16_T__ > > +#if __FLT_MAX_EXP__ > __FLT16_MAX_EXP__ && __FLT_MANT_DIG__ > __FLT16_MANT_DIG__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if __DBL_MAX_EXP__ > __FLT16_MAX_EXP__ && __DBL_MANT_DIG__ > __FLT16_MANT_DIG__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if __LDBL_MAX_EXP__ > __FLT16_MAX_EXP__ && __LDBL_MANT_DIG__ > __FLT16_MANT_DIG__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#endif > > +#ifdef __STDCPP_FLOAT32_T__ > > +#if __FLT_MAX_EXP__ == __FLT32_MAX_EXP__ && __FLT_MANT_DIG__ == __FLT32_MANT_DIG__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if __DBL_MAX_EXP__ > __FLT32_MAX_EXP__ && __DBL_MANT_DIG__ > __FLT32_MANT_DIG__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if __LDBL_MAX_EXP__ > __FLT32_MAX_EXP__ && __LDBL_MANT_DIG__ > __FLT32_MANT_DIG__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#endif > > +#ifdef __STDCPP_FLOAT64_T__ > > +#if __FLT_MAX_EXP__ < __FLT64_MAX_EXP__ && __FLT_MANT_DIG__ < __FLT64_MANT_DIG__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if __DBL_MAX_EXP__ == __FLT64_MAX_EXP__ && __DBL_MANT_DIG__ == __FLT64_MANT_DIG__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if __LDBL_MAX_EXP__ > __FLT64_MAX_EXP__ && __LDBL_MANT_DIG__ > __FLT64_MANT_DIG__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if __LDBL_MAX_EXP__ == __FLT64_MAX_EXP__ && __LDBL_MANT_DIG__ == __FLT64_MANT_DIG__ \ > > + && __DBL_MAX_EXP__ == __FLT64_MAX_EXP__ && __DBL_MANT_DIG__ == __FLT64_MANT_DIG__ > > +// An extended floating-point type with the same set of values as more than one > > +// cv-unqualified standard floating-point type has a rank equal to the rank of > > +// double. > > +// Then long double will have higher rank than float64_t. > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#endif > > +#ifdef __STDCPP_FLOAT128_T__ > > +#if __FLT_MAX_EXP__ < __FLT128_MAX_EXP__ && __FLT_MANT_DIG__ < __FLT128_MANT_DIG__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if __DBL_MAX_EXP__ < __FLT128_MAX_EXP__ && __DBL_MANT_DIG__ < __FLT128_MANT_DIG__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if __LDBL_MAX_EXP__ <= __FLT128_MAX_EXP__ && __LDBL_MANT_DIG__ <= __FLT128_MANT_DIG__ \ > > + && __LDBL_MANT_DIG__ != 106 // IBM extended long double and IEEE quad are unordered. > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#ifdef __SIZEOF_FLOAT128__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#endif > > +#ifdef __STDCPP_BFLOAT16_T__ > > +#if __FLT_MAX_EXP__ > __BFLT16_MAX_EXP__ && __FLT_MANT_DIG__ > __BFLT16_MANT_DIG__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if __DBL_MAX_EXP__ > __BFLT16_MAX_EXP__ && __DBL_MANT_DIG__ > __BFLT16_MANT_DIG__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#if __LDBL_MAX_EXP__ > __BFLT16_MAX_EXP__ && __LDBL_MANT_DIG__ > __BFLT16_MANT_DIG__ > > +static_assert (is_same::value); > > +static_assert (is_same::value); > > +#endif > > +#endif > > + > > +void foo (float) {} > > +void foo (double) {} > > +void foo (long double) {} > > +#ifdef __STDCPP_FLOAT16_T__ > > +void foo (float16_t) {} > > +#endif > > +#ifdef __STDCPP_FLOAT32_T__ > > +void foo (float32_t) {} > > +#endif > > +#ifdef __STDCPP_FLOAT64_T__ > > +void foo (float64_t) {} > > +#endif > > +#ifdef __STDCPP_FLOAT128_T__ > > +void foo (float128_t) {} > > +#endif > > +#ifdef __STDCPP_BFLOAT16_T__ > > +void foo (bfloat16_t) {} > > +#endif > > --- gcc/testsuite/g++.dg/cpp23/ext-floating2.C.jj 2022-09-09 18:46:07.281922287 +0200 > > +++ gcc/testsuite/g++.dg/cpp23/ext-floating2.C 2022-09-09 18:46:07.281922287 +0200 > > @@ -0,0 +1,157 @@ > > +// P1467R9 - Extended floating-point types and standard names. > > +// { dg-do compile { target c++23 } } > > +// { dg-options "" } > > + > > +#include "ext-floating.h" > > + > > +#ifdef __STRICT_ANSI__ > > +#undef __SIZEOF_FLOAT128__ > > +#endif > > + > > +using namespace std; > > + > > +float fa = 1.0f; > > +float fb = (float) 1.0f; > > +float fc = 1.0; > > +float fd = (float) 1.0; > > +float fe = 1.0L; > > +float ff = (float) 1.0L; > > +#ifdef __SIZEOF_FLOAT128__ > > +float fg = 1.0Q; > > +float fh = (float) 1.0Q; > > +#endif > > +double da = 1.0f; > > +double db = (double) 1.0f; > > +double dc = 1.0; > > +double dd = (double) 1.0; > > +double de = 1.0L; > > +double df = (double) 1.0L; > > +#ifdef __SIZEOF_FLOAT128__ > > +double dg = 1.0Q; > > +double dh = (double) 1.0Q; > > +#endif > > +long double lda = 1.0f; > > +long double ldb = (long double) 1.0f; > > +long double ldc = 1.0; > > +long double ldd = (long double) 1.0; > > +long double lde = 1.0L; > > +long double ldf = (long double) 1.0L; > > +#ifdef __SIZEOF_FLOAT128__ > > +long double ldg = 1.0Q; > > +long double ldh = (long double) 1.0Q; > > +__float128 qa = 1.0f; > > +__float128 qb = (__float128) 1.0f; > > +__float128 qc = 1.0; > > +__float128 qd = (__float128) 1.0; > > +__float128 qe = 1.0L; > > +__float128 qf = (__float128) 1.0L; > > +__float128 qg = 1.0Q; > > +__float128 qh = (__float128) 1.0Q; > > +#endif > > +#ifdef __STDCPP_FLOAT16_T__ > > +float16_t f16a = 1.0F16; > > +float16_t f16b = (float16_t) 1.0F16; > > +#ifdef __STDCPP_FLOAT32_T__ > > +float16_t f16c = 1.0F32; // { dg-error "cannot convert '_Float32' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target { float16 && float32 } } } > > +float16_t f16d = (float16_t) 1.0F32; > > +#endif > > +#ifdef __STDCPP_FLOAT64_T__ > > +float16_t f16e = 1.0F64; // { dg-error "cannot convert '_Float64' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target { float16 && float64 } } } > > +float16_t f16f = (float16_t) 1.0F64; > > +#endif > > +#ifdef __STDCPP_FLOAT128_T__ > > +float16_t f16g = 1.0F128; // { dg-error "cannot convert '_Float128' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target { float16 && float128 } } } > > +float16_t f16h = (float16_t) 1.0F128; > > +#endif > > +float16_t f16j = (float16_t) 1.0f; > > +float16_t f16l = (float16_t) 1.0; > > +float16_t f16n = (float16_t) 1.0L; > > +#ifdef __SIZEOF_FLOAT128__ > > +float16_t f16p = (float16_t) 1.0Q; > > +#endif > > +#endif > > +#ifdef __STDCPP_FLOAT32_T__ > > +#ifdef __STDCPP_FLOAT16_T__ > > +float32_t f32a = 1.0F16; > > +float32_t f32b = (float32_t) 1.0F16; > > +#endif > > +float32_t f32c = 1.0F32; > > +float32_t f32d = (float32_t) 1.0F32; > > +#ifdef __STDCPP_FLOAT64_T__ > > +float32_t f32e = 1.0F64; // { dg-error "cannot convert '_Float64' to 'std::float32_t' \\\{aka '_Float32'\\\} in initialization" "" { target { float32 && float64 } } } > > +float32_t f32f = (float32_t) 1.0F64; > > +#endif > > +#ifdef __STDCPP_FLOAT128_T__ > > +float32_t f32g = 1.0F128; // { dg-error "cannot convert '_Float128' to 'std::float32_t' \\\{aka '_Float32'\\\} in initialization" "" { target { float32 && float128 } } } > > +float32_t f32h = (float32_t) 1.0F128; > > +#endif > > +#if __FLT_MAX_EXP__ <= __FLT32_MAX_EXP__ && __FLT_MANT_DIG__ <= __FLT32_MANT_DIG__ > > +float32_t f32i = 1.0f; > > +#endif > > +float32_t f32j = (float32_t) 1.0f; > > +float32_t f32l = (float32_t) 1.0; > > +float32_t f32n = (float32_t) 1.0L; > > +#ifdef __SIZEOF_FLOAT128__ > > +float32_t f32p = (float32_t) 1.0Q; > > +#endif > > +#endif > > +#ifdef __STDCPP_FLOAT64_T__ > > +#ifdef __STDCPP_FLOAT16_T__ > > +float64_t f64a = 1.0F16; > > +float64_t f64b = (float64_t) 1.0F16; > > +#endif > > +#ifdef __STDCPP_FLOAT32_T__ > > +float64_t f64c = 1.0F32; > > +float64_t f64d = (float64_t) 1.0F32; > > +#endif > > +float64_t f64e = 1.0F64; > > +float64_t f64f = (float64_t) 1.0F64; > > +#ifdef __STDCPP_FLOAT128_T__ > > +float64_t f64g = 1.0F128; // { dg-error "cannot convert '_Float128' to 'std::float64_t' \\\{aka '_Float64'\\\} in initialization" "" { target { float64 && float128 } } } > > +float64_t f64h = (float64_t) 1.0F128; > > +#endif > > +#if __FLT_MAX_EXP__ <= __FLT64_MAX_EXP__ && __FLT_MANT_DIG__ <= __FLT64_MANT_DIG__ > > +float64_t f64i = 1.0f; > > +#endif > > +float64_t f64j = (float64_t) 1.0f; > > +#if __DBL_MAX_EXP__ <= __FLT64_MAX_EXP__ && __DBL_MANT_DIG__ <= __FLT64_MANT_DIG__ > > +float64_t f64k = 1.0; > > +#endif > > +float64_t f64l = (float64_t) 1.0; > > +float64_t f64n = (float64_t) 1.0L; > > +#ifdef __SIZEOF_FLOAT128__ > > +float64_t f64p = (float64_t) 1.0Q; > > +#endif > > +#endif > > +#ifdef __STDCPP_FLOAT128_T__ > > +#ifdef __STDCPP_FLOAT16_T__ > > +float128_t f128a = 1.0F16; > > +float128_t f128b = (float128_t) 1.0F16; > > +#endif > > +#ifdef __STDCPP_FLOAT32_T__ > > +float128_t f128c = 1.0F32; > > +float128_t f128d = (float128_t) 1.0F32; > > +#endif > > +#ifdef __STDCPP_FLOAT64_T__ > > +float128_t f128e = 1.0F64; > > +float128_t f128f = (float128_t) 1.0F64; > > +#endif > > +float128_t f128g = 1.0F128; > > +float128_t f128h = (float128_t) 1.0F128; > > +#if __FLT_MAX_EXP__ <= __FLT128_MAX_EXP__ && __FLT_MANT_DIG__ <= __FLT128_MANT_DIG__ > > +float128_t f128i = 1.0f; > > +#endif > > +float128_t f128j = (float128_t) 1.0f; > > +#if __DBL_MAX_EXP__ <= __FLT128_MAX_EXP__ && __DBL_MANT_DIG__ <= __FLT128_MANT_DIG__ > > +float128_t f128k = 1.0; > > +#endif > > +float128_t f128l = (float128_t) 1.0; > > +#if __LDBL_MAX_EXP__ <= __FLT128_MAX_EXP__ && __LDBL_MANT_DIG__ <= __FLT128_MANT_DIG__ && __LDBL_MANT_DIG__ != 106 > > +float128_t f128m = 1.0L; > > +#endif > > +float128_t f128n = (float128_t) 1.0L; > > +#ifdef __SIZEOF_FLOAT128__ > > +float128_t f128o = 1.0Q; > > +float128_t f128p = (float128_t) 1.0Q; > > +#endif > > +#endif > > --- gcc/testsuite/g++.dg/cpp23/ext-floating3.C.jj 2022-09-09 18:46:07.281922287 +0200 > > +++ gcc/testsuite/g++.dg/cpp23/ext-floating3.C 2022-09-10 10:21:25.748210213 +0200 > > @@ -0,0 +1,128 @@ > > +// P1467R9 - Extended floating-point types and standard names. > > +// Variant of ext-floating2.C test with x86 specific assumptions > > +// about float, double, long double and existence of __float128. > > +// And some further tests. > > +// { dg-do compile { target { c++23 && { i?86-*-linux* x86_64-*-linux* } } } } > > +// { dg-options "" } > > + > > +#include "ext-floating.h" > > + > > +#if !defined(__STDCPP_FLOAT32_T__) \ > > + || !defined(__STDCPP_FLOAT64_T__) || !defined(__STDCPP_FLOAT128_T__) \ > > + || __FLT_MAX_EXP__ != __FLT32_MAX_EXP__ || __FLT_MANT_DIG__ != __FLT32_MANT_DIG__ \ > > + || __DBL_MAX_EXP__ != __FLT64_MAX_EXP__ || __DBL_MANT_DIG__ != __FLT64_MANT_DIG__ \ > > + || __LDBL_MAX_EXP__ != __FLT128_MAX_EXP__ || __LDBL_MANT_DIG__ >= __FLT128_MANT_DIG__ \ > > + || !defined(__SIZEOF_FLOAT128__) > > +#error Unexpected set of floating point types > > +#endif > > + > > +using namespace std; > > + > > +#ifdef __STDCPP_FLOAT16_T__ > > +float16_t f16i = 1.0f; // { dg-error "cannot convert 'float' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target float16 } } > > +float16_t f16k = 1.0; // { dg-error "cannot convert 'double' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target float16 } } > > +float16_t f16m = 1.0L; // { dg-error "cannot convert 'long double' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target float16 } } > > +float16_t f16o = 1.0Q; // { dg-error "cannot convert '__float128' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target float16 } } > > +#endif > > +float32_t f32i = 1.0f; > > +float32_t f32k = 1.0; // { dg-error "cannot convert 'double' to 'std::float32_t' \\\{aka '_Float32'\\\} in initialization" } > > +float32_t f32m = 1.0L; // { dg-error "cannot convert 'long double' to 'std::float32_t' \\\{aka '_Float32'\\\} in initialization" } > > +float32_t f32o = 1.0Q; // { dg-error "cannot convert '__float128' to 'std::float32_t' \\\{aka '_Float32'\\\} in initialization" } > > +float64_t f64i = 1.0f; > > +float64_t f64k = 1.0; > > +float64_t f64m = 1.0L; // { dg-error "cannot convert 'long double' to 'std::float64_t' \\\{aka '_Float64'\\\} in initialization" } > > +float64_t f64o = 1.0Q; // { dg-error "cannot convert '__float128' to 'std::float64_t' \\\{aka '_Float64'\\\} in initialization" } > > +float128_t f128i = 1.0f; > > +float128_t f128k = 1.0; > > +float128_t f128m = 1.0L; > > +float128_t f128o = 1.0Q; > > + > > +#ifdef __STDCPP_FLOAT16_T__ > > +constexpr float16_t f16x = 1.0F16; > > +#endif > > +constexpr float32_t f32x = 2.0F32; > > +constexpr float64_t f64x = 3.0F64; > > +constexpr float128_t f128x = 4.0F128; > > +constexpr float fx = 5.0f; > > +constexpr double dx = 6.0; > > +constexpr long double ldx = 7.0L; > > + > > +constexpr int foo (float32_t) { return 1; } > > +constexpr int foo (float64_t) { return 2; } > > +constexpr int bar (float) { return 3; } > > +constexpr int bar (double) { return 4; } > > +constexpr int bar (long double) { return 5; } > > +constexpr int baz (float32_t) { return 6; } > > +constexpr int baz (float64_t) { return 7; } > > +constexpr int baz (float128_t) { return 8; } > > +constexpr int qux (float64_t) { return 9; } > > +constexpr int qux (float32_t) { return 10; } > > +constexpr int fred (long double) { return 11; } > > +constexpr int fred (double) { return 12; } > > +constexpr int fred (float) { return 13; } > > +constexpr int thud (float128_t) { return 14; } > > +constexpr int thud (float64_t) { return 15; } > > +constexpr int thud (float32_t) { return 16; } > > +struct S { > > + constexpr operator float32_t () const { return 1.0f32; } > > + constexpr operator float64_t () const { return 2.0f64; } > > +}; > > +struct T { > > + constexpr operator float64_t () const { return 3.0f64; } > > + constexpr operator float32_t () const { return 4.0f32; } > > +}; > > + > > +void > > +test (S s, T t) > > +{ > > +#ifdef __STDCPP_FLOAT16_T__ > > + foo (float16_t (1.0)); // { dg-error "call of overloaded 'foo\\\(std::float16_t\\\)' is ambiguous" "" { target float16 } } > > +#endif > > + static_assert (foo (float (2.0)) == 1); > > + static_assert (foo (double (3.0)) == 2); > > + constexpr double x (s); > > + static_assert (x == 2.0); > > +#ifdef __STDCPP_FLOAT16_T__ > > + bar (f16x); // { dg-error "call of overloaded 'bar\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } } > > +#endif > > + static_assert (bar (f32x) == 3); > > + static_assert (bar (f64x) == 4); > > + bar (f128x); // { dg-error "no matching function for call to 'bar\\\(const std::float128_t\\\&\\\)'" } > > + static_assert (bar (fx) == 3); > > + static_assert (bar (dx) == 4); > > + static_assert (bar (ldx) == 5); > > +#ifdef __STDCPP_FLOAT16_T__ > > + baz (f16x); // { dg-error "call of overloaded 'baz\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } } > > +#endif > > + static_assert (baz (f32x) == 6); > > + static_assert (baz (f64x) == 7); > > + static_assert (baz (f128x) == 8); > > + static_assert (baz (fx) == 6); > > + static_assert (baz (dx) == 7); > > + static_assert (baz (ldx) == 8); > > +#ifdef __STDCPP_FLOAT16_T__ > > + qux (float16_t (1.0)); // { dg-error "call of overloaded 'qux\\\(std::float16_t\\\)' is ambiguous" "" { target float16 } } > > +#endif > > + static_assert (qux (float (2.0)) == 10); > > + static_assert (qux (double (3.0)) == 9); > > + constexpr double y (t); > > + static_assert (y == 3.0); > > +#ifdef __STDCPP_FLOAT16_T__ > > + fred (f16x); // { dg-error "call of overloaded 'fred\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } } > > +#endif > > + static_assert (fred (f32x) == 13); > > + static_assert (fred (f64x) == 12); > > + fred (f128x); // { dg-error "no matching function for call to 'fred\\\(const std::float128_t\\\&\\\)'" } > > + static_assert (fred (fx) == 13); > > + static_assert (fred (dx) == 12); > > + static_assert (fred (ldx) == 11); > > +#ifdef __STDCPP_FLOAT16_T__ > > + thud (f16x); // { dg-error "call of overloaded 'thud\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } } > > +#endif > > + static_assert (thud (f32x) == 16); > > + static_assert (thud (f64x) == 15); > > + static_assert (thud (f128x) == 14); > > + static_assert (thud (fx) == 16); > > + static_assert (thud (dx) == 15); > > + static_assert (thud (ldx) == 14); > > +} > > --- gcc/testsuite/g++.dg/cpp23/ext-floating4.C.jj 2022-09-09 18:48:11.979261440 +0200 > > +++ gcc/testsuite/g++.dg/cpp23/ext-floating4.C 2022-09-10 10:55:24.105457186 +0200 > > @@ -0,0 +1,126 @@ > > +// P1467R9 - Extended floating-point types and standard names. > > +// Variant of ext-floating3.C test with different specific assumptions > > +// about float, double, long double. > > +// float, double and long double are assumed to be IEEE 754 single, double > > +// and quad. > > +// { dg-do compile { target { c++23 && { aarch64*-*-* powerpc64le*-*-linux* riscv*-*-* s390*-*-* sparc*-*-linux* } } } } > > +// { dg-options "" } > > +// { dg-additional-options "-mlong-double-128" { target s390*-*-* sparc*-*-linux* } } > > +// { dg-additional-options "-mvsx -mfloat128 -mlong-double-128 -mabi=ieeelongdouble -Wno-psabi" { target powerpc64le*-*-linux* } } > > + > > +#include "ext-floating.h" > > + > > +#if !defined(__STDCPP_FLOAT32_T__) \ > > + || !defined(__STDCPP_FLOAT64_T__) || !defined(__STDCPP_FLOAT128_T__) \ > > + || __FLT_MAX_EXP__ != __FLT32_MAX_EXP__ || __FLT_MANT_DIG__ != __FLT32_MANT_DIG__ \ > > + || __DBL_MAX_EXP__ != __FLT64_MAX_EXP__ || __DBL_MANT_DIG__ != __FLT64_MANT_DIG__ \ > > + || __LDBL_MAX_EXP__ != __FLT128_MAX_EXP__ || __LDBL_MANT_DIG__ != __FLT128_MANT_DIG__ > > +#error Unexpected set of floating point types > > +#endif > > + > > +using namespace std; > > + > > +#ifdef __STDCPP_FLOAT16_T__ > > +float16_t f16i = 1.0f; // { dg-error "cannot convert 'float' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target float16 } } > > +float16_t f16k = 1.0; // { dg-error "cannot convert 'double' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target float16 } } > > +float16_t f16m = 1.0L; // { dg-error "cannot convert 'long double' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target float16 } } > > +#endif > > +float32_t f32i = 1.0f; > > +float32_t f32k = 1.0; // { dg-error "cannot convert 'double' to 'std::float32_t' \\\{aka '_Float32'\\\} in initialization" } > > +float32_t f32m = 1.0L; // { dg-error "cannot convert 'long double' to 'std::float32_t' \\\{aka '_Float32'\\\} in initialization" } > > +float64_t f64i = 1.0f; > > +float64_t f64k = 1.0; > > +float64_t f64m = 1.0L; // { dg-error "cannot convert 'long double' to 'std::float64_t' \\\{aka '_Float64'\\\} in initialization" } > > +float128_t f128i = 1.0f; > > +float128_t f128k = 1.0; > > +float128_t f128m = 1.0L; > > + > > +#ifdef __STDCPP_FLOAT16_T__ > > +constexpr float16_t f16x = 1.0F16; > > +#endif > > +constexpr float32_t f32x = 2.0F32; > > +constexpr float64_t f64x = 3.0F64; > > +constexpr float128_t f128x = 4.0F128; > > +constexpr float fx = 5.0f; > > +constexpr double dx = 6.0; > > +constexpr long double ldx = 7.0L; > > + > > +constexpr int foo (float32_t) { return 1; } > > +constexpr int foo (float64_t) { return 2; } > > +constexpr int bar (float) { return 3; } > > +constexpr int bar (double) { return 4; } > > +constexpr int bar (long double) { return 5; } > > +constexpr int baz (float32_t) { return 6; } > > +constexpr int baz (float64_t) { return 7; } > > +constexpr int baz (float128_t) { return 8; } > > +constexpr int qux (float64_t) { return 9; } > > +constexpr int qux (float32_t) { return 10; } > > +constexpr int fred (long double) { return 11; } > > +constexpr int fred (double) { return 12; } > > +constexpr int fred (float) { return 13; } > > +constexpr int thud (float128_t) { return 14; } > > +constexpr int thud (float64_t) { return 15; } > > +constexpr int thud (float32_t) { return 16; } > > +struct S { > > + constexpr operator float32_t () const { return 1.0f32; } > > + constexpr operator float64_t () const { return 2.0f64; } > > +}; > > +struct T { > > + constexpr operator float64_t () const { return 3.0f64; } > > + constexpr operator float32_t () const { return 4.0f32; } > > +}; > > + > > +void > > +test (S s, T t) > > +{ > > +#ifdef __STDCPP_FLOAT16_T__ > > + foo (float16_t (1.0)); // { dg-error "call of overloaded 'foo\\\(std::float16_t\\\)' is ambiguous" "" { target float16 } } > > +#endif > > + static_assert (foo (float (2.0)) == 1); > > + static_assert (foo (double (3.0)) == 2); > > + constexpr double x (s); > > + static_assert (x == 2.0); > > +#ifdef __STDCPP_FLOAT16_T__ > > + bar (f16x); // { dg-error "call of overloaded 'bar\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } } > > +#endif > > + static_assert (bar (f32x) == 3); > > + static_assert (bar (f64x) == 4); > > + static_assert (bar (f128x) == 5); > > + static_assert (bar (fx) == 3); > > + static_assert (bar (dx) == 4); > > + static_assert (bar (ldx) == 5); > > +#ifdef __STDCPP_FLOAT16_T__ > > + baz (f16x); // { dg-error "call of overloaded 'baz\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } } > > +#endif > > + static_assert (baz (f32x) == 6); > > + static_assert (baz (f64x) == 7); > > + static_assert (baz (f128x) == 8); > > + static_assert (baz (fx) == 6); > > + static_assert (baz (dx) == 7); > > + static_assert (baz (ldx) == 8); > > +#ifdef __STDCPP_FLOAT16_T__ > > + qux (float16_t (1.0)); // { dg-error "call of overloaded 'qux\\\(std::float16_t\\\)' is ambiguous" "" { target float16 } } > > +#endif > > + static_assert (qux (float (2.0)) == 10); > > + static_assert (qux (double (3.0)) == 9); > > + constexpr double y (t); > > + static_assert (y == 3.0); > > +#ifdef __STDCPP_FLOAT16_T__ > > + fred (f16x); // { dg-error "call of overloaded 'fred\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } } > > +#endif > > + static_assert (fred (f32x) == 13); > > + static_assert (fred (f64x) == 12); > > + static_assert (fred (f128x) == 11); > > + static_assert (fred (fx) == 13); > > + static_assert (fred (dx) == 12); > > + static_assert (fred (ldx) == 11); > > +#ifdef __STDCPP_FLOAT16_T__ > > + thud (f16x); // { dg-error "call of overloaded 'thud\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } } > > +#endif > > + static_assert (thud (f32x) == 16); > > + static_assert (thud (f64x) == 15); > > + static_assert (thud (f128x) == 14); > > + static_assert (thud (fx) == 16); > > + static_assert (thud (dx) == 15); > > + static_assert (thud (ldx) == 14); > > +} > > --- gcc/testsuite/g++.dg/cpp23/ext-floating5.C.jj 2022-09-09 20:00:22.489534397 +0200 > > +++ gcc/testsuite/g++.dg/cpp23/ext-floating5.C 2022-09-10 10:44:59.653943267 +0200 > > @@ -0,0 +1,13 @@ > > +// P1467R9 - Extended floating-point types and standard names. > > +// IBM extended long double and _Float128 should have unordered conversion > > +// ranks as IBM extended long double has variable precision from 53 bits > > +// for denormals to more than 2150 bits for certain numbers. > > +// { dg-do compile { target { c++23 && { powerpc*-*-linux* } } } } > > +// { dg-require-effective-target ppc_float128_sw } > > +// { dg-options "-mvsx -mfloat128 -mlong-double-128 -mabi=ibmlongdouble" } > > + > > +auto a = 1.0F128 + 1.0L; // { dg-error "invalid operands to binary \\\+ \\\(have '_Float128' and 'long double'\\\)" } > > +auto b = 1.0L + 1.0F128; // { dg-error "invalid operands to binary \\\+ \\\(have 'long double' and '_Float128'\\\)" } > > +bool c; > > +auto d = c ? 1.0F128 : 1.0L; // { dg-error "operands to '\\\?:' have unordered conversion rank of types '_Float128' and 'long double'" } > > +auto e = c ? 1.0L : 1.0F128; // { dg-error "operands to '\\\?:' have unordered conversion rank of types 'long double' and '_Float128'" } > > --- gcc/testsuite/g++.dg/cpp23/ext-floating6.C.jj 2022-09-10 10:19:12.402030094 +0200 > > +++ gcc/testsuite/g++.dg/cpp23/ext-floating6.C 2022-09-09 18:46:07.281922287 +0200 > > @@ -0,0 +1,30 @@ > > +// P1467R9 - Extended floating-point types and standard names. > > +// { dg-do compile { target c++23 } } > > +// { dg-options "" } > > + > > +#include "ext-floating.h" > > + > > +#ifdef __STRICT_ANSI__ > > +#undef __SIZEOF_FLOAT128__ > > +#endif > > + > > +using namespace std; > > + > > +float foo (float x, float y, float z) { return x * y + z; } > > +double foo (double x, double y, double z) { return x * y + z; } > > +long double foo (long double x, long double y, long double z) { return x * y + z; } > > +#ifdef __STDCPP_FLOAT16_T__ > > +float16_t foo (float16_t x, float16_t y, float16_t z) { return x * y + z; } > > +#endif > > +#ifdef __STDCPP_FLOAT32_T__ > > +float32_t foo (float32_t x, float32_t y, float32_t z) { return x * y + z; } > > +#endif > > +#ifdef __STDCPP_FLOAT64_T__ > > +float64_t foo (float64_t x, float64_t y, float64_t z) { return x * y + z; } > > +#endif > > +#ifdef __STDCPP_FLOAT128_T__ > > +float128_t foo (float128_t x, float128_t y, float128_t z) { return x * y + z; } > > +#endif > > +#ifdef __STDCPP_BFLOAT16_T__ > > +bfloat16_t foo (bfloat16_t x, bfloat16_t y, bfloat16_t z) { return x * y + z; } > > +#endif > > --- gcc/testsuite/g++.dg/cpp23/ext-floating7.C.jj 2022-09-10 10:47:37.550796997 +0200 > > +++ gcc/testsuite/g++.dg/cpp23/ext-floating7.C 2022-09-10 10:53:25.622065903 +0200 > > @@ -0,0 +1,119 @@ > > +// P1467R9 - Extended floating-point types and standard names. > > +// { dg-do run { target { c++23 && float16_runtime } } } > > +// { dg-options "" } > > +// { dg-add-options float16 } > > + > > +#ifndef WIDTH > > +#ifndef __STDCPP_FLOAT16_T__ > > +#error Unexpected > > +#endif > > +#define WIDTH 16 > > +#endif > > + > > +#include > > +#include "ext-floating.h" > > + > > +#define CONCATX(X, Y) X ## Y > > +#define CONCAT(X, Y) CONCATX (X, Y) > > +#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z) > > +#define TYPE CONCAT (_Float, WIDTH) > > +#define CST(C) CONCAT3 (C, f, WIDTH) > > +#define CSTU(C) CONCAT3 (C, F, WIDTH) > > + > > +extern "C" void abort (); > > + > > +volatile TYPE a = CST (1.0), b = CSTU (2.5), c = -CST (2.5); > > +volatile TYPE a2 = CST (1.0), z = CST (0.0), nz = -CST (0.0); > > + > > +// These types are not subject to default argument promotions. > > + > > +TYPE > > +vafn (TYPE arg1, ...) > > +{ > > + va_list ap; > > + TYPE ret; > > + va_start (ap, arg1); > > + ret = arg1 + va_arg (ap, TYPE); > > + va_end (ap); > > + return ret; > > +} > > + > > +TYPE > > +fn (TYPE arg) > > +{ > > + return arg / 4; > > +} > > + > > +int > > +main (void) > > +{ > > + volatile TYPE r; > > + r = -b; > > + if (r != c) > > + abort (); > > + r = a + b; > > + if (r != CST (3.5)) > > + abort (); > > + r = a - b; > > + if (r != -CST (1.5)) > > + abort (); > > + r = 2 * c; > > + if (r != -5) > > + abort (); > > + r = b * c; > > + if (r != -CST (6.25)) > > + abort (); > > + r = b / (a + a); > > + if (r != CST (1.25)) > > + abort (); > > + r = c * 3; > > + if (r != -CST (7.5)) > > + abort (); > > + volatile int i = r; > > + if (i != -7) > > + abort (); > > + r = vafn (a, c); > > + if (r != -CST (1.5)) > > + abort (); > > + r = fn (a); > > + if (r != CST (0.25)) > > + abort (); > > + if ((a < b) != 1) > > + abort (); > > + if ((b < a) != 0) > > + abort (); > > + if ((a < a2) != 0) > > + abort (); > > + if ((nz < z) != 0) > > + abort (); > > + if ((a <= b) != 1) > > + abort (); > > + if ((b <= a) != 0) > > + abort (); > > + if ((a <= a2) != 1) > > + abort (); > > + if ((nz <= z) != 1) > > + abort (); > > + if ((a > b) != 0) > > + abort (); > > + if ((b > a) != 1) > > + abort (); > > + if ((a > a2) != 0) > > + abort (); > > + if ((nz > z) != 0) > > + abort (); > > + if ((a >= b) != 0) > > + abort (); > > + if ((b >= a) != 1) > > + abort (); > > + if ((a >= a2) != 1) > > + abort (); > > + if ((nz >= z) != 1) > > + abort (); > > + i = (nz == z); > > + if (i != 1) > > + abort (); > > + i = (a == b); > > + if (i != 0) > > + abort (); > > +} > > --- gcc/testsuite/g++.dg/cpp23/ext-floating8.C.jj 2022-09-10 10:52:54.654486646 +0200 > > +++ gcc/testsuite/g++.dg/cpp23/ext-floating8.C 2022-09-10 10:53:41.424851341 +0200 > > @@ -0,0 +1,13 @@ > > +// P1467R9 - Extended floating-point types and standard names. > > +// { dg-do run { target { c++23 && float32_runtime } } } > > +// { dg-options "" } > > +// { dg-add-options float32 } > > + > > +#ifndef WIDTH > > +#ifndef __STDCPP_FLOAT32_T__ > > +#error Unexpected > > +#endif > > +#define WIDTH 32 > > +#endif > > + > > +#include "ext-floating7.C" > > --- gcc/testsuite/g++.dg/cpp23/ext-floating9.C.jj 2022-09-10 10:53:49.328744035 +0200 > > +++ gcc/testsuite/g++.dg/cpp23/ext-floating9.C 2022-09-10 10:53:57.280636056 +0200 > > @@ -0,0 +1,13 @@ > > +// P1467R9 - Extended floating-point types and standard names. > > +// { dg-do run { target { c++23 && float64_runtime } } } > > +// { dg-options "" } > > +// { dg-add-options float64 } > > + > > +#ifndef WIDTH > > +#ifndef __STDCPP_FLOAT64_T__ > > +#error Unexpected > > +#endif > > +#define WIDTH 64 > > +#endif > > + > > +#include "ext-floating7.C" > > --- gcc/testsuite/g++.dg/cpp23/ext-floating10.C.jj 2022-09-10 10:54:08.224487463 +0200 > > +++ gcc/testsuite/g++.dg/cpp23/ext-floating10.C 2022-09-10 10:54:21.578306159 +0200 > > @@ -0,0 +1,13 @@ > > +// P1467R9 - Extended floating-point types and standard names. > > +// { dg-do run { target { c++23 && float128_runtime } } } > > +// { dg-options "" } > > +// { dg-add-options float128 } > > + > > +#ifndef WIDTH > > +#ifndef __STDCPP_FLOAT128_T__ > > +#error Unexpected > > +#endif > > +#define WIDTH 128 > > +#endif > > + > > +#include "ext-floating7.C" > > --- gcc/testsuite/g++.dg/cpp23/ext-floating.h.jj 2022-09-09 18:46:07.281922287 +0200 > > +++ gcc/testsuite/g++.dg/cpp23/ext-floating.h 2022-09-09 18:46:07.281922287 +0200 > > @@ -0,0 +1,30 @@ > > +// P1467R9 - Extended floating-point types and standard names. > > + > > +namespace std > > +{ > > + #ifdef __STDCPP_FLOAT16_T__ > > + using float16_t = _Float16; > > + #endif > > + #ifdef __STDCPP_FLOAT32_T__ > > + using float32_t = _Float32; > > + #endif > > + #ifdef __STDCPP_FLOAT64_T__ > > + using float64_t = _Float64; > > + #endif > > + #ifdef __STDCPP_FLOAT128_T__ > > + using float128_t = _Float128; > > + #endif > > + #undef __STDCPP_BFLOAT16_T__ > > + #ifdef __STDCPP_BFLOAT16_T__ > > + using bfloat16_t = __bf16; // ??? > > + #endif > > + template struct integral_constant { > > + static constexpr T value = v; > > + }; > > + typedef integral_constant false_type; > > + typedef integral_constant true_type; > > + template > > + struct is_same : std::false_type {}; > > + template > > + struct is_same : std::true_type {}; > > +} > > --- gcc/testsuite/g++.target/i386/float16-1.C.jj 2021-12-30 15:12:43.315149146 +0100 > > +++ gcc/testsuite/g++.target/i386/float16-1.C 2022-09-12 08:49:38.178955414 +0200 > > @@ -1,8 +1,8 @@ > > /* { dg-do compile } */ > > /* { dg-options "-O2 -mno-sse2" } */ > > > > -_Float16/* { dg-error "does not name a type" } */ > > +_Float16 /* { dg-error "expected unqualified-id before '_Float16'" } */ > > foo (_Float16 x) > > { > > return x; > > -} > > +} /* { dg-error "'_Float16' is not supported on this target" } */ > > --- libcpp/expr.cc.jj 2022-09-08 13:01:19.837771596 +0200 > > +++ libcpp/expr.cc 2022-09-09 09:52:46.533798139 +0200 > > @@ -215,7 +215,6 @@ interpret_float_suffix (cpp_reader *pfil > > case 'f': case 'F': > > f++; > > if (len > 0 > > - && !CPP_OPTION (pfile, cplusplus) > > && s[1] >= '1' > > && s[1] <= '9' > > && fn_bits == 0) > > @@ -230,7 +229,9 @@ interpret_float_suffix (cpp_reader *pfil > > len--; > > s++; > > } > > - if (len > 0 && s[1] == 'x') > > + if (len > 0 > > + && s[1] == 'x' > > + && !CPP_OPTION (pfile, cplusplus)) > > { > > fnx++; > > len--; > > --- include/demangle.h.jj 2022-08-26 09:23:37.788064821 +0200 > > +++ include/demangle.h 2022-09-09 09:52:46.533798139 +0200 > > @@ -457,6 +457,11 @@ enum demangle_component_type > > DEMANGLE_COMPONENT_MODULE_PARTITION, > > DEMANGLE_COMPONENT_MODULE_ENTITY, > > DEMANGLE_COMPONENT_MODULE_INIT, > > + > > + /* A builtin type with argument. This holds the builtin type > > + information. */ > > + DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE > > + > > }; > > > > /* Types which are only used internally. */ > > @@ -543,6 +548,14 @@ struct demangle_component > > const struct demangle_builtin_type_info *type; > > } s_builtin; > > > > + /* For DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE. */ > > + struct > > + { > > + /* Builtin type. */ > > + const struct demangle_builtin_type_info *type; > > + int arg; > > + } s_extended_builtin; > > + > > /* For DEMANGLE_COMPONENT_SUB_STD. */ > > struct > > { > > --- libiberty/cp-demangle.c.jj 2022-08-26 09:23:37.788064821 +0200 > > +++ libiberty/cp-demangle.c 2022-09-09 09:52:46.957792397 +0200 > > @@ -648,6 +648,10 @@ d_dump (struct demangle_component *dc, i > > case DEMANGLE_COMPONENT_BUILTIN_TYPE: > > printf ("builtin type %s\n", dc->u.s_builtin.type->name); > > return; > > + case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE: > > + printf ("builtin type %s%d\n", dc->u.s_extended_builtin.type->name, > > + dc->u.s_extended_builtin.type->arg); > > + return; > > case DEMANGLE_COMPONENT_OPERATOR: > > printf ("operator %s\n", dc->u.s_operator.op->name); > > return; > > @@ -771,11 +775,6 @@ d_dump (struct demangle_component *dc, i > > case DEMANGLE_COMPONENT_PTRMEM_TYPE: > > printf ("pointer to member type\n"); > > break; > > - case DEMANGLE_COMPONENT_FIXED_TYPE: > > - printf ("fixed-point type, accum? %d, sat? %d\n", > > - dc->u.s_fixed.accum, dc->u.s_fixed.sat); > > - d_dump (dc->u.s_fixed.length, indent + 2); > > - break; > > case DEMANGLE_COMPONENT_ARGLIST: > > printf ("argument list\n"); > > break; > > @@ -1109,6 +1108,27 @@ d_make_builtin_type (struct d_info *di, > > return p; > > } > > > > +/* Add a new extended builtin type component. */ > > + > > +static struct demangle_component * > > +d_make_extended_builtin_type (struct d_info *di, > > + const struct demangle_builtin_type_info *type, > > + int arg) > > +{ > > + struct demangle_component *p; > > + > > + if (type == NULL) > > + return NULL; > > + p = d_make_empty (di); > > + if (p != NULL) > > + { > > + p->type = DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE; > > + p->u.s_extended_builtin.type = type; > > + p->u.s_extended_builtin.arg = arg; > > + } > > + return p; > > +} > > + > > /* Add a new operator component. */ > > > > static struct demangle_component * > > @@ -2464,6 +2484,7 @@ cplus_demangle_builtin_types[D_BUILTIN_T > > /* 32 */ { NL ("char32_t"), NL ("char32_t"), D_PRINT_DEFAULT }, > > /* 33 */ { NL ("decltype(nullptr)"), NL ("decltype(nullptr)"), > > D_PRINT_DEFAULT }, > > + /* 34 */ { NL ("_Float"), NL ("_Float"), D_PRINT_FLOAT }, > > }; > > > > CP_STATIC_IF_GLIBCPP_V3 > > @@ -2727,19 +2748,22 @@ cplus_demangle_type (struct d_info *di) > > break; > > > > case 'F': > > - /* Fixed point types. DF */ > > - ret = d_make_empty (di); > > - ret->type = DEMANGLE_COMPONENT_FIXED_TYPE; > > - if ((ret->u.s_fixed.accum = IS_DIGIT (d_peek_char (di)))) > > - /* For demangling we don't care about the bits. */ > > - d_number (di); > > - ret->u.s_fixed.length = cplus_demangle_type (di); > > - if (ret->u.s_fixed.length == NULL) > > - return NULL; > > - d_number (di); > > - peek = d_next_char (di); > > - ret->u.s_fixed.sat = (peek == 's'); > > - break; > > + /* DF_ - _Float. */ > > + { > > + int arg = d_number (di); > > + char buf[12]; > > + if (d_peek_char (di) != '_') > > + return NULL; > > + ret > > + = d_make_extended_builtin_type (di, > > + &cplus_demangle_builtin_types[34], > > + arg); > > + d_advance (di, 1); > > + sprintf (buf, "%d", arg); > > + di->expansion += ret->u.s_extended_builtin.type->len > > + + strlen (buf); > > + break; > > + } > > > > case 'v': > > ret = d_vector_type (di); > > @@ -4202,6 +4226,7 @@ d_count_templates_scopes (struct d_print > > case DEMANGLE_COMPONENT_FUNCTION_PARAM: > > case DEMANGLE_COMPONENT_SUB_STD: > > case DEMANGLE_COMPONENT_BUILTIN_TYPE: > > + case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE: > > case DEMANGLE_COMPONENT_OPERATOR: > > case DEMANGLE_COMPONENT_CHARACTER: > > case DEMANGLE_COMPONENT_NUMBER: > > @@ -4210,6 +4235,7 @@ d_count_templates_scopes (struct d_print > > case DEMANGLE_COMPONENT_MODULE_NAME: > > case DEMANGLE_COMPONENT_MODULE_PARTITION: > > case DEMANGLE_COMPONENT_MODULE_INIT: > > + case DEMANGLE_COMPONENT_FIXED_TYPE: > > break; > > > > case DEMANGLE_COMPONENT_TEMPLATE: > > @@ -4309,10 +4335,6 @@ d_count_templates_scopes (struct d_print > > d_count_templates_scopes (dpi, dc->u.s_extended_operator.name); > > break; > > > > - case DEMANGLE_COMPONENT_FIXED_TYPE: > > - d_count_templates_scopes (dpi, dc->u.s_fixed.length); > > - break; > > - > > case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS: > > case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS: > > case DEMANGLE_COMPONENT_MODULE_ENTITY: > > @@ -4580,11 +4602,11 @@ d_find_pack (struct d_print_info *dpi, > > case DEMANGLE_COMPONENT_TAGGED_NAME: > > case DEMANGLE_COMPONENT_OPERATOR: > > case DEMANGLE_COMPONENT_BUILTIN_TYPE: > > + case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE: > > case DEMANGLE_COMPONENT_SUB_STD: > > case DEMANGLE_COMPONENT_CHARACTER: > > case DEMANGLE_COMPONENT_FUNCTION_PARAM: > > case DEMANGLE_COMPONENT_UNNAMED_TYPE: > > - case DEMANGLE_COMPONENT_FIXED_TYPE: > > case DEMANGLE_COMPONENT_DEFAULT_ARG: > > case DEMANGLE_COMPONENT_NUMBER: > > return NULL; > > @@ -5387,6 +5409,16 @@ d_print_comp_inner (struct d_print_info > > dc->u.s_builtin.type->java_len); > > return; > > > > + case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE: > > + if ((options & DMGL_JAVA) == 0) > > + d_append_buffer (dpi, dc->u.s_extended_builtin.type->name, > > + dc->u.s_extended_builtin.type->len); > > + else > > + d_append_buffer (dpi, dc->u.s_extended_builtin.type->java_name, > > + dc->u.s_extended_builtin.type->java_len); > > + d_append_num (dpi, dc->u.s_extended_builtin.arg); > > + return; > > + > > case DEMANGLE_COMPONENT_VENDOR_TYPE: > > d_print_comp (dpi, options, d_left (dc)); > > return; > > @@ -5525,22 +5557,6 @@ d_print_comp_inner (struct d_print_info > > return; > > } > > > > - case DEMANGLE_COMPONENT_FIXED_TYPE: > > - if (dc->u.s_fixed.sat) > > - d_append_string (dpi, "_Sat "); > > - /* Don't print "int _Accum". */ > > - if (dc->u.s_fixed.length->u.s_builtin.type > > - != &cplus_demangle_builtin_types['i'-'a']) > > - { > > - d_print_comp (dpi, options, dc->u.s_fixed.length); > > - d_append_char (dpi, ' '); > > - } > > - if (dc->u.s_fixed.accum) > > - d_append_string (dpi, "_Accum"); > > - else > > - d_append_string (dpi, "_Fract"); > > - return; > > - > > case DEMANGLE_COMPONENT_ARGLIST: > > case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: > > if (d_left (dc) != NULL) > > --- libiberty/cp-demangle.h.jj 2022-08-26 09:23:37.788064821 +0200 > > +++ libiberty/cp-demangle.h 2022-09-09 09:52:46.978792113 +0200 > > @@ -180,7 +180,7 @@ d_advance (struct d_info *di, int i) > > extern const struct demangle_operator_info cplus_demangle_operators[]; > > #endif > > > > -#define D_BUILTIN_TYPE_COUNT (34) > > +#define D_BUILTIN_TYPE_COUNT (35) > > > > CP_STATIC_IF_GLIBCPP_V3 > > const struct demangle_builtin_type_info > > --- libiberty/testsuite/demangle-expected.jj 2022-08-26 09:23:37.788064821 +0200 > > +++ libiberty/testsuite/demangle-expected 2022-09-09 09:52:46.993791909 +0200 > > @@ -1242,8 +1242,8 @@ _ZNSt9_Any_data9_M_accessIPZ4postISt8fun > > post >(std::function&&)::{lambda()#1}*& std::_Any_data::_M_access >(post >(std::function&&)::{lambda()#1}*&&)::{lambda()#1}*>() > > # > > --format=auto --no-params > > -_Z3xxxDFyuVb > > -xxx(unsigned long long _Fract, bool volatile) > > +_Z3xxxDF16_DF32_DF64_DF128_CDF16_Vb > > +xxx(_Float16, _Float32, _Float64, _Float128, _Float16 _Complex, bool volatile) > > xxx > > # https://sourceware.org/bugzilla/show_bug.cgi?id=16817 > > --format=auto --no-params > > --- fixincludes/inclhack.def.jj 2022-03-01 19:42:39.183264899 +0100 > > +++ fixincludes/inclhack.def 2022-09-11 20:08:07.787691125 +0200 > > @@ -2015,6 +2015,102 @@ fix = { > > EOT; > > }; > > > > +/* glibc-2.27 to 2.36 assume GCC 7 or later supports some or all > > + * of _Float{16,32,64,128} and _Float{32,64,128}x keywords for C, > > + * but doesn't for C++. > > + */ > > +fix = { > > + hackname = glibc_cxx_floatn_1; > > + files = bits/floatn.h, bits/floatn-common.h; > > + select = "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n" > > + "(([ \t]*/\\*[^\n]*\\*/\n)?" > > + "([ \t]*#[ \t]*if[^\n]*\n)?" > > + "[ \t]*#[ \t]*define __f(16|32|64|128)\\()"; > > + c_fix = format; > > + c_fix_arg = "%1(defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)\n%2"; > > + test_text = <<-EOT > > + # if !__GNUC_PREREQ (7, 0) || defined __cplusplus > > + /* The literal suffix f128 exists only since GCC 7.0. */ > > + # define __f128(x) x##l > > + # else > > + # define __f128(x) x##f128 > > + # endif > > + # if !__GNUC_PREREQ (7, 0) || defined __cplusplus > > + /* The literal suffix (f128) exist for powerpc only since GCC 7.0. */ > > + # if __LDBL_MANT_DIG__ == 113 > > + # define __f128(x) x##l > > + # else > > + # define __f128(x) x##q > > + # endif > > + # else > > + # define __f128(x) x##f128 > > + # endif > > + # if !__GNUC_PREREQ (7, 0) || defined __cplusplus > > + # ifdef __NO_LONG_DOUBLE_MATH > > + # define __f64(x) x##l > > + # else > > + # define __f64(x) x > > + # endif > > + # else > > + # define __f64(x) x##f64 > > + # endif > > + EOT; > > +}; > > + > > +fix = { > > + hackname = glibc_cxx_floatn_2; > > + files = bits/floatn.h, bits/floatn-common.h; > > + select = "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n" > > + "(([ \t]*/\\*[^\n]*\\*/\n)?" > > + "[ \t]*typedef[ \t]+[^\n]*[ \t]+_Float(16|32|64|128)([ \t]+__attribute__ \\(\\(__mode__ \\(__HF__\\)\\)\\))?;)"; > > + c_fix = format; > > + c_fix_arg = "%1(defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)\n%2"; > > + test_text = <<-EOT > > + # if !__GNUC_PREREQ (7, 0) || defined __cplusplus > > + typedef float _Float16 __attribute__ ((__mode__ (__HF__))); > > + # endif > > + # if !__GNUC_PREREQ (7, 0) || defined __cplusplus > > + typedef __float128 _Float128; > > + # endif > > + EOT; > > +}; > > + > > +fix = { > > + hackname = glibc_cxx_floatn_3; > > + files = bits/floatn.h, bits/floatn-common.h; > > + select = "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n" > > + "(([ \t]*/\\*[^\n]*\n?[^\n]*\\*/\n)?" > > + "([ \t]*#[ \t]*if[^\n]*\n)?" > > + "([ \t]*typedef[ \t]+[^\n]*;\n)?" > > + "[ \t]*#[ \t]*define __CFLOAT(16|32|64|128)[ \t]+)"; > > + c_fix = format; > > + c_fix_arg = "%1(defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)\n%2"; > > + test_text = <<-EOT > > + # if !__GNUC_PREREQ (7, 0) || defined __cplusplus > > + # define __CFLOAT128 _Complex long double > > + # else > > + # define __CFLOAT128 _Complex _Float128 > > + # endif > > + # if !__GNUC_PREREQ (7, 0) || defined __cplusplus > > + /* Add a typedef for older GCC compilers which don't natively support > > + _Complex _Float128. */ > > + typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__))); > > + # define __CFLOAT128 __cfloat128 > > + # else > > + # define __CFLOAT128 _Complex _Float128 > > + # endif > > + # if !__GNUC_PREREQ (7, 0) || defined __cplusplus > > + # ifdef __NO_LONG_DOUBLE_MATH > > + # define __CFLOAT64 _Complex long double > > + # else > > + # define __CFLOAT64 _Complex double > > + # endif > > + # else > > + # define __CFLOAT64 _Complex _Float64 > > + # endif > > + EOT; > > +}; > > + > > /* glibc-2.3.5 defines pthread mutex initializers incorrectly, > > * so we replace them with versions that correspond to the > > * definition. > > --- fixincludes/tests/base/bits/floatn.h.jj 2022-09-11 20:11:34.991962782 +0200 > > +++ fixincludes/tests/base/bits/floatn.h 2022-09-11 20:09:48.323368533 +0200 > > @@ -0,0 +1,74 @@ > > +/* DO NOT EDIT THIS FILE. > > + > > + It has been auto-edited by fixincludes from: > > + > > + "fixinc/tests/inc/bits/floatn.h" > > + > > + This had to be done to correct non-standard usages in the > > + original, manufacturer supplied header file. */ > > + > > + > > + > > +#if defined( GLIBC_CXX_FLOATN_1_CHECK ) > > +# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__) > > +/* The literal suffix f128 exists only since GCC 7.0. */ > > +# define __f128(x) x##l > > +# else > > +# define __f128(x) x##f128 > > +# endif > > +# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__) > > +/* The literal suffix (f128) exist for powerpc only since GCC 7.0. */ > > +# if __LDBL_MANT_DIG__ == 113 > > +# define __f128(x) x##l > > +# else > > +# define __f128(x) x##q > > +# endif > > +# else > > +# define __f128(x) x##f128 > > +# endif > > +# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__) > > +# ifdef __NO_LONG_DOUBLE_MATH > > +# define __f64(x) x##l > > +# else > > +# define __f64(x) x > > +# endif > > +# else > > +# define __f64(x) x##f64 > > +# endif > > +#endif /* GLIBC_CXX_FLOATN_1_CHECK */ > > + > > + > > +#if defined( GLIBC_CXX_FLOATN_2_CHECK ) > > +# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__) > > +typedef float _Float16 __attribute__ ((__mode__ (__HF__))); > > +# endif > > +# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__) > > +typedef __float128 _Float128; > > +# endif > > +#endif /* GLIBC_CXX_FLOATN_2_CHECK */ > > + > > + > > +#if defined( GLIBC_CXX_FLOATN_3_CHECK ) > > +# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__) > > +# define __CFLOAT128 _Complex long double > > +# else > > +# define __CFLOAT128 _Complex _Float128 > > +# endif > > +# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__) > > +/* Add a typedef for older GCC compilers which don't natively support > > + _Complex _Float128. */ > > +typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__))); > > +# define __CFLOAT128 __cfloat128 > > +# else > > +# define __CFLOAT128 _Complex _Float128 > > +# endif > > +# if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__) > > +# ifdef __NO_LONG_DOUBLE_MATH > > +# define __CFLOAT64 _Complex long double > > +# else > > +# define __CFLOAT64 _Complex double > > +# endif > > +# else > > +# define __CFLOAT64 _Complex _Float64 > > +# endif > > +#endif /* GLIBC_CXX_FLOATN_3_CHECK */ > > --- fixincludes/fixincl.x.jj 2022-03-01 19:42:39.169265091 +0100 > > +++ fixincludes/fixincl.x 2022-09-11 20:09:37.668565341 +0200 > > @@ -2,11 +2,11 @@ > > * > > * DO NOT EDIT THIS FILE (fixincl.x) > > * > > - * It has been AutoGen-ed February 27, 2022 at 07:47:03 PM by AutoGen 5.18.16 > > + * It has been AutoGen-ed September 11, 2022 at 08:09:37 PM by AutoGen 5.18.16 > > * From the definitions inclhack.def > > * and the template file fixincl > > */ > > -/* DO NOT SVN-MERGE THIS FILE, EITHER Sun Feb 27 19:47:03 UTC 2022 > > +/* DO NOT SVN-MERGE THIS FILE, EITHER Sun Sep 11 20:09:37 CEST 2022 > > * > > * You must regenerate it. Use the ./genfixes script. > > * > > @@ -15,7 +15,7 @@ > > * certain ANSI-incompatible system header files which are fixed to work > > * correctly with ANSI C and placed in a directory that GNU C will search. > > * > > - * This file contains 267 fixup descriptions. > > + * This file contains 270 fixup descriptions. > > * > > * See README for more information. > > * > > @@ -4107,6 +4107,132 @@ static const char* apzGlibc_C99_Inline_4 > > > > /* * * * * * * * * * * * * * * * * * * * * * * * * * > > * > > + * Description of Glibc_Cxx_Floatn_1 fix > > + */ > > +tSCC zGlibc_Cxx_Floatn_1Name[] = > > + "glibc_cxx_floatn_1"; > > + > > +/* > > + * File name selection pattern > > + */ > > +tSCC zGlibc_Cxx_Floatn_1List[] = > > + "bits/floatn.h\0bits/floatn-common.h\0"; > > +/* > > + * Machine/OS name selection pattern > > + */ > > +#define apzGlibc_Cxx_Floatn_1Machs (const char**)NULL > > + > > +/* > > + * content selection pattern - do fix if pattern found > > + */ > > +tSCC zGlibc_Cxx_Floatn_1Select0[] = > > + "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n\ > > +(([ \t]*/\\*[^\n\ > > +]*\\*/\n\ > > +)?([ \t]*#[ \t]*if[^\n\ > > +]*\n\ > > +)?[ \t]*#[ \t]*define __f(16|32|64|128)\\()"; > > + > > +#define GLIBC_CXX_FLOATN_1_TEST_CT 1 > > +static tTestDesc aGlibc_Cxx_Floatn_1Tests[] = { > > + { TT_EGREP, zGlibc_Cxx_Floatn_1Select0, (regex_t*)NULL }, }; > > + > > +/* > > + * Fix Command Arguments for Glibc_Cxx_Floatn_1 > > + */ > > +static const char* apzGlibc_Cxx_Floatn_1Patch[] = { > > + "format", > > + "%1(defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)\n\ > > +%2", > > + (char*)NULL }; > > + > > +/* * * * * * * * * * * * * * * * * * * * * * * * * * > > + * > > + * Description of Glibc_Cxx_Floatn_2 fix > > + */ > > +tSCC zGlibc_Cxx_Floatn_2Name[] = > > + "glibc_cxx_floatn_2"; > > + > > +/* > > + * File name selection pattern > > + */ > > +tSCC zGlibc_Cxx_Floatn_2List[] = > > + "bits/floatn.h\0bits/floatn-common.h\0"; > > +/* > > + * Machine/OS name selection pattern > > + */ > > +#define apzGlibc_Cxx_Floatn_2Machs (const char**)NULL > > + > > +/* > > + * content selection pattern - do fix if pattern found > > + */ > > +tSCC zGlibc_Cxx_Floatn_2Select0[] = > > + "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n\ > > +(([ \t]*/\\*[^\n\ > > +]*\\*/\n\ > > +)?[ \t]*typedef[ \t]+[^\n\ > > +]*[ \t]+_Float(16|32|64|128)([ \t]+__attribute__ \\(\\(__mode__ \\(__HF__\\)\\)\\))?;)"; > > + > > +#define GLIBC_CXX_FLOATN_2_TEST_CT 1 > > +static tTestDesc aGlibc_Cxx_Floatn_2Tests[] = { > > + { TT_EGREP, zGlibc_Cxx_Floatn_2Select0, (regex_t*)NULL }, }; > > + > > +/* > > + * Fix Command Arguments for Glibc_Cxx_Floatn_2 > > + */ > > +static const char* apzGlibc_Cxx_Floatn_2Patch[] = { > > + "format", > > + "%1(defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)\n\ > > +%2", > > + (char*)NULL }; > > + > > +/* * * * * * * * * * * * * * * * * * * * * * * * * * > > + * > > + * Description of Glibc_Cxx_Floatn_3 fix > > + */ > > +tSCC zGlibc_Cxx_Floatn_3Name[] = > > + "glibc_cxx_floatn_3"; > > + > > +/* > > + * File name selection pattern > > + */ > > +tSCC zGlibc_Cxx_Floatn_3List[] = > > + "bits/floatn.h\0bits/floatn-common.h\0"; > > +/* > > + * Machine/OS name selection pattern > > + */ > > +#define apzGlibc_Cxx_Floatn_3Machs (const char**)NULL > > + > > +/* > > + * content selection pattern - do fix if pattern found > > + */ > > +tSCC zGlibc_Cxx_Floatn_3Select0[] = > > + "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n\ > > +(([ \t]*/\\*[^\n\ > > +]*\n\ > > +?[^\n\ > > +]*\\*/\n\ > > +)?([ \t]*#[ \t]*if[^\n\ > > +]*\n\ > > +)?([ \t]*typedef[ \t]+[^\n\ > > +]*;\n\ > > +)?[ \t]*#[ \t]*define __CFLOAT(16|32|64|128)[ \t]+)"; > > + > > +#define GLIBC_CXX_FLOATN_3_TEST_CT 1 > > +static tTestDesc aGlibc_Cxx_Floatn_3Tests[] = { > > + { TT_EGREP, zGlibc_Cxx_Floatn_3Select0, (regex_t*)NULL }, }; > > + > > +/* > > + * Fix Command Arguments for Glibc_Cxx_Floatn_3 > > + */ > > +static const char* apzGlibc_Cxx_Floatn_3Patch[] = { > > + "format", > > + "%1(defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)\n\ > > +%2", > > + (char*)NULL }; > > + > > +/* * * * * * * * * * * * * * * * * * * * * * * * * * > > + * > > * Description of Glibc_Mutex_Init fix > > */ > > tSCC zGlibc_Mutex_InitName[] = > > @@ -10872,9 +10998,9 @@ static const char* apzX11_SprintfPatch[] > > * > > * List of all fixes > > */ > > -#define REGEX_COUNT 305 > > +#define REGEX_COUNT 308 > > #define MACH_LIST_SIZE_LIMIT 187 > > -#define FIX_COUNT 267 > > +#define FIX_COUNT 270 > > > > /* > > * Enumerate the fixes > > @@ -10977,6 +11103,9 @@ typedef enum { > > GLIBC_C99_INLINE_2_FIXIDX, > > GLIBC_C99_INLINE_3_FIXIDX, > > GLIBC_C99_INLINE_4_FIXIDX, > > + GLIBC_CXX_FLOATN_1_FIXIDX, > > + GLIBC_CXX_FLOATN_2_FIXIDX, > > + GLIBC_CXX_FLOATN_3_FIXIDX, > > GLIBC_MUTEX_INIT_FIXIDX, > > GLIBC_STDINT_FIXIDX, > > GLIBC_STRNCPY_FIXIDX, > > @@ -11635,6 +11764,21 @@ tFixDesc fixDescList[ FIX_COUNT ] = { > > GLIBC_C99_INLINE_4_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE, > > aGlibc_C99_Inline_4Tests, apzGlibc_C99_Inline_4Patch, 0 }, > > > > + { zGlibc_Cxx_Floatn_1Name, zGlibc_Cxx_Floatn_1List, > > + apzGlibc_Cxx_Floatn_1Machs, > > + GLIBC_CXX_FLOATN_1_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE, > > + aGlibc_Cxx_Floatn_1Tests, apzGlibc_Cxx_Floatn_1Patch, 0 }, > > + > > + { zGlibc_Cxx_Floatn_2Name, zGlibc_Cxx_Floatn_2List, > > + apzGlibc_Cxx_Floatn_2Machs, > > + GLIBC_CXX_FLOATN_2_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE, > > + aGlibc_Cxx_Floatn_2Tests, apzGlibc_Cxx_Floatn_2Patch, 0 }, > > + > > + { zGlibc_Cxx_Floatn_3Name, zGlibc_Cxx_Floatn_3List, > > + apzGlibc_Cxx_Floatn_3Machs, > > + GLIBC_CXX_FLOATN_3_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE, > > + aGlibc_Cxx_Floatn_3Tests, apzGlibc_Cxx_Floatn_3Patch, 0 }, > > + > > { zGlibc_Mutex_InitName, zGlibc_Mutex_InitList, > > apzGlibc_Mutex_InitMachs, > > GLIBC_MUTEX_INIT_TEST_CT, FD_MACH_ONLY, > > > > Jakub > > > > > -- > BR, > Hongtao -- BR, Hongtao