1// RUN: %clang_cc1 -verify %s -std=c++11
2
3struct Trivial {};
4
5template<typename T> struct CopyAssign {
6  static T t;
7  void test() {
8    t = t; // expected-error +{{deleted}}
9  }
10};
11template<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};
19template<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
26struct NonTrivialCopyAssign {
27  NonTrivialCopyAssign &operator=(const NonTrivialCopyAssign &);
28};
29struct NonTrivialMoveAssign {
30  NonTrivialMoveAssign &operator=(NonTrivialMoveAssign &&);
31};
32struct AmbiguousCopyAssign {
33  AmbiguousCopyAssign &operator=(const AmbiguousCopyAssign &) volatile;
34  AmbiguousCopyAssign &operator=(const AmbiguousCopyAssign &) const;
35};
36struct AmbiguousMoveAssign {
37  AmbiguousMoveAssign &operator=(const AmbiguousMoveAssign &&);
38  AmbiguousMoveAssign &operator=(volatile AmbiguousMoveAssign &&);
39};
40struct DeletedCopyAssign {
41  DeletedCopyAssign &operator=(const DeletedCopyAssign &) = delete; // expected-note 2{{deleted}}
42};
43struct DeletedMoveAssign {
44  DeletedMoveAssign &operator=(DeletedMoveAssign &&) = delete; // expected-note 2{{deleted}}
45};
46class InaccessibleCopyAssign {
47  InaccessibleCopyAssign &operator=(const InaccessibleCopyAssign &);
48};
49class InaccessibleMoveAssign {
50  InaccessibleMoveAssign &operator=(InaccessibleMoveAssign &&);
51};
52class 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
61struct A1 {
62  union {
63    NonTrivialCopyAssign x; // expected-note {{variant field 'x' has a non-trivial copy assign}}
64  };
65};
66template struct CopyAssign<A1>; // expected-note {{here}}
67
68struct 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};
74template struct MoveAssign<A2>; // expected-note {{here}}
75
76//   -- a non-static const data member of (array of) non-class type
77struct B1 {
78  const int a; // expected-note 2{{field 'a' is of const-qualified type}}
79};
80struct 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};
83struct B3 {
84  const void *a[3];
85};
86template struct CopyAssign<B1>; // expected-note {{here}}
87template struct MoveAssign<B1>; // expected-note {{here}}
88template struct CopyAssign<B2>; // expected-note {{here}}
89template struct MoveAssign<B2>; // expected-note {{here}}
90template struct CopyAssign<B3>;
91template struct MoveAssign<B3>;
92
93//   -- a non-static data member of reference type
94struct C1 {
95  int &a; // expected-note 2{{field 'a' is of reference type 'int &'}}
96};
97template struct CopyAssign<C1>; // expected-note {{here}}
98template struct MoveAssign<C1>; // expected-note {{here}}
99
100//   -- a non-static data member of class type M that cannot be copied/moved
101struct D1 {
102  AmbiguousCopyAssign a; // expected-note {{field 'a' has multiple copy}}
103};
104struct 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};
108struct D3 {
109  DeletedCopyAssign a; // expected-note {{field 'a' has a deleted copy}}
110};
111struct 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};
115struct D5 {
116  InaccessibleCopyAssign a; // expected-note {{field 'a' has an inaccessible copy}}
117};
118struct 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};
122struct D7 {
123  const Trivial a; // expected-note 3{{field 'a' has no }}
124};
125struct D8 {
126  volatile Trivial a; // expected-note 3{{field 'a' has no }}
127};
128template struct CopyAssign<D1>; // expected-note {{here}}
129template struct MoveAssign<D2>; // expected-note {{here}}
130template struct MoveOrCopyAssign<D2>; // expected-note {{here}}
131template struct CopyAssign<D3>; // expected-note {{here}}
132template struct MoveAssign<D4>; // expected-note {{here}}
133template struct MoveOrCopyAssign<D4>; // expected-note {{here}}
134template struct CopyAssign<D5>; // expected-note {{here}}
135template struct MoveAssign<D6>; // expected-note {{here}}
136template struct MoveOrCopyAssign<D6>; // expected-note {{here}}
137template struct CopyAssign<D7>; // expected-note {{here}}
138template struct MoveAssign<D7>; // expected-note {{here}}
139template struct MoveOrCopyAssign<D7>; // expected-note {{here}}
140template struct CopyAssign<D8>; // expected-note {{here}}
141template struct MoveAssign<D8>; // expected-note {{here}}
142template struct MoveOrCopyAssign<D8>; // expected-note {{here}}
143
144//   -- a direct or virtual base that cannot be copied/moved
145struct E1 : AmbiguousCopyAssign {}; // expected-note {{base class 'AmbiguousCopyAssign' has multiple copy}}
146struct E2 : AmbiguousMoveAssign { // expected-note {{base class 'AmbiguousMoveAssign' has multiple move}}
147  E2 &operator=(E2 &&) = default; // expected-note {{here}}
148};
149struct E3 : DeletedCopyAssign {}; // expected-note {{base class 'DeletedCopyAssign' has a deleted copy}}
150struct E4 : DeletedMoveAssign { // expected-note {{base class 'DeletedMoveAssign' has a deleted move}}
151  E4 &operator=(E4 &&) = default; // expected-note {{here}}
152};
153struct E5 : InaccessibleCopyAssign {}; // expected-note {{base class 'InaccessibleCopyAssign' has an inaccessible copy}}
154struct E6 : InaccessibleMoveAssign { // expected-note {{base class 'InaccessibleMoveAssign' has an inaccessible move}}
155  E6 &operator=(E6 &&) = default; // expected-note {{here}}
156};
157template struct CopyAssign<E1>; // expected-note {{here}}
158template struct MoveAssign<E2>; // expected-note {{here}}
159template struct CopyAssign<E3>; // expected-note {{here}}
160template struct MoveAssign<E4>; // expected-note {{here}}
161template struct CopyAssign<E5>; // expected-note {{here}}
162template struct MoveAssign<E6>; // expected-note {{here}}
163
164namespace 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
178namespace Mutable {
179  struct AmbiguousCopyAssign {
180    AmbiguousCopyAssign &operator=(const AmbiguousCopyAssign &);
181    AmbiguousCopyAssign &operator=(volatile AmbiguousCopyAssign &);
182  };
183  struct X {
184    AmbiguousCopyAssign a;
185  };
186  struct Y {
187    mutable AmbiguousCopyAssign a; // expected-note {{multiple copy assignment operators}}
188  };
189}
190template struct CopyAssign<Mutable::X>;
191template struct CopyAssign<Mutable::Y>; // expected-note {{here}}
192