From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 82AF03858C33 for ; Fri, 2 Feb 2024 20:57:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 82AF03858C33 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 82AF03858C33 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=1706907445; cv=none; b=fVeWa9iU7snEIiSDtJxUjtMOvOHOpKZ6kxoMbsPYhKd51bUpbn/OnTwVn+xarULRpjSta8CJrVZoqHDwKaeycNxCIYimkxx8MNX7wDZsf/n+BmAquEMNxv5HM//OTuvZCHoHY3zeOD33+gjelU6XR28VAdQ5Hor9TvBib0Q2XPo= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706907445; c=relaxed/simple; bh=fgssMJxNVi5Oaw8xZ3rDyWPuctkww2kw0cqt6uHLfig=; h=DKIM-Signature:From:Date:To:Subject:Message-ID:MIME-Version; b=tniVr1Oq4vhEs9kIhjaeIyoXwmvkkcthKxE3n5tVLYyvUkgpC8m+VwpA1rRtsH1vH+IhDwvuq9n5A5UWInmHzcGW4OhemM1UlG7IVSEYIRKMdSSGlJthCcL97cGzT30hkQotTsq8lexYwnaknxHOblrexCoND1AUGVxItuu+60U= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1706907441; 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: in-reply-to:in-reply-to:references:references; bh=lVIG3ZzNbLawgipgc9uhLYr1upkzZCHc6UusUKeHCAw=; b=JmHrvr+yy4t9637L71C7b3ieif3dsaShF7PLEFZUOgsHrO2os6z0KBFp7CYBok3tgL0ova 6IjrwZ/VSwAJdiYaL2fJGnwSwfYThp1eQY0fPWn7oeAcEFZwKFQS7DNN9La1CZB0X/bafX DH4Tuz/1SpDu3lEzXJ37VtWEfEMUZQw= Received: from mail-qv1-f71.google.com (mail-qv1-f71.google.com [209.85.219.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-16-RLV8LbZOPQaGk7LWuvnLkA-1; Fri, 02 Feb 2024 15:57:18 -0500 X-MC-Unique: RLV8LbZOPQaGk7LWuvnLkA-1 Received: by mail-qv1-f71.google.com with SMTP id 6a1803df08f44-68c52361422so30683116d6.3 for ; Fri, 02 Feb 2024 12:57:18 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706907438; x=1707512238; h=mime-version:references:message-id:in-reply-to:subject:cc:to:date :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=lVIG3ZzNbLawgipgc9uhLYr1upkzZCHc6UusUKeHCAw=; b=L8oAVGj2EAFzdaqskNZ0mJP3CX+2wcVeyAhxCDvy3Q5SdMFvzemSdCR1QNvWqi2RWR 7n1/JYoVcNeiJ+8Rfm54k0wmB7djrminG9Ha9aEQB9OcD///aey6GPDt/h8glk+CkMG5 5A1jTj7Q4jX4Q9FUAo+xQE3LeMm6LHBHHUA18NFAHpE41uImEQ0BqZvCgwRfJo0CQHDE cuqV7bsHbKqXDvDPmUxmg9OnRoWcuOAOq5IAZelgrRPF7bTeTMYRMzEYCa9TQM9w40Rv a0r0chsWm2lRFseCWdF9wf/lhuSQaKlBQjljbd+Fc/ekI5W/cxKdxt05/Tc7DjywVs+V 1HLA== X-Gm-Message-State: AOJu0YxVGWj21+0eSh9Az+bBc0j9Ap1icMpq71oQvzduBjI7vqtULXFM 9wEaUgPUsW8xY3jXtqelNkj77+wWD0mt0bJXYmV9pdwWK880O4uL3oOvb3vrywp3VfS+xRmmVfZ 3y1HtyuvOk2pBEcy5r+YsE17wJl9omNedUdRPfyjjgo7G5atw/8G6678= X-Received: by 2002:a0c:f0c8:0:b0:68c:85db:aa5e with SMTP id d8-20020a0cf0c8000000b0068c85dbaa5emr2568496qvl.21.1706907438187; Fri, 02 Feb 2024 12:57:18 -0800 (PST) X-Google-Smtp-Source: AGHT+IFHLI3U4Cr9cFUzz9M/1kZ0Ow0ZeCwe2737bEk4M90+3obyPZwNEpBUvomIXCh5KTHqJvfU6A== X-Received: by 2002:a0c:f0c8:0:b0:68c:85db:aa5e with SMTP id d8-20020a0cf0c8000000b0068c85dbaa5emr2568485qvl.21.1706907437766; Fri, 02 Feb 2024 12:57:17 -0800 (PST) X-Forwarded-Encrypted: i=0; AJvYcCVI9CW7l6EW/Dx6Dq8n5FqAJHaehcCkBB2ufk577egXmeAtV3oMlmQUth9xdWPTsvbCHMngH9lc15PhvZEFVs6SXT73Jmbb+g== Received: from [192.168.1.130] (ool-457670bb.dyn.optonline.net. [69.118.112.187]) by smtp.gmail.com with ESMTPSA id e6-20020ad450c6000000b0068c6fe93f45sm1127367qvq.122.2024.02.02.12.57.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Feb 2024 12:57:17 -0800 (PST) From: Patrick Palka X-Google-Original-From: Patrick Palka Date: Fri, 2 Feb 2024 15:57:16 -0500 (EST) To: Patrick Palka cc: Jason Merrill , gcc-patches@gcc.gnu.org Subject: Re: [PATCH 1/2] c++: requires-exprs and partial constraint subst [PR112769] In-Reply-To: <5f06be77-2314-65e4-a242-b84059bebfbe@idea> Message-ID: <720eaacc-cd6a-8a66-e057-752c6a21183d@idea> References: <20240202194104.317982-1-ppalka@redhat.com> <5f06be77-2314-65e4-a242-b84059bebfbe@idea> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=US-ASCII X-Spam-Status: No, score=-14.1 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_H5,RCVD_IN_MSPIKE_WL,RCVD_IN_SORBS_WEB,SPF_HELO_NONE,SPF_NONE,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 List-Id: On Fri, 2 Feb 2024, Patrick Palka wrote: > On Fri, 2 Feb 2024, Jason Merrill wrote: > > > On 2/2/24 14:41, Patrick Palka wrote: > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this > > > look OK for trunk? > > > > > > -- >8 -- > > > > > > In r11-3261-gb28b621ac67bee we made tsubst_requires_expr never partially > > > substitute into a requires-expression so as to avoid checking its > > > requirements out of order during e.g. generic lambda regeneration. > > > > > > Unfortunately we still do need to partially substitute into a > > > requires-expression in rare cases, in particular when it's used in > > > associated constraints that we are directly substituting for sake of > > > declaration matching or dguide constraint rewriting. We can identify > > > this situation by checking processing_constraint_expression_p, so this > > > patch uses this predicate to control whether we defer substitution or > > > partially substitute. The entering_scope=true change in tsubst_baselink > > > is needed to avoid ICEing from tsubst_baselink during name lookup when > > > rewriting std::ranges::ref_view's dguide constraints. > > > > Actually, I don't think we want to enter the scope when rewriting constraints. > > Would tsubst_scope work instead? > > Oops yes, because of the maybe_dependent_member_ref stuff, the handling > for which doesn't trigger here for some reason. Ah, I think it's > because the tf_dguide flag gets dropped during tsubst_requires_expr > since it uses tf_none rather than complain & ~tf_warning_or_error > which would preserve special tsubst flags such as tf_dguide. I'll fix... Like so? Lightly tested so far, bootstrap+regtest in progress. -- >8 -- Subject: [PATCH v2] c++: requires-exprs and partial constraint subst [PR112769] In r11-3261-gb28b621ac67bee we made tsubst_requires_expr never partially substitute into a requires-expression so as to avoid checking its requirements out of order during e.g. generic lambda regeneration. Unfortunately we still do need to partially substitute into a requires-expression in rare cases, in particular when it's used in associated constraints that we are directly substituting for sake of declaration matching or dguide constraint rewriting. We can identify this situation by checking processing_constraint_expression_p, so this patch uses this predicate to control whether we defer substitution or partially substitute. In turn, tsubst_requires_expr now needs to propagate semantic tsubst flags rather than just using tf_none, in particular for dguide constraint rewriting which sets tf_dguide. PR c++/112769 PR c++/110006 gcc/cp/ChangeLog: * constraint.cc (subst_info::quiet): Accomodate non-diagnostic tsubst flags. (tsubst_valid_expression_requirement): Likewise. (tsubst_simple_requirement): Likewise. Return a substituted _REQ node when processing_template_decl. (tsubst_type_requirement_1): Accomodate non-diagnostic tsubst flags. (tsubst_type_requirement): Return a substituted _REQ node when processing_template_decl. (tsubst_compound_requirement): Likewise. Accomodate non-diagnostic tsubst flags. (tsubst_nested_requirement): Likewise. (tsubst_requires_expr): Don't defer partial substitution when processing_constraint_expression_p is true, in which case return a substituted REQUIRES_EXPR. * pt.cc (tsubst_expr) : Accomodate non-diagnostic tsubst flags. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/class-deduction-alias18.C: New test. * g++.dg/cpp2a/concepts-friend16.C: New test. --- gcc/cp/constraint.cc | 56 +++++++++++++++---- gcc/cp/pt.cc | 3 +- .../g++.dg/cpp2a/class-deduction-alias18.C | 13 +++++ .../g++.dg/cpp2a/concepts-friend16.C | 25 +++++++++ 4 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias18.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-friend16.C diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index fef68cf7ab2..d9569013bd3 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -85,7 +85,7 @@ struct subst_info /* True if we should not diagnose errors. */ bool quiet() const { - return complain == tf_none; + return !(complain & tf_warning_or_error); } /* True if we should diagnose errors. */ @@ -1991,8 +1991,9 @@ hash_placeholder_constraint (tree c) static tree tsubst_valid_expression_requirement (tree t, tree args, sat_info info) { - tree r = tsubst_expr (t, args, tf_none, info.in_decl); - if (convert_to_void (r, ICV_STATEMENT, tf_none) != error_mark_node) + tsubst_flags_t quiet = info.complain & ~tf_warning_or_error; + tree r = tsubst_expr (t, args, quiet, info.in_decl); + if (convert_to_void (r, ICV_STATEMENT, quiet) != error_mark_node) return r; if (info.diagnose_unsatisfaction_p ()) @@ -2028,6 +2029,8 @@ tsubst_simple_requirement (tree t, tree args, sat_info info) tree expr = tsubst_valid_expression_requirement (t0, args, info); if (expr == error_mark_node) return error_mark_node; + if (processing_template_decl) + return finish_simple_requirement (EXPR_LOCATION (t), expr); return boolean_true_node; } @@ -2037,7 +2040,8 @@ tsubst_simple_requirement (tree t, tree args, sat_info info) static tree tsubst_type_requirement_1 (tree t, tree args, sat_info info, location_t loc) { - tree r = tsubst (t, args, tf_none, info.in_decl); + tsubst_flags_t quiet = info.complain & ~tf_warning_or_error; + tree r = tsubst (t, args, quiet, info.in_decl); if (r != error_mark_node) return r; @@ -2068,6 +2072,8 @@ tsubst_type_requirement (tree t, tree args, sat_info info) tree type = tsubst_type_requirement_1 (t0, args, info, EXPR_LOCATION (t)); if (type == error_mark_node) return error_mark_node; + if (processing_template_decl) + return finish_type_requirement (EXPR_LOCATION (t), type); return boolean_true_node; } @@ -2124,9 +2130,11 @@ tsubst_compound_requirement (tree t, tree args, sat_info info) location_t loc = cp_expr_loc_or_input_loc (expr); + subst_info quiet (info.complain & ~tf_warning_or_error, info.in_decl); + /* Check the noexcept condition. */ bool noexcept_p = COMPOUND_REQ_NOEXCEPT_P (t); - if (noexcept_p && !expr_noexcept_p (expr, tf_none)) + if (noexcept_p && !expr_noexcept_p (expr, quiet.complain)) { if (info.diagnose_unsatisfaction_p ()) inform (loc, "%qE is not %", expr); @@ -2139,8 +2147,6 @@ tsubst_compound_requirement (tree t, tree args, sat_info info) if (type == error_mark_node) return error_mark_node; - subst_info quiet (tf_none, info.in_decl); - /* Check expression against the result type. */ if (type) { @@ -2182,6 +2188,9 @@ tsubst_compound_requirement (tree t, tree args, sat_info info) } } + if (processing_template_decl) + return finish_compound_requirement (EXPR_LOCATION (t), + expr, type, noexcept_p); return boolean_true_node; } @@ -2190,7 +2199,16 @@ tsubst_compound_requirement (tree t, tree args, sat_info info) static tree tsubst_nested_requirement (tree t, tree args, sat_info info) { - sat_info quiet (tf_none, info.in_decl); + if (processing_template_decl) + { + tree req = TREE_OPERAND (t, 0); + req = tsubst_constraint (req, args, info.complain, info.in_decl); + if (req == error_mark_node) + return error_mark_node; + return finish_nested_requirement (EXPR_LOCATION (t), req); + } + + sat_info quiet (info.complain & ~tf_warning_or_error, info.in_decl); tree result = constraint_satisfaction_value (t, args, quiet); if (result == boolean_true_node) return boolean_true_node; @@ -2330,18 +2348,25 @@ tsubst_requires_expr (tree t, tree args, sat_info info) args = add_extra_args (REQUIRES_EXPR_EXTRA_ARGS (t), args, info.complain, info.in_decl); - if (processing_template_decl) + if (processing_template_decl + && !processing_constraint_expression_p ()) { /* We're partially instantiating a generic lambda. Substituting into this requires-expression now may cause its requirements to get checked out of order, so instead just remember the template - arguments and wait until we can substitute them all at once. */ + arguments and wait until we can substitute them all at once. + + Except if this requires-expr is part of associated constraints + that we're substituting into directly (for e.g. declaration + matching or dguide constraint rewriting), in which case we need + to partially substitute. */ t = copy_node (t); REQUIRES_EXPR_EXTRA_ARGS (t) = build_extra_args (t, args, info.complain); return t; } - if (tree parms = REQUIRES_EXPR_PARMS (t)) + tree parms = REQUIRES_EXPR_PARMS (t); + if (parms) { parms = tsubst_constraint_variables (parms, args, info); if (parms == error_mark_node) @@ -2349,10 +2374,13 @@ tsubst_requires_expr (tree t, tree args, sat_info info) } tree result = boolean_true_node; + if (processing_template_decl) + result = NULL_TREE; for (tree reqs = REQUIRES_EXPR_REQS (t); reqs; reqs = TREE_CHAIN (reqs)) { tree req = TREE_VALUE (reqs); - if (tsubst_requirement (req, args, info) == error_mark_node) + req = tsubst_requirement (req, args, info); + if (req == error_mark_node) { result = boolean_false_node; if (info.diagnose_unsatisfaction_p ()) @@ -2360,7 +2388,11 @@ tsubst_requires_expr (tree t, tree args, sat_info info) else break; } + else if (processing_template_decl) + result = tree_cons (NULL_TREE, req, result); } + if (processing_template_decl && result != boolean_false_node) + result = finish_requires_expr (EXPR_LOCATION (t), parms, nreverse (result)); return result; } diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 9d30a271713..7dcdb5aaf7d 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -21705,7 +21705,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) case REQUIRES_EXPR: { - tree r = tsubst_requires_expr (t, args, tf_none, in_decl); + complain &= ~tf_warning_or_error; + tree r = tsubst_requires_expr (t, args, complain, in_decl); RETURN (r); } diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias18.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias18.C new file mode 100644 index 00000000000..0bb11bb944c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias18.C @@ -0,0 +1,13 @@ +// PR c++/112769 +// { dg-do compile { target c++20 } } + +template +struct type +{ + type(T) requires requires { T{0}; }; +}; + +template +using alias = type<0, T>; + +alias foo{123}; diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-friend16.C b/gcc/testsuite/g++.dg/cpp2a/concepts-friend16.C new file mode 100644 index 00000000000..18974eeb172 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-friend16.C @@ -0,0 +1,25 @@ +// PR c++/110006 +// { dg-do compile { target c++20 } } + +template +class s; + +template +void constraint(s const&, int&); + +template +U function(s const x) + requires requires (U& u) { constraint(x, u); }; + +template +class s +{ + template + friend U function(s const x) + requires requires (U& u) { constraint(x, u); }; +}; + +int f(s q) +{ + return function(q); // { dg-bogus "ambiguous" } +} -- 2.43.0.493.gbc7ee2e5e1