From 21b76badebbdb7fcc871f60b0566e2f92d65b05a Mon Sep 17 00:00:00 2001 From: Gabor Horvath Date: Tue, 17 Feb 2015 21:45:38 +0000 Subject: [PATCH] [clang-tidy] Fixed two wrong fix-it cases in misc-inefficient-algorithm checker. llvm-svn: 229552 --- .../misc/InefficientAlgorithmCheck.cpp | 21 ++++++++- .../clang-tidy/misc-inefficient-algorithm.cpp | 43 +++++++++++++++++-- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/misc/InefficientAlgorithmCheck.cpp b/clang-tools-extra/clang-tidy/misc/InefficientAlgorithmCheck.cpp index 906140db54e3..16401b7d4758 100644 --- a/clang-tools-extra/clang-tidy/misc/InefficientAlgorithmCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/InefficientAlgorithmCheck.cpp @@ -17,9 +17,18 @@ using namespace clang::ast_matchers; namespace clang { namespace tidy { +static bool areTypesCompatible(QualType Left, QualType Right) { + if (const auto *LeftRefType = Left->getAs()) + Left = LeftRefType->getPointeeType(); + if (const auto *RightRefType = Right->getAs()) + Right = RightRefType->getPointeeType(); + return Left->getCanonicalTypeUnqualified() == + Right->getCanonicalTypeUnqualified(); +} + void InefficientAlgorithmCheck::registerMatchers(MatchFinder *Finder) { const std::string Algorithms = - "^::std::(find|count|equal_range|lower_blound|upper_bound)$"; + "^::std::(find|count|equal_range|lower_bound|upper_bound)$"; const auto ContainerMatcher = classTemplateSpecializationDecl( matchesName("^::std::(unordered_)?(multi)?(set|map)$")); const auto Matcher = @@ -57,6 +66,14 @@ void InefficientAlgorithmCheck::check(const MatchFinder::MatchResult &Result) { const llvm::StringRef IneffContName = IneffCont->getName(); const bool Unordered = IneffContName.find("unordered") != llvm::StringRef::npos; + const bool Maplike = IneffContName.find("map") != llvm::StringRef::npos; + + // Store if the key type of the container is compatible with the value + // that is searched for. + QualType ValueType = AlgCall->getArg(2)->getType(); + QualType KeyType = + IneffCont->getTemplateArgs()[0].getAsType().getCanonicalType(); + const bool CompatibleTypes = areTypesCompatible(KeyType, ValueType); // Check if the comparison type for the algorithm and the container matches. if (AlgCall->getNumArgs() == 4 && !Unordered) { @@ -87,7 +104,7 @@ void InefficientAlgorithmCheck::check(const MatchFinder::MatchResult &Result) { const auto *IneffContExpr = Result.Nodes.getNodeAs("IneffContExpr"); FixItHint Hint; - if (!AlgCall->getLocStart().isMacroID()) { + if (!AlgCall->getLocStart().isMacroID() && !Maplike && CompatibleTypes) { std::string ReplacementText = (llvm::Twine(Lexer::getSourceText( CharSourceRange::getTokenRange(IneffContExpr->getSourceRange()), diff --git a/clang-tools-extra/test/clang-tidy/misc-inefficient-algorithm.cpp b/clang-tools-extra/test/clang-tidy/misc-inefficient-algorithm.cpp index 4ed2fb25c9cb..ea668c2bedd9 100644 --- a/clang-tools-extra/test/clang-tidy/misc-inefficient-algorithm.cpp +++ b/clang-tools-extra/test/clang-tidy/misc-inefficient-algorithm.cpp @@ -23,6 +23,19 @@ template > struct set { iterator end() const; }; +struct other_iterator_type {}; + +template > struct map { + typedef other_iterator_type iterator; + iterator find(const K &k); + unsigned count(const K &k); + + iterator begin(); + iterator end(); + iterator begin() const; + iterator end() const; +}; + template struct unordered_set : set {}; template > struct multiset : set {}; @@ -32,15 +45,17 @@ template FwIt find(FwIt, FwIt, const K &); template FwIt find(FwIt, FwIt, const K &, Cmp); -template -FwIt find_if(FwIt, FwIt, Pred); +template FwIt find_if(FwIt, FwIt, Pred); template FwIt count(FwIt, FwIt, const K &); template FwIt lower_bound(FwIt, FwIt, const K &); + +template +FwIt lower_bound(FwIt, FwIt, const K &, Ord); } -#define FIND_IN_SET(x) find(x.begin(), x.end(), 10) +#define FIND_IN_SET(x) find(x.begin(), x.end(), 10) // CHECK-FIXES: #define FIND_IN_SET(x) find(x.begin(), x.end(), 10) template void f(const T &t) { @@ -93,4 +108,26 @@ int main() { find(us.begin(), us.end(), 10); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be // CHECK-FIXES: {{^ }}us.find(10);{{$}} + + std::map intmap; + find(intmap.begin(), intmap.end(), 46); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be + // CHECK-FIXES: {{^ }}find(intmap.begin(), intmap.end(), 46);{{$}} +} + +struct Value { + int value; +}; + +struct Ordering { + bool operator()(const Value &lhs, const Value &rhs) const { + return lhs.value < rhs.value; + } + bool operator()(int lhs, const Value &rhs) const { return lhs < rhs.value; } +}; + +void g(std::set container, int value) { + lower_bound(container.begin(), container.end(), value, Ordering()); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this STL algorithm call should be + // CHECK-FIXES: {{^ }}lower_bound(container.begin(), container.end(), value, Ordering());{{$}} }