On Wed, Nov 29, 2017 at 06:19:04PM -0700, Martin Sebor wrote: > > --- gcc/cp/decl.c.jj 2017-11-28 22:23:34.000000000 +0100 > > +++ gcc/cp/decl.c 2017-11-29 15:00:24.487658715 +0100 > > @@ -7518,6 +7518,12 @@ cp_finish_decomp (tree decl, tree first, > > "constant expression", type); > > goto error_out; > > } > > + 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.
Here is an incremental patch to deal with that on top of the previously posted patch, ok for trunk if it passes testing? Note, not using inform_n in this !tree_fits_uhwi_p case, because gettext doesn't recommend that for negative values and the other values printed there (the very large ones) are printed using hexadecimal where also I think human plural forms are rarely useful. 2017-11-30 Jakub Jelinek <ja...@redhat.com> * decl.c (cp_finish_decomp): 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: Likewise. --- gcc/cp/decl.c.jj 2017-11-30 09:44:19.000000000 +0100 +++ gcc/cp/decl.c 2017-11-30 09:57:44.539504854 +0100 @@ -7445,11 +7445,18 @@ 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); + inform_n (loc, eltscnt != (unsigned long) eltscnt + ? (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); @@ -7520,8 +7527,11 @@ cp_finish_decomp (tree decl, tree first, } if (!tree_fits_uhwi_p (tsize)) { - error_at (loc, "%u names provided while %qT decomposes into " - "%E elements", count, type, 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); --- gcc/testsuite/g++.dg/cpp1z/decomp3.C.jj 2017-09-15 18:11:04.000000000 +0200 +++ gcc/testsuite/g++.dg/cpp1z/decomp3.C 2017-11-30 10:09:42.756619330 +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-09-15 18:11:04.000000000 +0200 +++ gcc/testsuite/g++.dg/cpp1z/decomp10.C 2017-11-30 10:03:08.356491129 +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-11-30 09:44:19.000000000 +0100 +++ gcc/testsuite/g++.dg/cpp1z/decomp32.C 2017-11-30 10:09:53.126490397 +0100 @@ -16,9 +16,17 @@ namespace std { #endif } -auto [a] = A{}; // { dg-error "1 names provided while 'A' decomposes into -1 elements" } - // { dg-warning "structured bindings only available with" "" { target c++14_down } .-1 } +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 names provided while 'B' decomposes into \[0-9xa-fXA-F]* elements" "" { target int128 } } - // { dg-warning "structured bindings only available with" "" { target { c++14_down && int128 } } .-1 } +auto [b] = B{}; // { dg-error "1 name provided" } + // { 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" } + // { 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