From patchwork Thu Nov 11 00:07:16 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: C++ PATCH for c++/46369 (C++0x ICE with bitfield) Date: Wed, 10 Nov 2010 14:07:16 -0000 From: Jason Merrill X-Patchwork-Id: 70733 Message-Id: <4CDB33B4.9020007@redhat.com> To: gcc-patches List 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);