From patchwork Thu Aug 31 19:14:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 137338 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:c792:0:b0:3f2:4152:657d with SMTP id b18csp446603vqu; Thu, 31 Aug 2023 12:15:24 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHKB4seXjKtok+uApmFyCoaZFpPZnxSchquGsmf7iybf3qPRj2Or89EA9eFvHI47l9u/H2q X-Received: by 2002:a17:906:53cf:b0:9a2:ecd:d95d with SMTP id p15-20020a17090653cf00b009a20ecdd95dmr146537ejo.68.1693509324286; Thu, 31 Aug 2023 12:15:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1693509324; cv=none; d=google.com; s=arc-20160816; b=booh+tLzLVIRPpR29JunEzxvA0+vT4/yt4oIYpSqvurl6cD4cP7uZh8qAPhDYOxLUq fCUxBz6pTPGqjSeE4/G982VFXMPZcBS/vi0vQ6wdWM6vsWE9q6q1Cc32aY6RFQIj8Sli wcM54B9fxl3TJD6AyRqlmEnPvM6y+vqYDhjXn72ImMXWuNVA0T0dDzoVdwUvdcRigK13 uSZZFR6ZbcPfL4UUvHOD7SnLJo9CfiEUYWwqbdmXc1jknF+ZJa1AHr8w/0ZJ4hDEjIl+ tGR1IiuXJ0iqHt5bhZ6O1esq56DGgQFWXAxZ6ZhEA7xlmd3CXkLsKG23JDP9hTLEcl8T X2rQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence :content-disposition:in-reply-to:mime-version:references:message-id :subject:cc:to:date:dmarc-filter:delivered-to:dkim-signature :dkim-filter; bh=zAfY0bgPkQ0Yqqn1ZKrI9HYVafK4JZOLgQyQT1/ulkM=; fh=0xZT+NBKSeH8qOu04/61f1ZGePpF4jF/gxp331YE14k=; b=pPS6b2z/9unwoDodF6SE2yeRS7ot4FsoyIPRueMiV/99w1pUfnNQxttqVOYlfL2O1O 0Eoz6Vo0C+RG2b0heyBQoDf7/1YZevK1LzQqXsgqxb3266AbMU3wnXiXl1xiisyntRsj 4jBS6y994K0XuViC06nTx2xyDYGxRetduJt8Dnd9jQWtfgedrSBsO67DWT+yUF7tq65v 0N97LTayHdATgTtUuVrWgETLZfDSlTKqRvlYKplH55xhJyComczlbVyUjnLU0gV+QDlS 4YfyCYTbdyV9IgKS72JS830DcEvuan88csXPR5HYP+w7rb2g3wj4W0dSu9UdYzpz3ycf kUiw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=tem8LNTu; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id t16-20020a1709064f1000b009823816586esi1315333eju.500.2023.08.31.12.15.23 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 31 Aug 2023 12:15:24 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=tem8LNTu; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id F3A63385840B for ; Thu, 31 Aug 2023 19:15:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org F3A63385840B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1693509323; bh=zAfY0bgPkQ0Yqqn1ZKrI9HYVafK4JZOLgQyQT1/ulkM=; h=Date:To:Cc:Subject:References:In-Reply-To:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=tem8LNTuKmjW4rYjjD2GZ3+InoIl9AaUOhAUJMdAa6WX+fOfs0E38TmymZKLGgbxz 44Ng5HrH2ynJcjorEIKnNsmcJs1lSM2eXXjZZUi2k4ygrEqNpdKlZwFF5IobB0vx2S /8EcJ/TGRm1/Kq1YIyNtiS0htvvTFGEMplTKPljs= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 18C9E3858D20 for ; Thu, 31 Aug 2023 19:14:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 18C9E3858D20 Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-574-1MkMpFAQMmClyGg_GsD-YQ-1; Thu, 31 Aug 2023 15:14:22 -0400 X-MC-Unique: 1MkMpFAQMmClyGg_GsD-YQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 22D0F29AA2D6 for ; Thu, 31 Aug 2023 19:14:22 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.45.224.16]) by smtp.corp.redhat.com (Postfix) with ESMTPS id A6210140E950; Thu, 31 Aug 2023 19:14:21 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 37VJEJJa293642 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Thu, 31 Aug 2023 21:14:20 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 37VJEJ9J293641; Thu, 31 Aug 2023 21:14:19 +0200 Date: Thu, 31 Aug 2023 21:14:19 +0200 To: Jason Merrill Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] c++, v3: Fix up mangling of function/block scope static structured bindings and emit abi tags [PR111069] Message-ID: References: <88ab126d-1f07-3b00-d489-b7cdd4698828@redhat.com> <32de8636-64ef-2e75-1de6-9a164962441d@redhat.com> MIME-Version: 1.0 In-Reply-To: <32de8636-64ef-2e75-1de6-9a164962441d@redhat.com> X-Scanned-By: MIMEDefang 3.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-3.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1775773233224275114 X-GMAIL-MSGID: 1775773233224275114 On Thu, Aug 31, 2023 at 01:11:57PM -0400, Jason Merrill wrote: > > 2023-08-28 Jakub Jelinek > > > > PR c++/111069 > > gcc/ > > * common.opt (fabi-version=): Document version 19. > > * doc/invoke.texi (-fabi-version=): Likewise. > > gcc/c-family/ > > * c-opts.cc (c_common_post_options): Change latest_abi_version to 19. > > gcc/cp/ > > * cp-tree.h (determine_local_discriminator): Add NAME argument with > > NULL_TREE default. > > (struct cp_decomp): New type. > > Maybe cp_finish_decomp should take this as well? And tsubst_decomp_names, > and various other functions with decomp_first_name/decomp_cnt parms? Ok, done below. > > + if (tree tags = get_abi_tags (decl)) > > + { > > + /* We didn't emit ABI tags for structured bindings before ABI 19. */ > > + if (!G.need_abi_warning > > + && abi_warn_or_compat_version_crosses (19)) > > + G.need_abi_warning = 1; > > In general we should probably only warn about mangling changes if > TREE_PUBLIC (decl). I have done that but I think it ought to be unnecessary, because check_abi_tags starts with if (!TREE_PUBLIC (decl)) /* No need to worry about things local to this TU. */ return NULL_TREE; Here is an updated patch, so far just tested with make check-g++ GXX_TESTSUITE_STDS=98,11,14,17,20,2b,2c RUNTESTFLAGS="dg.exp='*decomp*'" ok for trunk if it passes full bootstrap/regtest? 2023-08-31 Jakub Jelinek PR c++/111069 gcc/ * common.opt (fabi-version=): Document version 19. * doc/invoke.texi (-fabi-version=): Likewise. gcc/c-family/ * c-opts.cc (c_common_post_options): Change latest_abi_version to 19. gcc/cp/ * cp-tree.h (determine_local_discriminator): Add NAME argument with NULL_TREE default. (struct cp_decomp): New type. (cp_finish_decl): Add DECOMP argument defaulted to nullptr. (cp_maybe_mangle_decomp): Remove declaration. (cp_finish_decomp): Add cp_decomp * argument, remove tree and unsigned args. (cp_convert_range_for): Likewise. * decl.cc (determine_local_discriminator): Add NAME argument, use it if non-NULL, otherwise compute it the old way. (maybe_commonize_var): Don't return early for structured bindings. (cp_finish_decl): Add DECOMP argument, if non-NULL, call cp_maybe_mangle_decomp. (cp_maybe_mangle_decomp): Make it static with a forward declaration. Call determine_local_discriminator. Replace FIRST and COUNT arguments with DECOMP argument. (cp_finish_decomp): Replace FIRST and COUNT arguments with DECOMP argument. * mangle.cc (find_decomp_unqualified_name): Remove. (write_unqualified_name): Don't call find_decomp_unqualified_name. (mangle_decomp): Handle mangling of static function/block scope structured bindings. Don't call decl_mangling_context twice. Call check_abi_tags, call write_abi_tags for abi version >= 19 and emit -Wabi warnings if needed. (write_guarded_var_name): Handle structured bindings. (mangle_ref_init_variable): Use write_guarded_var_name. * parser.cc (cp_parser_range_for): Adjust do_range_for_auto_deduction and cp_convert_range_for callers. (do_range_for_auto_deduction): Replace DECOMP_FIRST_NAME and DECOMP_CNT arguments with DECOMP. Adjust cp_finish_decomp caller. (cp_convert_range_for): Replace DECOMP_FIRST_NAME and DECOMP_CNT arguments with DECOMP. Don't call cp_maybe_mangle_decomp, adjust cp_finish_decl and cp_finish_decomp callers. (cp_parser_decomposition_declaration): Don't call cp_maybe_mangle_decomp, adjust cp_finish_decl and cp_finish_decomp callers. (cp_convert_omp_range_for): Adjust do_range_for_auto_deduction and cp_finish_decomp callers. (cp_finish_omp_range_for): Don't call cp_maybe_mangle_decomp, adjust cp_finish_decl and cp_finish_decomp callers. * pt.cc (tsubst_omp_for_iterator): Adjust tsubst_decomp_names caller. (tsubst_decomp_names): Replace FIRST and CNT arguments with DECOMP. (tsubst_expr): Don't call cp_maybe_mangle_decomp, adjust tsubst_decomp_names, cp_finish_decl, cp_finish_decomp and cp_convert_range_for callers. gcc/testsuite/ * g++.dg/cpp2a/decomp8.C: New test. * g++.dg/cpp2a/decomp9.C: New test. * g++.dg/abi/macro0.C: Expect __GXX_ABI_VERSION 1019 rather than 1018. Jakub --- gcc/common.opt.jj 2023-08-28 13:55:55.670370386 +0200 +++ gcc/common.opt 2023-08-31 19:53:31.186280641 +0200 @@ -1010,6 +1010,9 @@ Driver Undocumented ; 18: Corrects errors in mangling of lambdas with additional context. ; Default in G++ 13. ; +; 19: Emits ABI tags if needed in structured binding mangled names. +; Default in G++ 14. +; ; Additional positive integers will be assigned as new versions of ; the ABI become the default version of the ABI. fabi-version= --- gcc/doc/invoke.texi.jj 2023-08-31 19:52:16.734307207 +0200 +++ gcc/doc/invoke.texi 2023-08-31 19:53:31.191280572 +0200 @@ -3017,6 +3017,9 @@ in C++14 and up. Version 18, which first appeard in G++ 13, fixes manglings of lambdas that have additional context. +Version 19, which first appeard in G++ 14, fixes manglings of structured +bindings to include ABI tags. + See also @option{-Wabi}. @opindex fabi-compat-version --- gcc/c-family/c-opts.cc.jj 2023-08-28 13:55:55.613371156 +0200 +++ gcc/c-family/c-opts.cc 2023-08-31 19:53:31.192280558 +0200 @@ -974,7 +974,7 @@ c_common_post_options (const char **pfil /* Change flag_abi_version to be the actual current ABI level, for the benefit of c_cpp_builtins, and to make comparison simpler. */ - const int latest_abi_version = 18; + const int latest_abi_version = 19; /* Generate compatibility aliases for ABI v13 (8.2) by default. */ const int abi_compat_default = 13; --- gcc/cp/cp-tree.h.jj 2023-08-31 14:31:05.991763184 +0200 +++ gcc/cp/cp-tree.h 2023-08-31 20:39:34.052154029 +0200 @@ -6859,7 +6859,7 @@ extern void pop_switch (void); extern void note_break_stmt (void); extern bool note_iteration_stmt_body_start (void); extern void note_iteration_stmt_body_end (bool); -extern void determine_local_discriminator (tree); +extern void determine_local_discriminator (tree, tree = NULL_TREE); extern bool member_like_constrained_friend_p (tree); extern bool fns_correspond (tree, tree); extern int decls_match (tree, tree, bool = true); @@ -6892,10 +6892,10 @@ extern tree start_decl (const cp_decl extern void start_decl_1 (tree, bool); extern bool check_array_initializer (tree, tree, tree); extern void omp_declare_variant_finalize (tree, tree); -extern void cp_finish_decl (tree, tree, bool, tree, int); +struct cp_decomp { tree decl; unsigned int count; }; +extern void cp_finish_decl (tree, tree, bool, tree, int, cp_decomp * = nullptr); 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 void cp_finish_decomp (tree, cp_decomp *); extern int cp_complete_array_type (tree *, tree, bool); extern int cp_complete_array_type_or_error (tree *, tree, bool, tsubst_flags_t); extern tree build_ptrmemfunc_type (tree); @@ -7312,7 +7312,7 @@ extern tree clone_attrs (tree); extern bool maybe_clone_body (tree); /* In parser.cc */ -extern tree cp_convert_range_for (tree, tree, tree, tree, unsigned int, bool, +extern tree cp_convert_range_for (tree, tree, tree, cp_decomp *, bool, unsigned short, bool); extern void cp_convert_omp_range_for (tree &, tree &, tree &, tree &, tree &, tree &, tree &, tree &); --- gcc/cp/decl.cc.jj 2023-08-30 18:48:48.831597950 +0200 +++ gcc/cp/decl.cc 2023-08-31 20:48:21.127722180 +0200 @@ -911,15 +911,16 @@ static GTY((deletable)) vec generally very few of these in any particular function. */ void -determine_local_discriminator (tree decl) +determine_local_discriminator (tree decl, tree name) { auto_cond_timevar tv (TV_NAME_LOOKUP); retrofit_lang_decl (decl); tree ctx = DECL_CONTEXT (decl); - tree name = (TREE_CODE (decl) == TYPE_DECL - && TYPE_UNNAMED_P (TREE_TYPE (decl)) - ? NULL_TREE : DECL_NAME (decl)); size_t nelts = vec_safe_length (local_entities); + if (name == NULL_TREE) + name = (TREE_CODE (decl) == TYPE_DECL + && TYPE_UNNAMED_P (TREE_TYPE (decl)) + ? NULL_TREE : DECL_NAME (decl)); for (size_t i = 0; i < nelts; i += 2) { tree *pair = &(*local_entities)[i]; @@ -6417,8 +6418,9 @@ layout_var_decl (tree decl) void maybe_commonize_var (tree decl) { - /* Don't mess with __FUNCTION__ and similar. */ - if (DECL_ARTIFICIAL (decl)) + /* Don't mess with __FUNCTION__ and similar. But do handle structured + bindings. */ + if (DECL_ARTIFICIAL (decl) && !DECL_DECOMPOSITION_P (decl)) return; /* Static data in a function with comdat linkage also has comdat @@ -8212,6 +8214,8 @@ omp_declare_variant_finalize (tree decl, } } +static void cp_maybe_mangle_decomp (tree, cp_decomp *); + /* Finish processing of a declaration; install its line number and initial value. If the length of an array type is not known before, @@ -8221,11 +8225,14 @@ omp_declare_variant_finalize (tree decl, true, then INIT is an integral constant expression. FLAGS is LOOKUP_ONLYCONVERTING if the = init syntax was used, else 0 - if the (init) syntax was used. */ + if the (init) syntax was used. + + DECOMP is first identifier's DECL and identifier count in a structured + bindings, nullptr if not a structured binding. */ void cp_finish_decl (tree decl, tree init, bool init_const_expr_p, - tree asmspec_tree, int flags) + tree asmspec_tree, int flags, cp_decomp *decomp) { vec *cleanups = NULL; const char *asmspec = NULL; @@ -8600,6 +8607,9 @@ cp_finish_decl (tree decl, tree init, bo return; } + if (decomp) + cp_maybe_mangle_decomp (decl, decomp); + /* If this is a local variable that will need a mangled name, register it now. We must do this before processing the initializer for the variable, since the initialization might @@ -9070,18 +9080,37 @@ lookup_decomp_type (tree 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) +static void +cp_maybe_mangle_decomp (tree decl, cp_decomp *decomp) { if (!processing_template_decl && !error_operand_p (decl) && TREE_STATIC (decl)) { auto_vec v; - v.safe_grow (count, true); - tree d = first; - for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d)) - v[count - i - 1] = d; + v.safe_grow (decomp->count, true); + tree d = decomp->decl; + for (unsigned int i = 0; i < decomp->count; i++, d = DECL_CHAIN (d)) + v[decomp->count - i - 1] = d; + if (DECL_FUNCTION_SCOPE_P (decl)) + { + size_t sz = 3; + for (unsigned int i = 0; i < decomp->count; ++i) + sz += IDENTIFIER_LENGTH (DECL_NAME (v[i])) + 1; + char *name = XALLOCAVEC (char, sz); + name[0] = 'D'; + name[1] = 'C'; + char *p = name + 2; + for (unsigned int i = 0; i < decomp->count; ++i) + { + size_t len = IDENTIFIER_LENGTH (DECL_NAME (v[i])); + *p++ = ' '; + memcpy (p, IDENTIFIER_POINTER (DECL_NAME (v[i])), len); + p += len; + } + *p = '\0'; + determine_local_discriminator (decl, get_identifier (name)); + } SET_DECL_ASSEMBLER_NAME (decl, mangle_decomp (decl, v)); maybe_apply_pragma_weak (decl); } @@ -9093,8 +9122,10 @@ cp_maybe_mangle_decomp (tree decl, tree those decls. */ void -cp_finish_decomp (tree decl, tree first, unsigned int count) +cp_finish_decomp (tree decl, cp_decomp *decomp) { + tree first = decomp->decl; + unsigned count = decomp->count; if (error_operand_p (decl)) { error_out: --- gcc/cp/mangle.cc.jj 2023-08-28 13:55:55.819368372 +0200 +++ gcc/cp/mangle.cc 2023-08-31 20:48:21.127722180 +0200 @@ -1347,51 +1347,6 @@ 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 (!startswith (p, "_Z")) - return NULL; - p += 2; - if (startswith (p, "St")) - 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 (!startswith (p, "DC")) - return NULL; - if (nested) - { - if (end[-1] != 'E') - return NULL; - --end; - } - if (end[-1] != 'E') - return NULL; - *len = end - p; - return p; -} - /* "For the purposes of mangling, the name of an anonymous union is considered to be the name of the first named data member found by a pre-order, depth-first, declaration-order walk of the data members of the anonymous @@ -1465,17 +1420,7 @@ write_unqualified_name (tree decl) { found = true; gcc_assert (DECL_ASSEMBLER_NAME_SET_P (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)); + write_source_name (DECL_ASSEMBLER_NAME (decl)); } else if (DECL_DECLARES_FUNCTION_P (decl)) { @@ -4373,6 +4318,7 @@ mangle_decomp (const tree decl, vec (%qD) and %<%s=%d%> (%qD)", + G.entity, fabi_version, warn_abi_version, id2, + fabi_version, save_ver, id); + else + warning_at (DECL_SOURCE_LOCATION (G.entity), OPT_Wabi, + "the mangled name of %qD changes between " + "%<%s=%d%> (%qD) and %<%s=%d%> (%qD)", + G.entity, fabi_version, save_ver, id, + fabi_version, warn_abi_version, id2); + } + return id; } @@ -4574,6 +4573,13 @@ write_guarded_var_name (const tree varia /* The name of a guard variable for a reference temporary should refer to the reference, not the temporary. */ write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4); + else if (DECL_DECOMPOSITION_P (variable) + && DECL_NAME (variable) == NULL_TREE + && startswith (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (variable)), + "_Z")) + /* The name of a guard variable for a structured binding needs special + casing. */ + write_string (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (variable)) + 2); else write_name (variable, /*ignore_local_scope=*/0); } @@ -4640,7 +4646,7 @@ mangle_ref_init_variable (const tree var start_mangling (variable); write_string ("_ZGR"); check_abi_tags (variable); - write_name (variable, /*ignore_local_scope=*/0); + write_guarded_var_name (variable); /* Avoid name clashes with aggregate initialization of multiple references at once. */ write_compact_number (current_ref_temp_count++); --- gcc/cp/parser.cc.jj 2023-08-31 14:31:35.963352093 +0200 +++ gcc/cp/parser.cc 2023-08-31 20:48:21.127722180 +0200 @@ -2393,7 +2393,7 @@ static tree cp_parser_c_for static tree cp_parser_range_for (cp_parser *, tree, tree, tree, bool, unsigned short, bool, bool); static void do_range_for_auto_deduction - (tree, tree, tree, unsigned int); + (tree, tree, cp_decomp *); static tree cp_parser_perform_range_for_lookup (tree, tree *, tree *); static tree cp_parser_range_for_member_function @@ -13854,8 +13854,7 @@ cp_parser_range_for (cp_parser *parser, tree stmt, range_expr; auto_vec bindings; auto_vec names; - tree decomp_first_name = NULL_TREE; - unsigned int decomp_cnt = 0; + cp_decomp decomp_d, *decomp = NULL; /* Get the range declaration momentarily out of the way so that the range expression doesn't clash with it. */ @@ -13872,9 +13871,11 @@ cp_parser_range_for (cp_parser *parser, { tree d = range_decl; range_decl = TREE_OPERAND (v, 0); - decomp_cnt = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; - decomp_first_name = d; - for (unsigned int i = 0; i < decomp_cnt; i++, d = DECL_CHAIN (d)) + decomp = &decomp_d; + decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; + decomp->decl = d; + for (unsigned int i = 0; i < decomp->count; + i++, d = DECL_CHAIN (d)) { tree name = DECL_NAME (d); names.safe_push (name); @@ -13928,15 +13929,13 @@ cp_parser_range_for (cp_parser *parser, if (!type_dependent_expression_p (range_expr) /* do_auto_deduction doesn't mess with template init-lists. */ && !BRACE_ENCLOSED_INITIALIZER_P (range_expr)) - do_range_for_auto_deduction (range_decl, range_expr, decomp_first_name, - decomp_cnt); + do_range_for_auto_deduction (range_decl, range_expr, decomp); } else { stmt = begin_for_stmt (scope, init); - stmt = cp_convert_range_for (stmt, range_decl, range_expr, - decomp_first_name, decomp_cnt, ivdep, - unroll, novector); + stmt = cp_convert_range_for (stmt, range_decl, range_expr, decomp, + ivdep, unroll, novector); } return stmt; } @@ -13968,8 +13967,7 @@ build_range_temp (tree range_expr) a shortcut version of cp_convert_range_for. */ static void -do_range_for_auto_deduction (tree decl, tree range_expr, - tree decomp_first_name, unsigned int decomp_cnt) +do_range_for_auto_deduction (tree decl, tree range_expr, cp_decomp *decomp) { tree auto_node = type_uses_auto (TREE_TYPE (decl)); if (auto_node) @@ -13990,7 +13988,7 @@ do_range_for_auto_deduction (tree decl, tf_warning_or_error, adc_variable_type); if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl)) - cp_finish_decomp (decl, decomp_first_name, decomp_cnt); + cp_finish_decomp (decl, decomp); } } } @@ -14113,8 +14111,8 @@ warn_for_range_copy (tree decl, tree exp tree cp_convert_range_for (tree statement, tree range_decl, tree range_expr, - tree decomp_first_name, unsigned int decomp_cnt, - bool ivdep, unsigned short unroll, bool novector) + cp_decomp *decomp, bool ivdep, unsigned short unroll, + bool novector) { tree begin, end; tree iter_type, begin_expr, end_expr; @@ -14182,17 +14180,14 @@ 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. */ tree deref_begin = build_x_indirect_ref (input_location, begin, RO_UNARY_STAR, NULL_TREE, tf_warning_or_error); cp_finish_decl (range_decl, deref_begin, /*is_constant_init*/false, NULL_TREE, - LOOKUP_ONLYCONVERTING); + LOOKUP_ONLYCONVERTING, decomp); if (VAR_P (range_decl) && DECL_DECOMPOSITION_P (range_decl)) - cp_finish_decomp (range_decl, decomp_first_name, decomp_cnt); + cp_finish_decomp (range_decl, decomp); warn_for_range_copy (range_decl, deref_begin); @@ -15890,18 +15885,20 @@ cp_parser_decomposition_declaration (cp_ if (decl != error_mark_node) { - cp_maybe_mangle_decomp (decl, prev, v.length ()); + cp_decomp decomp = { 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 ()); + (is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT), + &decomp); + cp_finish_decomp (decl, &decomp); } } else if (decl != error_mark_node) { *maybe_range_for_decl = prev; + cp_decomp decomp = { prev, v.length () }; /* Ensure DECL_VALUE_EXPR is created for all the decls but the underlying DECL. */ - cp_finish_decomp (decl, prev, v.length ()); + cp_finish_decomp (decl, &decomp); } if (pushed_scope) @@ -43521,8 +43518,7 @@ cp_convert_omp_range_for (tree &this_pre && !BRACE_ENCLOSED_INITIALIZER_P (init)) { tree d = decl; - tree decomp_first_name = NULL_TREE; - unsigned decomp_cnt = 0; + cp_decomp decomp_d, *decomp = NULL; if (decl != error_mark_node && DECL_HAS_VALUE_EXPR_P (decl)) { tree v = DECL_VALUE_EXPR (decl); @@ -43531,11 +43527,12 @@ cp_convert_omp_range_for (tree &this_pre && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0))) { d = TREE_OPERAND (v, 0); - decomp_cnt = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; - decomp_first_name = decl; + decomp = &decomp_d; + decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; + decomp->decl = decl; } } - do_range_for_auto_deduction (d, init, decomp_first_name, decomp_cnt); + do_range_for_auto_deduction (d, init, decomp); } cond = global_namespace; incr = NULL_TREE; @@ -43626,8 +43623,7 @@ cp_convert_omp_range_for (tree &this_pre decl = begin; /* Defer popping sl here. */ - tree decomp_first_name = NULL_TREE; - unsigned decomp_cnt = 0; + cp_decomp decomp_d, *decomp = NULL; if (orig_decl != error_mark_node && DECL_HAS_VALUE_EXPR_P (orig_decl)) { tree v = DECL_VALUE_EXPR (orig_decl); @@ -43637,8 +43633,9 @@ cp_convert_omp_range_for (tree &this_pre { tree d = orig_decl; orig_decl = TREE_OPERAND (v, 0); - decomp_cnt = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; - decomp_first_name = d; + decomp = &decomp_d; + decomp->count = tree_to_uhwi (TREE_OPERAND (v, 1)) + 1; + decomp->decl = d; } } @@ -43651,10 +43648,10 @@ cp_convert_omp_range_for (tree &this_pre { TREE_TYPE (orig_decl) = do_auto_deduction (TREE_TYPE (orig_decl), t, auto_node); - if (decomp_first_name) + if (decomp) { ++processing_template_decl; - cp_finish_decomp (orig_decl, decomp_first_name, decomp_cnt); + cp_finish_decomp (orig_decl, decomp); --processing_template_decl; if (!processing_template_decl) clear_has_value_expr = true; @@ -43670,8 +43667,9 @@ cp_convert_omp_range_for (tree &this_pre the whole loop nest. The remaining elements are decls of derived decomposition variables that are bound inside the loop body. This structure is further mangled by finish_omp_for into the form required - for the OMP_FOR_ORIG_DECLS field of the OMP_FOR tree node. */ - tree v = make_tree_vec (decomp_cnt + 3); + for the OMP_FOR_ORIG_DECLS field of the OMP_FOR tree node. */\ + unsigned decomp_cnt = decomp ? decomp->count : 0; + tree v = make_tree_vec (decomp_cnt); TREE_VEC_ELT (v, 0) = range_temp_decl; TREE_VEC_ELT (v, 1) = end; TREE_VEC_ELT (v, 2) = orig_decl; @@ -43686,13 +43684,13 @@ cp_convert_omp_range_for (tree &this_pre name but the DECL_VALUE_EXPR will be dependent. Hide those from folding of other loop initializers e.g. for warning purposes until cp_finish_omp_range_for. */ - gcc_checking_assert (DECL_HAS_VALUE_EXPR_P (decomp_first_name) - || (TREE_TYPE (decomp_first_name) + gcc_checking_assert (DECL_HAS_VALUE_EXPR_P (decomp->decl) + || (TREE_TYPE (decomp->decl) == error_mark_node)); - DECL_HAS_VALUE_EXPR_P (decomp_first_name) = 0; + DECL_HAS_VALUE_EXPR_P (decomp->decl) = 0; } - TREE_VEC_ELT (v, i + 3) = decomp_first_name; - decomp_first_name = DECL_CHAIN (decomp_first_name); + TREE_VEC_ELT (v, i + 3) = decomp->decl; + decomp->decl = DECL_CHAIN (decomp->decl); } orig_decl = tree_cons (NULL_TREE, NULL_TREE, v); } @@ -43706,27 +43704,26 @@ cp_finish_omp_range_for (tree orig, tree gcc_assert (TREE_CODE (orig) == TREE_LIST && TREE_CODE (TREE_CHAIN (orig)) == TREE_VEC); tree decl = TREE_VEC_ELT (TREE_CHAIN (orig), 2); - tree decomp_first_name = NULL_TREE; - unsigned int decomp_cnt = 0; + cp_decomp decomp_d, *decomp = NULL; if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl)) { - decomp_first_name = TREE_VEC_ELT (TREE_CHAIN (orig), 3); - decomp_cnt = TREE_VEC_LENGTH (TREE_CHAIN (orig)) - 3; + decomp = &decomp_d; + decomp_d.decl = TREE_VEC_ELT (TREE_CHAIN (orig), 3); + decomp_d.count = TREE_VEC_LENGTH (TREE_CHAIN (orig)) - 3; if (TREE_PUBLIC (TREE_CHAIN (orig))) { /* Undo temporary clearing of DECL_HAS_VALUE_EXPR_P done by cp_convert_omp_range_for above. */ TREE_PUBLIC (TREE_CHAIN (orig)) = 0; - tree d = decomp_first_name; - for (unsigned i = 0; i < decomp_cnt; i++) + tree d = decomp_d.decl; + for (unsigned i = 0; i < decomp_d.count; i++) { if (TREE_TYPE (d) != error_mark_node) DECL_HAS_VALUE_EXPR_P (d) = 1; d = DECL_CHAIN (d); } } - cp_maybe_mangle_decomp (decl, decomp_first_name, decomp_cnt); } /* The declaration is initialized with *__begin inside the loop body. */ @@ -43734,9 +43731,9 @@ cp_finish_omp_range_for (tree orig, tree build_x_indirect_ref (input_location, begin, RO_UNARY_STAR, NULL_TREE, tf_warning_or_error), /*is_constant_init*/false, NULL_TREE, - LOOKUP_ONLYCONVERTING); + LOOKUP_ONLYCONVERTING, decomp); if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl)) - cp_finish_decomp (decl, decomp_first_name, decomp_cnt); + cp_finish_decomp (decl, decomp); } /* Return true if next tokens contain a standard attribute that contains --- gcc/cp/pt.cc.jj 2023-08-28 13:55:55.868367710 +0200 +++ gcc/cp/pt.cc 2023-08-31 20:48:21.127722180 +0200 @@ -18352,7 +18352,7 @@ tsubst_copy_asm_operands (tree t, tree a static tree *omp_parallel_combined_clauses; static tree tsubst_decomp_names (tree, tree, tree, tsubst_flags_t, tree, - tree *, unsigned int *); + cp_decomp *); /* Substitute one OMP_FOR iterator. */ @@ -18383,28 +18383,27 @@ tsubst_omp_for_iterator (tree t, int i, && VAR_P (TREE_OPERAND (v, 0)) && DECL_DECOMPOSITION_P (TREE_OPERAND (v, 0))) { - tree decomp_first = NULL_TREE; - unsigned decomp_cnt = 0; + cp_decomp decomp_d = { NULL_TREE, 0 }; tree d = tsubst_decl (TREE_OPERAND (v, 0), args, complain); maybe_push_decl (d); d = tsubst_decomp_names (d, TREE_OPERAND (v, 0), args, complain, - in_decl, &decomp_first, &decomp_cnt); + in_decl, &decomp_d); decomp = true; if (d == error_mark_node) decl = error_mark_node; else - for (unsigned int i = 0; i < decomp_cnt; i++) + for (unsigned int i = 0; i < decomp_d.count; i++) { - if (!DECL_HAS_VALUE_EXPR_P (decomp_first)) + if (!DECL_HAS_VALUE_EXPR_P (decomp_d.decl)) { tree v = build_nt (ARRAY_REF, d, - size_int (decomp_cnt - i - 1), + size_int (decomp_d.count - i - 1), NULL_TREE, NULL_TREE); - SET_DECL_VALUE_EXPR (decomp_first, v); - DECL_HAS_VALUE_EXPR_P (decomp_first) = 1; + SET_DECL_VALUE_EXPR (decomp_d.decl, v); + DECL_HAS_VALUE_EXPR_P (decomp_d.decl) = 1; } - fit_decomposition_lang_decl (decomp_first, d); - decomp_first = DECL_CHAIN (decomp_first); + fit_decomposition_lang_decl (decomp_d.decl, d); + decomp_d.decl = DECL_CHAIN (decomp_d.decl); } } } @@ -18723,11 +18722,10 @@ tsubst_find_omp_teams (tree *tp, int *wa static tree tsubst_decomp_names (tree decl, tree pattern_decl, tree args, - tsubst_flags_t complain, tree in_decl, tree *first, - unsigned int *cnt) + tsubst_flags_t complain, tree in_decl, cp_decomp *decomp) { tree decl2, decl3, prev = decl; - *cnt = 0; + decomp->count = 0; gcc_assert (DECL_NAME (decl) == NULL_TREE); for (decl2 = DECL_CHAIN (pattern_decl); decl2 @@ -18736,12 +18734,12 @@ tsubst_decomp_names (tree decl, tree pat && DECL_NAME (decl2); decl2 = DECL_CHAIN (decl2)) { - if (TREE_TYPE (decl2) == error_mark_node && *cnt == 0) + if (TREE_TYPE (decl2) == error_mark_node && decomp->count == 0) { gcc_assert (errorcount); return error_mark_node; } - (*cnt)++; + decomp->count++; gcc_assert (DECL_DECOMP_BASE (decl2) == pattern_decl); gcc_assert (DECL_HAS_VALUE_EXPR_P (decl2)); tree v = DECL_VALUE_EXPR (decl2); @@ -18771,7 +18769,7 @@ tsubst_decomp_names (tree decl, tree pat else prev = decl3; } - *first = prev; + decomp->decl = prev; return decl; } @@ -19043,8 +19041,8 @@ tsubst_expr (tree t, tree args, tsubst_f else { bool const_init = false; - unsigned int cnt = 0; - tree first = NULL_TREE, ndecl = error_mark_node; + cp_decomp decomp_d, *decomp = NULL; + tree ndecl = error_mark_node; tree asmspec_tree = NULL_TREE; maybe_push_decl (decl); @@ -19056,9 +19054,11 @@ tsubst_expr (tree t, tree args, tsubst_f if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl) && TREE_TYPE (pattern_decl) != error_mark_node) - ndecl = tsubst_decomp_names (decl, pattern_decl, args, - complain, in_decl, &first, - &cnt); + { + decomp = &decomp_d; + ndecl = tsubst_decomp_names (decl, pattern_decl, args, + complain, in_decl, decomp); + } init = tsubst_init (init, decl, args, complain, in_decl); @@ -19066,9 +19066,6 @@ tsubst_expr (tree t, tree args, tsubst_f const_init = (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (pattern_decl)); - if (ndecl != error_mark_node) - cp_maybe_mangle_decomp (ndecl, first, cnt); - /* In a non-template function, VLA type declarations are handled in grokdeclarator; for templates, handle them now. */ @@ -19085,10 +19082,11 @@ tsubst_expr (tree t, tree args, tsubst_f TREE_TYPE (asmspec_tree) = char_array_type_node; } - cp_finish_decl (decl, init, const_init, asmspec_tree, 0); + cp_finish_decl (decl, init, const_init, asmspec_tree, 0, + decomp); if (ndecl != error_mark_node) - cp_finish_decomp (ndecl, first, cnt); + cp_finish_decomp (ndecl, decomp); } } } @@ -19127,12 +19125,13 @@ tsubst_expr (tree t, tree args, tsubst_f maybe_push_decl (decl); expr = RECUR (RANGE_FOR_EXPR (t)); - tree decomp_first = NULL_TREE; - unsigned decomp_cnt = 0; + cp_decomp decomp_d, *decomp = NULL; if (VAR_P (decl) && DECL_DECOMPOSITION_P (decl)) - decl = tsubst_decomp_names (decl, RANGE_FOR_DECL (t), args, - complain, in_decl, - &decomp_first, &decomp_cnt); + { + decomp = &decomp_d; + decl = tsubst_decomp_names (decl, RANGE_FOR_DECL (t), args, + complain, in_decl, decomp); + } if (processing_template_decl) { @@ -19140,15 +19139,14 @@ tsubst_expr (tree t, tree args, tsubst_f RANGE_FOR_UNROLL (stmt) = RANGE_FOR_UNROLL (t); RANGE_FOR_NOVECTOR (stmt) = RANGE_FOR_NOVECTOR (t); finish_range_for_decl (stmt, decl, expr); - if (decomp_first && decl != error_mark_node) - cp_finish_decomp (decl, decomp_first, decomp_cnt); + if (decomp && decl != error_mark_node) + cp_finish_decomp (decl, decomp); } else { unsigned short unroll = (RANGE_FOR_UNROLL (t) ? tree_to_uhwi (RANGE_FOR_UNROLL (t)) : 0); - stmt = cp_convert_range_for (stmt, decl, expr, - decomp_first, decomp_cnt, + stmt = cp_convert_range_for (stmt, decl, expr, decomp, RANGE_FOR_IVDEP (t), unroll, RANGE_FOR_NOVECTOR (t)); } --- gcc/testsuite/g++.dg/cpp2a/decomp8.C.jj 2023-08-31 19:53:31.205280379 +0200 +++ gcc/testsuite/g++.dg/cpp2a/decomp8.C 2023-08-31 19:53:31.205280379 +0200 @@ -0,0 +1,74 @@ +// PR c++/111069 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +extern int a[2]; +struct Y { int b, c, d; }; + +inline int +freddy () +{ + static auto [i, j] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + static auto [k, l] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + int ret = ++i + ++k; + { + static auto [i, j] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + static auto [k, l] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + ret += ++i + ++k; + } + { + static auto [i, j] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + static auto [k, l] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + ret += ++i + ++k; + } + return ret; +} + +namespace N +{ + namespace M + { + template + inline int + corge () + { + static auto [i, j] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + static auto && [u, v, w] = Y{}; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + int ret = ++i + ++u; + { + static auto && [u, v, w] = Y{}; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + ret += ++v; + } + return ret; + } + } +} + +int (*p) () = &freddy; +int (*q) () = N::M::corge<3>; + +// { dg-final { scan-assembler "_ZZ6freddyvEDC1i1jE" } } +// { dg-final { scan-assembler "_ZZ6freddyvEDC1i1jE_0" } } +// { dg-final { scan-assembler "_ZZ6freddyvEDC1i1jE_1" } } +// { dg-final { scan-assembler "_ZZ6freddyvEDC1k1lE" } } +// { dg-final { scan-assembler "_ZZ6freddyvEDC1k1lE_0" } } +// { dg-final { scan-assembler "_ZZ6freddyvEDC1k1lE_1" } } +// { dg-final { scan-assembler "_ZZN1N1M5corgeILi3EEEivEDC1i1jE" } } +// { dg-final { scan-assembler "_ZGVZ6freddyvEDC1i1jE" } } +// { dg-final { scan-assembler "_ZGVZ6freddyvEDC1i1jE_0" } } +// { dg-final { scan-assembler "_ZGVZ6freddyvEDC1i1jE_1" } } +// { dg-final { scan-assembler "_ZGVZ6freddyvEDC1k1lE" } } +// { dg-final { scan-assembler "_ZGVZ6freddyvEDC1k1lE_0" } } +// { dg-final { scan-assembler "_ZGVZ6freddyvEDC1k1lE_1" } } +// { dg-final { scan-assembler "_ZGVZN1N1M5corgeILi3EEEivEDC1i1jE" } } +// { dg-final { scan-assembler "_ZGRZN1N1M5corgeILi3EEEivEDC1u1v1wE_" } } +// { dg-final { scan-assembler "_ZGRZN1N1M5corgeILi3EEEivEDC1u1v1wE_0_" } } --- gcc/testsuite/g++.dg/cpp2a/decomp9.C.jj 2023-08-31 19:53:31.205280379 +0200 +++ gcc/testsuite/g++.dg/cpp2a/decomp9.C 2023-08-31 19:53:31.205280379 +0200 @@ -0,0 +1,82 @@ +// PR c++/111069 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +struct [[gnu::abi_tag ("foobar")]] S { int i; }; +extern S a[2]; +struct [[gnu::abi_tag ("qux")]] T { int i; S j; int k; }; +extern T b[2]; + +namespace N { + auto [i, j] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + auto [k, l] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } } +} + +inline int +foo () +{ + static auto [m, n] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + static auto [o, p] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + int ret = ++N::i.i + ++N::k.i; + { + static auto [m, n] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + + ret += ++n.i; + } + { + static auto [m, n] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + + ret += ++n.i; + } + ret += ++m.i + ++o.i; + return ret; +} + +template +inline int +bar () +{ + static auto [m, n] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + static auto [o, p] = b; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + int ret = 0; + { + static auto [m, n] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + ret += ++n.i; + } + { + static auto [m, n] = a; // { dg-warning "structured bindings only available with" "" { target c++14_down } } + // { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-1 } + ret += ++n.i; + } + ret += ++m.i + ++o.i; + return ret; +} + +int (*p) () = &foo; +int (*q) () = &bar; + +// { dg-final { scan-assembler "_ZZ3foovEDC1m1nEB6foobar" } } +// { dg-final { scan-assembler "_ZZ3foovEDC1m1nEB6foobar_0" } } +// { dg-final { scan-assembler "_ZZ3foovEDC1m1nEB6foobar_1" } } +// { dg-final { scan-assembler "_ZZ3foovEDC1o1pEB3qux" } } +// { dg-final { scan-assembler "_ZZ3barI1TB3quxEivEDC1m1nEB6foobar" } } +// { dg-final { scan-assembler "_ZZ3barI1TB3quxEivEDC1m1nEB6foobar_0" } } +// { dg-final { scan-assembler "_ZZ3barI1TB3quxEivEDC1m1nEB6foobar_1" } } +// { dg-final { scan-assembler "_ZZ3barI1TB3quxEivEDC1o1pEB3qux" } } +// { dg-final { scan-assembler "_ZN1NDC1i1jEB6foobarE" } } +// { dg-final { scan-assembler "_ZN1NDC1k1lEB3quxE" } } +// { dg-final { scan-assembler "_ZGVZ3foovEDC1m1nEB6foobar" } } +// { dg-final { scan-assembler "_ZGVZ3foovEDC1m1nEB6foobar_0" } } +// { dg-final { scan-assembler "_ZGVZ3foovEDC1m1nEB6foobar_1" } } +// { dg-final { scan-assembler "_ZGVZ3foovEDC1o1pEB3qux" } } +// { dg-final { scan-assembler "_ZGVZ3barI1TB3quxEivEDC1m1nEB6foobar" } } +// { dg-final { scan-assembler "_ZGVZ3barI1TB3quxEivEDC1m1nEB6foobar_0" } } +// { dg-final { scan-assembler "_ZGVZ3barI1TB3quxEivEDC1m1nEB6foobar_1" } } +// { dg-final { scan-assembler "_ZGVZ3barI1TB3quxEivEDC1o1pEB3qux" } } --- gcc/testsuite/g++.dg/abi/macro0.C.jj 2022-10-11 10:00:07.456124822 +0200 +++ gcc/testsuite/g++.dg/abi/macro0.C 2023-08-31 19:53:31.222280146 +0200 @@ -1,6 +1,6 @@ // This testcase will need to be kept in sync with c_common_post_options. // { dg-options "-fabi-version=0" } -#if __GXX_ABI_VERSION != 1018 +#if __GXX_ABI_VERSION != 1019 #error "Incorrect value of __GXX_ABI_VERSION" #endif