================
@@ -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

Reply via email to