Patchwork C++ PATCH for c++/46369 (C++0x ICE with bitfield)

login
register
mail settings
Submitter Jason Merrill
Date Nov. 11, 2010, 12:07 a.m.
Message ID <4CDB33B4.9020007@redhat.com>
Download mbox | patch
Permalink /patch/70733/
State New
Headers show

Comments

Jason Merrill - Nov. 11, 2010, 12:07 a.m.
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 <jason@redhat.com>
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.

Patch

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);