If one defines a new variable in C , then the name of the variable can be used in the initialization expression, for example:
int x = sizeof(x);
And what about default value of a function argument? Is it allowed there to reference the argument by its name? For example:
void f(int y = sizeof(y)) {}
This function is accepted in Clang, but rejected in GCC with the error:
'y' was not declared in this scope
Demo: https://gcc.godbolt.org/z/YsvYnhjTb
Which compiler is right here?
CodePudding user response:
According tp the C 17 Standard (11.3.6 Default arguments)
9 A default argument is evaluated each time the function is called with no argument for the corresponding parameter. A parameter shall not appear as a potentially-evaluated expression in a default argument. Parameters of a function declared before a default argument are in scope and can hide namespace and class member name
And there is provided an example
int h(int a, int b = sizeof(a)); // OK, unevaluated operand
So this function declaration
void f(int y = sizeof(y)) {}
is correct because in this expression sizeof( y )
y
is not an evaluated operand.
(The C 17 Standard, 8.3.3 Sizeof)
1 The sizeof operator yields the number of bytes in the object representation of its operand. The operand is either an expression, which is an unevaluated operand (Clause 8), or a parenthesized type-id.
And ( The C 17 Standard, 6.3.2 Point of declaration)
1 The point of declaration for a name is immediately after its complete declarator (Clause 11) and before its initializer (if any), except as noted below.
CodePudding user response:
The code does not appear ill-formed, so Clang is alright.
[basic.scope.pdecl]
1 The point of declaration for a name is immediately after its complete declarator ([dcl.decl]) and before its initializer (if any), except as noted below.
This is the notorious passage that is under discussion. I bring it here just to mention that "except as noted below" doesn't include any mention of default arguments. So y
is declared right before = sizeof(y)
.
The other relevant paragraph is
[dcl.fct.default]
9 A default argument is evaluated each time the function is called with no argument for the corresponding parameter. A parameter shall not appear as a potentially-evaluated expression in a default argument. Parameters of a function declared before a default argument are in scope and can hide namespace and class member names.
sizeof(y)
is not potentially evaluated, so this is also fine.
Seeing as the first paragraph makes y
available as a name, and it's used in a way that is not illegal, must be some quirk of GCC that rejects the code.
Though personally, I don't see it as a great loss. This is not the most practical bit of code.