[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / CXX / special / class.copy / p25-0x.cpp
blobc13c686bd6b540cd20f21ba62738dd5d9def250d
1 // RUN: %clang_cc1 -std=c++11 -verify %s -Wno-deprecated-builtins
2 // RUN: %clang_cc1 -std=c++11 -verify %s -Wno-deprecated-builtins -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14
3 // RUN: %clang_cc1 -fsyntax-only -std=c++2b -DDEDUCING_THIS -Wno-deprecated-builtins %s -verify
5 // expected-no-diagnostics
7 #if DEDUCING_THIS
8 #define EXPLICIT_PARAMETER(...) this __VA_ARGS__,
9 #else
10 #define EXPLICIT_PARAMETER(Param)
11 #endif
14 template<typename T, bool B> struct trivially_assignable_check {
15 static_assert(B == __has_trivial_assign(T), "");
16 static_assert(B == __is_trivially_assignable(T&, T), "");
17 static_assert(B == __is_trivially_assignable(T&, const T &), "");
18 static_assert(B == __is_trivially_assignable(T&, T &&), "");
19 static_assert(B == __is_trivially_assignable(T&&, T), "");
20 static_assert(B == __is_trivially_assignable(T&&, const T &), "");
21 static_assert(B == __is_trivially_assignable(T&&, T &&), "");
22 typedef void type;
24 template<typename T> using trivially_assignable =
25 typename trivially_assignable_check<T, true>::type;
26 template<typename T> using not_trivially_assignable =
27 typename trivially_assignable_check<T, false>::type;
29 struct Trivial {};
30 using _ = trivially_assignable<Trivial>;
32 // A copy/move assignment operator for class X is trivial if it is not user-provided,
33 struct UserProvided {
34 UserProvided &operator=(EXPLICIT_PARAMETER(UserProvided&)
35 const UserProvided &);
37 using _ = not_trivially_assignable<UserProvided>;
39 // its declared parameter type is the same as if it had been implicitly
40 // declared,
41 struct NonConstCopy {
42 NonConstCopy &operator=(EXPLICIT_PARAMETER(NonConstCopy&) NonConstCopy &) = default;
43 #if DEDUCING_THIS
44 NonConstCopy &operator=(EXPLICIT_PARAMETER(NonConstCopy&&) NonConstCopy &) = default;
45 #endif
47 #if defined(CLANG_ABI_COMPAT) && CLANG_ABI_COMPAT <= 14
48 // Up until (and including) Clang 14, non-const copy assignment operators were not trivial because
49 // of dr2171
50 using _ = not_trivially_assignable<NonConstCopy>;
51 #else
52 // In the latest Clang version, all defaulted assignment operators are trivial, even if non-const,
53 // because dr2171 is fixed
54 static_assert(__has_trivial_assign(NonConstCopy), "");
55 static_assert(__is_trivially_assignable(NonConstCopy &, NonConstCopy &), "");
56 static_assert(!__is_trivially_assignable(NonConstCopy &, const NonConstCopy &), "");
57 static_assert(!__is_trivially_assignable(NonConstCopy &, NonConstCopy), "");
58 static_assert(!__is_trivially_assignable(NonConstCopy &, NonConstCopy &&), "");
59 static_assert(__is_trivially_assignable(NonConstCopy &&, NonConstCopy &), "");
60 static_assert(!__is_trivially_assignable(NonConstCopy &&, const NonConstCopy &), "");
61 static_assert(!__is_trivially_assignable(NonConstCopy &&, NonConstCopy), "");
62 static_assert(!__is_trivially_assignable(NonConstCopy &&, NonConstCopy &&), "");
64 struct DefaultedSpecialMembers {
65 DefaultedSpecialMembers &operator=(EXPLICIT_PARAMETER(DefaultedSpecialMembers&)
66 const DefaultedSpecialMembers &) = default;
67 DefaultedSpecialMembers &operator=(EXPLICIT_PARAMETER(DefaultedSpecialMembers&)
68 DefaultedSpecialMembers &) = default;
69 DefaultedSpecialMembers &operator=(EXPLICIT_PARAMETER(DefaultedSpecialMembers&)
70 DefaultedSpecialMembers &&) = default;
71 #if DEDUCING_THIS
72 DefaultedSpecialMembers &operator=(EXPLICIT_PARAMETER(DefaultedSpecialMembers&&)
73 const DefaultedSpecialMembers &) = default;
74 DefaultedSpecialMembers &operator=(EXPLICIT_PARAMETER(DefaultedSpecialMembers&&)
75 DefaultedSpecialMembers &) = default;
76 DefaultedSpecialMembers &operator=(EXPLICIT_PARAMETER(DefaultedSpecialMembers&&)
77 DefaultedSpecialMembers &&) = default;
78 #endif
80 using _ = trivially_assignable<DefaultedSpecialMembers>;
81 #endif
83 // class X has no virtual functions
84 struct VFn {
85 virtual void f();
87 using _ = not_trivially_assignable<VFn>;
89 // and no virtual base classes
90 struct VBase : virtual Trivial {};
91 using _ = not_trivially_assignable<VBase>;
93 // and the assignment operator selected to copy/move each [direct subobject] is trivial
94 struct TemplateCtor {
95 template<typename T> TemplateCtor operator=(T &);
97 using _ = trivially_assignable<TemplateCtor>;
98 struct TemplateCtorMember {
99 TemplateCtor tc;
101 using _ = trivially_assignable<TemplateCtorMember>;
102 struct MutableTemplateCtorMember {
103 mutable TemplateCtor mtc;
105 static_assert(!__is_trivially_assignable(MutableTemplateCtorMember, const MutableTemplateCtorMember &), "");
106 static_assert(__is_trivially_assignable(MutableTemplateCtorMember, MutableTemplateCtorMember &&), "");
108 // Both trivial and non-trivial special members.
109 struct TNT {
110 TNT &operator=(EXPLICIT_PARAMETER(TNT&) const TNT &) = default; // trivial
111 TNT &operator=(EXPLICIT_PARAMETER(TNT&) TNT &); // non-trivial
112 TNT &operator=(EXPLICIT_PARAMETER(TNT&) TNT &&) = default; // trivial
113 TNT &operator=(EXPLICIT_PARAMETER(TNT&) const TNT &&); // non-trivial
114 #if DEDUCING_THIS
115 TNT &operator=(this TNT&&, const TNT &) = default; // trivial
116 TNT &operator=(this TNT&&, TNT &); // non-trivial
117 TNT &operator=(this TNT&&, TNT &&) = default; // trivial
118 TNT &operator=(this TNT&&, const TNT &&); // non-trivial
119 #endif
122 static_assert(!__has_trivial_assign(TNT), "lie deliberately for gcc compatibility");
123 static_assert(__is_trivially_assignable(TNT, TNT), "");
124 static_assert(!__is_trivially_assignable(TNT, TNT &), "");
125 static_assert(__is_trivially_assignable(TNT, const TNT &), "");
126 static_assert(!__is_trivially_assignable(TNT, volatile TNT &), "");
127 static_assert(__is_trivially_assignable(TNT, TNT &&), "");
128 static_assert(!__is_trivially_assignable(TNT, const TNT &&), "");
129 static_assert(!__is_trivially_assignable(TNT, volatile TNT &&), "");
131 // This has only trivial special members.
132 struct DerivedFromTNT : TNT {};
134 static_assert(__has_trivial_assign(DerivedFromTNT), "");
135 static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT), "");
136 static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT &), "");
137 static_assert(__is_trivially_assignable(DerivedFromTNT, const DerivedFromTNT &), "");
138 static_assert(!__is_trivially_assignable(DerivedFromTNT, volatile DerivedFromTNT &), "");
139 static_assert(__is_trivially_assignable(DerivedFromTNT, DerivedFromTNT &&), "");
140 static_assert(__is_trivially_assignable(DerivedFromTNT, const DerivedFromTNT &&), "");
141 static_assert(!__is_trivially_assignable(DerivedFromTNT, volatile DerivedFromTNT &&), "");
143 // This has only trivial special members.
144 struct TNTMember {
145 TNT tnt;
148 static_assert(__has_trivial_assign(TNTMember), "");
149 static_assert(__is_trivially_assignable(TNTMember, TNTMember), "");
150 static_assert(__is_trivially_assignable(TNTMember, TNTMember &), "");
151 static_assert(__is_trivially_assignable(TNTMember, const TNTMember &), "");
152 static_assert(!__is_trivially_assignable(TNTMember, volatile TNTMember &), "");
153 static_assert(__is_trivially_assignable(TNTMember, TNTMember &&), "");
154 static_assert(__is_trivially_assignable(TNTMember, const TNTMember &&), "");
155 static_assert(!__is_trivially_assignable(TNTMember, volatile TNTMember &&), "");
157 struct NCCTNT : NonConstCopy, TNT {};
159 static_assert(!__has_trivial_assign(NCCTNT), "");
160 static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT), "");
161 static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT &), "");
162 static_assert(!__is_trivially_assignable(NCCTNT, const NCCTNT &), "");
163 static_assert(!__is_trivially_assignable(NCCTNT, volatile NCCTNT &), "");
164 static_assert(!__is_trivially_assignable(NCCTNT, NCCTNT &&), "");
165 static_assert(!__is_trivially_assignable(NCCTNT, const NCCTNT &&), "");
166 static_assert(!__is_trivially_assignable(NCCTNT, volatile NCCTNT &&), "");
168 struct MultipleTrivial {
169 // All four of these are trivial.
170 MultipleTrivial &operator=(const MultipleTrivial &) & = default;
171 MultipleTrivial &operator=(const MultipleTrivial &) && = default;
172 MultipleTrivial &operator=(MultipleTrivial &&) & = default;
173 MultipleTrivial &operator=(MultipleTrivial &&) && = default;
176 using _ = trivially_assignable<MultipleTrivial>;
178 struct RefQualifier {
179 RefQualifier &operator=(const RefQualifier &) & = default;
180 RefQualifier &operator=(const RefQualifier &) &&;
181 RefQualifier &operator=(RefQualifier &&) &;
182 RefQualifier &operator=(RefQualifier &&) && = default;
184 struct DerivedFromRefQualifier : RefQualifier {
185 // Both of these call the trivial copy operation.
186 DerivedFromRefQualifier &operator=(const DerivedFromRefQualifier &) & = default;
187 DerivedFromRefQualifier &operator=(const DerivedFromRefQualifier &) && = default;
188 // Both of these call the non-trivial move operation.
189 DerivedFromRefQualifier &operator=(DerivedFromRefQualifier &&) & = default;
190 DerivedFromRefQualifier &operator=(DerivedFromRefQualifier &&) && = default;
192 static_assert(__is_trivially_assignable(DerivedFromRefQualifier&, const DerivedFromRefQualifier&), "");
193 static_assert(__is_trivially_assignable(DerivedFromRefQualifier&&, const DerivedFromRefQualifier&), "");
194 static_assert(!__is_trivially_assignable(DerivedFromRefQualifier&, DerivedFromRefQualifier&&), "");
195 static_assert(!__is_trivially_assignable(DerivedFromRefQualifier&&, DerivedFromRefQualifier&&), "");
197 struct TemplateAssignNoMove {
198 TemplateAssignNoMove &operator=(const TemplateAssignNoMove &) = default;
199 template<typename T> TemplateAssignNoMove &operator=(T &&);
201 static_assert(__is_trivially_assignable(TemplateAssignNoMove, const TemplateAssignNoMove &), "");
202 static_assert(!__is_trivially_assignable(TemplateAssignNoMove, TemplateAssignNoMove &&), "");
204 struct UseTemplateAssignNoMove {
205 TemplateAssignNoMove tanm;
207 static_assert(__is_trivially_assignable(UseTemplateAssignNoMove, const UseTemplateAssignNoMove &), "");
208 static_assert(!__is_trivially_assignable(UseTemplateAssignNoMove, UseTemplateAssignNoMove &&), "");
210 struct TemplateAssignNoMoveSFINAE {
211 TemplateAssignNoMoveSFINAE &operator=(const TemplateAssignNoMoveSFINAE &) = default;
212 template<typename T, typename U = typename T::error> TemplateAssignNoMoveSFINAE &operator=(T &&);
214 static_assert(__is_trivially_assignable(TemplateAssignNoMoveSFINAE, const TemplateAssignNoMoveSFINAE &), "");
215 static_assert(__is_trivially_assignable(TemplateAssignNoMoveSFINAE, TemplateAssignNoMoveSFINAE &&), "");
217 struct UseTemplateAssignNoMoveSFINAE {
218 TemplateAssignNoMoveSFINAE tanm;
220 static_assert(__is_trivially_assignable(UseTemplateAssignNoMoveSFINAE, const UseTemplateAssignNoMoveSFINAE &), "");
221 static_assert(__is_trivially_assignable(UseTemplateAssignNoMoveSFINAE, UseTemplateAssignNoMoveSFINAE &&), "");
223 namespace TrivialityDependsOnImplicitDeletion {
224 struct PrivateMove {
225 PrivateMove &operator=(const PrivateMove &) = default;
226 private:
227 PrivateMove &operator=(PrivateMove &&);
228 friend class Access;
230 static_assert(__is_trivially_assignable(PrivateMove, const PrivateMove &), "");
231 static_assert(!__is_trivially_assignable(PrivateMove, PrivateMove &&), "");
233 struct NoAccess {
234 PrivateMove pm;
235 // NoAccess's move would be deleted, so is suppressed,
236 // so moves of it use PrivateMove's copy ctor, which is trivial.
238 static_assert(__is_trivially_assignable(NoAccess, const NoAccess &), "");
239 static_assert(__is_trivially_assignable(NoAccess, NoAccess &&), "");
240 struct TopNoAccess : NoAccess {};
241 static_assert(__is_trivially_assignable(TopNoAccess, const TopNoAccess &), "");
242 static_assert(__is_trivially_assignable(TopNoAccess, TopNoAccess &&), "");
244 struct Access {
245 PrivateMove pm;
246 // NoAccess's move would *not* be deleted, so is *not* suppressed,
247 // so moves of it use PrivateMove's move ctor, which is not trivial.
249 static_assert(__is_trivially_assignable(Access, const Access &), "");
250 static_assert(!__is_trivially_assignable(Access, Access &&), "");
251 struct TopAccess : Access {};
252 static_assert(__is_trivially_assignable(TopAccess, const TopAccess &), "");
253 static_assert(!__is_trivially_assignable(TopAccess, TopAccess &&), "");