Index: clang-tidy/performance/UnnecessaryValueParamCheck.cpp =================================================================== --- clang-tidy/performance/UnnecessaryValueParamCheck.cpp +++ clang-tidy/performance/UnnecessaryValueParamCheck.cpp @@ -58,6 +58,18 @@ return Matches.empty(); } +bool isExplicitTemplateSpecialization(const FunctionDecl &Function) { + if (const auto *SpecializationInfo = Function.getTemplateSpecializationInfo()) + if (SpecializationInfo->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization) + return true; + if (const auto *Method = llvm::dyn_cast(&Function)) + if (Method->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization && + Method->getMemberSpecializationInfo()->isExplicitSpecialization()) + return true; + return false; +} + } // namespace UnnecessaryValueParamCheck::UnnecessaryValueParamCheck( @@ -133,9 +145,11 @@ // 2. the function is virtual as it might break overrides // 3. the function is referenced outside of a call expression within the // compilation unit as the signature change could introduce build errors. + // 4. the function is an explicit template specialization. const auto *Method = llvm::dyn_cast(Function); if (Param->getLocStart().isMacroID() || (Method && Method->isVirtual()) || - isReferencedOutsideOfCallExpr(*Function, *Result.Context)) + isReferencedOutsideOfCallExpr(*Function, *Result.Context) || + isExplicitTemplateSpecialization(*Function)) return; for (const auto *FunctionDecl = Function; FunctionDecl != nullptr; FunctionDecl = FunctionDecl->getPreviousDecl()) { 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 @@ -348,3 +348,13 @@ ExpensiveToCopyType E; NegativeUsingConstructor S(E); } + +template +void templateFunction(T) { +} + +template<> +void templateFunction(ExpensiveToCopyType E) { + // CHECK-MESSAGES: [[@LINE-1]]:64: warning: the parameter 'E' is copied + E.constReference(); +}