Index: clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp =================================================================== --- clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp +++ clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp @@ -51,18 +51,6 @@ 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( @@ -146,11 +134,12 @@ // 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. + // 4. the function is a primary template or an explicit template + // specialization. const auto *Method = llvm::dyn_cast(Function); if (Param->getBeginLoc().isMacroID() || (Method && Method->isVirtual()) || isReferencedOutsideOfCallExpr(*Function, *Result.Context) || - isExplicitTemplateSpecialization(*Function)) + (Function->getTemplatedKind() != FunctionDecl::TK_NonTemplate)) return; for (const auto *FunctionDecl = Function; FunctionDecl != nullptr; FunctionDecl = FunctionDecl->getPreviousDecl()) { Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -116,6 +116,10 @@ ` related to passing arguments that refer to program elements without a trivial identifier. +- Fixed a crash in :doc:`performance-unnecessary-value-param + ` when the specialization + template has an unnecessary value paramter. Removed the fix for a template. + Removed checks ^^^^^^^^^^^^^^ Index: clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-value-param-delayed.cpp =================================================================== --- clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-value-param-delayed.cpp +++ clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-value-param-delayed.cpp @@ -69,7 +69,7 @@ template void templateWithNonTemplatizedParameter(const ExpensiveToCopyType S, T V) { // CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'S' - // CHECK-FIXES: template void templateWithNonTemplatizedParameter(const ExpensiveToCopyType& S, T V) { + // CHECK-NOT-FIXES: template void templateWithNonTemplatizedParameter(const ExpensiveToCopyType& S, T V) { } void instantiated() { Index: clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-value-param.cpp =================================================================== --- clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-value-param.cpp +++ clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-value-param.cpp @@ -109,7 +109,7 @@ template void templateWithNonTemplatizedParameter(const ExpensiveToCopyType S, T V) { // CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'S' - // CHECK-FIXES: template void templateWithNonTemplatizedParameter(const ExpensiveToCopyType& S, T V) { + // CHECK-NOT-FIXES: template void templateWithNonTemplatizedParameter(const ExpensiveToCopyType& S, T V) { } void instantiated() { @@ -381,3 +381,24 @@ // CHECK-FIXES: void templateFunction(ExpensiveToCopyType E) { E.constReference(); } + +template +T templateSpecializationFunction(ExpensiveToCopyType E) { + // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'E' is copied + // CHECK-NOT-FIXES: T templateSpecializationFunction(const ExpensiveToCopyType& E) { + return T(); +} + +template <> +bool templateSpecializationFunction(ExpensiveToCopyType E) { + // CHECK-MESSAGES: [[@LINE-1]]:57: warning: the parameter 'E' is copied + // CHECK-NOT-FIXES: bool templateSpecializationFunction(const ExpensiveToCopyType& E) { + return true; +} + +template <> +int templateSpecializationFunction(ExpensiveToCopyType E) { + // CHECK-MESSAGES: [[@LINE-1]]:56: warning: the parameter 'E' is copied + // CHECK-NOT-FIXES: int templateSpecializationFunction(const ExpensiveToCopyType& E) { + return 0; +}