1 // RUN: %clang_cc1 -verify %s -std=c++11
2 
3 struct Trivial {};
4 
5 template<typename T> struct CopyAssign {
6   static T t;
7   void test() {
8     t = t; // expected-error +{{deleted}}
9   }
10 };
11 template<typename T> struct MoveAssign {
12   static T t;
13   void test() {
14     // Overload resolution will ignore a defaulted, deleted move assignment,
15     // so check for it in a different way.
16     T &(T::*f)(T&&) = &T::operator=; // expected-error +{{deleted}}
17   }
18 };
19 template<typename T> struct MoveOrCopyAssign {
20   static T t;
21   void test() {
22     t = static_cast<T&&>(t); // expected-error +{{copy assignment operator is implicitly deleted}}
23   }
24 };
25 
26 struct NonTrivialCopyAssign {
27   NonTrivialCopyAssign &operator=(const NonTrivialCopyAssign &);
28 };
29 struct NonTrivialMoveAssign {
30   NonTrivialMoveAssign &operator=(NonTrivialMoveAssign &&);
31 };
32 struct AmbiguousCopyAssign {
33   AmbiguousCopyAssign &operator=(const AmbiguousCopyAssign &);
34   AmbiguousCopyAssign &operator=(volatile AmbiguousCopyAssign &);
35 };
36 struct AmbiguousMoveAssign {
37   AmbiguousMoveAssign &operator=(const AmbiguousMoveAssign &&);
38   AmbiguousMoveAssign &operator=(volatile AmbiguousMoveAssign &&);
39 };
40 struct DeletedCopyAssign {
41   DeletedCopyAssign &operator=(const DeletedCopyAssign &) = delete; // expected-note 2{{deleted}}
42 };
43 struct DeletedMoveAssign {
44   DeletedMoveAssign &operator=(DeletedMoveAssign &&) = delete; // expected-note 2{{deleted}}
45 };
46 class InaccessibleCopyAssign {
47   InaccessibleCopyAssign &operator=(const InaccessibleCopyAssign &);
48 };
49 class InaccessibleMoveAssign {
50   InaccessibleMoveAssign &operator=(InaccessibleMoveAssign &&);
51 };
52 class NonConstCopyAssign {
53   NonConstCopyAssign &operator=(NonConstCopyAssign &);
54 };
55 
56 // A defaulted copy/move assignment operator for class X is defined as deleted
57 // if X has:
58 
59 //   -- a variant member with a non-trivial corresponding assignment operator
60 //      and X is a union-like class
61 struct A1 {
62   union {
63     NonTrivialCopyAssign x; // expected-note {{variant field 'x' has a non-trivial copy assign}}
64   };
65 };
66 template struct CopyAssign<A1>; // expected-note {{here}}
67 
68 struct A2 {
69   A2 &operator=(A2 &&) = default; // expected-note {{here}}
70   union {
71     NonTrivialMoveAssign x; // expected-note {{variant field 'x' has a non-trivial move assign}}
72   };
73 };
74 template struct MoveAssign<A2>; // expected-note {{here}}
75 
76 //   -- a non-static const data member of (array of) non-class type
77 struct B1 {
78   const int a; // expected-note 2{{field 'a' is of const-qualified type}}
79 };
80 struct B2 {
81   const void *const a[3][9][2]; // expected-note 2{{field 'a' is of const-qualified type 'const void *const [3][9][2]'}}
82 };
83 struct B3 {
84   const void *a[3];
85 };
86 template struct CopyAssign<B1>; // expected-note {{here}}
87 template struct MoveAssign<B1>; // expected-note {{here}}
88 template struct CopyAssign<B2>; // expected-note {{here}}
89 template struct MoveAssign<B2>; // expected-note {{here}}
90 template struct CopyAssign<B3>;
91 template struct MoveAssign<B3>;
92 
93 //   -- a non-static data member of reference type
94 struct C1 {
95   int &a; // expected-note 2{{field 'a' is of reference type 'int &'}}
96 };
97 template struct CopyAssign<C1>; // expected-note {{here}}
98 template struct MoveAssign<C1>; // expected-note {{here}}
99 
100 //   -- a non-static data member of class type M that cannot be copied/moved
101 struct D1 {
102   AmbiguousCopyAssign a; // expected-note {{field 'a' has multiple copy}}
103 };
104 struct D2 {
105   D2 &operator=(D2 &&) = default; // expected-note {{here}} expected-note {{copy assignment operator is implicitly deleted}}
106   AmbiguousMoveAssign a; // expected-note {{field 'a' has multiple move}}
107 };
108 struct D3 {
109   DeletedCopyAssign a; // expected-note {{field 'a' has a deleted copy}}
110 };
111 struct D4 {
112   D4 &operator=(D4 &&) = default; // expected-note {{here}} expected-note {{copy assignment operator is implicitly deleted}}
113   DeletedMoveAssign a; // expected-note {{field 'a' has a deleted move}}
114 };
115 struct D5 {
116   InaccessibleCopyAssign a; // expected-note {{field 'a' has an inaccessible copy}}
117 };
118 struct D6 {
119   D6 &operator=(D6 &&) = default; // expected-note {{here}} expected-note {{copy assignment operator is implicitly deleted}}
120   InaccessibleMoveAssign a; // expected-note {{field 'a' has an inaccessible move}}
121 };
122 struct D7 {
123   const Trivial a; // expected-note 3{{field 'a' has no }}
124 };
125 struct D8 {
126   volatile Trivial a; // expected-note 3{{field 'a' has no }}
127 };
128 template struct CopyAssign<D1>; // expected-note {{here}}
129 template struct MoveAssign<D2>; // expected-note {{here}}
130 template struct MoveOrCopyAssign<D2>; // expected-note {{here}}
131 template struct CopyAssign<D3>; // expected-note {{here}}
132 template struct MoveAssign<D4>; // expected-note {{here}}
133 template struct MoveOrCopyAssign<D4>; // expected-note {{here}}
134 template struct CopyAssign<D5>; // expected-note {{here}}
135 template struct MoveAssign<D6>; // expected-note {{here}}
136 template struct MoveOrCopyAssign<D6>; // expected-note {{here}}
137 template struct CopyAssign<D7>; // expected-note {{here}}
138 template struct MoveAssign<D7>; // expected-note {{here}}
139 template struct MoveOrCopyAssign<D7>; // expected-note {{here}}
140 template struct CopyAssign<D8>; // expected-note {{here}}
141 template struct MoveAssign<D8>; // expected-note {{here}}
142 template struct MoveOrCopyAssign<D8>; // expected-note {{here}}
143 
144 //   -- a direct or virtual base that cannot be copied/moved
145 struct E1 : AmbiguousCopyAssign {}; // expected-note {{base class 'AmbiguousCopyAssign' has multiple copy}}
146 struct E2 : AmbiguousMoveAssign { // expected-note {{base class 'AmbiguousMoveAssign' has multiple move}}
147   E2 &operator=(E2 &&) = default; // expected-note {{here}}
148 };
149 struct E3 : DeletedCopyAssign {}; // expected-note {{base class 'DeletedCopyAssign' has a deleted copy}}
150 struct E4 : DeletedMoveAssign { // expected-note {{base class 'DeletedMoveAssign' has a deleted move}}
151   E4 &operator=(E4 &&) = default; // expected-note {{here}}
152 };
153 struct E5 : InaccessibleCopyAssign {}; // expected-note {{base class 'InaccessibleCopyAssign' has an inaccessible copy}}
154 struct E6 : InaccessibleMoveAssign { // expected-note {{base class 'InaccessibleMoveAssign' has an inaccessible move}}
155   E6 &operator=(E6 &&) = default; // expected-note {{here}}
156 };
157 template struct CopyAssign<E1>; // expected-note {{here}}
158 template struct MoveAssign<E2>; // expected-note {{here}}
159 template struct CopyAssign<E3>; // expected-note {{here}}
160 template struct MoveAssign<E4>; // expected-note {{here}}
161 template struct CopyAssign<E5>; // expected-note {{here}}
162 template struct MoveAssign<E6>; // expected-note {{here}}
163 
164 namespace PR13381 {
165   struct S {
166     S &operator=(const S&);
167     S &operator=(const volatile S&) volatile = delete; // expected-note{{deleted here}}
168   };
169   struct T {
170     volatile S s; // expected-note{{field 's' has a deleted copy assignment}}
171   };
172   void g() {
173     T t;
174     t = T(); // expected-error{{object of type 'PR13381::T' cannot be assigned because its copy assignment operator is implicitly deleted}}
175   }
176 }
177