Author: alexfh Date: Wed Jun 7 03:25:51 2017 New Revision: 304879 URL: http://llvm.org/viewvc/llvm-project?rev=304879&view=rev Log: [clang-tidy] Make misc-inaccurate-erase work with real C++11 containers.
The check failed to match iterator->const_iterator conversion that is happening at least when using the libstdc++'s vector. We might want to make it match even more flexible patterns, if we see more false negatives. Modified: clang-tools-extra/trunk/clang-tidy/misc/InaccurateEraseCheck.cpp clang-tools-extra/trunk/test/clang-tidy/misc-inaccurate-erase.cpp Modified: clang-tools-extra/trunk/clang-tidy/misc/InaccurateEraseCheck.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/InaccurateEraseCheck.cpp?rev=304879&r1=304878&r2=304879&view=diff ============================================================================== --- clang-tools-extra/trunk/clang-tidy/misc/InaccurateEraseCheck.cpp (original) +++ clang-tools-extra/trunk/clang-tidy/misc/InaccurateEraseCheck.cpp Wed Jun 7 03:25:51 2017 @@ -28,38 +28,40 @@ void InaccurateEraseCheck::registerMatch if (!getLangOpts().CPlusPlus) return; - const auto CheckForEndCall = hasArgument( - 1, anyOf(cxxConstructExpr(has(ignoringParenImpCasts( - cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end")))) - .bind("InaccEndCall")))), - anything())); + const auto EndCall = + callExpr( + callee(functionDecl(hasAnyName("remove", "remove_if", "unique"))), + hasArgument( + 1, + anyOf(cxxConstructExpr(has(ignoringImplicit( + cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end")))) + .bind("end")))), + anything()))) + .bind("alg"); const auto DeclInStd = decl(isInStdNamespace()); Finder->addMatcher( cxxMemberCallExpr( on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))), callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1), - hasArgument(0, has(ignoringParenImpCasts( - callExpr(callee(functionDecl(hasAnyName( - "remove", "remove_if", "unique"))), - CheckForEndCall) - .bind("InaccAlgCall")))), + hasArgument(0, has(ignoringImplicit( + anyOf(EndCall, has(ignoringImplicit(EndCall)))))), unless(isInTemplateInstantiation())) - .bind("InaccErase"), + .bind("erase"), this); } void InaccurateEraseCheck::check(const MatchFinder::MatchResult &Result) { const auto *MemberCall = - Result.Nodes.getNodeAs<CXXMemberCallExpr>("InaccErase"); + Result.Nodes.getNodeAs<CXXMemberCallExpr>("erase"); const auto *EndExpr = - Result.Nodes.getNodeAs<CXXMemberCallExpr>("InaccEndCall"); + Result.Nodes.getNodeAs<CXXMemberCallExpr>("end"); const SourceLocation Loc = MemberCall->getLocStart(); FixItHint Hint; if (!Loc.isMacroID() && EndExpr) { - const auto *AlgCall = Result.Nodes.getNodeAs<CallExpr>("InaccAlgCall"); + const auto *AlgCall = Result.Nodes.getNodeAs<CallExpr>("alg"); std::string ReplacementText = Lexer::getSourceText( CharSourceRange::getTokenRange(EndExpr->getSourceRange()), *Result.SourceManager, getLangOpts()); Modified: clang-tools-extra/trunk/test/clang-tidy/misc-inaccurate-erase.cpp URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/misc-inaccurate-erase.cpp?rev=304879&r1=304878&r2=304879&view=diff ============================================================================== --- clang-tools-extra/trunk/test/clang-tidy/misc-inaccurate-erase.cpp (original) +++ clang-tools-extra/trunk/test/clang-tidy/misc-inaccurate-erase.cpp Wed Jun 7 03:25:51 2017 @@ -2,12 +2,15 @@ namespace std { template <typename T> struct vec_iterator { - T *ptr; + T ptr; vec_iterator operator++(int); + + template <typename X> + vec_iterator(const vec_iterator<X> &); // Omit enable_if<...>. }; template <typename T> struct vector { - typedef vec_iterator<T> iterator; + typedef vec_iterator<T*> iterator; iterator begin(); iterator end(); @@ -16,6 +19,17 @@ template <typename T> struct vector { void erase(iterator, iterator); }; +template <typename T> struct vector_with_const_iterator { + typedef vec_iterator<T*> iterator; + typedef vec_iterator<const T*> const_iterator; + + iterator begin(); + iterator end(); + + void erase(const_iterator); + void erase(const_iterator, const_iterator); +}; + template <typename FwIt, typename T> FwIt remove(FwIt begin, FwIt end, const T &val); @@ -61,6 +75,10 @@ int main() { // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one // CHECK-FIXES: {{^ }}p->erase(remove(p->begin(), p->end(), 11), p->end());{{$}} + std::vector_with_const_iterator<int> v2; + v2.erase(remove(v2.begin(), v2.end(), 12)); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: this call will remove at most one + // CHECK-FIXES: {{^ }}v2.erase(remove(v2.begin(), v2.end(), 12), v2.end());{{$}} // Fix is not trivial. auto it = v.end(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits