[clang-tools-extra] [clang-tidy] Add modernize-use-span-first-last check (PR #118074)

2024-11-29 Thread Helmut Januschka via cfe-commits

https://github.com/hjanuschka updated 
https://github.com/llvm/llvm-project/pull/118074

>From cb748c34d35b8c0c9ca93a67b111dcf5d7665b34 Mon Sep 17 00:00:00 2001
From: Helmut Januschka 
Date: Fri, 29 Nov 2024 10:17:49 +0100
Subject: [PATCH 1/7] [clang-tidy] Add modernize-use-span-first-last check

Add new check that modernizes std::span::subspan() calls to use the more
expressive first() and last() member functions where applicable.
---
 .../clang-tidy/modernize/CMakeLists.txt   |  1 +
 .../modernize/ModernizeTidyModule.cpp |  3 +
 .../modernize/UseSpanFirstLastCheck.cpp   | 97 +++
 .../modernize/UseSpanFirstLastCheck.h | 40 
 clang-tools-extra/docs/ReleaseNotes.rst   |  4 +
 .../checks/modernize/use-span-first-last.rst  | 19 
 .../modernize-subspan-conversion.cpp  | 50 ++
 7 files changed, 214 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-span-first-last.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/modernize-subspan-conversion.cpp

diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index c919d49b42873a..47dd12a2640b6c 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -49,6 +49,7 @@ add_clang_library(clangTidyModernizeModule STATIC
   UseTransparentFunctorsCheck.cpp
   UseUncaughtExceptionsCheck.cpp
   UseUsingCheck.cpp
+  UseSpanFirstLastCheck.cpp
 
   LINK_LIBS
   clangTidy
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index 18607593320635..6fc5de5aad20b7 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -42,6 +42,7 @@
 #include "UseNullptrCheck.h"
 #include "UseOverrideCheck.h"
 #include "UseRangesCheck.h"
+#include "UseSpanFirstLastCheck.h"
 #include "UseStartsEndsWithCheck.h"
 #include "UseStdFormatCheck.h"
 #include "UseStdNumbersCheck.h"
@@ -122,6 +123,8 @@ class ModernizeModule : public ClangTidyModule {
 CheckFactories.registerCheck(
 "modernize-use-uncaught-exceptions");
 CheckFactories.registerCheck("modernize-use-using");
+
CheckFactories.registerCheck("modernize-use-span-first-last");
+
   }
 };
 
diff --git a/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
new file mode 100644
index 00..f57571f2aa7c86
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
@@ -0,0 +1,97 @@
+//===--- 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 "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+void UseSpanFirstLastCheck::registerMatchers(MatchFinder *Finder) {
+  // Match span::subspan calls
+  const auto HasSpanType = hasType(hasUnqualifiedDesugaredType(
+  recordType(hasDeclaration(classTemplateSpecializationDecl(
+  hasName("::std::span"));
+
+  Finder->addMatcher(
+  cxxMemberCallExpr(
+  callee(memberExpr(hasDeclaration(
+  cxxMethodDecl(hasName("subspan"),
+  on(expr(HasSpanType)))
+  .bind("subspan"),
+  this);
+}
+
+void UseSpanFirstLastCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs("subspan");
+  if (!Call)
+return;
+
+  handleSubspanCall(Result, Call);
+}
+
+void UseSpanFirstLastCheck::handleSubspanCall(
+const MatchFinder::MatchResult &Result, const CXXMemberCallExpr *Call) {
+  // Get arguments
+  unsigned NumArgs = Call->getNumArgs();
+  if (NumArgs == 0 || NumArgs > 2)
+return;
+
+  const Expr *Offset = Call->getArg(0);
+  const Expr *Count = NumArgs > 1 ? Call->getArg(1) : nullptr;
+  auto &Context = *Result.Context;
+  bool IsZeroOffset = false;
+
+  // Check if offset is zero through any implicit casts
+  const Expr* OffsetE = Offset->IgnoreImpCasts();
+  if (const auto *IL = dyn_cast(OffsetE)) {
+IsZeroOffset = IL->getValue() == 0;
+  }
+
+  // Build replacement text
+  std::string Replacement;
+  if (IsZeroOffset && Count) {
+   

[clang-tools-extra] [clang-tidy] Add modernize-use-span-first-last check (PR #118074)

2024-11-29 Thread Helmut Januschka via cfe-commits

https://github.com/hjanuschka updated 
https://github.com/llvm/llvm-project/pull/118074

>From cb748c34d35b8c0c9ca93a67b111dcf5d7665b34 Mon Sep 17 00:00:00 2001
From: Helmut Januschka 
Date: Fri, 29 Nov 2024 10:17:49 +0100
Subject: [PATCH 1/6] [clang-tidy] Add modernize-use-span-first-last check

Add new check that modernizes std::span::subspan() calls to use the more
expressive first() and last() member functions where applicable.
---
 .../clang-tidy/modernize/CMakeLists.txt   |  1 +
 .../modernize/ModernizeTidyModule.cpp |  3 +
 .../modernize/UseSpanFirstLastCheck.cpp   | 97 +++
 .../modernize/UseSpanFirstLastCheck.h | 40 
 clang-tools-extra/docs/ReleaseNotes.rst   |  4 +
 .../checks/modernize/use-span-first-last.rst  | 19 
 .../modernize-subspan-conversion.cpp  | 50 ++
 7 files changed, 214 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-span-first-last.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/modernize-subspan-conversion.cpp

diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index c919d49b42873a..47dd12a2640b6c 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -49,6 +49,7 @@ add_clang_library(clangTidyModernizeModule STATIC
   UseTransparentFunctorsCheck.cpp
   UseUncaughtExceptionsCheck.cpp
   UseUsingCheck.cpp
+  UseSpanFirstLastCheck.cpp
 
   LINK_LIBS
   clangTidy
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index 18607593320635..6fc5de5aad20b7 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -42,6 +42,7 @@
 #include "UseNullptrCheck.h"
 #include "UseOverrideCheck.h"
 #include "UseRangesCheck.h"
+#include "UseSpanFirstLastCheck.h"
 #include "UseStartsEndsWithCheck.h"
 #include "UseStdFormatCheck.h"
 #include "UseStdNumbersCheck.h"
@@ -122,6 +123,8 @@ class ModernizeModule : public ClangTidyModule {
 CheckFactories.registerCheck(
 "modernize-use-uncaught-exceptions");
 CheckFactories.registerCheck("modernize-use-using");
+
CheckFactories.registerCheck("modernize-use-span-first-last");
+
   }
 };
 
diff --git a/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
new file mode 100644
index 00..f57571f2aa7c86
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
@@ -0,0 +1,97 @@
+//===--- 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 "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+void UseSpanFirstLastCheck::registerMatchers(MatchFinder *Finder) {
+  // Match span::subspan calls
+  const auto HasSpanType = hasType(hasUnqualifiedDesugaredType(
+  recordType(hasDeclaration(classTemplateSpecializationDecl(
+  hasName("::std::span"));
+
+  Finder->addMatcher(
+  cxxMemberCallExpr(
+  callee(memberExpr(hasDeclaration(
+  cxxMethodDecl(hasName("subspan"),
+  on(expr(HasSpanType)))
+  .bind("subspan"),
+  this);
+}
+
+void UseSpanFirstLastCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs("subspan");
+  if (!Call)
+return;
+
+  handleSubspanCall(Result, Call);
+}
+
+void UseSpanFirstLastCheck::handleSubspanCall(
+const MatchFinder::MatchResult &Result, const CXXMemberCallExpr *Call) {
+  // Get arguments
+  unsigned NumArgs = Call->getNumArgs();
+  if (NumArgs == 0 || NumArgs > 2)
+return;
+
+  const Expr *Offset = Call->getArg(0);
+  const Expr *Count = NumArgs > 1 ? Call->getArg(1) : nullptr;
+  auto &Context = *Result.Context;
+  bool IsZeroOffset = false;
+
+  // Check if offset is zero through any implicit casts
+  const Expr* OffsetE = Offset->IgnoreImpCasts();
+  if (const auto *IL = dyn_cast(OffsetE)) {
+IsZeroOffset = IL->getValue() == 0;
+  }
+
+  // Build replacement text
+  std::string Replacement;
+  if (IsZeroOffset && Count) {
+   

[clang-tools-extra] [clang-tidy] Add modernize-use-span-first-last check (PR #118074)

2024-11-29 Thread Helmut Januschka via cfe-commits

https://github.com/hjanuschka updated 
https://github.com/llvm/llvm-project/pull/118074

>From cb748c34d35b8c0c9ca93a67b111dcf5d7665b34 Mon Sep 17 00:00:00 2001
From: Helmut Januschka 
Date: Fri, 29 Nov 2024 10:17:49 +0100
Subject: [PATCH 1/4] [clang-tidy] Add modernize-use-span-first-last check

Add new check that modernizes std::span::subspan() calls to use the more
expressive first() and last() member functions where applicable.
---
 .../clang-tidy/modernize/CMakeLists.txt   |  1 +
 .../modernize/ModernizeTidyModule.cpp |  3 +
 .../modernize/UseSpanFirstLastCheck.cpp   | 97 +++
 .../modernize/UseSpanFirstLastCheck.h | 40 
 clang-tools-extra/docs/ReleaseNotes.rst   |  4 +
 .../checks/modernize/use-span-first-last.rst  | 19 
 .../modernize-subspan-conversion.cpp  | 50 ++
 7 files changed, 214 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-span-first-last.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/modernize-subspan-conversion.cpp

diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index c919d49b42873a..47dd12a2640b6c 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -49,6 +49,7 @@ add_clang_library(clangTidyModernizeModule STATIC
   UseTransparentFunctorsCheck.cpp
   UseUncaughtExceptionsCheck.cpp
   UseUsingCheck.cpp
+  UseSpanFirstLastCheck.cpp
 
   LINK_LIBS
   clangTidy
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index 18607593320635..6fc5de5aad20b7 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -42,6 +42,7 @@
 #include "UseNullptrCheck.h"
 #include "UseOverrideCheck.h"
 #include "UseRangesCheck.h"
+#include "UseSpanFirstLastCheck.h"
 #include "UseStartsEndsWithCheck.h"
 #include "UseStdFormatCheck.h"
 #include "UseStdNumbersCheck.h"
@@ -122,6 +123,8 @@ class ModernizeModule : public ClangTidyModule {
 CheckFactories.registerCheck(
 "modernize-use-uncaught-exceptions");
 CheckFactories.registerCheck("modernize-use-using");
+
CheckFactories.registerCheck("modernize-use-span-first-last");
+
   }
 };
 
diff --git a/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
new file mode 100644
index 00..f57571f2aa7c86
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
@@ -0,0 +1,97 @@
+//===--- 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 "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+void UseSpanFirstLastCheck::registerMatchers(MatchFinder *Finder) {
+  // Match span::subspan calls
+  const auto HasSpanType = hasType(hasUnqualifiedDesugaredType(
+  recordType(hasDeclaration(classTemplateSpecializationDecl(
+  hasName("::std::span"));
+
+  Finder->addMatcher(
+  cxxMemberCallExpr(
+  callee(memberExpr(hasDeclaration(
+  cxxMethodDecl(hasName("subspan"),
+  on(expr(HasSpanType)))
+  .bind("subspan"),
+  this);
+}
+
+void UseSpanFirstLastCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs("subspan");
+  if (!Call)
+return;
+
+  handleSubspanCall(Result, Call);
+}
+
+void UseSpanFirstLastCheck::handleSubspanCall(
+const MatchFinder::MatchResult &Result, const CXXMemberCallExpr *Call) {
+  // Get arguments
+  unsigned NumArgs = Call->getNumArgs();
+  if (NumArgs == 0 || NumArgs > 2)
+return;
+
+  const Expr *Offset = Call->getArg(0);
+  const Expr *Count = NumArgs > 1 ? Call->getArg(1) : nullptr;
+  auto &Context = *Result.Context;
+  bool IsZeroOffset = false;
+
+  // Check if offset is zero through any implicit casts
+  const Expr* OffsetE = Offset->IgnoreImpCasts();
+  if (const auto *IL = dyn_cast(OffsetE)) {
+IsZeroOffset = IL->getValue() == 0;
+  }
+
+  // Build replacement text
+  std::string Replacement;
+  if (IsZeroOffset && Count) {
+   

[clang-tools-extra] [clang-tidy] Add modernize-use-span-first-last check (PR #118074)

2024-11-29 Thread Carlos Galvez via cfe-commits

carlosgalvezp wrote:

> not sure if this is a readability or a modernize check 

`readability`. `modernize` is for using new features from newer standards.

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


[clang-tools-extra] [clang-tidy] Add modernize-use-span-first-last check (PR #118074)

2024-11-29 Thread Carlos Galvez via cfe-commits


@@ -0,0 +1,40 @@
+//===--- UseSpanFirstLastCheck.h - 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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USESPANFIRSTLASTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USESPANFIRSTLASTCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::modernize {
+
+/// Converts std::span::subspan() calls to the more modern first()/last()
+/// methods where applicable.
+///
+/// For example:
+/// \code
+///   std::span s = ...;
+///   auto sub = s.subspan(0, n);// ->  auto sub = s.first(n);
+///   auto sub2 = s.subspan(n);  // ->  auto sub2 = s.last(s.size() - n);
+/// \endcode
+class UseSpanFirstLastCheck : public ClangTidyCheck {
+public:
+  UseSpanFirstLastCheck(StringRef Name, ClangTidyContext *Context)

carlosgalvezp wrote:

Limit this check to C++20

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


[clang-tools-extra] [clang-tidy] Add modernize-use-span-first-last check (PR #118074)

2024-11-29 Thread Carlos Galvez via cfe-commits

carlosgalvezp wrote:

```cpp
auto sub2 = s.subspan(n);// transforms to: auto sub2 = s.last(s.size() 
- n);
```

IMHO the transformed code is less readable. It would be more useful to do the 
opposite transformation, maybe that's what you intended?

```cpp
auto sub2 = s.subspan(s.size() - n);// transforms to: auto sub2 = 
s.last(n);
```

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


[clang-tools-extra] [clang-tidy] Add modernize-use-span-first-last check (PR #118074)

2024-11-29 Thread Helmut Januschka via cfe-commits

https://github.com/hjanuschka updated 
https://github.com/llvm/llvm-project/pull/118074

>From cb748c34d35b8c0c9ca93a67b111dcf5d7665b34 Mon Sep 17 00:00:00 2001
From: Helmut Januschka 
Date: Fri, 29 Nov 2024 10:17:49 +0100
Subject: [PATCH 1/3] [clang-tidy] Add modernize-use-span-first-last check

Add new check that modernizes std::span::subspan() calls to use the more
expressive first() and last() member functions where applicable.
---
 .../clang-tidy/modernize/CMakeLists.txt   |  1 +
 .../modernize/ModernizeTidyModule.cpp |  3 +
 .../modernize/UseSpanFirstLastCheck.cpp   | 97 +++
 .../modernize/UseSpanFirstLastCheck.h | 40 
 clang-tools-extra/docs/ReleaseNotes.rst   |  4 +
 .../checks/modernize/use-span-first-last.rst  | 19 
 .../modernize-subspan-conversion.cpp  | 50 ++
 7 files changed, 214 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-span-first-last.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/modernize-subspan-conversion.cpp

diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index c919d49b42873a..47dd12a2640b6c 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -49,6 +49,7 @@ add_clang_library(clangTidyModernizeModule STATIC
   UseTransparentFunctorsCheck.cpp
   UseUncaughtExceptionsCheck.cpp
   UseUsingCheck.cpp
+  UseSpanFirstLastCheck.cpp
 
   LINK_LIBS
   clangTidy
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index 18607593320635..6fc5de5aad20b7 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -42,6 +42,7 @@
 #include "UseNullptrCheck.h"
 #include "UseOverrideCheck.h"
 #include "UseRangesCheck.h"
+#include "UseSpanFirstLastCheck.h"
 #include "UseStartsEndsWithCheck.h"
 #include "UseStdFormatCheck.h"
 #include "UseStdNumbersCheck.h"
@@ -122,6 +123,8 @@ class ModernizeModule : public ClangTidyModule {
 CheckFactories.registerCheck(
 "modernize-use-uncaught-exceptions");
 CheckFactories.registerCheck("modernize-use-using");
+
CheckFactories.registerCheck("modernize-use-span-first-last");
+
   }
 };
 
diff --git a/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
new file mode 100644
index 00..f57571f2aa7c86
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
@@ -0,0 +1,97 @@
+//===--- 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 "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+void UseSpanFirstLastCheck::registerMatchers(MatchFinder *Finder) {
+  // Match span::subspan calls
+  const auto HasSpanType = hasType(hasUnqualifiedDesugaredType(
+  recordType(hasDeclaration(classTemplateSpecializationDecl(
+  hasName("::std::span"));
+
+  Finder->addMatcher(
+  cxxMemberCallExpr(
+  callee(memberExpr(hasDeclaration(
+  cxxMethodDecl(hasName("subspan"),
+  on(expr(HasSpanType)))
+  .bind("subspan"),
+  this);
+}
+
+void UseSpanFirstLastCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs("subspan");
+  if (!Call)
+return;
+
+  handleSubspanCall(Result, Call);
+}
+
+void UseSpanFirstLastCheck::handleSubspanCall(
+const MatchFinder::MatchResult &Result, const CXXMemberCallExpr *Call) {
+  // Get arguments
+  unsigned NumArgs = Call->getNumArgs();
+  if (NumArgs == 0 || NumArgs > 2)
+return;
+
+  const Expr *Offset = Call->getArg(0);
+  const Expr *Count = NumArgs > 1 ? Call->getArg(1) : nullptr;
+  auto &Context = *Result.Context;
+  bool IsZeroOffset = false;
+
+  // Check if offset is zero through any implicit casts
+  const Expr* OffsetE = Offset->IgnoreImpCasts();
+  if (const auto *IL = dyn_cast(OffsetE)) {
+IsZeroOffset = IL->getValue() == 0;
+  }
+
+  // Build replacement text
+  std::string Replacement;
+  if (IsZeroOffset && Count) {
+   

[clang-tools-extra] [clang-tidy] Add modernize-use-span-first-last check (PR #118074)

2024-11-29 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff 056153f36eca184f81969f5cd5c8cd967c935f96 
ec5a6b0ceb0fbbf03ea36a38fb627b25ab4e62de --extensions h,cpp -- 
clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp 
clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.h 
clang-tools-extra/test/clang-tidy/checkers/modernize/modernize-subspan-conversion.cpp
 clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index 6fc5de5aad..d1778640bb 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -123,8 +123,8 @@ public:
 CheckFactories.registerCheck(
 "modernize-use-uncaught-exceptions");
 CheckFactories.registerCheck("modernize-use-using");
-
CheckFactories.registerCheck("modernize-use-span-first-last");
-
+CheckFactories.registerCheck(
+"modernize-use-span-first-last");
   }
 };
 

``




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


[clang-tools-extra] [clang-tidy] Add modernize-use-span-first-last check (PR #118074)

2024-11-29 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-tidy

Author: Helmut Januschka (hjanuschka)


Changes

Add new clang-tidy check that suggests using std::span's more expressive 
first() and last() member functions instead of equivalent subspan() calls.

The check modernizes code by replacing:
- subspan(0, n) -> first(n)
- subspan(n) -> last(size() - n)

These dedicated methods were added to the standard to provide clearer 
alternatives to common subspan operations. They improve readability by better 
expressing intent and are less error-prone by eliminating manual offset 
calculations.

For example:
```cpp
std::span s = ...;
auto sub1 = s.subspan(0, n); // transforms to: auto sub1 = s.first(n);
auto sub2 = s.subspan(n);// transforms to: auto sub2 = s.last(s.size() 
- n);
auto sub3 = s.subspan(1, n); // not transformed, no direct equivalent
```


not sure if this is a readability or a modernize check ❓ 

---
Full diff: https://github.com/llvm/llvm-project/pull/118074.diff


7 Files Affected:

- (modified) clang-tools-extra/clang-tidy/modernize/CMakeLists.txt (+1) 
- (modified) clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
(+3) 
- (added) clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp 
(+98) 
- (added) clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.h (+40) 
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+4) 
- (added) 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-span-first-last.rst 
(+19) 
- (added) 
clang-tools-extra/test/clang-tidy/checkers/modernize/modernize-subspan-conversion.cpp
 (+50) 


``diff
diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index c919d49b42873a..47dd12a2640b6c 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -49,6 +49,7 @@ add_clang_library(clangTidyModernizeModule STATIC
   UseTransparentFunctorsCheck.cpp
   UseUncaughtExceptionsCheck.cpp
   UseUsingCheck.cpp
+  UseSpanFirstLastCheck.cpp
 
   LINK_LIBS
   clangTidy
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index 18607593320635..6fc5de5aad20b7 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -42,6 +42,7 @@
 #include "UseNullptrCheck.h"
 #include "UseOverrideCheck.h"
 #include "UseRangesCheck.h"
+#include "UseSpanFirstLastCheck.h"
 #include "UseStartsEndsWithCheck.h"
 #include "UseStdFormatCheck.h"
 #include "UseStdNumbersCheck.h"
@@ -122,6 +123,8 @@ class ModernizeModule : public ClangTidyModule {
 CheckFactories.registerCheck(
 "modernize-use-uncaught-exceptions");
 CheckFactories.registerCheck("modernize-use-using");
+
CheckFactories.registerCheck("modernize-use-span-first-last");
+
   }
 };
 
diff --git a/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
new file mode 100644
index 00..6cf01386b0c3fb
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
@@ -0,0 +1,98 @@
+//===--- 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 "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+void UseSpanFirstLastCheck::registerMatchers(MatchFinder *Finder) {
+  // Match span::subspan calls
+  const auto HasSpanType =
+  hasType(hasUnqualifiedDesugaredType(recordType(hasDeclaration(
+  classTemplateSpecializationDecl(hasName("::std::span"));
+
+  Finder->addMatcher(cxxMemberCallExpr(callee(memberExpr(hasDeclaration(
+   
cxxMethodDecl(hasName("subspan"),
+   on(expr(HasSpanType)))
+ .bind("subspan"),
+ this);
+}
+
+void UseSpanFirstLastCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs("subspan");
+  if (!Call)
+return;
+
+  handleSubspanCall(Result, Call);
+}
+
+void UseSpanFirstLastCheck::handleSubspanCall(
+const MatchFinder::MatchResult &Result, const CXXMemberCallExpr *Call) {
+  // Get arguments
+  unsigned NumArgs = Call->getNumArgs();
+  if (NumArgs == 0 || NumArgs > 2)
+return;
+
+  const Expr *Offset = Call->getArg(0);
+  c

[clang-tools-extra] [clang-tidy] Add modernize-use-span-first-last check (PR #118074)

2024-11-29 Thread Helmut Januschka via cfe-commits

https://github.com/hjanuschka created 
https://github.com/llvm/llvm-project/pull/118074

Add new clang-tidy check that suggests using std::span's more expressive 
first() and last() member functions instead of equivalent subspan() calls.

The check modernizes code by replacing:
- subspan(0, n) -> first(n)
- subspan(n) -> last(size() - n)

These dedicated methods were added to the standard to provide clearer 
alternatives to common subspan operations. They improve readability by better 
expressing intent and are less error-prone by eliminating manual offset 
calculations.

For example:
```cpp
std::span s = ...;
auto sub1 = s.subspan(0, n); // transforms to: auto sub1 = s.first(n);
auto sub2 = s.subspan(n);// transforms to: auto sub2 = s.last(s.size() 
- n);
auto sub3 = s.subspan(1, n); // not transformed, no direct equivalent
```


not sure if this is a readability or a modernize check ❓ 

>From cb748c34d35b8c0c9ca93a67b111dcf5d7665b34 Mon Sep 17 00:00:00 2001
From: Helmut Januschka 
Date: Fri, 29 Nov 2024 10:17:49 +0100
Subject: [PATCH 1/2] [clang-tidy] Add modernize-use-span-first-last check

Add new check that modernizes std::span::subspan() calls to use the more
expressive first() and last() member functions where applicable.
---
 .../clang-tidy/modernize/CMakeLists.txt   |  1 +
 .../modernize/ModernizeTidyModule.cpp |  3 +
 .../modernize/UseSpanFirstLastCheck.cpp   | 97 +++
 .../modernize/UseSpanFirstLastCheck.h | 40 
 clang-tools-extra/docs/ReleaseNotes.rst   |  4 +
 .../checks/modernize/use-span-first-last.rst  | 19 
 .../modernize-subspan-conversion.cpp  | 50 ++
 7 files changed, 214 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-span-first-last.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/modernize-subspan-conversion.cpp

diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index c919d49b42873a..47dd12a2640b6c 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -49,6 +49,7 @@ add_clang_library(clangTidyModernizeModule STATIC
   UseTransparentFunctorsCheck.cpp
   UseUncaughtExceptionsCheck.cpp
   UseUsingCheck.cpp
+  UseSpanFirstLastCheck.cpp
 
   LINK_LIBS
   clangTidy
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index 18607593320635..6fc5de5aad20b7 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -42,6 +42,7 @@
 #include "UseNullptrCheck.h"
 #include "UseOverrideCheck.h"
 #include "UseRangesCheck.h"
+#include "UseSpanFirstLastCheck.h"
 #include "UseStartsEndsWithCheck.h"
 #include "UseStdFormatCheck.h"
 #include "UseStdNumbersCheck.h"
@@ -122,6 +123,8 @@ class ModernizeModule : public ClangTidyModule {
 CheckFactories.registerCheck(
 "modernize-use-uncaught-exceptions");
 CheckFactories.registerCheck("modernize-use-using");
+
CheckFactories.registerCheck("modernize-use-span-first-last");
+
   }
 };
 
diff --git a/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
new file mode 100644
index 00..f57571f2aa7c86
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseSpanFirstLastCheck.cpp
@@ -0,0 +1,97 @@
+//===--- 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 "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+void UseSpanFirstLastCheck::registerMatchers(MatchFinder *Finder) {
+  // Match span::subspan calls
+  const auto HasSpanType = hasType(hasUnqualifiedDesugaredType(
+  recordType(hasDeclaration(classTemplateSpecializationDecl(
+  hasName("::std::span"));
+
+  Finder->addMatcher(
+  cxxMemberCallExpr(
+  callee(memberExpr(hasDeclaration(
+  cxxMethodDecl(hasName("subspan"),
+  on(expr(HasSpanType)))
+  .bind("subspan"),
+  this);
+}
+
+void UseSpanFirstLastCheck::check(const MatchFinder::MatchResult &Result) {
+  c