[cfe-commits] r124006 - in /cfe/trunk: lib/Sema/SemaCXXCast.cpp test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp
Douglas Gregor
dgregor at apple.com
Fri Jan 21 16:06:57 PST 2011
Author: dgregor
Date: Fri Jan 21 18:06:57 2011
New Revision: 124006
URL: http://llvm.org/viewvc/llvm-project?rev=124006&view=rev
Log:
Teach static_cast and dynamic_cast about rvalue references.
Added:
cfe/trunk/test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp
cfe/trunk/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp
Modified:
cfe/trunk/lib/Sema/SemaCXXCast.cpp
Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=124006&r1=124005&r2=124006&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Fri Jan 21 18:06:57 2011
@@ -341,7 +341,9 @@
DestPointee = DestPointer->getPointeeType();
} else if ((DestReference = DestType->getAs<ReferenceType>())) {
DestPointee = DestReference->getPointeeType();
- VK = isa<LValueReferenceType>(DestReference) ? VK_LValue : VK_RValue;
+ VK = isa<LValueReferenceType>(DestReference) ? VK_LValue
+ : isa<RValueReferenceType>(DestReference) ? VK_XValue
+ : VK_RValue;
} else {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr)
<< OrigDestType << DestRange;
@@ -364,10 +366,8 @@
// C++0x 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to
// complete class type, [...]. If T is an lvalue reference type, v shall be
- // an lvalue of a complete class type, [...]. If T is an rvalue reference
- // type, v shall be an expression having a complete effective class type,
- // [...]
-
+ // an lvalue of a complete class type, [...]. If T is an rvalue reference
+ // type, v shall be an expression having a complete class type, [...]
QualType SrcType = Self.Context.getCanonicalType(OrigSrcType);
QualType SrcPointee;
if (DestPointer) {
@@ -578,8 +578,9 @@
if (tcr != TC_NotApplicable)
return tcr;
- // N2844 5.2.9p3: An lvalue of type "cv1 T1" can be cast to type "rvalue
- // reference to cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
+ // 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, msg);
if (tcr != TC_NotApplicable) {
Kind = CK_NoOp;
@@ -695,13 +696,14 @@
TryCastResult
TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
unsigned &msg) {
- // N2844 5.2.9p3: An lvalue of type "cv1 T1" can be cast to type "rvalue
- // reference to cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
+ // 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".
const RValueReferenceType *R = DestType->getAs<RValueReferenceType>();
if (!R)
return TC_NotApplicable;
- if (!SrcExpr->isLValue())
+ if (!SrcExpr->isGLValue())
return TC_NotApplicable;
// Because we try the reference downcast before this function, from now on
@@ -710,15 +712,13 @@
bool DerivedToBase;
bool ObjCConversion;
if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
- SrcExpr->getType(), R->getPointeeType(),
+ R->getPointeeType(), SrcExpr->getType(),
DerivedToBase, ObjCConversion) <
Sema::Ref_Compatible_With_Added_Qualification) {
msg = diag::err_bad_lvalue_to_rvalue_cast;
return TC_Failed;
}
- // FIXME: We should probably have an AST node for lvalue-to-rvalue
- // conversions.
return TC_Success;
}
Added: cfe/trunk/test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp?rev=124006&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.post/expr.dynamic.cast/p3-0x.cpp Fri Jan 21 18:06:57 2011
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+struct X { virtual ~X(); };
+struct Y : public X { };
+struct Z; // expected-note{{forward declaration of 'Z'}}
+
+void test(X &x, Y &y, Z &z) {
+ // If T is an rvalue reference type, v shall be an expression having
+ // a complete class type, and the result is an xvalue of the type
+ // referred to by T.
+ Y &&yr0 = dynamic_cast<Y&&>(x);
+ Y &&yr1 = dynamic_cast<Y&&>(static_cast<X&&>(x));
+ Y &&yr2 = dynamic_cast<Y&&>(z); // expected-error{{'Z' is an incomplete type}}
+}
Added: cfe/trunk/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp?rev=124006&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp Fri Jan 21 18:06:57 2011
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// 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" (8.5.3).
+struct A { };
+struct B : A { };
+
+template<typename T> T& lvalue();
+template<typename T> T&& xvalue();
+
+void test(A &a, B &b) {
+ A &&ar0 = static_cast<A&&>(a);
+ A &&ar1 = static_cast<A&&>(b);
+ A &&ar2 = static_cast<A&&>(lvalue<A>());
+ A &&ar3 = static_cast<A&&>(lvalue<B>());
+ A &&ar4 = static_cast<A&&>(xvalue<A>());
+ A &&ar5 = static_cast<A&&>(xvalue<B>());
+ const A &&ar6 = static_cast<const A&&>(a);
+ const A &&ar7 = static_cast<const A&&>(b);
+ const A &&ar8 = static_cast<const A&&>(lvalue<A>());
+ const A &&ar9 = static_cast<const A&&>(lvalue<B>());
+ const A &&ar10 = static_cast<const A&&>(xvalue<A>());
+ const A &&ar11 = static_cast<const A&&>(xvalue<B>());
+}
More information about the cfe-commits
mailing list