EricWF updated this revision to Diff 76775.
EricWF added a comment.

- Add tests under `test/CXX`
- Add FIXME regarding the C++1z change from glvalue to lvalue in p3.


https://reviews.llvm.org/D26231

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaCast.cpp
  test/CXX/expr/expr.post/expr.static.cast/p3-p4-0x.cpp
  test/SemaCXX/rval-references.cpp

Index: test/SemaCXX/rval-references.cpp
===================================================================
--- test/SemaCXX/rval-references.cpp
+++ test/SemaCXX/rval-references.cpp
@@ -30,11 +30,15 @@
   int &&virr2 = 0;
   int &&virr3 = virr2; // expected-error {{rvalue reference to type 'int' cannot bind to lvalue of type 'int'}}
   int i1 = 0;
+  const double d1 = 0;
+  const int ci1 = 1;
   int &&virr4 = i1; // expected-error {{rvalue reference to type 'int' cannot bind to lvalue of type 'int'}}
   int &&virr5 = ret_irr();
   int &&virr6 = static_cast<int&&>(i1);
-  (void)static_cast<not_int&&>(i1); // expected-error {{types are not compatible}}
-
+  (void)static_cast<not_int &&>(i1); // expected-error {{reference to type 'not_int' could not bind to an lvalue of type 'int'}}
+  (void)static_cast<int &&>(static_cast<int const&&>(i1)); // expected-error {{cannot cast from rvalue reference of type 'const int' to rvalue reference type 'int &&'}}
+  (void)static_cast<int &&>(ci1);    // expected-error {{types are not compatible}}
+  (void)static_cast<int &&>(d1);
   int i2 = over(i1);
   not_int ni1 = over(0);
   int i3 = over(virr2);
Index: test/CXX/expr/expr.post/expr.static.cast/p3-p4-0x.cpp
===================================================================
--- /dev/null
+++ test/CXX/expr/expr.post/expr.static.cast/p3-p4-0x.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+// 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" (8.5.3).
+// p4
+// Otherwise, an expression e can be explicitly converted to a type T using a
+// static_cast of the form static_cast<T>(e) if the declaration T t(e); is
+// well-formed, for some invented temporary variable t (8.5). [...]
+struct A { };
+struct B : A { };
+
+struct C { explicit operator A&&(); };
+struct D { operator B(); };
+
+template<typename T> T& lvalue();
+template<typename T> T&& xvalue();
+template <typename T> T prvalue();
+
+void test(A &a, B &b) {
+  A &&ar0 = static_cast<A&&>(prvalue<A>());
+  A &&ar1 = static_cast<A&&>(prvalue<B>());
+  A &&ar2 = static_cast<A&&>(lvalue<C>());
+  A &&ar3 = static_cast<A&&>(xvalue<C>());
+  A &&ar4 = static_cast<A&&>(prvalue<C>());
+  A &&ar5 = static_cast<A&&>(lvalue<D>());
+  A &&ar6 = static_cast<A&&>(xvalue<D>());
+  A &&ar7 = static_cast<A&&>(prvalue<D>());
+
+  const A &&ar8 = static_cast<const A&&>(prvalue<A>());
+  const A &&ar9 = static_cast<const A&&>(prvalue<B>());
+  const A &&ar10 = static_cast<const A&&>(lvalue<C>());
+  const A &&ar11 = static_cast<const A&&>(xvalue<C>());
+  const A &&ar12 = static_cast<const A&&>(prvalue<C>());
+  const A &&ar13 = static_cast<const A&&>(lvalue<D>());
+}
Index: lib/Sema/SemaCast.cpp
===================================================================
--- lib/Sema/SemaCast.cpp
+++ lib/Sema/SemaCast.cpp
@@ -1134,17 +1134,18 @@
 }
 
 /// Tests whether a conversion according to N2844 is valid.
-TryCastResult
-TryLValueToRValueCast(Sema &Self, Expr *SrcExpr, QualType DestType,
-                      bool CStyle, CastKind &Kind, CXXCastPath &BasePath, 
+TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
+                                    QualType DestType, bool CStyle,
+                                    CastKind &Kind, CXXCastPath &BasePath,
                                     unsigned &msg) {
   // C++11 [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;
 
+  // FIXME C++1z doesn't allow this conversions for xvalues.
   if (!SrcExpr->isGLValue())
     return TC_NotApplicable;
 
@@ -1161,14 +1162,14 @@
     ToType = ToType.getUnqualifiedType();
   }
 
-  if (Self.CompareReferenceRelationship(SrcExpr->getLocStart(),
-                                        ToType, FromType,
-                                        DerivedToBase, ObjCConversion,
-                                        ObjCLifetimeConversion) 
-        != Sema::Ref_Compatible) {
-    if (CStyle)
+  Sema::ReferenceCompareResult RefResult = Self.CompareReferenceRelationship(
+      SrcExpr->getLocStart(), ToType, FromType, DerivedToBase, ObjCConversion,
+      ObjCLifetimeConversion);
+  if (RefResult != Sema::Ref_Compatible) {
+    if (CStyle || RefResult == Sema::Ref_Incompatible)
       return TC_NotApplicable;
-    msg = diag::err_bad_lvalue_to_rvalue_cast;
+    msg = SrcExpr->isLValue() ? diag::err_bad_lvalue_to_rvalue_cast
+                              : diag::err_bad_rvalue_to_rvalue_cast;
     return TC_Failed;
   }
 
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -5942,6 +5942,9 @@
 def err_bad_lvalue_to_rvalue_cast : Error<
   "cannot cast from lvalue of type %1 to rvalue reference type %2; types are "
   "not compatible">;
+def err_bad_rvalue_to_rvalue_cast : Error<
+  "cannot cast from rvalue reference of type %1 to rvalue reference type %2; types are "
+  "not compatible">;
 def err_bad_static_cast_pointer_nonpointer : Error<
   "cannot cast from type %1 to pointer type %2">;
 def err_bad_static_cast_member_pointer_nonmp : Error<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to