diff options
Diffstat (limited to 'clang-tools-extra/test/clang-tidy')
2 files changed, 255 insertions, 0 deletions
diff --git a/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance-nesting-threshold.cpp b/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance-nesting-threshold.cpp new file mode 100644 index 00000000000..03752497b40 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance-nesting-threshold.cpp @@ -0,0 +1,33 @@ +// RUN: %check_clang_tidy %s readability-static-accessed-through-instance %t -- -config="{CheckOptions: [{key: readability-static-accessed-through-instance.NameSpecifierNestingThreshold, value: 4}]}" -- + +// Nested specifiers +namespace M { +namespace N { +struct V { + static int v; + struct T { + static int t; + struct U { + static int u; + }; + }; +}; +} +} + +void f(M::N::V::T::U u) { + M::N::V v; + v.v = 12; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} M::N::V::v = 12;{{$}} + + M::N::V::T w; + w.t = 12; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} M::N::V::T::t = 12;{{$}} + + // u.u is not changed, because the nesting level is over 4 + u.u = 12; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} u.u = 12;{{$}} +} diff --git a/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance.cpp b/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance.cpp new file mode 100644 index 00000000000..1c760b84576 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance.cpp @@ -0,0 +1,222 @@ +// RUN: %check_clang_tidy %s readability-static-accessed-through-instance %t + +struct C { + static void foo(); + static int x; + int nsx; + void mf() { + (void)&x; // OK, x is accessed inside the struct. + (void)&C::x; // OK, x is accessed using a qualified-id. + foo(); // OK, foo() is accessed inside the struct. + } + void ns() const; +}; + +int C::x = 0; + +struct CC { + void foo(); + int x; +}; + +template <typename T> struct CT { + static T foo(); + static T x; + int nsx; + void mf() { + (void)&x; // OK, x is accessed inside the struct. + (void)&C::x; // OK, x is accessed using a qualified-id. + foo(); // OK, foo() is accessed inside the struct. + } +}; + +// Expressions with side effects +C &f(int, int, int, int); +void g() { + f(1, 2, 3, 4).x; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance [readability-static-accessed-through-instance] + // CHECK-FIXES: {{^}} f(1, 2, 3, 4).x;{{$}} +} + +int i(int &); +void j(int); +C h(); +bool a(); +int k(bool); + +void f(C c) { + j(i(h().x)); + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: static member + // CHECK-FIXES: {{^}} j(i(h().x));{{$}} + + // The execution of h() depends on the return value of a(). + j(k(a() && h().x)); + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: static member + // CHECK-FIXES: {{^}} j(k(a() && h().x));{{$}} + + if ([c]() { + c.ns(); + return c; + }().x == 15) + ; + // CHECK-MESSAGES: :[[@LINE-5]]:7: warning: static member + // CHECK-FIXES: {{^}} if ([c]() {{{$}} +} + +// Nested specifiers +namespace N { +struct V { + static int v; + struct T { + static int t; + struct U { + static int u; + }; + }; +}; +} + +void f(N::V::T::U u) { + N::V v; + v.v = 12; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} N::V::v = 12;{{$}} + + N::V::T w; + w.t = 12; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} N::V::T::t = 12;{{$}} + + // u.u is not changed to N::V::T::U::u; because the nesting level is over 3. + u.u = 12; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} u.u = 12;{{$}} + + using B = N::V::T::U; + B b; + b.u; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} B::u;{{$}} +} + +// Templates +template <typename T> T CT<T>::x; + +template <typename T> struct CCT { + T foo(); + T x; +}; + +typedef C D; + +using E = D; + +#define FOO(c) c.foo() +#define X(c) c.x + +template <typename T> void f(T t, C c) { + t.x; // OK, t is a template parameter. + c.x; // 1 + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} C::x; // 1{{$}} +} + +template <int N> struct S { static int x; }; + +template <> struct S<0> { int x; }; + +template <int N> void h() { + S<N> sN; + sN.x; // OK, value of N affects whether x is static or not. + + S<2> s2; + s2.x; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} S<2>::x;{{$}} +} + +void static_through_instance() { + C *c1 = new C(); + c1->foo(); // 1 + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} C::foo(); // 1{{$}} + c1->x; // 2 + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} C::x; // 2{{$}} + c1->nsx; // OK, nsx is a non-static member. + + const C *c2 = new C(); + c2->foo(); // 2 + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} C::foo(); // 2{{$}} + + C::foo(); // OK, foo() is accessed using a qualified-id. + C::x; // OK, x is accessed using a qualified-id. + + D d; + d.foo(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} D::foo();{{$}} + d.x; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} D::x;{{$}} + + E e; + e.foo(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} E::foo();{{$}} + e.x; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} E::x;{{$}} + + CC *cc = new CC; + + f(*c1, *c1); + f(*cc, *c1); + + // Macros: OK, macros are not checked. + FOO((*c1)); + X((*c1)); + FOO((*cc)); + X((*cc)); + + // Templates + CT<int> ct; + ct.foo(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} CT<int>::foo();{{$}} + ct.x; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member + // CHECK-FIXES: {{^}} CT<int>::x;{{$}} + ct.nsx; // OK, nsx is a non-static member + + CCT<int> cct; + cct.foo(); // OK, CCT has no static members. + cct.x; // OK, CCT has no static members. + + h<4>(); +} + +// Overloaded member access operator +struct Q { + static int K; + int y = 0; +}; + +int Q::K = 0; + +struct Qptr { + Q *q; + + explicit Qptr(Q *qq) : q(qq) {} + + Q *operator->() { + ++q->y; + return q; + } +}; + +int func(Qptr qp) { + qp->y = 10; // OK, the overloaded operator might have side-effects. + qp->K = 10; // +} |

