From patchwork Thu Sep 5 15:02:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathaniel Shead X-Patchwork-Id: 97178 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 0CBAD384AB4F for ; Thu, 5 Sep 2024 15:03:38 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-pf1-x42b.google.com (mail-pf1-x42b.google.com [IPv6:2607:f8b0:4864:20::42b]) by sourceware.org (Postfix) with ESMTPS id D2DC23858294 for ; Thu, 5 Sep 2024 15:03:00 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org D2DC23858294 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org D2DC23858294 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::42b ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1725548583; cv=none; b=M0TqzHLzLZk2ildeFVhIRO5lunE0hRg1RL6BEvq1FbwZ91yTnFUare8ZqqnNeXEd57Igi3IixNTkMh+JpuMBt7YocLXgI078iZI1YVKMIqFlRNEm/yTzPnIcFxYTJZ58V3kvCicnPIoAuszFhBHVOLISyFInlD8zdxfV+lsKeiw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1725548583; c=relaxed/simple; bh=pKXkX7JvyRPP+UPPs3r8aD8VC4++wUTkD7AXn+1AdR8=; h=DKIM-Signature:Message-ID:Date:From:To:Subject:MIME-Version; b=u2SoQmM0rPmFiwoIqayyH+/N9Lb+eoqpSAJ+j0tL7bq6r9MJDoBII0kDYLm11wBT71eY2GjwiYt/aNg7GMfg6ZCtbZI9U7Kz7MJeqMWQOrDmfeY277zOxEXipRRfwFKuxZYqUL7QDf88parLUy+BJ0b/7XQBSJlNTFLq/K6M/CE= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-pf1-x42b.google.com with SMTP id d2e1a72fcca58-71790698b22so88942b3a.1 for ; Thu, 05 Sep 2024 08:03:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1725548580; x=1726153380; darn=gcc.gnu.org; h=content-disposition:mime-version:subject:cc:to:from:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=WaDTE4k/Ee7VpoUrT0G9TwHR/jRV2s35xYJBlTQne6Q=; b=KdWG7WO9ttcxFgajV3vqfla5T730HWlD2wIakcXhq9L7J00QlgeWLi3rbqPeFLERl7 PmQphm9vjdA52i5vfbNzDNKKbI5Zc4TKvnE+ZqjJlFohl37itc7J78af5JbzhlQDLUQj LzxP4fXI7eeZt7L4la+PNB2aa6ixlAc0yLohyo/PvN1MykU5A5cV913Jpn67XXvFRPR7 Cc/EqAicuT99PXUQ/V1o0VGm2beQWBJRnfzVwaUhWtmc9iITvGFDVr47doK36oLwQfLr ntOZ7X0KR0F5njqPeFuJ63phW2swEQl8+649MgLljAXkqMHxmDVVhKnc7gznXjXHsUdm h/Gg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725548580; x=1726153380; h=content-disposition:mime-version:subject:cc:to:from:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=WaDTE4k/Ee7VpoUrT0G9TwHR/jRV2s35xYJBlTQne6Q=; b=YLq9K//YnQqnA4m5Tj2tZijOJVs+DPLD+eyJwTlWVuKiLGZIWIiVNcFAuv7OfCA7+X 0zO9qSnrJfRnUCXJb21lTtPHsbBkFa0Zi0eOdJy8HjCj121R0uVkSwxQYKyYIBKikIhI VBEXeCGrZYaGVOWmYhmMrm2SPArhi7umSv2R6u9ppC8XEXRSKROuKUMCIWT5jzzssaB7 Dzp9W6ozZMKdiXAnYOa5fPC9JnlDNEq5fGV+We7XuUbjYdrMp601N/livDuFfnvgUWHB 8LUZ62usaWHWLSFcTz3xQBtpOoQPe0GKdnwy8WTCH9QaXEWJjP0CuKD50tG+QX7bu4B+ GvlA== X-Gm-Message-State: AOJu0YxEVKM43y4cxuFFtprhmgZHtt99niYe/MVpMJLd4chIat77mRow t5c0rBuPCIRCBHWL1hZtvxRPfA46mJrpO0WEGIE93XelZXJ7GoNbNhdzOg== X-Google-Smtp-Source: AGHT+IEBwv19NfnfNmjZNdW0qAgotZbH6+Hj2JalqwhPSmmnVJtJ5Eu/qsvFnDPCg3fGiuURbVmi8A== X-Received: by 2002:a05:6a21:9993:b0:1c4:b62f:fec7 with SMTP id adf61e73a8af0-1ccee4b732bmr12586840637.9.1725548579410; Thu, 05 Sep 2024 08:02:59 -0700 (PDT) Received: from Thaum. (163-47-68-2.ipv4.originbroadband.com.au. [163.47.68.2]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71778520f36sm3446634b3a.19.2024.09.05.08.02.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Sep 2024 08:02:59 -0700 (PDT) Message-ID: <66d9c823.a70a0220.7bd4f.d873@mx.google.com> X-Google-Original-Message-ID: Date: Fri, 6 Sep 2024 01:02:53 +1000 From: Nathaniel Shead To: gcc-patches@gcc.gnu.org Cc: Jason Merrill Subject: [PATCH] c++: Fix mangling of otherwise unattached class-scope lambdas [PR116568] MIME-Version: 1.0 Content-Disposition: inline X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org Bootstrapped and regtested (so far just dg.exp) on x86_64-pc-linux-gnu, OK for trunk if full regtest passes? Or would it be better to try to implement all the rules mentioned in the linked pull request for one commit; I admit I haven't looked very closely yet at how else we diverge? -- >8 -- This is a step closer to implementing the suggested changes for https://github.com/itanium-cxx-abi/cxx-abi/pull/85. The main purpose of the patch is to solve testcase PR c++/116568, caused by lambda expressions within the templates not correctly having the extra mangling scope attached. While I was working on this I found some other cases where the mangling of lambdas was incorrect and causing issues, notably the testcase lambda-ctx3.C which currently emits the same mangling for the base class and member lambdas, causing mysterious assembler errors. Fixing this ended up also improving the situation for PR c++/107741 as well, though it doesn't seem easily possible to fix the A::x case at this time so I've left that as an XFAIL. PR c++/107741 PR c++/116568 gcc/cp/ChangeLog: * cp-tree.h (LAMBDA_EXPR_EXTRA_SCOPE): Adjust comment. * parser.cc (cp_parser_class_head): Start (and do not finish) lambda scope for all valid types. (cp_parser_class_specifier): Finish lambda scope after parsing members instead. (cp_parser_member_declaration): Adjust comment to mention missing lambda scoping for static member initializers. * pt.cc (instantiate_class_template): Add lambda scoping. (instantiate_template): Likewise. gcc/testsuite/ChangeLog: * g++.dg/abi/lambda-ctx2.C: New test. * g++.dg/abi/lambda-ctx3.C: New test. * g++.dg/modules/lambda-8.h: New test. * g++.dg/modules/lambda-8_a.H: New test. * g++.dg/modules/lambda-8_b.C: New test. Signed-off-by: Nathaniel Shead --- gcc/cp/cp-tree.h | 3 +- gcc/cp/parser.cc | 31 +++++++++++++-------- gcc/cp/pt.cc | 12 +++++++- gcc/testsuite/g++.dg/abi/lambda-ctx2.C | 34 +++++++++++++++++++++++ gcc/testsuite/g++.dg/abi/lambda-ctx3.C | 21 ++++++++++++++ gcc/testsuite/g++.dg/modules/lambda-8.h | 7 +++++ gcc/testsuite/g++.dg/modules/lambda-8_a.H | 5 ++++ gcc/testsuite/g++.dg/modules/lambda-8_b.C | 5 ++++ 8 files changed, 104 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/abi/lambda-ctx2.C create mode 100644 gcc/testsuite/g++.dg/abi/lambda-ctx3.C create mode 100644 gcc/testsuite/g++.dg/modules/lambda-8.h create mode 100644 gcc/testsuite/g++.dg/modules/lambda-8_a.H create mode 100644 gcc/testsuite/g++.dg/modules/lambda-8_b.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 2eeb5e3e8b1..af1e254745b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1513,7 +1513,8 @@ enum cp_lambda_default_capture_mode_type { (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->locus) /* The mangling scope for the lambda: FUNCTION_DECL, PARM_DECL, VAR_DECL, - FIELD_DECL or NULL_TREE. If this is NULL_TREE, we have no linkage. */ + FIELD_DECL, TYPE_DECL, or NULL_TREE. If this is NULL_TREE, we have no + linkage. */ #define LAMBDA_EXPR_EXTRA_SCOPE(NODE) \ (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->extra_scope) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 5654bc00e4d..6e5228757a5 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -27051,6 +27051,8 @@ cp_parser_class_specifier (cp_parser* parser) if (!braces.require_open (parser)) { pop_deferring_access_checks (); + if (type != error_mark_node) + finish_lambda_scope (); return error_mark_node; } @@ -27115,7 +27117,10 @@ cp_parser_class_specifier (cp_parser* parser) if (cp_parser_allow_gnu_extensions_p (parser)) attributes = cp_parser_gnu_attributes_opt (parser); if (type != error_mark_node) - type = finish_struct (type, attributes); + { + type = finish_struct (type, attributes); + finish_lambda_scope (); + } if (nested_name_specifier_p) pop_inner_scope (old_scope, scope); @@ -27955,6 +27960,12 @@ cp_parser_class_head (cp_parser* parser, if (flag_concepts) type = associate_classtype_constraints (type); + /* Lambdas in bases and members must have the same mangling scope for ABI. + We open this scope now, and will close it in cp_parser_class_specifier + after parsing the member list. */ + if (type && type != error_mark_node) + start_lambda_scope (TYPE_NAME (type)); + /* We will have entered the scope containing the class; the names of base classes should be looked up in that context. For example: @@ -27969,16 +27980,10 @@ cp_parser_class_head (cp_parser* parser, if (cp_lexer_next_token_is (parser->lexer, CPP_COLON)) { if (type) - { - pushclass (type); - start_lambda_scope (TYPE_NAME (type)); - } + pushclass (type); bases = cp_parser_base_clause (parser); if (type) - { - finish_lambda_scope (); - popclass (); - } + popclass (); } else bases = NULL_TREE; @@ -28644,9 +28649,11 @@ cp_parser_member_declaration (cp_parser* parser) pure-specifier. It is not correct to parse the initializer before registering the member declaration since the member declaration should be in scope while - its initializer is processed. However, the rest of the - front end does not yet provide an interface that allows - us to handle this correctly. */ + its initializer is processed. And similarly, the ABI of + lambdas declared in the initializer should be scoped to + the member. However, the rest of the front end does not + yet provide an interface that allows us to handle this + correctly. */ if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) { /* In [class.mem]: diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 9195a5274e1..ed3aaaf4473 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -12482,6 +12482,10 @@ instantiate_class_template (tree type) gcc_assert (!DECL_CLASS_SCOPE_P (TYPE_MAIN_DECL (pattern)) || COMPLETE_OR_OPEN_TYPE_P (TYPE_CONTEXT (type))); + /* When instantiating nested lambdas, ensure that they get the mangling + scope of the new class type. */ + start_lambda_scope (TYPE_NAME (type)); + base_list = NULL_TREE; /* Defer access checking while we substitute into the types named in the base-clause. */ @@ -12841,6 +12845,8 @@ instantiate_class_template (tree type) finish_struct_1 (type); TYPE_BEING_DEFINED (type) = 0; + finish_lambda_scope (); + /* Remember if instantiating this class ran into errors, so we can avoid instantiating member functions in limit_bad_template_recursion. We set this flag even if the problem was in another instantiation triggered by @@ -22210,6 +22216,7 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain) ctx = tsubst_entering_scope (DECL_CONTEXT (gen_tmpl), targ_ptr, complain, gen_tmpl); push_nested_class (ctx); + start_lambda_scope (TYPE_NAME (ctx)); } tree pattern = DECL_TEMPLATE_RESULT (gen_tmpl); @@ -22239,7 +22246,10 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain) if (fndecl == NULL_TREE) fndecl = tsubst_decl (pattern, targ_ptr, complain, /*use_spec_table=*/false); if (DECL_CLASS_SCOPE_P (gen_tmpl)) - pop_nested_class (); + { + finish_lambda_scope (); + pop_nested_class (); + } pop_from_top_level (); if (fndecl == error_mark_node) diff --git a/gcc/testsuite/g++.dg/abi/lambda-ctx2.C b/gcc/testsuite/g++.dg/abi/lambda-ctx2.C new file mode 100644 index 00000000000..26896105a6c --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/lambda-ctx2.C @@ -0,0 +1,34 @@ +// PR c++/107741 +// { dg-do compile { target c++17 } } + +struct A { + // We currently parse static member initializers for non-templates before we + // see their decls, and so don't get the chance to attach it as scope. + static constexpr auto x = []{ return 1; }; +}; + +template +struct B { + static constexpr auto x = []{ return 2; }; +}; + +template +struct C { + static int x; +}; + +void side_effect(); + +template +int C::x = (side_effect(), []{ return 3; }()); + +template int C::x; + +void f() { + A::x(); + B::x(); +} + +// { dg-final { scan-assembler {_ZNK1A1xMUlvE_clEv:} { xfail *-*-* } } } +// { dg-final { scan-assembler {_ZNK1BIiE1xMUlvE_clEv:} } } +// { dg-final { scan-assembler {_ZNK1CIiE1xMUlvE_clEv:} } } diff --git a/gcc/testsuite/g++.dg/abi/lambda-ctx3.C b/gcc/testsuite/g++.dg/abi/lambda-ctx3.C new file mode 100644 index 00000000000..f92f2500531 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/lambda-ctx3.C @@ -0,0 +1,21 @@ +// { dg-do compile { target c++20 } } +// { dg-additional-options "-fkeep-inline-functions" } +// See also https://github.com/itanium-cxx-abi/cxx-abi/pull/85 + +struct A { + decltype([]{ return 1; }) f; +}; + +struct B : decltype([]{ return 2; }) { + decltype([]{ return 3; }) f; +}; + +struct C : decltype([]{ return 4; }) { + decltype([]{ return 5; }) f; +}; + +// { dg-final { scan-assembler {_ZNK1AUlvE_clEv:} } } +// { dg-final { scan-assembler {_ZNK1BUlvE_clEv:} } } +// { dg-final { scan-assembler {_ZNK1BUlvE0_clEv:} } } +// { dg-final { scan-assembler {_ZNK1CUlvE_clEv:} } } +// { dg-final { scan-assembler {_ZNK1CUlvE0_clEv:} } } diff --git a/gcc/testsuite/g++.dg/modules/lambda-8.h b/gcc/testsuite/g++.dg/modules/lambda-8.h new file mode 100644 index 00000000000..0c66f053b20 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/lambda-8.h @@ -0,0 +1,7 @@ +template struct S { + template static constexpr auto x = []{}; + template using t = decltype([]{}); +}; + +inline auto x = S::x; +using t = S::t; diff --git a/gcc/testsuite/g++.dg/modules/lambda-8_a.H b/gcc/testsuite/g++.dg/modules/lambda-8_a.H new file mode 100644 index 00000000000..d20958ee140 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/lambda-8_a.H @@ -0,0 +1,5 @@ +// PR c++/116568 +// { dg-additional-options "-fmodules-ts -std=c++20" } +// { dg-module-cmi {} } + +#include "lambda-8.h" diff --git a/gcc/testsuite/g++.dg/modules/lambda-8_b.C b/gcc/testsuite/g++.dg/modules/lambda-8_b.C new file mode 100644 index 00000000000..05ea4afd8c1 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/lambda-8_b.C @@ -0,0 +1,5 @@ +// PR c++/116568 +// { dg-additional-options "-fmodules-ts -std=c++20" } + +#include "lambda-8.h" +import "lambda-8_a.H";