[clang-tidy] Support replacements in macro arguments in misc-inefficient-algorithm

Summary:
Support replacements in macro arguments in the
misc-inefficient-algorithm check.

Reviewers: klimek

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D11677

llvm-svn: 243747
This commit is contained in:
Alexander Kornienko 2015-07-31 13:34:58 +00:00
parent a2ce083d2d
commit b4fbb173f0
2 changed files with 40 additions and 11 deletions

View File

@ -105,18 +105,41 @@ void InefficientAlgorithmCheck::check(const MatchFinder::MatchResult &Result) {
const auto *IneffContExpr = Result.Nodes.getNodeAs<Expr>("IneffContExpr");
FixItHint Hint;
if (!AlgCall->getLocStart().isMacroID() && !Maplike && CompatibleTypes) {
SourceManager &SM = *Result.SourceManager;
LangOptions LangOpts = Result.Context->getLangOpts();
CharSourceRange CallRange =
CharSourceRange::getTokenRange(AlgCall->getSourceRange());
// FIXME: Create a common utility to extract a file range that the given token
// sequence is exactly spelled at (without macro argument expansions etc.).
// We can't use Lexer::makeFileCharRange here, because for
//
// #define F(x) x
// x(a b c);
//
// it will return "x(a b c)", when given the range "a"-"c". It makes sense for
// removals, but not for replacements.
//
// This code is over-simplified, but works for many real cases.
if (SM.isMacroArgExpansion(CallRange.getBegin()) &&
SM.isMacroArgExpansion(CallRange.getEnd())) {
CallRange.setBegin(SM.getSpellingLoc(CallRange.getBegin()));
CallRange.setEnd(SM.getSpellingLoc(CallRange.getEnd()));
}
if (!CallRange.getBegin().isMacroID() && !Maplike && CompatibleTypes) {
StringRef ContainerText = Lexer::getSourceText(
CharSourceRange::getTokenRange(IneffContExpr->getSourceRange()), SM,
LangOpts);
StringRef ParamText = Lexer::getSourceText(
CharSourceRange::getTokenRange(AlgParam->getSourceRange()), SM,
LangOpts);
std::string ReplacementText =
(llvm::Twine(Lexer::getSourceText(
CharSourceRange::getTokenRange(IneffContExpr->getSourceRange()),
*Result.SourceManager, Result.Context->getLangOpts())) +
(PtrToContainer ? "->" : ".") + AlgDecl->getName() + "(" +
Lexer::getSourceText(
CharSourceRange::getTokenRange(AlgParam->getSourceRange()),
*Result.SourceManager, Result.Context->getLangOpts()) +
")").str();
Hint = FixItHint::CreateReplacement(AlgCall->getSourceRange(),
ReplacementText);
(llvm::Twine(ContainerText) + (PtrToContainer ? "->" : ".") +
AlgDecl->getName() + "(" + ParamText + ")")
.str();
Hint = FixItHint::CreateReplacement(CallRange, ReplacementText);
}
diag(AlgCall->getLocStart(),

View File

@ -76,6 +76,12 @@ int main() {
auto c = count(s.begin(), s.end(), 43);
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: this STL algorithm call should be
// CHECK-FIXES: {{^ }}auto c = s.count(43);{{$}}
#define SECOND(x, y, z) y
SECOND(q,std::count(s.begin(), s.end(), 22),w);
// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: this STL algorithm call should be
// CHECK-FIXES: {{^ }}SECOND(q,s.count(22),w);{{$}}
it = find_if(s.begin(), s.end(), [](int) { return false; });
std::multiset<int> ms;