[clang-tools-extra] 2aec866 - [clang-tidy][abseil-string-find-startswith] Add string_view to default string-like classes (#72283)

Piotr Zegar via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 14 14:25:54 PST 2023


Author: Nicolas van Kempen
Date: 2023-11-14T22:25:23Z
New Revision: 2aec86683c074a19b9c4d42d0b2b33d4f999ba00

URL: https://github.com/llvm/llvm-project/commit/2aec86683c074a19b9c4d42d0b2b33d4f999ba00
DIFF: https://github.com/llvm/llvm-project/commit/2aec86683c074a19b9c4d42d0b2b33d4f999ba00.diff

LOG: [clang-tidy][abseil-string-find-startswith] Add string_view to default string-like classes (#72283)

As per title. A small improvement to this check, `string_view` should
work out of the box.

Added: 
    

Modified: 
    clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
    clang-tools-extra/docs/ReleaseNotes.rst
    clang-tools-extra/docs/clang-tidy/checks/abseil/string-find-startswith.rst
    clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
    clang-tools-extra/test/clang-tidy/checkers/abseil/string-find-startswith.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp b/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
index b36144d1912fce0..221e924c10f621d 100644
--- a/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
+++ b/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
@@ -19,11 +19,14 @@ using namespace clang::ast_matchers;
 
 namespace clang::tidy::abseil {
 
+const auto DefaultStringLikeClasses =
+    "::std::basic_string;::std::basic_string_view";
+
 StringFindStartswithCheck::StringFindStartswithCheck(StringRef Name,
                                                      ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
       StringLikeClasses(utils::options::parseStringList(
-          Options.get("StringLikeClasses", "::std::basic_string"))),
+          Options.get("StringLikeClasses", DefaultStringLikeClasses))),
       IncludeInserter(Options.getLocalOrGlobal("IncludeStyle",
                                                utils::IncludeSorter::IS_LLVM),
                       areDiagsSelfContained()),

diff  --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index a24e3a735d2d2d5..caf45696707206c 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -208,6 +208,10 @@ New check aliases
 Changes in existing checks
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+- Improved :doc:`abseil-string-find-startswith
+  <clang-tidy/checks/abseil/string-find-startswith>` check to also consider
+  ``std::basic_string_view`` in addition to ``std::basic_string`` by default.
+
 - Improved :doc:`bugprone-dangling-handle
   <clang-tidy/checks/bugprone/dangling-handle>` check to support functional
   casting during type conversions at variable initialization, now with improved

diff  --git a/clang-tools-extra/docs/clang-tidy/checks/abseil/string-find-startswith.rst b/clang-tools-extra/docs/clang-tidy/checks/abseil/string-find-startswith.rst
index 8224c37a087b8bc..c82c38772a5c9a8 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/abseil/string-find-startswith.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/abseil/string-find-startswith.rst
@@ -3,9 +3,10 @@
 abseil-string-find-startswith
 =============================
 
-Checks whether a ``std::string::find()`` or ``std::string::rfind()`` result is
-compared with 0, and suggests replacing with ``absl::StartsWith()``. This is
-both a readability and performance issue.
+Checks whether a ``std::string::find()`` or ``std::string::rfind()`` (and
+corresponding ``std::string_view`` methods) result is compared with 0, and
+suggests replacing with ``absl::StartsWith()``. This is both a readability and
+performance issue.
 
 .. code-block:: c++
 
@@ -28,9 +29,9 @@ Options
 
 .. option:: StringLikeClasses
 
-   Semicolon-separated list of names of string-like classes. By default only
-   ``std::basic_string`` is considered. The list of methods to considered is
-   fixed.
+   Semicolon-separated list of names of string-like classes. By default both
+   ``std::basic_string`` and ``std::basic_string_view`` are considered. The list
+   of methods to be considered is fixed.
 
 .. option:: IncludeStyle
 

diff  --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
index 6f569655e6762a9..d0aac7b78ec939b 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
+++ b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string
@@ -43,6 +43,11 @@ struct basic_string {
   size_type find(const C* s, size_type pos = 0) const;
   size_type find(const C* s, size_type pos, size_type n) const;
 
+  size_type rfind(const _Type& str, size_type pos = npos) const;
+  size_type rfind(const C* s, size_type pos, size_type count) const;
+  size_type rfind(const C* s, size_type pos = npos) const;
+  size_type rfind(C ch, size_type pos = npos) const;
+
   _Type& insert(size_type pos, const _Type& str);
   _Type& insert(size_type pos, const C* s);
   _Type& insert(size_type pos, const C* s, size_type n);
@@ -54,6 +59,8 @@ struct basic_string {
   _Type& operator+=(const C* s);
   _Type& operator=(const _Type& str);
   _Type& operator=(const C* s);
+
+  static constexpr size_t npos = -1;
 };
 
 typedef basic_string<char> string;
@@ -63,8 +70,23 @@ typedef basic_string<char32> u32string;
 
 template <typename C, typename T = char_traits<C>>
 struct basic_string_view {
+  typedef size_t size_type;
+  typedef basic_string_view<C, T> _Type;
+
   const C *str;
   constexpr basic_string_view(const C* s) : str(s) {}
+
+  size_type find(_Type v, size_type pos = 0) const;
+  size_type find(C ch, size_type pos = 0) const;
+  size_type find(const C* s, size_type pos, size_type count) const;
+  size_type find(const C* s, size_type pos = 0) const;
+
+  size_type rfind(_Type v, size_type pos = npos) const;
+  size_type rfind(C ch, size_type pos = npos) const;
+  size_type rfind(const C* s, size_type pos, size_type count) const;
+  size_type rfind(const C* s, size_type pos = npos) const;
+
+  static constexpr size_t npos = -1;
 };
 typedef basic_string_view<char> string_view;
 typedef basic_string_view<wchar_t> wstring_view;

diff  --git a/clang-tools-extra/test/clang-tidy/checkers/abseil/string-find-startswith.cpp b/clang-tools-extra/test/clang-tidy/checkers/abseil/string-find-startswith.cpp
index e51568077eda151..417598790bc007f 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/abseil/string-find-startswith.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/abseil/string-find-startswith.cpp
@@ -1,27 +1,14 @@
 // RUN: %check_clang_tidy %s abseil-string-find-startswith %t -- \
-// RUN:   -config="{CheckOptions: {abseil-string-find-startswith.StringLikeClasses: '::std::basic_string;::basic_string'}}"
+// RUN:   -config="{CheckOptions: \
+// RUN:     {abseil-string-find-startswith.StringLikeClasses: \
+// RUN:       '::std::basic_string;::std::basic_string_view;::basic_string'}}" \
+// RUN:   -- -isystem %clang_tidy_headers
+
+#include <string>
 
 using size_t = decltype(sizeof(int));
 
 namespace std {
-template <typename T> class allocator {};
-template <typename T> class char_traits {};
-template <typename C, typename T = std::char_traits<C>,
-          typename A = std::allocator<C>>
-struct basic_string {
-  basic_string();
-  basic_string(const basic_string &);
-  basic_string(const C *, const A &a = A());
-  ~basic_string();
-  int find(basic_string<C> s, int pos = 0);
-  int find(const char *s, int pos = 0);
-  int rfind(basic_string<C> s, int pos = npos);
-  int rfind(const char *s, int pos = npos);
-  static constexpr size_t npos = -1;
-};
-typedef basic_string<char> string;
-typedef basic_string<wchar_t> wstring;
-
 struct cxx_string {
   int find(const char *s, int pos = 0);
   int rfind(const char *s, int pos = npos);
@@ -39,7 +26,7 @@ std::string bar();
 
 #define A_MACRO(x, y) ((x) == (y))
 
-void tests(std::string s, global_string s2) {
+void tests(std::string s, global_string s2, std::string_view sv) {
   s.find("a") == 0;
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith instead of find() == 0 [abseil-string-find-startswith]
   // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, "a");{{$}}
@@ -96,6 +83,14 @@ void tests(std::string s, global_string s2) {
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
   // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s2, "a");{{$}}
 
+  sv.find("a") == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(sv, "a");{{$}}
+
+  sv.rfind("a", 0) != 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(sv, "a");{{$}}
+
   // expressions that don't trigger the check are here.
   A_MACRO(s.find("a"), 0);
   A_MACRO(s.rfind("a", 0), 0);


        


More information about the cfe-commits mailing list