1// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-const-or-ref-data-members %t
2namespace std {
3template <typename T>
4struct unique_ptr {};
5
6template <typename T>
7struct shared_ptr {};
8} // namespace std
9
10namespace gsl {
11template <typename T>
12struct not_null {};
13} // namespace gsl
14
15struct Ok {
16 int i;
17 int *p;
18 const int *pc;
19 std::unique_ptr<int> up;
20 std::shared_ptr<int> sp;
21 gsl::not_null<int> n;
22};
23
24struct ConstMember {
25 const int c;
26 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: member 'c' of type 'const int' is const qualified [cppcoreguidelines-avoid-const-or-ref-data-members]
27};
28
29struct LvalueRefMember {
30 int &lr;
31 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'lr' of type 'int &' is a reference
32};
33
34struct ConstRefMember {
35 const int &cr;
36 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: member 'cr' of type 'const int &' is a reference
37};
38
39struct RvalueRefMember {
40 int &&rr;
41 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: member 'rr' of type 'int &&' is a reference
42};
43
44struct ConstAndRefMembers {
45 const int c;
46 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: member 'c' of type 'const int' is const qualified
47 int &lr;
48 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'lr' of type 'int &' is a reference
49 const int &cr;
50 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: member 'cr' of type 'const int &' is a reference
51 int &&rr;
52 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: member 'rr' of type 'int &&' is a reference
53};
54
55struct Foo {};
56
57struct Ok2 {
58 Foo i;
59 Foo *p;
60 const Foo *pc;
61 std::unique_ptr<Foo> up;
62 std::shared_ptr<Foo> sp;
63 gsl::not_null<Foo> n;
64};
65
66struct ConstMember2 {
67 const Foo c;
68 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: member 'c' of type 'const Foo' is const qualified
69};
70
71struct LvalueRefMember2 {
72 Foo &lr;
73 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'lr' of type 'Foo &' is a reference
74};
75
76struct ConstRefMember2 {
77 const Foo &cr;
78 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: member 'cr' of type 'const Foo &' is a reference
79};
80
81struct RvalueRefMember2 {
82 Foo &&rr;
83 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: member 'rr' of type 'Foo &&' is a reference
84};
85
86struct ConstAndRefMembers2 {
87 const Foo c;
88 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: member 'c' of type 'const Foo' is const qualified
89 Foo &lr;
90 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'lr' of type 'Foo &' is a reference
91 const Foo &cr;
92 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: member 'cr' of type 'const Foo &' is a reference
93 Foo &&rr;
94 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: member 'rr' of type 'Foo &&' is a reference
95};
96
97using ConstType = const int;
98using RefType = int &;
99using ConstRefType = const int &;
100using RefRefType = int &&;
101
102struct WithAlias {
103 ConstType c;
104 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: member 'c' of type 'ConstType' (aka 'const int') is const qualified
105 RefType lr;
106 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: member 'lr' of type 'RefType' (aka 'int &') is a reference
107 ConstRefType cr;
108 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: member 'cr' of type 'ConstRefType' (aka 'const int &') is a reference
109 RefRefType rr;
110 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: member 'rr' of type 'RefRefType' (aka 'int &&') is a reference
111};
112
113template <int N>
114using Array = int[N];
115
116struct ConstArrayMember {
117 const Array<1> c;
118 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: member 'c' of type 'const Array<1>' (aka 'const int[1]') is const qualified
119};
120
121struct LvalueRefArrayMember {
122 Array<2> &lr;
123 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: member 'lr' of type 'Array<2> &' (aka 'int (&)[2]') is a reference
124};
125
126struct ConstLvalueRefArrayMember {
127 const Array<3> &cr;
128 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: member 'cr' of type 'const Array<3> &' (aka 'const int (&)[3]') is a reference
129};
130
131struct RvalueRefArrayMember {
132 Array<4> &&rr;
133 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: member 'rr' of type 'Array<4> &&' (aka 'int (&&)[4]') is a reference
134};
135
136template <typename T>
137struct TemplatedOk {
138 T t;
139};
140
141template <typename T>
142struct TemplatedConst {
143 T t;
144 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: member 't' of type 'const int' is const qualified
145};
146
147template <typename T>
148struct TemplatedConstRef {
149 T t;
150 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: member 't' of type 'const int &' is a reference
151};
152
153template <typename T>
154struct TemplatedRefRef {
155 T t;
156 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: member 't' of type 'int &&' is a reference
157};
158
159template <typename T>
160struct TemplatedRef {
161 T t;
162 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: member 't' of type 'int &' is a reference
163};
164
165TemplatedOk<int> t1{};
166TemplatedConst<const int> t2{.t: 123};
167TemplatedConstRef<const int &> t3{.t: 123};
168TemplatedRefRef<int &&> t4{.t: 123};
169TemplatedRef<int &> t5{.t: t1.t};
170
171// Lambdas capturing const or ref members should not trigger warnings
172void lambdas()
173{
174 int x1{123};
175 const int x2{123};
176 const int& x3{123};
177 int&& x4{123};
178 int& x5{x1};
179
180 auto v1 = [x1]{};
181 auto v2 = [x2]{};
182 auto v3 = [x3]{};
183 auto v4 = [x4]{};
184 auto v5 = [x5]{};
185
186 auto r1 = [&x1]{};
187 auto r2 = [&x2]{};
188 auto r3 = [&x3]{};
189 auto r4 = [&x4]{};
190 auto r5 = [&x5]{};
191
192 auto iv = [=]{
193 auto c1 = x1;
194 auto c2 = x2;
195 auto c3 = x3;
196 auto c4 = x4;
197 auto c5 = x5;
198 };
199
200 auto ir = [&]{
201 auto c1 = x1;
202 auto c2 = x2;
203 auto c3 = x3;
204 auto c4 = x4;
205 auto c5 = x5;
206 };
207}
208
209struct NonCopyableWithRef
210{
211 NonCopyableWithRef(NonCopyableWithRef const&) = delete;
212 NonCopyableWithRef& operator=(NonCopyableWithRef const&) = delete;
213 NonCopyableWithRef(NonCopyableWithRef&&) = default;
214 NonCopyableWithRef& operator=(NonCopyableWithRef&&) = default;
215
216 int& x;
217 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'x' of type 'int &' is a reference
218};
219
220struct NonMovableWithRef
221{
222 NonMovableWithRef(NonMovableWithRef const&) = default;
223 NonMovableWithRef& operator=(NonMovableWithRef const&) = default;
224 NonMovableWithRef(NonMovableWithRef&&) = delete;
225 NonMovableWithRef& operator=(NonMovableWithRef&&) = delete;
226
227 int& x;
228 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'x' of type 'int &' is a reference
229};
230
231struct NonCopyableNonMovableWithRef
232{
233 NonCopyableNonMovableWithRef(NonCopyableNonMovableWithRef const&) = delete;
234 NonCopyableNonMovableWithRef(NonCopyableNonMovableWithRef&&) = delete;
235 NonCopyableNonMovableWithRef& operator=(NonCopyableNonMovableWithRef const&) = delete;
236 NonCopyableNonMovableWithRef& operator=(NonCopyableNonMovableWithRef&&) = delete;
237
238 int& x; // OK, non copyable nor movable
239};
240
241struct NonCopyable
242{
243 NonCopyable(NonCopyable const&) = delete;
244 NonCopyable& operator=(NonCopyable const&) = delete;
245 NonCopyable(NonCopyable&&) = default;
246 NonCopyable& operator=(NonCopyable&&) = default;
247};
248
249struct NonMovable
250{
251 NonMovable(NonMovable const&) = default;
252 NonMovable& operator=(NonMovable const&) = default;
253 NonMovable(NonMovable&&) = delete;
254 NonMovable& operator=(NonMovable&&) = delete;
255};
256
257struct NonCopyableNonMovable
258{
259 NonCopyableNonMovable(NonCopyableNonMovable const&) = delete;
260 NonCopyableNonMovable(NonCopyableNonMovable&&) = delete;
261 NonCopyableNonMovable& operator=(NonCopyableNonMovable const&) = delete;
262 NonCopyableNonMovable& operator=(NonCopyableNonMovable&&) = delete;
263};
264
265// Test inheritance
266struct InheritFromNonCopyable : NonCopyable
267{
268 int& x;
269 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'x' of type 'int &' is a reference
270};
271
272struct InheritFromNonMovable : NonMovable
273{
274 int& x;
275 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'x' of type 'int &' is a reference
276};
277
278struct InheritFromNonCopyableNonMovable : NonCopyableNonMovable
279{
280 int& x; // OK, non copyable nor movable
281};
282
283struct InheritBothFromNonCopyableAndNonMovable : NonCopyable, NonMovable
284{
285 int& x; // OK, non copyable nor movable
286};
287
288// Test composition
289struct ContainsNonCopyable
290{
291 NonCopyable x;
292 int& y;
293 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'y' of type 'int &' is a reference
294};
295
296struct ContainsNonMovable
297{
298 NonMovable x;
299 int& y;
300 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: member 'y' of type 'int &' is a reference
301};
302
303struct ContainsNonCopyableNonMovable
304{
305 NonCopyableNonMovable x;
306 int& y; // OK, non copyable nor movable
307};
308
309struct ContainsBothNonCopyableAndNonMovable
310{
311 NonCopyable x;
312 NonMovable y;
313 int& z; // OK, non copyable nor movable
314};
315
316// If copies are deleted and moves are not declared, moves are not implicitly declared,
317// so the class is also not movable and we should not warn
318struct NonCopyableMovesNotDeclared
319{
320 NonCopyableMovesNotDeclared(NonCopyableMovesNotDeclared const&) = delete;
321 NonCopyableMovesNotDeclared& operator=(NonCopyableMovesNotDeclared const&) = delete;
322
323 int& x; // OK, non copyable nor movable
324};
325
326// If moves are deleted but copies are not declared, copies are implicitly deleted,
327// so the class is also not copyable and we should not warn
328struct NonMovableCopiesNotDeclared
329{
330 NonMovableCopiesNotDeclared(NonMovableCopiesNotDeclared&&) = delete;
331 NonMovableCopiesNotDeclared& operator=(NonMovableCopiesNotDeclared&&) = delete;
332
333 int& x; // OK, non copyable nor movable
334};
335

source code of clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-const-or-ref-data-members.cpp