From: Douglas Gregor Date: Sat, 22 Jan 2011 00:19:52 +0000 (+0000) Subject: Update const_cast semantics for rvalue references. Add tests for X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=575d2a30f288ddab2f24a77dfcc71f6f7f808394;p=clang Update const_cast semantics for rvalue references. Add tests for reinterpret_cast and const_cast using rvalue references. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124007 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 7badc7a797..075deda4dd 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -1050,9 +1050,8 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType, bool CStyle, unsigned &msg) { DestType = Self.Context.getCanonicalType(DestType); QualType SrcType = SrcExpr->getType(); - if (const LValueReferenceType *DestTypeTmp = - DestType->getAs()) { - if (!SrcExpr->isLValue()) { + if (const ReferenceType *DestTypeTmp =DestType->getAs()) { + if (DestTypeTmp->isLValueReferenceType() && !SrcExpr->isLValue()) { // Cannot const_cast non-lvalue to lvalue reference type. But if this // is C-style, static_cast might find a way, so we simply suggest a // message and tell the parent to keep searching. @@ -1156,8 +1155,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr, if (const ReferenceType *DestTypeTmp = DestType->getAs()) { bool LValue = DestTypeTmp->isLValueReferenceType(); if (LValue && !SrcExpr->isLValue()) { - // Cannot cast non-lvalue to reference type. See the similar comment in - // const_cast. + // Cannot cast non-lvalue to lvalue reference type. See the similar + // comment in const_cast. msg = diag::err_bad_cxx_cast_rvalue; return TC_NotApplicable; } diff --git a/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp b/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp new file mode 100644 index 0000000000..d46488107b --- /dev/null +++ b/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// The result of the expression const_cast(v) is of type T. If T is +// an lvalue reference to object type, the result is an lvalue; if T +// is an rvalue reference to object type, the result is an xvalue;. + +unsigned int f(int); + +template T& lvalue(); +template T&& xvalue(); +template T prvalue(); + +void test_classification(const int *ptr) { + int *ptr0 = const_cast(ptr); + int *ptr1 = const_cast(xvalue()); + int *ptr2 = const_cast(prvalue()); +} diff --git a/test/CXX/expr/expr.post/expr.reinterpret.cast/p1-0x.cpp b/test/CXX/expr/expr.post/expr.reinterpret.cast/p1-0x.cpp new file mode 100644 index 0000000000..e80082a040 --- /dev/null +++ b/test/CXX/expr/expr.post/expr.reinterpret.cast/p1-0x.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +// If T is an lvalue reference type or an rvalue reference to function +// type, the result is an lvalue; if T is an rvalue reference to +// object type, the result is an xvalue; + +unsigned int f(int); + +template T&& xvalue(); +void test_classification(char *ptr) { + int (&fr0)(int) = reinterpret_cast(f); + int &&ir0 = reinterpret_cast(*ptr); + int &&ir1 = reinterpret_cast(0); + int &&ir2 = reinterpret_cast('a'); + int &&ir3 = reinterpret_cast(xvalue()); +}