407 lines · cpp
1// RUN: %check_clang_tidy %s readability-static-accessed-through-instance %t -- --fix-notes -- -isystem %S/Inputs/static-accessed-through-instance2#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 effects46C &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 effects51 // 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 member63 // CHECK-MESSAGES: :[[@LINE-2]]:7: note: member base expression may carry some side effects64 // 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 member69 // CHECK-MESSAGES: :[[@LINE-2]]:14: note: member base expression may carry some side effects70 // 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 member78 // CHECK-MESSAGES: :[[@LINE-6]]:7: note: member base expression may carry some side effects79 // CHECK-FIXES: if (C::x == 15)80}81 82// Nested specifiers83namespace 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 member99 // CHECK-FIXES: N::V::v = 12;100 101 N::V::T w;102 w.t = 12;103 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member104 // 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 member109 // 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 member115 // CHECK-FIXES: B::u;116}117 118// Templates119template <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.x132 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 member137 // 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 member151 // CHECK-FIXES: S<2>::x;152}153 154void static_through_instance() {155 C *c1 = new C();156 c1->foo(); // 1157 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member158 // CHECK-FIXES: C::foo(); // 1159 c1->x; // 2160 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member161 // CHECK-FIXES: C::x; // 2162 c1->Anonymous; // 3163 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member164 // CHECK-FIXES: C::Anonymous; // 3165 c1->E1; // 4166 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member167 // CHECK-FIXES: C::E1; // 4168 c1->E0; // 5169 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member170 // CHECK-FIXES: C::E0; // 5171 172 c1->nsx; // OK, nsx is a non-static member.173 174 const C *c2 = new C();175 c2->foo(); // 2176 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member177 // CHECK-FIXES: C::foo(); // 2178 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 member185 // CHECK-FIXES: D::foo();186 d.x;187 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member188 // CHECK-FIXES: D::x;189 190 E e;191 e.foo();192 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member193 // CHECK-FIXES: E::foo();194 e.x;195 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member196 // CHECK-FIXES: E::x;197 198 CC *cc = new CC;199 200 f(*c1, *c1);201 f(*cc, *c1);202 203 // Macros: OK, macros are not checked.204 FOO((*c1));205 X((*c1));206 FOO((*cc));207 X((*cc));208 209 // Templates210 CT<int> ct;211 ct.foo();212 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member213 // CHECK-FIXES: CT<int>::foo();214 ct.x;215 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member216 // CHECK-FIXES: CT<int>::x;217 ct.nsx; // OK, nsx is a non-static member218 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 member233 // CHECK-FIXES: SP::I;234}235 236namespace NSP {237struct SP {238 static int I;239} P;240} // namespace NSP241 242void usensp() {243 NSP::P.I;244 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member245 // CHECK-FIXES: NSP::SP::I;246}247 248// Overloaded member access operator249struct 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 effects272 // 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 member285 // 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 member300 // CHECK-FIXES: Outer::S::I;301}302 303// https://bugs.llvm.org/show_bug.cgi?id=48758304namespace Bugzilla_48758 {305 306unsigned int x1 = threadIdx.x;307// CHECK-MESSAGES-NOT: :[[@LINE-1]]:10: warning: static member308unsigned int x2 = blockIdx.x;309// CHECK-MESSAGES-NOT: :[[@LINE-1]]:10: warning: static member310unsigned int x3 = blockDim.x;311// CHECK-MESSAGES-NOT: :[[@LINE-1]]:10: warning: static member312unsigned int x4 = gridDim.x;313// CHECK-MESSAGES-NOT: :[[@LINE-1]]:10: warning: static member314 315} // namespace Bugzilla_48758316 317// https://github.com/llvm/llvm-project/issues/61736318namespace llvm_issue_61736319{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_61736373 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 effects404 // CHECK-FIXES: PR75163::Static::call();405 }406}407