]> granicus.if.org Git - clang/commitdiff
Update const_cast semantics for rvalue references. Add tests for
authorDouglas Gregor <dgregor@apple.com>
Sat, 22 Jan 2011 00:19:52 +0000 (00:19 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 22 Jan 2011 00:19:52 +0000 (00:19 +0000)
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

lib/Sema/SemaCXXCast.cpp
test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp [new file with mode: 0644]
test/CXX/expr/expr.post/expr.reinterpret.cast/p1-0x.cpp [new file with mode: 0644]

index 7badc7a7971ba1ea8ccef20dacc928f1597a6d58..075deda4dd9438a28ff82a44cabd19bca551a3b1 100644 (file)
@@ -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<LValueReferenceType>()) {
-    if (!SrcExpr->isLValue()) {
+  if (const ReferenceType *DestTypeTmp =DestType->getAs<ReferenceType>()) {
+    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<ReferenceType>()) {
     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 (file)
index 0000000..d464881
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// The result of the expression const_cast<T>(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<typename T> T& lvalue();
+template<typename T> T&& xvalue();
+template<typename T> T prvalue();
+
+void test_classification(const int *ptr) {
+  int *ptr0 = const_cast<int *&&>(ptr);
+  int *ptr1 = const_cast<int *&&>(xvalue<const int*>());
+  int *ptr2 = const_cast<int *&&>(prvalue<const int*>());
+}
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 (file)
index 0000000..e80082a
--- /dev/null
@@ -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<typename T> T&& xvalue();
+void test_classification(char *ptr) {
+  int (&fr0)(int) = reinterpret_cast<int (&&)(int)>(f);
+  int &&ir0 = reinterpret_cast<int &&>(*ptr);
+  int &&ir1 = reinterpret_cast<int &&>(0);
+  int &&ir2 = reinterpret_cast<int &&>('a');
+  int &&ir3 = reinterpret_cast<int &&>(xvalue<char>());
+}