================
@@ -0,0 +1,106 @@
+//===--- UseStartsEndsWithCheck.cpp - clang-tidy 
--------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "UseStartsEndsWithCheck.h"
+
+#include "../utils/OptionsUtils.h"
+#include "clang/Lex/Lexer.h"
+
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+const auto DefaultStringLikeClasses =
+    "::std::basic_string;::std::basic_string_view";
+
+UseStartsEndsWithCheck::UseStartsEndsWithCheck(StringRef Name,
+                                               ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      StringLikeClasses(utils::options::parseStringList(
+          Options.get("StringLikeClasses", DefaultStringLikeClasses))) {}
+
+void UseStartsEndsWithCheck::registerMatchers(MatchFinder *Finder) {
+  const auto ZeroLiteral = integerLiteral(equals(0));
+  const auto StringClassMatcher = cxxRecordDecl(hasAnyName(StringLikeClasses));
+  const auto StringType = hasUnqualifiedDesugaredType(
+      recordType(hasDeclaration(StringClassMatcher)));
+
+  const auto StringFind = cxxMemberCallExpr(
+      // .find()-call on a string...
+      callee(cxxMethodDecl(hasName("find")).bind("findfun")),
+      on(hasType(StringType)),
+      // ... with some search expression ...
+      hasArgument(0, expr().bind("needle")),
+      // ... and either "0" as second argument or the default argument (also 
0).
+      anyOf(hasArgument(1, ZeroLiteral), argumentCountIs(1)));
+
+  const auto StringRFind = cxxMemberCallExpr(
+      // .rfind()-call on a string...
+      callee(cxxMethodDecl(hasName("rfind")).bind("rfindfun")),
+      on(hasType(StringType)),
+      // ... with some search expression ...
+      hasArgument(0, expr().bind("needle")),
+      // ... and "0" as second argument.
+      hasArgument(1, ZeroLiteral));
+
+  Finder->addMatcher(
+      // Match [=!]= with a zero on one side and a string.(r?)find on the 
other.
+      binaryOperator(
+          hasAnyOperatorName("==", "!="),
+          hasOperands(ZeroLiteral,
+                      cxxMemberCallExpr(anyOf(StringFind, StringRFind))
+                          .bind("findexpr")))
+          .bind("expr"),
+      this);
+}
+
+void UseStartsEndsWithCheck::check(const MatchFinder::MatchResult &Result) {
+  const ASTContext &Context = *Result.Context;
+  const SourceManager &Source = Context.getSourceManager();
+
+  const auto *ComparisonExpr = Result.Nodes.getNodeAs<BinaryOperator>("expr");
+  const auto *Needle = Result.Nodes.getNodeAs<Expr>("needle");
+  const Expr *Haystack = Result.Nodes.getNodeAs<CXXMemberCallExpr>("findexpr")
+                             ->getImplicitObjectArgument();
+  const auto *FindFun = Result.Nodes.getNodeAs<CXXMethodDecl>("findfun");
+  const auto *RFindFun = Result.Nodes.getNodeAs<CXXMethodDecl>("rfindfun");
+  assert(!FindFun != !RFindFun); // XOR.
+
+  if (ComparisonExpr->getBeginLoc().isMacroID()) {
+    return;
+  }
+
+  const StringRef NeedleExprCode = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(Needle->getSourceRange()), Source,
+      Context.getLangOpts());
+  const StringRef HaystackExprCode = Lexer::getSourceText(
+      CharSourceRange::getTokenRange(Haystack->getSourceRange()), Source,
+      Context.getLangOpts());
+
+  const bool Rev = RFindFun != nullptr;
+  const bool Neg = ComparisonExpr->getOpcode() == BO_NE;
+  const std::string ReplacementCode = ((Neg ? "!" : "") + HaystackExprCode +
+                                       ".starts_with(" + NeedleExprCode + ")")
+                                          .str();
+
+  diag(ComparisonExpr->getBeginLoc(),
----------------
PiotrZSL wrote:

actually you could point here to place where call to find/rfind happen

https://github.com/llvm/llvm-project/pull/72385
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to