re PR c++/51868 (Crash when generating the move constructor for a class with a bit...
authorJason Merrill <jason@redhat.com>
Mon, 16 Jan 2012 18:40:26 +0000 (13:40 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 16 Jan 2012 18:40:26 +0000 (13:40 -0500)
PR c++/51868
* typeck.c (build_static_cast_1): Handle bit-fields properly.

From-SVN: r183218

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/rv-bitfield.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/rv-bitfield2.C [new file with mode: 0644]

index 86ab82f985a034eda8827c5dd1326952e825cf0c..a5a07e47db8357f22166b7202c312706feb461c7 100644 (file)
@@ -1,3 +1,8 @@
+2012-01-16  Jason Merrill  <jason@redhat.com>
+
+       PR c++/51868
+       * typeck.c (build_static_cast_1): Handle bit-fields properly.
+
 2012-01-13  Ian Lance Taylor  <iant@google.com>
 
        PR c++/50012
index 11edeeed3b91c0606585f2e40529f703923fc05c..91e7a0a09ca7e9de904fdd2b20a1b1a5feaff56a 100644 (file)
@@ -5812,11 +5812,12 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
 {
   tree intype;
   tree result;
+  cp_lvalue_kind clk;
 
   /* Assume the cast is valid.  */
   *valid_p = true;
 
-  intype = TREE_TYPE (expr);
+  intype = unlowered_expr_type (expr);
 
   /* Save casted types in the function's used types hash table.  */
   used_types_insert (type);
@@ -5882,22 +5883,29 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
      cv2 T2 if cv2 T2 is reference-compatible with cv1 T1 (8.5.3)."  */
   if (TREE_CODE (type) == REFERENCE_TYPE
       && TYPE_REF_IS_RVALUE (type)
-      && real_lvalue_p (expr)
+      && (clk = real_lvalue_p (expr))
       && reference_related_p (TREE_TYPE (type), intype)
       && (c_cast_p || at_least_as_qualified_p (TREE_TYPE (type), intype)))
     {
-      /* Handle the lvalue case here by casting to lvalue reference and
-        then changing it to an rvalue reference.  Casting an xvalue to
-        rvalue reference will be handled by the main code path.  */
-      tree lref = cp_build_reference_type (TREE_TYPE (type), false);
-      result = (perform_direct_initialization_if_possible
-               (lref, expr, c_cast_p, complain));
-      result = cp_fold_convert (type, result);
-      /* Make sure we don't fold back down to a named rvalue reference,
-        because that would be an lvalue.  */
-      if (DECL_P (result))
-       result = build1 (NON_LVALUE_EXPR, type, result);
-      return convert_from_reference (result);
+      if (clk == clk_ordinary)
+       {
+         /* Handle the (non-bit-field) lvalue case here by casting to
+            lvalue reference and then changing it to an rvalue reference.
+            Casting an xvalue to rvalue reference will be handled by the
+            main code path.  */
+         tree lref = cp_build_reference_type (TREE_TYPE (type), false);
+         result = (perform_direct_initialization_if_possible
+                   (lref, expr, c_cast_p, complain));
+         result = cp_fold_convert (type, result);
+         /* Make sure we don't fold back down to a named rvalue reference,
+            because that would be an lvalue.  */
+         if (DECL_P (result))
+           result = build1 (NON_LVALUE_EXPR, type, result);
+         return convert_from_reference (result);
+       }
+      else
+       /* For a bit-field or packed field, bind to a temporary.  */
+       expr = rvalue (expr);
     }
 
   /* Resolve overloaded address here rather than once in
index 4e58ca5c01865431a53a2ee957c8b0c56c978c3b..0bdffcc3761b7e7c6f0c945a1afc1d717f8f3c17 100644 (file)
@@ -1,3 +1,9 @@
+2012-01-16  Jason Merrill  <jason@redhat.com>
+
+       PR c++/51868
+       * g++.dg/cpp0x/rv-bitfield.C: New.
+       * g++.dg/cpp0x/rv-bitfield2.C: New.
+
 2012-01-16  Paul Thomas  <pault@gcc.gnu.org>
 
        * gfortran.dg/class_array_3.f03: Remove the explicit loop in
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-bitfield.C b/gcc/testsuite/g++.dg/cpp0x/rv-bitfield.C
new file mode 100644 (file)
index 0000000..ed866f9
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-options -std=c++0x }
+
+struct A
+{
+  int i : 1;
+};
+
+int main()
+{
+  A a;
+  static_cast<int&&>(a.i);
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-bitfield2.C b/gcc/testsuite/g++.dg/cpp0x/rv-bitfield2.C
new file mode 100644 (file)
index 0000000..e054151
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/51868
+// { dg-options -std=c++0x }
+
+struct A {
+  A() {}
+  A(const A&) {}
+  A(A&&) {}
+};
+
+struct B {
+  A a;
+  int f : 1;
+};
+
+B func() {
+  return B();
+}