From patchwork Sat Dec 4 20:26:17 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 48497 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 7CF113858407 for ; Sat, 4 Dec 2021 20:27:05 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7CF113858407 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1638649625; bh=7RtTMK6tpxuxg2bZGdwlAMFEFWd/svVUW7iy0yoHfuk=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=rY/2AFDKS5pgUovsM6U+19kmZKDUgBBd3y9Xkdhdil+HU1e4l153TuTruoUvPvv39 Y33isDkhbTJL2p6O66dSxRlX5KcPQZT4cIvaBZnlYVi9ZXplnvsulf0ZNeLs7k6tfi v1JEJRY49a6+2w/NzY78RM23OOJawn/xixAgutps= 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 50DE53858D39 for ; Sat, 4 Dec 2021 20:26:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 50DE53858D39 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-551-6jMXIH87P26CBPptFtocOg-1; Sat, 04 Dec 2021 15:26:33 -0500 X-MC-Unique: 6jMXIH87P26CBPptFtocOg-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 5CF01801B01 for ; Sat, 4 Dec 2021 20:26:32 +0000 (UTC) Received: from pdp-11.redhat.com (unknown [10.22.32.46]) by smtp.corp.redhat.com (Postfix) with ESMTP id DBE0F19C79; Sat, 4 Dec 2021 20:26:31 +0000 (UTC) To: Jason Merrill , GCC Patches Subject: [PATCH] c++: Fix for decltype and bit-fields [PR95009] Date: Sat, 4 Dec 2021 15:26:17 -0500 Message-Id: <20211204202617.362235-1-polacek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-14.2 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_H3, 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: Marek Polacek via Gcc-patches From: Marek Polacek Reply-To: Marek Polacek Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Here, decltype deduces the wrong type for certain expressions involving bit-fields. Unlike in C, in C++ bit-field width is explicitly not part of the type, so I think decltype should never deduce to 'int:N'. The problem isn't that we're not calling unlowered_expr_type--we are--it's that is_bitfield_expr_with_lowered_type only handles certain codes, but not others. For example, += works fine but ++ does not. This also fixes decltype-bitfield2.C where we were crashing (!), but unfortunately it does not fix 84516 or 70733 where the problem is likely a missing call to unlowered_expr_type. It occurs to me now that typeof likely has had the same issue, but this patch should fix that too. Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11? PR c++/95009 gcc/cp/ChangeLog: * typeck.c (is_bitfield_expr_with_lowered_type) : Handle UNARY_PLUS_EXPR, NEGATE_EXPR, NON_LVALUE_EXPR, BIT_NOT_EXPR, *CREMENT_EXPR too. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/decltype-bitfield1.C: New test. * g++.dg/cpp0x/decltype-bitfield2.C: New test. --- gcc/cp/typeck.c | 14 +++- .../g++.dg/cpp0x/decltype-bitfield1.C | 65 +++++++++++++++++++ .../g++.dg/cpp0x/decltype-bitfield2.C | 18 +++++ 3 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype-bitfield1.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype-bitfield2.C base-commit: 689407ef916503b2f5a3c8c07fe7d5ab1913f956 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 5ed9a5ab9ee..4e60db40c76 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2209,9 +2209,9 @@ invalid_nonstatic_memfn_p (location_t loc, tree expr, tsubst_flags_t complain) return false; } -/* If EXP is a reference to a bitfield, and the type of EXP does not - match the declared type of the bitfield, return the declared type - of the bitfield. Otherwise, return NULL_TREE. */ +/* If EXP is a reference to a bit-field, and the type of EXP does not + match the declared type of the bit-field, return the declared type + of the bit-field. Otherwise, return NULL_TREE. */ tree is_bitfield_expr_with_lowered_type (const_tree exp) @@ -2230,6 +2230,14 @@ is_bitfield_expr_with_lowered_type (const_tree exp) case MODIFY_EXPR: case SAVE_EXPR: + case UNARY_PLUS_EXPR: + case PREDECREMENT_EXPR: + case PREINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + case NEGATE_EXPR: + case NON_LVALUE_EXPR: + case BIT_NOT_EXPR: return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0)); case COMPONENT_REF: diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-bitfield1.C b/gcc/testsuite/g++.dg/cpp0x/decltype-bitfield1.C new file mode 100644 index 00000000000..2d8d8e81bff --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/decltype-bitfield1.C @@ -0,0 +1,65 @@ +// PR c++/95009 +// { dg-do compile { target c++11 } } + +struct false_type { static constexpr bool value = false; }; +struct true_type { static constexpr bool value = true; }; +template +struct is_same : false_type {}; +template +struct is_same : true_type {}; + +struct A { + int i : 31; + unsigned long l : 37; +} a; + +void +g () +{ + // Careful: pre{in,de}crements are lvalues -> deduce T&. */ + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); + static_assert (is_same::value, ""); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-bitfield2.C b/gcc/testsuite/g++.dg/cpp0x/decltype-bitfield2.C new file mode 100644 index 00000000000..4bf9c7682ff --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/decltype-bitfield2.C @@ -0,0 +1,18 @@ +// PR c++/95009 +// { dg-do compile { target c++11 } } + +struct A { + int i:31; +}; + +template +void f () +{ +} + +int main () +{ + A a; + f(); + f(); +}