Is Type(::x); valid?
c++, compiler-errors, declaration, expression, language-lawyer
Solution
As far as I can tell this is covered by draft C++ standard section `8.3` Meaning of declarators paragraph 6 which says (emphasis mine going forward):
In a declaration T D where D has the form
( D1 )
the type of the contained declarator-id is the same as that of the contained declarator-id in the declaration
T D1
Parentheses do not alter the type of the embedded declarator-id, but they can alter the binding of complex declarators.
so:
int(::x);
is equivalent to:
int ::x ;
which is clearly not valid, and this produces the same error as well. So `gcc 4.9` is not correct here but since this looks fixed in the `gcc 4.8.3` which was released later I would expect this to be fixed in later releases of `4.9` as well. Although I don't see any obvious matches for this issue in the gcc 4.8.3 bugs fixed list but they don't claim it is a complete list.
The second case is a functional explicit type conversion which is covered in section `5.2.3` Explicit type conversion (functional notation) which says:
A simple-type-specifier (7.1.6.2) or typename-specifier (14.6) followed by a parenthesized expression-list constructs a value of the specified type given the expression list. If the expression list is a single expression, the type conversion expression is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression (5.4).[...]
This is unambiguous since `::x + 2` is an expression.
The section that covers when a statement is considered a declaration or a expression is `6.8` Ambiguity resolution which says:
There is an ambiguity in the grammar involving expression-statements and declarations: An expressionstatement with a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration. [ Note: To disambiguate, the whole statement might have to be examined to determine if it is an expression-statement or a declaration. This disambiguates many examples.
and provides the following examples:
T(a)->m = 7; // expression-statement
T(a)++; // expression-statement
T(a,5)<<c; // expression-statement
T(*d)(int); // declaration
T(e)[5]; // declaration
T(f) = { 1, 2 }; // declaration
T(*g)(double(3)); // declaration
Note: without the `()` then `T ::D` is a qualified-id in the case of `T` being a class, that is a covered in the grammar of `5.1` Primary expressions.
Update
Filed a gcc bug report.
gcc's response is that:
Current G++ and EDG both treat it as the valid expression (int)::x
Since this response implies `clang` is incorrect(I don't agree though), I filed a clang bug report and older bug report looks similar and seems to disagree with the `gcc` response.
Update 2
In response to the `clang bug report` Richard Smith agrees this should be treated as a declaration and says:
That does not imply clang is incorrect; in fact, Clang is correct here, as far as I can see. (I've also sent a bug report to EDG.)
That said, we should give a proper 'you hit a vexing parse, here's how to disambiguate' error in this case.
Update 3
`gcc` confirms it is a bug.
Problem
While discussing the `Type(identifier);` syntax and how it's a declaration, I came across `Type(::x);` not working with Clang. I would expect that given a global variable `x`, it would treat `::x` as an expression (`::x + 2` works) and cast `::x` to `Type`. However, it gives a compiler error. Here is a short example: ``` int x; int main() { int(::x); //does not compile int(::x + 2); //compiles } ``` The compiler error given by Clang 3.5 is: error: definition or redeclaration of 'x' cannot name the global scope GCC 4.9.0, however, compiles this just fine. Is this code valid or not?