1// RUN: %check_clang_tidy %s readability-static-accessed-through-instance %t -- --fix-notes -- -isystem %S/Inputs/static-accessed-through-instance
2#include <__clang_cuda_builtin_vars.h>
3
4enum OutEnum {
5 E0,
6};
7
8struct C {
9 static void foo();
10 static int x;
11 int nsx;
12 enum {
13 Anonymous,
14 };
15 enum E {
16 E1,
17 };
18 using enum OutEnum;
19 void mf() {
20 (void)&x; // OK, x is accessed inside the struct.
21 (void)&C::x; // OK, x is accessed using a qualified-id.
22 foo(); // OK, foo() is accessed inside the struct.
23 }
24 void ns() const;
25};
26
27int C::x = 0;
28
29struct CC {
30 void foo();
31 int x;
32};
33
34template <typename T> struct CT {
35 static T foo();
36 static T x;
37 int nsx;
38 void mf() {
39 (void)&x; // OK, x is accessed inside the struct.
40 (void)&C::x; // OK, x is accessed using a qualified-id.
41 foo(); // OK, foo() is accessed inside the struct.
42 }
43};
44
45// Expressions with side effects
46C &f(int, int, int, int);
47void g() {
48 f(1, 2, 3, 4).x;
49 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance [readability-static-accessed-through-instance]
50 // CHECK-MESSAGES: :[[@LINE-2]]:3: note: member base expression may carry some side effects
51 // CHECK-FIXES: {{^}} C::x;{{$}}
52}
53
54int i(int &);
55void j(int);
56C h();
57bool a();
58int k(bool);
59
60void f(C c) {
61 j(i(h().x));
62 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: static member
63 // CHECK-MESSAGES: :[[@LINE-2]]:7: note: member base expression may carry some side effects
64 // CHECK-FIXES: {{^}} j(i(C::x));{{$}}
65
66 // The execution of h() depends on the return value of a().
67 j(k(a() && h().x));
68 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: static member
69 // CHECK-MESSAGES: :[[@LINE-2]]:14: note: member base expression may carry some side effects
70 // CHECK-FIXES: {{^}} j(k(a() && C::x));{{$}}
71
72 if ([c]() {
73 c.ns();
74 return c;
75 }().x == 15)
76 ;
77 // CHECK-MESSAGES: :[[@LINE-5]]:7: warning: static member
78 // CHECK-MESSAGES: :[[@LINE-6]]:7: note: member base expression may carry some side effects
79 // CHECK-FIXES: {{^}} if (C::x == 15){{$}}
80}
81
82// Nested specifiers
83namespace N {
84struct V {
85 static int v;
86 struct T {
87 static int t;
88 struct U {
89 static int u;
90 };
91 };
92};
93}
94
95void f(N::V::T::U u) {
96 N::V v;
97 v.v = 12;
98 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
99 // CHECK-FIXES: {{^}} N::V::v = 12;{{$}}
100
101 N::V::T w;
102 w.t = 12;
103 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
104 // CHECK-FIXES: {{^}} N::V::T::t = 12;{{$}}
105
106 // u.u is not changed to N::V::T::U::u; because the nesting level is over 3.
107 u.u = 12;
108 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
109 // CHECK-FIXES: {{^}} u.u = 12;{{$}}
110
111 using B = N::V::T::U;
112 B b;
113 b.u;
114 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
115 // CHECK-FIXES: {{^}} B::u;{{$}}
116}
117
118// Templates
119template <typename T> T CT<T>::x;
120
121template <typename T> struct CCT {
122 T foo();
123 T x;
124};
125
126typedef C D;
127
128using E = D;
129
130#define FOO(c) c.foo()
131#define X(c) c.x
132
133template <typename T> void f(T t, C c) {
134 t.x; // OK, t is a template parameter.
135 c.x;
136 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
137 // CHECK-FIXES: {{^}} C::x;{{$}}
138}
139
140template <int N> struct S { static int x; };
141
142template <> struct S<0> { int x; };
143
144template <int N> void h() {
145 S<N> sN;
146 sN.x; // OK, value of N affects whether x is static or not.
147
148 S<2> s2;
149 s2.x;
150 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
151 // CHECK-FIXES: {{^}} S<2>::x;{{$}}
152}
153
154void static_through_instance() {
155 C *c1 = new C();
156 c1->foo(); // 1
157 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
158 // CHECK-FIXES: {{^}} C::foo(); // 1{{$}}
159 c1->x; // 2
160 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
161 // CHECK-FIXES: {{^}} C::x; // 2{{$}}
162 c1->Anonymous; // 3
163 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
164 // CHECK-FIXES: {{^}} C::Anonymous; // 3{{$}}
165 c1->E1; // 4
166 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
167 // CHECK-FIXES: {{^}} C::E1; // 4{{$}}
168 c1->E0; // 5
169 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
170 // CHECK-FIXES: {{^}} C::E0; // 5{{$}}
171
172 c1->nsx; // OK, nsx is a non-static member.
173
174 const C *c2 = new C();
175 c2->foo(); // 2
176 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
177 // CHECK-FIXES: {{^}} C::foo(); // 2{{$}}
178
179 C::foo(); // OK, foo() is accessed using a qualified-id.
180 C::x; // OK, x is accessed using a qualified-id.
181
182 D d;
183 d.foo();
184 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
185 // CHECK-FIXES: {{^}} D::foo();{{$}}
186 d.x;
187 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
188 // CHECK-FIXES: {{^}} D::x;{{$}}
189
190 E e;
191 e.foo();
192 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
193 // CHECK-FIXES: {{^}} E::foo();{{$}}
194 e.x;
195 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
196 // CHECK-FIXES: {{^}} E::x;{{$}}
197
198 CC *cc = new CC;
199
200 f(t: *c1, c: *c1);
201 f(t: *cc, c: *c1);
202
203 // Macros: OK, macros are not checked.
204 FOO((*c1));
205 X((*c1));
206 FOO((*cc));
207 X((*cc));
208
209 // Templates
210 CT<int> ct;
211 ct.foo();
212 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
213 // CHECK-FIXES: {{^}} CT<int>::foo();{{$}}
214 ct.x;
215 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
216 // CHECK-FIXES: {{^}} CT<int>::x;{{$}}
217 ct.nsx; // OK, nsx is a non-static member
218
219 CCT<int> cct;
220 cct.foo(); // OK, CCT has no static members.
221 cct.x; // OK, CCT has no static members.
222
223 h<4>();
224}
225
226struct SP {
227 static int I;
228} P;
229
230void usep() {
231 P.I;
232 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
233 // CHECK-FIXES: {{^}} SP::I;{{$}}
234}
235
236namespace NSP {
237struct SP {
238 static int I;
239} P;
240} // namespace NSP
241
242void usensp() {
243 NSP::P.I;
244 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
245 // CHECK-FIXES: {{^}} NSP::SP::I;{{$}}
246}
247
248// Overloaded member access operator
249struct Q {
250 static int K;
251 int y = 0;
252};
253
254int Q::K = 0;
255
256struct Qptr {
257 Q *q;
258
259 explicit Qptr(Q *qq) : q(qq) {}
260
261 Q *operator->() {
262 ++q->y;
263 return q;
264 }
265};
266
267void func(Qptr qp) {
268 qp->y = 10;
269 qp->K = 10;
270 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance [readability-static-accessed-through-instance]
271 // CHECK-MESSAGES: :[[@LINE-2]]:3: note: member base expression may carry some side effects
272 // CHECK-FIXES: {{^}} Q::K = 10;
273}
274
275namespace {
276 struct Anonymous {
277 static int I;
278 };
279}
280
281void use_anonymous() {
282 Anonymous Anon;
283 Anon.I;
284 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
285 // CHECK-FIXES: {{^}} Anonymous::I;{{$}}
286}
287
288namespace Outer {
289 inline namespace Inline {
290 struct S {
291 static int I;
292 };
293 }
294}
295
296void use_inline() {
297 Outer::S V;
298 V.I;
299 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
300 // CHECK-FIXES: {{^}} Outer::S::I;{{$}}
301}
302
303// https://bugs.llvm.org/show_bug.cgi?id=48758
304namespace Bugzilla_48758 {
305
306unsigned int x1 = threadIdx.x;
307// CHECK-MESSAGES-NOT: :[[@LINE-1]]:10: warning: static member
308unsigned int x2 = blockIdx.x;
309// CHECK-MESSAGES-NOT: :[[@LINE-1]]:10: warning: static member
310unsigned int x3 = blockDim.x;
311// CHECK-MESSAGES-NOT: :[[@LINE-1]]:10: warning: static member
312unsigned int x4 = gridDim.x;
313// CHECK-MESSAGES-NOT: :[[@LINE-1]]:10: warning: static member
314
315} // namespace Bugzilla_48758
316
317// https://github.com/llvm/llvm-project/issues/61736
318namespace llvm_issue_61736
319{
320
321struct {
322 static void f() {}
323} AnonStruct, *AnonStructPointer;
324
325class {
326 public:
327 static void f() {}
328} AnonClass, *AnonClassPointer;
329
330void testAnonymousStructAndClass() {
331 AnonStruct.f();
332 AnonStructPointer->f();
333
334 AnonClass.f();
335 AnonClassPointer->f();
336}
337
338struct Embedded {
339 struct {
340 static void f() {}
341 } static EmbeddedStruct, *EmbeddedStructPointer;
342
343 class {
344 public:
345 static void f() {}
346 } static EmbeddedClass, *EmbeddedClassPointer;
347};
348
349void testEmbeddedAnonymousStructAndClass() {
350 Embedded::EmbeddedStruct.f();
351 Embedded::EmbeddedStructPointer->f();
352
353 Embedded::EmbeddedClass.f();
354 Embedded::EmbeddedClassPointer->f();
355
356 Embedded E;
357 E.EmbeddedStruct.f();
358 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance [readability-static-accessed-through-instance]
359 // CHECK-FIXES: {{^}} llvm_issue_61736::Embedded::EmbeddedStruct.f();{{$}}
360 E.EmbeddedStructPointer->f();
361 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance [readability-static-accessed-through-instance]
362 // CHECK-FIXES: {{^}} llvm_issue_61736::Embedded::EmbeddedStructPointer->f();{{$}}
363
364 E.EmbeddedClass.f();
365 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance [readability-static-accessed-through-instance]
366 // CHECK-FIXES: {{^}} llvm_issue_61736::Embedded::EmbeddedClass.f();{{$}}
367 E.EmbeddedClassPointer->f();
368 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance [readability-static-accessed-through-instance]
369 // CHECK-FIXES: {{^}} llvm_issue_61736::Embedded::EmbeddedClassPointer->f();{{$}}
370}
371
372} // namespace llvm_issue_61736
373
374namespace PR51861 {
375 class Foo {
376 public:
377 static Foo& getInstance();
378 static int getBar();
379 };
380
381 inline int Foo::getBar() { return 42; }
382
383 void test() {
384 auto& params = Foo::getInstance();
385 params.getBar();
386 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: static member accessed through instance [readability-static-accessed-through-instance]
387 // CHECK-FIXES: {{^}} PR51861::Foo::getBar();{{$}}
388 }
389}
390
391namespace PR75163 {
392 struct Static {
393 static void call();
394 };
395
396 struct Ptr {
397 Static* operator->();
398 };
399
400 void test(Ptr& ptr) {
401 ptr->call();
402 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: static member accessed through instance [readability-static-accessed-through-instance]
403 // CHECK-MESSAGES: :[[@LINE-2]]:5: note: member base expression may carry some side effects
404 // CHECK-FIXES: {{^}} PR75163::Static::call();{{$}}
405 }
406}
407

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang-tools-extra/test/clang-tidy/checkers/readability/static-accessed-through-instance.cpp