From 38f4bea834ef4c25cd89c824f15ee8d6b30a3760 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 15 Dec 2017 22:40:45 +0100 Subject: [PATCH] re PR c++/83205 (ICE on structured binding with ill-formed negative std::tuple_size::value) 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 | 6 +++++ gcc/cp/decl.c | 26 ++++++++++++++++++---- gcc/testsuite/ChangeLog | 7 ++++++ gcc/testsuite/g++.dg/cpp1z/decomp10.C | 3 ++- gcc/testsuite/g++.dg/cpp1z/decomp3.C | 25 ++++++++++++--------- gcc/testsuite/g++.dg/cpp1z/decomp32.C | 32 +++++++++++++++++++++++++++ 6 files changed, 84 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp32.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d96b679de63..5c281004ef6 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2017-12-15 Jakub Jelinek + 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. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 0e6ee059e23..ca9e0c7b205 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ba86d2f9380..7bbf0e9f09e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,12 @@ 2017-12-15 Jakub Jelinek + 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. diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp10.C b/gcc/testsuite/g++.dg/cpp1z/decomp10.C index a841d3572ea..6ed9272a2f4 100644 --- a/gcc/testsuite/g++.dg/cpp1z/decomp10.C +++ b/gcc/testsuite/g++.dg/cpp1z/decomp10.C @@ -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 { 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 { enum { value = 1 }; }; diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp3.C b/gcc/testsuite/g++.dg/cpp1z/decomp3.C index 71dc938daef..529f3732fd5 100644 --- a/gcc/testsuite/g++.dg/cpp1z/decomp3.C +++ b/gcc/testsuite/g++.dg/cpp1z/decomp3.C @@ -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 index 00000000000..a76d0c7ace8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp32.C @@ -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 struct tuple_size; + template <> struct tuple_size { + static constexpr int value = -1; + }; +#ifdef __SIZEOF_INT128__ + template <> struct tuple_size { + 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 } -- 2.30.2