================ @@ -0,0 +1,104 @@ +//===--- UseSpanFirstLastCheck.cpp - clang-tidy -----------------*- C++ -*-===// +// +// 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 "UseSpanFirstLastCheck.h" +#include "../utils/ASTUtils.h" +#include "../utils/Matchers.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; +using namespace clang::tidy::matchers; + +namespace clang::tidy::readability { + +void UseSpanFirstLastCheck::registerMatchers(MatchFinder *Finder) { + const auto HasSpanType = + hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration( + classTemplateSpecializationDecl(hasName("::std::span")))))); + + // Match span.subspan(0, n) -> first(n) + Finder->addMatcher( + cxxMemberCallExpr( + callee(memberExpr(hasDeclaration(cxxMethodDecl(hasName("subspan"))))), + on(expr(HasSpanType).bind("span_object")), + hasArgument(0, integerLiteral(equals(0))), + hasArgument(1, expr().bind("count")), argumentCountIs(2)) + .bind("first_subspan"), + this); + + // Match span.subspan(span.size() - n) or span.subspan(std::ranges::size(span) + // - n) + // -> last(n) + const auto SizeCall = anyOf( + cxxMemberCallExpr( + callee(memberExpr(hasDeclaration(cxxMethodDecl(hasName("size"))))), + on(expr(isStatementIdenticalToBoundNode("span_object")))), + callExpr(callee(functionDecl( + hasAnyName("::std::size", "::std::ranges::size"))), + hasArgument( + 0, expr(isStatementIdenticalToBoundNode("span_object"))))); + + Finder->addMatcher( + cxxMemberCallExpr( + callee(memberExpr(hasDeclaration(cxxMethodDecl(hasName("subspan"))))), + on(expr(HasSpanType).bind("span_object")), + hasArgument(0, binaryOperator(hasOperatorName("-"), hasLHS(SizeCall), + hasRHS(expr().bind("count")))), + argumentCountIs(1)) ---------------- 5chmidti wrote:
The `argumentCountIs` matcher should be the first this that is checked inside the `cxxMemberCallExpr` matcher, because that is a simple integer comparison that can exclude a lot of AST nodes from further matching. The same applies to the other `cxxMemberCallExpr` above. https://github.com/llvm/llvm-project/pull/118074 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits