Somebody had asked the other day why something compiles with clang, but not with gcc. I intuitively understood what was happening and was able to help the person, but it got me wondering -- according to the standard, which compiler was correct? Here is a boiled down version of the code:
#include <iostream>
#include <string>
class foo
{
public:
foo(const std::string& x):
name(x)
{ }
foo& operator()(const std::string& x)
{
std::cout << name << ": " << x << std::endl;
return (*this);
}
std::string name;
};
int main()
{
std::string x = "foo";
foo(x)("bar")("baz");
return 0;
}
This compiles fine with clang++, but g++ gives the following error:
runme.cpp: In function ‘int main()’:
runme.cpp:21:11: error: conflicting declaration ‘foo x’
foo(x)("bar")("baz");
^
runme.cpp:20:17: error: ‘x’ has a previous declaration as ‘std::string x’
std::string x = "foo";
If I add a pair of parentheses in line 21, g++ is happy:
(foo(x))("bar")("baz");
In other words, g++ interprets this line as:
foo x ("bar")("baz");
Methinks itsa bug in g++, but again, I wanted to ask the standard experts, which compiler got it wrong?
PS: gcc-4.8.3, clang-3.5.1
If we remove the line
then g++ complains about:
with the syntax error:
I do not see how
foo (x)("bar")("baz");
could be a valid declaration, and apparently g++ can't either. The linefoo x("bar")("baz");
is rejected with the same error.The "ambiguity resolution" mentioned in Shafik's post only kicks in when the expression-statement is syntactically indistinguishable from a declaration. However in this case it is not a valid declaration syntax so there is no ambiguity, it must be an expression-statement.
g++ fails to process the line as an expression-statement so it is a g++ bug.
This is eerily similar to this g++ bug recently discussed on SO; it seems that g++ is perhaps deciding too soon in processing that the line must be a declaration .
As far as I can tell this is covered in the draft C++ standard section
6.8
Ambiguity resolution which says that there can be an ambiguity between expression statements and declarations and says:and gives the following examples:
and then says:
It seems like this case falls into the declaration examples in particular the last example seems to make the case in the OP, sogcc
would be correct then.Relevant section mentioned above
5.2.3
Explicit type conversion (functional notation) says:and
8.3
Meaning of declarators which says:Update
I was originally using N337 but if we look at N4296 section
6.8
was updated an it now includes the following note:which means that
gcc
is incorrect since:can not be a valid declaration, I originally interpreted paragraph
2
as saying if you case begins with any of the following then it is declaration, which is perhaps how thegcc
implementor interpreted as well.I should have been more suspicious of paragraph
2
since the only normative part of paragraph2
really said nothing with respect to paragraph1
and seems to place a requirement on an example which is not normative. We can see that that statement form paragraph2
is now actually a note which makes much more sense.As T.C. noted below, paragraph
2
was actually never normative, it just appeared that way and he linked to the change that fixed it.