148 lines · cpp
1// RUN: %check_clang_tidy %s performance-faster-string-find %t2// 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 std36 37namespace llvm {38struct StringRef {39 int find(const char *) const;40};41} // namespace llvm42 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 literal57 // 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 properly67 Str.find("'");68 // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'find' called with a string literal69 // CHECK-FIXES: Str.find('\'');70 Str.find("\'");71 // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'find' called with a string literal72 // CHECK-FIXES: Str.find('\'');73 74 // Other methods that can also be replaced75 Str.rfind("a");76 // CHECK-MESSAGES: [[@LINE-1]]:13: warning: 'rfind' called with a string literal77 // CHECK-FIXES: Str.rfind('a');78 Str.find_first_of("a");79 // CHECK-MESSAGES: [[@LINE-1]]:21: warning: 'find_first_of' called with a string80 // 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 a83 // 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 string86 // 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 a89 // 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 literal95 // CHECK-FIXES: WStr.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 literal99 // CHECK-FIXES: WStr.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 literal105 // 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 literal110 // CHECK-FIXES: WStrView.find(L'n');111 WStrView.find(L"\x3A9");112 // CHECK-MESSAGES: [[@LINE-1]]:17: warning: 'find' called with a string literal113 // 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 literal119 // 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 literal133 // CHECK-FIXES: return std::string().find('A', pos);134}135 136int FindStr() {137 return FindTemplateDependant(std::string()) + FindTemplateNotDependant(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 literal146 // CHECK-MESSAGES: [[@LINE-2]]:37: warning: 'find' called with a string literal147}148