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