On Fri, Dec 15, 2017 at 11:23:21PM +0100, Jakub Jelinek wrote: > Hi! > > I've backported today following 23 patches after bootstrapping/regtesting > them on x86_64-linux and i686-linux.
And 2 more: Jakub
2017-12-16 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2017-12-15 Jakub Jelinek <ja...@redhat.com> PR c++/81197 * cp-tree.h (cp_maybe_mangle_decomp): Declare. * decl.c (cp_maybe_mangle_decomp): New function. (cp_finish_decomp): Don't SET_DECL_ASSEMBLER_NAME here. * parser.c (cp_convert_range_for, cp_parser_decomposition_declaration): Call cp_maybe_mangle_decomp. * pt.c (tsubst_expr): Likewise. * mangle.c (find_decomp_unqualified_name): New function. (write_unqualified_name): Handle DECL_DECOMPOSITION_P where DECL_ASSEMBLER_NAME is already set. * g++.dg/cpp1z/decomp34.C: New test. --- gcc/cp/decl.c (revision 255704) +++ gcc/cp/decl.c (revision 255705) @@ -7339,6 +7339,25 @@ lookup_decomp_type (tree v) return *decomp_type_table->get (v); } +/* Mangle a decomposition declaration if needed. Arguments like + in cp_finish_decomp. */ + +void +cp_maybe_mangle_decomp (tree decl, tree first, unsigned int count) +{ + if (!processing_template_decl + && !error_operand_p (decl) + && DECL_NAMESPACE_SCOPE_P (decl)) + { + auto_vec<tree, 16> v; + v.safe_grow (count); + tree d = first; + for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d)) + v[count - i - 1] = d; + SET_DECL_ASSEMBLER_NAME (decl, mangle_decomp (decl, v)); + } +} + /* Finish a decomposition declaration. DECL is the underlying declaration "e", FIRST is the head of a chain of decls for the individual identifiers chained through DECL_CHAIN in reverse order and COUNT is the number of @@ -7612,8 +7631,6 @@ cp_finish_decomp (tree decl, tree first, DECL_HAS_VALUE_EXPR_P (v[i]) = 1; } } - else if (DECL_NAMESPACE_SCOPE_P (decl)) - SET_DECL_ASSEMBLER_NAME (decl, mangle_decomp (decl, v)); } /* Returns a declaration for a VAR_DECL as if: --- gcc/cp/pt.c (revision 255704) +++ gcc/cp/pt.c (revision 255705) @@ -16135,19 +16135,23 @@ tsubst_expr (tree t, tree args, tsubst_f if (VAR_P (decl)) const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (pattern_decl)); - cp_finish_decl (decl, init, const_init, NULL_TREE, 0); if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl) && TREE_TYPE (pattern_decl) != error_mark_node) { unsigned int cnt; tree first; - decl = tsubst_decomp_names (decl, pattern_decl, args, - complain, in_decl, &first, - &cnt); - if (decl != error_mark_node) - cp_finish_decomp (decl, first, cnt); + tree ndecl + = tsubst_decomp_names (decl, pattern_decl, args, + complain, in_decl, &first, &cnt); + if (ndecl != error_mark_node) + cp_maybe_mangle_decomp (ndecl, first, cnt); + cp_finish_decl (decl, init, const_init, NULL_TREE, 0); + if (ndecl != error_mark_node) + cp_finish_decomp (ndecl, first, cnt); } + else + cp_finish_decl (decl, init, const_init, NULL_TREE, 0); } } } --- gcc/cp/parser.c (revision 255704) +++ gcc/cp/parser.c (revision 255705) @@ -11735,6 +11735,9 @@ cp_convert_range_for (tree statement, tr tf_warning_or_error); finish_for_expr (expression, statement); + if (VAR_P (range_decl) && DECL_DECOMPOSITION_P (range_decl)) + cp_maybe_mangle_decomp (range_decl, decomp_first_name, decomp_cnt); + /* The declaration is initialized with *__begin inside the loop body. */ cp_finish_decl (range_decl, build_x_indirect_ref (input_location, begin, RO_NULL, @@ -13059,6 +13062,7 @@ cp_parser_decomposition_declaration (cp_ if (decl != error_mark_node) { + cp_maybe_mangle_decomp (decl, prev, v.length ()); cp_finish_decl (decl, initializer, non_constant_p, NULL_TREE, is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT); cp_finish_decomp (decl, prev, v.length ()); --- gcc/cp/mangle.c (revision 255704) +++ gcc/cp/mangle.c (revision 255705) @@ -1247,6 +1247,51 @@ write_template_prefix (const tree node) add_substitution (substitution); } +/* As the list of identifiers for the structured binding declaration + DECL is likely gone, try to recover the DC <source-name>+ E portion + from its mangled name. Return pointer to the DC and set len to + the length up to and including the terminating E. On failure + return NULL. */ + +static const char * +find_decomp_unqualified_name (tree decl, size_t *len) +{ + const char *p = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + const char *end = p + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl)); + bool nested = false; + if (strncmp (p, "_Z", 2)) + return NULL; + p += 2; + if (!strncmp (p, "St", 2)) + p += 2; + else if (*p == 'N') + { + nested = true; + ++p; + while (ISDIGIT (p[0])) + { + char *e; + long num = strtol (p, &e, 10); + if (num >= 1 && num < end - e) + p = e + num; + else + break; + } + } + if (strncmp (p, "DC", 2)) + return NULL; + if (nested) + { + if (end[-1] != 'E') + return NULL; + --end; + } + if (end[-1] != 'E') + return NULL; + *len = end - p; + return p; +} + /* We don't need to handle thunks, vtables, or VTTs here. Those are mangled through special entry points. @@ -1291,7 +1336,17 @@ write_unqualified_name (tree decl) { found = true; gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl)); - write_source_name (DECL_ASSEMBLER_NAME (decl)); + const char *decomp_str = NULL; + size_t decomp_len = 0; + if (VAR_P (decl) + && DECL_DECOMPOSITION_P (decl) + && DECL_NAME (decl) == NULL_TREE + && DECL_NAMESPACE_SCOPE_P (decl)) + decomp_str = find_decomp_unqualified_name (decl, &decomp_len); + if (decomp_str) + write_chars (decomp_str, decomp_len); + else + write_source_name (DECL_ASSEMBLER_NAME (decl)); } else if (DECL_DECLARES_FUNCTION_P (decl)) { --- gcc/cp/cp-tree.h (revision 255704) +++ gcc/cp/cp-tree.h (revision 255705) @@ -6149,6 +6149,7 @@ extern void start_decl_1 (tree, bool); extern bool check_array_initializer (tree, tree, tree); extern void cp_finish_decl (tree, tree, bool, tree, int); extern tree lookup_decomp_type (tree); +extern void cp_maybe_mangle_decomp (tree, tree, unsigned int); extern void cp_finish_decomp (tree, tree, unsigned int); extern int cp_complete_array_type (tree *, tree, bool); extern int cp_complete_array_type_or_error (tree *, tree, bool, tsubst_flags_t); --- gcc/testsuite/g++.dg/cpp1z/decomp34.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp1z/decomp34.C (revision 255705) @@ -0,0 +1,11 @@ +// PR c++/81197 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +struct X { int a; }; +struct Y { int b, c, d; }; +auto&& [t] = X{}; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } +namespace A { namespace B { auto&& [u, v, ww] = Y{}; } } // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + +// { dg-final { scan-assembler "_ZGRDC1tE0" } } +// { dg-final { scan-assembler "_ZGRN1A1BDC1u1v2wwEE1" } }
2017-12-16 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2017-12-15 Jakub Jelinek <ja...@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. * 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. --- gcc/cp/decl.c (revision 255705) +++ gcc/cp/decl.c (revision 255706) @@ -7446,11 +7446,20 @@ 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); + /* 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, "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; --- gcc/testsuite/g++.dg/cpp1z/decomp3.C (revision 255705) +++ gcc/testsuite/g++.dg/cpp1z/decomp3.C (revision 255706) @@ -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 "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { 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 "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } - auto [ l, m ] = b; // { dg-error "only 2 names provided while 'A' decomposes into 3 elements" } - // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } - auto & [ n, o, p, q ] = b; // { dg-error "4 names provided while 'A' decomposes into 3 elements" } - // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { 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 "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { 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 "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { 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 "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { 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 "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-2 } auto [] { c }; // { dg-error "empty decomposition declaration" } // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } - auto [ r, s ] = c; // { dg-error "2 names provided while 'B' decomposes into 1 elements" } - // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { 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 "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-2 } } --- gcc/testsuite/g++.dg/cpp1z/decomp10.C (revision 255705) +++ gcc/testsuite/g++.dg/cpp1z/decomp10.C (revision 255706) @@ -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 (nonexistent) +++ gcc/testsuite/g++.dg/cpp1z/decomp32.C (revision 255706) @@ -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 "decomposition declaration 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 "decomposition declaration 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 "decomposition declaration 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 "decomposition declaration only available with" "" { target c++14_down } .-2 }