Hi. This issue, pointed out in private email by Vincenzo, puzzles me, I'm not even sure whether it's a C++ proper or an optimization issue related to the way we are lately able to optimize at compile time, mathematical functions of compile time constant arguments. To be safe, I'm adding in CC both Jason and Richi. (Note, I'm using math.h instead of cmath for avoidance of doubt that this may have to do with the library...) ////////////// #include <math.h> int main() { constexpr double ds = sinh(1.0); // Ok constexpr double das = asinh(1.0); // Doesn't compile. }
We do have code to constant fold asinh in builtins.c: static tree fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore) { ... CASE_FLT_FN (BUILT_IN_ASINH): if (validate_arg (arg0, REAL_TYPE)) return do_mpfr_arg1 (arg0, type, mpfr_asinh, NULL, NULL, 0); break; It works for C: #include <math.h> int main() { const double ds = sinh(1.0); // Ok const double das = asinh(1.0); // Doesn't compile. } in the .original dump: ;; Function main (null) ;; enabled by -tree-original { const double ds = 1.175201193643801378385660427738912403583526611328125e+0; const double das = 8.8137358701954304773806825323845259845256805419921875e-1; const double ds = 1.175201193643801378385660427738912403583526611328125e+0; const double das = 8.8137358701954304773806825323845259845256805419921875e-1; }
With C++ I get > ./cc1plus -quiet t.c -fdump-tree-original -std=c++0x t.c: In function 'int main()': t.c:6:39: error: 'asinh' was not declared in this scope without -std=c++0x the asinh declaration is there (this seems to be a glibc issue?). Look at the output from -dD -E -std=c++0x vs. w/o -std=c++0x.
Because __STRICT_ANSI__ is defined. Works with -std=gnu++0x.
Richard, we need a target here, because not all targets have asinh (a C99 function) in math.h. Otherwise, if you take out constexpr, of course it works. Only with constexpr the issue is interesting, because, roughly speaking, it looks like the front-end doesn't realize that the whole initialization of das can happen at compile time. But I'm confused here, because I don't know the details about the way the C++0x front-end figures out whether a function *not* marked constexpr, like asinh, actually is being called with compile time constant argument and thus calling it to initialize constexpr data is fine.
We don't want this to depend on -std=gnu++0x vs -std=c++0x!! The function is there, declared and callable, as removing constexpr reveals, the behavior wrt constexpr data cannot depend on __STRICT_ANSI__.
On Fri, 22 Jul 2011, paolo.carlini at oracle dot com wrote: > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49813 > > --- Comment #5 from Paolo Carlini <paolo.carlini at oracle dot com> 2011-07-22 10:52:03 UTC --- > We don't want this to depend on -std=gnu++0x vs -std=c++0x!! > > The function is there, declared and callable, as removing constexpr reveals, > the behavior wrt constexpr data cannot depend on __STRICT_ANSI__. No, with -std=c++0x asinh is not declared and I get the error above. With -std=gnu++0x the testcase works for me, even with constexpr. No bug here.
I just tried. This: #include <math.h> int main() { double ds = sinh(1.0); double das = asinh(1.0); } this compiles fine with -std=c++0x for me. On Linux of course, other targets have specific issues not relevant here. Or, for that matter: #include <cmath> int main() { double ds = std::sinh(1.0); double das = std::asinh(1.0); } we *really* want the latter to work fine both with -std=c++0x and -std=gnu++0x.
what about other "new C99 functions" such as cexprMath.cpp:16:64: error: 'float std::nextafter(float, float)' is not 'constexpr' cexprMath.cpp:17:58: error: 'float std::trunc(float)' is not 'constexpr' cexprMath.cpp:18:48: error: 'float std::lgamma(float)' is not 'constexpr' cexprMath.cpp:19:46: error: 'float std::erfc(float)' is not 'constexpr' ? have not tested all (yet). from #include <cmath> struct foo { static constexpr float a = std::cos(3.); static constexpr float c = std::exp(3.); static constexpr float d = std::log(3.); static constexpr float e1 = std::asin(1.); static constexpr float h = std::sqrt(.1); static constexpr float p = std::pow(1.3,-0.75); static constexpr float es = std::sinh(1.); static constexpr float ec = std::cosh(1.); static constexpr float et = std::tanh(1.); static constexpr float zs = std::asinh(1.2); static constexpr float zc = std::acosh(1.2); static constexpr float zt = std::atanh(.5); static constexpr float pi1 =std::nextafter(std::cos(-1.f),0.f); static constexpr float three =std::trunc(std::cos(-1.f)); static constexpr float l0 = std::lgamma(0.45f); static constexpr float er = std::erfc(0.45f); }; as we are on the subject: if the argument of the function is invalid such as static constexpr float nan1 = std::asin(1.45f); static constexpr float nan2 = std::sqrt(-1.45f); I get exactly the same error as above which is a bit confusing cexprMath.cpp:20:48: error: call to non-constexpr function 'float std::asin(float)' cexprMath.cpp:20:48: error: field initializer is not constant cexprMath.cpp:21:49: error: call to non-constexpr function 'float std::sqrt(float)' cexprMath.cpp:21:49: error: field initializer is not constant (the test of the message has changed between 4.6 and 4.7)
Yes, Vincenzo, all the other C99-only functions should be audited. I suppose a clean fix will automatically deal with all of them.
On Fri, 22 Jul 2011, paolo.carlini at oracle dot com wrote: > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49813 > > --- Comment #9 from Paolo Carlini <paolo.carlini at oracle dot com> 2011-07-22 11:09:55 UTC --- > Yes, Vincenzo, all the other C99-only functions should be audited. I suppose a > clean fix will automatically deal with all of them. Looking at -original it seems that libstdc++ lacks C99 overloads for double - it has them for float and long double only. Or that inline float asinh(float __x) { return __builtin_asinhf(__x); } inline long double asinh(long double __x) { return __builtin_asinhl(__x); } template<typename _Tp> inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, double>::__type asinh(_Tp __x) { return __builtin_asinh(__x); } isn't constexpr compatible. Doesn't sound like a middle-end issue but either a library or frontend issue to me. That said, it works fine if you give a asinh declaration in the testcase. Richard.
It does *not* Richi, there is an using ::asinh above. Exactly the same for sinh.
On Fri, 22 Jul 2011, rguenther at suse dot de wrote: > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49813 > > --- Comment #10 from rguenther at suse dot de <rguenther at suse dot de> 2011-07-22 11:17:38 UTC --- > On Fri, 22 Jul 2011, paolo.carlini at oracle dot com wrote: > > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49813 > > > > --- Comment #9 from Paolo Carlini <paolo.carlini at oracle dot com> 2011-07-22 11:09:55 UTC --- > > Yes, Vincenzo, all the other C99-only functions should be audited. I suppose a > > clean fix will automatically deal with all of them. > > Looking at -original it seems that libstdc++ lacks C99 overloads for > double - it has them for float and long double only. > > Or that > > inline float > asinh(float __x) > { return __builtin_asinhf(__x); } > > inline long double > asinh(long double __x) > { return __builtin_asinhl(__x); } > > template<typename _Tp> > inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, > double>::__type > asinh(_Tp __x) > { return __builtin_asinh(__x); } > > isn't constexpr compatible. > > Doesn't sound like a middle-end issue but either a library or frontend > issue to me. > > That said, it works fine if you give a asinh declaration in the > testcase. Btw, asinh is template<typename _Tp> inline typename __gnu_cxx::__promote<_Tp>::__type asinh(_Tp __x) { typedef typename __gnu_cxx::__promote<_Tp>::__type __type; return asinh(__type(__x)); } vs. sinh which is template<typename _Tp> inline typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, double>::__type sinh(_Tp __x) { return __builtin_sinh(__x); } note the lack of __gnu_cxx::__promote
... and let's decide to look at mainline, first at least.
On Fri, 22 Jul 2011, paolo.carlini at oracle dot com wrote: > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49813 > > --- Comment #11 from Paolo Carlini <paolo.carlini at oracle dot com> 2011-07-22 11:20:36 UTC --- > It does *not* Richi, there is an using ::asinh above. Exactly the same for > sinh. There is also a using ::asinhf but still std:: provides an overload. Please provide a _complete_ standalone testcase that you think should work and does not (w/o any includes). I suspect it's because of DEF_C99_BUILTIN (BUILT_IN_CASINH, "casinh", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING) so if -std=c++0x does not include C99 functions then we have no implicit builtin support and the following does not work: extern "C" double asinh(double x); namespace std { using ::asinh; } int main() { constexpr double das = std::asinh(1.0); } it also does not work with namespace std { double asinh (double x) { return __builtin_asinh (x); } } int main() { constexpr double das = std::asinh(1.0); // Doesn't compile. } but it works with int main() { constexpr double das = __builtin_asinh(1.0); // Doesn't compile. } which means this is still a C++ frontend / library issue.
Also works with namespace std { constexpr double asinh (double x) { return __builtin_asinh (x); } } int main() { constexpr double das = std::asinh(1.0); }
(In reply to comment #14) > There is also a using ::asinhf but still std:: provides an overload. So? This is what C++0x says we should have. As regards a complete testcase, I gave two, one using <math.h>, one a *real world* piece of C++0x code, compiled with -std=c++0x on Linux. #include <cmath> int main() { constexpr double cds = std::sinh(1.0); // Ok constexpr double cdas = std::asinh(1.0); // Not Ok. double das = std::asinh(1.0); // Ok. } we don't want those inconsistencies. By the way, I find your: constexpr double cdas = __builtin_asinh(1.0); very interesting. Looks like really the front-end is doing something strange wrt declarations of C99 functions: if <math.h> provided by glibc is include then the declarations are definitely there, in strict c++0x mode too, but the front-end is trying to invent something on its own, disregards those declarations somehow, but *only* when dealing with constexpr data, not otherwise.
On Fri, 22 Jul 2011, paolo.carlini at oracle dot com wrote: > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49813 > > --- Comment #16 from Paolo Carlini <paolo.carlini at oracle dot com> 2011-07-22 11:40:07 UTC --- > (In reply to comment #14) > > There is also a using ::asinhf but still std:: provides an overload. > > So? This is what C++0x says we should have. > > As regards a complete testcase, I gave two, one using <math.h>, one a *real > world* piece of C++0x code, compiled with -std=c++0x on Linux. > > #include <cmath> > > int main() > { > constexpr double cds = std::sinh(1.0); // Ok > constexpr double cdas = std::asinh(1.0); // Not Ok. > double das = std::asinh(1.0); // Ok. > } > > we don't want those inconsistencies. > > By the way, I find your: > > constexpr double cdas = __builtin_asinh(1.0); > > very interesting. Looks like really the front-end is doing something strange > wrt declarations of C99 functions: if <math.h> provided by glibc is include > then the declarations are definitely there, in strict c++0x mode too, but the > front-end is trying to invent something on its own, disregards those > declarations somehow, but *only* when dealing with constexpr data, not > otherwise. Is it valid in C++0x to provide a global function double asinh (double x) { abort (); } ? In that case we can't inject __builtin_asinh as asinh into the global namespace (as -std=gnu++0x does) and the using ::asinh is bogus(?) If the above is invalid then with -std=c++0x the C++ frontend should set flag_iso_c99 to true. Richard.
Before any other discussion (I believe we want to hear Jason now) I only want to add this: I think the whole discussion about -std=c++0x vs -std=gnu++0x can only possibly be useful in so far as it helps figuring out where is the bug. Because, really, part of the C++11 standard is certainly the unconditional availability of all of the C99 mathematical functions (more generally, the reference C language is everywhere C99 instead of C89, as it should be in 2011). Thus, I don't know at this point where exactly is the bug/issue, in the front-end, in some glibc bits vs C++11, in interactions, but I'm pretty sure we *do* have an issue here. To restate, from the C++11 point of view, sinh and asinh are 100% on a par. If we see an inconsistency in our implementers "world" about the way we are dealing in strict c++0x mode with those mathematical functions, it's our fault, a bug or a QoI issue.
Strictly speaking, the bug is that constexpr double ds = sinh(1.0); // Ok is accepted; the standard doesn't say that sinh is constexpr, so it isn't usable in a constant expression. G++ treating built-ins as constexpr is an extension, which should be disabled in strict conformance mode. Paolo, can you raise the question of marking C library functions as constexpr with the library WG? But practically speaking, we should have C90 builtins in C++98, and C99 builtins in C++11. I suppose that means setting flag_isoc94 and flag_isoc99 in C++.
I see, everything makes sense now. And OK, I'll raise the issue (in fact, we have Daniel in CC, in this bug... ;)
Hum (Jason and Daniel, in particular) I'm wondering if the issue could fall under http://lwg.github.com/issues/lwg-active.html#2013 but then, we would be able to assume / do it only for glibc on which we have control?!? I have no idea if the implementations in the various libc out there all satisfy the prerequisites for a function to be marked constexpr. Do you see my point? Or Jason you mean something else entirely?
Author: jason Date: Fri Jul 22 16:06:08 2011 New Revision: 176635 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=176635 Log: PR c++/49813 * c-opts.c (set_std_cxx0x): Set flag_isoc94 and flag_isoc99. * c-pretty-print.c (pp_c_cv_qualifiers): Check c_dialect_cxx as well as flag_isoc99 for 'restrict'. (pp_c_specifier_qualifier_list): Likewise for _Complex. Added: trunk/gcc/testsuite/g++.dg/opt/builtins2.C Modified: trunk/gcc/c-family/ChangeLog trunk/gcc/c-family/c-opts.c trunk/gcc/c-family/c-pretty-print.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/other/error27.C
would http://lwg.github.com/issues/lwg-active.html#2013 allow gcc to declare constexpr the x86 builtins (and corresponding wrapper functions)? I would be interested to have constepxr vectors (__m128 etc)
As far as I can see, Vincenzo, in that case the problem is a bit different, because those functions aren't ISO: should Intel issue an updated document describing the builtins and acknowledging the new C++? To be honest I know little about the way those builtins are "standardized", the way Intel issues updates to the specs. Maybe you could open about that a separate "exploratory" Bugzilla (in CC people like Uros)?!?
(In reply to comment #21) As far as I could follow this discussion, LWG 2013 seems to be the right location from the library view of point. But a compiler should not allow for function calls to participate in constant expressions, if these functions are not marked as constexpr. Library functions and other intrinsics can probably be considered as exceptions, because they are not required to be "explainable" by normal language rules.
Ah, yes, LWG 2013 does seem to allow GCC to treat these functions as constexpr. So, fixed for 4.7.
Thanks Jason. Let's reopen this as a library issue now: I have to mark constexpr the C++0x library provided overloads (for float, long double, double too for the C90 functions). Will do momentarily.
(I meant to say -some- C90 functions, like std::abs, in most of the cases only the overloads for float and long double require work)
(In reply to comment #28) > (I meant to say -some- C90 functions, like std::abs, in most of the cases only > the overloads for float and long double require work) You have to be careful though as we do not guarantee to fold things in the middle-end. For example I don't think mpfr handles all exceptional values, so we might end up not folding those (like with -fsignalling-nans or signed zeros). Also for -frounding-math we do not constant fold floating point expressions. But I'm not sure what guarantee a constexpr marked overload of, say, sqrt provides. We at least don't fold sqrt (-1.0).
Jason, looks like we have a remaining curious C++ front-end issue with isinf for long double, see the below. Can you have a look? Thanks! Paolo. ////////////////// inline constexpr bool isinf(long double __x) { return __builtin_isinf(__x); } inline constexpr bool isinf(double __x) { return __builtin_isinf(__x); } inline constexpr bool isnan(long double __x) { return __builtin_isnan(__x); } int main() { constexpr long double num1 = __builtin_isinf(1.l); // Ok. constexpr long double num2 = isinf(1.l); // Error. constexpr double num3 = isinf(1.); // Ok. constexpr long double num4 = isnan(1.l); // Ok. }
Richard, as far as I can see, if we don't fold, we don't fold, that line of user code with, eg constexpr data, will simply not compile. I don't think this is a major issue...
On Mon, 25 Jul 2011, paolo.carlini at oracle dot com wrote: > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49813 > > --- Comment #31 from Paolo Carlini <paolo.carlini at oracle dot com> 2011-07-25 10:54:24 UTC --- > Richard, as far as I can see, if we don't fold, we don't fold, that line of > user code with, eg constexpr data, will simply not compile. I don't think this > is a major issue... Ah, ok. So a constexpr function only means the frontend has to "try" to constant-fold it, and if it doesn't fold to a constant it's an errorneous program. I suppose only if the result is used in a constexpr, that is (recursively so).
indeed as noted in comment 8 20 static constexpr float nan1 = std::asin(1.45); 21 static constexpr float nan2 = std::sqrt(-1.45); produces the quite confusion error message: cexprMath.cpp:20:47: error: field initializer is not constant cexprMath.cpp:21:48: error: field initializer is not constant something saying that the argument is out-of-range may be more appropriate
Better diagnostic would be always welcome, but probably we should deal with that elsewhere (we *do* have PRs about constexpr vs diagnostics), because it's a generic problem, isn't specific to the math functions in the library (quite a special case actually, because C++11 does *not* even mandate those functions to be constexpr)
Also, something seems wrong with nextafter, but for the intrinsic too this time, thus maybe is a middle-end issue (eg, not optimized at all?). Try: constexpr float na = __builtin_nextafter(0.0f, 0.0f);
Or, more correctly: constexpr float na = __builtin_nextafterf(0.0f, 0.0f);
On Mon, 25 Jul 2011, paolo.carlini at oracle dot com wrote: > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49813 > > --- Comment #35 from Paolo Carlini <paolo.carlini at oracle dot com> 2011-07-25 11:41:57 UTC --- > Also, something seems wrong with nextafter, but for the intrinsic too this > time, thus maybe is a middle-end issue (eg, not optimized at all?). Try: > > constexpr float na = __builtin_nextafter(0.0f, 0.0f); Not all functions are folded by the middle-end. Look into builtins.c. Patches welcome.
Ah Ok, maybe I will be able to work on that. Just wanted to make sure we understand where the problem is.
(however, the issue in Comment #30, isinf vs long double, seems a real glitch somewhere, the intrinsic works fine)
Created attachment 24826 [details] Library bits, passes testing, the isinf overload for long double cannot be marked constexpr
The testcase in Comment #30 has the types wrong, the below is a corrected version (the substance of the issue doesn't change at all). I'm also thinking of checking in the library bits with a temporary workaround of the form: inline constexpr bool isinf(long double __x) { return fpclassify(__x) == FP_INFINITE; } which works. ///////////// inline constexpr bool isinf(long double __x) { return __builtin_isinf(__x); } inline constexpr bool isinf(double __x) { return __builtin_isinf(__x); } inline constexpr bool isnan(long double __x) { return __builtin_isnan(__x); } int main() { constexpr int i1 = __builtin_isinf(1.l); // Ok. constexpr bool b2 = isinf(1.l); // Error. constexpr bool b3 = isinf(1.); // Ok. constexpr bool b4 = isnan(1.l); // Ok. }
(In reply to comment #34) > (we *do* have PRs about constexpr vs diagnostics) Notably 45923, which I have just closed as fixed by my June 29 patch. The comment 8 testcase results in errors like wa.C:16:64: error: call to non-constexpr function ‘float std::nextafter(float, float)’ wa.C:16:64: error: field initializer is not constant ... which seems plenty clear to me: the initializer is not constant because of the call to a non-constexpr function. The isinf issue has to do with the (...) signature; morally_constexpr_builtin_function_p rejects varargs. Seems like we should add BUILT_IN_ISINF and its variants to builtin_valid_in_constant_expr_p.
(In reply to comment #42) > Seems like we should add BUILT_IN_ISINF and its variants to > builtin_valid_in_constant_expr_p. Actually, we seem to ignore the arguments when a function satisfies that function, which isn't what we want. Probably morally_constexpr_builtin_function_p should be rewritten to just have an enumeration of suitable builtins, and then move into builtins.c with a different name, right after is_inexpensive_builtin.
Please.. ;)
I have just noticed that with -m32 the isinf overloads for float and double are also affected, that is: constexpr bool isinf(float __x) { return __builtin_isinf(__x); } constexpr bool isinf(double __x) { return __builtin_isinf(__x); }
Another note, about std::nextafter, std::nexttoward, & co: I see mpfr provides an mpfr_nexttoward, which likely could be exploited in builtins.c pretty easily. Kaveh, do you have any plan about those?
Author: paolo Date: Wed Jul 27 19:33:51 2011 New Revision: 176847 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=176847 Log: 2011-07-27 Paolo Carlini <paolo.carlini@oracle.com> PR c++/49813 * include/c_global/cmath: Use _GLIBCXX_CONSTEXPR and constexpr. Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/c_global/cmath
(In reply to comment #41) > The testcase in Comment #30 has the types wrong, the below is a corrected > version (the substance of the issue doesn't change at all). I'm also thinking > of checking in the library bits with a temporary workaround of the form: > inline constexpr bool > isinf(long double __x) > { return fpclassify(__x) == FP_INFINITE; } > which works. > ///////////// > inline constexpr bool > isinf(long double __x) > { return __builtin_isinf(__x); } > inline constexpr bool > isinf(double __x) > { return __builtin_isinf(__x); } > inline constexpr bool > isnan(long double __x) > { return __builtin_isnan(__x); } > int main() > { > constexpr int i1 = __builtin_isinf(1.l); // Ok. > constexpr bool b2 = isinf(1.l); // Error. > constexpr bool b3 = isinf(1.); // Ok. > constexpr bool b4 = isnan(1.l); // Ok. > } The isinf (and isinf_sign) functions use the (...) signature, but isinff and isinfl do not. So if as noted in comment#42 the problem is with the long double variant using ellipses by calling isinf(...), perhaps you can fix it by using __builtin_isinfl (with the trailng "L") in the inline definition. I'm not sure why isnan passes, cause that one uses ellipses for the double variant also. Probably best to fix all the inlines to use the specific "L" or "F" function.
Thanks for your feedback Kaveh. Note, however, that, as I mentioned only today in Comment #45, with -m32 we have problems also with the overload for double, I have no idea how to fix it. More generally, I would be *really* curious to understand what's so special about isinf vs isnan and the other classification facilities, only isinf gives me troubles...
(In reply to comment #46) > Another note, about std::nextafter, std::nexttoward, & co: I see mpfr provides > an mpfr_nexttoward, which likely could be exploited in builtins.c pretty > easily. > Kaveh, do you have any plan about those? It's been several years since I did the mpfr work so my memory is a little foggy, but I think I intentionally skipped the next* functions. IIRC, these functions are very sensitive to the target floating point format. It wasn't clear to me that the "next" FP value in mpfr actually corresponded to the "next" value in the target FP format or how to verify if it was so. (I'm thinking mainly of the non-ieee formats here.) If these odd formats aren't used in GCC anymore then it might be okay to implement the builtins using mpfr. Alternatively, you can implement the builtins only for the formats where mpfr's format is identical to the target fp format. But then the optimization won't work everywhere so your library testcase will fail on some cpus. I'm not sure it's worth the trouble (and to answer your question I don't have any plans to work on it.)
It isn't hard to implement it ourselves just on the REAL_VALUE_TYPE type. We'd just need to handle a few special cases (e.g. x NaN or y NaN I guess we'd normally just don't optimize), and then we'd just add_significand/sub_significand of all zeros but LSB bit set, if it returns non-zero, bump/decrease exponent if possible, if not possible, give up/set to zero.
On Wed, 27 Jul 2011, ghazi at gcc dot gnu.org wrote: > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49813 > > --- Comment #50 from Kaveh Ghazi <ghazi at gcc dot gnu.org> 2011-07-27 23:13:18 UTC --- > (In reply to comment #46) > > Another note, about std::nextafter, std::nexttoward, & co: I see mpfr provides > > an mpfr_nexttoward, which likely could be exploited in builtins.c pretty > > easily. > > Kaveh, do you have any plan about those? > > It's been several years since I did the mpfr work so my memory is a little > foggy, but I think I intentionally skipped the next* functions. IIRC, these > functions are very sensitive to the target floating point format. It wasn't > clear to me that the "next" FP value in mpfr actually corresponded to the > "next" value in the target FP format or how to verify if it was so. (I'm > thinking mainly of the non-ieee formats here.) > > If these odd formats aren't used in GCC anymore then it might be okay to > implement the builtins using mpfr. Alternatively, you can implement the > builtins only for the formats where mpfr's format is identical to the target fp > format. But then the optimization won't work everywhere so your library > testcase will fail on some cpus. > > I'm not sure it's worth the trouble (and to answer your question I don't have > any plans to work on it.) I think the next* functions should be done with real.c stuff as it could be indeed dependent on the target format. Richard.
Author: sje Date: Thu Jul 28 20:59:11 2011 New Revision: 176899 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=176899 Log: 2011-07-28 Paolo Carlini <paolo.carlini@oracle.com> PR c++/49813 * semantics.c (potential_constant_expression_1): Handle FMA_EXPR. Checking this in for Paolo. Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/semantics.c
Author: jason Date: Mon Aug 1 18:14:29 2011 New Revision: 177066 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=177066 Log: PR c++/49813 * semantics.c (potential_constant_expression_1): Allow any builtin. (morally_constexpr_builtin_function_p): Remove. Added: trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin1.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/semantics.c trunk/gcc/testsuite/ChangeLog
I've changed the compiler to allow all builtins in constexpr functions.
Author: paolo Date: Mon Aug 1 19:26:39 2011 New Revision: 177070 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=177070 Log: 2011-08-01 Paolo Carlini <paolo.carlini@oracle.com> PR c++/49813 * include/c_global/cmath (isinf): Remove workaround. Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/c_global/cmath
Any objections to adding to the Wiki a list of the intrinsics not yet folded by the middle-end as an open project? Or we do already have such a list somewhere (beyond inspecting builtins.c)?
I think this is completely done by now.
The resolution of LWG 2013 changed: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3788.html#2013 and it no longer gives implementation the freedom to treat standard library functions as constexpr unless it is explicitly required. The new wording was included in the draft standard since at least N3936. Although a strict reading seems to leave some wiggle room the intention as mentioned in the updated issue was to avoid "diverging library implementations, as users may use SFINAE to observe different behavior from otherwise identical code".
There's no wiggle room, we're definitely non-conforming. Maybe the changes could be limited to -std=gnu++NN modes only, although Paolo argued strongly against that in this bug report. It doesn't seem to be causing any issues for anybody though, so I'm not very motivated to "fix" our non-conformance by removing features (and probably breaking somebody's code).
(In reply to Jonathan Wakely from comment #60) > There's no wiggle room, we're definitely non-conforming. > > Maybe the changes could be limited to -std=gnu++NN modes only, although > Paolo argued strongly against that in this bug report. > > It doesn't seem to be causing any issues for anybody though, so I'm not very > motivated to "fix" our non-conformance by removing features (and probably > breaking somebody's code). I'd say we should (but perhaps for GCC11 only) remove those constexpr markings and users that really need constexpr behavior will just need to use __builtin_sinh etc. instead which ought to be constexpr because it is a builtin.