[clang-tools-extra] [clang-tidy] Add new modernize-string-find-startswith check (PR #72385)
Piotr Zegar via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 15 07:36:10 PST 2023
================
@@ -0,0 +1,105 @@
+//===--- StringFindStartswithCheck.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 "StringFindStartswithCheck.h"
+
+#include "../utils/OptionsUtils.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+const auto DefaultStringLikeClasses =
+ "::std::basic_string;::std::basic_string_view";
+
+StringFindStartswithCheck::StringFindStartswithCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ StringLikeClasses(utils::options::parseStringList(
+ Options.get("StringLikeClasses", DefaultStringLikeClasses))) {}
+
+void StringFindStartswithCheck::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), hasArgument(1, cxxDefaultArgExpr())));
+
+ const auto StringRFind = cxxMemberCallExpr(
+ // .rfind()-call on a string...
+ callee(cxxMethodDecl(hasName("rfind")).bind("findfun")),
+ 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(ignoringParenImpCasts(ZeroLiteral),
+ ignoringParenImpCasts(
+ cxxMemberCallExpr(anyOf(StringFind, StringRFind))
+ .bind("findexpr"))))
+ .bind("expr"),
+ this);
+}
+
+void StringFindStartswithCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto &Context = *Result.Context;
+ const auto &Source = Context.getSourceManager();
+
+ const auto *ComparisonExpr = Result.Nodes.getNodeAs<BinaryOperator>("expr");
+ const auto *Needle = Result.Nodes.getNodeAs<Expr>("needle");
+ const auto *Haystack = Result.Nodes.getNodeAs<CXXMemberCallExpr>("findexpr")
+ ->getImplicitObjectArgument();
+ const auto *FindFun = Result.Nodes.getNodeAs<CXXMethodDecl>("findfun");
+
+ if (ComparisonExpr->getBeginLoc().isMacroID()) {
+ return;
+ }
+
+ const auto Rev = FindFun->getName().contains("rfind");
+ const auto Neg = ComparisonExpr->getOpcode() == BO_NE;
+
+ const auto NeedleExprCode = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(Needle->getSourceRange()), Source,
+ Context.getLangOpts());
+ const auto HaystackExprCode = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(Haystack->getSourceRange()), Source,
----------------
PiotrZSL wrote:
Wont work with macros, you may want to get expansion location
https://github.com/llvm/llvm-project/pull/72385
More information about the cfe-commits
mailing list