Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp =================================================================== --- clang-tidy/performance/UnnecessaryValueParamCheck.cpp +++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp @@ -128,7 +128,8 @@ const auto &CurrentParam = *FunctionDecl->getParamDecl(Index); Diag << utils::fixit::changeVarDeclToReference(CurrentParam, *Result.Context); - if (!IsConstQualified) + if (!IsConstQualified && + !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,12 @@ 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) { +}