From patchwork Thu Mar 4 23:19:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 1447586 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=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=Fn8Itaqt; dkim-atps=neutral Received: from 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 RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Ds6JZ12fHz9sVt for ; Fri, 5 Mar 2021 10:19:24 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 58947385803F; Thu, 4 Mar 2021 23:19:22 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 58947385803F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1614899962; bh=rI+sIPTJN/4hd22bsn6k5m8TYrO/lPKWyoWmK6f7UZM=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=Fn8ItaqtSs+OLNFF0E5OgeQQ5I0w7MeTOGeLnK3yUKFeuOEvzf46pJkhG54LaNVQV f8zhMD0oC/tSiCQoxYjAJbAIueBY+SITAEFUpHxBz5iOvls8B/47PhxwuZIWLO/jJu c0HNt+6orCA0NwPmpKT/fBMWDR74zpvtg4mY9mqQ= 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 [63.128.21.124]) by sourceware.org (Postfix) with ESMTP id 672F23858024 for ; Thu, 4 Mar 2021 23:19:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 672F23858024 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-276-Y3aPBrRhMo-dWZ_GnV4meA-1; Thu, 04 Mar 2021 18:19:17 -0500 X-MC-Unique: Y3aPBrRhMo-dWZ_GnV4meA-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 8DB5A57 for ; Thu, 4 Mar 2021 23:19:16 +0000 (UTC) Received: from pdp-11.hsd1.ma.comcast.net (ovpn-113-194.rdu2.redhat.com [10.10.113.194]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2D3A85D9C6; Thu, 4 Mar 2021 23:19:16 +0000 (UTC) To: Jason Merrill , GCC Patches Subject: [PATCH] c++: Pointer-to-member fn conversion with noexcept [PR99374] Date: Thu, 4 Mar 2021 18:19:14 -0500 Message-Id: <20210304231914.1202675-1-polacek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-14.5 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_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Marek Polacek via Gcc-patches From: Marek Polacek Reply-To: Marek Polacek Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" The issue in this PR is that we wrongly reject converting pointers to member function of incomplete types, one of which has noexcept. Recall that pointers (including pointers to member functions) to non-throwing functions can be implicitly converted to potentially-throwing functions (but not vice versa). We reject the conversion when called from can_convert_arg_bad because standard_conversion can't create such a conversion. It comes down to the DERIVED_FROM_P check in the TYPE_PTRMEMFUNC_P block. It considers every class derived from itself, but not when the class is incomplete. But surely we want to reach fnptr_conv_p when tbase is fbase (one of them could be an alias to the other so use same_type_p instead of ==). Another approach would be to not perform DERIVED_FROM_P at all when either tbase or fbase are incomplete (so perhaps something like at the end of ptr_reasonably_similar). Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/10? gcc/cp/ChangeLog: PR c++/99374 * call.c (standard_conversion): When converting pointers to member, don't return NULL when the bases are equivalent but incomplete. gcc/testsuite/ChangeLog: PR c++/99374 * g++.dg/cpp1z/noexcept-type23.C: New test. --- gcc/cp/call.c | 4 +++- gcc/testsuite/g++.dg/cpp1z/noexcept-type23.C | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/noexcept-type23.C base-commit: 0d737ed2171165ba39ab5647f8a94c588fc9a898 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 123f06b1f2b..605cbe15f4e 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -1449,7 +1449,9 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, tree fbase = class_of_this_parm (fromfn); tree tbase = class_of_this_parm (tofn); - if (!DERIVED_FROM_P (fbase, tbase)) + /* If FBASE and TBASE are equivalent but incomplete, DERIVED_FROM_P + yields false. But a pointer to member of incomplete class is OK. */ + if (!DERIVED_FROM_P (fbase, tbase) && !same_type_p (fbase, tbase)) return NULL; tree fstat = static_fn_type (fromfn); diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type23.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type23.C new file mode 100644 index 00000000000..612dd6ceb5e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type23.C @@ -0,0 +1,14 @@ +// PR c++/99374 +// { dg-do compile { target c++17 } } + +struct S; +struct R; +using F1 = int (S::*)(); +using F2 = int (S::*)() noexcept; +using F3 = int (R::*)() noexcept; +using T = S; +using F4 = int (T::*)() noexcept; +F1 f21 = F2(); +F1 f41 = F4(); +F2 f12 = F1(); // { dg-error "cannot convert" } +F1 f31 = F3(); // { dg-error "cannot convert" }