re PR c++/83205 (ICE on structured binding with ill-formed negative std::tuple_size...
authorJakub Jelinek <jakub@redhat.com>
Fri, 15 Dec 2017 21:40:45 +0000 (22:40 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 15 Dec 2017 21:40:45 +0000 (22:40 +0100)
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.

From-SVN: r255706

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1z/decomp10.C
gcc/testsuite/g++.dg/cpp1z/decomp3.C
gcc/testsuite/g++.dg/cpp1z/decomp32.C [new file with mode: 0644]

index d96b679de630687f0c7065b667c4d317d07c0300..5c281004ef63e51a2536337fd8183154536fb0a4 100644 (file)
@@ -1,5 +1,11 @@
 2017-12-15  Jakub Jelinek  <jakub@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.
+
        PR c++/81197
        * cp-tree.h (cp_maybe_mangle_decomp): Declare.
        * decl.c (cp_maybe_mangle_decomp): New function.
index 0e6ee059e230474faa133d0ee9b3183e74d76e87..ca9e0c7b2058b2fda2c075526c23038d65bc3c2d 100644 (file)
@@ -7446,11 +7446,20 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
        {
        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);
@@ -7519,6 +7528,15 @@ cp_finish_decomp (tree decl, tree first, unsigned int count)
                         "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;
index ba86d2f938091f015acbe40638b749b3576f779d..7bbf0e9f09eadcebefe26068d19abf6e62307b78 100644 (file)
@@ -1,5 +1,12 @@
 2017-12-15  Jakub Jelinek  <jakub@redhat.com>
 
+       PR c++/83205
+       * 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.
+
        PR c++/81197
        * g++.dg/cpp1z/decomp34.C: New test.
 
index a841d3572ea87441bf408756badfb20788773cdb..6ed9272a2f4c02e348559c809018999c940deb3c 100644 (file)
@@ -11,7 +11,8 @@ void f1() { auto [ x ] = a1; }        // { dg-error "is not an integral constant expres
 
 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 }; };
index 71dc938daefd9859aadf19e53a644e050e01d8b3..529f3732fd5db7c77cd764919a4041c6bf417f8d 100644 (file)
@@ -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 }
 }
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp32.C b/gcc/testsuite/g++.dg/cpp1z/decomp32.C
new file mode 100644 (file)
index 0000000..a76d0c7
--- /dev/null
@@ -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 }