Home | History | Annotate | Download | only in class.copy
      1 // RUN: %clang_cc1 -std=c++11 -verify %s
      2 
      3 // expected-no-diagnostics
      4 
      5 template<typename T, bool B> struct trivially_copyable_check {
      6   static_assert(B == __has_trivial_copy(T), "");
      7   static_assert(B == __is_trivially_constructible(T, T), "");
      8   static_assert(B == __is_trivially_constructible(T, const T &), "");
      9   static_assert(B == __is_trivially_constructible(T, T &&), "");
     10   typedef void type;
     11 };
     12 template<typename T> using trivially_copyable =
     13   typename trivially_copyable_check<T, true>::type;
     14 template<typename T> using not_trivially_copyable =
     15   typename trivially_copyable_check<T, false>::type;
     16 
     17 struct Trivial {};
     18 using _ = trivially_copyable<Trivial>;
     19 
     20 // A copy/move constructor for class X is trivial if it is not user-provided,
     21 struct UserProvided {
     22   UserProvided(const UserProvided &);
     23 };
     24 using _ = not_trivially_copyable<UserProvided>;
     25 
     26 // its declared parameter type is the same as if it had been implicitly
     27 // declared,
     28 struct NonConstCopy {
     29   NonConstCopy(NonConstCopy &) = default;
     30 };
     31 using _ = not_trivially_copyable<NonConstCopy>;
     32 
     33 // class X has no virtual functions
     34 struct VFn {
     35   virtual void f();
     36 };
     37 using _ = not_trivially_copyable<VFn>;
     38 
     39 // and no virtual base classes
     40 struct VBase : virtual Trivial {};
     41 using _ = not_trivially_copyable<VBase>;
     42 
     43 // and the constructor selected to copy/move each [direct subobject] is trivial
     44 struct TemplateCtor {
     45   template<typename T> TemplateCtor(T &);
     46 };
     47 using _ = trivially_copyable<TemplateCtor>;
     48 struct TemplateCtorMember {
     49   TemplateCtor tc;
     50 };
     51 using _ = trivially_copyable<TemplateCtorMember>;
     52 
     53 // We can select a non-trivial copy ctor even if there is a trivial one.
     54 struct MutableTemplateCtorMember {
     55   mutable TemplateCtor mtc;
     56 };
     57 static_assert(!__is_trivially_constructible(MutableTemplateCtorMember, const MutableTemplateCtorMember &), "");
     58 static_assert(__is_trivially_constructible(MutableTemplateCtorMember, MutableTemplateCtorMember &&), "");
     59 struct MutableTemplateCtorMember2 {
     60   MutableTemplateCtorMember2(const MutableTemplateCtorMember2 &) = default;
     61   MutableTemplateCtorMember2(MutableTemplateCtorMember2 &&) = default;
     62   mutable TemplateCtor mtc;
     63 };
     64 static_assert(!__is_trivially_constructible(MutableTemplateCtorMember2, const MutableTemplateCtorMember2 &), "");
     65 static_assert(__is_trivially_constructible(MutableTemplateCtorMember2, MutableTemplateCtorMember2 &&), "");
     66 
     67 // Both trivial and non-trivial special members.
     68 struct TNT {
     69   TNT(const TNT &) = default; // trivial
     70   TNT(TNT &); // non-trivial
     71 
     72   TNT(TNT &&) = default; // trivial
     73   TNT(const TNT &&); // non-trivial
     74 };
     75 
     76 static_assert(!__has_trivial_copy(TNT), "lie deliberately for gcc compatibility");
     77 static_assert(__is_trivially_constructible(TNT, TNT), "");
     78 static_assert(!__is_trivially_constructible(TNT, TNT &), "");
     79 static_assert(__is_trivially_constructible(TNT, const TNT &), "");
     80 static_assert(!__is_trivially_constructible(TNT, volatile TNT &), "");
     81 static_assert(__is_trivially_constructible(TNT, TNT &&), "");
     82 static_assert(!__is_trivially_constructible(TNT, const TNT &&), "");
     83 static_assert(!__is_trivially_constructible(TNT, volatile TNT &&), "");
     84 
     85 // This has only trivial special members.
     86 struct DerivedFromTNT : TNT {};
     87 
     88 static_assert(__has_trivial_copy(DerivedFromTNT), "");
     89 static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT), "");
     90 static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT &), "");
     91 static_assert(__is_trivially_constructible(DerivedFromTNT, const DerivedFromTNT &), "");
     92 static_assert(!__is_trivially_constructible(DerivedFromTNT, volatile DerivedFromTNT &), "");
     93 static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT &&), "");
     94 static_assert(__is_trivially_constructible(DerivedFromTNT, const DerivedFromTNT &&), "");
     95 static_assert(!__is_trivially_constructible(DerivedFromTNT, volatile DerivedFromTNT &&), "");
     96 
     97 // This has only trivial special members.
     98 struct TNTMember {
     99   TNT tnt;
    100 };
    101 
    102 static_assert(__has_trivial_copy(TNTMember), "");
    103 static_assert(__is_trivially_constructible(TNTMember, TNTMember), "");
    104 static_assert(__is_trivially_constructible(TNTMember, TNTMember &), "");
    105 static_assert(__is_trivially_constructible(TNTMember, const TNTMember &), "");
    106 static_assert(!__is_trivially_constructible(TNTMember, volatile TNTMember &), "");
    107 static_assert(__is_trivially_constructible(TNTMember, TNTMember &&), "");
    108 static_assert(__is_trivially_constructible(TNTMember, const TNTMember &&), "");
    109 static_assert(!__is_trivially_constructible(TNTMember, volatile TNTMember &&), "");
    110 
    111 struct NCCTNT : NonConstCopy, TNT {};
    112 
    113 static_assert(!__has_trivial_copy(NCCTNT), "");
    114 static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT), "");
    115 static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT &), "");
    116 static_assert(!__is_trivially_constructible(NCCTNT, const NCCTNT &), "");
    117 static_assert(!__is_trivially_constructible(NCCTNT, volatile NCCTNT &), "");
    118 static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT &&), "");
    119 static_assert(!__is_trivially_constructible(NCCTNT, const NCCTNT &&), "");
    120 static_assert(!__is_trivially_constructible(NCCTNT, volatile NCCTNT &&), "");
    121 
    122 struct TemplateCtorNoMove {
    123   TemplateCtorNoMove(const TemplateCtorNoMove &) = default;
    124   template<typename T> TemplateCtorNoMove(T &&);
    125 };
    126 static_assert(__is_trivially_constructible(TemplateCtorNoMove, const TemplateCtorNoMove &), "");
    127 static_assert(!__is_trivially_constructible(TemplateCtorNoMove, TemplateCtorNoMove &&), "");
    128 
    129 struct UseTemplateCtorNoMove {
    130   TemplateCtorNoMove tcnm;
    131 };
    132 static_assert(__is_trivially_constructible(UseTemplateCtorNoMove, const UseTemplateCtorNoMove &), "");
    133 static_assert(!__is_trivially_constructible(UseTemplateCtorNoMove, UseTemplateCtorNoMove &&), "");
    134 
    135 struct TemplateCtorNoMoveSFINAE {
    136   TemplateCtorNoMoveSFINAE(const TemplateCtorNoMoveSFINAE &) = default;
    137   template<typename T, typename U = typename T::error> TemplateCtorNoMoveSFINAE(T &&);
    138 };
    139 static_assert(__is_trivially_constructible(TemplateCtorNoMoveSFINAE, const TemplateCtorNoMoveSFINAE &), "");
    140 static_assert(__is_trivially_constructible(TemplateCtorNoMoveSFINAE, TemplateCtorNoMoveSFINAE &&), "");
    141 
    142 struct UseTemplateCtorNoMoveSFINAE {
    143   TemplateCtorNoMoveSFINAE tcnm;
    144 };
    145 static_assert(__is_trivially_constructible(UseTemplateCtorNoMoveSFINAE, const UseTemplateCtorNoMoveSFINAE &), "");
    146 static_assert(__is_trivially_constructible(UseTemplateCtorNoMoveSFINAE, UseTemplateCtorNoMoveSFINAE &&), "");
    147 
    148 namespace TrivialityDependsOnImplicitDeletion {
    149   struct PrivateMove {
    150     PrivateMove(const PrivateMove &) = default;
    151   private:
    152     PrivateMove(PrivateMove &&);
    153     friend class Access;
    154   };
    155   static_assert(__is_trivially_constructible(PrivateMove, const PrivateMove &), "");
    156   static_assert(!__is_trivially_constructible(PrivateMove, PrivateMove &&), "");
    157 
    158   struct NoAccess {
    159     PrivateMove pm;
    160     // NoAccess's move is deleted, so moves of it use PrivateMove's copy ctor,
    161     // which is trivial.
    162   };
    163   static_assert(__is_trivially_constructible(NoAccess, const NoAccess &), "");
    164   static_assert(__is_trivially_constructible(NoAccess, NoAccess &&), "");
    165   struct TopNoAccess : NoAccess {};
    166   static_assert(__is_trivially_constructible(TopNoAccess, const TopNoAccess &), "");
    167   static_assert(__is_trivially_constructible(TopNoAccess, TopNoAccess &&), "");
    168 
    169   struct Access {
    170     PrivateMove pm;
    171     // NoAccess's move would *not* be deleted, so is *not* suppressed,
    172     // so moves of it use PrivateMove's move ctor, which is not trivial.
    173   };
    174   static_assert(__is_trivially_constructible(Access, const Access &), "");
    175   static_assert(!__is_trivially_constructible(Access, Access &&), "");
    176   struct TopAccess : Access {};
    177   static_assert(__is_trivially_constructible(TopAccess, const TopAccess &), "");
    178   static_assert(!__is_trivially_constructible(TopAccess, TopAccess &&), "");
    179 }
    180 
    181 namespace TrivialityDependsOnDestructor {
    182   class HasInaccessibleDestructor { ~HasInaccessibleDestructor() = default; };
    183   struct HasImplicitlyDeletedDestructor : HasInaccessibleDestructor {};
    184   struct HasImplicitlyDeletedCopyCtor : HasImplicitlyDeletedDestructor {
    185     HasImplicitlyDeletedCopyCtor() = default;
    186     template<typename T> HasImplicitlyDeletedCopyCtor(T &&);
    187     // Copy ctor is deleted but trivial.
    188     // Move ctor is suppressed.
    189     HasImplicitlyDeletedCopyCtor(const HasImplicitlyDeletedCopyCtor&) = default;
    190     HasImplicitlyDeletedCopyCtor(HasImplicitlyDeletedCopyCtor&&) = default;
    191   };
    192   struct Test : HasImplicitlyDeletedCopyCtor {
    193     Test(const Test&) = default;
    194     Test(Test&&) = default;
    195   };
    196   // Implicit copy ctor calls deleted trivial copy ctor.
    197   static_assert(__has_trivial_copy(Test), "");
    198   // This is false because the destructor is deleted.
    199   static_assert(!__is_trivially_constructible(Test, const Test &), "");
    200   // Implicit move ctor calls template ctor.
    201   static_assert(!__is_trivially_constructible(Test, Test &&), "");
    202 
    203   struct HasAccessibleDestructor { ~HasAccessibleDestructor() = default; };
    204   struct HasImplicitlyDefaultedDestructor : HasAccessibleDestructor {};
    205   struct HasImplicitlyDefaultedCopyCtor : HasImplicitlyDefaultedDestructor {
    206     template<typename T> HasImplicitlyDefaultedCopyCtor(T &&);
    207     // Copy ctor is trivial.
    208     // Move ctor is trivial.
    209   };
    210   struct Test2 : HasImplicitlyDefaultedCopyCtor {};
    211   // Implicit copy ctor calls trivial copy ctor.
    212   static_assert(__has_trivial_copy(Test2), "");
    213   static_assert(__is_trivially_constructible(Test2, const Test2 &), "");
    214   // Implicit move ctor calls trivial move ctor.
    215   static_assert(__is_trivially_constructible(Test2, Test2 &&), "");
    216 }
    217