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;
+}