// RUN: %check_clang_tidy -std=c++17-or-later %s performance-string-view-conversions %t #include #include using namespace std::literals::string_literals; using namespace std::literals::string_view_literals; void foo_sv(int p1, std::string_view p2, double p3); void foo_wsv(int p1, std::wstring_view p2, double p3); void foo_wsv(std::wstring_view p2); void foo_str(int p1, const std::string& p2, double p3); void foo_wstr(int p1, const std::wstring& p2, double p3); std::string foo_str(int p1); std::wstring foo_wstr(int, const std::string&); std::string_view foo_sv(int p1); struct TakesStringView { TakesStringView(int, std::string_view); }; struct StringBuilder { StringBuilder& operator+=(std::string_view); StringBuilder& append(std::string_view); }; void positive(std::string_view sv, std::wstring_view wsv) { // string(string_view) // foo_sv(42, std::string(sv), 3.14); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: foo_sv(42, sv, 3.14); foo_sv(42, std::string(sv).c_str(), 3.14); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant conversion to 'const std::basic_string' and calling .c_str() and then back to 'std::string_view' (aka 'basic_string_view') [performance-string-view-conversions] // CHECK-FIXES: foo_sv(42, sv, 3.14); foo_sv(42, std::string(sv).data(), 3.14); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant conversion to 'const std::basic_string' and calling .data() and then back to 'std::string_view' (aka 'basic_string_view') [performance-string-view-conversions] // CHECK-FIXES: foo_sv(42, sv, 3.14); foo_sv(42, std::string("Hello, world"), 3.14); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: foo_sv(42, "Hello, world", 3.14); foo_sv(42, std::string( ( "Hello, world" ) ), 3.14); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: foo_sv(42, "Hello, world", 3.14); // TODO: support for ""sv literals foo_sv(42, "Hello, world"s, 3.14); foo_sv(42, std::string{"Hello, world"}, 3.14); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: foo_sv(42, "Hello, world", 3.14); const char *ptr = "Hello, world"; foo_sv(42, std::string(ptr), 3.14); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: foo_sv(42, ptr, 3.14); char arr[] = "Hello, world"; foo_sv(42, std::string(arr), 3.14); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: foo_sv(42, arr, 3.14); foo_sv(42, std::string(foo_sv(42)), 3.14); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: foo_sv(42, foo_sv(42), 3.14); std::string s = "hello"; foo_sv(42, std::string(s), 3.14); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: foo_sv(42, s, 3.14); foo_sv(42, std::string{s}, 3.14); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: foo_sv(42, s, 3.14); // wstring(wstring_view) // foo_wsv(42, std::wstring(wsv), 3.14); // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: redundant conversion to 'std::wstring' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: foo_wsv(42, wsv, 3.14); foo_wsv(42, std::wstring(wsv).c_str(), 3.14); // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: redundant conversion to 'const std::basic_string' and calling .c_str() and then back to 'std::wstring_view' (aka 'basic_string_view') [performance-string-view-conversions] // CHECK-FIXES: foo_wsv(42, wsv, 3.14); const wchar_t *wptr = L"Hello, world"; foo_wsv(42, std::wstring(wptr), 3.14); // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: redundant conversion to 'std::wstring' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: foo_wsv(42, wptr, 3.14); TakesStringView(0, std::string("foo")); // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: TakesStringView(0, "foo"); TakesStringView var(0, std::string("foo")); // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: TakesStringView var(0, "foo"); TakesStringView(1, std::string{"foo"}); // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: TakesStringView(1, "foo"); TakesStringView(2, std::string(std::string_view("foo"))); // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: TakesStringView(2, std::string_view("foo")); TakesStringView(3, std::string(foo_sv(42))); // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: TakesStringView(3, foo_sv(42)); StringBuilder builder; builder += std::string("hmm"); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: builder += "hmm"; builder.append(std::string("hmm")); // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: builder.append("hmm"); std::string_view{std::string(foo_sv(1))}; // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: redundant conversion to 'std::string' (aka 'basic_string') and then back to 'basic_string_view>' [performance-string-view-conversions] // CHECK-FIXES: std::string_view{foo_sv(1)}; std::string_view(std::string("hmm").data()); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: redundant conversion to 'const std::basic_string' and calling .data() and then back to 'std::string_view' (aka 'basic_string_view') [performance-string-view-conversions] // CHECK-FIXES: std::string_view("hmm"); } void negative(std::string_view sv, std::wstring_view wsv) { // No warnings expected: already string_view foo_sv(42, sv, 3.14); foo_sv(42, "Hello, world", 3.14); foo_sv(42, foo_sv(42), 3.14); // No warnings expected: complex expression foo_sv(42, std::string(sv) + "bar", 3.14); foo_sv(42, std::string( sv ) + ("foo" "bar") , 3.14); foo_sv(42, "foo" + std::string(sv), 3.14); foo_sv(42, "foo" + std::string(sv) + "bar", 3.14); foo_sv(42, std::string(sv) + std::string(sv), 3.14); foo_sv(42, std::string("foo") + std::string("bar"), 3.14); foo_sv(42, std::string(5, 'a'), 3.14); foo_sv(42, std::string("foo").append("bar"), 3.14); foo_sv(42, std::string(sv).substr(0, 5), 3.14); // No warnings expected: string parameter, not string-view foo_str(42, std::string(sv), 3.14); foo_str(42, std::string("Hello, world"), 3.14); foo_wstr(42, std::wstring(wsv), 3.14); foo_wstr(42, std::wstring(L"Hello, world"), 3.14); foo_sv(42, foo_str(42), 3.14); foo_sv(42, foo_sv(42), 3.14); // Move semantics ignored std::string s; foo_sv(42, std::move(s), 3.14); TakesStringView{0, std::move(s)}; // Inner calls are ignored foo_wsv(foo_wstr(42, "Hello, world")); foo_wsv(foo_wstr(42, std::string("Hello, world"))); // No warnings expected: string parameter of a limited length, not string-view foo_sv(142, std::string("Hello, world", 5), 3.14); TakesStringView{0, std::string("Hello, world", 5)}; }