From patchwork Thu Nov 11 00:07:16 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 70733 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id D8597B711F for ; Thu, 11 Nov 2010 11:07:27 +1100 (EST) Received: (qmail 31022 invoked by alias); 11 Nov 2010 00:07:25 -0000 Received: (qmail 31011 invoked by uid 22791); 11 Nov 2010 00:07:24 -0000 X-SWARE-Spam-Status: No, hits=-6.1 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 11 Nov 2010 00:07:20 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oAB07IKB018073 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 10 Nov 2010 19:07:19 -0500 Received: from [127.0.0.1] (ovpn-113-25.phx2.redhat.com [10.3.113.25]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id oAB07HBJ019628 for ; Wed, 10 Nov 2010 19:07:18 -0500 Message-ID: <4CDB33B4.9020007@redhat.com> Date: Wed, 10 Nov 2010 18:07:16 -0600 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.15) Gecko/20101108 Lightning/1.0b1 Shredder/3.0.11pre MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/46369 (C++0x ICE with bitfield) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Since fold_binary can turn a COMPONENT_REF into a BIT_FIELD_REF, I need to deal with it. Tested x86_64-pc-linux-gnu, applied to trunk. commit 1bf00ede219cbc994aa4be4819ff14b8ebc5fa82 Author: Jason Merrill Date: Wed Nov 10 17:09:39 2010 -0600 PR c++/46369 * semantics.c (cxx_eval_bit_field_ref): New. (cxx_eval_constant_expression): Call it. diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index b48559e..38e03f6 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -6264,6 +6264,45 @@ cxx_eval_component_reference (const constexpr_call *call, tree t, } /* Subroutine of cxx_eval_constant_expression. + Attempt to reduce a field access of a value of class type that is + expressed as a BIT_FIELD_REF. */ + +static tree +cxx_eval_bit_field_ref (const constexpr_call *call, tree t, + bool allow_non_constant, bool addr, + bool *non_constant_p) +{ + tree orig_whole = TREE_OPERAND (t, 0); + tree whole = cxx_eval_constant_expression (call, orig_whole, + allow_non_constant, addr, + non_constant_p); + tree start, field, value; + unsigned HOST_WIDE_INT i; + + if (whole == orig_whole) + return t; + /* Don't VERIFY_CONSTANT here; we only want to check that we got a + CONSTRUCTOR. */ + if (!*non_constant_p && TREE_CODE (whole) != CONSTRUCTOR) + { + if (!allow_non_constant) + error ("%qE is not a constant expression", orig_whole); + *non_constant_p = true; + } + if (*non_constant_p) + return t; + + start = TREE_OPERAND (t, 2); + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value) + { + if (bit_position (field) == start) + return value; + } + gcc_unreachable(); + return error_mark_node; +} + +/* Subroutine of cxx_eval_constant_expression. Evaluate a short-circuited logical expression T in the context of a given constexpr CALL. BAILOUT_VALUE is the value for early return. CONTINUE_VALUE is used here purely for @@ -6841,6 +6880,11 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, non_constant_p); break; + case BIT_FIELD_REF: + r = cxx_eval_bit_field_ref (call, t, allow_non_constant, addr, + non_constant_p); + break; + case COND_EXPR: case VEC_COND_EXPR: r = cxx_eval_conditional_expression (call, t, allow_non_constant, addr, diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield.C new file mode 100644 index 0000000..7eba498 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield.C @@ -0,0 +1,10 @@ +// PR c++/46369 +// { dg-options -std=c++0x } + +struct A +{ + unsigned i : 1; +}; + +constexpr A f() { return { 1 }; } +constexpr bool b = (f().i == 1);