Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp =================================================================== --- clang-tidy/performance/UnnecessaryValueParamCheck.cpp +++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp @@ -128,7 +128,10 @@ const auto &CurrentParam = *FunctionDecl->getParamDecl(Index); Diag << utils::fixit::changeVarDeclToReference(CurrentParam, *Result.Context); - if (!IsConstQualified) + // The parameter of each declaration needs to be checked individually as to + // whether it is const or not as constness can differ between definition and + // declaration. + if (!CurrentParam.getType().getCanonicalType().isConstQualified()) Diag << utils::fixit::changeVarDeclToConst(CurrentParam); } } Index: test/clang-tidy/performance-unnecessary-value-param.cpp =================================================================== --- test/clang-tidy/performance-unnecessary-value-param.cpp +++ test/clang-tidy/performance-unnecessary-value-param.cpp @@ -237,3 +237,19 @@ ExpensiveToCopyType B; B = A; } + +// Case where parameter in declaration is already const-qualified but not in +// implementation. Make sure a second 'const' is not added to the declaration. +void PositiveConstDeclaration(const ExpensiveToCopyType A); +// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A); +void PositiveConstDeclaration(ExpensiveToCopyType A) { + // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied + // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) { +} + +void PositiveNonConstDeclaration(ExpensiveToCopyType A); +// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A); +void PositiveNonConstDeclaration(const ExpensiveToCopyType A) { + // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A' + // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A) { +}