diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp index ba2b89c291214..00f4b00f53819 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp @@ -51,18 +51,6 @@ bool hasLoopStmtAncestor(const DeclRefExpr &DeclRef, const Decl &Decl, 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( @@ -147,11 +135,12 @@ void UnnecessaryValueParamCheck::check(const MatchFinder::MatchResult &Result) { // 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()) { diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 787f535dedb64..5196c53291d19 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -202,6 +202,10 @@ Changes in existing checks ` to simplify expressions using DeMorgan's Theorem. +- 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 ^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-value-param-delayed.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-value-param-delayed.cpp index 623bf8b30829e..53ec8713be338 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-value-param-delayed.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-value-param-delayed.cpp @@ -69,7 +69,7 @@ struct PositiveConstValueConstructor { 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-FIXES-NOT: template void templateWithNonTemplatizedParameter(const ExpensiveToCopyType& S, T V) { } void instantiated() { diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-value-param.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-value-param.cpp index f801494cf0ff5..d578eedd94a39 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-value-param.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/performance-unnecessary-value-param.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t +// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -- -fno-delayed-template-parsing // CHECK-FIXES: #include @@ -109,7 +109,7 @@ struct PositiveConstValueConstructor { 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-FIXES-NOT: template void templateWithNonTemplatizedParameter(const ExpensiveToCopyType& S, T V) { } void instantiated() { @@ -381,3 +381,24 @@ void templateFunction(ExpensiveToCopyType E) { // 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-FIXES-NOT: T templateSpecializationFunction(const ExpensiveToCopyType& E) { + return T(); +} + +template <> +bool templateSpecializationFunction(ExpensiveToCopyType E) { + // CHECK-MESSAGES: [[@LINE-1]]:57: warning: the parameter 'E' is copied + // CHECK-FIXES-NOT: bool templateSpecializationFunction(const ExpensiveToCopyType& E) { + return true; +} + +template <> +int templateSpecializationFunction(ExpensiveToCopyType E) { + // CHECK-MESSAGES: [[@LINE-1]]:56: warning: the parameter 'E' is copied + // CHECK-FIXES-NOT: int templateSpecializationFunction(const ExpensiveToCopyType& E) { + return 0; +}