p12-0x.cpp revision 743cbb91499e138a63a398c6515667905f1b3be8
1// RUN: %clang_cc1 -std=c++11 -verify %s
2
3// expected-no-diagnostics
4
5template<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};
12template<typename T> using trivially_copyable =
13  typename trivially_copyable_check<T, true>::type;
14template<typename T> using not_trivially_copyable =
15  typename trivially_copyable_check<T, false>::type;
16
17struct Trivial {};
18using _ = trivially_copyable<Trivial>;
19
20// A copy/move constructor for class X is trivial if it is not user-provided,
21struct UserProvided {
22  UserProvided(const UserProvided &);
23};
24using _ = not_trivially_copyable<UserProvided>;
25
26// its declared parameter type is the same as if it had been implicitly
27// declared,
28struct NonConstCopy {
29  NonConstCopy(NonConstCopy &) = default;
30};
31using _ = not_trivially_copyable<NonConstCopy>;
32
33// class X has no virtual functions
34struct VFn {
35  virtual void f();
36};
37using _ = not_trivially_copyable<VFn>;
38
39// and no virtual base classes
40struct VBase : virtual Trivial {};
41using _ = not_trivially_copyable<VBase>;
42
43// and the constructor selected to copy/move each [direct subobject] is trivial
44struct TemplateCtor {
45  template<typename T> TemplateCtor(T &);
46};
47using _ = trivially_copyable<TemplateCtor>;
48struct TemplateCtorMember {
49  TemplateCtor tc;
50};
51using _ = trivially_copyable<TemplateCtorMember>;
52
53// We can select a non-trivial copy ctor even if there is a trivial one.
54struct MutableTemplateCtorMember {
55  mutable TemplateCtor mtc;
56};
57static_assert(!__is_trivially_constructible(MutableTemplateCtorMember, const MutableTemplateCtorMember &), "");
58static_assert(__is_trivially_constructible(MutableTemplateCtorMember, MutableTemplateCtorMember &&), "");
59struct MutableTemplateCtorMember2 {
60  MutableTemplateCtorMember2(const MutableTemplateCtorMember2 &) = default;
61  MutableTemplateCtorMember2(MutableTemplateCtorMember2 &&) = default;
62  mutable TemplateCtor mtc;
63};
64static_assert(!__is_trivially_constructible(MutableTemplateCtorMember2, const MutableTemplateCtorMember2 &), "");
65static_assert(__is_trivially_constructible(MutableTemplateCtorMember2, MutableTemplateCtorMember2 &&), "");
66
67// Both trivial and non-trivial special members.
68struct 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
76static_assert(!__has_trivial_copy(TNT), "lie deliberately for gcc compatibility");
77static_assert(__is_trivially_constructible(TNT, TNT), "");
78static_assert(!__is_trivially_constructible(TNT, TNT &), "");
79static_assert(__is_trivially_constructible(TNT, const TNT &), "");
80static_assert(!__is_trivially_constructible(TNT, volatile TNT &), "");
81static_assert(__is_trivially_constructible(TNT, TNT &&), "");
82static_assert(!__is_trivially_constructible(TNT, const TNT &&), "");
83static_assert(!__is_trivially_constructible(TNT, volatile TNT &&), "");
84
85// This has only trivial special members.
86struct DerivedFromTNT : TNT {};
87
88static_assert(__has_trivial_copy(DerivedFromTNT), "");
89static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT), "");
90static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT &), "");
91static_assert(__is_trivially_constructible(DerivedFromTNT, const DerivedFromTNT &), "");
92static_assert(!__is_trivially_constructible(DerivedFromTNT, volatile DerivedFromTNT &), "");
93static_assert(__is_trivially_constructible(DerivedFromTNT, DerivedFromTNT &&), "");
94static_assert(__is_trivially_constructible(DerivedFromTNT, const DerivedFromTNT &&), "");
95static_assert(!__is_trivially_constructible(DerivedFromTNT, volatile DerivedFromTNT &&), "");
96
97// This has only trivial special members.
98struct TNTMember {
99  TNT tnt;
100};
101
102static_assert(__has_trivial_copy(TNTMember), "");
103static_assert(__is_trivially_constructible(TNTMember, TNTMember), "");
104static_assert(__is_trivially_constructible(TNTMember, TNTMember &), "");
105static_assert(__is_trivially_constructible(TNTMember, const TNTMember &), "");
106static_assert(!__is_trivially_constructible(TNTMember, volatile TNTMember &), "");
107static_assert(__is_trivially_constructible(TNTMember, TNTMember &&), "");
108static_assert(__is_trivially_constructible(TNTMember, const TNTMember &&), "");
109static_assert(!__is_trivially_constructible(TNTMember, volatile TNTMember &&), "");
110
111struct NCCTNT : NonConstCopy, TNT {};
112
113static_assert(!__has_trivial_copy(NCCTNT), "");
114static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT), "");
115static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT &), "");
116static_assert(!__is_trivially_constructible(NCCTNT, const NCCTNT &), "");
117static_assert(!__is_trivially_constructible(NCCTNT, volatile NCCTNT &), "");
118static_assert(!__is_trivially_constructible(NCCTNT, NCCTNT &&), "");
119static_assert(!__is_trivially_constructible(NCCTNT, const NCCTNT &&), "");
120static_assert(!__is_trivially_constructible(NCCTNT, volatile NCCTNT &&), "");
121
122struct TemplateCtorNoMove {
123  TemplateCtorNoMove(const TemplateCtorNoMove &) = default;
124  template<typename T> TemplateCtorNoMove(T &&);
125};
126static_assert(__is_trivially_constructible(TemplateCtorNoMove, const TemplateCtorNoMove &), "");
127static_assert(!__is_trivially_constructible(TemplateCtorNoMove, TemplateCtorNoMove &&), "");
128
129struct UseTemplateCtorNoMove {
130  TemplateCtorNoMove tcnm;
131};
132static_assert(__is_trivially_constructible(UseTemplateCtorNoMove, const UseTemplateCtorNoMove &), "");
133static_assert(!__is_trivially_constructible(UseTemplateCtorNoMove, UseTemplateCtorNoMove &&), "");
134
135struct TemplateCtorNoMoveSFINAE {
136  TemplateCtorNoMoveSFINAE(const TemplateCtorNoMoveSFINAE &) = default;
137  template<typename T, typename U = typename T::error> TemplateCtorNoMoveSFINAE(T &&);
138};
139static_assert(__is_trivially_constructible(TemplateCtorNoMoveSFINAE, const TemplateCtorNoMoveSFINAE &), "");
140static_assert(__is_trivially_constructible(TemplateCtorNoMoveSFINAE, TemplateCtorNoMoveSFINAE &&), "");
141
142struct UseTemplateCtorNoMoveSFINAE {
143  TemplateCtorNoMoveSFINAE tcnm;
144};
145static_assert(__is_trivially_constructible(UseTemplateCtorNoMoveSFINAE, const UseTemplateCtorNoMoveSFINAE &), "");
146static_assert(__is_trivially_constructible(UseTemplateCtorNoMoveSFINAE, UseTemplateCtorNoMoveSFINAE &&), "");
147
148namespace 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
181namespace 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