User account creation filtered due to spam.
Following up to 49813, this is a list of intrinsics, corresponding to C89 and C99 <math.h> (and C++11 <cmath>) facilities, not yet folded by the middle-end.
Note: in the audit trail of PR49813, Comment #51, Jakub explains that nextafter and nexttoward should be doable rather easily.
Uhm, remquo is strange. I see a do_mpfr_remquo but the following C++11 snippet is rejected, I don't know why:
int r = 0;
constexpr double d = __builtin_remquo(1.0, 1.0, &r);
... frexp also don't understand at the moment. I see a fold_builtin_frexp but the following doesn't compile:
int r = 0;
constexpr double d = __builtin_frexp(1.0, &r);
I think we can safely scratch frexp & remquo from the list: I double checked that the middle-end functions correctly compute the constants.
(It seems more a problem with my C++ test snippets in Comments #1 / #2: I suppose any definition of such functions isn't viable for constexpr, because the body has to assign the pointed integer additionally to returning a value... If Jason could confirm it would be great)
(In reply to comment #3)
> (It seems more a problem with my C++ test snippets in Comments #1 / #2: I
> suppose any definition of such functions isn't viable for constexpr, because
> the body has to assign the pointed integer additionally to returning a value...
> If Jason could confirm it would be great)
Correct, the assignment makes it non-constant.
This is a serious 'fault' that prevents making constexpr and functions that use frexp, even though the mantissa and exponent are definitely constant.
This prevents using constexpr in Boost.Math functions and distributions, Boost.Multiprecision and Proposed Boost.Fixed-Point.
Suggestions on workaround(s)?
Two separate constexpr functions for mantissa and exponent?
One function that 'returns' both as a tuple/pair?
Either are a major nuisance to replace frexp.
(Perhaps a single function to 'return' both doesn't such a good idea now?)
Shouldn't this be solvable in C++14 and later?
We still reject it:
error: ‘((y = 1), 6.2e-1)’ is not a constant expression
but I suppose with some hacking of cp/constexpr.c this could be handled.
constexpr double f1 (double x)
int y = 0;
return __builtin_frexp (x, &y);
constexpr int f2 (double x)
int y = 0;
__builtin_frexp (x, &y);
constexpr double c1 = f1 (1.24);
constexpr int c2 = f2 (1.24);
Created attachment 38912 [details]
Untested patch (for -std=c++14 and later only).
Date: Wed Jul 20 14:00:02 2016
New Revision: 238520
* constexpr.c (cxx_eval_builtin_function_call): Pass false as lval
when evaluating call arguments. Use fold_builtin_call_array instead
of fold_build_call_array_loc, return t if it returns NULL. Otherwise
check the result with potential_constant_expression and call
cxx_eval_constant_expression on it.
* g++.dg/cpp0x/constexpr-50060.C: New test.
* g++.dg/cpp1y/constexpr-50060.C: New test.
Should be fixed on the trunk (for C++14/C++17 and later).
Thanks for all this, which looks helpful, but I am not able to use unreleased compiler versions, so meanwhile I am working to use a workaround (to allow me to see what other pitfalls lie ahead for the novice ;-). FWIW my proof of concept is
// Version that returns both mantissa and exponent as a tuple.
// Proof of concept only, ignoring sign, overflow, denorm, infinite and NaNs.
constexpr std::tuple<float, int> frexp(float f)
int e = 0;
if (f >= 1.f)
f /= 2 ;
else if (f <= 0.1f)
f *= 2;
return std::make_tuple(f, e);
constexpr std::tuple<float, int> ee = frexp(1.f);
(I can confirm by checking that debugging will not step into the function, and also I can assign the tuple or the elements to a constexpr variable.)
Of course, this isn't a 'drop-in' for std::frexp, nor templated on other floating-point types, like Boost.Multiprecision types, but it will help for now.
I hope that this can be resolved somehow eventually, though I fear the pointer update will always be a nono for constexpr, preventing a truely 'drop-in' solution thus preventing any function that uses frexp from being constexpr.