1// RUN: %check_clang_tidy %s performance-faster-string-find %t
2// RUN: %check_clang_tidy -check-suffix=CUSTOM %s performance-faster-string-find %t -- \
3// RUN: -config="{CheckOptions: \
4// RUN: {performance-faster-string-find.StringLikeClasses: \
5// RUN: '::llvm::StringRef;'}}"
6
7namespace std {
8template <typename Char>
9struct basic_string {
10 int find(const Char *, int = 0) const;
11 int find(const Char *, int, int) const;
12 int rfind(const Char *) const;
13 int find_first_of(const Char *) const;
14 int find_first_not_of(const Char *) const;
15 int find_last_of(const Char *) const;
16 int find_last_not_of(const Char *) const;
17};
18
19typedef basic_string<char> string;
20typedef basic_string<wchar_t> wstring;
21
22template <typename Char>
23struct basic_string_view {
24 int find(const Char *, int = 0) const;
25 int find(const Char *, int, int) const;
26 int rfind(const Char *) const;
27 int find_first_of(const Char *) const;
28 int find_first_not_of(const Char *) const;
29 int find_last_of(const Char *) const;
30 int find_last_not_of(const Char *) const;
31};
32
33typedef basic_string_view<char> string_view;
34typedef basic_string_view<wchar_t> wstring_view;
35} // namespace std
36
37namespace llvm {
38struct StringRef {
39 int find(const char *) const;
40};
41} // namespace llvm
42
43struct NotStringRef {
44 int find(const char *);
45};
46
47void StringFind() {
48 std::string Str;
49
50 Str.find("a");
51 // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'find' called with a string literal consisting of a single character; consider using the more effective overload accepting a character [performance-faster-string-find]
52 // CHECK-FIXES: Str.find('a');
53
54 // Works with the pos argument.
55 Str.find("a", 1);
56 // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'find' called with a string literal
57 // CHECK-FIXES: Str.find('a', 1);
58
59 // Doesn't work with strings smaller or larger than 1 char.
60 Str.find("");
61 Str.find("ab");
62
63 // Doesn't do anything with the 3 argument overload.
64 Str.find("a", 1, 1);
65
66 // Single quotes are escaped properly
67 Str.find("'");
68 // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'find' called with a string literal
69 // CHECK-FIXES: Str.find('\'');
70 Str.find("\'");
71 // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'find' called with a string literal
72 // CHECK-FIXES: Str.find('\'');
73
74 // Other methods that can also be replaced
75 Str.rfind("a");
76 // CHECK-MESSAGES: [[@LINE-1]]:13: warning: 'rfind' called with a string literal
77 // CHECK-FIXES: Str.rfind('a');
78 Str.find_first_of("a");
79 // CHECK-MESSAGES: [[@LINE-1]]:21: warning: 'find_first_of' called with a string
80 // CHECK-FIXES: Str.find_first_of('a');
81 Str.find_first_not_of("a");
82 // CHECK-MESSAGES: [[@LINE-1]]:25: warning: 'find_first_not_of' called with a
83 // CHECK-FIXES: Str.find_first_not_of('a');
84 Str.find_last_of("a");
85 // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'find_last_of' called with a string
86 // CHECK-FIXES: Str.find_last_of('a');
87 Str.find_last_not_of("a");
88 // CHECK-MESSAGES: [[@LINE-1]]:24: warning: 'find_last_not_of' called with a
89 // CHECK-FIXES: Str.find_last_not_of('a');
90
91 // std::wstring should work.
92 std::wstring WStr;
93 WStr.find(L"n");
94 // CHECK-MESSAGES: [[@LINE-1]]:13: warning: 'find' called with a string literal
95 // CHECK-FIXES: Str.find(L'n');
96 // Even with unicode that fits in one wide char.
97 WStr.find(L"\x3A9");
98 // CHECK-MESSAGES: [[@LINE-1]]:13: warning: 'find' called with a string literal
99 // CHECK-FIXES: Str.find(L'\x3A9');
100
101 // std::string_view and std::wstring_view should work.
102 std::string_view StrView;
103 StrView.find("n");
104 // CHECK-MESSAGES: [[@LINE-1]]:16: warning: 'find' called with a string literal
105 // CHECK-FIXES: StrView.find('n');
106 std::wstring_view WStrView;
107
108 WStrView.find(L"n");
109 // CHECK-MESSAGES: [[@LINE-1]]:17: warning: 'find' called with a string literal
110 // CHECK-FIXES: WStrView.find(L'n');
111 WStrView.find(L"\x3A9");
112 // CHECK-MESSAGES: [[@LINE-1]]:17: warning: 'find' called with a string literal
113 // CHECK-FIXES: WStrView.find(L'\x3A9');
114
115 // Also with other types, but only if it was specified in the options.
116 llvm::StringRef sr;
117 sr.find("x");
118 // CHECK-MESSAGES-CUSTOM: [[@LINE-1]]:11: warning: 'find' called with a string literal
119 // CHECK-FIXES-CUSTOM: sr.find('x');
120 NotStringRef nsr;
121 nsr.find("x");
122}
123
124
125template <typename T>
126int FindTemplateDependant(T value) {
127 return value.find("A");
128}
129template <typename T>
130int FindTemplateNotDependant(T pos) {
131 return std::string().find("A", pos);
132 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: 'find' called with a string literal
133 // CHECK-FIXES: return std::string().find('A', pos);
134}
135
136int FindStr() {
137 return FindTemplateDependant(value: std::string()) + FindTemplateNotDependant(pos: 1);
138}
139
140#define STR_MACRO(str) str.find("A")
141#define POS_MACRO(pos) std::string().find("A",pos)
142
143int Macros() {
144 return STR_MACRO(std::string()) + POS_MACRO(1);
145 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'find' called with a string literal
146 // CHECK-MESSAGES: [[@LINE-2]]:37: warning: 'find' called with a string literal
147}
148

source code of clang-tools-extra/test/clang-tidy/checkers/performance/faster-string-find.cpp