[clang] [clang][constexpr] Fix assertion failure in C++26 constexpr structured binding pack evaluation (#170991) (PR #213534)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 3 23:48:30 PDT 2026
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
More information about the cfe-commits
mailing list