xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/misc/unused-parameters.cpp (revision 1b897f737df2097f8fee1b203676ea7f01dff06d)
1 // RUN: echo "static void staticFunctionHeader(int i) {;}" > %T/header.h
2 // RUN: echo "static void staticFunctionHeader(int  /*i*/) {;}" > %T/header-fixed.h
3 // RUN: %check_clang_tidy -std=c++11 %s misc-unused-parameters %t -- -header-filter='.*' -- -fno-delayed-template-parsing
4 // RUN: diff %T/header.h %T/header-fixed.h
5 // FIXME: Make the test work in all language modes.
6 
7 #include "header.h"
8 // CHECK-MESSAGES: header.h:1:38: warning
9 
10 // Basic removal
11 // =============
12 void a(int i) {;}
13 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
14 // CHECK-FIXES: {{^}}void a(int  /*i*/) {;}{{$}}
15 
16 void b(int i = 1) {;}
17 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
18 // CHECK-FIXES: {{^}}void b(int  /*i*/ = 1) {;}{{$}}
19 
20 void c(int *i) {;}
21 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: parameter 'i' is unused [misc-unused-parameters]
22 // CHECK-FIXES: {{^}}void c(int * /*i*/) {;}{{$}}
23 
24 void d(int i[]) {;}
25 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
26 // CHECK-FIXES: {{^}}void d(int  /*i*/[]) {;}{{$}}
27 
28 void e(int i[1]) {;}
29 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters]
30 // CHECK-FIXES: {{^}}void e(int  /*i*/[1]) {;}{{$}}
31 
32 void f(void (*fn)()) {;}
33 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: parameter 'fn' is unused [misc-unused-parameters]
34 // CHECK-FIXES: {{^}}void f(void (* /*fn*/)()) {;}{{$}}
35 
36 int *k([[clang::lifetimebound]] int *i) {;}
37 // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: parameter 'i' is unused [misc-unused-parameters]
38 // CHECK-FIXES: {{^}}int *k({{\[\[clang::lifetimebound\]\]}} int * /*i*/) {;}{{$}}
39 
40 #define ATTR_BEFORE(x) [[clang::lifetimebound]] x
41 int* m(ATTR_BEFORE(const int *i)) { return nullptr; }
42 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: parameter 'i' is unused [misc-unused-parameters]
43 // CHECK-FIXES: {{^}}int* m(ATTR_BEFORE(const int * /*i*/)) { return nullptr; }{{$}}
44 #undef ATTR_BEFORE
45 
46 // Unchanged cases
47 // ===============
48 void f(int i); // Don't remove stuff in declarations
49 void g(int i = 1);
50 void h(int i[]);
51 void s(int i[1]);
52 void u(void (*fn)());
53 void w(int i) { (void)i; } // Don't remove used parameters
54 
55 // Don't reanchor the attribute to the type:
56 int *x(int *i [[clang::lifetimebound]]) { return nullptr; }
57 #define ATTR_AFTER(x) x [[clang::lifetimebound]]
58 int* y(ATTR_AFTER(const int *i)) { return nullptr; }
59 #undef ATTR_AFTER
60 
61 bool useLambda(int (*fn)(int));
62 static bool static_var = useLambda([] (int a) { return a; });
63 
64 // Remove parameters of local functions
65 // ====================================
66 static void staticFunctionA(int i);
67 // CHECK-FIXES: {{^}}static void staticFunctionA();
68 static void staticFunctionA(int i) {;}
69 // CHECK-MESSAGES: :[[@LINE-1]]:33: warning
70 // CHECK-FIXES: {{^}}static void staticFunctionA()
71 
72 static void staticFunctionB(int i, int j) { (void)i; }
73 // CHECK-MESSAGES: :[[@LINE-1]]:40: warning
74 // CHECK-FIXES: {{^}}static void staticFunctionB(int i)
75 
76 static void staticFunctionC(int i, int j) { (void)j; }
77 // CHECK-MESSAGES: :[[@LINE-1]]:33: warning
78 // CHECK-FIXES: {{^}}static void staticFunctionC(int j)
79 
80 static void staticFunctionD(int i, int j, int k) { (void)i; (void)k; }
81 // CHECK-MESSAGES: :[[@LINE-1]]:40: warning
82 // CHECK-FIXES: {{^}}static void staticFunctionD(int i, int k)
83 
84 static void staticFunctionE(int i = 4) {;}
85 // CHECK-MESSAGES: :[[@LINE-1]]:33: warning
86 // CHECK-FIXES: {{^}}static void staticFunctionE()
87 
88 static void staticFunctionF(int i = 4);
89 // CHECK-FIXES: {{^}}static void staticFunctionF();
90 static void staticFunctionF(int i) {;}
91 // CHECK-MESSAGES: :[[@LINE-1]]:33: warning
92 // CHECK-FIXES: {{^}}static void staticFunctionF()
93 
94 static void staticFunctionG(int i[]);
95 // CHECK-FIXES: {{^}}static void staticFunctionG();
96 static void staticFunctionG(int i[]) {;}
97 // CHECK-MESSAGES: :[[@LINE-1]]:33: warning
98 // CHECK-FIXES: {{^}}static void staticFunctionG()
99 
100 static void staticFunctionH(void (*fn)());
101 // CHECK-FIXES: {{^}}static void staticFunctionH();
102 static void staticFunctionH(void (*fn)()) {;}
103 // CHECK-MESSAGES: :[[@LINE-1]]:36: warning
104 // CHECK-FIXES: {{^}}static void staticFunctionH()
105 
106 static void someCallSites() {
107   staticFunctionA(1);
108 // CHECK-FIXES: staticFunctionA();
109   staticFunctionB(1, 2);
110 // CHECK-FIXES: staticFunctionB(1);
111   staticFunctionC(1, 2);
112 // CHECK-FIXES: staticFunctionC(2);
113   staticFunctionD(1, 2, 3);
114 // CHECK-FIXES: staticFunctionD(1, 3);
115   staticFunctionE(1);
116 // CHECK-FIXES: staticFunctionE();
117   staticFunctionF(1);
118 // CHECK-FIXES: staticFunctionF();
119   staticFunctionF();
120 // CHECK-FIXES: staticFunctionF();
121   int t[] = {1};
122   staticFunctionG(t);
123 // CHECK-FIXES: staticFunctionG();
124   void func();
125   staticFunctionH(&func);
126 // CHECK-FIXES: staticFunctionH();
127 }
128 
129 /*
130  * FIXME: This fails because the removals overlap and ClangTidy doesn't apply
131  *        them.
132  * static void bothVarsUnused(int a, int b) {;}
133  */
134 
135 // Regression test for long variable names and expressions
136 // =======================================================
137 static int variableWithLongName1(int LongName1, int LongName2) {
138 // CHECK-MESSAGES: :[[@LINE-1]]:53: warning: parameter 'LongName2' is unused
139 // CHECK-FIXES: {{^}}static int variableWithLongName1(int LongName1) {
140   return LongName1;
141 }
142 static int variableWithLongName2(int LongName1, int LongName2) {
143 // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: parameter 'LongName1' is unused
144 // CHECK-FIXES: {{^}}static int variableWithLongName2(int LongName2) {
145   return LongName2;
146 }
147 static void someLongNameCallSites() {
148   int LongName1 = 7, LongName2 = 17;
149   variableWithLongName1(LongName1, LongName2);
150 // CHECK-FIXES: variableWithLongName1(LongName1);
151   variableWithLongName2(LongName1, LongName2);
152 // CHECK-FIXES: variableWithLongName2(LongName2);
153 }
154 
155 class SomeClass {
156   static void f(int i) {;}
157 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning
158 // CHECK-FIXES: static void f(int  /*i*/) {;}
159   static void g(int i = 1) {;}
160 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning
161 // CHECK-FIXES: static void g(int  /*i*/ = 1) {;}
162   static void h(int i[]) {;}
163 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning
164 // CHECK-FIXES: static void h(int  /*i*/[]) {;}
165   static void s(void (*fn)()) {;}
166 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning
167 // CHECK-FIXES: static void s(void (* /*fn*/)()) {;}
168 };
169 
170 namespace {
171 class C {
172 public:
173   void f(int i);
174 // CHECK-FIXES: void f();
175   void g(int i) {;}
176 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning
177 // CHECK-FIXES: void g() {;}
178   void h(int i) {;}
179 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning
180 // CHECK-FIXES: void h(int  /*i*/) {;}
181   void s(int i = 1) {;}
182 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning
183 // CHECK-FIXES: void s(int  /*i*/ = 1) {;}
184   void u(int i[]) {;}
185 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning
186 // CHECK-FIXES: void u(int  /*i*/[]) {;}
187   void w(void (*fn)()) {;}
188 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning
189 // CHECK-FIXES: void w(void (* /*fn*/)()) {;}
190 };
191 
192 void C::f(int i) {;}
193 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning
194 // CHECK-FIXES: void C::f() {;}
195 
196 template <typename T>
197 void useFunction(T t);
198 
199 void someMoreCallSites() {
200   C c;
201   c.f(1);
202 // CHECK-FIXES: c.f();
203   c.g(1);
204 // CHECK-FIXES: c.g();
205 
206   useFunction(&C::h);
207   useFunction(&C::s);
208   useFunction(&C::u);
209   useFunction(&C::w);
210 }
211 
212 class Base {
213   virtual void f(int i);
214 };
215 
216 class Derived : public Base {
217   void f(int i) override {;}
218 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning
219 // CHECK-FIXES: void f(int  /*i*/) override {;}
220 };
221 
222 } // end namespace
223 
224 template <typename T> void someFunctionTemplate(T b, T e) { (void)b; (void)e; }
225 
226 template <typename T> void someFunctionTemplateOneUnusedParam(T b, T e) { (void)e; }
227 // CHECK-MESSAGES: :[[@LINE-1]]:65: warning
228 // CHECK-FIXES: {{^}}template <typename T> void someFunctionTemplateOneUnusedParam(T  /*b*/, T e) { (void)e; }
229 
230 template <typename T> void someFunctionTemplateAllUnusedParams(T b, T e) {;}
231 // CHECK-MESSAGES: :[[@LINE-1]]:66: warning
232 // CHECK-MESSAGES: :[[@LINE-2]]:71: warning
233 // CHECK-FIXES: {{^}}template <typename T> void someFunctionTemplateAllUnusedParams(T  /*b*/, T  /*e*/) {;}
234 
235 static void dontGetConfusedByParametersInFunctionTypes() { void (*F)(int i); }
236 
237 template <typename T> class Function {};
238 static Function<void(int, int i)> dontGetConfusedByFunctionReturnTypes() {
239   return Function<void(int, int)>();
240 }
241 
242 namespace PR38055 {
243 namespace {
244 struct a {
245   void b(int c) {;}
246 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: parameter 'c' is unused
247 // CHECK-FIXES: {{^}}  void b() {;}{{$}}
248 };
249 template <class>
250 class d {
251   a e;
252   void f() { e.b(0); }
253 };
254 }  // namespace
255 }  // namespace PR38055
256 
257 namespace strict_mode_off {
258 // Do not warn on empty function bodies.
259 void f1(int foo1) {}
260 void f2(int foo2) {
261   // "empty" in the AST sense, not in textual sense.
262 }
263 void f3(int foo3) {;}
264 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: parameter 'foo3' is unused
265 // CHECK-FIXES: {{^}}void f3(int  /*foo3*/) {;}{{$}}
266 
267 class E {
268   int i;
269 
270 public:
271   E(int j) {}
272 };
273 class F {
274   int i;
275 
276 public:
277   // Constructor initializer counts as a non-empty body.
278   F(int j) : i() {}
279 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'j' is unused
280 // CHECK-FIXES: {{^}}  F(int  /*j*/) : i() {}{{$}}
281 };
282 
283 class A {
284 public:
285   A();
286   A(int);
287 };
288 class B : public A {
289 public:
290   B(int i) : A() {}
291 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is unused
292 // CHECK-FIXES: {{^}}  B(int  /*i*/) : A() {}{{$}}
293 };
294 } // namespace strict_mode_off
295 
296 namespace lambda {
297 using fn = void(int);
298 void f(fn *);
299 void test() {
300   // CHECK-MESSAGES: :[[@LINE+2]]:12: warning: parameter 'I' is unused
301   // CHECK-FIXES: {{^}}  f([](int  /*I*/) {
302   f([](int I) { return; });
303 }
304 } // namespace lambda
305 
306 // Do not warn on naked functions.
307 [[gnu::naked]] int nakedFunction(int a, float b, const char *c) { ; }
308 __attribute__((naked)) void nakedFunction(int a, int b) { ; }
309