189a1d03eSRichard // RUN: echo "static void staticFunctionHeader(int i) {;}" > %T/header.h 289a1d03eSRichard // RUN: echo "static void staticFunctionHeader(int /*i*/) {;}" > %T/header-fixed.h 389a1d03eSRichard // RUN: %check_clang_tidy -std=c++11 %s misc-unused-parameters %t -- -header-filter='.*' -- -fno-delayed-template-parsing 489a1d03eSRichard // RUN: diff %T/header.h %T/header-fixed.h 589a1d03eSRichard // FIXME: Make the test work in all language modes. 689a1d03eSRichard 789a1d03eSRichard #include "header.h" 889a1d03eSRichard // CHECK-MESSAGES: header.h:1:38: warning 989a1d03eSRichard 1089a1d03eSRichard // Basic removal 1189a1d03eSRichard // ============= 1289a1d03eSRichard void a(int i) {;} 1389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters] 1489a1d03eSRichard // CHECK-FIXES: {{^}}void a(int /*i*/) {;}{{$}} 1589a1d03eSRichard 1689a1d03eSRichard void b(int i = 1) {;} 1789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters] 1889a1d03eSRichard // CHECK-FIXES: {{^}}void b(int /*i*/ = 1) {;}{{$}} 1989a1d03eSRichard 2089a1d03eSRichard void c(int *i) {;} 2189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: parameter 'i' is unused [misc-unused-parameters] 2289a1d03eSRichard // CHECK-FIXES: {{^}}void c(int * /*i*/) {;}{{$}} 2389a1d03eSRichard 2489a1d03eSRichard void d(int i[]) {;} 2589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters] 2689a1d03eSRichard // CHECK-FIXES: {{^}}void d(int /*i*/[]) {;}{{$}} 2789a1d03eSRichard 2889a1d03eSRichard void e(int i[1]) {;} 2989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: parameter 'i' is unused [misc-unused-parameters] 3089a1d03eSRichard // CHECK-FIXES: {{^}}void e(int /*i*/[1]) {;}{{$}} 3189a1d03eSRichard 3289a1d03eSRichard void f(void (*fn)()) {;} 3389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: parameter 'fn' is unused [misc-unused-parameters] 3489a1d03eSRichard // CHECK-FIXES: {{^}}void f(void (* /*fn*/)()) {;}{{$}} 3589a1d03eSRichard 36*1b897f73SMaksim Ivanov int *k([[clang::lifetimebound]] int *i) {;} 37*1b897f73SMaksim Ivanov // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: parameter 'i' is unused [misc-unused-parameters] 38*1b897f73SMaksim Ivanov // CHECK-FIXES: {{^}}int *k({{\[\[clang::lifetimebound\]\]}} int * /*i*/) {;}{{$}} 39*1b897f73SMaksim Ivanov 40*1b897f73SMaksim Ivanov #define ATTR_BEFORE(x) [[clang::lifetimebound]] x 41*1b897f73SMaksim Ivanov int* m(ATTR_BEFORE(const int *i)) { return nullptr; } 42*1b897f73SMaksim Ivanov // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: parameter 'i' is unused [misc-unused-parameters] 43*1b897f73SMaksim Ivanov // CHECK-FIXES: {{^}}int* m(ATTR_BEFORE(const int * /*i*/)) { return nullptr; }{{$}} 44*1b897f73SMaksim Ivanov #undef ATTR_BEFORE 45*1b897f73SMaksim Ivanov 4689a1d03eSRichard // Unchanged cases 4789a1d03eSRichard // =============== 4889a1d03eSRichard void f(int i); // Don't remove stuff in declarations 4989a1d03eSRichard void g(int i = 1); 5089a1d03eSRichard void h(int i[]); 5189a1d03eSRichard void s(int i[1]); 5289a1d03eSRichard void u(void (*fn)()); 5389a1d03eSRichard void w(int i) { (void)i; } // Don't remove used parameters 5489a1d03eSRichard 55*1b897f73SMaksim Ivanov // Don't reanchor the attribute to the type: 56*1b897f73SMaksim Ivanov int *x(int *i [[clang::lifetimebound]]) { return nullptr; } 57*1b897f73SMaksim Ivanov #define ATTR_AFTER(x) x [[clang::lifetimebound]] 58*1b897f73SMaksim Ivanov int* y(ATTR_AFTER(const int *i)) { return nullptr; } 59*1b897f73SMaksim Ivanov #undef ATTR_AFTER 60*1b897f73SMaksim Ivanov 6189a1d03eSRichard bool useLambda(int (*fn)(int)); 6289a1d03eSRichard static bool static_var = useLambda([] (int a) { return a; }); 6389a1d03eSRichard 6489a1d03eSRichard // Remove parameters of local functions 6589a1d03eSRichard // ==================================== 6689a1d03eSRichard static void staticFunctionA(int i); 6789a1d03eSRichard // CHECK-FIXES: {{^}}static void staticFunctionA(); 6889a1d03eSRichard static void staticFunctionA(int i) {;} 6989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:33: warning 7089a1d03eSRichard // CHECK-FIXES: {{^}}static void staticFunctionA() 7189a1d03eSRichard 7289a1d03eSRichard static void staticFunctionB(int i, int j) { (void)i; } 7389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:40: warning 7489a1d03eSRichard // CHECK-FIXES: {{^}}static void staticFunctionB(int i) 7589a1d03eSRichard 7689a1d03eSRichard static void staticFunctionC(int i, int j) { (void)j; } 7789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:33: warning 7889a1d03eSRichard // CHECK-FIXES: {{^}}static void staticFunctionC(int j) 7989a1d03eSRichard 8089a1d03eSRichard static void staticFunctionD(int i, int j, int k) { (void)i; (void)k; } 8189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:40: warning 8289a1d03eSRichard // CHECK-FIXES: {{^}}static void staticFunctionD(int i, int k) 8389a1d03eSRichard 8489a1d03eSRichard static void staticFunctionE(int i = 4) {;} 8589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:33: warning 8689a1d03eSRichard // CHECK-FIXES: {{^}}static void staticFunctionE() 8789a1d03eSRichard 8889a1d03eSRichard static void staticFunctionF(int i = 4); 8989a1d03eSRichard // CHECK-FIXES: {{^}}static void staticFunctionF(); 9089a1d03eSRichard static void staticFunctionF(int i) {;} 9189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:33: warning 9289a1d03eSRichard // CHECK-FIXES: {{^}}static void staticFunctionF() 9389a1d03eSRichard 9489a1d03eSRichard static void staticFunctionG(int i[]); 9589a1d03eSRichard // CHECK-FIXES: {{^}}static void staticFunctionG(); 9689a1d03eSRichard static void staticFunctionG(int i[]) {;} 9789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:33: warning 9889a1d03eSRichard // CHECK-FIXES: {{^}}static void staticFunctionG() 9989a1d03eSRichard 10089a1d03eSRichard static void staticFunctionH(void (*fn)()); 10189a1d03eSRichard // CHECK-FIXES: {{^}}static void staticFunctionH(); 10289a1d03eSRichard static void staticFunctionH(void (*fn)()) {;} 10389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:36: warning 10489a1d03eSRichard // CHECK-FIXES: {{^}}static void staticFunctionH() 10589a1d03eSRichard 10689a1d03eSRichard static void someCallSites() { 10789a1d03eSRichard staticFunctionA(1); 10889a1d03eSRichard // CHECK-FIXES: staticFunctionA(); 10989a1d03eSRichard staticFunctionB(1, 2); 11089a1d03eSRichard // CHECK-FIXES: staticFunctionB(1); 11189a1d03eSRichard staticFunctionC(1, 2); 11289a1d03eSRichard // CHECK-FIXES: staticFunctionC(2); 11389a1d03eSRichard staticFunctionD(1, 2, 3); 11489a1d03eSRichard // CHECK-FIXES: staticFunctionD(1, 3); 11589a1d03eSRichard staticFunctionE(1); 11689a1d03eSRichard // CHECK-FIXES: staticFunctionE(); 11789a1d03eSRichard staticFunctionF(1); 11889a1d03eSRichard // CHECK-FIXES: staticFunctionF(); 11989a1d03eSRichard staticFunctionF(); 12089a1d03eSRichard // CHECK-FIXES: staticFunctionF(); 12189a1d03eSRichard int t[] = {1}; 12289a1d03eSRichard staticFunctionG(t); 12389a1d03eSRichard // CHECK-FIXES: staticFunctionG(); 12489a1d03eSRichard void func(); 12589a1d03eSRichard staticFunctionH(&func); 12689a1d03eSRichard // CHECK-FIXES: staticFunctionH(); 12789a1d03eSRichard } 12889a1d03eSRichard 12989a1d03eSRichard /* 13089a1d03eSRichard * FIXME: This fails because the removals overlap and ClangTidy doesn't apply 13189a1d03eSRichard * them. 13289a1d03eSRichard * static void bothVarsUnused(int a, int b) {;} 13389a1d03eSRichard */ 13489a1d03eSRichard 13589a1d03eSRichard // Regression test for long variable names and expressions 13689a1d03eSRichard // ======================================================= 13789a1d03eSRichard static int variableWithLongName1(int LongName1, int LongName2) { 13889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:53: warning: parameter 'LongName2' is unused 13989a1d03eSRichard // CHECK-FIXES: {{^}}static int variableWithLongName1(int LongName1) { 14089a1d03eSRichard return LongName1; 14189a1d03eSRichard } 14289a1d03eSRichard static int variableWithLongName2(int LongName1, int LongName2) { 14389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:38: warning: parameter 'LongName1' is unused 14489a1d03eSRichard // CHECK-FIXES: {{^}}static int variableWithLongName2(int LongName2) { 14589a1d03eSRichard return LongName2; 14689a1d03eSRichard } 14789a1d03eSRichard static void someLongNameCallSites() { 14889a1d03eSRichard int LongName1 = 7, LongName2 = 17; 14989a1d03eSRichard variableWithLongName1(LongName1, LongName2); 15089a1d03eSRichard // CHECK-FIXES: variableWithLongName1(LongName1); 15189a1d03eSRichard variableWithLongName2(LongName1, LongName2); 15289a1d03eSRichard // CHECK-FIXES: variableWithLongName2(LongName2); 15389a1d03eSRichard } 15489a1d03eSRichard 15589a1d03eSRichard class SomeClass { 15689a1d03eSRichard static void f(int i) {;} 15789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:21: warning 15889a1d03eSRichard // CHECK-FIXES: static void f(int /*i*/) {;} 15989a1d03eSRichard static void g(int i = 1) {;} 16089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:21: warning 16189a1d03eSRichard // CHECK-FIXES: static void g(int /*i*/ = 1) {;} 16289a1d03eSRichard static void h(int i[]) {;} 16389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:21: warning 16489a1d03eSRichard // CHECK-FIXES: static void h(int /*i*/[]) {;} 16589a1d03eSRichard static void s(void (*fn)()) {;} 16689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:24: warning 16789a1d03eSRichard // CHECK-FIXES: static void s(void (* /*fn*/)()) {;} 16889a1d03eSRichard }; 16989a1d03eSRichard 17089a1d03eSRichard namespace { 17189a1d03eSRichard class C { 17289a1d03eSRichard public: 17389a1d03eSRichard void f(int i); 17489a1d03eSRichard // CHECK-FIXES: void f(); 17589a1d03eSRichard void g(int i) {;} 17689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: warning 17789a1d03eSRichard // CHECK-FIXES: void g() {;} 17889a1d03eSRichard void h(int i) {;} 17989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: warning 18089a1d03eSRichard // CHECK-FIXES: void h(int /*i*/) {;} 18189a1d03eSRichard void s(int i = 1) {;} 18289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: warning 18389a1d03eSRichard // CHECK-FIXES: void s(int /*i*/ = 1) {;} 18489a1d03eSRichard void u(int i[]) {;} 18589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: warning 18689a1d03eSRichard // CHECK-FIXES: void u(int /*i*/[]) {;} 18789a1d03eSRichard void w(void (*fn)()) {;} 18889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:17: warning 18989a1d03eSRichard // CHECK-FIXES: void w(void (* /*fn*/)()) {;} 19089a1d03eSRichard }; 19189a1d03eSRichard 19289a1d03eSRichard void C::f(int i) {;} 19389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:15: warning 19489a1d03eSRichard // CHECK-FIXES: void C::f() {;} 19589a1d03eSRichard 19689a1d03eSRichard template <typename T> 19789a1d03eSRichard void useFunction(T t); 19889a1d03eSRichard 19989a1d03eSRichard void someMoreCallSites() { 20089a1d03eSRichard C c; 20189a1d03eSRichard c.f(1); 20289a1d03eSRichard // CHECK-FIXES: c.f(); 20389a1d03eSRichard c.g(1); 20489a1d03eSRichard // CHECK-FIXES: c.g(); 20589a1d03eSRichard 20689a1d03eSRichard useFunction(&C::h); 20789a1d03eSRichard useFunction(&C::s); 20889a1d03eSRichard useFunction(&C::u); 20989a1d03eSRichard useFunction(&C::w); 21089a1d03eSRichard } 21189a1d03eSRichard 21289a1d03eSRichard class Base { 21389a1d03eSRichard virtual void f(int i); 21489a1d03eSRichard }; 21589a1d03eSRichard 21689a1d03eSRichard class Derived : public Base { 21789a1d03eSRichard void f(int i) override {;} 21889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: warning 21989a1d03eSRichard // CHECK-FIXES: void f(int /*i*/) override {;} 22089a1d03eSRichard }; 22189a1d03eSRichard 22289a1d03eSRichard } // end namespace 22389a1d03eSRichard 22489a1d03eSRichard template <typename T> void someFunctionTemplate(T b, T e) { (void)b; (void)e; } 22589a1d03eSRichard 22689a1d03eSRichard template <typename T> void someFunctionTemplateOneUnusedParam(T b, T e) { (void)e; } 22789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:65: warning 22889a1d03eSRichard // CHECK-FIXES: {{^}}template <typename T> void someFunctionTemplateOneUnusedParam(T /*b*/, T e) { (void)e; } 22989a1d03eSRichard 23089a1d03eSRichard template <typename T> void someFunctionTemplateAllUnusedParams(T b, T e) {;} 23189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:66: warning 23289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-2]]:71: warning 23389a1d03eSRichard // CHECK-FIXES: {{^}}template <typename T> void someFunctionTemplateAllUnusedParams(T /*b*/, T /*e*/) {;} 23489a1d03eSRichard 23589a1d03eSRichard static void dontGetConfusedByParametersInFunctionTypes() { void (*F)(int i); } 23689a1d03eSRichard 23789a1d03eSRichard template <typename T> class Function {}; 23889a1d03eSRichard static Function<void(int, int i)> dontGetConfusedByFunctionReturnTypes() { 23989a1d03eSRichard return Function<void(int, int)>(); 24089a1d03eSRichard } 24189a1d03eSRichard 24289a1d03eSRichard namespace PR38055 { 24389a1d03eSRichard namespace { 24489a1d03eSRichard struct a { 24589a1d03eSRichard void b(int c) {;} 24689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: parameter 'c' is unused 24789a1d03eSRichard // CHECK-FIXES: {{^}} void b() {;}{{$}} 24889a1d03eSRichard }; 24989a1d03eSRichard template <class> 25089a1d03eSRichard class d { 25189a1d03eSRichard a e; 25289a1d03eSRichard void f() { e.b(0); } 25389a1d03eSRichard }; 25489a1d03eSRichard } // namespace 25589a1d03eSRichard } // namespace PR38055 25689a1d03eSRichard 25789a1d03eSRichard namespace strict_mode_off { 25889a1d03eSRichard // Do not warn on empty function bodies. 25989a1d03eSRichard void f1(int foo1) {} 26089a1d03eSRichard void f2(int foo2) { 26189a1d03eSRichard // "empty" in the AST sense, not in textual sense. 26289a1d03eSRichard } 26389a1d03eSRichard void f3(int foo3) {;} 26489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: parameter 'foo3' is unused 26589a1d03eSRichard // CHECK-FIXES: {{^}}void f3(int /*foo3*/) {;}{{$}} 26689a1d03eSRichard 26789a1d03eSRichard class E { 26889a1d03eSRichard int i; 26989a1d03eSRichard 27089a1d03eSRichard public: 27189a1d03eSRichard E(int j) {} 27289a1d03eSRichard }; 27389a1d03eSRichard class F { 27489a1d03eSRichard int i; 27589a1d03eSRichard 27689a1d03eSRichard public: 27789a1d03eSRichard // Constructor initializer counts as a non-empty body. 27889a1d03eSRichard F(int j) : i() {} 27989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'j' is unused 28089a1d03eSRichard // CHECK-FIXES: {{^}} F(int /*j*/) : i() {}{{$}} 28189a1d03eSRichard }; 28289a1d03eSRichard 28389a1d03eSRichard class A { 28489a1d03eSRichard public: 28589a1d03eSRichard A(); 28689a1d03eSRichard A(int); 28789a1d03eSRichard }; 28889a1d03eSRichard class B : public A { 28989a1d03eSRichard public: 29089a1d03eSRichard B(int i) : A() {} 29189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: parameter 'i' is unused 29289a1d03eSRichard // CHECK-FIXES: {{^}} B(int /*i*/) : A() {}{{$}} 29389a1d03eSRichard }; 29489a1d03eSRichard } // namespace strict_mode_off 29589a1d03eSRichard 29689a1d03eSRichard namespace lambda { 29789a1d03eSRichard using fn = void(int); 29889a1d03eSRichard void f(fn *); 29989a1d03eSRichard void test() { 30089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE+2]]:12: warning: parameter 'I' is unused 30189a1d03eSRichard // CHECK-FIXES: {{^}} f([](int /*I*/) { 30289a1d03eSRichard f([](int I) { return; }); 30389a1d03eSRichard } 30489a1d03eSRichard } // namespace lambda 30589a1d03eSRichard 30689a1d03eSRichard // Do not warn on naked functions. 30789a1d03eSRichard [[gnu::naked]] int nakedFunction(int a, float b, const char *c) { ; } 30889a1d03eSRichard __attribute__((naked)) void nakedFunction(int a, int b) { ; } 309