From patchwork Thu Jul 29 14:21:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 1511306 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=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@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=rIc8qmDi; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (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 4GbCSC3RRWz9sRK for ; Fri, 30 Jul 2021 00:23:21 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 55C0539B2845 for ; Thu, 29 Jul 2021 14:23:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 55C0539B2845 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1627568599; bh=dzHfwgUCdoa0RPeSPW9w0h82EWWOclOLS/I8ZylLSNA=; h=Date:To:Subject:References:In-Reply-To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=rIc8qmDiQzbYolf87EHHpYN50AM9HKCOrsUnvptcSXF2ebtrkBQZQPhvLfvJowl/O zZpoTOT/yVurG7QWH+2cx8H83msOuOg/wS8DR/N92RL2RA/oea9sys2yUgsf2JVRBj gcSP9vCBP4zFE6CQmytD8cbmNwEwiOrhSUB+JIbI= 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 [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 7D2C339B206E for ; Thu, 29 Jul 2021 14:21:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 7D2C339B206E 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-184-8ZTqzWyVPzil8Fe2tUdPYg-1; Thu, 29 Jul 2021 10:21:54 -0400 X-MC-Unique: 8ZTqzWyVPzil8Fe2tUdPYg-1 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 0822610D1BC7 for ; Thu, 29 Jul 2021 14:21:54 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-112-143.ams2.redhat.com [10.36.112.143]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 97BAC19630; Thu, 29 Jul 2021 14:21:53 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.16.1/8.16.1) with ESMTPS id 16TELoiR2498490 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Thu, 29 Jul 2021 16:21:51 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.16.1/8.16.1/Submit) id 16TELoNg2498489; Thu, 29 Jul 2021 16:21:50 +0200 Date: Thu, 29 Jul 2021 16:21:49 +0200 To: Jason Merrill , Jonathan Wakely Subject: [PATCH] c++: __builtin_is_pointer_interconvertible_with_class incremental fix [PR101539] Message-ID: <20210729142149.GA2380545@tucnak> References: <20210729075010.GX2380545@tucnak> MIME-Version: 1.0 In-Reply-To: <20210729075010.GX2380545@tucnak> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-6.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: Jakub Jelinek via Gcc-patches From: Jakub Jelinek Reply-To: Jakub Jelinek Cc: gcc-patches@gcc.gnu.org Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" On Thu, Jul 29, 2021 at 09:50:10AM +0200, Jakub Jelinek via Gcc-patches wrote: > Now that I'm writing the above text and rereading the > pointer-interconvertibility definition, I think my first_nonstatic_data_member_p > and fold_builtin_is_pointer_inverconvertible_with_class have one bug, > for unions the pointer inter-convertibility doesn't talk about std layout at > all, so I think I need to check for std_layout_type_p only for non-union > class types and accept any union, std_layout_type_p or not. But when > recursing from a union type into anonymous structure type punt if the > anonymous structure type is not std_layout_type_p + add testcase coverage. For this part, here is an incremental fix. Tested on x86_64-linux. It also shows that in the case (we're beyond the standard in this case because anonymous structures are not in the standard) of union with non-std-layout anonymous structure in it, in the case in the testcases like: struct D {}; struct E { [[no_unique_address]] D e; }; union Y { int a; struct : public E { short b; long c; }; long long d; }; the builtin will return false for &Y::b - while &Y::b is at offset zero, the anonymous structure is not std-layout and therefore the pointer-interconvertibility rules say pointers aren't interconvertible. But in case like: union Y2 { int a; struct : public E { int b; long c; }; long long d; }; it will return true for &Y2::b - while the same applies, there is another union member with int type. In theory when seeing the PTRMEM_CST we could still differentiate, &Y2::a is ok but &Y2::b is not. But as soon as we have just an INTEGER_CST with OFFSET_TYPE or need to check it at runtime, all we know is that we have pointer to int data member in Y2 at offset 0, and that is the same for &Y2::a and &Y2::b. 2021-07-29 Jakub Jelinek PR c++/101539 * semantics.c (first_nonstatic_data_member_p): Don't recurse into non-std-layout non-union class types from union type. (fold_builtin_is_pointer_inverconvertible_with_class): Don't check std-layout type for union types. * g++.dg/cpp2a/is-pointer-interconvertible-with-class1.C: Add tests for non-std-layout union type. * g++.dg/cpp2a/is-pointer-interconvertible-with-class2.C: Likewise. * g++.dg/cpp2a/is-pointer-interconvertible-with-class4.C: Add tests for non-std-layout anonymous class type in union. * g++.dg/cpp2a/is-pointer-interconvertible-with-class5.C: Likewise. Jakub --- gcc/cp/semantics.c.jj 2021-07-28 23:06:38.665443459 +0200 +++ gcc/cp/semantics.c 2021-07-29 15:44:30.659713391 +0200 @@ -10631,7 +10631,9 @@ first_nonstatic_data_member_p (tree type if (TREE_CODE (type) != UNION_TYPE) return first_nonstatic_data_member_p (TREE_TYPE (field), membertype); - if (first_nonstatic_data_member_p (TREE_TYPE (field), membertype)) + if ((TREE_CODE (TREE_TYPE (field)) == UNION_TYPE + || std_layout_type_p (TREE_TYPE (field))) + && first_nonstatic_data_member_p (TREE_TYPE (field), membertype)) return true; } else if (TREE_CODE (type) != UNION_TYPE) @@ -10677,7 +10679,8 @@ fold_builtin_is_pointer_inverconvertible if (!complete_type_or_else (basetype, NULL_TREE)) return boolean_false_node; - if (!std_layout_type_p (basetype)) + if (TREE_CODE (basetype) != UNION_TYPE + && !std_layout_type_p (basetype)) return boolean_false_node; if (!first_nonstatic_data_member_p (basetype, membertype)) --- gcc/testsuite/g++.dg/cpp2a/is-pointer-interconvertible-with-class1.C.jj 2021-07-28 23:06:38.667443431 +0200 +++ gcc/testsuite/g++.dg/cpp2a/is-pointer-interconvertible-with-class1.C 2021-07-29 15:46:55.809743808 +0200 @@ -28,6 +28,7 @@ union U { int a; double b; long long c; struct V { union { int a; long b; }; int c; }; union X { int a; union { short b; long c; }; long long d; }; struct Y { void foo () {} }; +union Z { int a; private: int b; protected: int c; public: int d; }; static_assert (std::is_pointer_interconvertible_with_class (&B::b)); static_assert (!std::is_pointer_interconvertible_with_class (&B::b2)); @@ -60,3 +61,5 @@ static_assert (std::is_pointer_interconv static_assert (std::is_pointer_interconvertible_with_class (&X::d)); static_assert (!std::is_pointer_interconvertible_with_class ((int B::*) nullptr)); static_assert (!std::is_pointer_interconvertible_with_class (&Y::foo)); +static_assert (std::is_pointer_interconvertible_with_class (&Z::a)); +static_assert (std::is_pointer_interconvertible_with_class (&Z::d)); --- gcc/testsuite/g++.dg/cpp2a/is-pointer-interconvertible-with-class2.C.jj 2021-07-28 23:06:38.667443431 +0200 +++ gcc/testsuite/g++.dg/cpp2a/is-pointer-interconvertible-with-class2.C 2021-07-29 15:48:33.075423974 +0200 @@ -28,6 +28,7 @@ union U { int a; double b; long long c; struct V { union { int a; long b; }; int c; }; union X { int a; union { short b; long c; }; long long d; }; struct Y { void foo () {} }; +union Z { int a; private: int b; protected: int c; public: int d; }; int main () @@ -125,4 +126,10 @@ main () auto t31 = &Y::foo; if (std::is_pointer_interconvertible_with_class (t31)) __builtin_abort (); + auto t32 = &Z::a; + if (!std::is_pointer_interconvertible_with_class (t32)) + __builtin_abort (); + auto t33 = &Z::d; + if (!std::is_pointer_interconvertible_with_class (t33)) + __builtin_abort (); } --- gcc/testsuite/g++.dg/cpp2a/is-pointer-interconvertible-with-class4.C.jj 2021-07-28 23:06:38.667443431 +0200 +++ gcc/testsuite/g++.dg/cpp2a/is-pointer-interconvertible-with-class4.C 2021-07-29 15:56:54.340622140 +0200 @@ -14,6 +14,9 @@ is_pointer_interconvertible_with_class ( struct W { struct { int a; long b; }; int c; }; union X { int a; struct { short b; long c; }; long long d; }; +struct D {}; +struct E { [[no_unique_address]] D e; }; +union Y { int a; struct : public E { short b; long c; }; long long d; }; static_assert (std::is_pointer_interconvertible_with_class (&W::a)); static_assert (!std::is_pointer_interconvertible_with_class (&W::b)); @@ -22,3 +25,7 @@ static_assert (std::is_pointer_interconv static_assert (std::is_pointer_interconvertible_with_class (&X::b)); static_assert (!std::is_pointer_interconvertible_with_class (&X::c)); static_assert (std::is_pointer_interconvertible_with_class (&X::d)); +static_assert (std::is_pointer_interconvertible_with_class (&Y::a)); +static_assert (!std::is_pointer_interconvertible_with_class (&Y::b)); +static_assert (!std::is_pointer_interconvertible_with_class (&Y::c)); +static_assert (std::is_pointer_interconvertible_with_class (&Y::d)); --- gcc/testsuite/g++.dg/cpp2a/is-pointer-interconvertible-with-class5.C.jj 2021-07-28 23:06:38.667443431 +0200 +++ gcc/testsuite/g++.dg/cpp2a/is-pointer-interconvertible-with-class5.C 2021-07-29 15:57:10.829398399 +0200 @@ -14,6 +14,9 @@ is_pointer_interconvertible_with_class ( struct W { struct { int a; long b; }; int c; }; union X { int a; struct { short b; long c; }; long long d; }; +struct D {}; +struct E { [[no_unique_address]] D e; }; +union Y { int a; struct : public E { short b; long c; }; long long d; }; int main () @@ -39,4 +42,16 @@ main () auto t7 = &X::d; if (!std::is_pointer_interconvertible_with_class (t7)) __builtin_abort (); + auto t8 = &Y::a; + if (!std::is_pointer_interconvertible_with_class (t8)) + __builtin_abort (); + auto t9 = &Y::b; + if (std::is_pointer_interconvertible_with_class (t9)) + __builtin_abort (); + auto t10 = &Y::c; + if (std::is_pointer_interconvertible_with_class (t10)) + __builtin_abort (); + auto t11 = &Y::d; + if (!std::is_pointer_interconvertible_with_class (t11)) + __builtin_abort (); }