================
@@ -0,0 +1,171 @@
+// RUN: %check_clang_tidy -std=c++17-or-later %s
performance-replace-with-string-view %t -- -- -I %S/Inputs
+
+namespace std {
+ template <typename CharT>
+ class basic_string_view {
+ public:
+ basic_string_view(const CharT *);
+ basic_string_view();
+ };
+ using string_view = basic_string_view<char>;
+ using wstring_view = basic_string_view<wchar_t>;
+ using u16string_view = basic_string_view<char16_t>;
+
+ template <typename CharT>
+ class basic_string {
+ public:
+ basic_string();
+ basic_string(const CharT *);
+ basic_string(basic_string_view<CharT>);
+
+ basic_string operator+(const basic_string &) const;
+ };
+ using string = basic_string<char>;
+ using wstring = basic_string<wchar_t>;
+ using u16string = basic_string<char16_t>;
+}
+
+// ==========================================================
+// Positive tests
+// ==========================================================
+
+std::string simpleLiteral() {
+// CHECK-MESSAGES:[[@LINE-1]]:1:
{{.*}}[performance-replace-with-string-view]{{.*}}
+// CHECK-FIXES: std::string_view{{.*}}
+ return "simpleLiteral";
+}
+
+std::string implicitView(std::string_view sv) {
+// CHECK-MESSAGES:[[@LINE-1]]:1:
{{.*}}[performance-replace-with-string-view]{{.*}}
+// CHECK-FIXES: std::string_view{{.*}}
+ return sv;
+}
+
+std::string emptyReturn() {
+// CHECK-MESSAGES:[[@LINE-1]]:1:
{{.*}}[performance-replace-with-string-view]{{.*}}
+// CHECK-FIXES: std::string_view{{.*}}
+ return {};
+}
+
+std::string switchCaseTest(int i) {
+// CHECK-MESSAGES:[[@LINE-1]]:1:
{{.*}}[performance-replace-with-string-view]{{.*}}
+// CHECK-FIXES: std::string_view{{.*}}
+ switch (i) {
+ case 1:
+ return "case1";
+ case 2:
+ return "case2";
+ case 3:
+ return {};
+ default:
+ return "default";
+ }
+}
+
+std::string ifElseTest(bool flag) {
+// CHECK-MESSAGES:[[@LINE-1]]:1:
{{.*}}[performance-replace-with-string-view]{{.*}}
+// CHECK-FIXES: std::string_view{{.*}}
+ if (flag)
+ return "true";
+ return "false";
+}
+
+std::wstring wideStringTest() {
+// CHECK-MESSAGES:[[@LINE-1]]:1:
{{.*}}[performance-replace-with-string-view]{{.*}}
+// CHECK-FIXES: std::wstring_view{{.*}}
+ return L"wide literal";
+}
+
+std::u16string u16StringTest() {
+// CHECK-MESSAGES:[[@LINE-1]]:1:
{{.*}}[performance-replace-with-string-view]{{.*}}
+// CHECK-FIXES: std::u16string_view{{.*}}
+ return u"u16 literal";
+}
+
+class A {
+ std::string classMethodInt() { return "internal"; }
+// CHECK-MESSAGES:[[@LINE-1]]:3:
{{.*}}[performance-replace-with-string-view]{{.*}}
+// CHECK-FIXES: std::string_view{{.*}}
+
+ std::string classMethodExt();
+// CHECK-MESSAGES:[[@LINE+4]]:1:
{{.*}}[performance-replace-with-string-view]{{.*}}
+// CHECK-FIXES: std::string_view{{.*}}
+};
+
+std::string A::classMethodExt() { return "external"; }
+// CHECK-FIXES: std::string_view{{.*}}
+
+// ==========================================================
+// Negative tests
+// ==========================================================
+
+std::string localVariable() {
+ std::string s = "local variable";
+ // TODO: extract and return literal
+ return s;
+}
+
+std::string dynamicCalculation() {
+ std::string s1 = "hello ";
+ return s1 + "world";
+}
+
+std::string mixedReturns(bool flag) {
+ if (flag) {
+ return "safe static literal";
+ }
+ std::string s = "unsafe dynamic";
+ return s;
+}
+
+std::string_view alreadyGood() {
+ return "alreadyGood";
+}
+
+std::string returnArgCopy(std::string s) {
+ // Must not be converted to string_view because of use-after-free on stack
+ return s;
+}
+
+std::string returnIndirection(const char* ptr) {
+ // Can be unsafe or intentional, like converting string_view into string
+ return ptr;
+}
+
+std::string localBuffer() {
+ char buf[] = "local buffer";
+ // Must not be converted to string_view because of use-after-free on stack
+ return buf;
+}
+
+std::string returnConstVar() {
+ // TODO: seems safe
+ constexpr auto kVar = "const string";
+ return kVar;
+}
+
+std::string passStringView(std::string_view sv) {
+ // Can be unsafe or intentional, like converting string_view into string
+ return std::string(sv);
+}
+
+std::string explicitConstruction() {
+ // Cannot be std::string_view: returning address of local temporary object
+ // TODO: extract and return literal
+ return std::string("explicitConstruction");
+}
+
+struct B {
+ virtual ~B() = default;
+ virtual std::string virtMethod1() { return "B::virtual1"; }
+ virtual std::string virtMethod2();
+};
+
+ std::string B::virtMethod2() { return "B::virtual2"; }
+
+struct C: public B {
+ std::string virtMethod1() override { return "C::virtual"; }
+ std::string virtMethod2() override;
+};
+
+std::string C::virtMethod2() { return "C::virtual"; }
----------------
vbvictor wrote:
Please add tests with function templates, macros, lambdas. What if function
itself templated with return `std::basic_string<T>`
Please add if not all return-stmt are literals, like
```cpp
foo() {
if (1)
return "haha"
return std::string(itoa(42))
}
```
Add tests if function has multiple declarations (possibly in headers) and one
definition
https://github.com/llvm/llvm-project/pull/172170
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits