// 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 is deleted, 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 &&), ""); }