I have a simple code snippet shown below (https://godbolt.org/z/cPT3PhYdj):
int main() {
int x = 1;
auto(1); // why
auto{1}; // why
static_cast<void>(auto(x)); // ok
auto{x}; // why
auto(x); // why
}
Where both GCC and Clang emit an error showing:
// by GCC Trunk [-std=c 23]
<source>: In function 'int main()':
<source>:7:3: error: declaration of 'auto x' has no initializer
7 | auto(x); // why
| ^~~~
Compiler returned: 1
// by Clang Trunk [-std=c 2b]
<source>:3:8: error: expected unqualified-id
auto(1); // why
^
<source>:3:8: error: expected ')'
<source>:3:7: note: to match this '('
auto(1); // why
^
<source>:4:7: error: expected unqualified-id
auto{1}; // why
^
<source>:6:7: error: expected unqualified-id
auto{x}; // why
^
<source>:7:8: error: redefinition of 'x'
auto(x); // why
^
<source>:2:7: note: previous definition is here
int x = 1;
^
<source>:7:8: error: declaration of variable 'x' with deduced type 'auto' requires an initializer
auto(x); // why
^
6 errors generated.
Compiler returned: 1
Are these expressions supposed to be parsed as explicit type decay conversion auto(expr)
or auto{expr}
in expression statements or parsed as a declaration?
If auto(identifier)
is reinterpreted as auto identifier
, then which priority comes first, the declaration or the auto(identifer)
cast expression?
CodePudding user response:
From Explicit cast conversion:
auto ( expression ) (8) (since C 23) auto { expression } (9) (since C 23)
8,9) The
auto
specifier is replaced with the deduced type of the invented variablex
declared withauto x(expression);
(which is never interpreted as a function declaration) orauto x{expression};
respectively. The result is always a prvalue of an object type.
So your usage seems to be allowed(in accordance with ) by the above quoted statement.
Here is a working demo of your code. Note in the linked demo, only the usage auto(x)
produces an error, all other cases work fine.
Also note that from PR105516:
auto(x);
is interpreted asauto x;
. Useauto(x);
if you want that to be an expression.
CodePudding user response:
As far as I can tell the paper introducing this feature didn't make any further relevant changes except to allow auto
as type specifier in a functional-style explicit cast.
So intuitively auto
here should behave the same as any other type specifier would.
For example, replacing auto
with int
, it is expected that all of these cases work and are functional-style explicit casts, except
int(x); // auto(x);
This one could according to the grammar also be a declaration of a variable named x
of type int
(or placeholder type) with parentheses around the declarator and without initializer.
As usual, the grammar is disambiguated by preferring the interpretation as declaration (see [stmt.ambig]/1). At least, I don't think that it should be different for auto
. A declaration with auto
placeholder type requires an initializer, which is not present in this interpretation, but according to [stmt.ambig]/3 the disambiguation is supposed to be done very early and purely syntactic even if it ends up in an ill-formed declaration. I am not completely sure but I guess this should mean that auto(x);
should still be disambiguated as a declaration.
I don't know why Clang gives errors for many of the other lines. I suppose the feature is either implemented only partially or these are implementation bugs (it is a very new feature in an unfinished standard revision).