From patchwork Sat Jan 25 06:08:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 1229172 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-518250-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha1 header.s=default header.b=xDfxgC5D; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=P8yPDU7J; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 484QZK3Xwdz9sRf for ; Sat, 25 Jan 2020 17:09:10 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:content-type :content-transfer-encoding; q=dns; s=default; b=KiLxXVg1x999+C6p bQsMNJYLauo50eHdJelDeb2BEbSe9pgidbUXBBA8MFfzHIAxRP8B2NR9/ZCzqJFy 9baLpOHxieslQs+Ufs5BluiE6LSnoH4KmckI4Cb6k4ABIXVeYaj3f6N3BirFoXmv HedCj4YL+pK3O4C4ku3l6v/Jz/o= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:content-type :content-transfer-encoding; s=default; bh=sjpKwOTq2hu1mtsgq33HMU /wuA8=; b=xDfxgC5DrTzu6JplCF5/KKYXPycsm6AV6GXPJz3znH8uy7CLFBoOPV RKwJy72nkVXknhx/PY2bDuBZlRVlNh+FdgwDUKQIgAFvPAxDza+jO5+i/htnbx0L Bykpdj91IZOUldAQ973wrEFZF2QZoVnvS7oww9R7HL6WVXBFx5oIw= Received: (qmail 1916 invoked by alias); 25 Jan 2020 06:09:02 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 1908 invoked by uid 89); 25 Jan 2020 06:09:02 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-19.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 spammy=fell X-HELO: us-smtp-delivery-1.mimecast.com Received: from us-smtp-1.mimecast.com (HELO us-smtp-delivery-1.mimecast.com) (207.211.31.81) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 25 Jan 2020 06:09:00 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1579932538; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=eZ/y4HcUZS8axC7SkfLvDnWDlcyWBJbVE/K6puIsGcQ=; b=P8yPDU7JmZtdPGPizoWoFkFUetBfs8OEVYxiUMPduXvLm0rn6Y1I+Zzv95ZnrH8gchoyl2 8ttVjmdUDjfLDJAN1K5dJDpQETSC81zOtX/BfILokPL2EwtBeq3Dxj5G/FmOBR3LAP31x6 dSsaG/7+W7AOZpPXJnl91IsHbNeCooM= Received: from mail-qv1-f70.google.com (mail-qv1-f70.google.com [209.85.219.70]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-259-vmuKg7PkPraGmNrHoayxBA-1; Sat, 25 Jan 2020 01:08:56 -0500 Received: by mail-qv1-f70.google.com with SMTP id d10so2625837qvb.3 for ; Fri, 24 Jan 2020 22:08:56 -0800 (PST) Received: from barrymore.redhat.com (209-6-216-142.s141.c3-0.smr-cbr1.sbo-smr.ma.cable.rcncustomer.com. [209.6.216.142]) by smtp.gmail.com with ESMTPSA id n32sm5002671qtk.66.2020.01.24.22.08.54 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 24 Jan 2020 22:08:54 -0800 (PST) From: Jason Merrill To: gcc-patches@gcc.gnu.org Subject: [COMMITTED] c++: Fix ICE with constrained friend (PR93400). Date: Sat, 25 Jan 2020 01:08:53 -0500 Message-Id: <20200125060853.9501-1-jason@redhat.com> X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-IsSubscribed: yes Here, the problem was that tsubst_friend_function was modifying the CONSTRAINT_INFO for the friend template to have the constraints for one instantiation, which fell down when we went to adjust it for another instantiation. Fixed by deferring substitution of trailing requirements until we try to check declaration matching. Tested x86_64-pc-linux-gnu, applying to trunk. PR c++/93400 - ICE with constrained friend. * constraint.cc (maybe_substitute_reqs_for): New. * decl.c (function_requirements_equivalent_p): Call it. * pt.c (tsubst_friend_function): Only substitute TEMPLATE_PARMS_CONSTRAINTS. (tsubst_template_parms): Copy constraints. --- gcc/cp/cp-tree.h | 1 + gcc/cp/constraint.cc | 23 ++++++++++++++ gcc/cp/decl.c | 2 ++ gcc/cp/pt.c | 31 +++++-------------- gcc/testsuite/g++.dg/cpp2a/concepts-friend3.C | 3 ++ gcc/testsuite/g++.dg/cpp2a/concepts-friend5.C | 8 +++++ gcc/testsuite/g++.dg/cpp2a/concepts-pr84140.C | 5 ++- 7 files changed, 47 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-friend5.C base-commit: 8b91e848130e45b427599ad30e99f96e447ea9aa diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 77bcf046608..b8035b4360d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7832,6 +7832,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 get_template_head_requirements (tree); extern tree get_trailing_function_requirements (tree); extern tree get_shorthand_constraints (tree); diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index 823604afb89..cda644eabe2 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -1189,6 +1189,29 @@ remove_constraints (tree t) decl_constraints->remove (t); } +/* If DECL is a friend, substitute into REQS to produce requirements suitable + for declaration matching. */ + +tree +maybe_substitute_reqs_for (tree reqs, const_tree decl_) +{ + if (reqs == NULL_TREE) + return NULL_TREE; + tree decl = CONST_CAST_TREE (decl_); + tree result = STRIP_TEMPLATE (decl); + if (DECL_FRIEND_P (result)) + { + tree tmpl = decl == result ? DECL_TI_TEMPLATE (result) : decl; + tree gargs = generic_targs_for (tmpl); + processing_template_decl_sentinel s; + if (uses_template_parms (gargs)) + ++processing_template_decl; + reqs = tsubst_constraint (reqs, gargs, + tf_warning_or_error, NULL_TREE); + } + return reqs; +} + /* Returns the template-head requires clause for the template declaration T or NULL_TREE if none. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 98ed79f3579..e55de5dd53d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -942,6 +942,8 @@ function_requirements_equivalent_p (tree newfn, tree oldfn) tree reqs2 = get_trailing_function_requirements (oldfn); if ((reqs1 != NULL_TREE) != (reqs2 != NULL_TREE)) return false; + reqs1 = maybe_substitute_reqs_for (reqs1, newfn); + reqs2 = maybe_substitute_reqs_for (reqs2, oldfn); return cp_tree_equal (reqs1, reqs2); } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 209044135cb..45c204e4269 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10834,29 +10834,12 @@ tsubst_friend_function (tree decl, tree args) DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (new_friend)) = DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (decl)); - /* Attach the template requirements to the new declaration - for declaration matching. We need to rebuild the requirements - so that parameter levels match. */ - if (tree ci = get_constraints (decl)) - { - tree parms = DECL_TEMPLATE_PARMS (new_friend); - tree args = generic_targs_for (new_friend); - tree treqs = tsubst_constraint (CI_TEMPLATE_REQS (ci), args, - tf_warning_or_error, NULL_TREE); - tree freqs = tsubst_constraint (CI_DECLARATOR_REQS (ci), args, - tf_warning_or_error, NULL_TREE); - - /* Update the constraints -- these won't really be valid for - checking, but that's not what we need them for. These ensure - that the declared function can find the friend during - declaration matching. */ - tree new_ci = get_constraints (new_friend); - CI_TEMPLATE_REQS (new_ci) = treqs; - CI_DECLARATOR_REQS (new_ci) = freqs; - - /* Also update the template parameter list. */ - TEMPLATE_PARMS_CONSTRAINTS (parms) = treqs; - } + /* Substitute TEMPLATE_PARMS_CONSTRAINTS so that parameter levels will + match in decls_match. */ + tree parms = DECL_TEMPLATE_PARMS (new_friend); + tree treqs = TEMPLATE_PARMS_CONSTRAINTS (parms); + treqs = maybe_substitute_reqs_for (treqs, new_friend); + TEMPLATE_PARMS_CONSTRAINTS (parms) = treqs; } /* The mangled name for the NEW_FRIEND is incorrect. The function @@ -13225,6 +13208,8 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain) tree_cons (size_int (TMPL_PARMS_DEPTH (parms) - TMPL_ARGS_DEPTH (args)), new_vec, NULL_TREE); + TEMPLATE_PARMS_CONSTRAINTS (*new_parms) + = TEMPLATE_PARMS_CONSTRAINTS (parms); } --processing_template_decl; diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-friend3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-friend3.C index 4f49358ed7d..4278278b9df 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-friend3.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-friend3.C @@ -4,6 +4,7 @@ template concept True = true; template struct B { int i = ++U::x; }; template void f() { ++U::x; } +template void g() requires True { ++U::x; } template class C { @@ -11,10 +12,12 @@ template class C template friend struct B; template friend void f(); + template friend void g() requires True; }; int main() { f>(); + g>(); B>(); } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-friend5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-friend5.C new file mode 100644 index 00000000000..394f141bf17 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-friend5.C @@ -0,0 +1,8 @@ +// PR c++/93400 +// { dg-do compile { target concepts } } + +template bool a = true; +template concept b = a; +template struct f { template friend auto g(c, f); }; +auto d = f<1>{}; +auto e = f<0>{}; diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84140.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84140.C index d901ab20cbf..83a9083cf17 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84140.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84140.C @@ -1,14 +1,13 @@ // { dg-do run { target c++2a } } -// { dg-additional-options "-fconcepts-ts" } template constexpr bool is_same_v = false; template constexpr bool is_same_v = true; template -concept bool Same = is_same_v; +concept Same = is_same_v; template -concept bool Diff = requires(T& t, U& u) { u - t; }; +concept Diff = requires(T& t, U& u) { u - t; }; template int distance(I, S) { return 0; }