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_assignable_check {
      6   static_assert(B == __has_trivial_assign(T), "");
      7   static_assert(B == __is_trivially_assignable(T&, T), "");
      8   static_assert(B == __is_trivially_assignable(T&, const T &), "");
      9   static_assert(B == __is_trivially_assignable(T&, T &&), "");
     10   static_assert(B == __is_trivially_assignable(T&&, T), "");
     11   static_assert(B == __is_trivially_assignable(T&&, const T &), "");
     12   static_assert(B == __is_trivially_assignable(T&&, T &&), "");
     13   typedef void type;
     14 };
     15 template<typename T> using trivially_assignable =
     16   typename trivially_assignable_check<T, true>::type;
     17 template<typename T> using not_trivially_assignable =
     18   typename trivially_assignable_check<T, false>::type;
     19 
     20 struct Trivial {};
     21 using _ = trivially_assignable<Trivial>;
     22 
     23 // A copy/move assignment operator for class X is trivial if it is not user-provided,
     24 struct UserProvided {
     25   UserProvided &operator=(const UserProvided &);
     26 };
     27 using _ = not_trivially_assignable<UserProvided>;
     28 
     29 // its declared parameter type is the same as if it had been implicitly
     30 // declared,
     31 struct NonConstCopy {
     32   NonConstCopy &operator=(NonConstCopy &) = default;
     33 };
     34 using _ = not_trivially_assignable<NonConstCopy>;
     35 
     36 // class X has no virtual functions
     37 struct VFn {
     38   virtual void f();
     39 };
     40 using _ = not_trivially_assignable<VFn>;
     41 
     42 // and no virtual base classes
     43 struct VBase : virtual Trivial {};
     44 using _ = not_trivially_assignable<VBase>;
     45 
     46 // and the assignment operator selected to copy/move each [direct subobject] is trivial
     47 struct TemplateCtor {
     48   template<typename T> TemplateCtor operator=(T &);
     49 };
     50 using _ = trivially_assignable<TemplateCtor>;
     51 struct TemplateCtorMember {
     52   TemplateCtor tc;
     53 };
     54 using _ = trivially_assignable<TemplateCtorMember>;
     55 struct MutableTemplateCtorMember {
     56   mutable TemplateCtor mtc;
     57 };
     58 static_assert(!__is_trivially_assignable(MutableTemplateCtorMember, const MutableTemplateCtorMember &), "");
     59 static_assert(__is_trivially_assignable(MutableTemplateCtorMember, MutableTemplateCtorMember &&), "");
     60 
     61 // Both trivial and non-trivial special members.
     62 struct TNT {
     63   TNT &operator=(const TNT &) = default; // trivial
     64   TNT &operator=(TNT &); // non-trivial
     65 
     66   TNT &operator=(TNT &&) = default; // trivial
     67   TNT &operator=(const TNT &&); // non-trivial
     68 };
     69 
     70 static_assert(!__has_trivial_assign(TNT), "lie deliberately for gcc compatibility");
     71 static_assert(__is_trivially_assignable(TNT, TNT), "");
     72 static_assert(!__is_trivially_assignable(TNT, TNT &), "");
     73 static_assert(__is_trivially_assignable(TNT, const TNT &), "");
     74 static_assert(!__is_trivially_assignable(TNT, volatile TNT &), "");
     75 static_assert(__is_trivially_assignable(TNT, TNT &&), "");
     76 static_assert(!__is_trivially_assignable(TNT, const TNT &&), "");
     77 static_assert(!__is_trivially_assignable(TNT, volatile TNT &&), "");
     78 
     79 // This has only trivial special members.
     80 struct DerivedFromTNT : TNT {};
     81 
     82 static_assert(__has_trivial_assign(DerivedFromTNT), "");
     83 static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT), "");
     84 static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT &), "");
     85 static_assert(__is_trivially_assignable(DerivedFromTNT, const DerivedFromTNT &), "");
     86 static_assert(!__is_trivially_assignable(DerivedFromTNT, volatile DerivedFromTNT &), "");
     87 static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT &&), "");
     88 static_assert(__is_trivially_assignable(DerivedFromTNT, const DerivedFromTNT &&), "");
     89 static_assert(!__is_trivially_assignable(DerivedFromTNT, volatile DerivedFromTNT &&), "");
     90 
     91 // This has only trivial special members.
     92 struct TNTMember {
     93   TNT tnt;
     94 };
     95 
     96 static_assert(__has_trivial_assign(TNTMember), "");
     97 static_assert(__is_trivially_assignable(TNTMember, TNTMember), "");
     98 static_assert(__is_trivially_assignable(TNTMember, TNTMember &), "");
     99 static_assert(__is_trivially_assignable(TNTMember, const TNTMember &), "");
    100 static_assert(!__is_trivially_assignable(TNTMember, volatile TNTMember &), "");
    101 static_assert(__is_trivially_assignable(TNTMember, TNTMember &&), "");
    102 static_assert(__is_trivially_assignable(TNTMember, const TNTMember &&), "");
    103 static_assert(!__is_trivially_assignable(TNTMember, volatile TNTMember &&), "");
    104 
    105 struct NCCTNT : NonConstCopy, TNT {};
    106 
    107 static_assert(!__has_trivial_assign(NCCTNT), "");
    108 static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT), "");
    109 static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT &), "");
    110 static_assert(!__is_trivially_assignable(NCCTNT, const NCCTNT &), "");
    111 static_assert(!__is_trivially_assignable(NCCTNT, volatile NCCTNT &), "");
    112 static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT &&), "");
    113 static_assert(!__is_trivially_assignable(NCCTNT, const NCCTNT &&), "");
    114 static_assert(!__is_trivially_assignable(NCCTNT, volatile NCCTNT &&), "");
    115 
    116 struct MultipleTrivial {
    117   // All four of these are trivial.
    118   MultipleTrivial &operator=(const MultipleTrivial &) & = default;
    119   MultipleTrivial &operator=(const MultipleTrivial &) && = default;
    120   MultipleTrivial &operator=(MultipleTrivial &&) & = default;
    121   MultipleTrivial &operator=(MultipleTrivial &&) && = default;
    122 };
    123 
    124 using _ = trivially_assignable<MultipleTrivial>;
    125 
    126 struct RefQualifier {
    127   RefQualifier &operator=(const RefQualifier &) & = default;
    128   RefQualifier &operator=(const RefQualifier &) &&;
    129   RefQualifier &operator=(RefQualifier &&) &;
    130   RefQualifier &operator=(RefQualifier &&) && = default;
    131 };
    132 struct DerivedFromRefQualifier : RefQualifier {
    133   // Both of these call the trivial copy operation.
    134   DerivedFromRefQualifier &operator=(const DerivedFromRefQualifier &) & = default;
    135   DerivedFromRefQualifier &operator=(const DerivedFromRefQualifier &) && = default;
    136   // Both of these call the non-trivial move operation.
    137   DerivedFromRefQualifier &operator=(DerivedFromRefQualifier &&) & = default;
    138   DerivedFromRefQualifier &operator=(DerivedFromRefQualifier &&) && = default;
    139 };
    140 static_assert(__is_trivially_assignable(DerivedFromRefQualifier&, const DerivedFromRefQualifier&), "");
    141 static_assert(__is_trivially_assignable(DerivedFromRefQualifier&&, const DerivedFromRefQualifier&), "");
    142 static_assert(!__is_trivially_assignable(DerivedFromRefQualifier&, DerivedFromRefQualifier&&), "");
    143 static_assert(!__is_trivially_assignable(DerivedFromRefQualifier&&, DerivedFromRefQualifier&&), "");
    144 
    145 struct TemplateAssignNoMove {
    146   TemplateAssignNoMove &operator=(const TemplateAssignNoMove &) = default;
    147   template<typename T> TemplateAssignNoMove &operator=(T &&);
    148 };
    149 static_assert(__is_trivially_assignable(TemplateAssignNoMove, const TemplateAssignNoMove &), "");
    150 static_assert(!__is_trivially_assignable(TemplateAssignNoMove, TemplateAssignNoMove &&), "");
    151 
    152 struct UseTemplateAssignNoMove {
    153   TemplateAssignNoMove tanm;
    154 };
    155 static_assert(__is_trivially_assignable(UseTemplateAssignNoMove, const UseTemplateAssignNoMove &), "");
    156 static_assert(!__is_trivially_assignable(UseTemplateAssignNoMove, UseTemplateAssignNoMove &&), "");
    157 
    158 struct TemplateAssignNoMoveSFINAE {
    159   TemplateAssignNoMoveSFINAE &operator=(const TemplateAssignNoMoveSFINAE &) = default;
    160   template<typename T, typename U = typename T::error> TemplateAssignNoMoveSFINAE &operator=(T &&);
    161 };
    162 static_assert(__is_trivially_assignable(TemplateAssignNoMoveSFINAE, const TemplateAssignNoMoveSFINAE &), "");
    163 static_assert(__is_trivially_assignable(TemplateAssignNoMoveSFINAE, TemplateAssignNoMoveSFINAE &&), "");
    164 
    165 struct UseTemplateAssignNoMoveSFINAE {
    166   TemplateAssignNoMoveSFINAE tanm;
    167 };
    168 static_assert(__is_trivially_assignable(UseTemplateAssignNoMoveSFINAE, const UseTemplateAssignNoMoveSFINAE &), "");
    169 static_assert(__is_trivially_assignable(UseTemplateAssignNoMoveSFINAE, UseTemplateAssignNoMoveSFINAE &&), "");
    170 
    171 namespace TrivialityDependsOnImplicitDeletion {
    172   struct PrivateMove {
    173     PrivateMove &operator=(const PrivateMove &) = default;
    174   private:
    175     PrivateMove &operator=(PrivateMove &&);
    176     friend class Access;
    177   };
    178   static_assert(__is_trivially_assignable(PrivateMove, const PrivateMove &), "");
    179   static_assert(!__is_trivially_assignable(PrivateMove, PrivateMove &&), "");
    180 
    181   struct NoAccess {
    182     PrivateMove pm;
    183     // NoAccess's move would be deleted, so is suppressed,
    184     // so moves of it use PrivateMove's copy ctor, which is trivial.
    185   };
    186   static_assert(__is_trivially_assignable(NoAccess, const NoAccess &), "");
    187   static_assert(__is_trivially_assignable(NoAccess, NoAccess &&), "");
    188   struct TopNoAccess : NoAccess {};
    189   static_assert(__is_trivially_assignable(TopNoAccess, const TopNoAccess &), "");
    190   static_assert(__is_trivially_assignable(TopNoAccess, TopNoAccess &&), "");
    191 
    192   struct Access {
    193     PrivateMove pm;
    194     // NoAccess's move would *not* be deleted, so is *not* suppressed,
    195     // so moves of it use PrivateMove's move ctor, which is not trivial.
    196   };
    197   static_assert(__is_trivially_assignable(Access, const Access &), "");
    198   static_assert(!__is_trivially_assignable(Access, Access &&), "");
    199   struct TopAccess : Access {};
    200   static_assert(__is_trivially_assignable(TopAccess, const TopAccess &), "");
    201   static_assert(!__is_trivially_assignable(TopAccess, TopAccess &&), "");
    202 }
    203