[PATCH] D76496: [clang-tidy] add support to 3-arg find() in StringFindStartswith

2020-08-27 Thread Niko Weh via Phabricator via cfe-commits
niko updated this revision to Diff 288378.
niko added a comment.

Rebasing to HEAD


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D76496/new/

https://reviews.llvm.org/D76496

Files:
  clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
@@ -13,6 +13,7 @@
   ~basic_string();
   int find(basic_string s, int pos = 0);
   int find(const char *s, int pos = 0);
+  int find(const char *s, int pos, int n);
 };
 typedef basic_string string;
 typedef basic_string wstring;
@@ -41,6 +42,10 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
   // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
 
+  s.find(s, 0) == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
+
   s.find("aaa") != 0;
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
   // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "aaa");{{$}}
@@ -61,9 +66,14 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
   // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s2, "a");{{$}}
 
+  s.find("a", 0, 1) == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, absl::string_view("a", 
1));{{$}}
+
   // expressions that don't trigger the check are here.
   A_MACRO(s.find("a"), 0);
   s.find("a", 1) == 0;
   s.find("a", 1) == 1;
   s.find("a") == 1;
+  s.find("a", 1, 1) == 0;
 }
Index: clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
===
--- clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
+++ clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
@@ -40,12 +40,13 @@
 
   auto StringFind = cxxMemberCallExpr(
   // .find()-call on a string...
-  callee(cxxMethodDecl(hasName("find"))),
-  on(hasType(StringType)),
+  callee(cxxMethodDecl(hasName("find"))), on(hasType(StringType)),
   // ... with some search expression ...
   hasArgument(0, expr().bind("needle")),
   // ... and either "0" as second argument or the default argument (also 
0).
-  anyOf(hasArgument(1, ZeroLiteral), hasArgument(1, cxxDefaultArgExpr(;
+  anyOf(hasArgument(1, ZeroLiteral), hasArgument(1, cxxDefaultArgExpr())),
+  // ... and optionally a third argument for 'search string length'.
+  optionally(hasArgument(2, expr().bind("needle_length";
 
   Finder->addMatcher(
   // Match [=!]= with a zero on one side and a string.find on the other.
@@ -69,6 +70,7 @@
   const Expr *Haystack = Result.Nodes.getNodeAs("findexpr")
  ->getImplicitObjectArgument();
   assert(Haystack != nullptr);
+  const auto *NeedleLength = Result.Nodes.getNodeAs("needle_length");
 
   if (ComparisonExpr->getBeginLoc().isMacroID())
 return;
@@ -82,6 +84,20 @@
   CharSourceRange::getTokenRange(Haystack->getSourceRange()), Source,
   Context.getLangOpts());
 
+  // If there is a third argument (search string length), create an
+  // absl::string_view(search string, search string length) and use that
+  // as the search string in StartsWith.
+  std::string NewNeedleStr;
+  if (NeedleLength != nullptr) {
+const StringRef NeedleLengthCode = Lexer::getSourceText(
+CharSourceRange::getTokenRange(NeedleLength->getSourceRange()), Source,
+Context.getLangOpts());
+NewNeedleStr = std::string("absl::string_view(") + NeedleExprCode.str() +
+   ", " + NeedleLengthCode.str() + ")";
+  } else {
+NewNeedleStr = NeedleExprCode.str();
+  }
+
   // Create the StartsWith string, negating if comparison was "!=".
   bool Neg = ComparisonExpr->getOpcodeStr() == "!=";
   StringRef StartswithStr;
@@ -100,7 +116,7 @@
 
   Diagnostic << FixItHint::CreateReplacement(
   ComparisonExpr->getSourceRange(),
-  (StartswithStr + "(" + HaystackExprCode + ", " + NeedleExprCode + ")")
+  (StartswithStr + "(" + HaystackExprCode + ", " + NewNeedleStr + ")")
   .str());
 
   // Create a preprocessor #include FixIt hint (CreateIncludeInsertion checks


Index: clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
@@ -13,6 +13,7 @@
   ~basic_string();
   int find(basic_string s, int pos =

[PATCH] D76496: [clang-tidy] add support to 3-arg find() in StringFindStartswith

2020-05-01 Thread Niko Weh via Phabricator via cfe-commits
niko added a comment.

In D76496#1976713 , @njames93 wrote:

> In D76496#1949851 , @niko wrote:
>
> > Correct me if I'm wrong, but that seems to be in violation of IWYU? Maybe 
> > I'm misreading this, or is the idea that higher-lever tooling (e.g. IWYU 
> > fixer) is supposed to address that?
>
>
> It is but it sort of gets a pass as the absl/strings/match.h has to include 
> it. 
>  Similar to how if you `#include `, you wouldn't then `#include 
> ` so you could construct a `std::vector` using a 
> `std::initializer_list`.


Makes sense. Thanks!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D76496/new/

https://reviews.llvm.org/D76496



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D76496: [clang-tidy] add support to 3-arg find() in StringFindStartswith

2020-05-01 Thread Niko Weh via Phabricator via cfe-commits
niko updated this revision to Diff 261512.
niko added a comment.

[clang-tidy] add 3-arg support to StringFindStartswith via string_view


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D76496/new/

https://reviews.llvm.org/D76496

Files:
  clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
@@ -13,6 +13,7 @@
   ~basic_string();
   int find(basic_string s, int pos = 0);
   int find(const char *s, int pos = 0);
+  int find(const char *s, int pos, int n);
 };
 typedef basic_string string;
 typedef basic_string wstring;
@@ -41,6 +42,10 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
   // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
 
+  s.find(s, 0) == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
+
   s.find("aaa") != 0;
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
   // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "aaa");{{$}}
@@ -61,9 +66,14 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
   // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s2, "a");{{$}}
 
+  s.find("a", 0, 1) == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, absl::string_view("a", 
1));{{$}}
+
   // expressions that don't trigger the check are here.
   A_MACRO(s.find("a"), 0);
   s.find("a", 1) == 0;
   s.find("a", 1) == 1;
   s.find("a") == 1;
+  s.find("a", 1, 1) == 0;
 }
Index: clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
===
--- clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
+++ clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
@@ -40,12 +40,13 @@
 
   auto StringFind = cxxMemberCallExpr(
   // .find()-call on a string...
-  callee(cxxMethodDecl(hasName("find"))),
-  on(hasType(StringType)),
+  callee(cxxMethodDecl(hasName("find"))), on(hasType(StringType)),
   // ... with some search expression ...
   hasArgument(0, expr().bind("needle")),
   // ... and either "0" as second argument or the default argument (also 
0).
-  anyOf(hasArgument(1, ZeroLiteral), hasArgument(1, cxxDefaultArgExpr(;
+  anyOf(hasArgument(1, ZeroLiteral), hasArgument(1, cxxDefaultArgExpr())),
+  // ... and optionally a third argument for 'search string length'.
+  optionally(hasArgument(2, expr().bind("needle_length";
 
   Finder->addMatcher(
   // Match [=!]= with a zero on one side and a string.find on the other.
@@ -69,6 +70,7 @@
   const Expr *Haystack = Result.Nodes.getNodeAs("findexpr")
  ->getImplicitObjectArgument();
   assert(Haystack != nullptr);
+  const auto *NeedleLength = Result.Nodes.getNodeAs("needle_length");
 
   if (ComparisonExpr->getBeginLoc().isMacroID())
 return;
@@ -82,6 +84,21 @@
   CharSourceRange::getTokenRange(Haystack->getSourceRange()), Source,
   Context.getLangOpts());
 
+  // If there is a third argument (search string length), create an
+  // absl::string_view(search string, search string length) and use that
+  // as the search string in StartsWith.
+  std::string NewNeedleStr;
+  if (NeedleLength != nullptr) {
+const StringRef NeedleLengthCode = Lexer::getSourceText(
+CharSourceRange::getTokenRange(NeedleLength->getSourceRange()), Source,
+Context.getLangOpts());
+NewNeedleStr = std::string("absl::string_view(") +
+NeedleExprCode.str() + ", " + NeedleLengthCode.str() +
+")";
+  } else {
+NewNeedleStr = NeedleExprCode.str();
+  }
+
   // Create the StartsWith string, negating if comparison was "!=".
   bool Neg = ComparisonExpr->getOpcodeStr() == "!=";
   StringRef StartswithStr;
@@ -100,7 +117,7 @@
 
   Diagnostic << FixItHint::CreateReplacement(
   ComparisonExpr->getSourceRange(),
-  (StartswithStr + "(" + HaystackExprCode + ", " + NeedleExprCode + ")")
+  (StartswithStr + "(" + HaystackExprCode + ", " + NewNeedleStr + ")")
   .str());
 
   // Create a preprocessor #include FixIt hint (CreateIncludeInsertion checks


Index: clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-starts

[PATCH] D76496: [clang-tidy] StringFindStartswith should ignore 3-arg find()

2020-03-30 Thread Niko Weh via Phabricator via cfe-commits
niko added a comment.

In D76496#1947127 , @njames93 wrote:

> In D76496#1947059 , @niko wrote:
>
> > In D76496#1935127 , @njames93 
> > wrote:
> >
> > > I'm not hugely familiar with the abseil library, but from what I can see 
> > > `absl::StartsWith` takes `absl::string_view` as args. Therefore surely it 
> > > makes sense to handle the 3rd arg for `str::find` by explicitly 
> > > constructing the `absl::string_view` from the pointer and size.
> >
> >
> > I am mainly worried that the 3-arg find is rarely used, and using 
> > absl::string_view requires another option to be specified for the header 
> > file. If you think that's still a good tradeoff i'll change it to construct 
> > a string_view.
>
>
> The `absl/strings/match` header includes the `absl/strings/string_view` 
> header so you wouldn't need to include another header file. Well that's as 
> long as the user hasn't done something funky with header files, but arguably 
> the shouldn't be using Fix-Its if they have done something like that.


Correct me if I'm wrong, but that seems to be in violation of IWYU? Maybe I'm 
misreading this, or is the idea that higher-lever tooling (e.g. IWYU fixer) is 
supposed to address that?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D76496/new/

https://reviews.llvm.org/D76496



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D76496: [clang-tidy] StringFindStartswith should ignore 3-arg find()

2020-03-27 Thread Niko Weh via Phabricator via cfe-commits
niko added a comment.

In D76496#1935127 , @njames93 wrote:

> I'm not hugely familiar with the abseil library, but from what I can see 
> `absl::StartsWith` takes `absl::string_view` as args. Therefore surely it 
> makes sense to handle the 3rd arg for `str::find` by explicitly constructing 
> the `absl::string_view` from the pointer and size.


I am mainly worried that the 3-arg find is rarely used, and using 
absl::string_view requires another option to be specified for the header file. 
If you think that's still a good tradeoff i'll change it to construct a 
string_view.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D76496/new/

https://reviews.llvm.org/D76496



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D76496: [clang-tidy] StringFindStartswith should ignore 3-arg find()

2020-03-20 Thread Niko Weh via Phabricator via cfe-commits
niko created this revision.
niko added a reviewer: hokein.
Herald added subscribers: cfe-commits, xazax.hun.
Herald added a project: clang.

string::find() has a 3-argument version, with the third argument
specifying the 'length of sequence of characters to match' (for a const
char* 1st argument, typically used when it is not null-terminated).

This case seems rare enough that I think the best way is to just ignore
it. I believe the second-best alternative would be to pull in
string_view.h, and suggest constructing string_view from the first and
third argument - this seems like overkill but i'm happy to be convinced
otherwise.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D76496

Files:
  clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
@@ -13,6 +13,7 @@
   ~basic_string();
   int find(basic_string s, int pos = 0);
   int find(const char *s, int pos = 0);
+  int find(const char *s, int pos, int n);
 };
 typedef basic_string string;
 typedef basic_string wstring;
@@ -41,6 +42,10 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
   // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
 
+  s.find(s, 0) == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
+
   s.find("aaa") != 0;
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
   // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "aaa");{{$}}
@@ -66,4 +71,5 @@
   s.find("a", 1) == 0;
   s.find("a", 1) == 1;
   s.find("a") == 1;
+  s.find("a", 0, 1) == 0;
 }
Index: clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
===
--- clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
+++ clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
@@ -40,8 +40,9 @@
 
   auto StringFind = cxxMemberCallExpr(
   // .find()-call on a string...
-  callee(cxxMethodDecl(hasName("find"))),
-  on(hasType(StringType)),
+  callee(cxxMethodDecl(hasName("find"))), on(hasType(StringType)),
+  // ... with 1 or two arguments (but not three),
+  anyOf(argumentCountIs(1), argumentCountIs(2)),
   // ... with some search expression ...
   hasArgument(0, expr().bind("needle")),
   // ... and either "0" as second argument or the default argument (also 
0).


Index: clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/abseil-string-find-startswith.cpp
@@ -13,6 +13,7 @@
   ~basic_string();
   int find(basic_string s, int pos = 0);
   int find(const char *s, int pos = 0);
+  int find(const char *s, int pos, int n);
 };
 typedef basic_string string;
 typedef basic_string wstring;
@@ -41,6 +42,10 @@
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
   // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
 
+  s.find(s, 0) == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
+
   s.find("aaa") != 0;
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
   // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "aaa");{{$}}
@@ -66,4 +71,5 @@
   s.find("a", 1) == 0;
   s.find("a", 1) == 1;
   s.find("a") == 1;
+  s.find("a", 0, 1) == 0;
 }
Index: clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
===
--- clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
+++ clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp
@@ -40,8 +40,9 @@
 
   auto StringFind = cxxMemberCallExpr(
   // .find()-call on a string...
-  callee(cxxMethodDecl(hasName("find"))),
-  on(hasType(StringType)),
+  callee(cxxMethodDecl(hasName("find"))), on(hasType(StringType)),
+  // ... with 1 or two arguments (but not three),
+  anyOf(argumentCountIs(1), argumentCountIs(2)),
   // ... with some search expression ...
   hasArgument(0, expr().bind("needle")),
   // ... and either "0" as second argument or the default argument (also 0).
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D43847: [clang-tidy] Add check: replace string::find(...) == 0 with absl::StartsWith

2018-03-07 Thread Niko Weh via Phabricator via cfe-commits
niko added a comment.

If this is OK as it is, can someone with commit access push this? Thanks!


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D43847



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D43847: [clang-tidy] Add check: replace string::find(...) == 0 with absl::StartsWith

2018-03-06 Thread Niko Weh via Phabricator via cfe-commits
niko added inline comments.



Comment at: clang-tidy/abseil/AbseilTidyModule.cpp:15
+
+#include 
+

hokein wrote:
> What is this header used for?
Sorry, ended up in the wrong file, moved to StringFindStartswithCheck.cpp.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D43847



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D43847: [clang-tidy] Add check: replace string::find(...) == 0 with absl::StartsWith

2018-03-06 Thread Niko Weh via Phabricator via cfe-commits
niko updated this revision to Diff 137249.
niko marked 4 inline comments as done.

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D43847

Files:
  clang-tidy/CMakeLists.txt
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/StringFindStartswithCheck.cpp
  clang-tidy/abseil/StringFindStartswithCheck.h
  clang-tidy/plugin/CMakeLists.txt
  clang-tidy/tool/CMakeLists.txt
  clang-tidy/tool/ClangTidyMain.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-string-find-startswith.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-string-find-startswith.cpp

Index: test/clang-tidy/abseil-string-find-startswith.cpp
===
--- test/clang-tidy/abseil-string-find-startswith.cpp
+++ test/clang-tidy/abseil-string-find-startswith.cpp
@@ -0,0 +1,55 @@
+// RUN: %check_clang_tidy %s abseil-string-find-startswith %t
+
+namespace std {
+template  class allocator {};
+template  class char_traits {};
+template ,
+  typename A = std::allocator>
+struct basic_string {
+  basic_string();
+  basic_string(const basic_string &);
+  basic_string(const C *, const A &a = A());
+  ~basic_string();
+  int find(basic_string s, int pos = 0);
+  int find(const char *s, int pos = 0);
+};
+typedef basic_string string;
+typedef basic_string wstring;
+} // namespace std
+
+std::string foo(std::string);
+std::string bar();
+
+#define A_MACRO(x, y) ((x) == (y))
+
+void tests(std::string s) {
+  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");{{$}}
+
+  s.find(s) == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
+
+  s.find("aaa") != 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "aaa");{{$}}
+
+  s.find(foo(foo(bar( != 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, foo(foo(bar(;{{$}}
+
+  if (s.find("") == 0) { /* do something */ }
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}if (absl::StartsWith(s, "")) { /* do something */ }{{$}}
+
+  0 != s.find("a");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "a");{{$}}
+
+  // expressions that don't trigger the check are here.
+  A_MACRO(s.find("a"), 0);
+  s.find("a", 1) == 0;
+  s.find("a", 1) == 1;
+  s.find("a") == 1;
+}
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -4,6 +4,7 @@
 =
 
 .. toctree::
+   abseil-string-find-startswith
android-cloexec-accept
android-cloexec-accept4
android-cloexec-creat
Index: docs/clang-tidy/checks/abseil-string-find-startswith.rst
===
--- docs/clang-tidy/checks/abseil-string-find-startswith.rst
+++ docs/clang-tidy/checks/abseil-string-find-startswith.rst
@@ -0,0 +1,41 @@
+.. title:: clang-tidy - abseil-string-find-startswith
+
+abseil-string-find-startswith
+=
+
+Checks whether a ``std::string::find()`` result is compared with 0, and
+suggests replacing with ``absl::StartsWith()``. This is both a readability and
+performance issue.
+
+.. code-block:: c++
+
+  string s = "...";
+  if (s.find("Hello World") == 0) { /* do something */ }
+
+becomes
+
+
+.. code-block:: c++
+
+  string s = "...";
+  if (absl::StartsWith(s, "Hello World")) { /* do something */ }
+
+
+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.
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or `google`. Default
+   is `llvm`.
+
+.. option:: AbseilStringsMatchHeader
+
+   The location of Abseil's ``strings/match.h``. Defaults to
+   ``absl/strings/match.h``.
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -75,6 +75,15 @@
 
   Warns if a class inherits from multiple classes that are not pure virtual.
 
+- New `abseil` module for checks related to the `Abseil `_
+  library.
+
+- New `abseil-string-find-startswith
+  `_ check
+
+  Checks whether a ``std::string::find()`` result is compared with 0, and
+  suggests replacing with ``absl::StartsWith()``.
+

[PATCH] D43847: [clang-tidy] Add check: replace string::find(...) == 0 with absl::StartsWith

2018-03-05 Thread Niko Weh via Phabricator via cfe-commits
niko marked an inline comment as done.
niko added inline comments.



Comment at: clang-tidy/absl/StringFindStartswithCheck.cpp:81
+  auto include_hint = include_inserter_->CreateIncludeInsertion(
+  source.getFileID(expr->getLocStart()), 
"third_party/absl/strings/match.h",
+  false);

niko wrote:
> hokein wrote:
> > The include path maybe different in different project.
> > 
> > I think we also need an option for the inserting header, and make it 
> > default to `absl/strings/match.h`.
> Instead of having a "AbseilStringsMatchHeader" option, does it make sense to 
> have a "AbseilIncludeDir" option here & default that to `absl`? (esp. if 
> there are going to be other abseil-checks in the future...)
Discussed offline with @hokein. Will leave AbseilStringsMatchHeader.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D43847



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D43847: [clang-tidy] Add check: replace string::find(...) == 0 with absl::StartsWith

2018-03-05 Thread Niko Weh via Phabricator via cfe-commits
niko updated this revision to Diff 137008.
niko marked 11 inline comments as done.
niko added a comment.

Addressed reviewer comments.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D43847

Files:
  clang-tidy/CMakeLists.txt
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/StringFindStartswithCheck.cpp
  clang-tidy/abseil/StringFindStartswithCheck.h
  clang-tidy/plugin/CMakeLists.txt
  clang-tidy/tool/CMakeLists.txt
  clang-tidy/tool/ClangTidyMain.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-string-find-startswith.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-string-find-startswith.cpp

Index: test/clang-tidy/abseil-string-find-startswith.cpp
===
--- test/clang-tidy/abseil-string-find-startswith.cpp
+++ test/clang-tidy/abseil-string-find-startswith.cpp
@@ -0,0 +1,59 @@
+// RUN: %check_clang_tidy %s abseil-string-find-startswith %t
+// -std=c++11
+
+namespace std {
+template  class allocator {};
+template  class char_traits {};
+template ,
+  typename A = std::allocator>
+struct basic_string {
+  basic_string();
+  basic_string(const basic_string &);
+  basic_string(const C *, const A &a = A());
+  ~basic_string();
+  int find(basic_string s, int pos = 0);
+  int find(const char *s, int pos = 0);
+};
+typedef basic_string string;
+typedef basic_string wstring;
+} // namespace std
+
+std::string foo(std::string);
+std::string bar();
+
+#define A_MACRO(x, y) ((x) == (y))
+
+void tests(std::string s) {
+  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");{{$}}
+
+  s.find(s) == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
+
+  s.find("aaa") != 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "aaa");{{$}}
+
+  s.find(foo(foo(bar( != 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, foo(foo(bar(;{{$}}
+
+  if (s.find("") == 0) { /* do something */ }
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}if (absl::StartsWith(s, "")) { /* do something */ }{{$}}
+
+  0 != s.find("a");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
+  // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "a");{{$}}
+
+  // message but no fixit:
+  A_MACRO(s.find("a"), 0);
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
+
+  // expressions that don't trigger the check are here.
+  s.find("a", 1) == 0;
+  s.find("a", 1) == 1;
+  s.find("a") == 1;
+}
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -4,6 +4,7 @@
 =
 
 .. toctree::
+   abseil-string-find-startswith
android-cloexec-accept
android-cloexec-accept4
android-cloexec-creat
Index: docs/clang-tidy/checks/abseil-string-find-startswith.rst
===
--- docs/clang-tidy/checks/abseil-string-find-startswith.rst
+++ docs/clang-tidy/checks/abseil-string-find-startswith.rst
@@ -0,0 +1,41 @@
+.. title:: clang-tidy - abseil-string-find-startswith
+
+abseil-string-find-startswith
+=
+
+Checks whether a ``std::string::find()`` result is compared with 0, and
+suggests replacing with ``absl::StartsWith()``. This is both a readability and
+performance issue.
+
+.. code-block:: c++
+
+  string s = "...";
+  if (s.find("Hello World") == 0) { /* do something */ }
+
+becomes
+
+
+.. code-block:: c++
+
+  string s = "...";
+  if (absl::StartsWith(s, "Hello World")) { /* do something */ }
+
+
+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 consired is
+   fixed.
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or `google`. Default
+   is `llvm`.
+
+.. option:: AbseilStringsMatchHeader
+
+   The location of Abseil's ``strings/match.h``. Defaults to
+   ``absl/strings/match.h``.
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -75,6 +75,15 @@
 
   Warns if a class inherits from multiple classes that are not pure virtual.
 
+- New `abseil` module for checks related to the `Abseil `_
+  library.
+
+- New `abseil-string-find-startswith
+  

[PATCH] D43847: [clang-tidy] Add check: replace string::find(...) == 0 with absl::StartsWith

2018-03-02 Thread Niko Weh via Phabricator via cfe-commits
niko added a comment.

Thanks everyone for your comments! I renamed the namespace and filenames to 
'abseil'.

@Eugene.Zelenko, definitely interested in extending this to a C++20 modernize 
check and adding `absl::EndsWith()` support,  would it be OK though to do this 
in a later patch?




Comment at: clang-tidy/absl/StringFindStartswithCheck.cpp:17-19
+  auto stringClassMatcher = anyOf(cxxRecordDecl(hasName("string")),
+  cxxRecordDecl(hasName("__versa_string")),
+  cxxRecordDecl(hasName("basic_string")));

hokein wrote:
> aaron.ballman wrote:
> > These should be using elaborated type specifiers to ensure we get the 
> > correct class, not some class that happens to have the same name. Also, 
> > this list should be configurable so that users can add their own entries to 
> > it.
> +1, we could add a `StringLikeClasses` option.
I've made the list configurable. Can you clarify what I would need to add in 
terms of type specifiers?



Comment at: clang-tidy/absl/StringFindStartswithCheck.cpp:44-47
+  const auto *expr = result.Nodes.getNodeAs("expr");
+  const auto *needle = result.Nodes.getNodeAs("needle");
+  const auto *haystack = result.Nodes.getNodeAs("findexpr")
+ ->getImplicitObjectArgument();

aaron.ballman wrote:
> Btw, these can use `auto` because the type is spelled out in the 
> initialization.
Thanks for the clarification. Is this true even for `Haystack` (as 
`->getImplicitObjectArgument()`'s type is Expr)?



Comment at: clang-tidy/absl/StringFindStartswithCheck.cpp:72
+   .str())
+  << FixItHint::CreateReplacement(expr->getSourceRange(),
+  (startswith_str + "(" +

aaron.ballman wrote:
> This fixit should be guarded in case it lands in the middle of a macro for 
> some reason.
Sorry, could you elaborate?



Comment at: clang-tidy/absl/StringFindStartswithCheck.cpp:81
+  auto include_hint = include_inserter_->CreateIncludeInsertion(
+  source.getFileID(expr->getLocStart()), 
"third_party/absl/strings/match.h",
+  false);

hokein wrote:
> The include path maybe different in different project.
> 
> I think we also need an option for the inserting header, and make it default 
> to `absl/strings/match.h`.
Instead of having a "AbseilStringsMatchHeader" option, does it make sense to 
have a "AbseilIncludeDir" option here & default that to `absl`? (esp. if there 
are going to be other abseil-checks in the future...)



Comment at: docs/clang-tidy/checks/absl-string-find-startswith.rst:18
+``if (absl::StartsWith(s, "Hello World")) { /* do something */ };``
+

Eugene.Zelenko wrote:
> Is there any online documentation about such usage? If so please refer to in 
> at. See other guidelines as example.
I don't believe there is documentation for this yet. The [comment in the 
header](https://github.com/abseil/abseil-cpp/blob/9850abf25d8efcdc1ff752f1eeef13b640c4ead4/absl/strings/match.h#L50)
 explains what it does but doesn't have an explicit usage example. (If that 
qualifies I'll obviously include it?)


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D43847



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D43847: [clang-tidy] Add check: replace string::find(...) == 0 with absl::StartsWith

2018-03-02 Thread Niko Weh via Phabricator via cfe-commits
niko updated this revision to Diff 136821.
niko marked 23 inline comments as done.
niko added a comment.

Renamed 'absl' to 'abseil', applied reviewer suggestions


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D43847

Files:
  clang-tidy/CMakeLists.txt
  clang-tidy/abseil/AbseilTidyModule.cpp
  clang-tidy/abseil/CMakeLists.txt
  clang-tidy/abseil/StringFindStartswithCheck.cpp
  clang-tidy/abseil/StringFindStartswithCheck.h
  clang-tidy/plugin/CMakeLists.txt
  clang-tidy/tool/CMakeLists.txt
  clang-tidy/tool/ClangTidyMain.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/abseil-string-find-startswith.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/abseil-string-find-startswith.cpp

Index: test/clang-tidy/abseil-string-find-startswith.cpp
===
--- test/clang-tidy/abseil-string-find-startswith.cpp
+++ test/clang-tidy/abseil-string-find-startswith.cpp
@@ -0,0 +1,54 @@
+// RUN: %check_clang_tidy %s abseil-string-find-startswith %t
+// -std=c++11
+
+namespace std {
+template  class allocator {};
+template  class char_traits {};
+template ,
+  typename A = std::allocator>
+struct basic_string {
+  basic_string();
+  basic_string(const basic_string &);
+  basic_string(const C *, const A &a = A());
+  ~basic_string();
+  int find(basic_string s, int pos = 0);
+  int find(const char *s, int pos = 0);
+};
+typedef basic_string string;
+typedef basic_string wstring;
+} // namespace std
+
+std::string foo(std::string);
+std::string bar();
+
+void tests(std::string s) {
+  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");{{$}}
+
+  s.find(s) == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith instead of find() == 0 [abseil-string-find-startswith]
+  // CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s, s);{{$}}
+
+  s.find("aaa") != 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith instead of find() != 0 [abseil-string-find-startswith]
+  // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "aaa");{{$}}
+
+  s.find(foo(foo(bar( != 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith instead of find() != 0 [abseil-string-find-startswith]
+  // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, foo(foo(bar(;{{$}}
+
+  if (s.find("") == 0) { /* do something */ }
+  // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use absl::StartsWith instead of find() == 0 [abseil-string-find-startswith]
+  // CHECK-FIXES: {{^[[:space:]]*}}if (absl::StartsWith(s, "")) { /* do something */ }{{$}}
+
+  0 != s.find("a");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith instead of find() != 0 [abseil-string-find-startswith]
+  // CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "a");{{$}}
+
+
+  // expressions that don't trigger the check are here.
+  s.find("a", 1) == 0;
+  s.find("a", 1) == 1;
+  s.find("a") == 1;
+}
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -4,6 +4,7 @@
 =
 
 .. toctree::
+   abseil-string-find-startswith
android-cloexec-accept
android-cloexec-accept4
android-cloexec-creat
Index: docs/clang-tidy/checks/abseil-string-find-startswith.rst
===
--- docs/clang-tidy/checks/abseil-string-find-startswith.rst
+++ docs/clang-tidy/checks/abseil-string-find-startswith.rst
@@ -0,0 +1,41 @@
+.. title:: clang-tidy - abseil-string-find-startswith
+
+abseil-string-find-startswith
+==
+
+Checks whether a ``std::string::find()`` result is compared with 0, and
+suggests replacing with ``absl::StartsWith()``. This is both a readability and
+performance issue.
+
+.. code-block:: c++
+
+  string s = "...";
+  if (s.find("Hello World") == 0) { /* do something */ }
+
+becomes
+
+
+.. code-block:: c++
+
+  string s = "...";
+  if (absl::StartsWith(s, "Hello World")) { /* do something */ }
+
+
+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 consired is
+   fixed.
+
+.. option:: IncludeStyle
+
+   A string specifying which include-style is used, `llvm` or `google`. Default
+   is `llvm`.
+
+.. option:: AbseilStringsMatchHeader
+
+   The location of Abseil's ``strings/match.h``. Defaults to
+   ``absl/strings/match.h``.
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -75,6 +75,15 @@
 
   Warns if a class inherits from multiple classes that are not pure virtual.
 
+- New `abseil` module for checks r

[PATCH] D43847: [tidy] Add check: replace string::find(...) == 0 with absl::StartsWith

2018-02-27 Thread Niko Weh via Phabricator via cfe-commits
niko created this revision.
niko added reviewers: ioeric, hokein.
Herald added subscribers: cfe-commits, mgorny.

Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D43847

Files:
  clang-tidy/CMakeLists.txt
  clang-tidy/absl/AbslTidyModule.cpp
  clang-tidy/absl/CMakeLists.txt
  clang-tidy/absl/StringFindStartswithCheck.cpp
  clang-tidy/absl/StringFindStartswithCheck.h
  clang-tidy/plugin/CMakeLists.txt
  clang-tidy/tool/CMakeLists.txt
  clang-tidy/tool/ClangTidyMain.cpp
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/absl-string-find-startswith.rst
  docs/clang-tidy/checks/list.rst
  test/clang-tidy/absl-string-find-startswith.cpp

Index: test/clang-tidy/absl-string-find-startswith.cpp
===
--- test/clang-tidy/absl-string-find-startswith.cpp
+++ test/clang-tidy/absl-string-find-startswith.cpp
@@ -0,0 +1,49 @@
+// RUN: %check_clang_tidy %s absl-string-find-startswith %t -- -- -I%S
+// -std=c++11
+
+namespace std {
+template  class allocator {};
+template  class char_traits {};
+template ,
+  typename A = std::allocator>
+struct basic_string {
+  basic_string();
+  basic_string(const basic_string &);
+  basic_string(const C *, const A &a = A());
+  ~basic_string();
+  int find(basic_string s, int pos = 0);
+  int find(const char *s, int pos = 0);
+};
+typedef basic_string string;
+typedef basic_string wstring;
+} // namespace std
+
+std::string foo(std::string);
+std::string bar();
+
+void tests(std::string s) {
+  s.find("a") == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use absl::StartsWith instead of
+  // find() == 0 [absl-string-find-startswith] CHECK_FIXES:
+  // {{^}}absl::StartsWith(s, "a");{{$}}
+
+  s.find(s) == 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use absl::StartsWith instead of
+  // find() == 0 [absl-string-find-startswith] CHECK_FIXES:
+  // {{^}}absl::StartsWith(s, s);{{$}}
+
+  s.find("aaa") != 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use !absl::StartsWith instead of
+  // find() != 0 [absl-string-find-startswith] CHECK_FIXES:
+  // {{^}}!absl::StartsWith(s, "aaa");{{$}}
+
+  s.find(foo(foo(bar( != 0;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Use !absl::StartsWith instead of
+  // find() != 0 [absl-string-find-startswith] CHECK_FIXES:
+  // {{^}}!absl::StartsWith(s, foo(foo(foo)));{{$}}
+
+  // expressions that don't trigger the check are here.
+  s.find("a", 1) == 0;
+  s.find("a", 1) == 1;
+  s.find("a") == 1;
+}
Index: docs/clang-tidy/checks/list.rst
===
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -4,6 +4,7 @@
 =
 
 .. toctree::
+   absl-string-find-startswith
android-cloexec-accept
android-cloexec-accept4
android-cloexec-creat
Index: docs/clang-tidy/checks/absl-string-find-startswith.rst
===
--- docs/clang-tidy/checks/absl-string-find-startswith.rst
+++ docs/clang-tidy/checks/absl-string-find-startswith.rst
@@ -0,0 +1,18 @@
+.. title:: clang-tidy - absl-string-find-startswith
+
+absl-string-find-startswith
+==
+
+This check triggers on (in)equality comparisons between string.find()
+and zero. Comparisons like this should be replaced with
+absl::StartsWith(string, prefix). This is both a readability and a
+performance issue.
+
+::
+
+string s = "...";
+if (s.find("Hello World") == 0) { /* do something */ }
+
+should be replaced with
+``if (absl::StartsWith(s, "Hello World")) { /* do something */ };``
+
Index: docs/ReleaseNotes.rst
===
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -57,6 +57,12 @@
 Improvements to clang-tidy
 --
 
+- New `absl-string-find-startswith
+  `_ check
+
+  Checks whether a string::find result is compared with 0, and suggests
+  replacing with absl::StartsWith.
+
 - New `fuchsia-statically-constructed-objects
   `_ check
 
Index: clang-tidy/tool/ClangTidyMain.cpp
===
--- clang-tidy/tool/ClangTidyMain.cpp
+++ clang-tidy/tool/ClangTidyMain.cpp
@@ -462,6 +462,11 @@
 static int LLVM_ATTRIBUTE_UNUSED CERTModuleAnchorDestination =
 CERTModuleAnchorSource;
 
+// This anchor is used to force the linker to link the AbslModule.
+extern volatile int AbslModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED AbslModuleAnchorDestination =
+AbslModuleAnchorSource;
+
 // This anchor is used to force the linker to link the BoostModule.
 extern volatile int BoostModuleAnchorSource;
 static int LLVM_ATTRIBUTE_UNUSED BoostModuleAnchorDestination =
Index: clang-tidy/tool/CMakeLists.txt