From patchwork Fri Feb 11 18:55:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 51054 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C295C385802A for ; Fri, 11 Feb 2022 18:57:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org C295C385802A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1644605820; bh=qmXFD5r9A2uXTG0KHjf5xb2BakvNI404ymjZ3e/EDTA=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=R5YFu8+3I1uwHKITQw8aH3GCeeNNWYYjUxJSIcKs0CLqRUmRnX2ctEs2JCvbsONEN wlZfHfL+sRb/kz01dB75/ut97vo4iNCrIkv357+br49pkTrqtiDbGJ2bmwjKJgLGXj 3xZJyhUod1ScblcaV7jssk5EXv2Hn+mB33GIKrAY= 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 6F36E385842F for ; Fri, 11 Feb 2022 18:56:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 6F36E385842F Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-361-bRgVN4mhMkOFP3cDEngKbw-1; Fri, 11 Feb 2022 13:56:24 -0500 X-MC-Unique: bRgVN4mhMkOFP3cDEngKbw-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 38653100C661 for ; Fri, 11 Feb 2022 18:56:23 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.39.192.125]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C1F8C10E54FA; Fri, 11 Feb 2022 18:56:19 +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 21BItuwp2449933 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 11 Feb 2022 19:56:06 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.16.1/8.16.1/Submit) id 21BItoao2449932; Fri, 11 Feb 2022 19:55:50 +0100 Date: Fri, 11 Feb 2022 19:55:50 +0100 To: Jason Merrill Subject: [PATCH] c++: Reject __builtin_clear_padding on non-trivially-copyable types with one exception [PR102586] Message-ID: <20220211185550.GT2646553@tucnak> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-5.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, KAM_SHORT, RCVD_IN_DNSWL_LOW, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE 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+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Hi! As mentioned by Jason in the PR, non-trivially-copyable types (or non-POD for purposes of layout?) types can be base classes of derived classes in which the padding in those non-trivially-copyable types can be redused for some real data members or even the layout can change and data members can be moved to other positions. __builtin_clear_padding is right now used for multiple purposes, in where it isn't used yet but was planned as the main spot it can be used for trivially copyable types only, ditto for std::bit_cast where we also use it. It is used for OpenMP long double atomics too but long double is trivially copyable, and lastly for -ftrivial-auto-var-init=. The following patch restricts the builtin to pointers to trivially-copyable types, with the exception when it is called directly on an address of a variable, in that case already the FE can verify it is the complete object type and so it is safe to clear all the paddings in it. Bootstrapped/regtested on powerpc64le-linux, ok for trunk? Something like the https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102586#c16 will still be needed with adjusted testcase from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102586#c15 such that __builtin_clear_padding is called directly on var addresses rather than in separate functions. 2022-02-11 Jakub Jelinek PR tree-optimization/102586 gcc/ * doc/extend.texi (__builtin_clear_padding): Clearify that for C++ argument type should be pointer to trivially-copyable type unless it is address of a variable or parameter. gcc/cp/ * call.cc (build_cxx_call): Diagnose __builtin_clear_padding where first argument's type is pointer to non-trivially-copyable type unless it is address of a variable or parameter. gcc/testsuite/ * g++.dg/cpp2a/builtin-clear-padding1.C: New test. Jakub --- gcc/doc/extend.texi.jj 2022-02-09 15:16:03.336783697 +0100 +++ gcc/doc/extend.texi 2022-02-11 13:22:39.846157538 +0100 @@ -13993,6 +13993,11 @@ bits that are padding bits for all the u This built-in-function is useful if the padding bits of an object might have intederminate values and the object representation needs to be bitwise compared to some other object, for example for atomic operations. + +For C++, @var{ptr} argument type should be pointer to trivially-copyable +type, unless the argument is address of a variable or parameter, because +otherwise it isn't known if the type isn't just a base class whose padding +bits are reused or laid out differently in a derived class. @end deftypefn @deftypefn {Built-in Function} @var{type} __builtin_bit_cast (@var{type}, @var{arg}) --- gcc/cp/call.cc.jj 2022-02-09 20:13:51.523305107 +0100 +++ gcc/cp/call.cc 2022-02-11 12:58:19.168301395 +0100 @@ -10398,6 +10398,27 @@ build_cxx_call (tree fn, int nargs, tree if (!check_builtin_function_arguments (EXPR_LOCATION (fn), vNULL, fndecl, orig_fndecl, nargs, argarray)) return error_mark_node; + else if (fndecl_built_in_p (fndecl, BUILT_IN_CLEAR_PADDING)) + { + tree arg0 = argarray[0]; + STRIP_NOPS (arg0); + if (TREE_CODE (arg0) == ADDR_EXPR + && DECL_P (TREE_OPERAND (arg0, 0)) + && same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (TREE_TYPE (argarray[0])), + TREE_TYPE (TREE_TYPE (arg0)))) + /* For __builtin_clear_padding (&var) we know the type + is for a complete object, so there is no risk in clearing + padding that is reused in some derived class member. */; + else if (!trivially_copyable_p (TREE_TYPE (TREE_TYPE (argarray[0])))) + { + error_at (EXPR_LOC_OR_LOC (argarray[0], input_location), + "argument %u in call to function %qE " + "has pointer to a non-trivially-copyable type (%qT)", + 1, fndecl, TREE_TYPE (argarray[0])); + return error_mark_node; + } + } } if (VOID_TYPE_P (TREE_TYPE (fn))) --- gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C.jj 2022-02-11 13:13:49.125471991 +0100 +++ gcc/testsuite/g++.dg/cpp2a/builtin-clear-padding1.C 2022-02-11 13:13:43.403550851 +0100 @@ -0,0 +1,50 @@ +// PR tree-optimization/102586 +// { dg-do compile } +// { dg-options "-Wno-inaccessible-base" } + +struct C0 {}; +struct C1 {}; +struct C2 : C1, virtual C0 {}; +struct C3 : virtual C2, C1 {}; +struct C4 : virtual C3, C1 {}; +struct C5 : C4 {}; +struct C6 { char c; }; +struct C7 : virtual C6, virtual C3, C1 {}; +struct C8 : C7 {}; + +void +foo (C0 *c0, C1 *c1, C2 *c2, C3 *c3, C4 *c4, C5 *c5, C6 *c6, C7 *c7, C8 *c8) +{ + __builtin_clear_padding (c0); + __builtin_clear_padding (c1); + __builtin_clear_padding (c2); // { dg-error "argument 1 in call to function '__builtin_clear_padding' has pointer to a non-trivially-copyable type \\\('C2\\\*'\\\)" } + __builtin_clear_padding (c3); // { dg-error "argument 1 in call to function '__builtin_clear_padding' has pointer to a non-trivially-copyable type \\\('C3\\\*'\\\)" } + __builtin_clear_padding (c4); // { dg-error "argument 1 in call to function '__builtin_clear_padding' has pointer to a non-trivially-copyable type \\\('C4\\\*'\\\)" } + __builtin_clear_padding (c5); // { dg-error "argument 1 in call to function '__builtin_clear_padding' has pointer to a non-trivially-copyable type \\\('C5\\\*'\\\)" } + __builtin_clear_padding (c6); + __builtin_clear_padding (c7); // { dg-error "argument 1 in call to function '__builtin_clear_padding' has pointer to a non-trivially-copyable type \\\('C7\\\*'\\\)" } + __builtin_clear_padding (c8); // { dg-error "argument 1 in call to function '__builtin_clear_padding' has pointer to a non-trivially-copyable type \\\('C8\\\*'\\\)" } +} + +void +bar () +{ + C0 c0; + C1 c1; + C2 c2; + C3 c3; + C4 c4; + C5 c5; + C6 c6; + C7 c7; + C8 c8; + __builtin_clear_padding (&c0); + __builtin_clear_padding (&c1); + __builtin_clear_padding (&c2); + __builtin_clear_padding (&c3); + __builtin_clear_padding (&c4); +// __builtin_clear_padding (&c5); + __builtin_clear_padding (&c6); + __builtin_clear_padding (&c7); + __builtin_clear_padding (&c8); +}