babadany2999 wrote:

Hi @zwuis, thanks for the review!

I've used the following in my reasoning: 
[basic.def.odr](https://eel.is/c++draft/basic.def.odr) and 
[dcl.struct.bind](https://eel.is/c++draft/dcl.struct.bind).

According to `[basic.def.odr] p5`:

> A variable is named by an expression if the expression is an id-expression or 
> splice-expression ([[expr.prim.splice]]) that designates it.
    A variable x that is named by a potentially evaluated expression N that 
appears at a point P is odr-used by N unless[...]

The statement A variable is named by an expression if the expression is an 
id-expression applies here due to `[dcl.struct.bind] p1`:

> First, a variable with a unique name e is introduced.

To establish the bindings to the subobjects of `e`, expressions like 
```e.m_i```, ```e[i]```, or ```get<i>(e)``` are formed. Because these 
expressions do not appear in an unevaluated context, they are potentially 
evaluated expressions naming `e`. Therefore, `e` is odr-used unless one of the 
exceptions in `p5` applies.

Now checking the invariants:

`[basic.def.odr] p5.1`:

> x is a reference that is usable in constant expressions at P 
> ([[expr.const.init]])

According to `[dcl.struct.bind] p1`, in a **by-value** structured binding 
declaration (with no ref-qualifiers), `e` is defined as an object:

> If the assignment-expression in the initializer has array type cv1 A and no 
> ref-qualifier is present, e is defined by attribute-specifier-seqopt S cv A e 
> ; [...] Otherwise, e is defined as-if by attribute-specifier-seqopt 
> decl-specifier-seq ref-qualifieropt e initializer ;

Because `e` is an object and not a reference, `p5.1` does not apply.

`[basic.def.odr] p5.2`:

> N is an element of the set of potential results of an expression E, where
    [(5.2.1)] E is a discarded-value expression ([[expr.context]]) to which the 
lvalue-to-rvalue conversion is not applied, or
    [(5.2.2)] x is a non-volatile object that is usable in constant expressions 
at P and has no mutable subobjects, and
    [(5.2.2.1)] E is a class member access expression ([[expr.ref]]) naming a 
non-static data member of reference type and whose object expression has 
non-volatile-qualified type, or
    [(5.2.2.2)] the lvalue-to-rvalue conversion ([[conv.lval]]) is applied to E 
and E has non-volatile-qualified non-class type.

According to `[dcl.struct.bind] p3` and `[dcl.struct.bind] p6, p7 and p8`:

> (p3) Let SBi denote the ith structured binding in the structured binding 
> declaration after expanding the structured binding pack, if any.

> (p6) [...] Each SBi is the name of an lvalue that refers to the element i of 
> the array and whose type is T

> (p7) [...] Each SBi is the name of an lvalue of type Ti that refers to the 
> object bound to ri, [...]

> (p8) Designating the non-static data members of E as m0, m1, m2,… (in 
> declaration order), each SBi is the name of an lvalue that refers to the 
> member mi of e and whose type is that of e.mi ([[expr.ref]]);

Because paragraphs `6`, `7`, and `8` explicitly mandate that the expressions 
mapping `SBi` to `e` establish `lvalues` referring to the subobjects, the 
result of the expression is not discarded, which disproves `[(5.2.1)]`. 
Furthermore, because it establishes an `lvalue` alias to retain object 
identity, it does not undergo an `lvalue-to-rvalue` conversion, which disproves 
`[(5.2.2.2)]`.

Since none of the non-ODR-use exceptions apply, the hidden variable `e` is 
inherently ODR-used by the standard definition.

### Note
This is my first time reading the standard, so **please** point out where my 
reasoning is incorrect, whenever you have a moment.
I also hadn't used the reasoning when applying the fix; I basically just fixed 
the issue without knowing if that fix was correct according to the standard. As 
such, I will try to refer to the standard from now on to ensure that my fixes 
are strictly correct. Thank you for your review!

https://github.com/llvm/llvm-project/pull/213534
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to