Here, we had DECL_VALUE_EXPR of a structured binding referring to a pass-by-invisible-reference parameter, but not being adjusted by cp_genericize. We get here because we were looking through a reference temporary. Removing that code doesn't seem to break anything; I'm guessing that it isn't needed anymore because of my change to support references better in constexpr evaluation.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 793633ca2cbbcd2ba9175320728745d6ebcba9e8 Author: Jason Merrill <ja...@redhat.com> Date: Sat Mar 18 23:47:50 2017 -0400 PR c++/80084 - wrong C++17 decomposition by reference of parameter. * decl.c (cp_finish_decomp): Don't pull out the DECL_INITIAL of a reference decomposition. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index bf24e8b..0a92566 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7439,9 +7439,6 @@ cp_finish_decomp (tree decl, tree first, unsigned int count) if (TREE_CODE (type) == REFERENCE_TYPE) { - /* If e is a constant reference, use the referent directly. */ - if (DECL_INITIAL (decl)) - dexp = DECL_INITIAL (decl); dexp = convert_from_reference (dexp); type = TREE_TYPE (type); } diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp27.C b/gcc/testsuite/g++.dg/cpp1z/decomp27.C new file mode 100644 index 0000000..f26722a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp27.C @@ -0,0 +1,26 @@ +// PR c++/80084 +// { dg-options -std=c++1z } +// { dg-do run } + +struct A +{ + A() { } + A(const A&) { } +}; + +struct B +{ + A a; +}; + +void f(B b) +{ + auto& [a] = b; + if (&a != &b.a) + __builtin_abort(); +} + +int main() +{ + f(B()); +}