[clang-tools-extra] [clang-tidy][modernize-use-starts-ends-with] Add support for compare() (PR #89530)
Piotr Zegar via cfe-commits
cfe-commits at lists.llvm.org
Sun Apr 21 14:20:47 PDT 2024
================
@@ -16,6 +16,75 @@
using namespace clang::ast_matchers;
namespace clang::tidy::modernize {
+namespace {
+// Given two argument indices X and Y, matches when a call expression has a
+// string at index X with an expression representing that string's length at
+// index Y. The string can be a string literal or a variable. The length can be
+// matched via an integer literal or a call to strlen() in the case of a string
+// literal, and by a call to size() or length() in the string variable case.
+AST_POLYMORPHIC_MATCHER_P2(hasStringAndLengthArguments,
+ AST_POLYMORPHIC_SUPPORTED_TYPES(
+ CallExpr, CXXConstructExpr,
+ CXXUnresolvedConstructExpr, ObjCMessageExpr),
+ unsigned, StringArgIndex, unsigned, LengthArgIndex) {
+ if (StringArgIndex >= Node.getNumArgs() ||
+ LengthArgIndex >= Node.getNumArgs()) {
+ return false;
+ }
+
+ const Expr *StringArgExpr =
+ Node.getArg(StringArgIndex)->IgnoreParenImpCasts();
+ const Expr *LengthArgExpr =
+ Node.getArg(LengthArgIndex)->IgnoreParenImpCasts();
+
+ if (const auto *StringArg = dyn_cast<StringLiteral>(StringArgExpr)) {
+ // Match an integer literal equal to the string length or a call to strlen.
+
+ static const auto Matcher = expr(anyOf(
+ integerLiteral().bind("integer_literal_size"),
+ callExpr(callee(functionDecl(hasName("strlen"))), argumentCountIs(1),
+ hasArgument(0, stringLiteral().bind("strlen_arg")))));
+
+ if (!Matcher.matches(*LengthArgExpr, Finder, Builder)) {
+ return false;
+ }
+
+ return Builder->removeBindings(
+ [&](const ast_matchers::internal::BoundNodesMap &Nodes) {
+ const auto *IntegerLiteralSize =
+ Nodes.getNodeAs<IntegerLiteral>("integer_literal_size");
+ const auto *StrlenArg = Nodes.getNodeAs<StringLiteral>("strlen_arg");
+ if (IntegerLiteralSize) {
+ return IntegerLiteralSize->getValue().getZExtValue() !=
+ StringArg->getLength();
+ }
+ return StrlenArg->getLength() != StringArg->getLength();
+ });
+ }
+
+ if (const auto *StringArg = dyn_cast<DeclRefExpr>(StringArgExpr)) {
+ // Match a call to size() or length() on the same variable.
+
+ static const auto Matcher = cxxMemberCallExpr(
+ on(declRefExpr(to(varDecl().bind("string_var_decl")))),
+ callee(cxxMethodDecl(hasAnyName("size", "length"), isConst(),
+ parameterCountIs(0))));
----------------
PiotrZSL wrote:
instead of making them static, pass them to this matcher as two "InnerMatcher", check how other checks/matchers do that. Static matchers could make problems with object lifetime, and code like this is not allowed per codding standard.
https://github.com/llvm/llvm-project/pull/89530
More information about the cfe-commits
mailing list