On Tue, Jan 10, 2017 at 02:03:14PM -0500, Jason Merrill wrote: > The FI20 comment on the decomposition declarations proposal complained > that the syntax unnecessarily excluded parenthesized initialization. > This patch implements the resolution. > > Tested x86_64-pc-linux-gnu, applying to trunk.
> commit 749ec367e50b356a40fd41a3daae10d9d948062b > Author: Jason Merrill <ja...@redhat.com> > Date: Mon Jan 9 17:33:42 2017 -0500 > > FI 20, decomposition declaration with parenthesized initializer. > > * parser.c (cp_parser_decomposition_declaration): Use > cp_parser_initializer. I had a testcase for this from the time when I've been trying to implement FI 20 myself. Here is just the testcase change, but it fails, instead of invoking the explicit A (const A &x) ctor I was expecting for auto [b,c,d,e,f,g] ( a );, that is the ctor invoked also for auto [b,c,d,e,f,g] { a };, it is invoking the template <typename T> A (const T &x) ctor that is invoked for auto [b,c,d,e,f,g] = a; So, is auto [b,c,d,e,f,g] ( a ); direct initialization like auto [b,c,d,e,f,g] { a }; or is it copy initialization like auto [b,c,d,e,f,g] = a; ? Note, I've tried to compile the decomp6.C testcase (and all other decomp* testcases) with svn trunk clang++ too, and it fails on the auto [b,c,d,e,f,g] { a }; on line 62 already: decomp6.C:12:24: error: member reference base type 'A const[6]' is not a structure or union A (const T &x) : a (x.a) { tccnt++; } ~^~ decomp6.C:62:28: note: in instantiation of function template specialization 'A::A<A [6]>' requested here auto [b,c,d,e,f,g] { a }; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } ^ Is that a clang++ bug, right? That said, when I change that line 62 to: auto [b,c,d,e,f,g] ( a );, the test passes with clang++ even when patched with the patch, so (a) seems to be treated as direct-initialization. clang++ ICEd on a bunch of testcases, but when it didn't, appart from decomp6.C matched my expectations on where errors should be reported and where not. Lastly, I have a testcase I'm not sure about: int a[3]; struct S { int b, c, d; } s; void foo () { auto [ b, c, d ] = a; auto [ e, f, g ] = s; auto [ h, i, j ] { s }; auto [ k, l, m ] { s, }; auto [ n, o, p ] { a }; // { dg-error "invalid conversion from 'int.' to 'int'" } auto [ q, r, t ] ( s ); auto [ u, v, w ] ( s, ); // { dg-error "expected primary-expression before '.' token" } auto [ x, y, z ] ( a ); // { dg-error "expression list treated as compound expression in initializer" "" { target *-*-* } .-1 } } but where clang++ actually matches the current g++ behavior. In the https://github.com/cplusplus/draft/commit/6f3920a66311ec2893a9e30ce2b54cecba4951ba wording, it talks only about assignment-expression in between () or {}, does that mean: auto [ k, l, m ] { s, }; should be invalid? And is the auto [ n, o, p ] { a }; error a bug or not (though clang++ agrees on that with g++). We don't error on auto [ x, y, z ] ( a ); 2017-01-11 Jakub Jelinek <ja...@redhat.com> FI 20, decomposition declaration with parenthesized initializer. * g++.dg/cpp1z/decomp6.C (main): Add further tests. --- gcc/testsuite/g++.dg/cpp1z/decomp6.C.jj 2016-11-14 08:52:27.000000000 +0100 +++ gcc/testsuite/g++.dg/cpp1z/decomp6.C 2016-11-29 18:11:33.000000000 +0100 @@ -89,4 +89,40 @@ main () } if (ccnt != 12 || dcnt != 24 || cccnt != 6 || tccnt != 6) __builtin_abort (); + + { + A a[6]; + if (ccnt != 18 || dcnt != 24 || cccnt != 6 || tccnt != 6) + __builtin_abort (); + { + auto [b,c,d,e,f,g] ( a ); // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + if (ccnt != 18 || dcnt != 24 || cccnt != 12 || tccnt != 6) + __builtin_abort (); + b.a++; + c.a += 2; + f.a += 3; + if (b.a != 7 || c.a != 8 || d.a != 6 || e.a != 6 || f.a != 9 || g.a != 6) + __builtin_abort (); + if (&b == &a[0] || &c == &a[1] || &d == &a[2] || &e == &a[3] || &f == &a[4] || &g == &a[5]) + __builtin_abort (); + { + auto&[ h, i, j, k, l, m ] (a); // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + if (ccnt != 18 || dcnt != 24 || cccnt != 12 || tccnt != 6) + __builtin_abort (); + j.a += 4; + k.a += 5; + m.a += 6; + if (a[0].a != 6 || a[1].a != 6 || a[2].a != 10 || a[3].a != 11 || a[4].a != 6 || a[5].a != 12) + __builtin_abort (); + if (&h != &a[0] || &i != &a[1] || &j != &a[2] || &k != &a[3] || &l != &a[4] || &m != &a[5]) + __builtin_abort (); + } + if (ccnt != 18 || dcnt != 24 || cccnt != 12 || tccnt != 6) + __builtin_abort (); + } + if (ccnt != 18 || dcnt != 30 || cccnt != 12 || tccnt != 6) + __builtin_abort (); + } + if (ccnt != 18 || dcnt != 36 || cccnt != 12 || tccnt != 6) + __builtin_abort (); } Jakub