summaryrefslogtreecommitdiffstats
path: root/test/CXX/special/class.copy
diff options
context:
space:
mode:
Diffstat (limited to 'test/CXX/special/class.copy')
-rw-r--r--test/CXX/special/class.copy/implicit-move.cpp2
-rw-r--r--test/CXX/special/class.copy/p12-0x.cpp216
-rw-r--r--test/CXX/special/class.copy/p18-cxx11.cpp62
-rw-r--r--test/CXX/special/class.copy/p23-cxx11.cpp2
-rw-r--r--test/CXX/special/class.copy/p25-0x.cpp202
-rw-r--r--test/CXX/special/class.copy/p28-cxx11.cpp19
6 files changed, 501 insertions, 2 deletions
diff --git a/test/CXX/special/class.copy/implicit-move.cpp b/test/CXX/special/class.copy/implicit-move.cpp
index 597e327..3337412 100644
--- a/test/CXX/special/class.copy/implicit-move.cpp
+++ b/test/CXX/special/class.copy/implicit-move.cpp
@@ -54,7 +54,7 @@ void test_basic_exclusion() {
static_assert(noexcept(HasMoveConstructor((HasMoveConstructor()))), "");
HasMoveConstructor hmc;
- hmc = HasMoveConstructor(); // expected-error {{selected implicitly-deleted copy assignment}}
+ hmc = HasMoveConstructor(); // expected-error {{object of type 'HasMoveConstructor' cannot be assigned because its copy assignment operator is implicitly deleted}}
(HasMoveAssignment(HasMoveAssignment())); // expected-error {{uses deleted function}}
HasMoveAssignment hma;
diff --git a/test/CXX/special/class.copy/p12-0x.cpp b/test/CXX/special/class.copy/p12-0x.cpp
new file mode 100644
index 0000000..17b3191
--- /dev/null
+++ b/test/CXX/special/class.copy/p12-0x.cpp
@@ -0,0 +1,216 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+
+// expected-no-diagnostics
+
+template<typename T, bool B> struct trivially_copyable_check {
+ static_assert(B == __has_trivial_copy(T), "");
+ static_assert(B == __is_trivially_constructible(T, T), "");
+ static_assert(B == __is_trivially_constructible(T, const T &), "");
+ static_assert(B == __is_trivially_constructible(T, T &&), "");
+ typedef void type;
+};
+template<typename T> using trivially_copyable =
+ typename trivially_copyable_check<T, true>::type;
+template<typename T> using not_trivially_copyable =
+ typename trivially_copyable_check<T, false>::type;
+
+struct Trivial {};
+using _ = trivially_copyable<Trivial>;
+
+// A copy/move constructor for class X is trivial if it is not user-provided,
+struct UserProvided {
+ UserProvided(const UserProvided &);
+};
+using _ = not_trivially_copyable<UserProvided>;
+
+// its declared parameter type is the same as if it had been implicitly
+// declared,
+struct NonConstCopy {
+ NonConstCopy(NonConstCopy &) = default;
+};
+using _ = not_trivially_copyable<NonConstCopy>;
+
+// class X has no virtual functions
+struct VFn {
+ virtual void f();
+};
+using _ = not_trivially_copyable<VFn>;
+
+// and no virtual base classes
+struct VBase : virtual Trivial {};
+using _ = not_trivially_copyable<VBase>;
+
+// and the constructor selected to copy/move each [direct subobject] is trivial
+struct TemplateCtor {
+ template<typename T> TemplateCtor(T &);
+};
+using _ = trivially_copyable<TemplateCtor>;
+struct TemplateCtorMember {
+ TemplateCtor tc;
+};
+using _ = trivially_copyable<TemplateCtorMember>;
+
+// We can select a non-trivial copy ctor even if there is a trivial one.
+struct MutableTemplateCtorMember {
+ mutable TemplateCtor mtc;
+};
+static_assert(!__is_trivially_constructible(MutableTemplateCtorMember, const MutableTemplateCtorMember &), "");
+static_assert(__is_trivially_constructible(MutableTemplateCtorMember, MutableTemplateCtorMember &&), "");
+struct MutableTemplateCtorMember2 {
+ MutableTemplateCtorMember2(const MutableTemplateCtorMember2 &) = default;
+ MutableTemplateCtorMember2(MutableTemplateCtorMember2 &&) = default;
+ mutable TemplateCtor mtc;
+};
+static_assert(!__is_trivially_constructible(MutableTemplateCtorMember2, const MutableTemplateCtorMember2 &), "");
+static_assert(__is_trivially_constructible(MutableTemplateCtorMember2, MutableTemplateCtorMember2 &&), "");
+
+// Both trivial and non-trivial special members.
+struct TNT {
+ TNT(const TNT &) = default; // trivial
+ TNT(TNT &); // non-trivial
+
+ TNT(TNT &&) = default; // trivial
+ TNT(const TNT &&); // non-trivial
+};
+
+static_assert(!__has_trivial_copy(TNT), "lie deliberately for gcc compatibility");
+static_assert(__is_trivially_constructible(TNT, TNT), "");
+static_assert(!__is_trivially_constructible(TNT, TNT &), "");
+static_assert(__is_trivially_constructible(TNT, const TNT &), "");
+static_assert(!__is_trivially_constructible(TNT, volatile TNT &), "");
+static_assert(__is_trivially_constructible(TNT, TNT &&), "");
+static_assert(!__is_trivially_constructible(TNT, const TNT &&), "");
+static_assert(!__is_trivially_constructible(TNT, volatile TNT &&), "");
+
+// This has only trivial special members.
+struct DerivedFromTNT : TNT {};
+
+static_assert(__has_trivial_copy(DerivedFromTNT), "");
+static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT), "");
+static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT &), "");
+static_assert(__is_trivially_constructible(DerivedFromTNT, const DerivedFromTNT &), "");
+static_assert(!__is_trivially_constructible(DerivedFromTNT, volatile DerivedFromTNT &), "");
+static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT &&), "");
+static_assert(__is_trivially_constructible(DerivedFromTNT, const DerivedFromTNT &&), "");
+static_assert(!__is_trivially_constructible(DerivedFromTNT, volatile DerivedFromTNT &&), "");
+
+// This has only trivial special members.
+struct TNTMember {
+ TNT tnt;
+};
+
+static_assert(__has_trivial_copy(TNTMember), "");
+static_assert(__is_trivially_constructible(TNTMember, TNTMember), "");
+static_assert(__is_trivially_constructible(TNTMember, TNTMember &), "");
+static_assert(__is_trivially_constructible(TNTMember, const TNTMember &), "");
+static_assert(!__is_trivially_constructible(TNTMember, volatile TNTMember &), "");
+static_assert(__is_trivially_constructible(TNTMember, TNTMember &&), "");
+static_assert(__is_trivially_constructible(TNTMember, const TNTMember &&), "");
+static_assert(!__is_trivially_constructible(TNTMember, volatile TNTMember &&), "");
+
+struct NCCTNT : NonConstCopy, TNT {};
+
+static_assert(!__has_trivial_copy(NCCTNT), "");
+static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT), "");
+static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT &), "");
+static_assert(!__is_trivially_constructible(NCCTNT, const NCCTNT &), "");
+static_assert(!__is_trivially_constructible(NCCTNT, volatile NCCTNT &), "");
+static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT &&), "");
+static_assert(!__is_trivially_constructible(NCCTNT, const NCCTNT &&), "");
+static_assert(!__is_trivially_constructible(NCCTNT, volatile NCCTNT &&), "");
+
+struct TemplateCtorNoMove {
+ TemplateCtorNoMove(const TemplateCtorNoMove &) = default;
+ template<typename T> TemplateCtorNoMove(T &&);
+};
+static_assert(__is_trivially_constructible(TemplateCtorNoMove, const TemplateCtorNoMove &), "");
+static_assert(!__is_trivially_constructible(TemplateCtorNoMove, TemplateCtorNoMove &&), "");
+
+struct UseTemplateCtorNoMove {
+ TemplateCtorNoMove tcnm;
+};
+static_assert(__is_trivially_constructible(UseTemplateCtorNoMove, const UseTemplateCtorNoMove &), "");
+static_assert(!__is_trivially_constructible(UseTemplateCtorNoMove, UseTemplateCtorNoMove &&), "");
+
+struct TemplateCtorNoMoveSFINAE {
+ TemplateCtorNoMoveSFINAE(const TemplateCtorNoMoveSFINAE &) = default;
+ template<typename T, typename U = typename T::error> TemplateCtorNoMoveSFINAE(T &&);
+};
+static_assert(__is_trivially_constructible(TemplateCtorNoMoveSFINAE, const TemplateCtorNoMoveSFINAE &), "");
+static_assert(__is_trivially_constructible(TemplateCtorNoMoveSFINAE, TemplateCtorNoMoveSFINAE &&), "");
+
+struct UseTemplateCtorNoMoveSFINAE {
+ TemplateCtorNoMoveSFINAE tcnm;
+};
+static_assert(__is_trivially_constructible(UseTemplateCtorNoMoveSFINAE, const UseTemplateCtorNoMoveSFINAE &), "");
+static_assert(__is_trivially_constructible(UseTemplateCtorNoMoveSFINAE, UseTemplateCtorNoMoveSFINAE &&), "");
+
+namespace TrivialityDependsOnImplicitDeletion {
+ struct PrivateMove {
+ PrivateMove(const PrivateMove &) = default;
+ private:
+ PrivateMove(PrivateMove &&);
+ friend class Access;
+ };
+ static_assert(__is_trivially_constructible(PrivateMove, const PrivateMove &), "");
+ static_assert(!__is_trivially_constructible(PrivateMove, PrivateMove &&), "");
+
+ struct NoAccess {
+ PrivateMove pm;
+ // NoAccess's move would be deleted, so is suppressed,
+ // so moves of it use PrivateMove's copy ctor, which is trivial.
+ };
+ static_assert(__is_trivially_constructible(NoAccess, const NoAccess &), "");
+ static_assert(__is_trivially_constructible(NoAccess, NoAccess &&), "");
+ struct TopNoAccess : NoAccess {};
+ static_assert(__is_trivially_constructible(TopNoAccess, const TopNoAccess &), "");
+ static_assert(__is_trivially_constructible(TopNoAccess, TopNoAccess &&), "");
+
+ struct Access {
+ PrivateMove pm;
+ // NoAccess's move would *not* be deleted, so is *not* suppressed,
+ // so moves of it use PrivateMove's move ctor, which is not trivial.
+ };
+ static_assert(__is_trivially_constructible(Access, const Access &), "");
+ static_assert(!__is_trivially_constructible(Access, Access &&), "");
+ struct TopAccess : Access {};
+ static_assert(__is_trivially_constructible(TopAccess, const TopAccess &), "");
+ static_assert(!__is_trivially_constructible(TopAccess, TopAccess &&), "");
+}
+
+namespace TrivialityDependsOnDestructor {
+ class HasInaccessibleDestructor { ~HasInaccessibleDestructor() = default; };
+ struct HasImplicitlyDeletedDestructor : HasInaccessibleDestructor {};
+ struct HasImplicitlyDeletedCopyCtor : HasImplicitlyDeletedDestructor {
+ HasImplicitlyDeletedCopyCtor() = default;
+ template<typename T> HasImplicitlyDeletedCopyCtor(T &&);
+ // Copy ctor is deleted but trivial.
+ // Move ctor is suppressed.
+ HasImplicitlyDeletedCopyCtor(const HasImplicitlyDeletedCopyCtor&) = default;
+ HasImplicitlyDeletedCopyCtor(HasImplicitlyDeletedCopyCtor&&) = default;
+ };
+ struct Test : HasImplicitlyDeletedCopyCtor {
+ Test(const Test&) = default;
+ Test(Test&&) = default;
+ };
+ // Implicit copy ctor calls deleted trivial copy ctor.
+ static_assert(__has_trivial_copy(Test), "");
+ // This is false because the destructor is deleted.
+ static_assert(!__is_trivially_constructible(Test, const Test &), "");
+ // Implicit move ctor calls template ctor.
+ static_assert(!__is_trivially_constructible(Test, Test &&), "");
+
+ struct HasAccessibleDestructor { ~HasAccessibleDestructor() = default; };
+ struct HasImplicitlyDefaultedDestructor : HasAccessibleDestructor {};
+ struct HasImplicitlyDefaultedCopyCtor : HasImplicitlyDefaultedDestructor {
+ template<typename T> HasImplicitlyDefaultedCopyCtor(T &&);
+ // Copy ctor is trivial.
+ // Move ctor is trivial.
+ };
+ struct Test2 : HasImplicitlyDefaultedCopyCtor {};
+ // Implicit copy ctor calls trivial copy ctor.
+ static_assert(__has_trivial_copy(Test2), "");
+ static_assert(__is_trivially_constructible(Test2, const Test2 &), "");
+ // Implicit move ctor calls trivial move ctor.
+ static_assert(__is_trivially_constructible(Test2, Test2 &&), "");
+}
diff --git a/test/CXX/special/class.copy/p18-cxx11.cpp b/test/CXX/special/class.copy/p18-cxx11.cpp
new file mode 100644
index 0000000..7b09dd6
--- /dev/null
+++ b/test/CXX/special/class.copy/p18-cxx11.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -std=c++11 %s -verify
+// expected-no-diagnostics
+
+// C++98 [class.copy]p10 / C++11 [class.copy]p18.
+
+// The implicitly-declared copy assignment operator for a class X will have the form
+// X& X::operator=(const X&)
+// if [every direct subobject] has a copy assignment operator whose first parameter is
+// of type 'const volatile[opt] T &' or 'T'. Otherwise, it will have the form
+// X &X::operator=(X&)
+
+struct ConstCopy {
+ ConstCopy &operator=(const ConstCopy &);
+};
+
+struct NonConstCopy {
+ NonConstCopy &operator=(NonConstCopy &);
+};
+
+struct DeletedConstCopy {
+ DeletedConstCopy &operator=(const DeletedConstCopy &) = delete;
+};
+
+struct DeletedNonConstCopy {
+ DeletedNonConstCopy &operator=(DeletedNonConstCopy &) = delete;
+};
+
+struct ImplicitlyDeletedConstCopy {
+ ImplicitlyDeletedConstCopy &operator=(ImplicitlyDeletedConstCopy &&);
+};
+
+struct ByValueCopy {
+ ByValueCopy &operator=(ByValueCopy);
+};
+
+struct AmbiguousConstCopy {
+ AmbiguousConstCopy &operator=(const AmbiguousConstCopy&);
+ AmbiguousConstCopy &operator=(AmbiguousConstCopy);
+};
+
+
+struct A : ConstCopy {};
+struct B : NonConstCopy { ConstCopy a; };
+struct C : ConstCopy { NonConstCopy a; };
+struct D : DeletedConstCopy {};
+struct E : DeletedNonConstCopy {};
+struct F { ImplicitlyDeletedConstCopy a; };
+struct G : virtual B {};
+struct H : ByValueCopy {};
+struct I : AmbiguousConstCopy {};
+
+struct Test {
+ friend A &A::operator=(const A &);
+ friend B &B::operator=(B &);
+ friend C &C::operator=(C &);
+ friend D &D::operator=(const D &);
+ friend E &E::operator=(E &);
+ friend F &F::operator=(const F &);
+ friend G &G::operator=(G &);
+ friend H &H::operator=(const H &);
+ friend I &I::operator=(const I &);
+};
diff --git a/test/CXX/special/class.copy/p23-cxx11.cpp b/test/CXX/special/class.copy/p23-cxx11.cpp
index 7c04a82..90945c5 100644
--- a/test/CXX/special/class.copy/p23-cxx11.cpp
+++ b/test/CXX/special/class.copy/p23-cxx11.cpp
@@ -143,6 +143,6 @@ namespace PR13381 {
};
void g() {
T t;
- t = T(); // expected-error{{implicitly-deleted copy assignment}}
+ t = T(); // expected-error{{object of type 'PR13381::T' cannot be assigned because its copy assignment operator is implicitly deleted}}
}
}
diff --git a/test/CXX/special/class.copy/p25-0x.cpp b/test/CXX/special/class.copy/p25-0x.cpp
new file mode 100644
index 0000000..c7224ae
--- /dev/null
+++ b/test/CXX/special/class.copy/p25-0x.cpp
@@ -0,0 +1,202 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+
+// expected-no-diagnostics
+
+template<typename T, bool B> struct trivially_assignable_check {
+ static_assert(B == __has_trivial_assign(T), "");
+ static_assert(B == __is_trivially_assignable(T&, T), "");
+ static_assert(B == __is_trivially_assignable(T&, const T &), "");
+ static_assert(B == __is_trivially_assignable(T&, T &&), "");
+ static_assert(B == __is_trivially_assignable(T&&, T), "");
+ static_assert(B == __is_trivially_assignable(T&&, const T &), "");
+ static_assert(B == __is_trivially_assignable(T&&, T &&), "");
+ typedef void type;
+};
+template<typename T> using trivially_assignable =
+ typename trivially_assignable_check<T, true>::type;
+template<typename T> using not_trivially_assignable =
+ typename trivially_assignable_check<T, false>::type;
+
+struct Trivial {};
+using _ = trivially_assignable<Trivial>;
+
+// A copy/move assignment operator for class X is trivial if it is not user-provided,
+struct UserProvided {
+ UserProvided &operator=(const UserProvided &);
+};
+using _ = not_trivially_assignable<UserProvided>;
+
+// its declared parameter type is the same as if it had been implicitly
+// declared,
+struct NonConstCopy {
+ NonConstCopy &operator=(NonConstCopy &) = default;
+};
+using _ = not_trivially_assignable<NonConstCopy>;
+
+// class X has no virtual functions
+struct VFn {
+ virtual void f();
+};
+using _ = not_trivially_assignable<VFn>;
+
+// and no virtual base classes
+struct VBase : virtual Trivial {};
+using _ = not_trivially_assignable<VBase>;
+
+// and the assignment operator selected to copy/move each [direct subobject] is trivial
+struct TemplateCtor {
+ template<typename T> TemplateCtor operator=(T &);
+};
+using _ = trivially_assignable<TemplateCtor>;
+struct TemplateCtorMember {
+ TemplateCtor tc;
+};
+using _ = trivially_assignable<TemplateCtorMember>;
+struct MutableTemplateCtorMember {
+ mutable TemplateCtor mtc;
+};
+static_assert(!__is_trivially_assignable(MutableTemplateCtorMember, const MutableTemplateCtorMember &), "");
+static_assert(__is_trivially_assignable(MutableTemplateCtorMember, MutableTemplateCtorMember &&), "");
+
+// Both trivial and non-trivial special members.
+struct TNT {
+ TNT &operator=(const TNT &) = default; // trivial
+ TNT &operator=(TNT &); // non-trivial
+
+ TNT &operator=(TNT &&) = default; // trivial
+ TNT &operator=(const TNT &&); // non-trivial
+};
+
+static_assert(!__has_trivial_assign(TNT), "lie deliberately for gcc compatibility");
+static_assert(__is_trivially_assignable(TNT, TNT), "");
+static_assert(!__is_trivially_assignable(TNT, TNT &), "");
+static_assert(__is_trivially_assignable(TNT, const TNT &), "");
+static_assert(!__is_trivially_assignable(TNT, volatile TNT &), "");
+static_assert(__is_trivially_assignable(TNT, TNT &&), "");
+static_assert(!__is_trivially_assignable(TNT, const TNT &&), "");
+static_assert(!__is_trivially_assignable(TNT, volatile TNT &&), "");
+
+// This has only trivial special members.
+struct DerivedFromTNT : TNT {};
+
+static_assert(__has_trivial_assign(DerivedFromTNT), "");
+static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT), "");
+static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT &), "");
+static_assert(__is_trivially_assignable(DerivedFromTNT, const DerivedFromTNT &), "");
+static_assert(!__is_trivially_assignable(DerivedFromTNT, volatile DerivedFromTNT &), "");
+static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT &&), "");
+static_assert(__is_trivially_assignable(DerivedFromTNT, const DerivedFromTNT &&), "");
+static_assert(!__is_trivially_assignable(DerivedFromTNT, volatile DerivedFromTNT &&), "");
+
+// This has only trivial special members.
+struct TNTMember {
+ TNT tnt;
+};
+
+static_assert(__has_trivial_assign(TNTMember), "");
+static_assert(__is_trivially_assignable(TNTMember, TNTMember), "");
+static_assert(__is_trivially_assignable(TNTMember, TNTMember &), "");
+static_assert(__is_trivially_assignable(TNTMember, const TNTMember &), "");
+static_assert(!__is_trivially_assignable(TNTMember, volatile TNTMember &), "");
+static_assert(__is_trivially_assignable(TNTMember, TNTMember &&), "");
+static_assert(__is_trivially_assignable(TNTMember, const TNTMember &&), "");
+static_assert(!__is_trivially_assignable(TNTMember, volatile TNTMember &&), "");
+
+struct NCCTNT : NonConstCopy, TNT {};
+
+static_assert(!__has_trivial_assign(NCCTNT), "");
+static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT), "");
+static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT &), "");
+static_assert(!__is_trivially_assignable(NCCTNT, const NCCTNT &), "");
+static_assert(!__is_trivially_assignable(NCCTNT, volatile NCCTNT &), "");
+static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT &&), "");
+static_assert(!__is_trivially_assignable(NCCTNT, const NCCTNT &&), "");
+static_assert(!__is_trivially_assignable(NCCTNT, volatile NCCTNT &&), "");
+
+struct MultipleTrivial {
+ // All four of these are trivial.
+ MultipleTrivial &operator=(const MultipleTrivial &) & = default;
+ MultipleTrivial &operator=(const MultipleTrivial &) && = default;
+ MultipleTrivial &operator=(MultipleTrivial &&) & = default;
+ MultipleTrivial &operator=(MultipleTrivial &&) && = default;
+};
+
+using _ = trivially_assignable<MultipleTrivial>;
+
+struct RefQualifier {
+ RefQualifier &operator=(const RefQualifier &) & = default;
+ RefQualifier &operator=(const RefQualifier &) &&;
+ RefQualifier &operator=(RefQualifier &&) &;
+ RefQualifier &operator=(RefQualifier &&) && = default;
+};
+struct DerivedFromRefQualifier : RefQualifier {
+ // Both of these call the trivial copy operation.
+ DerivedFromRefQualifier &operator=(const DerivedFromRefQualifier &) & = default;
+ DerivedFromRefQualifier &operator=(const DerivedFromRefQualifier &) && = default;
+ // Both of these call the non-trivial move operation.
+ DerivedFromRefQualifier &operator=(DerivedFromRefQualifier &&) & = default;
+ DerivedFromRefQualifier &operator=(DerivedFromRefQualifier &&) && = default;
+};
+static_assert(__is_trivially_assignable(DerivedFromRefQualifier&, const DerivedFromRefQualifier&), "");
+static_assert(__is_trivially_assignable(DerivedFromRefQualifier&&, const DerivedFromRefQualifier&), "");
+static_assert(!__is_trivially_assignable(DerivedFromRefQualifier&, DerivedFromRefQualifier&&), "");
+static_assert(!__is_trivially_assignable(DerivedFromRefQualifier&&, DerivedFromRefQualifier&&), "");
+
+struct TemplateAssignNoMove {
+ TemplateAssignNoMove &operator=(const TemplateAssignNoMove &) = default;
+ template<typename T> TemplateAssignNoMove &operator=(T &&);
+};
+static_assert(__is_trivially_assignable(TemplateAssignNoMove, const TemplateAssignNoMove &), "");
+static_assert(!__is_trivially_assignable(TemplateAssignNoMove, TemplateAssignNoMove &&), "");
+
+struct UseTemplateAssignNoMove {
+ TemplateAssignNoMove tanm;
+};
+static_assert(__is_trivially_assignable(UseTemplateAssignNoMove, const UseTemplateAssignNoMove &), "");
+static_assert(!__is_trivially_assignable(UseTemplateAssignNoMove, UseTemplateAssignNoMove &&), "");
+
+struct TemplateAssignNoMoveSFINAE {
+ TemplateAssignNoMoveSFINAE &operator=(const TemplateAssignNoMoveSFINAE &) = default;
+ template<typename T, typename U = typename T::error> TemplateAssignNoMoveSFINAE &operator=(T &&);
+};
+static_assert(__is_trivially_assignable(TemplateAssignNoMoveSFINAE, const TemplateAssignNoMoveSFINAE &), "");
+static_assert(__is_trivially_assignable(TemplateAssignNoMoveSFINAE, TemplateAssignNoMoveSFINAE &&), "");
+
+struct UseTemplateAssignNoMoveSFINAE {
+ TemplateAssignNoMoveSFINAE tanm;
+};
+static_assert(__is_trivially_assignable(UseTemplateAssignNoMoveSFINAE, const UseTemplateAssignNoMoveSFINAE &), "");
+static_assert(__is_trivially_assignable(UseTemplateAssignNoMoveSFINAE, UseTemplateAssignNoMoveSFINAE &&), "");
+
+namespace TrivialityDependsOnImplicitDeletion {
+ struct PrivateMove {
+ PrivateMove &operator=(const PrivateMove &) = default;
+ private:
+ PrivateMove &operator=(PrivateMove &&);
+ friend class Access;
+ };
+ static_assert(__is_trivially_assignable(PrivateMove, const PrivateMove &), "");
+ static_assert(!__is_trivially_assignable(PrivateMove, PrivateMove &&), "");
+
+ struct NoAccess {
+ PrivateMove pm;
+ // NoAccess's move would be deleted, so is suppressed,
+ // so moves of it use PrivateMove's copy ctor, which is trivial.
+ };
+ static_assert(__is_trivially_assignable(NoAccess, const NoAccess &), "");
+ static_assert(__is_trivially_assignable(NoAccess, NoAccess &&), "");
+ struct TopNoAccess : NoAccess {};
+ static_assert(__is_trivially_assignable(TopNoAccess, const TopNoAccess &), "");
+ static_assert(__is_trivially_assignable(TopNoAccess, TopNoAccess &&), "");
+
+ struct Access {
+ PrivateMove pm;
+ // NoAccess's move would *not* be deleted, so is *not* suppressed,
+ // so moves of it use PrivateMove's move ctor, which is not trivial.
+ };
+ static_assert(__is_trivially_assignable(Access, const Access &), "");
+ static_assert(!__is_trivially_assignable(Access, Access &&), "");
+ struct TopAccess : Access {};
+ static_assert(__is_trivially_assignable(TopAccess, const TopAccess &), "");
+ static_assert(!__is_trivially_assignable(TopAccess, TopAccess &&), "");
+}
diff --git a/test/CXX/special/class.copy/p28-cxx11.cpp b/test/CXX/special/class.copy/p28-cxx11.cpp
new file mode 100644
index 0000000..dc501d9
--- /dev/null
+++ b/test/CXX/special/class.copy/p28-cxx11.cpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -std=c++98 %s -fsyntax-only
+// RUN: %clang_cc1 -std=c++11 %s -verify
+
+// In C++11, we must perform overload resolution to determine which function is
+// called by a defaulted assignment operator, and the selected operator might
+// not be a copy or move assignment (it might be a specialization of a templated
+// 'operator=', for instance).
+struct A {
+ A &operator=(const A &);
+
+ template<typename T>
+ A &operator=(T &&) { return T::error; } // expected-error {{no member named 'error' in 'A'}}
+};
+
+struct B : A {
+ B &operator=(B &&);
+};
+
+B &B::operator=(B &&) = default; // expected-note {{here}}
OpenPOWER on IntegriCloud