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