Handle C-style casts to rvalue reference types that cast away constness.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124319 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 3a9ad5f..c492c2a 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -78,7 +78,8 @@
 // %1: Source Type
 // %2: Destination Type
 static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
-                                           QualType DestType, CastKind &Kind,
+                                           QualType DestType, bool CStyle,
+                                           CastKind &Kind,
                                            CXXCastPath &BasePath,
                                            unsigned &msg);
 static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr,
@@ -583,7 +584,8 @@
   // C++0x [expr.static.cast]p3: 
   //   A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2
   //   T2" if "cv2 T2" is reference-compatible with "cv1 T1".
-  tcr = TryLValueToRValueCast(Self, SrcExpr, DestType, Kind, BasePath, msg);
+  tcr = TryLValueToRValueCast(Self, SrcExpr, DestType, CStyle, Kind, BasePath, 
+                              msg);
   if (tcr != TC_NotApplicable)
     return tcr;
 
@@ -695,7 +697,8 @@
 /// Tests whether a conversion according to N2844 is valid.
 TryCastResult
 TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
-                      CastKind &Kind, CXXCastPath &BasePath, unsigned &msg) {
+                      bool CStyle, CastKind &Kind, CXXCastPath &BasePath, 
+                      unsigned &msg) {
   // C++0x [expr.static.cast]p3:
   //   A glvalue of type "cv1 T1" can be cast to type "rvalue reference to 
   //   cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
@@ -711,8 +714,15 @@
   // FIXME: Should allow casting away constness if CStyle.
   bool DerivedToBase;
   bool ObjCConversion;
+  QualType FromType = SrcExpr->getType();
+  QualType ToType = R->getPointeeType();
+  if (CStyle) {
+    FromType = FromType.getUnqualifiedType();
+    ToType = ToType.getUnqualifiedType();
+  }
+  
   if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
-                                        R->getPointeeType(), SrcExpr->getType(),
+                                        ToType, FromType,
                                         DerivedToBase, ObjCConversion) <
         Sema::Ref_Compatible_With_Added_Qualification) {
     msg = diag::err_bad_lvalue_to_rvalue_cast;
diff --git a/test/CXX/expr/expr.cast/p4-0x.cpp b/test/CXX/expr/expr.cast/p4-0x.cpp
new file mode 100644
index 0000000..5824cd2
--- /dev/null
+++ b/test/CXX/expr/expr.cast/p4-0x.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+struct X { };
+struct Y : X { };
+
+void test_lvalue_to_rvalue_drop_cvquals(const X &x, const Y &y, const int &i) {
+  (void)(X&&)x;
+  (void)(int&&)i;
+  (void)(X&&)y;
+  (void)(Y&&)x;
+}