@@ -17,9 +17,6 @@ using namespace clang::ast_matchers;
1717namespace clang ::tidy::readability {
1818
1919void UseSpanFirstLastCheck::registerMatchers (MatchFinder *Finder) {
20- if (!getLangOpts ().CPlusPlus20 )
21- return ;
22-
2320 // Match span::subspan calls
2421 const auto HasSpanType =
2522 hasType (hasUnqualifiedDesugaredType (recordType (hasDeclaration (
@@ -53,56 +50,54 @@ void UseSpanFirstLastCheck::handleSubspanCall(
5350 // Check if this is subspan(0, n) -> first(n)
5451 bool IsZeroOffset = false ;
5552 const Expr *OffsetE = Offset->IgnoreImpCasts ();
56- if (const auto *IL = dyn_cast<IntegerLiteral>(OffsetE)) {
53+ if (const auto *IL = dyn_cast<IntegerLiteral>(OffsetE))
5754 IsZeroOffset = IL->getValue () == 0 ;
58- }
5955
6056 // Check if this is subspan(size() - n) -> last(n)
6157 bool IsSizeMinusN = false ;
6258 const Expr *SizeMinusArg = nullptr ;
63- if (const auto *BO = dyn_cast<BinaryOperator>(OffsetE)) {
64- if (BO->getOpcode () == BO_Sub) {
65- if (const auto *SizeCall = dyn_cast<CXXMemberCallExpr>(BO->getLHS ())) {
66- if (SizeCall->getMethodDecl ()->getName () == " size" ) {
67- IsSizeMinusN = true ;
68- SizeMinusArg = BO->getRHS ();
69- }
70- }
59+
60+ const auto *BO = dyn_cast<BinaryOperator>(OffsetE);
61+ if (BO && BO->getOpcode () == BO_Sub) {
62+ const auto *SizeCall = dyn_cast<CXXMemberCallExpr>(BO->getLHS ());
63+ if (SizeCall && SizeCall->getMethodDecl ()->getName () == " size" ) {
64+ IsSizeMinusN = true ;
65+ SizeMinusArg = BO->getRHS ();
7166 }
7267 }
7368
7469 // Build replacement text
7570 std::string Replacement;
7671 if (IsZeroOffset && Count) {
7772 // subspan(0, count) -> first(count)
78- auto CountStr = Lexer::getSourceText (
73+ const auto CountStr = Lexer::getSourceText (
7974 CharSourceRange::getTokenRange (Count->getSourceRange ()),
8075 Context.getSourceManager (), Context.getLangOpts ());
8176 const auto *Base =
8277 cast<CXXMemberCallExpr>(Call)->getImplicitObjectArgument ();
83- auto BaseStr = Lexer::getSourceText (
78+ const StringRef BaseStr = Lexer::getSourceText (
8479 CharSourceRange::getTokenRange (Base->getSourceRange ()),
8580 Context.getSourceManager (), Context.getLangOpts ());
8681 Replacement = BaseStr.str () + " .first(" + CountStr.str () + " )" ;
8782 } else if (IsSizeMinusN && SizeMinusArg) {
8883 // subspan(size() - n) -> last(n)
89- auto ArgStr = Lexer::getSourceText (
84+ const StringRef ArgStr = Lexer::getSourceText (
9085 CharSourceRange::getTokenRange (SizeMinusArg->getSourceRange ()),
9186 Context.getSourceManager (), Context.getLangOpts ());
9287 const auto *Base =
9388 cast<CXXMemberCallExpr>(Call)->getImplicitObjectArgument ();
94- auto BaseStr = Lexer::getSourceText (
89+ const StringRef BaseStr = Lexer::getSourceText (
9590 CharSourceRange::getTokenRange (Base->getSourceRange ()),
9691 Context.getSourceManager (), Context.getLangOpts ());
9792 Replacement = BaseStr.str () + " .last(" + ArgStr.str () + " )" ;
9893 }
9994
10095 if (!Replacement.empty ()) {
10196 if (IsZeroOffset && Count) {
102- diag (Call->getBeginLoc (), " prefer span::first() over subspan()" )
97+ diag (Call->getBeginLoc (), " prefer ' span::first()' over ' subspan()' " )
10398 << FixItHint::CreateReplacement (Call->getSourceRange (), Replacement);
10499 } else {
105- diag (Call->getBeginLoc (), " prefer span::last() over subspan()" )
100+ diag (Call->getBeginLoc (), " prefer ' span::last()' over ' subspan()' " )
106101 << FixItHint::CreateReplacement (Call->getSourceRange (), Replacement);
107102 }
108103 }
0 commit comments