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