Consider the code:
#include <type_traits>
#include <cmath>
#include <iostream>
template <class Integer>
constexpr Integer bitwise_sqrt(const Integer& x)
{
// TODO put real code here, doesn't need it for the bug case though
return 0;
}
template <class Integer>
constexpr Integer fast_sqrt(const Integer& x)
{
return static_cast<Integer>(std::sqrt(static_cast<double>(x)));
}
template <class Integer>
constexpr Integer get_sqrt(const Integer& x)
{
if(std::is_constant_evaluated())
return bitwise_sqrt(x);
return fast_sqrt(x);
}
int main()
{
unsigned i;
std::cin >> i;
i = get_sqrt(i);
std::cout << i << std::endl;
}
Input comes from std::cin, I assume we can all agree that in this context get_sqrt() can not be a constant context. However, std::is_constant_evaluated() is returning true.
Note that:
- The issue only occurs when compiling with
-std=c++2b.
- The issue does not occur prior to clang-14.
- The issue does not occur if we use
__builtin_is_constant_evaluated() directly.
- Reproduced on Ubuntu-22 with
ubuntu clang version 14.0.0-1ubuntu1
This is a reduced test case from Boost.Multiprecision BTW.
Consider the code:
Input comes from
std::cin, I assume we can all agree that in this contextget_sqrt()can not be a constant context. However,std::is_constant_evaluated()is returning true.Note that:
-std=c++2b.__builtin_is_constant_evaluated()directly.ubuntu clang version 14.0.0-1ubuntu1This is a reduced test case from
Boost.MultiprecisionBTW.