Open xmh0511 opened 1 year ago
Presumably, we only need to check whether the consisted token sequences are the same.
No, we also need to check lookup results and same-partial-specializations etc.
The point of [basic.def.odr] p14.11 is "used by a function call (in D)":
Default arguments of a called function (if used) become part of the odr-check of the caller (in addition to being checked for the callee, it seems).
So, in the context "as if its token sequence were present in the definition of D;", do we check the associated type or something else regarding the token sequence, such as the token sequence composes a lambda-expression, just in the same way as we do for the entity that is defined in the definition? This is the concern in https://github.com/cplusplus/CWG/issues/272.
Or, the intent is that: if we explicitly exclude "entities defined within default arguments or default template arguments", the entities whose token sequences are assumed to be in the definition will be excluded by the rule.
It is even that we cannot find the formal rule that can interpret the following explanation
If the definition of g appears in multiple translation units, the program is ill-formed (no diagnostic required) because each such definition uses a default argument that refers to a distinct lambda-expression closure type.
inline void g(bool cond, void (*p)() = []{}) {
if (cond) g(false);
}
[basic.def.odr] p14.11 says:
is treated as if its token sequence were present in the definition of D; that is, the default argument or default template argument is subject to the requirements described in this paragraph (recursively).
Then [basic.def.odr] p14.4 says:
Each such definition shall consist of the same sequence of tokens, where the definition of a closure type is considered to consist of the sequence of tokens of the corresponding lambda-expression.
They have the same token sequence, hence their closure types are the same. Moreover, [basic.def.odr] p14.6 explicitly says it does not apply to default argument
In each such definition, except within the default arguments and default template arguments of D, corresponding lambda-expressions shall have the same closure type (see below).
So, there is no rule that requires the lambda-expression appearing in the default argument shall have the same type, anyway.
They have the same token sequence, hence their closure types are the same.
That is, in general, not the case.
Closure types can differ unless a surrounding ODR application (e.g. to an enclosing class) causes the "single definition" interpretation.
There is nothing that would cause the "single definition" interpretation for the default argument, so the values of the default arguments can differ. When we're using that default argument, we're inlining the definition of the closure type into the definition of the g
(per the default argument rule), which causes the ODR check on g
to fail.
There is nothing that would cause the "single definition" interpretation for the default argument, so the values of the default arguments can differ. When we're using that default argument, we're inlining the definition of the closure type into the definition of the
g
(per the default argument rule), which causes the ODR check ong
to fail.
This is the issue here. There is no bullet imposing the requirement that the closure type of the lambda-expression in the default argument shall have the same type. After all, the only bullet that requires the lambda-expression to have the same type is [basic.def.odr] p14.6
In each such definition, except within the default arguments and default template arguments of D, corresponding lambda-expressions shall have the same closure type (see below).
However, it has explicitly excluded it from applying to the lambda-expression within the default arguments.
This is the issue here. There is no bullet imposing the requirement that the closure type of the lambda-expression in the default argument shall have the same type.
And that's how we want it to be, so the status quo is good, right?
And that's how we want it to be, so the status quo is good, right?
If there is no bullet in the list imposing the requirement, that they shall be the same, on the closure type of the lambda-expression in the default argument, then the explanation is wrong
If the definition of g appears in multiple translation units, the program is ill-formed (no diagnostic required) because each such definition uses a default argument that refers to a distinct lambda-expression closure type.
The example
inline void g(bool cond, void (*p)() = []{}) {
if (cond) g(false);
}
should be ok.
Full name of submitter (unless configured in github; will be published with the issue): Jim X
[basic.def.odr] p14.11 says:
According to [basic.def] p2, a definition of
D
is alsoD
's declaration, then according to grammar, all default arguments are presented in the declaration ofD
, so this is true to say the default arguments are presented in the definition ofD
, so why do we need to assume an entity that is presented in the definition as if it were presented in that definition? This is obscure. According to the context, we may want to interpret the "definition" to the body of a function.Furthermore, the [basic.def.odr] p14.11 has its issue that
What is the intent of this wording? Do we need to check whether the closure type satisfies the requirements for the default argument if it is a closure expression because of the wording "recursively"?
Presumably, we only need to check whether the consisted token sequences are the same. The relevant issue is https://github.com/cplusplus/CWG/issues/272