Index: clang-tidy/misc/UnusedParametersCheck.cpp =================================================================== --- clang-tidy/misc/UnusedParametersCheck.cpp +++ clang-tidy/misc/UnusedParametersCheck.cpp @@ -22,6 +22,38 @@ this); } +static FixItHint removeParameter(const FunctionDecl *Function, unsigned Index) { + const ParmVarDecl *Param = Function->getParamDecl(Index); + unsigned ParamCount = Function->getNumParams(); + SourceRange RemovalRange = Param->getSourceRange(); + if (ParamCount == 1) + return FixItHint::CreateRemoval(RemovalRange); + + if (Index == 0) + RemovalRange.setEnd( + Function->getParamDecl(Index + 1)->getLocStart().getLocWithOffset(-1)); + else + RemovalRange.setBegin( + Function->getParamDecl(Index - 1)->getLocEnd().getLocWithOffset(1)); + + return FixItHint::CreateRemoval(RemovalRange); +} + +static FixItHint removeArgument(const CallExpr *Call, unsigned Index) { + unsigned ArgCount = Call->getNumArgs(); + const Expr *Arg = Call->getArg(Index); + SourceRange RemovalRange = Arg->getSourceRange(); + if (ArgCount == 1) + return FixItHint::CreateRemoval(RemovalRange); + if (Index == 0) + RemovalRange.setEnd( + Call->getArg(Index + 1)->getLocStart().getLocWithOffset(-1)); + else + RemovalRange.setBegin( + Call->getArg(Index - 1)->getLocEnd().getLocWithOffset(1)); + return FixItHint::CreateRemoval(RemovalRange); +} + void UnusedParametersCheck::check(const MatchFinder::MatchResult &Result) { const auto *Function = Result.Nodes.getNodeAs("function"); if (!Function->doesThisDeclarationHaveABody()) @@ -33,9 +65,27 @@ auto MyDiag = diag(Param->getLocation(), "parameter '%0' is unused") << Param->getName(); - SourceRange RemovalRange(Param->getLocation(), Param->getLocEnd()); - MyDiag << FixItHint::CreateReplacement( - RemovalRange, (Twine(" /*") + Param->getName() + "*/").str()); + // Comment out parameter name for non-local functions. + if (Function->getStorageClass() != StorageClass::SC_Static) { + SourceRange RemovalRange(Param->getLocation(), Param->getLocEnd()); + MyDiag << FixItHint::CreateReplacement( + RemovalRange, (Twine(" /*") + Param->getName() + "*/").str()); + return; + } + + // Handle local functions by deleting the parameters. + unsigned ParamIndex = Param->getFunctionScopeIndex(); + // Fix all redeclarations. + for (const FunctionDecl *FD : Function->redecls()) + MyDiag << removeParameter(FD, ParamIndex); + + // Fix all call sites. + auto CallMatches = ast_matchers::match( + decl(forEachDescendant( + callExpr(callee(functionDecl(equalsNode(Function)))).bind("x"))), + *Result.Context->getTranslationUnitDecl(), *Result.Context); + for (const auto &Match : CallMatches) + MyDiag << removeArgument(Match.getNodeAs("x"), ParamIndex); } } // namespace tidy Index: test/clang-tidy/misc-unused-parameters.cpp =================================================================== --- test/clang-tidy/misc-unused-parameters.cpp +++ test/clang-tidy/misc-unused-parameters.cpp @@ -19,3 +19,40 @@ // =============== void g(int i); // Don't remove stuff in declarations void h(int i) { (void)i; } // Don't remove used parameters + +// Remove parameters of local functions +// ==================================== +static void staticFunctionA(int i); +// CHECK-FIXES: {{^}}static void staticFunctionA(); +static void staticFunctionA(int i) {} +// CHECK-MESSAGES: :[[@LINE-1]]:33: warning +// CHECK-FIXES: {{^}}static void staticFunctionA() + +static void staticFunctionB(int i, int j) { (void)i; } +// CHECK-MESSAGES: :[[@LINE-1]]:40: warning +// CHECK-FIXES: {{^}}static void staticFunctionB(int i) + +static void staticFunctionC(int i, int j) { (void)j; } +// CHECK-MESSAGES: :[[@LINE-1]]:33: warning +// CHECK-FIXES: {{^}}static void staticFunctionC( int j) + +static void staticFunctionD(int i, int j, int k) { (void)i; (void)k; } +// CHECK-MESSAGES: :[[@LINE-1]]:40: warning +// CHECK-FIXES: {{^}}static void staticFunctionD(int i, int k) + +static void staticFunctionE(int i = 4) {} +// CHECK-MESSAGES: :[[@LINE-1]]:33: warning +// CHECK-FIXES: {{^}}static void staticFunctionE() + + +static void someCallSites() { + staticFunctionA(1); +// CHECK-FIXES: {{^}} staticFunctionA(); + staticFunctionB(1, 2); +// CHECK-FIXES: {{^}} staticFunctionB(1); + staticFunctionC(1, 2); +// CHECK-FIXES: {{^}} staticFunctionC( 2); + staticFunctionD(1, 2, 3); +// CHECK-FIXES: {{^}} staticFunctionD(1, 3); + staticFunctionE(); +}