From patchwork Sun Aug 11 19:41:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Seyed Sajad Kahani X-Patchwork-Id: 1971378 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20230601 header.b=XKW6C7QY; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4Whp2c2KBrz1yXh for ; Mon, 12 Aug 2024 05:42:30 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 778F03858C66 for ; Sun, 11 Aug 2024 19:42:28 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by sourceware.org (Postfix) with ESMTPS id E8C213858D34 for ; Sun, 11 Aug 2024 19:42:08 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E8C213858D34 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 E8C213858D34 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::435 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1723405331; cv=none; b=CJshSJpU+mO2NIKpcZ6rTlDc4BpbRTkbivM+84hKKnvf604zXCzKFRMXoiEhyw71oM3TA/8sf0Jn2hZn76s5aE7bhJ3lODRa7XYdTJVfBGXlkqMPq50nZ3vRa37TXnetVGcqGNATPsIzQxq9wzadxS92qt7N+UElsdLXiei/yqs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1723405331; c=relaxed/simple; bh=C1fjOhQ8KywC1AoY3z4kD5RF2C/rH//d984gXUIB3Kw=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=ewhV+dO7wntnh8o57f/0a5E4XG8y6P96f/2z2X6j5E3+X3/l5Z/mlxK7CIoJX2tC3UQ68wnWYdiax6gN4dCxEpXhsi1iscXGQWPb/np+yLjXZg63xkoDQ0sFv39TZq8s7D8dy5+vjYZguBkB+8tcq8MpsGKaBGm9Nkhq+Hs9qn0= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-wr1-x435.google.com with SMTP id ffacd0b85a97d-3687f91af40so2228617f8f.0 for ; Sun, 11 Aug 2024 12:42:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1723405327; x=1724010127; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1Iqy57NmkcFqDvnFXD28bFJ2Za2i4L2w+t2aG9S7NHg=; b=XKW6C7QYIN10ELp0W+LYu6YOWyxsMYwCmN3RiChgbdIGbIYqr7C/RAB5UKsPgQhO5i UOe+EEc1KrrDdfVDhrhQuW+EqkrE7HRA+6+21hTY/0yBaLdy6nwxmHUvMljQtMiMwPh+ sXHFxP/qoSwkEVOmKrgOYc/o9zlAWTd66In+eRsWJjCTZbHqZNmAjFgCT7TBgci0Hw5q PDLwdqErjVqj21f4z5UnjXyPW4bJ0l8PmfwVecZwmi2hp8+aTU8Ak4L7d4HIEJi/XVRv TKUeaVbENW236aXmfjwgwH/h3QTYbzjLBhSIixpmeawvZovlyQB9pDMxCwKE9sLG9gHH BtYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723405327; x=1724010127; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1Iqy57NmkcFqDvnFXD28bFJ2Za2i4L2w+t2aG9S7NHg=; b=TPJZs8rxQRv9Q0hhkUk0uQVRKFI5A2hJP0ZEGWrgPcMoxbHVi5mEjQaTePFgYp2Qux 5F9aNtK+LVwymDmHSEN+WpRZixdMIFXipQH3jVpIIdONw4Olw38BK4dt0K3xTA8luBef 9JiIR7/T5xNTK/haHFjwHRKXNa2iAzVJeSUZ4a5LQGc8va/Z3aOa3CC6U5zLm5zgOb51 GqfX8OCtxI4Pd/LNKzM3kK9b76WnEMc40py2ufAtU7qIGv+28OgGISGRn7Iay6W3qDWk Sw6NLfv+xBGmdX6FSmG/mmGVR/DKujzy2LZjHoczEhCoutHL4wT7OijZDOqgN+OuTx0Z dKWg== X-Gm-Message-State: AOJu0Yx+Q4Y7NFkAFQRgaaiuZed+6kvawzvVxT/c1qou5P0QfGF5QkWS JbvSc3uuuJA2zzU255QO6S2C1ABYBXNWDjNierkolo7mG7VliMtBKJm0/pRiUQ0= X-Google-Smtp-Source: AGHT+IHzztQ/0JDpAZZLkiZIvzWVk/kNAOX1cf9sY6zdZ/pyB/xjz+wRbBcm2p5VBmTO2katyPwNwA== X-Received: by 2002:adf:a116:0:b0:36b:bb84:33e2 with SMTP id ffacd0b85a97d-36d605453ddmr5841431f8f.37.1723405326862; Sun, 11 Aug 2024 12:42:06 -0700 (PDT) Received: from localhost.localdomain (cpc86130-nfds16-2-0-cust181.8-2.cable.virginm.net. [82.11.162.182]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-36e4ebd2bb4sm5572809f8f.91.2024.08.11.12.42.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 11 Aug 2024 12:42:06 -0700 (PDT) From: Seyed Sajad Kahani To: gcc-patches@gcc.gnu.org Cc: ppalka@redhat.com, jason@redhat.com, Seyed Sajad Kahani Subject: [PATCH] c++: Fix constrained auto deduction templ parms resolution [PR114915, PR115030] Date: Sun, 11 Aug 2024 20:41:52 +0100 Message-ID: <20240811194152.461060-1-sska1377@gmail.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: <33b1ff282ba1e64a6ed3b9faa79cafa43c79b784.camel@gmail.com> References: <33b1ff282ba1e64a6ed3b9faa79cafa43c79b784.camel@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_ENVFROM_END_DIGIT, 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~incoming=patchwork.ozlabs.org@gcc.gnu.org When deducing auto for `adc_return_type`, `adc_variable_type`, and `adc_decomp_type` contexts (at the usage time), we try to resolve the outermost template arguments to be used for satisfaction. This is done by one of the following, depending on the scope: 1. Checking the `DECL_TEMPLATE_INFO` of the current function scope and extracting `DECL_TI_ARGS` from it for function scope deductions (pt.cc:31236). 2. Checking the `DECL_TEMPLATE_INFO` of the declaration (alongside with other conditions) for non-function scope variable declaration deductions (decl.cc:8527). Note that `DECL_TI_ARGS` for partial and explicit specializations will yield the arguments with respect to the most_general_template, which is the primary template. This can lead to rejection of valid code or acceptance of invalid code (PR115030) in a partial specialization context. For an explicitly specialized case, due to the mismatch between the desired depth and the actual depth of args, it can lead to ICEs (PR114915) where we intend to fill the missing levels with dummy levels (pt.cc:31260), while the missing levels are negative. This patch resolves PR114915 and PR115030 by replacing the logic of extracting args for the declaration in those two places with `outer_template_args`. `outer_template_args` is an existing function that was used in limited contexts to do so. Now, it is extended to handle partial and explicit specializations and lambda functions as well. A few inevitable changes are also made to the signature of some functions, relaxing `const_tree` to `tree`. PR c++/114915 PR c++/115030 gcc/cp/ChangeLog: * constraint.cc (maybe_substitute_reqs_for): Relax the argument type to be compatible with outer_template_args. * cp-tree.h (outer_template_args): Relax the argument type and add an optional argument. (maybe_substitute_reqs_for): Relax the argument type to be compatible with outer_template_args. * decl.cc (cp_finish_decl): Replace the logic of extracting args with outer_template_args. * pt.cc (outer_template_args): Handle partial and explicit specializations and lambda functions. (do_auto_deduction): Replace the logic of extracting args with outer_template_args. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-placeholder14.C: New test. * g++.dg/cpp2a/concepts-placeholder15.C: New test. * g++.dg/cpp2a/concepts-placeholder16.C: New test. * g++.dg/cpp2a/concepts-placeholder17.C: New test. --- gcc/cp/constraint.cc | 2 +- gcc/cp/cp-tree.h | 4 +- gcc/cp/decl.cc | 4 +- gcc/cp/pt.cc | 71 ++++++++++++------- .../g++.dg/cpp2a/concepts-placeholder14.C | 19 +++++ .../g++.dg/cpp2a/concepts-placeholder15.C | 26 +++++++ .../g++.dg/cpp2a/concepts-placeholder16.C | 33 +++++++++ .../g++.dg/cpp2a/concepts-placeholder17.C | 21 ++++++ 8 files changed, 150 insertions(+), 30 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder15.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder17.C diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index ebf4255e5..a1c3962c4 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -1332,7 +1332,7 @@ remove_constraints (tree t) for declaration matching. */ tree -maybe_substitute_reqs_for (tree reqs, const_tree decl) +maybe_substitute_reqs_for (tree reqs, tree decl) { if (reqs == NULL_TREE) return NULL_TREE; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9a8c86591..2d6733f57 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7215,7 +7215,7 @@ extern tree maybe_set_retval_sentinel (void); extern tree template_parms_to_args (tree); extern tree template_parms_level_to_args (tree); extern tree generic_targs_for (tree); -extern tree outer_template_args (const_tree); +extern tree outer_template_args (tree, bool = true); /* in expr.cc */ extern tree cplus_expand_constant (tree); @@ -8560,7 +8560,7 @@ extern void remove_constraints (tree); extern tree current_template_constraints (void); extern tree associate_classtype_constraints (tree); extern tree build_constraints (tree, tree); -extern tree maybe_substitute_reqs_for (tree, const_tree); +extern tree maybe_substitute_reqs_for (tree, tree); extern tree get_trailing_function_requirements (tree); extern tree get_shorthand_constraints (tree); diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index a139b293e..6b68d5f39 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -8557,10 +8557,10 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl) && !DECL_FUNCTION_SCOPE_P (decl)) - /* The outer template arguments might be needed for satisfaction. + /* The outer template arguments might be needed for satisfaction. (For function scope variables, do_auto_deduction will obtain the outer template arguments from current_function_decl.) */ - outer_targs = DECL_TI_ARGS (decl); + tree outer_targs = outer_template_args (decl, false); type = TREE_TYPE (decl) = do_auto_deduction (type, d_init, auto_node, tf_warning_or_error, adc, outer_targs, flags); diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 32640f8e9..e9bad58f3 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -4998,23 +4998,57 @@ generic_targs_for (tree tmpl) /* Return the template arguments corresponding to the template parameters of DECL's enclosing scope. When DECL is a member of a partial specialization, this returns the arguments for the partial specialization as opposed to those - for the primary template, which is the main difference between this function - and simply using e.g. the TYPE_TI_ARGS of DECL's DECL_CONTEXT. */ - + for the primary template, and for a full specialization, it returns null. + STRIP_CURRENT specifies whether it should include currently declared + templates or not. */ tree -outer_template_args (const_tree decl) +outer_template_args (tree decl, bool strip_current /* = true */) { if (TREE_CODE (decl) == TEMPLATE_DECL) decl = DECL_TEMPLATE_RESULT (decl); tree ti = get_template_info (decl); + tree args = NULL_TREE; + if (!ti) - return NULL_TREE; - tree args = TI_ARGS (ti); - if (!PRIMARY_TEMPLATE_P (TI_TEMPLATE (ti))) - return args; - if (TMPL_ARGS_DEPTH (args) == 1) - return NULL_TREE; - return strip_innermost_template_args (args, 1); + { + if (DECL_FUNCTION_SCOPE_P (decl)) + args = outer_template_args (DECL_CONTEXT (decl), false); + } + else + { + if (PRIMARY_TEMPLATE_P (TI_TEMPLATE (ti)) && TI_PARTIAL_INFO (ti)) + ti = TI_PARTIAL_INFO (ti); + + /* For an explicitly specialized declaration. */ + if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_SPECIALIZATION (decl)) + args = NULL_TREE; + else + { + args = TI_ARGS (ti); + + int parms_depth = + TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (TI_TEMPLATE (ti))); + /* If any of outer scopes are explicitly specialized. */ + if (TMPL_ARGS_DEPTH(args) > parms_depth) + args = get_innermost_template_args (args, parms_depth); + + if (strip_current && PRIMARY_TEMPLATE_P (TI_TEMPLATE (ti))) + { + if (TMPL_ARGS_DEPTH (args) == 1) + return NULL_TREE; + return strip_innermost_template_args (args, 1); + } + } + } + + /* Special treatment of lambda functions. */ + if (LAMBDA_FUNCTION_P (decl) && !strip_current) + { + tree regen_targs = lambda_regenerating_args (decl); + args = add_to_template_args (regen_targs, args); + } + + return args; } /* Update the declared TYPE by doing any lookups which were thought to be @@ -31233,20 +31267,7 @@ do_auto_deduction (tree type, tree init, tree auto_node, || context == adc_variable_type || context == adc_decomp_type) if (tree fn = current_function_decl) - if (DECL_TEMPLATE_INFO (fn) || LAMBDA_FUNCTION_P (fn)) - { - outer_targs = DECL_TEMPLATE_INFO (fn) - ? DECL_TI_ARGS (fn) : NULL_TREE; - if (LAMBDA_FUNCTION_P (fn)) - { - /* As in satisfy_declaration_constraints. */ - tree regen_args = lambda_regenerating_args (fn); - if (outer_targs) - outer_targs = add_to_template_args (regen_args, outer_targs); - else - outer_targs = regen_args; - } - } + outer_targs = outer_template_args(fn, false); tree full_targs = outer_targs; if (context == adc_unify && tmpl) diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C new file mode 100644 index 000000000..fcdbd7608 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C @@ -0,0 +1,19 @@ +// PR c++/114915 +// { dg-do compile { target c++20 } } + +template +concept C = __is_same(T, int); + +template +void f() { +} + +template<> +void f() { + C auto x = 1; +} + +int main() { + f(); + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder15.C b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder15.C new file mode 100644 index 000000000..b507e4165 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder15.C @@ -0,0 +1,26 @@ +// PR c++/114915 +// { dg-do compile { target c++20 } } + +template +concept C = __is_same(T, U); + +template +int x = 0; + +template<> +C auto x = 1.0; + +template +struct S {}; + +template +int y = 0; + +template +C auto y> = 'c'; + +int main() { + if (y> != 'c') + return 1; + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C new file mode 100644 index 000000000..f808ef1b6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder16.C @@ -0,0 +1,33 @@ +// PR c++/114915 +// { dg-do compile { target c++20 } } + +template +concept C = __is_same(T, U); + +template +struct A +{ + template + void f() { + } +}; + +template<> +template<> +void A::f() { + C auto x = 1; +} + +template<> +template +void A::f() { + C auto x = 1; +} + +int main() { + A a; + a.f(); + A b; + b.f(); + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder17.C b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder17.C new file mode 100644 index 000000000..4a8dcb3d5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder17.C @@ -0,0 +1,21 @@ + +// PR c++/115030 +// { dg-do compile { target c++20 } } + +template +concept C = __is_same(T, U); + +template +struct s { +}; + +template +char v = 'a'; + +template +C auto v> = 'c'; + +int main() { + v> = 'b'; + return 0; +} \ No newline at end of file