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

Reply via email to