forked from OSchip/llvm-project
Teach static_cast and dynamic_cast about rvalue references.
llvm-svn: 124006
This commit is contained in:
parent
3f9047e321
commit
465184ae10
|
@ -341,7 +341,9 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
|
||||||
DestPointee = DestPointer->getPointeeType();
|
DestPointee = DestPointer->getPointeeType();
|
||||||
} else if ((DestReference = DestType->getAs<ReferenceType>())) {
|
} else if ((DestReference = DestType->getAs<ReferenceType>())) {
|
||||||
DestPointee = DestReference->getPointeeType();
|
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 {
|
} else {
|
||||||
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr)
|
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr)
|
||||||
<< OrigDestType << DestRange;
|
<< OrigDestType << DestRange;
|
||||||
|
@ -364,10 +366,8 @@ CheckDynamicCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
|
||||||
|
|
||||||
// C++0x 5.2.7p2: If T is a pointer type, v shall be an rvalue of a pointer to
|
// 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
|
// 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
|
// 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,
|
// type, v shall be an expression having a complete class type, [...]
|
||||||
// [...]
|
|
||||||
|
|
||||||
QualType SrcType = Self.Context.getCanonicalType(OrigSrcType);
|
QualType SrcType = Self.Context.getCanonicalType(OrigSrcType);
|
||||||
QualType SrcPointee;
|
QualType SrcPointee;
|
||||||
if (DestPointer) {
|
if (DestPointer) {
|
||||||
|
@ -578,8 +578,9 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
|
||||||
if (tcr != TC_NotApplicable)
|
if (tcr != TC_NotApplicable)
|
||||||
return tcr;
|
return tcr;
|
||||||
|
|
||||||
// N2844 5.2.9p3: An lvalue of type "cv1 T1" can be cast to type "rvalue
|
// C++0x [expr.static.cast]p3:
|
||||||
// reference to cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
|
// 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);
|
tcr = TryLValueToRValueCast(Self, SrcExpr, DestType, msg);
|
||||||
if (tcr != TC_NotApplicable) {
|
if (tcr != TC_NotApplicable) {
|
||||||
Kind = CK_NoOp;
|
Kind = CK_NoOp;
|
||||||
|
@ -695,13 +696,14 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
|
||||||
TryCastResult
|
TryCastResult
|
||||||
TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
|
TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
|
||||||
unsigned &msg) {
|
unsigned &msg) {
|
||||||
// N2844 5.2.9p3: An lvalue of type "cv1 T1" can be cast to type "rvalue
|
// C++0x [expr.static.cast]p3:
|
||||||
// reference to cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
|
// 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>();
|
const RValueReferenceType *R = DestType->getAs<RValueReferenceType>();
|
||||||
if (!R)
|
if (!R)
|
||||||
return TC_NotApplicable;
|
return TC_NotApplicable;
|
||||||
|
|
||||||
if (!SrcExpr->isLValue())
|
if (!SrcExpr->isGLValue())
|
||||||
return TC_NotApplicable;
|
return TC_NotApplicable;
|
||||||
|
|
||||||
// Because we try the reference downcast before this function, from now on
|
// Because we try the reference downcast before this function, from now on
|
||||||
|
@ -710,15 +712,13 @@ TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
|
||||||
bool DerivedToBase;
|
bool DerivedToBase;
|
||||||
bool ObjCConversion;
|
bool ObjCConversion;
|
||||||
if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
|
if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
|
||||||
SrcExpr->getType(), R->getPointeeType(),
|
R->getPointeeType(), SrcExpr->getType(),
|
||||||
DerivedToBase, ObjCConversion) <
|
DerivedToBase, ObjCConversion) <
|
||||||
Sema::Ref_Compatible_With_Added_Qualification) {
|
Sema::Ref_Compatible_With_Added_Qualification) {
|
||||||
msg = diag::err_bad_lvalue_to_rvalue_cast;
|
msg = diag::err_bad_lvalue_to_rvalue_cast;
|
||||||
return TC_Failed;
|
return TC_Failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: We should probably have an AST node for lvalue-to-rvalue
|
|
||||||
// conversions.
|
|
||||||
return TC_Success;
|
return TC_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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}}
|
||||||
|
}
|
|
@ -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>());
|
||||||
|
}
|
Loading…
Reference in New Issue