// RUN: %check_clang_tidy %s performance-faster-string-find %t -- \ // RUN: -config="{CheckOptions: \ // RUN: [{key: performance-faster-string-find.StringLikeClasses, \ // RUN: value: 'std::basic_string; ::llvm::StringRef;'}]}" -- namespace std { template struct basic_string { int find(const Char *, int = 0) const; int find(const Char *, int, int) const; int rfind(const Char *) const; int find_first_of(const Char *) const; int find_first_not_of(const Char *) const; int find_last_of(const Char *) const; int find_last_not_of(const Char *) const; }; typedef basic_string string; typedef basic_string wstring; } // namespace std namespace llvm { struct StringRef { int find(const char *) const; }; } // namespace llvm struct NotStringRef { int find(const char *); }; void StringFind() { std::string Str; Str.find("a"); // 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] // CHECK-FIXES: Str.find('a'); // Works with the pos argument. Str.find("a", 1); // CHECK-MESSAGES: [[@LINE-1]]:12: warning: 'find' called with a string literal // CHECK-FIXES: Str.find('a', 1); // Doens't work with strings smaller or larger than 1 char. Str.find(""); Str.find("ab"); // Doesn't do anything with the 3 argument overload. Str.find("a", 1, 1); // Other methods that can also be replaced Str.rfind("a"); // CHECK-MESSAGES: [[@LINE-1]]:13: warning: 'rfind' called with a string literal // CHECK-FIXES: Str.rfind('a'); Str.find_first_of("a"); // CHECK-MESSAGES: [[@LINE-1]]:21: warning: 'find_first_of' called with a string // CHECK-FIXES: Str.find_first_of('a'); Str.find_first_not_of("a"); // CHECK-MESSAGES: [[@LINE-1]]:25: warning: 'find_first_not_of' called with a // CHECK-FIXES: Str.find_first_not_of('a'); Str.find_last_of("a"); // CHECK-MESSAGES: [[@LINE-1]]:20: warning: 'find_last_of' called with a string // CHECK-FIXES: Str.find_last_of('a'); Str.find_last_not_of("a"); // CHECK-MESSAGES: [[@LINE-1]]:24: warning: 'find_last_not_of' called with a // CHECK-FIXES: Str.find_last_not_of('a'); // std::wstring should work. std::wstring WStr; WStr.find(L"n"); // CHECK-MESSAGES: [[@LINE-1]]:13: warning: 'find' called with a string literal // CHECK-FIXES: Str.find(L'n'); // Even with unicode that fits in one wide char. WStr.find(L"\x3A9"); // CHECK-MESSAGES: [[@LINE-1]]:13: warning: 'find' called with a string literal // CHECK-FIXES: Str.find(L'\x3A9'); // Also with other types, but only if it was specified in the options. llvm::StringRef sr; sr.find("x"); // CHECK-MESSAGES: [[@LINE-1]]:11: warning: 'find' called with a string literal // CHECK-FIXES: sr.find('x'); NotStringRef nsr; nsr.find("x"); } template int FindTemplateDependant(T value) { return value.find("A"); } template int FindTemplateNotDependant(T pos) { return std::string().find("A", pos); // CHECK-MESSAGES: [[@LINE-1]]:29: warning: 'find' called with a string literal // CHECK-FIXES: return std::string().find('A', pos); } int FindStr() { return FindTemplateDependant(std::string()) + FindTemplateNotDependant(1); } #define STR_MACRO(str) str.find("A") #define POS_MACRO(pos) std::string().find("A",pos) int Macros() { return STR_MACRO(std::string()) + POS_MACRO(1); // CHECK-MESSAGES: [[@LINE-1]]:10: warning: 'find' called with a string literal // CHECK-MESSAGES: [[@LINE-2]]:37: warning: 'find' called with a string literal }