cjdb updated this revision to Diff 421836.
cjdb edited the summary of this revision.
cjdb added a comment.
Herald added a project: All.

adds `__is_copy_constructible`, `__is_copy_assignable`, 
`__is_move_constructible` (WIP), and `__is_move_assignable` (incomplete)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D116280/new/

https://reviews.llvm.org/D116280

Files:
  clang/include/clang/Basic/TokenKinds.def
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCXX/type-traits.cpp

Index: clang/test/SemaCXX/type-traits.cpp
===================================================================
--- clang/test/SemaCXX/type-traits.cpp
+++ clang/test/SemaCXX/type-traits.cpp
@@ -345,11 +345,19 @@
 }
 
 typedef Enum EnumType;
+typedef EnumClass EnumClassType;
 
 void is_enum()
 {
   { int arr[T(__is_enum(Enum))]; }
   { int arr[T(__is_enum(EnumType))]; }
+  { int arr[T(__is_enum(SignedEnum))]; }
+  { int arr[T(__is_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_enum(EnumClass))]; }
+  { int arr[T(__is_enum(EnumClassType))]; }
+  { int arr[T(__is_enum(SignedEnumClass))]; }
+  { int arr[T(__is_enum(UnsignedEnumClass))]; }
 
   { int arr[F(__is_enum(int))]; }
   { int arr[F(__is_enum(Union))]; }
@@ -363,6 +371,30 @@
   { int arr[F(__is_enum(HasAnonymousUnion))]; }
 }
 
+void is_scoped_enum()
+{
+  { int arr[F(__is_scoped_enum(Enum))]; }
+  { int arr[F(__is_scoped_enum(EnumType))]; }
+  { int arr[F(__is_scoped_enum(SignedEnum))]; }
+  { int arr[F(__is_scoped_enum(UnsignedEnum))]; }
+
+  { int arr[T(__is_scoped_enum(EnumClass))]; }
+  { int arr[T(__is_scoped_enum(EnumClassType))]; }
+  { int arr[T(__is_scoped_enum(SignedEnumClass))]; }
+  { int arr[T(__is_scoped_enum(UnsignedEnumClass))]; }
+
+  { int arr[F(__is_scoped_enum(int))]; }
+  { int arr[F(__is_scoped_enum(Union))]; }
+  { int arr[F(__is_scoped_enum(Int))]; }
+  { int arr[F(__is_scoped_enum(IntAr))]; }
+  { int arr[F(__is_scoped_enum(UnionAr))]; }
+  { int arr[F(__is_scoped_enum(Derives))]; }
+  { int arr[F(__is_scoped_enum(ClassType))]; }
+  { int arr[F(__is_scoped_enum(cvoid))]; }
+  { int arr[F(__is_scoped_enum(IntArNB))]; }
+  { int arr[F(__is_scoped_enum(HasAnonymousUnion))]; }
+}
+
 struct FinalClass final {
 };
 
@@ -702,6 +734,66 @@
   int t31[F(__is_array(cvoid*))];
 }
 
+void is_bounded_array()
+{
+  int t01[T(__is_bounded_array(IntAr))];
+  int t02[F(__is_bounded_array(IntArNB))];
+  int t03[T(__is_bounded_array(UnionAr))];
+
+  int t10[F(__is_bounded_array(void))];
+  int t11[F(__is_bounded_array(cvoid))];
+  int t12[F(__is_bounded_array(float))];
+  int t13[F(__is_bounded_array(double))];
+  int t14[F(__is_bounded_array(long double))];
+  int t15[F(__is_bounded_array(bool))];
+  int t16[F(__is_bounded_array(char))];
+  int t17[F(__is_bounded_array(signed char))];
+  int t18[F(__is_bounded_array(unsigned char))];
+  int t19[F(__is_bounded_array(wchar_t))];
+  int t20[F(__is_bounded_array(short))];
+  int t21[F(__is_bounded_array(unsigned short))];
+  int t22[F(__is_bounded_array(int))];
+  int t23[F(__is_bounded_array(unsigned int))];
+  int t24[F(__is_bounded_array(long))];
+  int t25[F(__is_bounded_array(unsigned long))];
+  int t26[F(__is_bounded_array(Union))];
+  int t27[F(__is_bounded_array(Derives))];
+  int t28[F(__is_bounded_array(ClassType))];
+  int t29[F(__is_bounded_array(Enum))];
+  int t30[F(__is_bounded_array(void*))];
+  int t31[F(__is_bounded_array(cvoid*))];
+}
+
+void is_unbounded_array()
+{
+  int t01[F(__is_unbounded_array(IntAr))];
+  int t02[T(__is_unbounded_array(IntArNB))];
+  int t03[F(__is_unbounded_array(UnionAr))];
+
+  int t10[F(__is_unbounded_array(void))];
+  int t11[F(__is_unbounded_array(cvoid))];
+  int t12[F(__is_unbounded_array(float))];
+  int t13[F(__is_unbounded_array(double))];
+  int t14[F(__is_unbounded_array(long double))];
+  int t15[F(__is_unbounded_array(bool))];
+  int t16[F(__is_unbounded_array(char))];
+  int t17[F(__is_unbounded_array(signed char))];
+  int t18[F(__is_unbounded_array(unsigned char))];
+  int t19[F(__is_unbounded_array(wchar_t))];
+  int t20[F(__is_unbounded_array(short))];
+  int t21[F(__is_unbounded_array(unsigned short))];
+  int t22[F(__is_unbounded_array(int))];
+  int t23[F(__is_unbounded_array(unsigned int))];
+  int t24[F(__is_unbounded_array(long))];
+  int t25[F(__is_unbounded_array(unsigned long))];
+  int t26[F(__is_unbounded_array(Union))];
+  int t27[F(__is_unbounded_array(Derives))];
+  int t28[F(__is_unbounded_array(ClassType))];
+  int t29[F(__is_unbounded_array(Enum))];
+  int t30[F(__is_unbounded_array(void*))];
+  int t31[F(__is_unbounded_array(cvoid*))];
+}
+
 template <typename T> void tmpl_func(T&) {}
 
 template <typename T> struct type_wrapper {
@@ -934,6 +1026,43 @@
   int t34[F(__is_pointer(void (StructWithMembers::*) ()))];
 }
 
