From 70356f771a65b378362b08d5fdb926fbb88e4aa7 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 15 Dec 2017 22:39:20 +0100 Subject: [PATCH] re PR c++/81197 (ICE with structured binding and lifetime-extended temporaries) 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. From-SVN: r255705 --- gcc/cp/ChangeLog | 11 ++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/decl.c | 21 +++++++++- gcc/cp/mangle.c | 57 ++++++++++++++++++++++++++- gcc/cp/parser.c | 4 ++ gcc/cp/pt.c | 16 +++++--- gcc/testsuite/ChangeLog | 3 ++ gcc/testsuite/g++.dg/cpp1z/decomp34.C | 11 ++++++ 8 files changed, 115 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp34.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 488b9f3f599..d96b679de63 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,16 @@ 2017-12-15 Jakub Jelinek + 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. + PR c++/80135 PR c++/81922 * typeck2.c (digest_init_r): Change nested argument type from bool to diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 05551dfdf29..f5f974da728 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 5df16bb21bf..0e6ee059e23 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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 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, unsigned int count) 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: diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 6d4e59101ee..ffd2b4c5844 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -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 + 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)) { diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 94e87c235f1..e13e127d45f 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -11940,6 +11940,9 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr, 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_UNARY_STAR, @@ -13283,6 +13286,7 @@ cp_parser_decomposition_declaration (cp_parser *parser, 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 ()); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5a6a7cff939..dc50f31034b 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -16135,19 +16135,23 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, 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); } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e1e29f195fd..ba86d2f9380 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2017-12-15 Jakub Jelinek + PR c++/81197 + * g++.dg/cpp1z/decomp34.C: New test. + PR c++/80135 PR c++/81922 * g++.dg/warn/Wplacement-new-size-1.C (fBx1): Initialize nested diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp34.C b/gcc/testsuite/g++.dg/cpp1z/decomp34.C new file mode 100644 index 00000000000..c7f0b8ac16e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp34.C @@ -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 "structured bindings only available with" "" { target c++14_down } } +namespace A { namespace B { auto&& [u, v, ww] = Y{}; } } // { dg-warning "structured bindings only available with" "" { target c++14_down } } + +// { dg-final { scan-assembler "_ZGRDC1tE0" } } +// { dg-final { scan-assembler "_ZGRN1A1BDC1u1v2wwEE1" } } -- 2.30.2