From patchwork Mon Aug 12 15:04: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: 1971633 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=VtZNjp4I; 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 4WjHrY4JlJz1yXl for ; Tue, 13 Aug 2024 01:05:33 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2C2A3385841E for ; Mon, 12 Aug 2024 15:05:31 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-lf1-x12d.google.com (mail-lf1-x12d.google.com [IPv6:2a00:1450:4864:20::12d]) by sourceware.org (Postfix) with ESMTPS id 2F59A3858D39 for ; Mon, 12 Aug 2024 15:05:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 2F59A3858D39 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 2F59A3858D39 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::12d ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1723475112; cv=none; b=dVr6Rg5/wGrGGyO9xO70yFQ4FkU2kibAYcf9gGyH0WqlcLTLeRk3sgtghAZLGOv4/wIf1WvJOrE7IgYhm00Xj/udiyRMTsEMpFISczTjbxHyZ+rA8qeZMCV75/BQjQvsypnM6E1PNsrj1uL5EBJfcwDsPMrWT2ia6xKC3/iAc50= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1723475112; c=relaxed/simple; bh=Eks2PFqW1JULqdbkquiO9tDGpx8HHeiKE8QsJ8YYILs=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=mF7Ul2J8ay6Yp4UUKe2BONHRDx224CVS9zP5nDxF8QFtfUNSLQaBIte8+yW/FtJfu5Eqn83DO+kicfAuJifEzSFNyrPv0jUBcJKsSX7O/dON8ihb9Kps5cytfqoMd7iwhhWASEy87hY6YR7b92azqmsTH+8jBOzrOzRp3PPLQlM= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-lf1-x12d.google.com with SMTP id 2adb3069b0e04-52f025ab3a7so562840e87.2 for ; Mon, 12 Aug 2024 08:05:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1723475104; x=1724079904; 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=wVd+wrKMS3pI4Z0tEWJagIroPOyndWtlg2YxVEvOwmw=; b=VtZNjp4IuftR2w8wYtpIyI281Pqmb85QnAxKCwrGvlZKcqNxex7xIwiDXbL3AEfkMy tyuWwUHU9LOO+4/eW8Bsb3/D0p8MjDcTGjKhohXtBm1JClvKn1FGEjFKou5WtH5wJaqW nD5/ycg6VZ+psuSDqDHwD4AHawFC71T7DCTExAQbhHC/JH6M2RfXc4UJWTMQpXMMTgNn XYJR1RNJ5TKTMAONK+qL6bt10XUtNKjJZfSvPnfHA+DHXnF7V2i5dfy2z6WdEvPtObrY ju7VPRMJUweT/XbwvGLrneSsJH6fk0vIMBGMh3aPGfzTqwjU3cu6iZ6lMALdLVcoXIk4 6hDA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1723475104; x=1724079904; 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=wVd+wrKMS3pI4Z0tEWJagIroPOyndWtlg2YxVEvOwmw=; b=Ki0gU9rrsrOroq/pYv0upwJPIvi7KNETQj3yoghG6uQp9m8g19bjIwbe+rJ0sj2maM lDQVntkQLUKZitxC3h1mVWj05NCdlY2BfyLp+LOOzteAXs/rK6M5lit8w84hTdw4e6UB 6KaqBjrN0TIDxS2981X0RDNep63gfwc/fjDsPrG7zOcauiong5kCnU/eZ7H9yA1Lfn+D 9XbtEohln8tprCcdBZN4JWmWAPDT6910dN9Qs/PRxwCqxzfSS9HAqZs9Z0RFNbFlfpV7 s/zAMl5TQCwkxUAK3myyG4HkoMOOzVTK+nHUNLh4f5RzfjpeJFN6Rdaeu+3awLlN10q1 LJpQ== X-Gm-Message-State: AOJu0Yxl03c8M/VToqTkDRzuBiLLxJ2r+nGEF9PXVNRLfTtSeMdeLlTu wdt0pTvAbxyd2nAgVcYobCaHK23b0RHDlLRP5xc3MpbjUaCpI2nMupZTciFs X-Google-Smtp-Source: AGHT+IEuLAVPapjRGx0WRL1Ww2fWKmmg0iaSJyRsBLc+I5A21Ld4TTGjG+1qxZXURVPT364wti1o1w== X-Received: by 2002:a05:6512:12d3:b0:52c:80f6:d384 with SMTP id 2adb3069b0e04-5321364b96cmr357509e87.3.1723475103698; Mon, 12 Aug 2024 08:05:03 -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-36e4e51ea56sm7731562f8f.76.2024.08.12.08.05.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 12 Aug 2024 08:05:03 -0700 (PDT) From: Seyed Sajad Kahani To: gcc-patches@gcc.gnu.org Cc: ppalka@redhat.com, jason@redhat.com, Seyed Sajad Kahani Subject: [PATCH v2] c++: Fix constrained auto deduction templ parms resolution [PR114915, PR115030] Date: Mon, 12 Aug 2024 16:04:52 +0100 Message-ID: <20240812150452.1302484-1-sska1377@gmail.com> X-Mailer: git-send-email 2.46.0 In-Reply-To: <20240811194152.461060-1-sska1377@gmail.com> References: <20240811194152.461060-1-sska1377@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.7 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 | 2 +- gcc/cp/pt.cc | 84 +++++++++++++------ .../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 | 20 +++++ 8 files changed, 161 insertions(+), 29 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..3a9344a32 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -8560,7 +8560,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, /* 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); + 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..b446884c8 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -4998,23 +4998,70 @@ 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 actual_depth = TMPL_ARGS_DEPTH (args); + /* Finding explicitly specialized scopes */ + for (tree tmpl = TI_TEMPLATE(ti); + DECL_LANG_SPECIFIC (tmpl) && DECL_TEMPLATE_INFO (tmpl); + tmpl = DECL_TI_TEMPLATE (tmpl)) + { + if (DECL_TEMPLATE_SPECIALIZATION (tmpl)) + { + actual_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)); + break; + } + if (TREE_CODE (DECL_TI_TEMPLATE (tmpl)) != TEMPLATE_DECL) + break; + } + + /* If any of outer scopes are explicitly specialized. */ + if (TMPL_ARGS_DEPTH(args) > actual_depth) + args = get_innermost_template_args (args, actual_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 +31280,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..a8bd48e39 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder17.C @@ -0,0 +1,20 @@ +// 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; +}