On Fri, Dec 15, 2017 at 08:09:20PM +0100, Jakub Jelinek wrote: > On Fri, Dec 15, 2017 at 02:01:36PM -0500, Jason Merrill wrote: > > On 11/29/2017 08:19 PM, Martin Sebor wrote: > > > On 11/29/2017 03:32 PM, Jakub Jelinek wrote: > > > > + if (!tree_fits_uhwi_p (tsize)) > > > > + { > > > > + error_at (loc, "%u names provided while %qT decomposes into " > > > > > > When count is 1 as in the test below the error isn't grammatically > > > correct ("1 names"). I see that the same message is already issued > > > elsewhere in the function so this seems like an opportunity to use > > > the right form here and also fix the other one at the same time or > > > in a followup. The error_n function exists to issue the right form > > > for the language, singular or plural. It's not as convenient when > > > the sentence contains two terms that may be singular or plural, > > > but that can also be dealt with. > > > > Agreed. > > Yeah, I've implemented it as an incremental patch. > So > http://gcc.gnu.org/ml/gcc-patches/2017-11/msg02521.html > for the ICE and > http://gcc.gnu.org/ml/gcc-patches/2017-11/msg02538.html > on top of it. The latter is what Nathan approved already, the former > needs review.
If it helps any, here are the 2 patches combined, re-tested on x86_64-linux with check-c++-all. 2017-12-15 Jakub Jelinek <ja...@redhat.com> PR c++/83205 * decl.c (cp_finish_decomp): Handle the case when tsize is not error_mark_node, but doesn't fit into uhwi. Split up count != eltscnt and !tree_fits_uhwi_p (tsize) error_at calls into error_n and inform_n to handle plural forms properly. * g++.dg/cpp1z/decomp3.C: Adjust for structured binding count mismatch diagnostics split into error and warning with plural forms. * g++.dg/cpp1z/decomp10.C: Likewise. * g++.dg/cpp1z/decomp32.C: New test. --- gcc/cp/decl.c.jj 2017-12-15 20:40:00.601221086 +0100 +++ gcc/cp/decl.c 2017-12-15 20:42:25.917445216 +0100 @@ -7427,11 +7427,20 @@ cp_finish_decomp (tree decl, tree first, { cnt_mismatch: if (count > eltscnt) - error_at (loc, "%u names provided while %qT decomposes into " - "%wu elements", count, type, eltscnt); + error_n (loc, count, + "%u name provided for structured binding", + "%u names provided for structured binding", count); else - error_at (loc, "only %u names provided while %qT decomposes into " - "%wu elements", count, type, eltscnt); + error_n (loc, count, + "only %u name provided for structured binding", + "only %u names provided for structured binding", count); + /* Some languages have special plural rules even for large values, + but it is periodic with period of 10, 100, 1000 etc. */ + inform_n (loc, eltscnt > INT_MAX + ? (eltscnt % 1000000) + 1000000 : eltscnt, + "while %qT decomposes into %wu element", + "while %qT decomposes into %wu elements", + type, eltscnt); goto error_out; } eltype = TREE_TYPE (type); @@ -7500,6 +7509,15 @@ cp_finish_decomp (tree decl, tree first, "constant expression", type); goto error_out; } + if (!tree_fits_uhwi_p (tsize)) + { + error_n (loc, count, + "%u name provided for structured binding", + "%u names provided for structured binding", count); + inform (loc, "while %qT decomposes into %E elements", + type, tsize); + goto error_out; + } eltscnt = tree_to_uhwi (tsize); if (count != eltscnt) goto cnt_mismatch; --- gcc/testsuite/g++.dg/cpp1z/decomp3.C.jj 2017-11-30 11:18:00.078805693 +0100 +++ gcc/testsuite/g++.dg/cpp1z/decomp3.C 2017-12-15 20:42:25.917445216 +0100 @@ -51,16 +51,21 @@ int arr[4]; void test3 (A &b, B c) { - auto [ d, e, f ] = arr; // { dg-error "only 3 names provided while 'int .4.' decomposes into 4 elements" } - // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-1 } - auto & [ g, h, i, j, k ] = arr; // { dg-error "5 names provided while 'int .4.' decomposes into 4 elements" } - // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-1 } - auto [ l, m ] = b; // { dg-error "only 2 names provided while 'A' decomposes into 3 elements" } - // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-1 } - auto & [ n, o, p, q ] = b; // { dg-error "4 names provided while 'A' decomposes into 3 elements" } - // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-1 } + auto [ d, e, f ] = arr; // { dg-error "only 3 names provided" } + // { dg-message "while 'int .4.' decomposes into 4 elements" "" { target *-*-* } .-1 } + // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-2 } + auto & [ g, h, i, j, k ] = arr; // { dg-error "5 names provided" } + // { dg-message "while 'int .4.' decomposes into 4 elements" "" { target *-*-* } .-1 } + // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-2 } + auto [ l, m ] = b; // { dg-error "only 2 names provided" } + // { dg-message "while 'A' decomposes into 3 elements" "" { target *-*-* } .-1 } + // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-2 } + auto & [ n, o, p, q ] = b; // { dg-error "4 names provided" } + // { dg-message "while 'A' decomposes into 3 elements" "" { target *-*-* } .-1 } + // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-2 } auto [] { c }; // { dg-error "empty structured binding declaration" } // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-1 } - auto [ r, s ] = c; // { dg-error "2 names provided while 'B' decomposes into 1 elements" } - // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-1 } + auto [ r, s ] = c; // { dg-error "2 names provided" } + // { dg-message "while 'B' decomposes into 1 element" "" { target *-*-* } .-1 } + // { dg-warning "structured bindings only available with -std=c..17 or -std=gnu..17" "" { target c++14_down } .-2 } } --- gcc/testsuite/g++.dg/cpp1z/decomp10.C.jj 2017-11-30 11:18:00.102805393 +0100 +++ gcc/testsuite/g++.dg/cpp1z/decomp10.C 2017-12-15 20:42:25.918445204 +0100 @@ -11,7 +11,8 @@ void f1() { auto [ x ] = a1; } // { dg-e struct A2 { int i,j; } a2; template<> struct std::tuple_size<A2> { enum { value = 5 }; }; -void f2() { auto [ x ] = a2; } // { dg-error "decomposes into 5" } +void f2() { auto [ x ] = a2; } // { dg-error "only 1 name provided" } + // { dg-message "decomposes into 5" "" { target *-*-* } .-1 } struct A3 { int i,j; } a3; template<> struct std::tuple_size<A3> { enum { value = 1 }; }; --- gcc/testsuite/g++.dg/cpp1z/decomp32.C.jj 2017-12-15 20:42:58.977041204 +0100 +++ gcc/testsuite/g++.dg/cpp1z/decomp32.C 2017-12-15 20:42:25.918445204 +0100 @@ -0,0 +1,32 @@ +// PR c++/83205 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +struct A { int i; }; +struct B { int i; }; +namespace std { + template <typename T> struct tuple_size; + template <> struct tuple_size<A> { + static constexpr int value = -1; + }; +#ifdef __SIZEOF_INT128__ + template <> struct tuple_size<B> { + static constexpr unsigned __int128 value = -1; + }; +#endif +} + +auto [a] = A{}; // { dg-error "1 name provided" } + // { dg-message "while 'A' decomposes into -1 elements" "" { target *-*-* } .-1 } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-2 } +#ifdef __SIZEOF_INT128__ +auto [b] = B{}; // { dg-error "1 name provided" "" { target int128 } } + // { dg-message "while 'B' decomposes into \[0-9xa-fXA-F]* elements" "" { target int128 } .-1 } + // { dg-warning "structured bindings only available with" "" { target { c++14_down && int128 } } .-2 } +auto [c, d] = B{}; // { dg-error "2 names provided" "" { target int128 } } + // { dg-message "while 'B' decomposes into \[0-9xa-fXA-F]* elements" "" { target int128 } .-1 } + // { dg-warning "structured bindings only available with" "" { target { c++14_down && int128 } } .-2 } +#endif +auto [e, f, g] = A{}; // { dg-error "3 names provided" } + // { dg-message "while 'A' decomposes into -1 elements" "" { target *-*-* } .-1 } + // { dg-warning "structured bindings only available with" "" { target c++14_down } .-2 } Jakub