Fix handling of const_cast from prvalue to rvalue reference: such a cast is
only permitted if the source object is of class type, and should materialize a
temporary for the reference to bind to.

llvm-svn: 184017
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index 7a43c45..d4afeb8 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -322,7 +322,7 @@
   //   constant expression;
   constexpr volatile S f() { return S(); }
   static_assert(f().i, ""); // ok! there's no lvalue-to-rvalue conversion here!
-  static_assert(((volatile const S&&)(S)0).i, ""); // expected-error {{constant expression}}
+  static_assert(((volatile const S&&)(S)0).i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
 }
 
 // DR1312: The proposed wording for this defect has issues, so we ignore this
diff --git a/clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp b/clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp
index 76ea96f..f4c0f1a 100644
--- a/clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp
+++ b/clang/test/CXX/expr/expr.post/expr.const.cast/p1-0x.cpp
@@ -6,14 +6,26 @@
 
 unsigned int f(int);
 
+struct X {};
+
 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*>());
+void test_classification(const int *ptr, X x) {
+  int *&&ptr0 = const_cast<int *&&>(ptr);
+  int *&&ptr1 = const_cast<int *&&>(xvalue<const int*>());
+  int *&&ptr2 = const_cast<int *&&>(prvalue<const int*>()); // expected-error {{const_cast from rvalue to reference type 'int *&&'}}
+  X &&ptr3 = const_cast<X&&>(x);
+  X &&ptr4 = const_cast<X&&>(xvalue<X>());
+  X &&ptr5 = const_cast<X&&>(prvalue<X>());
+
+  int *&ptr6 = const_cast<int *&>(ptr);
+  int *&ptr7 = const_cast<int *&>(xvalue<const int*>()); // expected-error {{const_cast from rvalue to reference type 'int *&'}}
+  int *&ptr8 = const_cast<int *&>(prvalue<const int*>()); // expected-error {{const_cast from rvalue to reference type 'int *&'}}
+  X &ptr9 = const_cast<X&>(x);
+  X &ptrA = const_cast<X&>(xvalue<X>()); // expected-error {{const_cast from rvalue to reference type 'X &'}}
+  X &ptrB = const_cast<X&>(prvalue<X>()); // expected-error {{const_cast from rvalue to reference type 'X &'}}
 }
 
 struct A {
diff --git a/clang/test/SemaCXX/const-cast.cpp b/clang/test/SemaCXX/const-cast.cpp
index 62851f8..1fe350d 100644
--- a/clang/test/SemaCXX/const-cast.cpp
+++ b/clang/test/SemaCXX/const-cast.cpp
@@ -38,6 +38,7 @@
   f *fpp = const_cast<f*>(&fp);
   int const A::* const A::*icapcap = 0;
   int A::* A::* iapap = const_cast<int A::* A::*>(icapcap);
+  (void)const_cast<A&&>(A()); // expected-warning {{C++11}}
 
   return var4;
 }
@@ -60,5 +61,6 @@
   f fp2 = const_cast<f>(fp1); // expected-error {{const_cast to 'f' (aka 'int (*)(int)'), which is not a reference, pointer-to-object, or pointer-to-data-member}}
   void (A::*mfn)() = 0;
   (void)const_cast<void (A::*)()>(mfn); // expected-error {{const_cast to 'void (A::*)()', which is not a reference, pointer-to-object, or pointer-to-data-member}}
+  (void)const_cast<int&&>(0); // expected-error {{const_cast from rvalue to reference type 'int &&'}} expected-warning {{C++11}}
   return **var3;
 }
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 173172a..b928887 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -79,6 +79,11 @@
 constexpr int n7 = **n5;
 constexpr int n8 = **n6;
 
+// const_cast from prvalue to xvalue.
+struct A { int n; };
+constexpr int n9 = (const_cast<A&&>(A{123})).n;
+static_assert(n9 == 123, "");
+
 }
 
 namespace TemplateArgumentConversion {