[clang-tidy] Do not issue fixit for explicit template specializations

Summary:

Do not issue fixit in UnnecessaryValueParamCheck if the function is an explicit template specialization as this could cause build breakages.

Reviewers: alexfh

Subscribers: JDevlieghere, xazax.hun, cfe-commits

Differential Revision: https://reviews.llvm.org/D35718

llvm-svn: 309067
This commit is contained in:
Felix Berger 2017-07-26 00:45:41 +00:00
parent 14d90fd05c
commit 603ea2df2a
2 changed files with 26 additions and 1 deletions

View File

@ -58,6 +58,18 @@ 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<CXXMethodDecl>(&Function))
if (Method->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization &&
Method->getMemberSpecializationInfo()->isExplicitSpecialization())
return true;
return false;
}
} // namespace
UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
@ -133,9 +145,11 @@ 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.
const auto *Method = llvm::dyn_cast<CXXMethodDecl>(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()) {

View File

@ -348,3 +348,14 @@ void fun() {
ExpensiveToCopyType E;
NegativeUsingConstructor S(E);
}
template<typename T>
void templateFunction(T) {
}
template<>
void templateFunction<ExpensiveToCopyType>(ExpensiveToCopyType E) {
// CHECK-MESSAGES: [[@LINE-1]]:64: warning: the parameter 'E' is copied
// CHECK-FIXES: void templateFunction<ExpensiveToCopyType>(ExpensiveToCopyType E) {
E.constReference();
}