================ @@ -7,42 +7,70 @@ //===----------------------------------------------------------------------===// #include "StringCompareCheck.h" -#include "../utils/FixItHintUtils.h" +#include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" #include "clang/Tooling/FixIt.h" +#include "llvm/ADT/StringRef.h" +#include <vector> using namespace clang::ast_matchers; +namespace optutils = clang::tidy::utils::options; namespace clang::tidy::readability { static const StringRef CompareMessage = "do not use 'compare' to test equality " "of strings; use the string equality " "operator instead"; +static const std::vector<StringRef> StringClasses = { + "::std::basic_string", "::std::basic_string_view"}; + +StringCompareCheck::StringCompareCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + StringLikeClasses( + optutils::parseStringList(Options.get("StringLikeClasses", ""))) {} + void StringCompareCheck::registerMatchers(MatchFinder *Finder) { - const auto StrCompare = cxxMemberCallExpr( - callee(cxxMethodDecl(hasName("compare"), - ofClass(classTemplateSpecializationDecl( - hasName("::std::basic_string"))))), - hasArgument(0, expr().bind("str2")), argumentCountIs(1), - callee(memberExpr().bind("str1"))); - - // First and second case: cast str.compare(str) to boolean. - Finder->addMatcher( - traverse(TK_AsIs, - implicitCastExpr(hasImplicitDestinationType(booleanType()), - has(StrCompare)) - .bind("match1")), - this); - - // Third and fourth case: str.compare(str) == 0 and str.compare(str) != 0. - Finder->addMatcher( - binaryOperator(hasAnyOperatorName("==", "!="), - hasOperands(StrCompare.bind("compare"), - integerLiteral(equals(0)).bind("zero"))) - .bind("match2"), - this); + const auto RegisterForClasses = [&, this](const auto &StringClassMatcher) { ---------------- vvd170501 wrote:
Type of `StringClassMatcher` dependinds on whether the check is used with or without `StringLikeClasses`, so a template lambda is needed. It's possible to use `anyOf` and `cxxRecordDecl` in both cases and remove the lambda, but this will probably slow the check down in default case. https://github.com/llvm/llvm-project/pull/88636 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits