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
8 #define EXPLICIT_PARAMETER(...) this __VA_ARGS__,
10 #define EXPLICIT_PARAMETER(Param)
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
&&), "");
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
;
30 using _
= trivially_assignable
<Trivial
>;
32 // A copy/move assignment operator for class X is trivial if it is not user-provided,
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
42 NonConstCopy
&operator=(EXPLICIT_PARAMETER(NonConstCopy
&) NonConstCopy
&) = default;
44 NonConstCopy
&operator=(EXPLICIT_PARAMETER(NonConstCopy
&&) NonConstCopy
&) = default;
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
50 using _
= not_trivially_assignable
<NonConstCopy
>;
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;
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;
80 using _
= trivially_assignable
<DefaultedSpecialMembers
>;
83 // class X has no virtual functions
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
95 template<typename T
> TemplateCtor
operator=(T
&);
97 using _
= trivially_assignable
<TemplateCtor
>;
98 struct TemplateCtorMember
{
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.
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
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
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.
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
{
225 PrivateMove
&operator=(const PrivateMove
&) = default;
227 PrivateMove
&operator=(PrivateMove
&&);
230 static_assert(__is_trivially_assignable(PrivateMove
, const PrivateMove
&), "");
231 static_assert(!__is_trivially_assignable(PrivateMove
, PrivateMove
&&), "");
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
&&), "");
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
&&), "");