From patchwork Mon Mar 25 20:44:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 87642 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 24B153858421 for ; Mon, 25 Mar 2024 20:45:40 +0000 (GMT) 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 6166F3858401 for ; Mon, 25 Mar 2024 20:44:55 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6166F3858401 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 6166F3858401 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711399498; cv=none; b=RGOl33tHrfcIpjewKEkcQa4altAroy631Jnr+UaTymIsAubWcYp59o9q/CK8oSt3jSA0b3KQUj4XSq+VpYsYS8h2s/dhVez3oVwTXgm4VrNgzfQkkNnLbytJpXDDCroXewifkIHmaJKfr5n7AZry1mbM2G75poI2K/b8lSXInO4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1711399498; c=relaxed/simple; bh=T0gSMYWJkJwVHJwsiN9VSatQ9FAN1w0phNsju3yrPvw=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=aIBqlO4GOHlQmIPk5eJndekFrKM3EYueFwhZWf4xZWsPKI+osawESfrbHV36WqWlMFAqvVB3WUCE+7EVIyc2T1Zrl/T3iaC1MUTm6DThyc70DG93wMbKEZJrsUcnGRoAMsIJJ7DH3RpVbnelXpG+VKvWoqv2l7hnzEjlNRFuDh8= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1711399495; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=SMqO26UGGpPagteUu4GBnowYrW+UqHTh29R+MqIGbK4=; b=Y/x7uqt/4D8hgHbqk+ZCXQb0cq3Y6UWrA/JVt/izOz9QgZuzDMwHjQ6LSTzvNlOI0H5epJ T2MO9ZR1c8pI6sQk/9It35hfJbkpMSOblh0tRMcmqxr5o6UXRmf67+x1GATyBlpVMwmvak u0wMTM5O4vK3gQ86Iclh1A9SP2zC1wI= Received: from mail-vk1-f200.google.com (mail-vk1-f200.google.com [209.85.221.200]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-194-4XPJ-2PKML2mYY_w-UV3jQ-1; Mon, 25 Mar 2024 16:44:53 -0400 X-MC-Unique: 4XPJ-2PKML2mYY_w-UV3jQ-1 Received: by mail-vk1-f200.google.com with SMTP id 71dfb90a1353d-4d43e670faeso1326224e0c.2 for ; Mon, 25 Mar 2024 13:44:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711399492; x=1712004292; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=SMqO26UGGpPagteUu4GBnowYrW+UqHTh29R+MqIGbK4=; b=kbbYvJ7lh8i+/RGKxKYnXu0PbqH7NfaQaEULP3ZMSrhIi4fDJHJKu3I90AG35Av6Py mKLagiE+DS8VYi02Lfsun9nIZgZLc0soqNOTDSngDQvy9l6CZtO7rfKxE90Xgigzfyf5 RJv14qI/DXsJfpzB5ErW8hPHkP1nYsKtj7ircwUzX5VflE8aC2bg837ubeZM0qZdoChY uSq3HNaftXC5M8oP/fHcjILNijLE0/JOGf7G+GFNL6yKftpD1t3XVFkiZYfM2TVejFgz UkMo70JZ1F50Zb1Wu2L92cfMrqvd+InEkOi7ZtVugte11b+wEk8kdM/55E9Hidv7tc7A i/Pg== X-Gm-Message-State: AOJu0YzLT0M+8sN7Iq2t01CYeEeZ9VNIY5LK4YOwVMd3eWvgTt9JOjCE i2hTQTf+GGWXhdbHz4jPeepJUvrYvB14YpNZaoPFwPmucBI98sSTXsSrcG74TJ+3mwhXYr4+wLB 0CeQXoP+us5/WnHbMluQJw64jywxQl70AhYlGEDvA1ORLKnUUt4y4bVyzClmcIBIWAAo3Qw4oS6 tIJk+wcl4UFw79c4lJ5rN5Jl4HzjYQdvvtbvzp X-Received: by 2002:a05:6122:1d02:b0:4d8:7970:28e6 with SMTP id gc2-20020a0561221d0200b004d8797028e6mr6073750vkb.0.1711399491727; Mon, 25 Mar 2024 13:44:51 -0700 (PDT) X-Google-Smtp-Source: AGHT+IH7brDUOHXbxRlOeWAV9EP/GXBz3ttBqBOcmzOnC7IWcwFVRliZ54Vi1q8TKl17vrfmab4ZkQ== X-Received: by 2002:a05:6122:1d02:b0:4d8:7970:28e6 with SMTP id gc2-20020a0561221d0200b004d8797028e6mr6073698vkb.0.1711399490440; Mon, 25 Mar 2024 13:44:50 -0700 (PDT) Received: from localhost.localdomain (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id e2-20020a0cf742000000b006967565c827sm3361053qvo.141.2024.03.25.13.44.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Mar 2024 13:44:50 -0700 (PDT) From: Patrick Palka To: gcc-patches@gcc.gnu.org Cc: jason@redhat.com, Patrick Palka Subject: [PATCH] c++: templated substitution into lambda-expr [PR114393] Date: Mon, 25 Mar 2024 16:44:48 -0400 Message-ID: <20240325204448.340940-1-ppalka@redhat.com> X-Mailer: git-send-email 2.44.0.325.g11c821f2f2 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, URIBL_BLACK 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 on x86_64-pc-linux-gnu, does this look OK for trunk? -- >8 -- The below testcases use a lambda-expr as a template argument and they all trip over the below added tsubst_lambda_expr sanity check ultimately because current_template_parms is empty, which causes push_template_decl to return error_mark_node from the call to begin_lambda_type. Were it not for the sanity check this silent error_mark_node result leads to nonsensical errors down the line, or silent breakage. In the first testcase, we hit this assert during instantiation of the dependent alias template-id c1_t<_Data> from instantiate_template, which clears current_template_parms via push_to_top_level. Similar story for the second testcase. For the third testcase we hit the assert during partial instantiation of the member template from instantiate_class_template which similarly calls push_to_top_level. These testcases illustrate that templated substitution into a lambda-expr is not always possible, in particular when we lost the relevant template context. I experimented with recovering the template context by making tsubst_lambda_expr fall back to using scope_chain->prev->template_parms if current_template_parms is empty which worked but seemed like a hack. I also experimented with preserving the template context by keeping current_template_parms set during instantiate_template for a dependent specialization which also worked but it's at odds with the fact that we cache dependent specializations (and so they should be independent of the template context). So instead of trying to make such substitution work, this patch uses the extra-args mechanism to defer templated substitution into a lambda-expr when we lost the relevant template context. PR c++/114393 PR c++/107457 PR c++/93595 gcc/cp/ChangeLog: * cp-tree.h (LAMBDA_EXPR_EXTRA_ARGS): (struct GTY): * module.cc (trees_out::core_vals) : Stream LAMBDA_EXPR_EXTRA_ARGS. (trees_in::core_vals) : Likewise. * pt.cc (has_extra_args_mechanism_p): (tsubst_lambda_expr): gcc/testsuite/ChangeLog: * g++.dg/cpp2a/lambda-targ2.C: New test. * g++.dg/cpp2a/lambda-targ3.C: New test. * g++.dg/cpp2a/lambda-targ4.C: New test. --- gcc/cp/cp-tree.h | 5 +++++ gcc/cp/module.cc | 2 ++ gcc/cp/pt.cc | 20 ++++++++++++++++++-- gcc/testsuite/g++.dg/cpp2a/lambda-targ2.C | 19 +++++++++++++++++++ gcc/testsuite/g++.dg/cpp2a/lambda-targ3.C | 12 ++++++++++++ gcc/testsuite/g++.dg/cpp2a/lambda-targ4.C | 12 ++++++++++++ 6 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ2.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ3.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-targ4.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index c29a5434492..27100537038 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1538,6 +1538,10 @@ enum cp_lambda_default_capture_mode_type { #define LAMBDA_EXPR_REGEN_INFO(NODE) \ (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->regen_info) +/* Like PACK_EXPANSION_EXTRA_ARGS, for lambda-expressions. */ +#define LAMBDA_EXPR_EXTRA_ARGS(NODE) \ + (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->extra_args) + /* The closure type of the lambda, which is also the type of the LAMBDA_EXPR. */ #define LAMBDA_EXPR_CLOSURE(NODE) \ @@ -1550,6 +1554,7 @@ struct GTY (()) tree_lambda_expr tree this_capture; tree extra_scope; tree regen_info; + tree extra_args; vec *pending_proxies; location_t locus; enum cp_lambda_default_capture_mode_type default_capture_mode : 2; diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 52c60cf370c..1cd890909e3 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -6312,6 +6312,7 @@ trees_out::core_vals (tree t) WT (((lang_tree_node *)t)->lambda_expression.this_capture); WT (((lang_tree_node *)t)->lambda_expression.extra_scope); WT (((lang_tree_node *)t)->lambda_expression.regen_info); + WT (((lang_tree_node *)t)->lambda_expression.extra_args); /* pending_proxies is a parse-time thing. */ gcc_assert (!((lang_tree_node *)t)->lambda_expression.pending_proxies); if (state) @@ -6814,6 +6815,7 @@ trees_in::core_vals (tree t) RT (((lang_tree_node *)t)->lambda_expression.this_capture); RT (((lang_tree_node *)t)->lambda_expression.extra_scope); RT (((lang_tree_node *)t)->lambda_expression.regen_info); + RT (((lang_tree_node *)t)->lambda_expression.extra_args); /* lambda_expression.pending_proxies is NULL */ ((lang_tree_node *)t)->lambda_expression.locus = state->read_location (*this); diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 8cf0d5b7a8d..b1a9ee2b385 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -3855,7 +3855,8 @@ has_extra_args_mechanism_p (const_tree t) return (PACK_EXPANSION_P (t) /* PACK_EXPANSION_EXTRA_ARGS */ || TREE_CODE (t) == REQUIRES_EXPR /* REQUIRES_EXPR_EXTRA_ARGS */ || (TREE_CODE (t) == IF_STMT - && IF_STMT_CONSTEXPR_P (t))); /* IF_STMT_EXTRA_ARGS */ + && IF_STMT_CONSTEXPR_P (t)) /* IF_STMT_EXTRA_ARGS */ + || TREE_CODE (t) == LAMBDA_EXPR) /* LAMBDA_EXPR_EXTRA_ARGS */; } /* Structure used to track the progress of find_parameter_packs_r. */ @@ -19571,6 +19572,18 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) tree oldfn = lambda_function (t); in_decl = oldfn; + args = add_extra_args (LAMBDA_EXPR_EXTRA_ARGS (t), args, complain, in_decl); + if (processing_template_decl && !in_template_context) + { + /* Defer templated substitution into a lambda-expr when arguments + are dependent or when we lost the necessary template context, + which may happen for a lambda-expr used as a template argument. */ + t = copy_node (t); + LAMBDA_EXPR_EXTRA_ARGS (t) = NULL_TREE; + LAMBDA_EXPR_EXTRA_ARGS (t) = build_extra_args (t, args, complain); + return t; + } + tree r = build_lambda_expr (); LAMBDA_EXPR_LOCATION (r) @@ -19662,7 +19675,10 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) tree type = begin_lambda_type (r); if (type == error_mark_node) - return error_mark_node; + { + gcc_checking_assert (!(complain & tf_error) || seen_error ()); + return error_mark_node; + } if (LAMBDA_EXPR_EXTRA_SCOPE (t)) record_lambda_scope (r); diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ2.C b/gcc/testsuite/g++.dg/cpp2a/lambda-targ2.C new file mode 100644 index 00000000000..41b8d8749f2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ2.C @@ -0,0 +1,19 @@ +// PR c++/114393 +// { dg-do compile { target c++20 } } + +template struct c1 {}; + +template +inline constexpr auto b_v = t; + +template +using c1_t = c1>; + +template +constexpr auto g(_Data __data) { + return c1_t<_Data>{}; +} + +void f() { + auto &&b = g(0); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ3.C b/gcc/testsuite/g++.dg/cpp2a/lambda-targ3.C new file mode 100644 index 00000000000..31d08add277 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ3.C @@ -0,0 +1,12 @@ +// PR c++/107457 +// { dg-do compile { target c++20 } } + +template +using lambda = decltype([]() {}); + +template> +void test() { } + +int main() { + test(); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ4.C b/gcc/testsuite/g++.dg/cpp2a/lambda-targ4.C new file mode 100644 index 00000000000..341a1aa5bb1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ4.C @@ -0,0 +1,12 @@ +// PR c++/93595 +// { dg-do compile { target c++20 } } + +template +struct bad { + template + static void f(T) { } +}; + +int main() { + bad<0>::f(0); +}