diff options
author | Jakub Jelinek <jakub@redhat.com> | 2017-12-15 22:40:45 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2017-12-15 22:40:45 +0100 |
commit | 38f4bea834ef4c25cd89c824f15ee8d6b30a3760 (patch) | |
tree | 4b137515b1818687477804ac20f81ccca104b582 /gcc | |
parent | 70356f771a65b378362b08d5fdb926fbb88e4aa7 (diff) | |
download | gcc-38f4bea834ef4c25cd89c824f15ee8d6b30a3760.zip gcc-38f4bea834ef4c25cd89c824f15ee8d6b30a3760.tar.gz gcc-38f4bea834ef4c25cd89c824f15ee8d6b30a3760.tar.bz2 |
re PR c++/83205 (ICE on structured binding with ill-formed negative std::tuple_size<T>::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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/decl.c | 26 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/decomp10.C | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/decomp3.C | 25 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp1z/decomp32.C | 32 |
6 files changed, 84 insertions, 15 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d96b679..5c28100 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 0e6ee05..ca9e0c7 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 ba86d2f..7bbf0e9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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. diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp10.C b/gcc/testsuite/g++.dg/cpp1z/decomp10.C index a841d35..6ed9272 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<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 }; }; diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp3.C b/gcc/testsuite/g++.dg/cpp1z/decomp3.C index 71dc938..529f373 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 0000000..a76d0c7 --- /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 <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 } |