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