Skip to content

Commit

Permalink
[clang-tidy] Improve string type matcher for abseil-string-find-start…
Browse files Browse the repository at this point in the history
…s-with check.

Summary:
This patch improves the check to match the desugared "string" type (so that it
can handle custom-implemented string classes), see the newly-added test.

Reviewers: alexfh

Subscribers: klimek, xazax.hun, cfe-commits

Differential Revision: https://reviews.llvm.org/D47704

llvm-svn: 334270
  • Loading branch information
hokein committed Jun 8, 2018
1 parent 6fc3759 commit 07996a5
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
Expand Up @@ -36,10 +36,13 @@ void StringFindStartswithCheck::registerMatchers(MatchFinder *Finder) {
auto ZeroLiteral = integerLiteral(equals(0));
auto StringClassMatcher = cxxRecordDecl(hasAnyName(SmallVector<StringRef, 4>(
StringLikeClasses.begin(), StringLikeClasses.end())));
auto StringType = hasUnqualifiedDesugaredType(
recordType(hasDeclaration(StringClassMatcher)));

auto StringFind = cxxMemberCallExpr(
// .find()-call on a string...
callee(cxxMethodDecl(hasName("find"), ofClass(StringClassMatcher))),
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).
Expand Down
@@ -1,4 +1,6 @@
// RUN: %check_clang_tidy %s abseil-string-find-startswith %t
// RUN: %check_clang_tidy %s abseil-string-find-startswith %t -- \
// RUN: -config="{CheckOptions: [{key: 'abseil-string-find-startswith.StringLikeClasses', value: '::std::basic_string;::basic_string'}]}" \
// RUN: -- -std=c++11

namespace std {
template <typename T> class allocator {};
Expand All @@ -15,14 +17,23 @@ struct basic_string {
};
typedef basic_string<char> string;
typedef basic_string<wchar_t> wstring;

struct cxx_string {
int find(const char *s, int pos = 0);
};
} // namespace std

struct basic_string : public std::cxx_string {
basic_string();
};
typedef basic_string global_string;

std::string foo(std::string);
std::string bar();

#define A_MACRO(x, y) ((x) == (y))

void tests(std::string s) {
void tests(std::string s, global_string s2) {
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");{{$}}
Expand All @@ -47,6 +58,10 @@ void tests(std::string s) {
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use !absl::StartsWith
// CHECK-FIXES: {{^[[:space:]]*}}!absl::StartsWith(s, "a");{{$}}

s2.find("a") == 0;
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use absl::StartsWith
// CHECK-FIXES: {{^[[:space:]]*}}absl::StartsWith(s2, "a");{{$}}

// expressions that don't trigger the check are here.
A_MACRO(s.find("a"), 0);
s.find("a", 1) == 0;
Expand Down

0 comments on commit 07996a5

Please sign in to comment.