Take the following code:
#include <array>
constexpr std::array<int, 10> a{};
static_assert(std::next(std::begin(a)) == std::begin(a) + 1);
With -std=c++17 GCC compiles it flawlessly, but Clang complains that the expression is not an integral constant expression. It looks like that the problem is about the std::next which, however, should be constexpr in C++17.
Nevertheless, std::next is in the std library, not in the compiler itself, therefore there is something weird going on. And just to make things even better, the example compiles perfectly if you pass -stdlib=libc++ to Clang.
What is going on? Who is wrong and who is right?
EDIT
The issue seems to be related to clang being toolchain-ed against GCC 7.2 inside godbolt. If you add the --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot parameter to the command line, everything works flawlessly. (Thanks to #einpoklum who reported the issue to godbolt -- I have been slower ;) )
EDIT
For everyone who consider that an old compiler should work for actual standard, sorry to say that the consideration is meaningless. I am talking about the last versions of both GCC and Clang. And the problem is reproducible with the trunk version of both. Older compilers are not relevant for this question (MSVC behaviour would be interesting, instead).
Compiling in Wandbox
#include <array>
int main()
{
constexpr std::array<int, 10> a{};
static_assert(std::next(std::begin(a)) == std::begin(a) + 1);
}
with clang++ 4.0.1 and command line
clang++ prog.cc -Wall -Wextra -std=c++1z
I get the error
prog.cc:6:18: error: static_assert expression is not an integral constant expression
static_assert(std::next(std::begin(a)) == std::begin(a) + 1);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:6:18: note: non-constexpr function 'next<const int *>' cannot be used in a constant expression
/opt/wandbox/clang-4.0.1/include/c++/v1/iterator:599:1: note: declared here
next(_InputIter __x,
^
1 error generated.
But compiling with clang++ 5.0.0 (or 6.0.0 or 7.0.0 HEAD) with
clang++ prog.cc -Wall -Wextra -std=c++17
So it seems a low support for C++17 in clang++ 4.0.1 (and/or libraries used by clang++), corrected in the following versions.
-- EDIT --
The problem is confirmed (see einpoklum's answer) for clang++ 5.0.0 and clang++ 6.0.0 in gobold.
So I suppose the problem is the version of libstdc++: seems that gobold is using a version (a older one, I suppose) where std::next() isn't defined as constexpr where wandbox is using a version where std::next() is constexpr.
With the Clang 6.0.0 and 5.0.0 version on GodBolt.org, your code does indeed fail to compile. But - with clang 5.0.0-3 on my system (Lubuntu 17.10), it seems to compile without errors.
This is weird behavior. So, perhaps not the best possible answer to your question, but faced with something like this I would report it on bugs.llvm.org and see what the clang/LLVM developers say.
Related
I have a std::atomic<float> that I would like to increment by a certain value. However, using fetch_add() on an atomic<float> does not compile and does not seem to be allowed. Is there anyway I can get around this? Here is the code snippet I tried:
std::atomic<float> data(0);
void do_work(){ data.fetch_add(1); }
The error I get is that fetch_add is not a member of atomic<float>
EDIT: Forgot to clarify that I am compiling with g++ version 9.3.0 using -std=c++2a
Floating point atomics are only supported by the C++ library in g++ 10.1 and later. See https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html and search for P0020R6.
Your code compiles fine with g++ 10.2: Try on godbolt
Having this error using c++17 on Mac OS.
As far as I can tell, code is correct and should work fine (compiles without issue w/ g++ and clang++ on linux).
Also, as far as I can tell, the current default mac version of clang [10.0.1] should support c++17 (full version info printout below).
So, my question is: is this actually a bug in my code, but it works by fluke on linux? Or is it an issue with MacOS clang e.g., not full c++17 implementation?
From cppref:
Defined in header (since C++17):
int abs( int n );
Other c++17 features seem to work completely fine.
#include <cmath>
// #include <cstdlib> //works if included
int main() {
int i = 1;
// return std::abs(1); // Works fine
return std::abs(i); // Fails
}
Compile with:
clang++ -std=c++17 test.cpp
Get this error:
test.cpp:7:10: error: call to 'abs' is ambiguous
return std::abs(i);
^~~~~~~~
/Library/Developer/CommandLineTools/usr/include/c++/v1/math.h:761:1: note:
candidate function
abs(float __lcpp_x) _NOEXCEPT {return ::fabsf(__lcpp_x);}
^
(... etc.)
1 error generated.
If you #include <cstdlib>, it works without error.
using -std=gnu++17 or -std=c++1z doesn't remove the problem either.
In the actual code (which is obviously more complex than the above, and actually uses c++17 features), the error happens depending on the order of my include files.
I can't replicate that in the simple example, but I assume it boils down to calling the cstdlib version instead of the cmath version.
Currently, my 'workaround' is to just put the header includes into the order that works..but this is hardly a long-term solution.
Does anyone know the cause?
Version info (error not specific to this MacOS version, also happens on my students' laptops):
Bens-iMac:test ben$ clang++ -v
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.5.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
See LWG Issue 2912
This has been fixed in libc++ trunk. I don't know if Apple has shipped this fix yet. As you found, including <cstdlib> is a workaround.
I can compile the following code (using std::transform_reduce) with gcc 9.2.1 on both Fedora and Ubuntu, but attempting to compile on clang see godbolt fails, and I've got a report that some FSF version of gcc 9.2.1 also refuses to compile the code, requiring a std::execution_policy as the first argument to the std::transform_reduce.
#include <vector>
#include <algorithm>
#include <numeric>
auto brokenvector(std::vector<int> const& a, std::vector<int> const& b)
{
return std::transform_reduce(cbegin(a), cend(a), cbegin(b), 0, std::plus<>{},std::multiplies<>{});
}
I specifically cannot use a std::execution_policy here, and both cppreference and the C++ draft standard document n4659 show overloads without an execution policy.
Have I stepped into some kind of political minefield where half of the available compilers refuse to implement the standard, or is the code incorrect?
This is a libstdc++ vs libc++ issue. libc++ implements the function and you can see it working with clang on godbolt using -stdlib=libc++ in this live example. gcc implements it now in trunk, but the currently released versions do not. The function was added in this commit.
I want to experiment with migrating a project from gcc to clang++. I admit ignorance on my part, I'm not sure why the following bit of code
template <typename T>
constexpr T pi{std::acos(T(-1.0))};
compiles silently with g++ but clang++ produces the error
trig.hpp:3:13: error: constexpr variable 'pi<float>' must be initialized by a constant expression
constexpr T pi{std::acos(T(-1.0))};
and I was hoping someone who knows more about it than I do could enlighten me.
NB: Tried with -std=C++14 and C++1y. Fails under clang version 3.6.2 (tags/RELEASE_362/final). Works with g++ (GCC) 5.2.0.
Clang is correct here, we are not allowed to use acos in a constant expression.
The issue is that acos is not marked constexpr in the standard but gcc treats some functions not marked in the standard including acos as constexpr. This is a non-conforming extension and should eventually be fixed in gcc.
Builtin functions are often used to constant fold and we can see if we use -fno-builtin with gcc it disables this non-conforming behavior and we will receive the following error:
error: call to non-constexpr function 'double acos(double)'
constexpr T pi{std::acos(T(-1.0))};
^
Given the following complete program:
#include <functional>
struct jobbie
{
std::function<void()> a;
};
void do_jobbie(jobbie j = {})
{
if (j.a)
j.a();
}
int main()
{
do_jobbie();
return 0;
}
compiling this on gcc (Ubuntu 4.8.1-2ubuntu1~12.04) 4.8.1:
boom!
richard#DEV1:~/tmp$ g++ -std=c++11 bug.cpp
bug.cpp: In function ‘int main()’:
bug.cpp:16:13: internal compiler error: in create_tmp_var, at gimplify.c:479
do_jobbie();
^
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-4.8/README.Bugs> for instructions.
Preprocessed source stored into /tmp/ccWGpb7M.out file, please attach this to your bugreport.
However, clang [Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)] is happy with it.
$ clang++ -std=c++11 bug.cpp
It seems to me that clang is correctly deducing that j defaults to a default-constructed jobbie object whereas gcc is (obviously) blowing up.
replacing line 8 with void do_jobbie(jobbie j = jobbie {}) fixes the problem on gcc.
Question - which of these is true:
clang is correct, gcc is faulty (ignoring the compiler blow-up)
clang is over-reaching the standard and it should not really compile
the standard does not make it clear?
An internal compiler error is always a compiler bug. Compilers should be able to process anything without crashing like that.
clang has similar handling for when it crashes, producing data for reporting the bug and pointing the user to clang's bug reporting web page.
I don't see anything tricky about this code. It seems straightforward to me that it should compile and run.
This indicates that it should work:
The default argument has the same semantic constraints as the initializer in a declaration of a variable of the parameter type, using the copy-initialization semantics.
(8.3.6, wording from draft n3936)