summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance.cpp')
-rw-r--r--clang-tools-extra/test/clang-tidy/readability-static-accessed-through-instance.cpp222
1 files changed, 222 insertions, 0 deletions
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; //
+}
OpenPOWER on IntegriCloud