From patchwork Wed Jun 19 13:54:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 1949701 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=BCZR9HHy; 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 4W44r73yCHz20Wb for ; Wed, 19 Jun 2024 23:55:03 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id AAA963885C24 for ; Wed, 19 Jun 2024 13:55:00 +0000 (GMT) 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.129.124]) by sourceware.org (Postfix) with ESMTPS id 0B67E388456D for ; Wed, 19 Jun 2024 13:54:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0B67E388456D 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 0B67E388456D Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1718805276; cv=none; b=o+l+7T9ZucBARZAL48I/PsGBfafwpNMoGo/mHeetnhfirYmVoUEUi7UdZbbaYmVDNVsL1hrr+Fnufeh1l1tV8G2jcSPceBVlkCtgTTNqZUFz2SkcfbEsBfU7XaRGyZ6prIXn6RvIFp34l4D/KNgxgBxJGuByIAe8ga1Fcf7191A= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1718805276; c=relaxed/simple; bh=3cUyiTAWSFgcUzjj+CDzodgMRgnAv9csMSgwl8X4oSc=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=hmdBA0rkRF3TIVDFWVHtoRSD5LNVgPL2bLnknoVHdrZifgqc72wZ1qRZ/D4GORGCe6LTR4bn2/r59TJIDierzgAjtCgvjuNBW/cdKVwKWUn0wPHRrgJFXj7PLmsmXQu6q+vOdgo177AaBarKAmcm3XwPP9Z6eqLUv+lCfQqeklE= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1718805273; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=LZBrTS3/oSz2sB8axy2m9DZfNZHGLeksj5KmqX5rF7s=; b=BCZR9HHyyDdtNEuEvi4oQwVBXcXPv8fjc4wY4Wzg9LSyg75OyyUMoFDBabSnHopYgy8bVs bQPujf90+kd2iQ1MwmxbeHztM/tdT77GcePassEg8K3yM7CUHwOL++wsbBP3UBdFbG/VNY ers2XHTnFhO6A93pn+MQmLR7SVGPJZw= Received: from mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-557-L2i1lJT5N7ecRaaK3amuGw-1; Wed, 19 Jun 2024 09:54:31 -0400 X-MC-Unique: L2i1lJT5N7ecRaaK3amuGw-1 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0ACB91956095 for ; Wed, 19 Jun 2024 13:54:30 +0000 (UTC) Received: from pdp-11.lan (unknown [10.22.8.207]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3A6C31956052; Wed, 19 Jun 2024 13:54:29 +0000 (UTC) From: Marek Polacek To: Jason Merrill , GCC Patches Subject: [PATCH] c++: implement DR1363 and DR1496 for __is_trivial [PR85723] Date: Wed, 19 Jun 2024 09:54:23 -0400 Message-ID: <20240619135423.18890-1-polacek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.9 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_H4, RCVD_IN_MSPIKE_WL, RCVD_IN_SBL_CSS, 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 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 Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? -- >8 -- is_trivial was introduced in which split POD into is_trivial and is_standard_layout. Later came CWG 1363. Since struct A { A() = default; A(int = 42) {} }; cannot be default-initialized, it should not be trivial, so the definition of what is a trivial class changed. Similarly, CWG 1496 concluded that struct B { B() = delete; }: should not be trivial either. P0848 adjusted the definition further to say "eligible". That means that template struct C { C() requires false = default; }; should not be trivial, either, since C::C() is not eligible. Bug 85723 reports that we implement none of the CWGs. I chose to fix this by using type_has_non_deleted_trivial_default_ctor which uses locate_ctor which uses build_new_method_call, which would be used by default-initialization as well. With that, all __is_trivial problems I could find in the Bugzilla are fixed, except for PR96288, which may need changes to trivially-copyable, so I'm not messing with that now. I hope this has no ABI implications. There's effort undergoing to remove "trivial class" from the core language as it's not really meaningful. So the impact of this change should be pretty low except to fix a few libstdc++ problems. PR c++/108769 PR c++/58074 PR c++/115522 PR c++/85723 gcc/cp/ChangeLog: * class.cc (type_has_non_deleted_trivial_default_ctor): Fix formatting. * tree.cc (trivial_type_p): Instead of TYPE_HAS_TRIVIAL_DFLT, use type_has_non_deleted_trivial_default_ctor. gcc/testsuite/ChangeLog: * g++.dg/warn/Wclass-memaccess.C: Add dg-warning. * g++.dg/ext/is_trivial1.C: New test. * g++.dg/ext/is_trivial2.C: New test. * g++.dg/ext/is_trivial3.C: New test. * g++.dg/ext/is_trivial4.C: New test. * g++.dg/ext/is_trivial5.C: New test. * g++.dg/ext/is_trivial6.C: New test. --- gcc/cp/class.cc | 3 +- gcc/cp/tree.cc | 4 +- gcc/testsuite/g++.dg/ext/is_trivial1.C | 14 ++++++ gcc/testsuite/g++.dg/ext/is_trivial2.C | 17 +++++++ gcc/testsuite/g++.dg/ext/is_trivial3.C | 15 ++++++ gcc/testsuite/g++.dg/ext/is_trivial4.C | 10 ++++ gcc/testsuite/g++.dg/ext/is_trivial5.C | 8 ++++ gcc/testsuite/g++.dg/ext/is_trivial6.C | 49 ++++++++++++++++++++ gcc/testsuite/g++.dg/warn/Wclass-memaccess.C | 2 + 9 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial1.C create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial2.C create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial3.C create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial4.C create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial5.C create mode 100644 gcc/testsuite/g++.dg/ext/is_trivial6.C base-commit: be18486825dd24533d320bf840bf95bd083487d1 diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index 0ce361eb88e..718601756dd 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -5918,7 +5918,8 @@ type_has_virtual_destructor (tree type) /* True iff class TYPE has a non-deleted trivial default constructor. */ -bool type_has_non_deleted_trivial_default_ctor (tree type) +bool +type_has_non_deleted_trivial_default_ctor (tree type) { return TYPE_HAS_TRIVIAL_DFLT (type) && locate_ctor (type); } diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index 28648c14c6d..5b837f89e03 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -4637,7 +4637,9 @@ trivial_type_p (const_tree t) t = strip_array_types (CONST_CAST_TREE (t)); if (CLASS_TYPE_P (t)) - return (TYPE_HAS_TRIVIAL_DFLT (t) + /* A trivial class is a class that is trivially copyable and has one or + more eligible default constructors, all of which are trivial. */ + return (type_has_non_deleted_trivial_default_ctor (CONST_CAST_TREE (t)) && trivially_copyable_p (t)); else return scalarish_type_p (t); diff --git a/gcc/testsuite/g++.dg/ext/is_trivial1.C b/gcc/testsuite/g++.dg/ext/is_trivial1.C new file mode 100644 index 00000000000..60ce48edfe9 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivial1.C @@ -0,0 +1,14 @@ +// PR c++/108769 +// { dg-do compile { target c++20 } } + +template +struct S { + S() requires false = default; +}; +static_assert(!__is_trivial(S)); + +template +struct R { + R() requires true = default; +}; +static_assert(__is_trivial(R)); diff --git a/gcc/testsuite/g++.dg/ext/is_trivial2.C b/gcc/testsuite/g++.dg/ext/is_trivial2.C new file mode 100644 index 00000000000..8a8e554580c --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivial2.C @@ -0,0 +1,17 @@ +// PR c++/58074 +// { dg-do compile { target c++11 } } + +struct Trivial +{ + Trivial() = delete; +}; + +struct NonTrivial +{ + NonTrivial() = default; + NonTrivial(NonTrivial&) = default; + NonTrivial& operator=(NonTrivial&) = default; +}; + +static_assert(!__is_trivial(Trivial), "Ouch"); +static_assert(__is_trivial(NonTrivial), "Ouch"); diff --git a/gcc/testsuite/g++.dg/ext/is_trivial3.C b/gcc/testsuite/g++.dg/ext/is_trivial3.C new file mode 100644 index 00000000000..9704a9468d5 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivial3.C @@ -0,0 +1,15 @@ +// PR c++/115522 +// { dg-do compile { target c++11 } } + +// Not default constructible. +struct S { + const int i; +}; + +static_assert(!__is_trivial(S), ""); + +struct R { + int &r; +}; + +static_assert(!__is_trivial(R), ""); diff --git a/gcc/testsuite/g++.dg/ext/is_trivial4.C b/gcc/testsuite/g++.dg/ext/is_trivial4.C new file mode 100644 index 00000000000..c26e784b76c --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivial4.C @@ -0,0 +1,10 @@ +// CWG 1363 +// PR c++/85723 +// { dg-do compile { target c++11 } } + +struct A { + A() = default; + A(int i = 0) { } +}; + +static_assert(!__is_trivial(A), ""); diff --git a/gcc/testsuite/g++.dg/ext/is_trivial5.C b/gcc/testsuite/g++.dg/ext/is_trivial5.C new file mode 100644 index 00000000000..5c89e1da6e8 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivial5.C @@ -0,0 +1,8 @@ +// CWG 1496 +// PR c++/85723 +// { dg-do compile { target c++11 } } + +struct NonTrivial { + NonTrivial() = delete; +}; +static_assert(!__is_trivial (NonTrivial), "NonTrivial is trivial"); diff --git a/gcc/testsuite/g++.dg/ext/is_trivial6.C b/gcc/testsuite/g++.dg/ext/is_trivial6.C new file mode 100644 index 00000000000..a3a688c5938 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_trivial6.C @@ -0,0 +1,49 @@ +// PR c++/85723 +// { dg-do compile { target c++20 } } + +template +struct A { + A() = delete; + A() requires(sizeof(T) == 1) = default; + A() requires(sizeof(T) != 1) = delete; +}; +static_assert(!__is_trivial(A)); +static_assert(__is_trivial(A)); + +template +struct B { + B() = default; + B() requires(sizeof(T) == 1) = default; + B() requires(sizeof(T) != 1) = delete; +}; +static_assert(__is_trivial(B)); +static_assert(__is_trivial(B)); + +template +struct C { + C() = default; + C() requires(sizeof(T) == 1) = delete; + C() requires(sizeof(T) != 1) = default; +}; +static_assert(__is_trivial(C)); +static_assert(__is_trivial(C)); + +template +struct D { + D() = default; + D(int = 42) {} + D() requires(sizeof(T) == 1) = delete; + D() requires(sizeof(T) != 1) = default; +}; +static_assert(!__is_trivial(D)); +static_assert(!__is_trivial(D)); + + +template +struct E { + E() = delete; + E() requires(sizeof(T) == 1) = default; + E() requires(sizeof(T) != 1) = delete; +}; +static_assert(!__is_trivial(E)); +static_assert(__is_trivial(E)); diff --git a/gcc/testsuite/g++.dg/warn/Wclass-memaccess.C b/gcc/testsuite/g++.dg/warn/Wclass-memaccess.C index 87aaa79ceca..636a6e6e1b8 100644 --- a/gcc/testsuite/g++.dg/warn/Wclass-memaccess.C +++ b/gcc/testsuite/g++.dg/warn/Wclass-memaccess.C @@ -1254,6 +1254,7 @@ void test (HasConstData *p, const HasConstData &x, // Reallocating is not diagnosed except in C++ 98 due to a bug. T (q = realloc, (p, 1)); // { dg-warning "moving an object of non-trivially copyable type .struct HasConstData.; use .new. and .delete. instead" "c++98" { target { c++98_only } } } +// { dg-warning "moving an object of non-trivial type" "" { target c++11 } .-1 } T (q = realloc, (p, n)); // { dg-warning "realloc" "c++98" { target { c++98_only } } } T (q = realloc, (p, sizeof *p)); // { dg-warning "realloc" "c++98" { target { c++98_only } } } } @@ -1333,6 +1334,7 @@ void test (HasReference *p, const HasReference &x, // in C++ 98 because of a bug, but it seems like it should be // diagnosed in all modes. T (q = realloc, (p, 1)); // { dg-warning "realloc" "c++ 98" { target { c++98_only } } } +// { dg-warning "moving an object of non-trivial type" "" { target c++11 } .-1 } T (q = realloc, (p, n)); // { dg-warning "realloc" "c++ 98" { target { c++98_only } } } T (q = realloc, (p, sizeof *p)); // { dg-warning "realloc" "c++ 98" { target { c++98_only } } } }