================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits