]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
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 21:34:26 +0000 (16:34 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 16 Jan 2012 21:34:26 +0000 (16:34 -0500)
PR c++/51868
* typeck.c (build_static_cast_1): Handle bit-fields properly.

From-SVN: r183223

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 9bb0366255213213b01be74041aefb40374b9b7e..f302fc3b353be8f23924c75be6efe334f577624e 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.
+
 2011-12-20  Dodji Seketeli  <dodji@redhat.com>
 
        PR debug/49951
index 1c099a2c80ca78088a06312840077ef9c2ee9cda..deb895111b625681c58f1bb518bd4b58e4bbe8db 100644 (file)
@@ -5696,11 +5696,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);
@@ -5766,22 +5767,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 ec2fc42f69d4b48d3573485017b786b6c6c2fc30..5c13ce27f0260c9c7926a4ced80d25cf8f8799a0 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-15  Uros Bizjak  <ubizjak@gmail.com>
 
        PR rtl-optimization/51821
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();
+}