1*37b6ba96SPiotr Zegar // RUN: %check_clang_tidy %s readability-static-accessed-through-instance %t -- --fix-notes -- -isystem %S/Inputs/static-accessed-through-instance
289a1d03eSRichard #include <__clang_cuda_builtin_vars.h>
389a1d03eSRichard
4edd6a339SCongcong Cai enum OutEnum {
5edd6a339SCongcong Cai E0,
6edd6a339SCongcong Cai };
7edd6a339SCongcong Cai
889a1d03eSRichard struct C {
989a1d03eSRichard static void foo();
1089a1d03eSRichard static int x;
1189a1d03eSRichard int nsx;
12edd6a339SCongcong Cai enum {
13edd6a339SCongcong Cai Anonymous,
14edd6a339SCongcong Cai };
15edd6a339SCongcong Cai enum E {
16edd6a339SCongcong Cai E1,
17edd6a339SCongcong Cai };
18edd6a339SCongcong Cai using enum OutEnum;
mfC1989a1d03eSRichard void mf() {
2089a1d03eSRichard (void)&x; // OK, x is accessed inside the struct.
2189a1d03eSRichard (void)&C::x; // OK, x is accessed using a qualified-id.
2289a1d03eSRichard foo(); // OK, foo() is accessed inside the struct.
2389a1d03eSRichard }
2489a1d03eSRichard void ns() const;
2589a1d03eSRichard };
2689a1d03eSRichard
2789a1d03eSRichard int C::x = 0;
2889a1d03eSRichard
2989a1d03eSRichard struct CC {
3089a1d03eSRichard void foo();
3189a1d03eSRichard int x;
3289a1d03eSRichard };
3389a1d03eSRichard
3489a1d03eSRichard template <typename T> struct CT {
3589a1d03eSRichard static T foo();
3689a1d03eSRichard static T x;
3789a1d03eSRichard int nsx;
mfCT3889a1d03eSRichard void mf() {
3989a1d03eSRichard (void)&x; // OK, x is accessed inside the struct.
4089a1d03eSRichard (void)&C::x; // OK, x is accessed using a qualified-id.
4189a1d03eSRichard foo(); // OK, foo() is accessed inside the struct.
4289a1d03eSRichard }
4389a1d03eSRichard };
4489a1d03eSRichard
4589a1d03eSRichard // Expressions with side effects
4689a1d03eSRichard C &f(int, int, int, int);
g()4789a1d03eSRichard void g() {
4889a1d03eSRichard f(1, 2, 3, 4).x;
4989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance [readability-static-accessed-through-instance]
50*37b6ba96SPiotr Zegar // CHECK-MESSAGES: :[[@LINE-2]]:3: note: member base expression may carry some side effects
51*37b6ba96SPiotr Zegar // CHECK-FIXES: {{^}} C::x;{{$}}
5289a1d03eSRichard }
5389a1d03eSRichard
5489a1d03eSRichard int i(int &);
5589a1d03eSRichard void j(int);
5689a1d03eSRichard C h();
5789a1d03eSRichard bool a();
5889a1d03eSRichard int k(bool);
5989a1d03eSRichard
f(C c)6089a1d03eSRichard void f(C c) {
6189a1d03eSRichard j(i(h().x));
6289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: static member
63*37b6ba96SPiotr Zegar // CHECK-MESSAGES: :[[@LINE-2]]:7: note: member base expression may carry some side effects
64*37b6ba96SPiotr Zegar // CHECK-FIXES: {{^}} j(i(C::x));{{$}}
6589a1d03eSRichard
6689a1d03eSRichard // The execution of h() depends on the return value of a().
6789a1d03eSRichard j(k(a() && h().x));
6889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: static member
69*37b6ba96SPiotr Zegar // CHECK-MESSAGES: :[[@LINE-2]]:14: note: member base expression may carry some side effects
70*37b6ba96SPiotr Zegar // CHECK-FIXES: {{^}} j(k(a() && C::x));{{$}}
7189a1d03eSRichard
7289a1d03eSRichard if ([c]() {
7389a1d03eSRichard c.ns();
7489a1d03eSRichard return c;
7589a1d03eSRichard }().x == 15)
7689a1d03eSRichard ;
7789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-5]]:7: warning: static member
78*37b6ba96SPiotr Zegar // CHECK-MESSAGES: :[[@LINE-6]]:7: note: member base expression may carry some side effects
79*37b6ba96SPiotr Zegar // CHECK-FIXES: {{^}} if (C::x == 15){{$}}
8089a1d03eSRichard }
8189a1d03eSRichard
8289a1d03eSRichard // Nested specifiers
8389a1d03eSRichard namespace N {
8489a1d03eSRichard struct V {
8589a1d03eSRichard static int v;
8689a1d03eSRichard struct T {
8789a1d03eSRichard static int t;
8889a1d03eSRichard struct U {
8989a1d03eSRichard static int u;
9089a1d03eSRichard };
9189a1d03eSRichard };
9289a1d03eSRichard };
9389a1d03eSRichard }
9489a1d03eSRichard
f(N::V::T::U u)9589a1d03eSRichard void f(N::V::T::U u) {
9689a1d03eSRichard N::V v;
9789a1d03eSRichard v.v = 12;
9889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
9989a1d03eSRichard // CHECK-FIXES: {{^}} N::V::v = 12;{{$}}
10089a1d03eSRichard
10189a1d03eSRichard N::V::T w;
10289a1d03eSRichard w.t = 12;
10389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
10489a1d03eSRichard // CHECK-FIXES: {{^}} N::V::T::t = 12;{{$}}
10589a1d03eSRichard
10689a1d03eSRichard // u.u is not changed to N::V::T::U::u; because the nesting level is over 3.
10789a1d03eSRichard u.u = 12;
10889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
10989a1d03eSRichard // CHECK-FIXES: {{^}} u.u = 12;{{$}}
11089a1d03eSRichard
11189a1d03eSRichard using B = N::V::T::U;
11289a1d03eSRichard B b;
11389a1d03eSRichard b.u;
11489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
11589a1d03eSRichard // CHECK-FIXES: {{^}} B::u;{{$}}
11689a1d03eSRichard }
11789a1d03eSRichard
11889a1d03eSRichard // Templates
11989a1d03eSRichard template <typename T> T CT<T>::x;
12089a1d03eSRichard
12189a1d03eSRichard template <typename T> struct CCT {
12289a1d03eSRichard T foo();
12389a1d03eSRichard T x;
12489a1d03eSRichard };
12589a1d03eSRichard
12689a1d03eSRichard typedef C D;
12789a1d03eSRichard
12889a1d03eSRichard using E = D;
12989a1d03eSRichard
13089a1d03eSRichard #define FOO(c) c.foo()
13189a1d03eSRichard #define X(c) c.x
13289a1d03eSRichard
f(T t,C c)13389a1d03eSRichard template <typename T> void f(T t, C c) {
13489a1d03eSRichard t.x; // OK, t is a template parameter.
13589a1d03eSRichard c.x;
13689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
13789a1d03eSRichard // CHECK-FIXES: {{^}} C::x;{{$}}
13889a1d03eSRichard }
13989a1d03eSRichard
14089a1d03eSRichard template <int N> struct S { static int x; };
14189a1d03eSRichard
14289a1d03eSRichard template <> struct S<0> { int x; };
14389a1d03eSRichard
h()14489a1d03eSRichard template <int N> void h() {
14589a1d03eSRichard S<N> sN;
14689a1d03eSRichard sN.x; // OK, value of N affects whether x is static or not.
14789a1d03eSRichard
14889a1d03eSRichard S<2> s2;
14989a1d03eSRichard s2.x;
15089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
15189a1d03eSRichard // CHECK-FIXES: {{^}} S<2>::x;{{$}}
15289a1d03eSRichard }
15389a1d03eSRichard
static_through_instance()15489a1d03eSRichard void static_through_instance() {
15589a1d03eSRichard C *c1 = new C();
15689a1d03eSRichard c1->foo(); // 1
15789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
15889a1d03eSRichard // CHECK-FIXES: {{^}} C::foo(); // 1{{$}}
15989a1d03eSRichard c1->x; // 2
16089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
16189a1d03eSRichard // CHECK-FIXES: {{^}} C::x; // 2{{$}}
162edd6a339SCongcong Cai c1->Anonymous; // 3
163edd6a339SCongcong Cai // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
164edd6a339SCongcong Cai // CHECK-FIXES: {{^}} C::Anonymous; // 3{{$}}
165edd6a339SCongcong Cai c1->E1; // 4
166edd6a339SCongcong Cai // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
167edd6a339SCongcong Cai // CHECK-FIXES: {{^}} C::E1; // 4{{$}}
168edd6a339SCongcong Cai c1->E0; // 5
169edd6a339SCongcong Cai // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
170edd6a339SCongcong Cai // CHECK-FIXES: {{^}} C::E0; // 5{{$}}
171edd6a339SCongcong Cai
17289a1d03eSRichard c1->nsx; // OK, nsx is a non-static member.
17389a1d03eSRichard
17489a1d03eSRichard const C *c2 = new C();
17589a1d03eSRichard c2->foo(); // 2
17689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
17789a1d03eSRichard // CHECK-FIXES: {{^}} C::foo(); // 2{{$}}
17889a1d03eSRichard
17989a1d03eSRichard C::foo(); // OK, foo() is accessed using a qualified-id.
18089a1d03eSRichard C::x; // OK, x is accessed using a qualified-id.
18189a1d03eSRichard
18289a1d03eSRichard D d;
18389a1d03eSRichard d.foo();
18489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
18589a1d03eSRichard // CHECK-FIXES: {{^}} D::foo();{{$}}
18689a1d03eSRichard d.x;
18789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
18889a1d03eSRichard // CHECK-FIXES: {{^}} D::x;{{$}}
18989a1d03eSRichard
19089a1d03eSRichard E e;
19189a1d03eSRichard e.foo();
19289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
19389a1d03eSRichard // CHECK-FIXES: {{^}} E::foo();{{$}}
19489a1d03eSRichard e.x;
19589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
19689a1d03eSRichard // CHECK-FIXES: {{^}} E::x;{{$}}
19789a1d03eSRichard
19889a1d03eSRichard CC *cc = new CC;
19989a1d03eSRichard
20089a1d03eSRichard f(*c1, *c1);
20189a1d03eSRichard f(*cc, *c1);
20289a1d03eSRichard
20389a1d03eSRichard // Macros: OK, macros are not checked.
20489a1d03eSRichard FOO((*c1));
20589a1d03eSRichard X((*c1));
20689a1d03eSRichard FOO((*cc));
20789a1d03eSRichard X((*cc));
20889a1d03eSRichard
20989a1d03eSRichard // Templates
21089a1d03eSRichard CT<int> ct;
21189a1d03eSRichard ct.foo();
21289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
21389a1d03eSRichard // CHECK-FIXES: {{^}} CT<int>::foo();{{$}}
21489a1d03eSRichard ct.x;
21589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
21689a1d03eSRichard // CHECK-FIXES: {{^}} CT<int>::x;{{$}}
21789a1d03eSRichard ct.nsx; // OK, nsx is a non-static member
21889a1d03eSRichard
21989a1d03eSRichard CCT<int> cct;
22089a1d03eSRichard cct.foo(); // OK, CCT has no static members.
22189a1d03eSRichard cct.x; // OK, CCT has no static members.
22289a1d03eSRichard
22389a1d03eSRichard h<4>();
22489a1d03eSRichard }
22589a1d03eSRichard
22689a1d03eSRichard struct SP {
22789a1d03eSRichard static int I;
22889a1d03eSRichard } P;
22989a1d03eSRichard
usep()23089a1d03eSRichard void usep() {
23189a1d03eSRichard P.I;
23289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
23389a1d03eSRichard // CHECK-FIXES: {{^}} SP::I;{{$}}
23489a1d03eSRichard }
23589a1d03eSRichard
23689a1d03eSRichard namespace NSP {
23789a1d03eSRichard struct SP {
23889a1d03eSRichard static int I;
23989a1d03eSRichard } P;
24089a1d03eSRichard } // namespace NSP
24189a1d03eSRichard
usensp()24289a1d03eSRichard void usensp() {
24389a1d03eSRichard NSP::P.I;
24489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
24589a1d03eSRichard // CHECK-FIXES: {{^}} NSP::SP::I;{{$}}
24689a1d03eSRichard }
24789a1d03eSRichard
24889a1d03eSRichard // Overloaded member access operator
24989a1d03eSRichard struct Q {
25089a1d03eSRichard static int K;
25189a1d03eSRichard int y = 0;
25289a1d03eSRichard };
25389a1d03eSRichard
25489a1d03eSRichard int Q::K = 0;
25589a1d03eSRichard
25689a1d03eSRichard struct Qptr {
25789a1d03eSRichard Q *q;
25889a1d03eSRichard
QptrQptr25989a1d03eSRichard explicit Qptr(Q *qq) : q(qq) {}
26089a1d03eSRichard
operator ->Qptr26189a1d03eSRichard Q *operator->() {
26289a1d03eSRichard ++q->y;
26389a1d03eSRichard return q;
26489a1d03eSRichard }
26589a1d03eSRichard };
26689a1d03eSRichard
func(Qptr qp)26789a1d03eSRichard int func(Qptr qp) {
268*37b6ba96SPiotr Zegar qp->y = 10;
269*37b6ba96SPiotr Zegar qp->K = 10;
270*37b6ba96SPiotr Zegar // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance [readability-static-accessed-through-instance]
271*37b6ba96SPiotr Zegar // CHECK-MESSAGES: :[[@LINE-2]]:3: note: member base expression may carry some side effects
272*37b6ba96SPiotr Zegar // CHECK-FIXES: {{^}} Q::K = 10;
27389a1d03eSRichard }
27489a1d03eSRichard
27589a1d03eSRichard namespace {
27689a1d03eSRichard struct Anonymous {
27789a1d03eSRichard static int I;
27889a1d03eSRichard };
27989a1d03eSRichard }
28089a1d03eSRichard
use_anonymous()28189a1d03eSRichard void use_anonymous() {
28289a1d03eSRichard Anonymous Anon;
28389a1d03eSRichard Anon.I;
28489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
28589a1d03eSRichard // CHECK-FIXES: {{^}} Anonymous::I;{{$}}
28689a1d03eSRichard }
28789a1d03eSRichard
28889a1d03eSRichard namespace Outer {
28989a1d03eSRichard inline namespace Inline {
29089a1d03eSRichard struct S {
29189a1d03eSRichard static int I;
29289a1d03eSRichard };
29389a1d03eSRichard }
29489a1d03eSRichard }
29589a1d03eSRichard
use_inline()29689a1d03eSRichard void use_inline() {
29789a1d03eSRichard Outer::S V;
29889a1d03eSRichard V.I;
29989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member
30089a1d03eSRichard // CHECK-FIXES: {{^}} Outer::S::I;{{$}}
30189a1d03eSRichard }
30289a1d03eSRichard
30389a1d03eSRichard // https://bugs.llvm.org/show_bug.cgi?id=48758
30489a1d03eSRichard namespace Bugzilla_48758 {
30589a1d03eSRichard
30689a1d03eSRichard unsigned int x1 = threadIdx.x;
30789a1d03eSRichard // CHECK-MESSAGES-NOT: :[[@LINE-1]]:10: warning: static member
30889a1d03eSRichard unsigned int x2 = blockIdx.x;
30989a1d03eSRichard // CHECK-MESSAGES-NOT: :[[@LINE-1]]:10: warning: static member
31089a1d03eSRichard unsigned int x3 = blockDim.x;
31189a1d03eSRichard // CHECK-MESSAGES-NOT: :[[@LINE-1]]:10: warning: static member
31289a1d03eSRichard unsigned int x4 = gridDim.x;
31389a1d03eSRichard // CHECK-MESSAGES-NOT: :[[@LINE-1]]:10: warning: static member
31489a1d03eSRichard
31589a1d03eSRichard } // namespace Bugzilla_48758
3163afe3dbfSAMS21
3173afe3dbfSAMS21 // https://github.com/llvm/llvm-project/issues/61736
3183afe3dbfSAMS21 namespace llvm_issue_61736
3193afe3dbfSAMS21 {
3203afe3dbfSAMS21
3213afe3dbfSAMS21 struct {
fllvm_issue_61736::__anon8797905004083223afe3dbfSAMS21 static void f() {}
3233afe3dbfSAMS21 } AnonStruct, *AnonStructPointer;
3243afe3dbfSAMS21
3253afe3dbfSAMS21 class {
3263afe3dbfSAMS21 public:
f()3273afe3dbfSAMS21 static void f() {}
3283afe3dbfSAMS21 } AnonClass, *AnonClassPointer;
3293afe3dbfSAMS21
testAnonymousStructAndClass()3303afe3dbfSAMS21 void testAnonymousStructAndClass() {
3313afe3dbfSAMS21 AnonStruct.f();
3323afe3dbfSAMS21 AnonStructPointer->f();
3333afe3dbfSAMS21
3343afe3dbfSAMS21 AnonClass.f();
3353afe3dbfSAMS21 AnonClassPointer->f();
3363afe3dbfSAMS21 }
3373afe3dbfSAMS21
3383afe3dbfSAMS21 struct Embedded {
3393afe3dbfSAMS21 struct {
fllvm_issue_61736::Embedded::__anon8797905006083403afe3dbfSAMS21 static void f() {}
3413afe3dbfSAMS21 } static EmbeddedStruct, *EmbeddedStructPointer;
3423afe3dbfSAMS21
3433afe3dbfSAMS21 class {
3443afe3dbfSAMS21 public:
f()3453afe3dbfSAMS21 static void f() {}
3463afe3dbfSAMS21 } static EmbeddedClass, *EmbeddedClassPointer;
3473afe3dbfSAMS21 };
3483afe3dbfSAMS21
testEmbeddedAnonymousStructAndClass()3493afe3dbfSAMS21 void testEmbeddedAnonymousStructAndClass() {
3503afe3dbfSAMS21 Embedded::EmbeddedStruct.f();
3513afe3dbfSAMS21 Embedded::EmbeddedStructPointer->f();
3523afe3dbfSAMS21
3533afe3dbfSAMS21 Embedded::EmbeddedClass.f();
3543afe3dbfSAMS21 Embedded::EmbeddedClassPointer->f();
3553afe3dbfSAMS21
3563afe3dbfSAMS21 Embedded E;
3573afe3dbfSAMS21 E.EmbeddedStruct.f();
3583afe3dbfSAMS21 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance [readability-static-accessed-through-instance]
3593afe3dbfSAMS21 // CHECK-FIXES: {{^}} llvm_issue_61736::Embedded::EmbeddedStruct.f();{{$}}
3603afe3dbfSAMS21 E.EmbeddedStructPointer->f();
3613afe3dbfSAMS21 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance [readability-static-accessed-through-instance]
3623afe3dbfSAMS21 // CHECK-FIXES: {{^}} llvm_issue_61736::Embedded::EmbeddedStructPointer->f();{{$}}
3633afe3dbfSAMS21
3643afe3dbfSAMS21 E.EmbeddedClass.f();
3653afe3dbfSAMS21 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance [readability-static-accessed-through-instance]
3663afe3dbfSAMS21 // CHECK-FIXES: {{^}} llvm_issue_61736::Embedded::EmbeddedClass.f();{{$}}
3673afe3dbfSAMS21 E.EmbeddedClassPointer->f();
3683afe3dbfSAMS21 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance [readability-static-accessed-through-instance]
3693afe3dbfSAMS21 // CHECK-FIXES: {{^}} llvm_issue_61736::Embedded::EmbeddedClassPointer->f();{{$}}
3703afe3dbfSAMS21 }
3713afe3dbfSAMS21
3723afe3dbfSAMS21 } // namespace llvm_issue_61736
373766dd7b8SPiotr Zegar
374766dd7b8SPiotr Zegar namespace PR51861 {
375766dd7b8SPiotr Zegar class Foo {
376766dd7b8SPiotr Zegar public:
377766dd7b8SPiotr Zegar static Foo& getInstance();
378766dd7b8SPiotr Zegar static int getBar();
379766dd7b8SPiotr Zegar };
380766dd7b8SPiotr Zegar
getBar()381766dd7b8SPiotr Zegar inline int Foo::getBar() { return 42; }
382766dd7b8SPiotr Zegar
test()383766dd7b8SPiotr Zegar void test() {
384766dd7b8SPiotr Zegar auto& params = Foo::getInstance();
385766dd7b8SPiotr Zegar params.getBar();
386766dd7b8SPiotr Zegar // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: static member accessed through instance [readability-static-accessed-through-instance]
387766dd7b8SPiotr Zegar // CHECK-FIXES: {{^}} PR51861::Foo::getBar();{{$}}
388766dd7b8SPiotr Zegar }
389766dd7b8SPiotr Zegar }
390*37b6ba96SPiotr Zegar
391*37b6ba96SPiotr Zegar namespace PR75163 {
392*37b6ba96SPiotr Zegar struct Static {
393*37b6ba96SPiotr Zegar static void call();
394*37b6ba96SPiotr Zegar };
395*37b6ba96SPiotr Zegar
396*37b6ba96SPiotr Zegar struct Ptr {
397*37b6ba96SPiotr Zegar Static* operator->();
398*37b6ba96SPiotr Zegar };
399*37b6ba96SPiotr Zegar
test(Ptr & ptr)400*37b6ba96SPiotr Zegar void test(Ptr& ptr) {
401*37b6ba96SPiotr Zegar ptr->call();
402*37b6ba96SPiotr Zegar // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: static member accessed through instance [readability-static-accessed-through-instance]
403*37b6ba96SPiotr Zegar // CHECK-MESSAGES: :[[@LINE-2]]:5: note: member base expression may carry some side effects
404*37b6ba96SPiotr Zegar // CHECK-FIXES: {{^}} PR75163::Static::call();{{$}}
405*37b6ba96SPiotr Zegar }
406*37b6ba96SPiotr Zegar }
407