[clang-tidy] Do not issue fix for functions that are referenced outside of callExpr
Summary: Suppress fixes for functions that are referenced within the compilation unit outside of a call expression as the signature change could break the code referencing the function. We still issue a warning in this case so that users can decide to manually change the function signature. Reviewers: alexfh, sbenza, aaron.ballman Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D26203 llvm-svn: 286424
This commit is contained in:
parent
4e1b5a53c7
commit
85f9e8b316
|
@ -39,6 +39,14 @@ bool isSubset(const S &SubsetCandidate, const S &SupersetCandidate) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool isReferencedOutsideOfCallExpr(const FunctionDecl &Function,
|
||||
ASTContext &Context) {
|
||||
auto Matches = match(declRefExpr(to(functionDecl(equalsNode(&Function))),
|
||||
unless(hasAncestor(callExpr()))),
|
||||
Context);
|
||||
return !Matches.empty();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
UnnecessaryValueParamCheck::UnnecessaryValueParamCheck(
|
||||
|
@ -118,10 +126,14 @@ void UnnecessaryValueParamCheck::check(const MatchFinder::MatchResult &Result) {
|
|||
"invocation but only used as a const reference; "
|
||||
"consider making it a const reference")
|
||||
<< paramNameOrIndex(Param->getName(), Index);
|
||||
// Do not propose fixes in macros since we cannot place them correctly, or if
|
||||
// function is virtual as it might break overrides.
|
||||
// Do not propose fixes when:
|
||||
// 1. the ParmVarDecl is in a macro, since we cannot place them correctly
|
||||
// 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.
|
||||
const auto *Method = llvm::dyn_cast<CXXMethodDecl>(Function);
|
||||
if (Param->getLocStart().isMacroID() || (Method && Method->isVirtual()))
|
||||
if (Param->getLocStart().isMacroID() || (Method && Method->isVirtual()) ||
|
||||
isReferencedOutsideOfCallExpr(*Function, *Result.Context))
|
||||
return;
|
||||
for (const auto *FunctionDecl = Function; FunctionDecl != nullptr;
|
||||
FunctionDecl = FunctionDecl->getPreviousDecl()) {
|
||||
|
|
|
@ -253,3 +253,21 @@ void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
|
|||
// CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
|
||||
// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A) {
|
||||
}
|
||||
|
||||
void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:75: warning: the parameter 'A' is copied
|
||||
// CHECK-FIXES: void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
|
||||
}
|
||||
|
||||
void ReferenceFunctionOutsideOfCallExpr() {
|
||||
void (*ptr)(ExpensiveToCopyType) = &PositiveOnlyMessageAsReferencedInCompilationUnit;
|
||||
}
|
||||
|
||||
void PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType A) {
|
||||
// CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'A' is copied
|
||||
// CHECK-FIXES: void PositiveMessageAndFixAsFunctionIsCalled(const ExpensiveToCopyType& A) {
|
||||
}
|
||||
|
||||
void ReferenceFunctionByCallingIt() {
|
||||
PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue