From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id DC9A03858C41 for ; Wed, 17 May 2023 18:18:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DC9A03858C41 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1684347488; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type; bh=C2/lnNgLgZ4YpLZhQPLAcBmuXYsHy3OEkbbsmW82PFw=; b=WTkVILLHGwNiPfUGSOg+x8A2HEiVIXeq8acWC1VuWa1mHlpVhpayT7t5dhF9KjLBggpAb5 5YkyMZeSn9sAAR1F2yOimOBce8xhzU0n8wjlIlvEkIioV94BixrJD6dZITWE/h5xl+bJ6R BEldrYv6Iw8EBMGjG0Y6DZBCPg+/z+w= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-135-jiz-8l0NOCG7ho583Sfpkg-1; Wed, 17 May 2023 14:18:05 -0400 X-MC-Unique: jiz-8l0NOCG7ho583Sfpkg-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id CE31688B767; Wed, 17 May 2023 18:18:04 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.192.17]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 758C31401C56; Wed, 17 May 2023 18:18:04 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 34HII2uJ609176 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Wed, 17 May 2023 20:18:02 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 34HII1Em609175; Wed, 17 May 2023 20:18:01 +0200 Date: Wed, 17 May 2023 20:18:01 +0200 From: Jakub Jelinek To: Jonathan Wakely Cc: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [PATCH] libstdc++: Fix up some templates [PR109883] Message-ID: Reply-To: Jakub Jelinek MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-3.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_NONE,TXREP,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Hi! As can be seen on the following testcase, for std::{atan2,fmod,pow,copysign,fdim,fmax,fmin,hypot,nextafter,remainder,remquo,fma} if one operand type is std::float{16,32,64,128}_t or std::bfloat16_t and another one some integral type or some other floating point type which promotes to the other operand's type, we can end up with endless recursion. This is because of a declaration ordering problem in , where the float, double and long double overloads of those functions come before the templates which use __gnu_cxx::__promote_{2,3}, but the std::float{16,32,64,128}_t and std::bfloat16_t overloads come later in the file. If the result of those promotions is _Float{16,32,64,128} or __gnu_cxx::__bfloat16_t, say std::pow(_Float64, int) calls std::pow(_Float64, _Float64) and the latter calls itself. The following patch fixes that by moving those templates later in the file, so that the calls from those templates see also the other overloads. I think other templates in the file like e.g. isgreater etc. shouldn't be a problem, because those just use __builtin_isgreater etc. in their bodies. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/13.2? 2023-05-17 Jakub Jelinek PR libstdc++/109883 * include/c_global/cmath (atan2, fmod, pow): Move __gnu_cxx::__promote_2 using templates after _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t overloads. (copysign, fdim, fmax, fmin, hypot, nextafter, remainder, remquo): Likewise. (fma): Move __gnu_cxx::__promote_3 using template after _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t overloads. * testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc: New test. --- libstdc++-v3/include/c_global/cmath.jj 2023-01-16 23:19:06.225717615 +0100 +++ libstdc++-v3/include/c_global/cmath 2023-05-17 15:07:07.823657320 +0200 @@ -151,15 +151,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_atan2l(__y, __x); } #endif - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - atan2(_Tp __y, _Up __x) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return atan2(__type(__y), __type(__x)); - } - using ::ceil; #ifndef __CORRECT_ISO_CPP_MATH_H_PROTO @@ -286,15 +277,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_fmodl(__x, __y); } #endif - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - fmod(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return fmod(__type(__x), __type(__y)); - } - using ::frexp; #ifndef __CORRECT_ISO_CPP_MATH_H_PROTO @@ -411,15 +393,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif #endif - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - pow(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return pow(__type(__x), __type(__y)); - } - using ::sin; #ifndef __CORRECT_ISO_CPP_MATH_H_PROTO @@ -1073,6 +1046,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __gnu_cxx::__bfloat16_t(__builtin_tanhf(__x)); } #endif + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + atan2(_Tp __y, _Up __x) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return atan2(__type(__y), __type(__x)); + } + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fmod(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fmod(__type(__x), __type(__y)); + } + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + pow(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return pow(__type(__x), __type(__y)); + } + #if _GLIBCXX_USE_C99_MATH #if !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC @@ -2107,16 +2107,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_copysignl(__x, __y); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - copysign(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return copysign(__type(__x), __type(__y)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr float erf(float __x) @@ -2199,16 +2189,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_fdiml(__x, __y); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - fdim(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return fdim(__type(__x), __type(__y)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr float fma(float __x, float __y, float __z) @@ -2219,16 +2199,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_fmal(__x, __y, __z); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type - fma(_Tp __x, _Up __y, _Vp __z) - { - typedef typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type __type; - return fma(__type(__x), __type(__y), __type(__z)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr float fmax(float __x, float __y) @@ -2239,16 +2209,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_fmaxl(__x, __y); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - fmax(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return fmax(__type(__x), __type(__y)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr float fmin(float __x, float __y) @@ -2259,16 +2219,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_fminl(__x, __y); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - fmin(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return fmin(__type(__x), __type(__y)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr float hypot(float __x, float __y) @@ -2279,16 +2229,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_hypotl(__x, __y); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - hypot(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return hypot(__type(__x), __type(__y)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr int ilogb(float __x) @@ -2481,16 +2421,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_nextafterl(__x, __y); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - nextafter(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return nextafter(__type(__x), __type(__y)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr float nexttoward(float __x, long double __y) @@ -2519,16 +2449,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_remainderl(__x, __y); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - remainder(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return remainder(__type(__x), __type(__y)); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP inline float remquo(float __x, float __y, int* __pquo) @@ -2539,16 +2459,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __builtin_remquol(__x, __y, __pquo); } #endif -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - remquo(_Tp __x, _Up __y, int* __pquo) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return remquo(__type(__x), __type(__y), __pquo); - } -#endif - #ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP constexpr float rint(float __x) @@ -3555,6 +3465,79 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __gnu_cxx::__bfloat16_t(__builtin_truncf(__x)); } #endif +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + copysign(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return copysign(__type(__x), __type(__y)); + } + + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fdim(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fdim(__type(__x), __type(__y)); + } + + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fmax(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fmax(__type(__x), __type(__y)); + } + + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fmin(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fmin(__type(__x), __type(__y)); + } + + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + hypot(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return hypot(__type(__x), __type(__y)); + } + + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + nextafter(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return nextafter(__type(__x), __type(__y)); + } + + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + remainder(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return remainder(__type(__x), __type(__y)); + } + + template + inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + remquo(_Tp __x, _Up __y, int* __pquo) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return remquo(__type(__x), __type(__y), __pquo); + } + + template + constexpr typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type + fma(_Tp __x, _Up __y, _Vp __z) + { + typedef typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type __type; + return fma(__type(__x), __type(__y), __type(__z)); + } +#endif #endif // _GLIBCXX_USE_C99_MATH_TR1 #endif // C++11 --- libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc.jj 2023-05-17 15:23:55.120327327 +0200 +++ libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc 2023-05-17 16:19:27.386931508 +0200 @@ -0,0 +1,129 @@ +// Copyright (C) 2023 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2b" } +// { dg-do link { target c++23 } } + +#include +#include + +template +void +test_functions() +{ + constexpr T zero = 0; + constexpr T one = 1; + constexpr auto a = std::acos(one); + constexpr auto b = std::asin(zero); + constexpr auto c = std::atan(zero); + constexpr auto d = std::cos(zero); + constexpr auto e = std::sin(zero); + constexpr auto f = std::tan(zero); + constexpr auto g = std::acosh(one); + constexpr auto h = std::asinh(zero); + constexpr auto i = std::atanh(zero); + constexpr auto j = std::cosh(zero); + constexpr auto k = std::sinh(zero); + constexpr auto l = std::tanh(zero); + constexpr auto m = std::exp(zero); + constexpr auto n = std::exp2(zero); + constexpr auto o = std::expm1(one); + constexpr auto p = std::log(one); + constexpr auto q = std::log10(one); + constexpr auto r = std::log1p(zero); + constexpr auto s = std::log2(one); + constexpr auto t = std::logb(one); + constexpr auto u = std::cbrt(zero); + constexpr auto v = std::fabs(zero); + constexpr auto w = std::sqrt(one); + constexpr auto x = std::erf(zero); + constexpr auto y = std::erfc(zero); +// constexpr auto z = std::lgamma(one); + constexpr auto A = std::tgamma(one); + constexpr auto B = std::ceil(zero); + constexpr auto C = std::floor(zero); +// constexpr auto D = std::nearbyint(zero); +// constexpr auto E = std::rint(zero); + constexpr auto F = std::round(zero); + constexpr auto G = std::trunc(zero); + constexpr auto H = std::atan2(zero, one); + constexpr auto I = std::hypot(one, zero); + constexpr auto J = std::pow(one, zero); + constexpr auto K = std::fmod(zero, one); + constexpr auto L = std::remainder(one, one); + constexpr auto M = std::copysign(zero, zero); + constexpr auto N = std::nextafter(zero, zero); + constexpr auto O = std::fdim(zero, zero); + constexpr auto P = std::fmax(zero, one); + constexpr auto Q = std::fmin(zero, one); + constexpr auto R = std::ilogb(one); + constexpr auto S = std::ldexp(one, 0); + constexpr auto U = std::scalbn(one, 1); + constexpr auto V = std::scalbln(one, 1); +// constexpr auto W = std::lrint(one); +// constexpr auto X = std::llrint(one); + constexpr auto Y = std::lround(one); + constexpr auto Z = std::llround(one); + constexpr auto a1 = std::fma(one, one, one); + constexpr auto b1 = std::atan2(zero, 1); + constexpr auto c1 = std::hypot(one, 0); + constexpr auto d1 = std::pow(one, 0); + constexpr auto e1 = std::fmod(zero, 1); + constexpr auto f1 = std::remainder(one, 1); + constexpr auto g1 = std::copysign(zero, 0); + constexpr auto h1 = std::nextafter(zero, 0); + constexpr auto i1 = std::fdim(zero, 0); + constexpr auto j1 = std::fmax(zero, 1); + constexpr auto k1 = std::fmin(zero, 1); + constexpr auto l1 = std::fma(one, one, 1); + constexpr auto n1 = std::atan2(0, one); + constexpr auto o1 = std::hypot(1, zero); + constexpr auto p1 = std::pow(1, zero); + constexpr auto q1 = std::fmod(0, one); + constexpr auto r1 = std::remainder(1, one); + constexpr auto s1 = std::copysign(0, zero); + constexpr auto t1 = std::nextafter(0, zero); + constexpr auto u1 = std::fdim(0, zero); + constexpr auto v1 = std::fmax(0, one); + constexpr auto w1 = std::fmin(0, one); + constexpr auto x1 = std::fma(one, 1, one); + constexpr auto y1 = std::fma(1, one, one); + constexpr auto z1 = std::fma(1, 1, one); + constexpr auto A1 = std::fma(1, one, 1); +} + +int +main() +{ +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + test_functions(); +#endif +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + test_functions(); +#endif +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + test_functions(); +#endif +#if defined(__STDCPP_FLOAT128_T__) \ + && (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \ + || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) + test_functions(); +#endif +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + test_functions(); +#endif +} Jakub