+void is_null_pointer()
+{
+  StructWithMembers x;
+
+  int t00[T(__is_nullptr(decltype(nullptr)))];
+  int t01[F(__is_nullptr(void*))];
+  int t02[F(__is_nullptr(cvoid*))];
+  int t03[F(__is_nullptr(cvoid*))];
+  int t04[F(__is_nullptr(char*))];
+  int t05[F(__is_nullptr(int*))];
+  int t06[F(__is_nullptr(int**))];
+  int t07[F(__is_nullptr(ClassType*))];
+  int t08[F(__is_nullptr(Derives*))];
+  int t09[F(__is_nullptr(Enum*))];
+  int t10[F(__is_nullptr(IntArNB*))];
+  int t11[F(__is_nullptr(Union*))];
+  int t12[F(__is_nullptr(UnionAr*))];
+  int t13[F(__is_nullptr(StructWithMembers*))];
+  int t14[F(__is_nullptr(void (*)()))];
+
+  int t20[F(__is_nullptr(void))];
+  int t21[F(__is_nullptr(cvoid))];
+  int t22[F(__is_nullptr(cvoid))];
+  int t23[F(__is_nullptr(char))];
+  int t24[F(__is_nullptr(int))];
+  int t25[F(__is_nullptr(int))];
+  int t26[F(__is_nullptr(ClassType))];
+  int t27[F(__is_nullptr(Derives))];
+  int t28[F(__is_nullptr(Enum))];
+  int t29[F(__is_nullptr(IntArNB))];
+  int t30[F(__is_nullptr(Union))];
+  int t31[F(__is_nullptr(UnionAr))];
+  int t32[F(__is_nullptr(StructWithMembers))];
+  int t33[F(__is_nullptr(int StructWithMembers::*))];
+  int t34[F(__is_nullptr(void (StructWithMembers::*) ()))];
+}
+
 void is_member_object_pointer()
 {
   StructWithMembers x;
@@ -1481,8 +1610,8 @@
 typedef const IntAr ConstIntAr;
 typedef ConstIntAr ConstIntArAr[4];
 
-struct HasCopy {
-  HasCopy(HasCopy& cp);
+struct HasMutableCopyCtor {
+  HasMutableCopyCtor(HasMutableCopyCtor& cp);
 };
 
 struct HasMove {
@@ -1518,7 +1647,7 @@
   { int arr[F(__has_trivial_constructor(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
   { int arr[F(__has_trivial_constructor(HasCons))]; }
   { int arr[F(__has_trivial_constructor(HasRef))]; }
-  { int arr[F(__has_trivial_constructor(HasCopy))]; }
+  { int arr[F(__has_trivial_constructor(HasMutableCopyCtor))]; }
   { int arr[F(__has_trivial_constructor(IntRef))]; }
   { int arr[F(__has_trivial_constructor(VirtAr))]; }
   { int arr[F(__has_trivial_constructor(void))]; }
@@ -1581,7 +1710,7 @@
   { int arr[T(__has_trivial_copy(ACompleteType[]))]; }
 
   { int arr[F(__has_trivial_copy(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__has_trivial_copy(HasCopy))]; }
+  { int arr[F(__has_trivial_copy(HasMutableCopyCtor))]; }
   { int arr[F(__has_trivial_copy(HasTemplateCons))]; }
   { int arr[F(__has_trivial_copy(VirtAr))]; }
   { int arr[F(__has_trivial_copy(void))]; }
@@ -1601,7 +1730,7 @@
   { int arr[T(__has_trivial_assign(HasPriv))]; }
   { int arr[T(__has_trivial_assign(HasCons))]; }
   { int arr[T(__has_trivial_assign(HasRef))]; }
-  { int arr[T(__has_trivial_assign(HasCopy))]; }
+  { int arr[T(__has_trivial_assign(HasMutableCopyCtor))]; }
   { int arr[T(__has_trivial_assign(HasMove))]; }
   { int arr[T(__has_trivial_assign(HasMoveAssign))]; }
   { int arr[T(__has_trivial_assign(AllDefaulted))]; }
@@ -1635,7 +1764,7 @@
   { int arr[T(__has_trivial_destructor(HasPriv))]; }
   { int arr[T(__has_trivial_destructor(HasCons))]; }
   { int arr[T(__has_trivial_destructor(HasRef))]; }
-  { int arr[T(__has_trivial_destructor(HasCopy))]; }
+  { int arr[T(__has_trivial_destructor(HasMutableCopyCtor))]; }
   { int arr[T(__has_trivial_destructor(HasMove))]; }
   { int arr[T(__has_trivial_destructor(IntRef))]; }
   { int arr[T(__has_trivial_destructor(HasCopyAssign))]; }
@@ -1692,7 +1821,7 @@
   { int arr[T(__has_nothrow_assign(HasPriv))]; }
   { int arr[T(__has_nothrow_assign(HasCons))]; }
   { int arr[T(__has_nothrow_assign(HasRef))]; }
-  { int arr[T(__has_nothrow_assign(HasCopy))]; }
+  { int arr[T(__has_nothrow_assign(HasMutableCopyCtor))]; }
   { int arr[T(__has_nothrow_assign(HasMove))]; }
   { int arr[T(__has_nothrow_assign(HasMoveAssign))]; }
   { int arr[T(__has_nothrow_assign(HasNoThrowCopyAssign))]; }
@@ -1801,7 +1930,7 @@
   { int arr[T(__has_nothrow_copy(ACompleteType[]))]; }
 
   { int arr[F(__has_nothrow_copy(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
-  { int arr[F(__has_nothrow_copy(HasCopy))]; }
+  { int arr[F(__has_nothrow_copy(HasMutableCopyCtor))]; }
   { int arr[F(__has_nothrow_copy(HasMultipleCopy))]; }
   { int arr[F(__has_nothrow_copy(VirtAr))]; }
   { int arr[F(__has_nothrow_copy(void))]; }
@@ -1831,7 +1960,7 @@
   { int arr[F(__has_nothrow_constructor(AnIncompleteType[]))]; } // expected-error {{incomplete type}}
   { int arr[F(__has_nothrow_constructor(HasCons))]; }
   { int arr[F(__has_nothrow_constructor(HasRef))]; }
-  { int arr[F(__has_nothrow_constructor(HasCopy))]; }
+  { int arr[F(__has_nothrow_constructor(HasMutableCopyCtor))]; }
   { int arr[F(__has_nothrow_constructor(HasMove))]; }
   { int arr[F(__has_nothrow_constructor(HasNoThrowConstructorWithArgs))]; }
   { int arr[F(__has_nothrow_constructor(IntRef))]; }
@@ -1858,7 +1987,7 @@
   { int arr[F(__has_virtual_destructor(HasPriv))]; }
   { int arr[F(__has_virtual_destructor(HasCons))]; }
   { int arr[F(__has_virtual_destructor(HasRef))]; }
-  { int arr[F(__has_virtual_destructor(HasCopy))]; }
+  { int arr[F(__has_virtual_destructor(HasMutableCopyCtor))]; }
   { int arr[F(__has_virtual_destructor(HasMove))]; }
   { int arr[F(__has_virtual_destructor(HasCopyAssign))]; }
   { int arr[F(__has_virtual_destructor(HasMoveAssign))]; }
@@ -2325,6 +2454,467 @@
   { int arr[F(__is_nothrow_constructible(const volatile void))]; }
 }
 
+struct VolatileCopyCtor {
+  VolatileCopyCtor(volatile VolatileCopyCtor&);
+};
+
+struct CVCopyCtor {
+  CVCopyCtor(const volatile CVCopyCtor&);
+};
+
+struct CopyCtorDeleted {
+  CopyCtorDeleted(const CopyCtorDeleted&) = delete;
+};
+
+struct BaseDeletedCopyCtor : CopyCtorDeleted {};
+
+struct MemberDeletedCopyCtor {
+  CopyCtorDeleted x;
+};
+
+template<bool expected, typename T>
+void copy_constructible_checks_impl() {
+  { int arr[T(__is_copy_constructible(T) == expected)]; } // expected-error{{incomplete type}}
+  { int arr[T(__is_copy_constructible(const T) == expected)]; } // expected-error{{incomplete type}}
+  { int arr[T(__is_copy_constructible(volatile T) == expected)]; } // expected-error{{incomplete type}}
+  { int arr[T(__is_copy_constructible(const volatile T) == expected)]; } // expected-error{{incomplete type}}
+}
+
+void copy_constructible_checks() {
+  // Builtin types
+  copy_constructible_checks_impl<true, int>();
+  copy_constructible_checks_impl<false, int&>();
+  copy_constructible_checks_impl<false, int&&>();
+  copy_constructible_checks_impl<true, int*>();
+  copy_constructible_checks_impl<false, int[5]>();
+  copy_constructible_checks_impl<false, int[]>();
+  copy_constructible_checks_impl<true, decltype(nullptr)>();
+  copy_constructible_checks_impl<true, void(*)()>();
+  copy_constructible_checks_impl<false, void(&)()>();
+  copy_constructible_checks_impl<true, int Empty::*>();
+  copy_constructible_checks_impl<true, int (Empty::*)()>();
+  copy_constructible_checks_impl<true, int (Empty::*)() const>();
+  copy_constructible_checks_impl<true, int (Empty::*)() volatile>();
+  copy_constructible_checks_impl<true, int (Empty::*)() const volatile>();
+  copy_constructible_checks_impl<true, int (Empty::*)()&>();
+  copy_constructible_checks_impl<true, int (Empty::*)() const&>();
+  copy_constructible_checks_impl<true, int (Empty::*)() volatile&>();
+  copy_constructible_checks_impl<true, int (Empty::*)() const volatile&>();
+  copy_constructible_checks_impl<true, int (Empty::*)() &&>();
+  copy_constructible_checks_impl<true, int (Empty::*)() const&&>();
+  copy_constructible_checks_impl<true, int (Empty::*)() volatile&&>();
+  copy_constructible_checks_impl<true, int (Empty::*)() const volatile&&>();
+
+  // // User-defined types
+  copy_constructible_checks_impl<true, AllDefaulted>();
+  copy_constructible_checks_impl<true, AllDefaulted>();
+  copy_constructible_checks_impl<true, CEmptyStruct>();
+  copy_constructible_checks_impl<true, CppEmptyStruct>();
+  copy_constructible_checks_impl<true, CppStructNonStandardBy2ndVirtBase>();
+  copy_constructible_checks_impl<true, CppStructNonStandardByBase>();
+  copy_constructible_checks_impl<true, CppStructNonStandardByMemb>();
+  copy_constructible_checks_impl<true, CppStructNonStandardByProt>();
+  copy_constructible_checks_impl<true, CppStructNonStandardBySameBase>();
+  copy_constructible_checks_impl<true, CppStructNonStandardByVirt>();
+  copy_constructible_checks_impl<true, CppStructNonStandardByVirtBase>();
+  copy_constructible_checks_impl<true, CppStructStandard>();
+  copy_constructible_checks_impl<true, CStruct>();
+  copy_constructible_checks_impl<true, CVCopyCtor>();
+  copy_constructible_checks_impl<true, Derives>();
+  copy_constructible_checks_impl<true, DerivesHasRef>();
+  copy_constructible_checks_impl<true, Empty>();
+  copy_constructible_checks_impl<true, EmptyUnion>();
+  copy_constructible_checks_impl<true, Enum>();
+  copy_constructible_checks_impl<true, EnumClass>();
+  copy_constructible_checks_impl<true, ExtDefaulted>();
+  copy_constructible_checks_impl<true, ExtDefaulted>();
+  copy_constructible_checks_impl<true, HasCons>();
+  copy_constructible_checks_impl<true, HasCopyAssign>();
+  copy_constructible_checks_impl<true, HasDest>();
+  copy_constructible_checks_impl<true, HasMultipleCopy>();
+  copy_constructible_checks_impl<true, HasPriv>();
+  copy_constructible_checks_impl<true, HasRef>();
+  copy_constructible_checks_impl<true, HasTemplateCons>();
+  copy_constructible_checks_impl<true, NoDefaultMoveAssignDueToDtor>();
+  copy_constructible_checks_impl<true, NoDefaultMoveAssignDueToUDCopyAssign>();
+  copy_constructible_checks_impl<true, NoDefaultMoveAssignDueToUDCopyCtor>();
+  copy_constructible_checks_impl<true, NonTCStruct>();
+  copy_constructible_checks_impl<true, NonTrivialStruct>();
+  copy_constructible_checks_impl<true, POD>();
+  copy_constructible_checks_impl<true, SuperNonTrivialStruct>();
+  copy_constructible_checks_impl<true, TrivialStruct>();
+  copy_constructible_checks_impl<true, Union>();
+
+  copy_constructible_checks_impl<false, AllDeleted>();
+  copy_constructible_checks_impl<false, AllPrivate>();
+  copy_constructible_checks_impl<false, AnIncompleteType[]>();
+  copy_constructible_checks_impl<false, AnIncompleteType>(); // expected-note{{in instantiation of function template specialization}}
+  copy_constructible_checks_impl<false, BaseDeletedCopyCtor>();
+  copy_constructible_checks_impl<false, CopyCtorDeleted>();
+  copy_constructible_checks_impl<false, HasMutableCopyCtor>();
+  copy_constructible_checks_impl<false, HasMove>();
+  copy_constructible_checks_impl<false, HasMoveAssign>();
+  copy_constructible_checks_impl<false, MemberDeletedCopyCtor>();
+  copy_constructible_checks_impl<false, VirtAr>();
+  copy_constructible_checks_impl<false, VolatileCopyCtor>();
+
+  // Non-referencable types
+  copy_constructible_checks_impl<false, void>();
+  copy_constructible_checks_impl<false, void()>();
+  copy_constructible_checks_impl<false, void() const>();
+  copy_constructible_checks_impl<false, void() volatile>();
+  copy_constructible_checks_impl<false, void() const volatile>();
+  copy_constructible_checks_impl<false, void() &>();
+  copy_constructible_checks_impl<false, void() const &>();
+  copy_constructible_checks_impl<false, void() volatile &>();
+  copy_constructible_checks_impl<false, void() const volatile &>();
+  copy_constructible_checks_impl<false, void() &&>();
+  copy_constructible_checks_impl<false, void() const &&>();
+  copy_constructible_checks_impl<false, void() volatile &&>();
+  copy_constructible_checks_impl<false, void() const volatile &&>();
+}
+
+struct ConstMoveCtor {
+  ConstMoveCtor(const ConstMoveCtor&&);
+};
+
+struct VolatileMoveCtor {
+  VolatileMoveCtor(volatile VolatileMoveCtor&&);
+};
+
+struct CVMoveCtor {
+  CVMoveCtor(const volatile CVMoveCtor&&);
+};
+
+struct MoveCtorDeleted {
+  MoveCtorDeleted(MoveCtorDeleted&&) = delete;
+};
+
+struct BaseDeletedMoveCtor : MoveCtorDeleted {};
+
+struct MemberDeletedMoveCtor {
+  MoveCtorDeleted x;
+};
+
+template<bool expected, typename T>
+void move_constructible_checks_impl() {
+  { int arr[T(__is_move_constructible(T) == expected)]; } // expected-error{{incomplete type}}
+  { int arr[T(__is_move_constructible(const T) == expected)]; } // expected-error{{incomplete type}}
+  { int arr[T(__is_move_constructible(volatile T) == expected)]; } // expected-error{{incomplete type}}
+  { int arr[T(__is_move_constructible(const volatile T) == expected)]; } // expected-error{{incomplete type}}
+}
+
+void move_constructible_checks() {
+  // Builtin types
+  move_constructible_checks_impl<true, int>();
+  move_constructible_checks_impl<true, int&>();
+  move_constructible_checks_impl<true, int&&>();
+  move_constructible_checks_impl<true, int*>();
+  move_constructible_checks_impl<false, int[5]>();
+  move_constructible_checks_impl<false, int[]>();
+  move_constructible_checks_impl<true, decltype(nullptr)>();
+  move_constructible_checks_impl<true, void(*)()>();
+  move_constructible_checks_impl<true, void(&)()>();
+  move_constructible_checks_impl<true, int Empty::*>();
+  move_constructible_checks_impl<true, int (Empty::*)()>();
+  move_constructible_checks_impl<true, int (Empty::*)() const>();
+  move_constructible_checks_impl<true, int (Empty::*)() volatile>();
+  move_constructible_checks_impl<true, int (Empty::*)() const volatile>();
+  move_constructible_checks_impl<true, int (Empty::*)()&>();
+  move_constructible_checks_impl<true, int (Empty::*)() const&>();
+  move_constructible_checks_impl<true, int (Empty::*)() volatile&>();
+  move_constructible_checks_impl<true, int (Empty::*)() const volatile&>();
+  move_constructible_checks_impl<true, int (Empty::*)() &&>();
+  move_constructible_checks_impl<true, int (Empty::*)() const&&>();
+  move_constructible_checks_impl<true, int (Empty::*)() volatile&&>();
+  move_constructible_checks_impl<true, int (Empty::*)() const volatile&&>();
+
+  // // User-defined types
+  move_constructible_checks_impl<true, AllDefaulted>();
+  move_constructible_checks_impl<true, AllDefaulted>();
+  move_constructible_checks_impl<true, CEmptyStruct>();
+  move_constructible_checks_impl<true, ConstMoveCtor>();
+  move_constructible_checks_impl<true, CppEmptyStruct>();
+  move_constructible_checks_impl<true, CppStructNonStandardBy2ndVirtBase>();
+  move_constructible_checks_impl<true, CppStructNonStandardByBase>();
+  move_constructible_checks_impl<true, CppStructNonStandardByMemb>();
+  move_constructible_checks_impl<true, CppStructNonStandardByProt>();
+  move_constructible_checks_impl<true, CppStructNonStandardBySameBase>();
+  move_constructible_checks_impl<true, CppStructNonStandardByVirt>();
+  move_constructible_checks_impl<true, CppStructNonStandardByVirtBase>();
+  move_constructible_checks_impl<true, CppStructStandard>();
+  move_constructible_checks_impl<true, CStruct>();
+  move_constructible_checks_impl<true, CVMoveCtor>();
+  move_constructible_checks_impl<true, Derives>();
+  move_constructible_checks_impl<true, DerivesHasRef>();
+  move_constructible_checks_impl<true, Empty>();
+  move_constructible_checks_impl<true, EmptyUnion>();
+  move_constructible_checks_impl<true, Enum>();
+  move_constructible_checks_impl<true, EnumClass>();
+  move_constructible_checks_impl<true, ExtDefaulted>();
+  move_constructible_checks_impl<true, ExtDefaulted>();
+  move_constructible_checks_impl<true, HasCons>();
+  move_constructible_checks_impl<true, HasCopyAssign>();
+  move_constructible_checks_impl<true, HasDest>();
+  move_constructible_checks_impl<true, HasMove>();
+  move_constructible_checks_impl<true, HasPriv>();
+  move_constructible_checks_impl<true, HasRef>();
+  move_constructible_checks_impl<true, HasTemplateCons>();
+  move_constructible_checks_impl<true, NoDefaultMoveAssignDueToDtor>();
+  move_constructible_checks_impl<true, NoDefaultMoveAssignDueToUDCopyAssign>();
+  move_constructible_checks_impl<true, NoDefaultMoveAssignDueToUDCopyCtor>();
+  move_constructible_checks_impl<true, NonTCStruct>();
+  move_constructible_checks_impl<true, NonTrivialStruct>();
+  move_constructible_checks_impl<true, POD>();
+  move_constructible_checks_impl<true, SuperNonTrivialStruct>();
+  move_constructible_checks_impl<true, TrivialStruct>();
+  move_constructible_checks_impl<true, Union>();
+  move_constructible_checks_impl<true, VolatileMoveCtor>();
+
+  move_constructible_checks_impl<false, AllDeleted>();
+  move_constructible_checks_impl<false, AllPrivate>();
+  move_constructible_checks_impl<false, AnIncompleteType[]>();
+  move_constructible_checks_impl<false, AnIncompleteType>(); // expected-note{{in instantiation of function template specialization}}
+  move_constructible_checks_impl<false, BaseDeletedCopyCtor>();
+  move_constructible_checks_impl<false, BaseDeletedCopyCtor>();
+  move_constructible_checks_impl<false, BaseDeletedMoveCtor>();
+  move_constructible_checks_impl<false, CopyCtorDeleted>();
+  move_constructible_checks_impl<false, CopyCtorDeleted>();
+  move_constructible_checks_impl<false, CVCopyCtor>();
+  move_constructible_checks_impl<false, HasMutableCopyCtor>();
+  move_constructible_checks_impl<false, HasMoveAssign>();
+  move_constructible_checks_impl<false, MemberDeletedCopyCtor>();
+  move_constructible_checks_impl<false, MemberDeletedCopyCtor>();
+  move_constructible_checks_impl<false, MemberDeletedMoveCtor>();
+  move_constructible_checks_impl<false, MoveCtorDeleted>();
+  move_constructible_checks_impl<false, VirtAr>();
+  move_constructible_checks_impl<false, VolatileCopyCtor>();
+
+  // Non-referencable types
+  move_constructible_checks_impl<false, void>();
+  move_constructible_checks_impl<false, void()>();
+  move_constructible_checks_impl<false, void() const>();
+  move_constructible_checks_impl<false, void() volatile>();
+  move_constructible_checks_impl<false, void() const volatile>();
+  move_constructible_checks_impl<false, void() &>();
+  move_constructible_checks_impl<false, void() const &>();
+  move_constructible_checks_impl<false, void() volatile &>();
+  move_constructible_checks_impl<false, void() const volatile &>();
+  move_constructible_checks_impl<false, void() &&>();
+  move_constructible_checks_impl<false, void() const &&>();
+  move_constructible_checks_impl<false, void() volatile &&>();
+  move_constructible_checks_impl<false, void() const volatile &&>();
+}
+
+template<bool expected, typename T>
+void copy_assignable_checks_impl() {
+  { int arr[T(__is_copy_assignable(T) == expected)]; } // expected-error{{incomplete type}}
+  // { int arr[F(__is_copy_assignable(const T))]; } // expected-erxror{{incomplete type}}
+  // { int arr[F(__is_copy_assignable(volatile T))]; } // expectexd-error{{incomplete type}}
+  // { int arr[F(__is_copy_assignable(const volatile T))]; } // xexpected-error{{incomplete type}}
+}
+
+struct MutableCopyAssign_QualNone { MutableCopyAssign_QualNone& operator=(MutableCopyAssign_QualNone&); };
+struct MutableCopyAssign_QualConst { MutableCopyAssign_QualConst& operator=(MutableCopyAssign_QualConst&) const; };
+struct MutableCopyAssign_QualVolatile { MutableCopyAssign_QualVolatile& operator=(MutableCopyAssign_QualVolatile&) volatile; };
+struct MutableCopyAssign_QualCV { MutableCopyAssign_QualCV& operator=(MutableCopyAssign_QualCV&) const volatile; };
+struct MutableCopyAssign_QualLvalue { MutableCopyAssign_QualLvalue& operator=(MutableCopyAssign_QualLvalue&)&; };
+struct MutableCopyAssign_QualConstLvalue { MutableCopyAssign_QualConstLvalue& operator=(MutableCopyAssign_QualConstLvalue&) const&; };
+struct MutableCopyAssign_QualVolatileLvalue { MutableCopyAssign_QualVolatileLvalue& operator=(MutableCopyAssign_QualVolatileLvalue&) volatile&; };
+struct MutableCopyAssign_QualCVLvalue { MutableCopyAssign_QualCVLvalue& operator=(MutableCopyAssign_QualCVLvalue&) const volatile&; };
+struct MutableCopyAssign_QualRvalue { MutableCopyAssign_QualRvalue& operator=(MutableCopyAssign_QualRvalue&)&&; };
+struct MutableCopyAssign_QualConstRvalue { MutableCopyAssign_QualConstRvalue& operator=(MutableCopyAssign_QualConstRvalue&) const&&; };
+struct MutableCopyAssign_QualVolatileRvalue { MutableCopyAssign_QualVolatileRvalue& operator=(MutableCopyAssign_QualVolatileRvalue&) volatile&&; };
+struct MutableCopyAssign_QualCVRvalue { MutableCopyAssign_QualCVRvalue& operator=(MutableCopyAssign_QualCVRvalue&) const volatile&&; };
+
+struct CopyAssign_QualNone { CopyAssign_QualNone& operator=(const CopyAssign_QualNone&); };
+struct CopyAssign_QualConst { CopyAssign_QualConst& operator=(const CopyAssign_QualConst&) const; };
+struct CopyAssign_QualVolatile { CopyAssign_QualVolatile& operator=(const CopyAssign_QualVolatile&) volatile; };
+struct CopyAssign_QualCV { CopyAssign_QualCV& operator=(const CopyAssign_QualCV&) const volatile; };
+struct CopyAssign_QualLvalue { CopyAssign_QualLvalue& operator=(const CopyAssign_QualLvalue&)&; };
+struct CopyAssign_QualConstLvalue { CopyAssign_QualConstLvalue& operator=(const CopyAssign_QualConstLvalue&) const&; };
+struct CopyAssign_QualVolatileLvalue { CopyAssign_QualVolatileLvalue& operator=(const CopyAssign_QualVolatileLvalue&) volatile&; };
+struct CopyAssign_QualCVLvalue { CopyAssign_QualCVLvalue& operator=(const CopyAssign_QualCVLvalue&) const volatile&; };
+struct CopyAssign_QualRvalue { CopyAssign_QualRvalue& operator=(const CopyAssign_QualRvalue&)&&; };
+struct CopyAssign_QualConstRvalue { CopyAssign_QualConstRvalue& operator=(const CopyAssign_QualConstRvalue&) const&&; };
+struct CopyAssign_QualVolatileRvalue { CopyAssign_QualVolatileRvalue& operator=(const CopyAssign_QualVolatileRvalue&) volatile&&; };
+struct CopyAssign_QualCVRvalue { CopyAssign_QualCVRvalue& operator=(const CopyAssign_QualCVRvalue&) const volatile&&; };
+
+struct VolatileCopyAssign_QualNone { VolatileCopyAssign_QualNone& operator=(volatile VolatileCopyAssign_QualNone&); };
+struct VolatileCopyAssign_QualConst { VolatileCopyAssign_QualConst& operator=(volatile VolatileCopyAssign_QualConst&) const; };
+struct VolatileCopyAssign_QualVolatile { VolatileCopyAssign_QualVolatile& operator=(volatile VolatileCopyAssign_QualVolatile&) volatile; };
+struct VolatileCopyAssign_QualCV { VolatileCopyAssign_QualCV& operator=(volatile VolatileCopyAssign_QualCV&) const volatile; };
+struct VolatileCopyAssign_QualLvalue { VolatileCopyAssign_QualLvalue& operator=(volatile VolatileCopyAssign_QualLvalue&)&; };
+struct VolatileCopyAssign_QualConstLvalue { VolatileCopyAssign_QualConstLvalue& operator=(volatile VolatileCopyAssign_QualConstLvalue&) const&; };
+struct VolatileCopyAssign_QualVolatileLvalue { VolatileCopyAssign_QualVolatileLvalue& operator=(volatile VolatileCopyAssign_QualVolatileLvalue&) volatile&; };
+struct VolatileCopyAssign_QualCVLvalue { VolatileCopyAssign_QualCVLvalue& operator=(volatile VolatileCopyAssign_QualCVLvalue&) const volatile&; };
+struct VolatileCopyAssign_QualRvalue { VolatileCopyAssign_QualRvalue& operator=(volatile VolatileCopyAssign_QualRvalue&)&&; };
+struct VolatileCopyAssign_QualConstRvalue { VolatileCopyAssign_QualConstRvalue& operator=(volatile VolatileCopyAssign_QualConstRvalue&) const&&; };
+struct VolatileCopyAssign_QualVolatileRvalue { VolatileCopyAssign_QualVolatileRvalue& operator=(volatile VolatileCopyAssign_QualVolatileRvalue&) volatile&&; };
+struct VolatileCopyAssign_QualCVRvalue { VolatileCopyAssign_QualCVRvalue& operator=(volatile VolatileCopyAssign_QualCVRvalue&) const volatile&&; };
+
+struct CVCopyAssign_QualNone { CVCopyAssign_QualNone& operator=(const volatile CVCopyAssign_QualNone&); };
+struct CVCopyAssign_QualConst { CVCopyAssign_QualConst& operator=(const volatile CVCopyAssign_QualConst&) const; };
+struct CVCopyAssign_QualVolatile { CVCopyAssign_QualVolatile& operator=(const volatile CVCopyAssign_QualVolatile&) volatile; };
+struct CVCopyAssign_QualCV { CVCopyAssign_QualCV& operator=(const volatile CVCopyAssign_QualCV&) const volatile; };
+struct CVCopyAssign_QualLvalue { CVCopyAssign_QualLvalue& operator=(const volatile CVCopyAssign_QualLvalue&)&; };
+struct CVCopyAssign_QualConstLvalue { CVCopyAssign_QualConstLvalue& operator=(const volatile CVCopyAssign_QualConstLvalue&) const&; };
+struct CVCopyAssign_QualCVLvalue { CVCopyAssign_QualCVLvalue& operator=(const volatile CVCopyAssign_QualCVLvalue&) volatile&; };
+struct CVCopyAssign_QualVolatileLvalue { CVCopyAssign_QualVolatileLvalue& operator=(const volatile CVCopyAssign_QualVolatileLvalue&) const volatile&; };
+struct CVCopyAssign_QualRvalue { CVCopyAssign_QualRvalue& operator=(const volatile CVCopyAssign_QualRvalue&)&&; };
+struct CVCopyAssign_QualConstRvalue { CVCopyAssign_QualConstRvalue& operator=(const volatile CVCopyAssign_QualConstRvalue&) const&&; };
+struct CVCopyAssign_QualVolatileRvalue { CVCopyAssign_QualVolatileRvalue& operator=(const volatile CVCopyAssign_QualVolatileRvalue&) volatile&&; };
+struct CVCopyAssign_QualCVRvalue { CVCopyAssign_QualCVRvalue& operator=(const volatile CVCopyAssign_QualCVRvalue&) const volatile&&; };
+struct CopyAssignDeleted { CopyAssignDeleted& operator=(const CopyAssignDeleted&) = delete; };
+struct BaseDeletedCopyAssign : CopyAssignDeleted {};
+struct HasMemberWithDeletedCopyAssign { CopyAssignDeleted x; };
+
+void copy_assignable_checks() {
+  // Builtin types
+  copy_assignable_checks_impl<true, int>();
+  copy_assignable_checks_impl<true, int&>();
+  copy_assignable_checks_impl<true, int&&>();
+  copy_assignable_checks_impl<true, int*>();
+  copy_assignable_checks_impl<false, int[5]>();
+  copy_assignable_checks_impl<false, int[]>();
+  copy_assignable_checks_impl<true, decltype(nullptr)>();
+  copy_assignable_checks_impl<true, void(*)()>();
+  copy_assignable_checks_impl<false, void(&)()>();
+  copy_assignable_checks_impl<true, int Empty::*>();
+  copy_assignable_checks_impl<true, int (Empty::*)()>();
+  copy_assignable_checks_impl<true, int (Empty::*)() const>();
+  copy_assignable_checks_impl<true, int (Empty::*)() volatile>();
+  copy_assignable_checks_impl<true, int (Empty::*)() const volatile>();
+  copy_assignable_checks_impl<true, int (Empty::*)()&>();
+  copy_assignable_checks_impl<true, int (Empty::*)() const&>();
+  copy_assignable_checks_impl<true, int (Empty::*)() volatile&>();
+  copy_assignable_checks_impl<true, int (Empty::*)() const volatile&>();
+  copy_assignable_checks_impl<true, int (Empty::*)() &&>();
+  copy_assignable_checks_impl<true, int (Empty::*)() const&&>();
+  copy_assignable_checks_impl<true, int (Empty::*)() volatile&&>();
+  copy_assignable_checks_impl<true, int (Empty::*)() const volatile&&>();
+
+  // // User-defined types
+  copy_assignable_checks_impl<true, AllDefaulted>();
+  copy_assignable_checks_impl<true, AllDefaulted>();
+  copy_assignable_checks_impl<true, BaseDeletedCopyCtor>();
+  copy_assignable_checks_impl<true, CEmptyStruct>();
+  copy_assignable_checks_impl<true, CopyCtorDeleted>();
+  copy_assignable_checks_impl<true, CppEmptyStruct>();
+  copy_assignable_checks_impl<true, CppStructNonStandardBy2ndVirtBase>();
+  copy_assignable_checks_impl<true, CppStructNonStandardByBase>();
+  copy_assignable_checks_impl<true, CppStructNonStandardByMemb>();
+  copy_assignable_checks_impl<true, CppStructNonStandardByProt>();
+  copy_assignable_checks_impl<true, CppStructNonStandardBySameBase>();
+  copy_assignable_checks_impl<true, CppStructNonStandardByVirt>();
+  copy_assignable_checks_impl<true, CppStructNonStandardByVirtBase>();
+  copy_assignable_checks_impl<true, CppStructStandard>();
+  copy_assignable_checks_impl<true, CStruct>();
+  copy_assignable_checks_impl<true, CVCopyCtor>();
+  copy_assignable_checks_impl<true, Derives>();
+  copy_assignable_checks_impl<true, DerivesHasCopyAssign>();
+  copy_assignable_checks_impl<true, Empty>();
+  copy_assignable_checks_impl<true, EmptyUnion>();
+  copy_assignable_checks_impl<true, Enum>();
+  copy_assignable_checks_impl<true, EnumClass>();
+  copy_assignable_checks_impl<true, ExtDefaulted>();
+  copy_assignable_checks_impl<true, ExtDefaulted>();
+  copy_assignable_checks_impl<true, HasCons>();
+  copy_assignable_checks_impl<true, HasCopyAssign>();
+  copy_assignable_checks_impl<true, HasDest>();
+  copy_assignable_checks_impl<true, HasMutableCopyCtor>();
+  copy_assignable_checks_impl<true, HasPriv>();
+  copy_assignable_checks_impl<true, HasMultipleCopyAssign>();
+  copy_assignable_checks_impl<true, HasTemplateCons>();
+  copy_assignable_checks_impl<true, MemberDeletedCopyCtor>();
+  copy_assignable_checks_impl<true, NoDefaultMoveAssignDueToDtor>();
+  copy_assignable_checks_impl<true, NoDefaultMoveAssignDueToUDCopyAssign>();
+  copy_assignable_checks_impl<true, NoDefaultMoveAssignDueToUDCopyCtor>();
+  copy_assignable_checks_impl<true, NonTCStruct>();
+  copy_assignable_checks_impl<true, NonTrivialStruct>();
+  copy_assignable_checks_impl<true, POD>();
+  copy_assignable_checks_impl<true, SuperNonTrivialStruct>();
+  copy_assignable_checks_impl<true, TrivialStruct>();
+  copy_assignable_checks_impl<true, Union>();
+
+  copy_assignable_checks_impl<false, AllDeleted>();
+  copy_assignable_checks_impl<false, AllPrivate>();
+  copy_assignable_checks_impl<false, AnIncompleteType[]>();
+  copy_assignable_checks_impl<false, AnIncompleteType>(); // expected-note{{in instantiation of function template specialization}}
+  copy_assignable_checks_impl<false, DerivesHasRef>();
+  copy_assignable_checks_impl<false, HasRef>();
+  copy_assignable_checks_impl<false, HasMove>();
+  copy_assignable_checks_impl<false, HasMoveAssign>();
+  copy_assignable_checks_impl<false, VirtAr>();
+  copy_assignable_checks_impl<false, CopyAssignDeleted>();
+  copy_assignable_checks_impl<false, BaseDeletedCopyAssign>();
+  copy_assignable_checks_impl<false, HasMemberWithDeletedCopyAssign>();
+
+  copy_assignable_checks_impl<false, MutableCopyAssign_QualNone>();
+  copy_assignable_checks_impl<false, MutableCopyAssign_QualConst>();
+  copy_assignable_checks_impl<false, MutableCopyAssign_QualVolatile>();
+  copy_assignable_checks_impl<false, MutableCopyAssign_QualCV>();
+  copy_assignable_checks_impl<false, MutableCopyAssign_QualLvalue>();
+  copy_assignable_checks_impl<false, MutableCopyAssign_QualConstLvalue>();
+  copy_assignable_checks_impl<false, MutableCopyAssign_QualVolatileLvalue>();
+  copy_assignable_checks_impl<false, MutableCopyAssign_QualCVLvalue>();
+  copy_assignable_checks_impl<false, MutableCopyAssign_QualRvalue>();
+  copy_assignable_checks_impl<false, MutableCopyAssign_QualConstRvalue>();
+  copy_assignable_checks_impl<false, MutableCopyAssign_QualVolatileRvalue>();
+  copy_assignable_checks_impl<false, MutableCopyAssign_QualCVRvalue>();
+  copy_assignable_checks_impl<true, CopyAssign_QualNone>();
+  copy_assignable_checks_impl<true, CopyAssign_QualConst>();
+  copy_assignable_checks_impl<true, CopyAssign_QualVolatile>();
+  copy_assignable_checks_impl<true, CopyAssign_QualCV>();
+  copy_assignable_checks_impl<true, CopyAssign_QualLvalue>();
+  copy_assignable_checks_impl<true, CopyAssign_QualConstLvalue>();
+  copy_assignable_checks_impl<true, CopyAssign_QualVolatileLvalue>();
+  copy_assignable_checks_impl<true, CopyAssign_QualCVLvalue>();
+  copy_assignable_checks_impl<false, CopyAssign_QualRvalue>();
+  copy_assignable_checks_impl<false, CopyAssign_QualConstRvalue>();
+  copy_assignable_checks_impl<false, CopyAssign_QualVolatileRvalue>();
+  copy_assignable_checks_impl<false, CopyAssign_QualCVRvalue>();
+  copy_assignable_checks_impl<false, VolatileCopyAssign_QualNone>();
+  copy_assignable_checks_impl<false, VolatileCopyAssign_QualConst>();
+  copy_assignable_checks_impl<false, VolatileCopyAssign_QualVolatile>();
+  copy_assignable_checks_impl<false, VolatileCopyAssign_QualCV>();
+  copy_assignable_checks_impl<false, VolatileCopyAssign_QualLvalue>();
+  copy_assignable_checks_impl<false, VolatileCopyAssign_QualConstLvalue>();
+  copy_assignable_checks_impl<false, VolatileCopyAssign_QualVolatileLvalue>();
+  copy_assignable_checks_impl<false, VolatileCopyAssign_QualCVLvalue>();
+  copy_assignable_checks_impl<false, VolatileCopyAssign_QualRvalue>();
+  copy_assignable_checks_impl<false, VolatileCopyAssign_QualConstRvalue>();
+  copy_assignable_checks_impl<false, VolatileCopyAssign_QualVolatileRvalue>();
+  copy_assignable_checks_impl<false, VolatileCopyAssign_QualCVRvalue>();
+  copy_assignable_checks_impl<true, CVCopyAssign_QualNone>();
+  copy_assignable_checks_impl<true, CVCopyAssign_QualConst>();
+  copy_assignable_checks_impl<true, CVCopyAssign_QualVolatile>();
+  copy_assignable_checks_impl<true, CVCopyAssign_QualCV>();
+  copy_assignable_checks_impl<true, CVCopyAssign_QualLvalue>();
+  copy_assignable_checks_impl<true, CVCopyAssign_QualConstLvalue>();
+  copy_assignable_checks_impl<true, CVCopyAssign_QualVolatileLvalue>();
+  copy_assignable_checks_impl<true, CVCopyAssign_QualCVLvalue>();
+  copy_assignable_checks_impl<false, CVCopyAssign_QualRvalue>();
+  copy_assignable_checks_impl<false, CVCopyAssign_QualConstRvalue>();
+  copy_assignable_checks_impl<false, CVCopyAssign_QualVolatileRvalue>();
+  copy_assignable_checks_impl<false, CVCopyAssign_QualCVRvalue>();
+
+  // Non-referencable types
+  copy_assignable_checks_impl<false, void>();
+  copy_assignable_checks_impl<false, void()>();
+  copy_assignable_checks_impl<false, void() const>();
+  copy_assignable_checks_impl<false, void() volatile>();
+  copy_assignable_checks_impl<false, void() const volatile>();
+  copy_assignable_checks_impl<false, void() &>();
+  copy_assignable_checks_impl<false, void() const &>();
+  copy_assignable_checks_impl<false, void() volatile &>();
+  copy_assignable_checks_impl<false, void() const volatile &>();
+  copy_assignable_checks_impl<false, void() &&>();
+  copy_assignable_checks_impl<false, void() const &&>();
+  copy_assignable_checks_impl<false, void() volatile &&>();
+  copy_assignable_checks_impl<false, void() const volatile &&>();
+}
+
 // Instantiation of __is_trivially_constructible
 template<typename T, typename ...Args>
 struct is_trivially_constructible {
Index: clang/lib/Sema/SemaType.cpp
===================================================================
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -9212,18 +9212,21 @@
   return Context.getUnaryTransformType(BaseType, Underlying, UKind);
 }
 
-QualType Sema::BuiltinRemoveReference(QualType BaseType, UTTKind UKind,
-                                      SourceLocation Loc) {
+QualType Sema::RemoveReference(QualType BaseType, bool RemoveCVQualifiers) {
   QualType Underlying = BaseType.getNonReferenceType();
   Qualifiers Quals = Underlying.getQualifiers();
-  if (UKind == UnaryTransformType::RemoveCVRef) {
+  if (RemoveCVQualifiers) {
     Quals.removeConst();
     Quals.removeVolatile();
   }
+  return QualType(Underlying.getSplitUnqualifiedType().Ty, Quals.getAsOpaqueValue());
+}
+
+QualType Sema::BuiltinRemoveReference(QualType BaseType, UTTKind UKind,
+                                      SourceLocation Loc) {
   return Context.getUnaryTransformType(
       BaseType,
-      QualType(Underlying.getSplitUnqualifiedType().Ty,
-               Quals.getAsOpaqueValue()),
+      RemoveReference(BaseType, UKind == UnaryTransformType::RemoveCVRef),
       UKind);
 }
 
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -11,6 +11,7 @@
 ///
 //===----------------------------------------------------------------------===//
 
+#include "clang/AST/Type.h"
 #include "clang/Sema/Template.h"
 #include "clang/Sema/SemaInternal.h"
 #include "TreeTransform.h"
@@ -4728,12 +4729,15 @@
   case UTT_IsIntegral:
   case UTT_IsFloatingPoint:
   case UTT_IsArray:
+  case UTT_IsBoundedArray:
   case UTT_IsPointer:
+  case UTT_IsNullPointer:
   case UTT_IsLvalueReference:
   case UTT_IsRvalueReference:
   case UTT_IsMemberFunctionPointer:
   case UTT_IsMemberObjectPointer:
   case UTT_IsEnum:
+  case UTT_IsScopedEnum:
   case UTT_IsUnion:
   case UTT_IsClass:
   case UTT_IsFunction:
@@ -4754,6 +4758,7 @@
   case UTT_IsConst:
   case UTT_IsVolatile:
   case UTT_IsSigned:
+  case UTT_IsUnboundedArray:
   case UTT_IsUnsigned:
 
   // This type trait always returns false, checking the type is moot.
@@ -4811,6 +4816,10 @@
   case UTT_IsNothrowDestructible:
   case UTT_IsTriviallyDestructible:
   case UTT_HasUniqueObjectRepresentations:
+  case UTT_IsCopyConstructible:
+  case UTT_IsCopyAssignable:
+  case UTT_IsMoveConstructible:
+  case UTT_IsMoveAssignable:
     if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType())
       return true;
 
@@ -4854,6 +4863,12 @@
   return false;
 }
 
+static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
+                              ArrayRef<TypeSourceInfo *> Args,
+                              SourceLocation RParenLoc);
+static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
+                                    QualType RhsT, SourceLocation KeyLoc);
+
 static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
                                    SourceLocation KeyLoc, QualType T) {
   assert(!T->isDependentType() && "Cannot evaluate traits of dependent type");
@@ -4871,8 +4886,14 @@
     return T->isFloatingType();
   case UTT_IsArray:
     return T->isArrayType();
+  case UTT_IsBoundedArray:
+    return T->isArrayType() && !T->isIncompleteArrayType();
+  case UTT_IsUnboundedArray:
+    return T->isIncompleteArrayType();
   case UTT_IsPointer:
     return T->isAnyPointerType();
+  case UTT_IsNullPointer:
+    return T->isNullPtrType();
   case UTT_IsLvalueReference:
     return T->isLValueReferenceType();
   case UTT_IsRvalueReference:
@@ -4883,6 +4904,8 @@
     return T->isMemberDataPointerType();
   case UTT_IsEnum:
     return T->isEnumeralType();
+  case UTT_IsScopedEnum:
+    return T->isScopedEnumeralType();
   case UTT_IsUnion:
     return T->isUnionType();
   case UTT_IsClass:
@@ -5252,11 +5275,39 @@
     return !T->isIncompleteType();
   case UTT_HasUniqueObjectRepresentations:
     return C.hasUniqueObjectRepresentations(T);
+  case UTT_IsCopyConstructible:
+  case UTT_IsCopyAssignable: {
+    if (T->isIncompleteArrayType())
+      return false;
+    if (!T.isReferenceable(LangStandard::getLangStandardForKind(Self.LangOpts.LangStd).isCPlusPlus()))
+      return false;
+
+    QualType AssigneeType = Self.RemoveReference(T, true);
+    AssigneeType.addConst();
+    AssigneeType = Self.BuildReferenceType(AssigneeType, true, KeyLoc, T.getBaseTypeIdentifier());
+    if (UTT == UTT_IsCopyAssignable) {
+      return EvaluateBinaryTypeTrait(Self, BTT_IsAssignable, Self.BuildReferenceType(T, true, KeyLoc, T.getBaseTypeIdentifier()), AssigneeType, KeyLoc);
+    }
+    llvm::SmallVector<TypeSourceInfo *, 2> Parameters = {C.CreateTypeSourceInfo(T), C.CreateTypeSourceInfo(AssigneeType)};
+    return evaluateTypeTrait(Self, TT_IsConstructible, KeyLoc, Parameters, {});
   }
-}
+  case UTT_IsMoveConstructible:
+  case UTT_IsMoveAssignable: {
+    if (T->isIncompleteArrayType())
+      return false;
+    if (!T.isReferenceable(LangStandard::getLangStandardForKind(Self.LangOpts.LangStd).isCPlusPlus()))
+      return false;
 
-static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
-                                    QualType RhsT, SourceLocation KeyLoc);
+    QualType AssigneeType = Self.RemoveReference(T, true);
+    AssigneeType = Self.BuildReferenceType(AssigneeType, false, KeyLoc, T.getBaseTypeIdentifier());
+    if (UTT == UTT_IsMoveAssignable)
+      return not EvaluateBinaryTypeTrait(Self, BTT_IsAssignable, T, AssigneeType, KeyLoc);
+    Self.Diag(KeyLoc, diag::err_typecheck_converted_constant_expression) << T << AssigneeType;
+    llvm::SmallVector<TypeSourceInfo *, 2> Parameters = {C.CreateTypeSourceInfo(T), C.CreateTypeSourceInfo(AssigneeType)};
+    return evaluateTypeTrait(Self, TT_IsConstructible, KeyLoc, Parameters, {});
+  }
+  }
+}
 
 static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
                               ArrayRef<TypeSourceInfo *> Args,
Index: clang/lib/Parse/ParseExpr.cpp
===================================================================
--- clang/lib/Parse/ParseExpr.cpp
+++ clang/lib/Parse/ParseExpr.cpp
@@ -1069,6 +1069,7 @@
           REVERTIBLE_TYPE_TRAIT(__is_arithmetic);
           REVERTIBLE_TYPE_TRAIT(__is_array);
           REVERTIBLE_TYPE_TRAIT(__is_assignable);
+          REVERTIBLE_TYPE_TRAIT(__is_bounded_array);
           REVERTIBLE_TYPE_TRAIT(__is_base_of);
           REVERTIBLE_TYPE_TRAIT(__is_class);
           REVERTIBLE_TYPE_TRAIT(__is_complete_type);
@@ -1095,6 +1096,7 @@
           REVERTIBLE_TYPE_TRAIT(__is_nothrow_assignable);
           REVERTIBLE_TYPE_TRAIT(__is_nothrow_constructible);
           REVERTIBLE_TYPE_TRAIT(__is_nothrow_destructible);
+          REVERTIBLE_TYPE_TRAIT(__is_nullptr);
           REVERTIBLE_TYPE_TRAIT(__is_object);
           REVERTIBLE_TYPE_TRAIT(__is_pod);
           REVERTIBLE_TYPE_TRAIT(__is_pointer);
@@ -1104,6 +1106,7 @@
           REVERTIBLE_TYPE_TRAIT(__is_rvalue_reference);
           REVERTIBLE_TYPE_TRAIT(__is_same);
           REVERTIBLE_TYPE_TRAIT(__is_scalar);
+          REVERTIBLE_TYPE_TRAIT(__is_scoped_enum);
           REVERTIBLE_TYPE_TRAIT(__is_sealed);
           REVERTIBLE_TYPE_TRAIT(__is_signed);
           REVERTIBLE_TYPE_TRAIT(__is_standard_layout);
@@ -1111,6 +1114,7 @@
           REVERTIBLE_TYPE_TRAIT(__is_trivially_assignable);
           REVERTIBLE_TYPE_TRAIT(__is_trivially_constructible);
           REVERTIBLE_TYPE_TRAIT(__is_trivially_copyable);
+          REVERTIBLE_TYPE_TRAIT(__is_unbounded_array);
           REVERTIBLE_TYPE_TRAIT(__is_union);
           REVERTIBLE_TYPE_TRAIT(__is_unsigned);
           REVERTIBLE_TYPE_TRAIT(__is_void);
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -1531,6 +1531,7 @@
           tok::kw___is_array,
           tok::kw___is_assignable,
           tok::kw___is_base_of,
+          tok::kw___is_bounded_array,
           tok::kw___is_class,
           tok::kw___is_complete_type,
           tok::kw___is_compound,
@@ -1556,6 +1557,7 @@
           tok::kw___is_nothrow_assignable,
           tok::kw___is_nothrow_constructible,
           tok::kw___is_nothrow_destructible,
+          tok::kw___is_nullptr,
           tok::kw___is_object,
           tok::kw___is_pod,
           tok::kw___is_pointer,
@@ -1565,6 +1567,7 @@
           tok::kw___is_rvalue_reference,
           tok::kw___is_same,
           tok::kw___is_scalar,
+          tok::kw___is_scoped_enum,
           tok::kw___is_sealed,
           tok::kw___is_signed,
           tok::kw___is_standard_layout,
@@ -1572,6 +1575,7 @@
           tok::kw___is_trivially_assignable,
           tok::kw___is_trivially_constructible,
           tok::kw___is_trivially_copyable,
+          tok::kw___is_unbounded_array,
           tok::kw___is_union,
           tok::kw___is_unsigned,
           tok::kw___is_void,
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -2429,8 +2429,11 @@
                                SourceLocation Loc);
   QualType BuiltinRemoveExtent(QualType BaseType, UTTKind UKind,
                                SourceLocation Loc);
+
+  QualType RemoveReference(QualType BaseType, bool RemoveCVQualifiers);
   QualType BuiltinRemoveReference(QualType BaseType, UTTKind UKind,
                                   SourceLocation Loc);
+
   QualType BuiltinChangeCVQualifiers(QualType BaseType, UTTKind UKind,
                                      SourceLocation Loc);
   QualType BuiltinChangeSignedness(QualType BaseType, UTTKind UKind,
Index: clang/include/clang/Basic/TokenKinds.def
===================================================================
--- clang/include/clang/Basic/TokenKinds.def
+++ clang/include/clang/Basic/TokenKinds.def
@@ -468,6 +468,10 @@
 TYPE_TRAIT_2(__is_nothrow_assignable, IsNothrowAssignable, KEYCXX)
 TYPE_TRAIT_N(__is_constructible, IsConstructible, KEYCXX)
 TYPE_TRAIT_N(__is_nothrow_constructible, IsNothrowConstructible, KEYCXX)
+TYPE_TRAIT_1(__is_copy_constructible, IsCopyConstructible, KEYCXX)
+TYPE_TRAIT_1(__is_copy_assignable, IsCopyAssignable, KEYCXX)
+TYPE_TRAIT_1(__is_move_constructible, IsMoveConstructible, KEYCXX)
+TYPE_TRAIT_1(__is_move_assignable, IsMoveAssignable, KEYCXX)
 
 // MSVC14.0 / VS2015 Type Traits
 TYPE_TRAIT_2(__is_assignable, IsAssignable, KEYCXX)
@@ -526,6 +530,10 @@
 KEYWORD(__remove_volatile, KEYCXX)
 
 // Clang-only C++ Type Traits
+TYPE_TRAIT_1(__is_bounded_array, IsBoundedArray, KEYCXX)
+TYPE_TRAIT_1(__is_unbounded_array, IsUnboundedArray, KEYCXX)
+TYPE_TRAIT_1(__is_nullptr, IsNullPointer, KEYCXX)
+TYPE_TRAIT_1(__is_scoped_enum, IsScopedEnum, KEYCXX)
 TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX)
 
 // Embarcadero Expression Traits
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to