This needs little explanation, but I'm expecting to get an ambiguity error from the following C++ code, however my compiler gives me different results that are apparently not part of the standard.
Environment:
Windows
Clang++ version 12.0.0
Clang++ target = x86_64-pc-windows-msvc
#include <iostream>
void print(int x) {
std::cout << "INT\n";
}
void print(double d) {
std::cout << "DOUBLE\n";
}
int main() {
print(5l); // 5l is type long, should cause ambiguity
}
output:
INT
Any idea why this is happening? My compiler is choosing the function taking an int for some reason instead of issuing an ambiguity error since it shouldn't be able to resolve the function call. Is there some conversion logic that I missed? Do I need to turn up some 'error levels' or something along those lines? Or is this a bug in the compiler? Thanks.
Turned out I had to add -fno-ms-compatibility to my clang compiler flags to switch off MSVC compatibility.
Related
I have the following SSCCE:
#include <iostream>
#include <string>
void foo(const std::string &a) {
std::cout << a << std::endl;
}
template <typename... Args>
void bar(Args &&... args) {
[&]() {
[&]() {
foo(args...);
}();
}();
}
int main() {
const std::string x("Hello World!");
bar(x);
}
Under clang++ (3.9.1) this compiles and emits "Hello World". Gcc 6.3 fails with a segmentation fault under -O3.
I can fix the problem by explicitly passing the pointer and the pack by reference, replacing [&]() with [&args...](). However, up to now, I thought that [&] would do the same as listing all arguments one by one.
So what is going wrong here?
P.S:
This is not limited to -O3. -O0 does not segfault but does not return the expected result ("Hello World!"):
[:~/tmp] $ g++-6 -std=c++1z param.cpp && ./a.out
[:~/tmp] $
P.P.S: Further reduced SSCCE. Now I don't even get a diagnostic with -Wall -Wextra anymore.
I strongly suspect a g++ bug.
Here are some notes:
replacing std::string with any elementary type, e.g., int still does not work
clang and VC++ will work just as intended
not passing parameter pack by reference causes an internal compiler error with g++ 7.0.1 with the following output:
internal compiler error: in make_decl_rtl, at varasm.c:1304
...
Please
submit a full bug report, with preprocessed source if appropriate.
Please include the complete backtrace with any bug report. See
http://gcc.gnu.org/bugs.html for instructions.
I have the following SSCCE:
#include <iostream>
#include <string>
void foo(const std::string &a) {
std::cout << a << std::endl;
}
template <typename... Args>
void bar(Args &&... args) {
[&]() {
[&]() {
foo(args...);
}();
}();
}
int main() {
const std::string x("Hello World!");
bar(x);
}
Under clang++ (3.9.1) this compiles and emits "Hello World". Gcc 6.3 fails with a segmentation fault under -O3.
I can fix the problem by explicitly passing the pointer and the pack by reference, replacing [&]() with [&args...](). However, up to now, I thought that [&] would do the same as listing all arguments one by one.
So what is going wrong here?
P.S:
This is not limited to -O3. -O0 does not segfault but does not return the expected result ("Hello World!"):
[:~/tmp] $ g++-6 -std=c++1z param.cpp && ./a.out
[:~/tmp] $
P.P.S: Further reduced SSCCE. Now I don't even get a diagnostic with -Wall -Wextra anymore.
I strongly suspect a g++ bug.
Here are some notes:
replacing std::string with any elementary type, e.g., int still does not work
clang and VC++ will work just as intended
not passing parameter pack by reference causes an internal compiler error with g++ 7.0.1 with the following output:
internal compiler error: in make_decl_rtl, at varasm.c:1304
...
Please
submit a full bug report, with preprocessed source if appropriate.
Please include the complete backtrace with any bug report. See
http://gcc.gnu.org/bugs.html for instructions.
I have been playing around a bit with the [[noreturn]] attribute, which I'm trying to get a handle of and make use of (I understand [[noreturn]] is a C++11 standard attribute and __attribute__((noreturn)) is a GCC/Clang extension). As part of this, I enabled the Clang warning -Wmissing-noreturn.
> clang++ -v
Ubuntu clang version 3.7.1-svn253742-1~exp1 (branches/release_37) (based on LLVM 3.7.1)
Target: x86_64-pc-linux-gnu
Thread model: posix
foo.cpp:
enum bar
{
A = 1,
B,
C
};
void foo()
{
switch (bar())
{
case A:
case B:
case C:
default:
break;
}
}
int main()
{
foo();
return 0;
}
Then compile:
> clang++ foo.cpp -o foo -Wmissing-noreturn -std=c++14
foo.cpp:9:1: warning: function 'foo' could be declared with attribute 'noreturn'
[-Wmissing-noreturn]
{
^
1 warning generated.
It appears to me that it would return! What's going on here? Is this a compiler bug?
If you remove the "= 1" from A, then it compiles fine without a warning.
If I do make the foo() function [[noreturn]] void foo(), then it does crash with a segmentation fault.
Ok sorry for delete the last answer. It was wrong. Ok noreturn meann that the function never end. and the segementation fould is because bar is not a variable
Just to give a follow up to an old question: clang is correct, even if a little pedantic.
Indeed the attribute noreturn is applicable to your foo() function, since it doesn't return anything. The fact that clang of 2016 gets confused with the slight variation in the enumeration that is a problem.
But we should forgive clang for this pecadillo, for C++11 grammar is not what could be called very simple.
When I compile this code:
template<typename T>
struct S {
std::vector<T> v;
S(initializer_list<T> l) : v(l) {
std::cout << "constructed with a " << l.size() << "-element list\n";
}
};
using the following command line:
clang++ -std=c++11 -stdlib=libc++ initializer_list.cpp
I get the following error.
initializer_list.cpp:12:23: error: expected ')'
S(initializer_list<T> l) : v(l) {
Does anyone know the fix if any??
Thanks in advance
You probably meant to write std::initializer_list<T>. Make sure you include <initializer_list>.
Your code sample is incomplete. It would be useful if you can provide a complete example. The problem with the code as written is that you're missing
#include <initializer_list>
#include <vector>
#include <iostream>
... and initializer_list is in namespace std, so you're also missing a std:: from your constructor declaration.
However, since you've claimed that neither of these is the issue, the most likely cause would seem to be that your C++ standard library implementation doesn't provide std::initializer_list. That would be the case if Clang is using GCC's libstdc++, and you do not have a suitably new version of that installed: you need at least version 4.4, but note that a patch is required to fix bugs in libstdc++-4.4 in order to make it work with Clang in C++11 mode, otherwise you will get errors about type_info and various other problems.
Also, you say that the diagnostic you received is this:
initializer_list.cpp:12:23: error: expected ')'
S(initializer_list<T> l) : v(l) {
^
(I've reconstructed the caret from the provided column number; it would be useful to preserve it in future questions.) For any of the above explanations, this will not be the first diagnostic which Clang produces; that would be something along the lines of:
initializer_list.cpp:12:5: error: no template named 'initializer_list'; did you mean 'std::initializer_list'?
S(initializer_list<T> l) : v(l) {
^~~~~~~~~~~~~~~~
std::initializer_list
So either you've missed out the first diagnostic from your question, or the problem is that you have declared some other (non-template) type named initializer_list in the code you omitted in your question, and that is hiding std::initializer_list. Without seeing the rest of your code or the rest of your diagnostics, it's not possible to tell which.
This compiles with out problems in VS 2009? Am I stupid?
GCC gives a warning, that the template is private....?
What am I missing?
#include <iostream>
using namespace std;
class A
{
private:
template<typename T>
A& operator<<(const T & v)
{
cout << v << endl;
return *this;
}
};
int main()
{
A a;
a << 4;
system("pause");
}
Microsoft acknowledges the bug and claims it will be fixed in the next major release for the compiler (which I read as VC11/VS-whatever-is-after-2010 - probably not a service pack for VC10/VS2010):
http://connect.microsoft.com/VisualStudio/feedback/details/649496/visual-c-doesnt-respect-the-access-modifier-for-operator-member-function-templates
from the comments, the fix appears to be already made to an internal compiler build.
This code should not compile - this is a bug (or silly extension) in VS. GCC should refuse it as well. The operator is inaccessible in the scope it is used.
Comeau treats this correctly:
"ComeauTest.c", line 28: error: function "A::operator<<(const T &) [with T=int]"
(declared at line 14) is inaccessible
a << 4;
EDIT: A relevant standard snippet, from 13.3/1
[Note: the function selected by
overload resolution is not guaranteed
to be appropriate for the context.
Other restrictions, such as the
accessibility of the function, can
make its use in the calling context
ill-formed. ]
No, you're not stupid - it's broken code and should be rejected. The Comeau compiler (http://www.comeaucomputing.com/tryitout) does correctly reject it.