From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 75295 invoked by alias); 5 Dec 2017 00:01:08 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 75237 invoked by uid 89); 5 Dec 2017 00:01:04 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.9 required=5.0 tests=BAYES_00,GIT_PATCH_2,GIT_PATCH_3,SPF_HELO_PASS,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=Finish X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 05 Dec 2017 00:01:02 +0000 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 21FD6356E5; Tue, 5 Dec 2017 00:01:01 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-116-34.ams2.redhat.com [10.36.116.34]) by smtp.corp.redhat.com (Postfix) with ESMTPS id BC29317DC2; Tue, 5 Dec 2017 00:01:00 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id vB500wfS007922; Tue, 5 Dec 2017 01:00:58 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id vB500u0O007921; Tue, 5 Dec 2017 01:00:56 +0100 Date: Tue, 05 Dec 2017 00:01:00 -0000 From: Jakub Jelinek To: Jason Merrill , Nathan Sidwell Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] Fix ICE with extend_ref_init_temps of structured binding (PR c++/81197) Message-ID: <20171205000056.GR2353@tucnak> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.7.1 (2016-10-04) X-IsSubscribed: yes X-SW-Source: 2017-12/txt/msg00184.txt.bz2 Hi! We were calling cp_finish_decl before cp_finish_decomp, so that the latter has the initializer finalized and can decompose it, and cp_finish_decomp was mangling the decl if needed. Unfortunately, as the following testcase shows, sometimes we need it mangled already earlier, during that cp_finish_decl call. Most of the patch below arranges the mangling (which needs just the list of the identifiers and namespace context) to be done before the cp_finish_decl. Another thing is that with the change we wouldn't ICE, but would emit weird mangled names, like _ZGR7_ZDC1tE0. The problem is that we don't keep the list of the corresponding identifiers around and only store the full mangled name in DECL_ASSEMBLER_NAME, but the DC + E case us and can appear elsewhere, including the lifetime extended temporary manglings. The patch just attempts to discover the DC in the mangled name and use a substring of the mangled name, there should be no substutions in there. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? Note, the _ZGR* mangling still looks weird, the ABI says: ::= GR _ # First temporary ::= GR _ # Subsequent temporaries but we instead of the _ or always emit a number, starting with 0. And, that number increases on every GR we produce, rather than just when referring to portions of some initializer of the same object. So, with the patch we e.g. emit _ZGRDC1tE0, while LLVM emits _ZGRDC1tE_ (and ICEs on the other structured binding, where we emit _ZGRN1A1BDC1u1v2wwEE1 but should be emitting _ZGRN1A1BDC1u1v2wwEE_ probably). 2017-12-05 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 (write_unqualified_name): Handle DECL_DECOMPOSITION_P where DECL_ASSEMBLER_NAME is already set. * g++.dg/cpp1z/decomp34.C: New test. --- gcc/cp/cp-tree.h.jj 2017-12-01 09:19:07.000000000 +0100 +++ gcc/cp/cp-tree.h 2017-12-04 13:14:11.673367545 +0100 @@ -6141,6 +6141,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/cp/decl.c.jj 2017-11-30 23:45:45.000000000 +0100 +++ gcc/cp/decl.c 2017-12-04 12:52:44.679418902 +0100 @@ -7359,6 +7359,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 @@ -7630,8 +7649,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/parser.c.jj 2017-12-01 22:13:19.000000000 +0100 +++ gcc/cp/parser.c 2017-12-04 12:56:04.883923605 +0100 @@ -11926,6 +11926,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_UNARY_STAR, @@ -13269,6 +13272,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/pt.c.jj 2017-11-30 23:45:48.000000000 +0100 +++ gcc/cp/pt.c 2017-12-04 12:59:10.309612507 +0100 @@ -16096,19 +16096,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/mangle.c.jj 2017-11-17 08:40:32.000000000 +0100 +++ gcc/cp/mangle.c 2017-12-04 14:28:49.132795687 +0100 @@ -1291,7 +1291,56 @@ write_unqualified_name (tree decl) { found = true; gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl)); - write_source_name (DECL_ASSEMBLER_NAME (decl)); + if (VAR_P (decl) + && DECL_DECOMPOSITION_P (decl) + && DECL_NAME (decl) == NULL_TREE + && DECL_NAMESPACE_SCOPE_P (decl)) + { + const char *p = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + const char *end = p + IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decl)); + bool nested = false; + /* The list of identifiers is likely gone at this point, so find the + DC + E part in the mangled name. */ + if (!strncmp (p, "_Z", 2)) + { + 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)) + p = NULL; + if (nested) + { + if (end[-1] != 'E') + p = NULL; + else + --end; + } + if (end[-1] != 'E') + p = NULL; + } + else + p = NULL; + if (p == NULL) + write_source_name (DECL_ASSEMBLER_NAME (decl)); + else + write_chars (p, end - p); + } + else + write_source_name (DECL_ASSEMBLER_NAME (decl)); } else if (DECL_DECLARES_FUNCTION_P (decl)) { --- gcc/testsuite/g++.dg/cpp1z/decomp34.C.jj 2017-12-04 14:32:40.967956222 +0100 +++ gcc/testsuite/g++.dg/cpp1z/decomp34.C 2017-12-04 14:30:57.000000000 +0100 @@ -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" } } Jakub