mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 11:46:41 +00:00

Also document cases with two or three arguments (matching default arguments) this check matches. Closes https://github.com/llvm/llvm-project/issues/129498.
375 lines
13 KiB
C++
375 lines
13 KiB
C++
// RUN: %check_clang_tidy -std=c++20 %s modernize-use-starts-ends-with %t -- \
|
|
// RUN: -- -isystem %clang_tidy_headers
|
|
|
|
#include <string.h>
|
|
#include <string>
|
|
|
|
std::string foo(std::string);
|
|
std::string bar();
|
|
|
|
class sub_string : public std::string {};
|
|
class sub_sub_string : public sub_string {};
|
|
|
|
struct string_like {
|
|
bool starts_with(const char *s) const;
|
|
size_t find(const char *s, size_t pos = 0) const;
|
|
};
|
|
|
|
struct string_like_camel {
|
|
bool startsWith(const char *s) const;
|
|
size_t find(const char *s, size_t pos = 0) const;
|
|
};
|
|
|
|
struct prefer_underscore_version {
|
|
bool starts_with(const char *s) const;
|
|
bool startsWith(const char *s) const;
|
|
size_t find(const char *s, size_t pos = 0) const;
|
|
};
|
|
|
|
struct prefer_underscore_version_flip {
|
|
bool startsWith(const char *s) const;
|
|
bool starts_with(const char *s) const;
|
|
size_t find(const char *s, size_t pos = 0) const;
|
|
};
|
|
|
|
void test(std::string s, std::string_view sv, sub_string ss, sub_sub_string sss,
|
|
string_like sl, string_like_camel slc, prefer_underscore_version puv,
|
|
prefer_underscore_version_flip puvf) {
|
|
s.find("a") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of find [modernize-use-starts-ends-with]
|
|
// CHECK-FIXES: s.starts_with("a");
|
|
|
|
(((((s)).find("a")))) == ((0));
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: ((s)).starts_with("a");
|
|
|
|
(s + "a").find("a") == ((0));
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: (s + "a").starts_with("a");
|
|
|
|
s.find(s) == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with(s);
|
|
|
|
s.find("aaa") != 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: !s.starts_with("aaa");
|
|
|
|
s.find(foo(foo(bar()))) != 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: !s.starts_with(foo(foo(bar())));
|
|
|
|
if (s.find("....") == 0) { /* do something */ }
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: if (s.starts_with("...."))
|
|
|
|
0 != s.find("a");
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: !s.starts_with("a");
|
|
|
|
s.rfind("a", 0) == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of rfind [modernize-use-starts-ends-with]
|
|
// CHECK-FIXES: s.starts_with("a");
|
|
|
|
s.rfind(s, 0) == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with(s);
|
|
|
|
s.rfind("aaa", 0) != 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: !s.starts_with("aaa");
|
|
|
|
s.rfind(foo(foo(bar())), 0) != 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: !s.starts_with(foo(foo(bar())));
|
|
|
|
if (s.rfind("....", 0) == 0) { /* do something */ }
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: if (s.starts_with("...."))
|
|
|
|
0 != s.rfind("a", 0);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: !s.starts_with("a");
|
|
|
|
#define FIND find
|
|
s.FIND("a") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with("a")
|
|
|
|
#define PREFIX "a"
|
|
s.find(PREFIX) == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with(PREFIX)
|
|
|
|
#define ZERO 0
|
|
s.find("a") == ZERO;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with("a")
|
|
|
|
sv.find("a") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: sv.starts_with("a");
|
|
|
|
sv.rfind("a", 0) != 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: !sv.starts_with("a");
|
|
|
|
ss.find("a") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: ss.starts_with("a");
|
|
|
|
sss.find("a") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: ss.starts_with("a");
|
|
|
|
sl.find("a") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: sl.starts_with("a");
|
|
|
|
slc.find("a") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use startsWith
|
|
// CHECK-FIXES: slc.startsWith("a");
|
|
|
|
puv.find("a") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: puv.starts_with("a");
|
|
|
|
puvf.find("a") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: puvf.starts_with("a");
|
|
|
|
s.compare(0, 1, "a") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of compare [modernize-use-starts-ends-with]
|
|
// CHECK-FIXES: s.starts_with("a");
|
|
|
|
s.compare(0, 1, "a") != 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of compare [modernize-use-starts-ends-with]
|
|
// CHECK-FIXES: !s.starts_with("a");
|
|
|
|
s.compare(0, strlen("a"), "a") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with("a");
|
|
|
|
s.compare(0, std::strlen("a"), "a") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with("a");
|
|
|
|
s.compare(0, std::strlen(("a")), "a") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with("a");
|
|
|
|
s.compare(0, std::strlen(("a")), (("a"))) == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with("a");
|
|
|
|
s.compare(0, s.size(), s) == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with(s);
|
|
|
|
s.compare(0, s.length(), s) == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with(s);
|
|
|
|
0 != s.compare(0, sv.length(), sv);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with(sv);
|
|
|
|
#define LENGTH(x) (x).length()
|
|
s.compare(0, LENGTH(s), s) == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with(s);
|
|
|
|
s.compare(ZERO, LENGTH(s), s) == ZERO;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with(s);
|
|
|
|
s.compare(ZERO, LENGTH(sv), sv) != 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: !s.starts_with(sv);
|
|
|
|
s.compare(s.size() - 6, 6, "suffix") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
|
|
// CHECK-FIXES: s.ends_with("suffix");
|
|
|
|
s.compare(s.size() - 6, strlen("abcdef"), "suffix") == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
|
|
// CHECK-FIXES: s.ends_with("suffix");
|
|
|
|
std::string suffix = "suffix";
|
|
s.compare(s.size() - suffix.size(), suffix.size(), suffix) == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
|
|
// CHECK-FIXES: s.ends_with(suffix);
|
|
|
|
s.rfind("suffix") == s.size() - 6;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
|
|
// CHECK-FIXES: s.ends_with("suffix");
|
|
|
|
s.rfind("suffix") == s.size() - strlen("suffix");
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
|
|
// CHECK-FIXES: s.ends_with("suffix");
|
|
|
|
s.rfind(suffix) == s.size() - suffix.size();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
|
|
// CHECK-FIXES: s.ends_with(suffix);
|
|
|
|
s.rfind(suffix, std::string::npos) == s.size() - suffix.size();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
|
|
// CHECK-FIXES: s.ends_with(suffix);
|
|
|
|
s.rfind(suffix) == (s.size() - suffix.size());
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
|
|
// CHECK-FIXES: s.ends_with(suffix);
|
|
|
|
s.rfind(suffix, s.npos) == (s.size() - suffix.size());
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
|
|
// CHECK-FIXES: s.ends_with(suffix);
|
|
|
|
s.rfind(suffix, s.npos) == (((s.size()) - (suffix.size())));
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
|
|
// CHECK-FIXES: s.ends_with(suffix);
|
|
|
|
s.rfind(suffix) != s.size() - suffix.size();
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
|
|
// CHECK-FIXES: !s.ends_with(suffix);
|
|
|
|
(s.size() - suffix.size()) == s.rfind(suffix);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
|
|
// CHECK-FIXES: s.ends_with(suffix);
|
|
|
|
s.find("a", 0) == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with("a");
|
|
|
|
s.find(s, ZERO) == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with(s);
|
|
|
|
s.find(s, 0) == ZERO;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with(s);
|
|
|
|
s.find("aaa", 0, 3) == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with("aaa");
|
|
|
|
s.find("aaa", ZERO, 3) == 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with("aaa");
|
|
|
|
s.find("aaa", ZERO, strlen(("aaa"))) == ZERO;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with("aaa");
|
|
|
|
s.rfind("aaa", 0, 3) != 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: !s.starts_with("aaa");
|
|
|
|
s.rfind("aaa", ZERO, 3) != 0;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: !s.starts_with("aaa");
|
|
|
|
s.rfind("aaa", ZERO, strlen(("aaa"))) == ZERO;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with
|
|
// CHECK-FIXES: s.starts_with("aaa");
|
|
|
|
struct S {
|
|
std::string s;
|
|
} t;
|
|
t.s.rfind(suffix) == (t.s.size() - suffix.size());
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use ends_with
|
|
// CHECK-FIXES: t.s.ends_with(suffix);
|
|
|
|
// Expressions that don't trigger the check are here.
|
|
#define EQ(x, y) ((x) == (y))
|
|
EQ(s.find("a"), 0);
|
|
|
|
#define DOTFIND(x, y) (x).find(y)
|
|
DOTFIND(s, "a") == 0;
|
|
|
|
#define STARTS_WITH_COMPARE(x, y) (x).compare(0, (x).size(), (y))
|
|
STARTS_WITH_COMPARE(s, s) == 0;
|
|
|
|
s.compare(0, 1, "ab") == 0;
|
|
s.rfind(suffix, 1) == s.size() - suffix.size();
|
|
|
|
#define STR(x) std::string(x)
|
|
0 == STR(s).find("a");
|
|
|
|
#define STRING s
|
|
if (0 == STRING.find("ala")) { /* do something */}
|
|
|
|
// Cases when literal-size and size parameters are different are not being matched.
|
|
s.find("aaa", 0, 2) == 0;
|
|
s.find("aaa", 0, strlen("aa")) == 0;
|
|
s.rfind("aaa", 0, 2) == 0;
|
|
s.rfind("aaa", 0, strlen("aa")) == 0;
|
|
}
|
|
|
|
void test_substr() {
|
|
std::string str("hello world");
|
|
std::string prefix = "hello";
|
|
|
|
// Basic pattern
|
|
str.substr(0, 5) == "hello";
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr [modernize-use-starts-ends-with]
|
|
// CHECK-FIXES: str.starts_with("hello");
|
|
|
|
// With string literal on left side
|
|
"hello" == str.substr(0, 5);
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr [modernize-use-starts-ends-with]
|
|
// CHECK-FIXES: str.starts_with("hello");
|
|
|
|
// Inequality comparison
|
|
str.substr(0, 5) != "world";
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr [modernize-use-starts-ends-with]
|
|
// CHECK-FIXES: !str.starts_with("world");
|
|
|
|
// Ensure non-zero start position is not transformed
|
|
str.substr(1, 5) == "hello";
|
|
str.substr(0, 4) == "hello"; // Length mismatch
|
|
|
|
size_t len = 5;
|
|
str.substr(0, len) == "hello"; // Non-constant length
|
|
|
|
// String literal with size calculation
|
|
str.substr(0, strlen("hello")) == "hello";
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr [modernize-use-starts-ends-with]
|
|
// CHECK-FIXES: str.starts_with("hello");
|
|
|
|
str.substr(0, prefix.size()) == prefix;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr [modernize-use-starts-ends-with]
|
|
// CHECK-FIXES: str.starts_with(prefix);
|
|
|
|
str.substr(0, prefix.length()) == prefix;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr [modernize-use-starts-ends-with]
|
|
// CHECK-FIXES: str.starts_with(prefix);
|
|
|
|
// Tests to verify macro behavior
|
|
#define MSG "hello"
|
|
str.substr(0, strlen(MSG)) == MSG;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr [modernize-use-starts-ends-with]
|
|
// CHECK-FIXES: str.starts_with(MSG);
|
|
|
|
#define STARTS_WITH(X, Y) (X).substr(0, (Y).size()) == (Y)
|
|
STARTS_WITH(str, prefix);
|
|
|
|
#define SUBSTR(X, A, B) (X).substr((A), (B))
|
|
SUBSTR(str, 0, 6) == "prefix";
|
|
|
|
#define STR() str
|
|
SUBSTR(STR(), 0, 6) == "prefix";
|
|
"prefix" == SUBSTR(STR(), 0, 6);
|
|
|
|
str.substr(0, strlen("hello123")) == "hello";
|
|
}
|
|
|
|
void test_operator_rewriting(std::string str, std::string prefix) {
|
|
str.substr(0, prefix.size()) == prefix;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr
|
|
// CHECK-FIXES: str.starts_with(prefix);
|
|
|
|
str.substr(0, prefix.size()) != prefix;
|
|
// CHECK-MESSAGES: :[[@LINE-1]]:{{[0-9]+}}: warning: use starts_with instead of substr
|
|
// CHECK-FIXES: !str.starts_with(prefix);
|
|
}
|