1 // RUN: %check_clang_tidy %s readability-convert-member-functions-to-static %t
2 
3 class DoNotMakeEmptyStatic {
emptyMethod()4   void emptyMethod() {}
5   void empty_method_out_of_line();
6 };
7 
empty_method_out_of_line()8 void DoNotMakeEmptyStatic::empty_method_out_of_line() {}
9 
10 class A {
11   int field;
12   const int const_field;
13   static int static_field;
14 
no_use()15   void no_use() {
16     // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'no_use' can be made static
17     // CHECK-FIXES: {{^}}  static void no_use() {
18     int i = 1;
19   }
20 
read_field()21   int read_field() {
22     return field;
23   }
24 
write_field()25   void write_field() {
26     field = 1;
27   }
28 
call_non_const_member()29   int call_non_const_member() { return read_field(); }
30 
call_static_member()31   int call_static_member() {
32     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'call_static_member' can be made static
33     // CHECK-FIXES: {{^}}  static int call_static_member() {
34     already_static();
35   }
36 
read_static()37   int read_static() {
38     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'read_static' can be made static
39     // CHECK-FIXES: {{^}}  static int read_static() {
40     return static_field;
41   }
write_static()42   void write_static() {
43     // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'write_static' can be made static
44     // CHECK-FIXES: {{^}}  static void write_static() {
45     static_field = 1;
46   }
47 
already_static()48   static int already_static() { return static_field; }
49 
already_const() const50   int already_const() const { return field; }
51 
already_const_convert_to_static() const52   int already_const_convert_to_static() const {
53     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'already_const_convert_to_static' can be made static
54     // CHECK-FIXES: {{^}}  static int already_const_convert_to_static() {
55     return static_field;
56   }
57 
58   static int out_of_line_already_static();
59 
60   void out_of_line_call_static();
61   // CHECK-FIXES: {{^}}  static void out_of_line_call_static();
62   int out_of_line_const_to_static() const;
63   // CHECK-FIXES: {{^}}  static int out_of_line_const_to_static() ;
64 };
65 
out_of_line_already_static()66 int A::out_of_line_already_static() { return 0; }
67 
out_of_line_call_static()68 void A::out_of_line_call_static() {
69   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: method 'out_of_line_call_static' can be made static
70   // CHECK-FIXES: {{^}}void A::out_of_line_call_static() {
71   already_static();
72 }
73 
out_of_line_const_to_static() const74 int A::out_of_line_const_to_static() const {
75   // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'out_of_line_const_to_static' can be made static
76   // CHECK-FIXES: {{^}}int A::out_of_line_const_to_static() {
77   return 0;
78 }
79 
80 struct KeepVirtual {
fKeepVirtual81   virtual int f() { return 0; }
hKeepVirtual82   virtual int h() const { return 0; }
83 };
84 
85 struct KeepVirtualDerived : public KeepVirtual {
fKeepVirtualDerived86   int f() { return 0; }
hKeepVirtualDerived87   int h() const override { return 0; }
88 };
89 
90 // Don't add 'static' to special member functions and operators.
91 struct KeepSpecial {
KeepSpecialKeepSpecial92   KeepSpecial() { int L = 0; }
~KeepSpecialKeepSpecial93   ~KeepSpecial() { int L = 0; }
operator +KeepSpecial94   int operator+() { return 0; }
operator intKeepSpecial95   operator int() { return 0; }
96 };
97 
KeepLambdas()98 void KeepLambdas() {
99   using FT = int (*)();
100   auto F = static_cast<FT>([]() { return 0; });
101   auto F2 = []() { return 0; };
102 }
103 
104 template <class Base>
105 struct KeepWithTemplateBase : public Base {
106   int i;
107   // We cannot make these methods static because they might need to override
108   // a function from Base.
static_fKeepWithTemplateBase109   int static_f() { return 0; }
110 };
111 
112 template <class T>
113 struct KeepTemplateClass {
114   int i;
115   // We cannot make these methods static because a specialization
116   // might use *this differently.
static_fKeepTemplateClass117   int static_f() { return 0; }
118 };
119 
120 struct KeepTemplateMethod {
121   int i;
122   // We cannot make these methods static because a specialization
123   // might use *this differently.
124   template <class T>
static_fKeepTemplateMethod125   static int static_f() { return 0; }
126 };
127 
instantiate()128 void instantiate() {
129   struct S {};
130   KeepWithTemplateBase<S> I1;
131   I1.static_f();
132 
133   KeepTemplateClass<int> I2;
134   I2.static_f();
135 
136   KeepTemplateMethod I3;
137   I3.static_f<int>();
138 }
139 
140 struct Trailing {
gTrailing141   auto g() const -> int {
142     // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'g' can be made static
143     // CHECK-FIXES: {{^}}  static auto g() -> int {
144     return 0;
145   }
146 
volTrailing147   void vol() volatile {
148     // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'vol' can be made static
149     return;
150   }
151 
refTrailing152   void ref() const & {
153     // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'ref' can be made static
154     return;
155   }
refrefTrailing156   void refref() const && {
157     // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'refref' can be made static
158     return;
159   }
160 
restrTrailing161   void restr() __restrict {
162     // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'restr' can be made static
163     return;
164   }
165 };
166 
167 struct UnevaluatedContext {
fUnevaluatedContext168   void f() { sizeof(this); }
169 
170   void noex() noexcept(noexcept(this));
171 };
172 
173 struct LambdaCapturesThis {
174   int Field;
175 
explicitCaptureLambdaCapturesThis176   int explicitCapture() {
177     return [this]() { return Field; }();
178   }
179 
implicitCaptureLambdaCapturesThis180   int implicitCapture() {
181     return [&]() { return Field; }();
182   }
183 };
184 
185 struct NoFixitInMacro {
186 #define CONST const
no_use_macro_constNoFixitInMacro187   int no_use_macro_const() CONST {
188     // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'no_use_macro_const' can be made static
189     return 0;
190   }
191 
192 #define ADD_CONST(F) F const
ADD_CONSTNoFixitInMacro193   int ADD_CONST(no_use_macro2()) {
194     return 0;
195   }
196 
197 #define FUN no_use_macro()
198   int i;
199   int FUN {
200     return i;
201   }
202 
203 #define T(FunctionName, Keyword) \
204   Keyword int FunctionName() { return 0; }
205 #define EMPTY
206   T(A, EMPTY)
207   T(B, static)
208 
209 #define T2(FunctionName) \
210   int FunctionName() { return 0; }
211   T2(A2)
212 
213 #define VOLATILE volatile
214   void volatileMacro() VOLATILE {
215     // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: method 'volatileMacro' can be made static
216     return;
217   }
218 };
219