Trying to compile the sqlpp17 codebase with gcc 8.2.1 and clang 6.0.1 have been a really strange experience. The code pushes the compilers to the limits and I hit probably a few compiler bugs in the meantime.
From the GCC Docs, [[maybe_unused]] is implemented since version 7, but if used this way:
struct foo {
foo([[maybe_unused]] bool thing1)
{
}
};
I hit this specific error:
<source>:2:9: error: expected unqualified-id before '[' token
foo([[maybe_unused]] bool thing1)
^
<source>:2:9: error: expected ')' before '[' token
foo([[maybe_unused]] bool thing1)
~^
)
Compiler returned: 1
Now, I know too little about C++17 to know if this error is correct, I know that clang 6 compiles that part fine (and fails somewhere else).
So, who's right, clang or gcc? (flags are -std=gnu++17 for both clang and gcc, generated by CMake)
This is a known bug in g++: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81429 G++ doesn't parse correctly [[maybe_unused]] attribute for first argument of the constructor.
Related
Consider the following code:
#include <tuple>
struct A {
template <typename... Types> operator std::tuple<Types...>() {
int i = 0;
return std::tuple<Types...>{Types(i++)...};
}
};
struct B {
B(int i){};
};
int main() {
A a;
std::tuple<B, B> t{a};
}
It produces the following warnings in gcc
$ g++-12 main.cpp -std=c++20 -Wall
main.cpp: In instantiation of ‘A::operator std::tuple<_UTypes ...>() [with Types = {B, B}]’:
main.cpp:18:23: required from here
main.cpp:7:46: warning: operation on ‘i’ may be undefined [-Wsequence-point]
7 | return std::tuple<Types...>{Types(i++)...};
| ^
main.cpp:7:46: warning: operation on ‘i’ may be undefined [-Wsequence-point]
but not in clang:
clang++-14 main.cpp -std=c++20 -Wall
main.cpp:18:20: warning: unused variable 't' [-Wunused-variable]
std::tuple<B, B> t{a};
^
1 warning generated.
Why?
This may be related but the referenced gcc bug is already fixed. I have gcc --version gcc (Debian 12.2.0-9) 12.2.0.
The order of evaluation of elements in a braced-init-list is strictly left-to-right, already since C++11, and regardless of the context in which the syntax is used. See https://timsong-cpp.github.io/cppwp/n3337/dcl.decl#dcl.init.list-4.
So the warning is bogus. #Artyer linked this bug report for a false positive warning under the question, which probably covers your example as well.
As mentioned in the other bug report you linked, GCC had actual wrong code generation for similar cases in earlier versions though, so you might want to be careful when relying on this order.
We just got burnt by a typo: "constexpr bool maxDistance=10000;"
Both gcc and clang compile this with no warning.
The real error here is that the variable shouldn't have been of type bool, but should have been an integer type instead.
How can we ensure we get a compiler warning in future?
#include <iostream>
constexpr bool number = 1234;
int main(int argc, char* argv[])
{
std::cout << number + 10000 << std::endl; // prints 10001.
return number;
}
The error here is that the variable is declared with the wrong type, however neither clang nor gcc give a warning.
gcc -Wall -std=c++14 test.cpp -lstdc++
clang -Wall -std=c++14 test.cpp -lstdc++
(using gcc 5.4.0 and clang 3.8.0)
Note: I've since learnt about a possible compile flag: -Wint-in-bool-context however this doesn't appear to be implemented in the version I'm using (5.4.0) nor in clang (3.8.0).
Is this the right way to go?
You should use direct list initialization syntax, it prohibits narrowing:
constexpr bool number{1234}; // error: narrowing conversion of '1234' from 'int' to 'bool' [-Wnarrowing]
I've discovered that gcc has a flag '-Wint-in-bool-context' however this doesn't appear to be implemented in the version I'm using (5.4.0) nor in clang (3.8.0).
Is this the right way to go?
I get an error when compile code containing <experimental/any>.
Code in main.cpp:
#include <experimental/any>
int main() { }
Compile this (clang version is 3.9):
clang++ main.cpp -o main -std=c++1z
Error after the compiling:
In file included from main.cpp:2:
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/experimental/any:364:34: error:
no template named '__any_caster'; did you mean 'any_cast'?
return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/experimental/any:361:30: note:
'any_cast' declared here
inline const _ValueType* any_cast(const any* __any) noexcept
^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/experimental/any:372:34: error:
no template named '__any_caster'; did you mean 'any_cast'?
return static_cast<_ValueType*>(__any_caster<_ValueType>(__any));
^
/usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../../include/c++/5.4.0/experimental/any:369:24: note:
'any_cast' declared here
inline _ValueType* any_cast(any* __any) noexcept
^
2 errors generated.
As #chris mentioned in the comments:
You could try with libc++. Perhaps there's an incompatibility with Clang in libstdc++'s new header.
This turns out to be true. Clang 3.9 is still experimental, and so it uses experimental headers, including a experimental C++ standard library. By default, it is provided by GCC, and so an incompatibility occurs between the GCC implementation and the Clang implementation.
I have the following code:
#include <type_traits>
int main()
{
}
g++ file.cc -std=c++0x
works just fine.
However, I need to use clang++ for some reason.
When I try
clang++ file.cc -std=c++0x
I get a bunch of errors:
In file included from file.cc:1:
In file included from /usr/include/c++/4.4.4/type_traits:50:
/usr/include/c++/4.4.4/tr1_impl/type_traits:230:41: error: expected ')'
struct is_function<_Res(_ArgTypes......)>
^
/usr/include/c++/4.4.4/tr1_impl/type_traits:230:28: note: to match this '('
struct is_function<_Res(_ArgTypes......)>
^
/usr/include/c++/4.4.4/tr1_impl/type_traits:230:12: error: redefinition of 'is_function<type-parameter-0-0 (type-parameter-0-1, ...)>'
struct is_function<_Res(_ArgTypes......)>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/4.4.4/tr1_impl/type_traits:227:12: note: previous definition is here
struct is_function<_Res(_ArgTypes...)>
^
/usr/include/c++/4.4.4/tr1_impl/type_traits:233:29: error: type qualifier is not allowed on this function
struct is_function<_Res(_ArgTypes...) const>
....
clang++ --version gives:
clang version 2.8 (branches/release_28)
Target: x86_64-redhat-linux-gnu
Thread model: posix
Any ideas how to fix that? (-std=c++11 doesn't work, not recognized.)
Clang 2.8 does not support C++11 features, you need to upgrade your compiler to use them.
I try to compile the simple code
#include <atomic>
int bar = 0;
void foo(std::atomic<int>&flag)
{ bar = flag; }
with clang++ 3.2 (downloaded as llvm 3.2 from llvm.org; on mac os.x 10.8.3 this fails with the error
/> clang++ -std=c++11 -stdlib=libc++ -O3 -march=native -c test.cc
In file included from test.cc:1:
/usr/include/c++/v1/atomic:576:17: error: first argument to atomic operation must be a pointer to non-const _Atomic type ('const _Atomic(int) *' invalid)
{return __c11_atomic_load(&__a_, __m);}
^ ~~~~~
/usr/include/c++/v1/atomic:580:53: note: in instantiation of member function
'std::_1::_atomic_base::load' requested here
operator _Tp() const _NOEXCEPT {return load();}
^
test.cc:5:9: note: in instantiation of member function 'std::_1::_atomic_base::operator int' requested here
bar = done;
When I use /usr/bin/clang++ instead (which comes with the OS or Xcode) it compiles just fine. The libc++ is that at /usr/lib/c++/v1 in both cases.
What am I missing? Is there another libc++ that comes with llvm 3.2 but which I'm missing? (I cannot find anything in the clang3.2 tree).
Xcode now bundles libc++ within the Xcode.app directory. You can inspect this directory by control-clicking Xcode.app and choose "Show Package Contents".