[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits

https://github.com/vbvictor edited 
https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,68 @@
+.. title:: clang-tidy - modernize-use-string-view
+
+modernize-use-string-view
+
+
+Looks for functions returning ``std::[w|u8|u16|u32]string`` and suggests to
+change it to ``std::[...]string_view`` for performance reasons if possible.
+
+Rationale:
+
+Each time a new ``std::string`` is created from a literal, a copy of that
+literal is allocated either in ``std::string``'s internal buffer
+(for short literals) or in a heap.
+
+For the cases where ``std::string`` is returned from a function,
+such allocations can sometimes be eliminated by using ``std::string_view``
+as a return type.
+
+This check looks for such functions returning ``std::string`` baked from the
+literals and suggests replacing their return type to ``std::string_view``.
+
+It handles ``std::string``, ``std::wstring``, ``std::u8string``,
+``std::u16string`` and ``std::u32string`` along with their aliases and selects
+the proper kind of ``std::string_view`` to return.
+
+Example:
+
+Consider the following code:
+
+.. code-block:: c++
+
+std::string foo(int i) {
+  switch(i)
+  {
+case 1:
+  return "case 1";
+case 2:
+  return "case 2";
+case 3:
+  return "case 3";
+default:
+  return "default";
+  }
+}

vbvictor wrote:

use 2-ident for code-block (same below)

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,68 @@
+.. title:: clang-tidy - modernize-use-string-view
+
+modernize-use-string-view
+
+
+Looks for functions returning ``std::[w|u8|u16|u32]string`` and suggests to
+change it to ``std::[...]string_view`` for performance reasons if possible.

vbvictor wrote:

```suggestion
Looks for functions returning ``std::[w|u8|u16|u32]string`` and suggests to
change it to ``std::[...]string_view`` if possible.
```

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,84 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "UseStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+AST_MATCHER(NamedDecl, isOperatorDecl) {
+  const DeclarationName::NameKind NK = Node.getDeclName().getNameKind();
+  return NK != DeclarationName::Identifier &&
+ NK != DeclarationName::CXXConstructorName &&
+ NK != DeclarationName::CXXDestructorName;
+}
+} // namespace
+
+static llvm::StringRef toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+static auto getStringTypeMatcher(StringRef CharType) {
+  return hasCanonicalType(hasDeclaration(cxxRecordDecl(hasName(CharType;
+}
+
+void UseStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = getStringTypeMatcher("::std::basic_string");
+  const auto IsStdStringView = 
getStringTypeMatcher("::std::basic_string_view");
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOperatorDecl(), isVirtual(,
+  returns(IsStdString), hasDescendant(returnStmt()),
+  unless(anyOf(
+  ast_matchers::isTemplateInstantiation(),
+  isExplicitTemplateSpecialization(),
+  hasDescendant(returnStmt(hasReturnValue(unless(ignoringImplicit(
+  anyOf(stringLiteral(), hasType(IsStdStringView),
+cxxConstructExpr(
+hasType(IsStdString),
+anyOf(argumentCountIs(0),
+  hasArgument(
+  0,
+  ignoringParenImpCasts(anyOf(
+  stringLiteral(),
+  
hasType(IsStdStringView)))
+  .bind("func"),
+  this);
+}
+
+void UseStringViewCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs("func");
+  assert(MatchedDecl);
+  const llvm::StringRef DestReturnTypeStr = toStringViewTypeStr(

vbvictor wrote:

```suggestion
  const StringRef DestReturnTypeStr = toStringViewTypeStr(
```

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,339 @@
+// RUN: %check_clang_tidy -std=c++20-or-later %s modernize-use-string-view %t 
-- -- -isystem %clang_tidy_headers

vbvictor wrote:

Please use this file for c++17-or-later and create new file 
`use-string-view-cxx20.cpp` to test c++20-or-later

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,84 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "UseStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+AST_MATCHER(NamedDecl, isOperatorDecl) {
+  const DeclarationName::NameKind NK = Node.getDeclName().getNameKind();
+  return NK != DeclarationName::Identifier &&
+ NK != DeclarationName::CXXConstructorName &&
+ NK != DeclarationName::CXXDestructorName;
+}
+} // namespace
+
+static llvm::StringRef toStringViewTypeStr(StringRef Type) {

vbvictor wrote:

```suggestion
static StringRef toStringViewTypeStr(StringRef Type) {
```

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,84 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "UseStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+AST_MATCHER(NamedDecl, isOperatorDecl) {
+  const DeclarationName::NameKind NK = Node.getDeclName().getNameKind();
+  return NK != DeclarationName::Identifier &&
+ NK != DeclarationName::CXXConstructorName &&
+ NK != DeclarationName::CXXDestructorName;
+}
+} // namespace
+
+static llvm::StringRef toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+static auto getStringTypeMatcher(StringRef CharType) {
+  return hasCanonicalType(hasDeclaration(cxxRecordDecl(hasName(CharType;
+}
+
+void UseStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = getStringTypeMatcher("::std::basic_string");
+  const auto IsStdStringView = 
getStringTypeMatcher("::std::basic_string_view");
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOperatorDecl(), isVirtual(,
+  returns(IsStdString), hasDescendant(returnStmt()),
+  unless(anyOf(
+  ast_matchers::isTemplateInstantiation(),
+  isExplicitTemplateSpecialization(),

vbvictor wrote:

Since we now don't match templates, lets override
```cpp
std::optional getCheckTraversalKind() const override {
return TK_IgnoreUnlessSpelledInSource;
  }
```
And I believe we can certanly remove `ast_matchers::isTemplateInstantiation()` 
and probably `isExplicitTemplateSpecialization()`

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,68 @@
+.. title:: clang-tidy - modernize-use-string-view
+
+modernize-use-string-view
+
+
+Looks for functions returning ``std::[w|u8|u16|u32]string`` and suggests to
+change it to ``std::[...]string_view`` for performance reasons if possible.
+
+Rationale:
+
+Each time a new ``std::string`` is created from a literal, a copy of that
+literal is allocated either in ``std::string``'s internal buffer
+(for short literals) or in a heap.
+
+For the cases where ``std::string`` is returned from a function,
+such allocations can sometimes be eliminated by using ``std::string_view``
+as a return type.
+
+This check looks for such functions returning ``std::string`` baked from the
+literals and suggests replacing their return type to ``std::string_view``.
+
+It handles ``std::string``, ``std::wstring``, ``std::u8string``,
+``std::u16string`` and ``std::u32string`` along with their aliases and selects
+the proper kind of ``std::string_view`` to return.
+
+Example:
+
+Consider the following code:
+
+.. code-block:: c++
+
+std::string foo(int i) {
+  switch(i)
+  {
+case 1:
+  return "case 1";
+case 2:
+  return "case 2";
+case 3:
+  return "case 3";

vbvictor wrote:

```suggestion
```
Let's make it just shorter and easier to read without any loss in functionality 
(same applied below).

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,68 @@
+.. title:: clang-tidy - modernize-use-string-view
+
+modernize-use-string-view
+
+
+Looks for functions returning ``std::[w|u8|u16|u32]string`` and suggests to
+change it to ``std::[...]string_view`` for performance reasons if possible.
+
+Rationale:
+

vbvictor wrote:

```suggestion
```
It is typically expected to have rationale in check docs, so omit it.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,68 @@
+.. title:: clang-tidy - modernize-use-string-view
+
+modernize-use-string-view
+
+
+Looks for functions returning ``std::[w|u8|u16|u32]string`` and suggests to
+change it to ``std::[...]string_view`` for performance reasons if possible.
+
+Rationale:
+
+Each time a new ``std::string`` is created from a literal, a copy of that
+literal is allocated either in ``std::string``'s internal buffer
+(for short literals) or in a heap.
+
+For the cases where ``std::string`` is returned from a function,
+such allocations can sometimes be eliminated by using ``std::string_view``
+as a return type.
+
+This check looks for such functions returning ``std::string`` baked from the
+literals and suggests replacing their return type to ``std::string_view``.
+
+It handles ``std::string``, ``std::wstring``, ``std::u8string``,
+``std::u16string`` and ``std::u32string`` along with their aliases and selects
+the proper kind of ``std::string_view`` to return.
+
+Example:
+
+Consider the following code:

vbvictor wrote:

```suggestion
Consider the following example:
```

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,68 @@
+.. title:: clang-tidy - modernize-use-string-view
+
+modernize-use-string-view
+

vbvictor wrote:

```suggestion
modernize-use-string-view
=
```

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,84 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "UseStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+AST_MATCHER(NamedDecl, isOperatorDecl) {
+  const DeclarationName::NameKind NK = Node.getDeclName().getNameKind();
+  return NK != DeclarationName::Identifier &&
+ NK != DeclarationName::CXXConstructorName &&
+ NK != DeclarationName::CXXDestructorName;
+}
+} // namespace

vbvictor wrote:

Use `cxxConversionDecl` matcher instead 
(https://clang.llvm.org/docs/LibASTMatchersReference.html)

See how it is preserved in ast https://godbolt.org/z/W355vcvrP

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,339 @@
+// RUN: %check_clang_tidy -std=c++20-or-later %s modernize-use-string-view %t 
-- -- -isystem %clang_tidy_headers
+
+#include 
+
+namespace std {
+namespace literals {
+namespace string_literals {
+  string operator""s(const char *, size_t);
+}
+namespace string_view_literals {
+  string_view operator""sv(const char *, size_t);
+}
+}
+template  struct is_same { static constexpr bool value = 
false; };
+template  struct is_same { static constexpr bool value = true; 
};
+template  constexpr bool is_same_v = is_same::value;
+} // namespace std
+
+
+// ==
+// Positive tests
+// ==
+
+std::string simpleLiteral() {
+// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::string_view' to 
avoid unnecessary copying and allocations [modernize-use-string-view]
+// CHECK-FIXES: std::string_view simpleLiteral() {
+  return "simpleLiteral";
+}
+
+std::wstring simpleLiteralW() {
+// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::wstring_view' 
to avoid unnecessary copying and allocations [modernize-use-string-view]
+// CHECK-FIXES: std::wstring_view simpleLiteralW() {
+  return L"wide literal";
+}
+
+std::u8string simpleLiteral8() {
+// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::u8string_view' 
to avoid unnecessary copying and allocations [modernize-use-string-view]
+// CHECK-FIXES: std::u8string_view simpleLiteral8() {
+  return u8"simpleLiteral";
+}
+
+std::u16string simpleLiteral16() {
+// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::u16string_view' 
to avoid unnecessary copying and allocations [modernize-use-string-view]
+// CHECK-FIXES: std::u16string_view simpleLiteral16() {
+  return u"simpleLiteral";
+}
+
+std::u32string simpleLiteral32() {
+// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::u32string_view' 
to avoid unnecessary copying and allocations [modernize-use-string-view]
+// CHECK-FIXES: std::u32string_view simpleLiteral32() {
+  return U"simpleLiteral";
+}
+
+std::string simpleRLiteral() {
+// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::string_view' to 
avoid unnecessary copying and allocations [modernize-use-string-view]
+// CHECK-FIXES: std::string_view simpleRLiteral() {
+  return R"(simpleLiteral)";
+}
+
+[[nodiscard]] std::string Attributed() {
+// CHECK-MESSAGES:[[@LINE-1]]:15: warning: consider using 'std::string_view' 
to avoid unnecessary copying and allocations [modernize-use-string-view]
+// CHECK-FIXES: {{\[\[nodiscard\]\]}} std::string_view Attributed() {
+  return "attributed";
+}
+
+const std::string Const() {
+// CHECK-MESSAGES:[[@LINE-1]]:7: warning: consider using 'std::string_view' to 
avoid unnecessary copying and allocations [modernize-use-string-view]
+// CHECK-FIXES: const std::string_view Const() {
+  return "Const";
+}
+
+auto Trailing() -> std::string {
+// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::string_view' to 
avoid unnecessary copying and allocations [modernize-use-string-view]
+// TODO: support fixes for deduced types

vbvictor wrote:

In check code, we unconditionally create a replacement:
```cpp
Diag << FixItHint::CreateReplacement(FuncDecl->getReturnTypeSourceRange(),
 DestReturnTypeStr);
```
What we replace in this case? does `getReturnTypeSourceRange()` returns an 
empty range? If it returns an empty range let's "`if`" it inside the body loop

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits

https://github.com/vbvictor edited 
https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Baranov Victor via cfe-commits

https://github.com/vbvictor commented:

Looks good, thanks for your work; however, I think we should add some options 
to tweak behavior before we can land it.

One major drawback is this pattern:

```diff
   template  std::string getArcana(const T &N) {
 return dump([&](TextNodeDumper &D) { D.Visit(N); });
   }
-  std::string getArcana(const NestedNameSpecifierLoc &NNS) { return ""; }
-  std::string getArcana(const TemplateName &NNS) { return ""; }
-  std::string getArcana(const CXXBaseSpecifier &CBS) { return ""; }
+  std::string_view getArcana(const NestedNameSpecifierLoc &NNS) { return ""; }
+  std::string_view getArcana(const TemplateName &NNS) { return ""; }
+  std::string_view getArcana(const CXXBaseSpecifier &CBS) { return ""; }
   std::string getArcana(const TemplateArgumentLoc &TAL) {
 return dump([&](TextNodeDumper &D) {
   D.Visit(TAL.getArgument(), TAL.getSourceRange());
 });
   }
   std::string getArcana(const TypeLoc &TL) {
 return dump([&](TextNodeDumper &D) { D.Visit(TL.getType()); });
   }
```

We have plenty of similar methods declared with `string` but some of them 
appear to use `std::string_view`. I'd want to leave `string` even in trivial 
cases for consistency.
So an option `AllowExplicitStringReturn` would allow manual `string` creation 
like this:
```cpp
std::string getArcana(const TemplateName &NNS) { 
return std::string{""}; // no warning
return std::string(""); // no warning
}
```
Instead of writing a bunch of `// NOLINT`
Note that `string("")` may conflict with `modernize-return-braced-init-list` 
but `string{}` won't.

Another drawback is:

```diff
-std::string toString(InvalidName::Kind K) {
+std::string_view toString(InvalidName::Kind K) {
   switch (K) {
   case InvalidName::Keywords:
 return "Keywords";
   llvm_unreachable("unhandled InvalidName kind");
 }
```

We probably want real `std::string` returned here, so I suggest the 
`IgnoredFunctions` option to handle this case (could be empty by default, and 
users would write their own functions like `to_string;toString`).
There are `IgnoredFunctions` in other options too.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Zinovy Nis via cfe-commits

irishrover wrote:

Here's what I got on the LLVM project trunk
[use-string-view.patch](https://github.com/user-attachments/files/24273974/use-string-view.patch)


https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Zinovy Nis via cfe-commits

irishrover wrote:

What's done:
- renamed to `modernize-use-string-view`
- added a lot of tests and some code had to be fixed due to that
- simplified some conditions
- minor cleanups.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From 02e40493c9f9bd8f77bdfb0fee7afd7ba3d26a1b Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH] [clang-tidy] Add a new check 'modernize-use-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/modernize/CMakeLists.txt   |   1 +
 .../modernize/ModernizeTidyModule.cpp |   3 +
 .../modernize/UseStringViewCheck.cpp  |  84 +
 .../clang-tidy/modernize/UseStringViewCheck.h |  34 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |  16 +-
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../checks/modernize/use-string-view.rst  |  68 
 .../clang-tidy/checkers/Inputs/Headers/string |  13 +
 .../checkers/modernize/use-string-view.cpp| 339 ++
 9 files changed, 554 insertions(+), 5 deletions(-)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp
 create mode 100644 clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index 488c359661018..858cf921f9d34 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -50,6 +50,7 @@ add_clang_library(clangTidyModernizeModule STATIC
   UseStdFormatCheck.cpp
   UseStdNumbersCheck.cpp
   UseStdPrintCheck.cpp
+  UseStringViewCheck.cpp
   UseTrailingReturnTypeCheck.cpp
   UseTransparentFunctorsCheck.cpp
   UseUncaughtExceptionsCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index 7224b2f32fd73..db8851159c5e8 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -51,6 +51,7 @@
 #include "UseStdFormatCheck.h"
 #include "UseStdNumbersCheck.h"
 #include "UseStdPrintCheck.h"
+#include "UseStringViewCheck.h"
 #include "UseTrailingReturnTypeCheck.h"
 #include "UseTransparentFunctorsCheck.h"
 #include "UseUncaughtExceptionsCheck.h"
@@ -131,6 +132,8 @@ class ModernizeModule : public ClangTidyModule {
 CheckFactories.registerCheck("modernize-use-noexcept");
 CheckFactories.registerCheck("modernize-use-nullptr");
 CheckFactories.registerCheck("modernize-use-override");
+CheckFactories.registerCheck(
+"modernize-use-string-view");
 CheckFactories.registerCheck(
 "modernize-use-trailing-return-type");
 CheckFactories.registerCheck(
diff --git a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp
new file mode 100644
index 0..1ccf21cad91d6
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp
@@ -0,0 +1,84 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "UseStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+AST_MATCHER(NamedDecl, isOperatorDecl) {
+  const DeclarationName::NameKind NK = Node.getDeclName().getNameKind();
+  return NK != DeclarationName::Identifier &&
+ NK != DeclarationName::CXXConstructorName &&
+ NK != DeclarationName::CXXDestructorName;
+}
+} // namespace
+
+static llvm::StringRef toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+static auto getStringTypeMatcher(StringRef CharType) {
+  return hasCanonicalType(hasDeclaration(cxxRecordDecl(hasName(CharType;
+}
+
+void UseStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = getStringTypeMatcher("::std:

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From 1547aa7559dd34ec34ec64d2c06a822262a5859b Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH] [clang-tidy] Add a new check 'modernize-use-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/modernize/CMakeLists.txt   |   1 +
 .../modernize/ModernizeTidyModule.cpp |   3 +
 .../modernize/UseStringViewCheck.cpp  |  84 +
 .../clang-tidy/modernize/UseStringViewCheck.h |  34 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |  16 +-
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../checks/modernize/use-string-view.rst  |  68 
 .../clang-tidy/checkers/Inputs/Headers/string |  13 +
 .../checkers/modernize/use-string-view.cpp| 339 ++
 9 files changed, 554 insertions(+), 5 deletions(-)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp
 create mode 100644 clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index 488c359661018..858cf921f9d34 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -50,6 +50,7 @@ add_clang_library(clangTidyModernizeModule STATIC
   UseStdFormatCheck.cpp
   UseStdNumbersCheck.cpp
   UseStdPrintCheck.cpp
+  UseStringViewCheck.cpp
   UseTrailingReturnTypeCheck.cpp
   UseTransparentFunctorsCheck.cpp
   UseUncaughtExceptionsCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index 7224b2f32fd73..db8851159c5e8 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -51,6 +51,7 @@
 #include "UseStdFormatCheck.h"
 #include "UseStdNumbersCheck.h"
 #include "UseStdPrintCheck.h"
+#include "UseStringViewCheck.h"
 #include "UseTrailingReturnTypeCheck.h"
 #include "UseTransparentFunctorsCheck.h"
 #include "UseUncaughtExceptionsCheck.h"
@@ -131,6 +132,8 @@ class ModernizeModule : public ClangTidyModule {
 CheckFactories.registerCheck("modernize-use-noexcept");
 CheckFactories.registerCheck("modernize-use-nullptr");
 CheckFactories.registerCheck("modernize-use-override");
+CheckFactories.registerCheck(
+"modernize-use-string-view");
 CheckFactories.registerCheck(
 "modernize-use-trailing-return-type");
 CheckFactories.registerCheck(
diff --git a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp
new file mode 100644
index 0..1ccf21cad91d6
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp
@@ -0,0 +1,84 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "UseStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+namespace {
+AST_MATCHER(NamedDecl, isOperatorDecl) {
+  const DeclarationName::NameKind NK = Node.getDeclName().getNameKind();
+  return NK != DeclarationName::Identifier &&
+ NK != DeclarationName::CXXConstructorName &&
+ NK != DeclarationName::CXXDestructorName;
+}
+} // namespace
+
+static llvm::StringRef toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+static auto getStringTypeMatcher(StringRef CharType) {
+  return hasCanonicalType(hasDeclaration(cxxRecordDecl(hasName(CharType;
+}
+
+void UseStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = getStringTypeMatcher("::std:

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover edited 
https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Zinovy Nis via cfe-commits


@@ -0,0 +1,67 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))

irishrover wrote:

`Type` is long and boring string like

```
std::wstring_view (C++17) | std::basic_string_view
std::u8string_view (C++20) | std::basic_string_view
std::u16string_view (C++17) | std::basic_string_view
std::u32string_view (C++17) | std::basic_string_view
```

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-20 Thread Zinovy Nis via cfe-commits


@@ -0,0 +1,67 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))

irishrover wrote:

No, `==` is not enough:
```cpp
std::string_view (C++17) | std::basic_string_view
std::wstring_view (C++17) | std::basic_string_view
std::u8string_view (C++20) | std::basic_string_view
std::u16string_view (C++17) | std::basic_string_view
std::u32string_view (C++17) | std::basic_string_view
```
See https://en.cppreference.com/w/cpp/string/basic_string_view.html

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-19 Thread Baranov Victor via cfe-commits

https://github.com/vbvictor edited 
https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-19 Thread Victor Chernyakin via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {

localspook wrote:

I believe `StringRef` has now entirely obsoleted `StringLiteral`. After 
#172765, we have no uses of `StringLiteral` left in clang-tidy.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-18 Thread Zinovy Nis via cfe-commits


@@ -0,0 +1,209 @@
+// RUN: %check_clang_tidy -std=c++17-or-later %s 
performance-replace-with-string-view %t -- -- -isystem %clang_tidy_headers
+
+#include 
+
+namespace std::literals {
+  namespace string_literals {
+string operator""s(const char *, size_t);
+  }
+  namespace string_view_literals {
+string_view operator""sv(const char *, size_t);
+  }
+}
+
+// ==
+// Positive tests
+// ==
+
+std::string simpleLiteral() {
+// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::string_view' to 
avoid unnecessary copying and allocations [performance-replace-with-string-view]
+// CHECK-FIXES: std::string_view simpleLiteral() {
+  return "simpleLiteral";
+}
+
+std::string emptyReturn() {
+// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::string_view' to 
avoid unnecessary copying and allocations [performance-replace-with-string-view]
+// CHECK-FIXES: std::string_view emptyReturn() {
+  return {};
+}
+
+std::string ctorReturn() {
+// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::string_view' to 
avoid unnecessary copying and allocations [performance-replace-with-string-view]
+// CHECK-FIXES: std::string_view ctorReturn() {
+  return std::string();
+}
+
+std::string switchCaseTest(int i) {
+// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::string_view' to 
avoid unnecessary copying and allocations [performance-replace-with-string-view]
+// CHECK-FIXES: std::string_view switchCaseTest(int i) {
+  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: warning: consider using 'std::string_view' to 
avoid unnecessary copying and allocations [performance-replace-with-string-view]
+// CHECK-FIXES: std::string_view ifElseTest(bool flag) {
+  if (flag)
+return "true";
+  return "false";
+}
+
+std::wstring wideStringTest() {
+// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::wstring_view' 
to avoid unnecessary copying and allocations 
[performance-replace-with-string-view]
+// CHECK-FIXES: std::wstring_view wideStringTest() {
+  return L"wide literal";
+}
+
+class A {
+  std::string classMethodInt() { return "internal"; }
+// CHECK-MESSAGES:[[@LINE-1]]:3: warning: consider using 'std::string_view' to 
avoid unnecessary copying and allocations [performance-replace-with-string-view]
+// CHECK-FIXES: std::string_view classMethodInt() { return "internal"; }
+
+  std::string classMethodExt();
+// CHECK-FIXES: std::string_view classMethodExt();

irishrover wrote:

Correct. The message is reported only once. But fix-hints are reported for each 
item from MatchedDecl->redecls().

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";

vbvictor wrote:

You can adjust those headers to properly handle prefixes?
Does that implementation differ a lot from yours? 

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Zinovy Nis via cfe-commits

irishrover wrote:

So I have 2 things to be done:
- rename the check
- add options for custom string types (most probably in the next PR)


https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From 3287e4251ddfb11ec36a8025f06431831a06f557 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  67 ++
 .../performance/ReplaceWithStringViewCheck.h  |  34 +++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  68 ++
 .../clang-tidy/checkers/Inputs/Headers/string |   1 +
 .../performance/replace-with-string-view.cpp  | 209 ++
 9 files changed, 390 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..fca4c75ed84a9
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,67 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), unless(cxxMethodDecl(isVirtual())),
+  returns(IsStdString), hasDescendant(retur

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Zinovy Nis via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";

irishrover wrote:

> Could you please add tests with these types?

Well... not now. Seems there're some problems with u/U/L prefixes support in 
our mock-headers.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Zinovy Nis via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,
+  returns(IsStdString), hasDescendant(returnStmt()),
+  unless(hasDescendant(
+  returnStmt(hasReturnValue(unless(ignoringImplicit(anyOf(
+  stringLiteral(), IsStdStringView,
+  cxxConstructExpr(
+  hasType(IsStdString),
+  anyOf(argumentCountIs(0),
+hasArgument(0, ignoringParenImpCasts(anyOf(
+   stringLiteral(),
+   IsStdStringView)
+  .bind("func"),
+  this);
+}
+
+void ReplaceWithStringViewCheck::check(const MatchFinder::MatchResult &Result) 
{
+  const auto *MatchedDecl = Result.Nodes.getNodeAs("func");
+  assert(MatchedDecl);
+  const llvm::StringLiteral DestReturnTypeStr =
+  toStringViewTypeStr(MatchedDecl->getReturnType()
+  .getDesugaredType(*Result.Context)
+  .getAsString());
+
+  auto Diag = diag(MatchedDecl->getReturnTypeSourceRange().getBegin(),
+   "consider using '%0' to avoid unnecessary "
+   "copying and allocations")
+  << DestReturnTypeStr << MatchedDecl;
+
+  for (const auto *FuncDecl = MatchedDecl; FuncDecl != nullptr;
+   FuncDecl = FuncDecl->getPreviousDecl()) {

irishrover wrote:

Thanks! My main project is Chromium so I often confuse code styles.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Zinovy Nis via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,
+  returns(IsStdString), hasDescendant(returnStmt()),
+  unless(hasDescendant(
+  returnStmt(hasReturnValue(unless(ignoringImplicit(anyOf(
+  stringLiteral(), IsStdStringView,
+  cxxConstructExpr(
+  hasType(IsStdString),
+  anyOf(argumentCountIs(0),
+hasArgument(0, ignoringParenImpCasts(anyOf(
+   stringLiteral(),
+   IsStdStringView)
+  .bind("func"),
+  this);
+}
+
+void ReplaceWithStringViewCheck::check(const MatchFinder::MatchResult &Result) 
{
+  const auto *MatchedDecl = Result.Nodes.getNodeAs("func");
+  assert(MatchedDecl);
+  const llvm::StringLiteral DestReturnTypeStr =
+  toStringViewTypeStr(MatchedDecl->getReturnType()
+  .getDesugaredType(*Result.Context)
+  .getAsString());
+
+  auto Diag = diag(MatchedDecl->getReturnTypeSourceRange().getBegin(),
+   "consider using '%0' to avoid unnecessary "
+   "copying and allocations")
+  << DestReturnTypeStr << MatchedDecl;

irishrover wrote:

Oops. FIxed)

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Zinovy Nis via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {

irishrover wrote:

> I'm not sure if we should use `StringRef`.
> 
> https://github.com/llvm/llvm-project/blob/f2d48dd15b2ec4781222dfb206719acaec3689fd/llvm/include/llvm/ADT/StringRef.h#L849-L850

You mean StringRef or StringLiteral?

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Baranov Victor via cfe-commits

vbvictor wrote:

> I prefer "misc-use-string-view" because there is not only one reason to use 
> it.
>
> Doesn't copy underlying string.
Cheap to copy.
Can take both std::string and string literals ("str").

I'm fine with `misc-use-string-view` since we already have 
`misc-use-internal-linkage`. But I have a gut feeling that 
`modernize-use-string-view` would be better because it brings "modernization" 
to the project (improvement in speed, readability, reusability).

---

In clang-tidy docs we have description of misc as "Checks that we didn’t have a 
better category for", so `use-string-view` feels like a modernization check to 
me.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Yanzuo Liu via cfe-commits

zwuis wrote:

> I prefer "misc-use-string-view" because there is not only one reason to use 
> it.
> 
> - Doesn't copy underlying string.
> - Cheap to copy.
> - Can take both `std::string` and string literals (`"str"`).

FYI someone suggested "modernize-use-span". #156058

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Yanzuo Liu via cfe-commits

https://github.com/zwuis edited https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Zinovy Nis via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {

irishrover wrote:

@vbvictor, what do you think of `misc-*`?


https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Yanzuo Liu via cfe-commits

https://github.com/zwuis edited https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Yanzuo Liu via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,
+  returns(IsStdString), hasDescendant(returnStmt()),
+  unless(hasDescendant(
+  returnStmt(hasReturnValue(unless(ignoringImplicit(anyOf(
+  stringLiteral(), IsStdStringView,
+  cxxConstructExpr(
+  hasType(IsStdString),
+  anyOf(argumentCountIs(0),
+hasArgument(0, ignoringParenImpCasts(anyOf(
+   stringLiteral(),
+   IsStdStringView)
+  .bind("func"),
+  this);
+}
+
+void ReplaceWithStringViewCheck::check(const MatchFinder::MatchResult &Result) 
{
+  const auto *MatchedDecl = Result.Nodes.getNodeAs("func");
+  assert(MatchedDecl);
+  const llvm::StringLiteral DestReturnTypeStr =
+  toStringViewTypeStr(MatchedDecl->getReturnType()
+  .getDesugaredType(*Result.Context)
+  .getAsString());
+
+  auto Diag = diag(MatchedDecl->getReturnTypeSourceRange().getBegin(),
+   "consider using '%0' to avoid unnecessary "
+   "copying and allocations")
+  << DestReturnTypeStr << MatchedDecl;
+
+  for (const auto *FuncDecl = MatchedDecl; FuncDecl != nullptr;
+   FuncDecl = FuncDecl->getPreviousDecl()) {

zwuis wrote:

Use `Decl::redecls()`. Functions can be redeclared after their definitions.

```cpp
void f() {}
void f();
```

---

Braces could be removed.

https://llvm.org/docs/CodingStandards.html#don-t-use-braces-on-simple-single-statement-bodies-of-if-else-loop-statements

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Yanzuo Liu via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,
+  returns(IsStdString), hasDescendant(returnStmt()),
+  unless(hasDescendant(
+  returnStmt(hasReturnValue(unless(ignoringImplicit(anyOf(
+  stringLiteral(), IsStdStringView,
+  cxxConstructExpr(
+  hasType(IsStdString),
+  anyOf(argumentCountIs(0),
+hasArgument(0, ignoringParenImpCasts(anyOf(
+   stringLiteral(),
+   IsStdStringView)
+  .bind("func"),
+  this);
+}
+
+void ReplaceWithStringViewCheck::check(const MatchFinder::MatchResult &Result) 
{
+  const auto *MatchedDecl = Result.Nodes.getNodeAs("func");
+  assert(MatchedDecl);
+  const llvm::StringLiteral DestReturnTypeStr =
+  toStringViewTypeStr(MatchedDecl->getReturnType()
+  .getDesugaredType(*Result.Context)
+  .getAsString());
+
+  auto Diag = diag(MatchedDecl->getReturnTypeSourceRange().getBegin(),
+   "consider using '%0' to avoid unnecessary "
+   "copying and allocations")
+  << DestReturnTypeStr << MatchedDecl;

zwuis wrote:

What's the output of `<< MatchedDecl`?

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Yanzuo Liu via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,

zwuis wrote:

It seems that `isVirtual()` is enough, `isOverride()` is not needed.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Yanzuo Liu via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,
+  returns(IsStdString), hasDescendant(returnStmt()),
+  unless(hasDescendant(
+  returnStmt(hasReturnValue(unless(ignoringImplicit(anyOf(
+  stringLiteral(), IsStdStringView,
+  cxxConstructExpr(
+  hasType(IsStdString),
+  anyOf(argumentCountIs(0),
+hasArgument(0, ignoringParenImpCasts(anyOf(
+   stringLiteral(),
+   IsStdStringView)
+  .bind("func"),
+  this);
+}
+
+void ReplaceWithStringViewCheck::check(const MatchFinder::MatchResult &Result) 
{
+  const auto *MatchedDecl = Result.Nodes.getNodeAs("func");
+  assert(MatchedDecl);
+  const llvm::StringLiteral DestReturnTypeStr =
+  toStringViewTypeStr(MatchedDecl->getReturnType()
+  .getDesugaredType(*Result.Context)

zwuis wrote:

We could use `QualType::getCanonicalType()` because we don't care typedefs and 
`getCanonicalType()` is faster.

https://github.com/llvm/llvm-project/blob/f2d48dd15b2ec4781222dfb206719acaec3689fd/clang/include/clang/AST/TypeBase.h#L1290-L1293

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Yanzuo Liu via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {

zwuis wrote:

I'm not sure if we should use `StringRef`.

https://github.com/llvm/llvm-project/blob/f2d48dd15b2ec4781222dfb206719acaec3689fd/llvm/include/llvm/ADT/StringRef.h#L849-L850

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Yanzuo Liu via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";

zwuis wrote:

Could you please add tests with these types?

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Yanzuo Liu via cfe-commits

https://github.com/zwuis commented:

Is it handled correctly?

```cpp
template  R f() {
  return "str";
}
template std::string f();
```

If not, we could set the traversal kind of this check to 
`TK_IgnoreUnlessSpelledInSource` to fix it. But I'm not sure if it breaks other 
tests.

---

Please add tests with literals (`"str"s` and `"str"sv`).

---

I prefer "misc-use-string-view" because there is not only one reason to use it.

- Doesn't copy underlying string.
- Cheap to copy.
- Can take both `std::string` and string literals (`"str"`).

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Yanzuo Liu via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";

zwuis wrote:

Duplicate `if`.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-17 Thread Zinovy Nis via cfe-commits

irishrover wrote:

> > Maybe it worth to merge the PR in the current state and then I'll add 
> > options support and other optimizations as separate commits not to 
> > overcomplicate this PR?
> 
> Sure, we can go like this. I'll try to re-review it soon.
> 
> For now, could we change check name to `modernize-use-string-view`, WDYT?
> 
> We have this issue #29059 to covert string to string_veiw. And I think 
> `modernize-use-string-view` check can be easily extended to convert global 
> `string a = "text"` to `string_view a = "text"`.
> 
> So it's better to give a generic name to cover more cases in the future 
> rather than having multiple smaller checks.

Yes> sure. So I move the check to modernize-* family (ironically it lived there 
initially before I submitted it here) and wait for the approvals.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-16 Thread Baranov Victor via cfe-commits

vbvictor wrote:

> Maybe it worth to merge the PR in the current state and then I'll add options 
> support and other optimizations as separate commits not to overcomplicate 
> this PR?

Sure, we can go like this.
I'll try to re-review it soon.

For now, could we change check name to `modernize-use-string-view`, WDYT?

We have this issue https://github.com/llvm/llvm-project/issues/29059 to covert 
string to string_veiw. And I think `modernize-use-string-view` check can be 
easily extended to convert global `string a = "text"` to `string_view a = 
"text"`.

So it's better to give a generic name to cover more cases in the future rather 
than having multiple smaller checks.




https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-16 Thread Zinovy Nis via cfe-commits

irishrover wrote:

Maybe it worth to merge the PR in the current state and then I'll add options 
support and other optimizations as separate commits not to overcomplicate this 
PR?

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-16 Thread Zinovy Nis via cfe-commits


@@ -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 
+  class basic_string_view {
+  public:
+basic_string_view(const CharT *);
+basic_string_view();
+  };
+  using string_view = basic_string_view;
+  using wstring_view = basic_string_view;
+  using u16string_view = basic_string_view;
+
+  template 
+  class basic_string {
+  public:
+basic_string();
+basic_string(const CharT *);
+basic_string(basic_string_view);
+
+basic_string operator+(const basic_string &) const;
+  };
+  using string = basic_string;
+  using wstring = basic_string;
+  using u16string = basic_string;
+}
+
+// ==
+// 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"; }

irishrover wrote:

```
std::string mixedReturns(bool flag) {
  if (flag) {
return "safe static literal";
  }
  std::string s = "unsafe dynamic";
  return s;
}
```

There's a case you mentioned, it's called `mixedReturns`.


https://github.com/llvm/llvm-project/pull/

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-16 Thread Zinovy Nis via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,
+  returns(IsStdString), hasDescendant(returnStmt()),

irishrover wrote:

```
std::string lambda() {
  // TODO: extract and return literal from lambda
  return []() {
 return "lambda";
  }();
}

```
is not matched. I added a `todo`

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-15 Thread via cfe-commits

github-actions[bot] wrote:


# :window: Windows x64 Test Results

The build failed before running any tests. Click on a failure below to see the 
details.


[code=1] 
tools/clang/tools/extra/clang-tidy/performance/CMakeFiles/obj.clangTidyPerformanceModule.dir/ReplaceWithStringViewCheck.cpp.obj

```
FAILED: [code=1] 
tools/clang/tools/extra/clang-tidy/performance/CMakeFiles/obj.clangTidyPerformanceModule.dir/ReplaceWithStringViewCheck.cpp.obj
sccache C:\clang\clang-msvc\bin\clang-cl.exe  /nologo -TP -DCLANG_BUILD_STATIC 
-DGTEST_HAS_RTTI=0 -DUNICODE -D_CRT_NONSTDC_NO_DEPRECATE 
-D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS 
-D_GLIBCXX_ASSERTIONS -D_HAS_EXCEPTIONS=0 -D_SCL_SECURE_NO_DEPRECATE 
-D_SCL_SECURE_NO_WARNINGS -D_UNICODE -D__STDC_CONSTANT_MACROS 
-D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS 
-Itools\clang\tools\extra\clang-tidy\performance 
-IC:\_work\llvm-project\llvm-project\clang-tools-extra\clang-tidy\performance 
-Itools\clang\tools\extra\clang-tidy 
-IC:\_work\llvm-project\llvm-project\clang\include -Itools\clang\include 
-Iinclude -IC:\_work\llvm-project\llvm-project\llvm\include /DWIN32 /D_WINDOWS  
 /Zc:inline /Zc:__cplusplus /Oi /Brepro /bigobj /permissive- 
-Werror=unguarded-availability-new /W4  -Wextra -Wno-unused-parameter 
-Wwrite-strings -Wcast-qual -Wmissing-field-initializers -Wimplicit-fallthrough 
-Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor 
-Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion 
-Wno-pass-failed -Wmisleading-indentation -Wctad-maybe-unsupported /Gw /O2 /Ob2 
 -MD  /EHs-c- /GR- -UNDEBUG -std:c++17 /showIncludes 
/Fotools\clang\tools\extra\clang-tidy\performance\CMakeFiles\obj.clangTidyPerformanceModule.dir\ReplaceWithStringViewCheck.cpp.obj
 
/Fdtools\clang\tools\extra\clang-tidy\performance\CMakeFiles\obj.clangTidyPerformanceModule.dir\
 -c -- 
C:\_work\llvm-project\llvm-project\clang-tools-extra\clang-tidy\performance\ReplaceWithStringViewCheck.cpp
C:\_work\llvm-project\llvm-project\clang-tools-extra\clang-tidy\performance\ReplaceWithStringViewCheck.cpp(75,1):
 error: extraneous closing brace ('}')
75 | } // namespace clang::tidy::performance
| ^
1 error generated.
```


If these failures are unrelated to your changes (for example tests are broken 
or flaky at HEAD), please open an issue at 
https://github.com/llvm/llvm-project/issues and add the `infrastructure` label.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-15 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff origin/main HEAD --extensions h,cpp -- 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp
 clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
--diff_from_common_commit
``

:warning:
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing `origin/main` to the base branch/commit you want to compare against.
:warning:





View the diff from clang-format here.


``diff
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
index 55978bec7..e97c53ec2 100644
--- a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -54,22 +54,22 @@ void 
ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
 void ReplaceWithStringViewCheck::check(const MatchFinder::MatchResult &Result) 
{
   const auto *MatchedDecl = Result.Nodes.getNodeAs("func");
   assert(MatchedDecl);
-const llvm::StringLiteral DestReturnTypeStr =
-toStringViewTypeStr(MatchedDecl->getReturnType()
-.getDesugaredType(*Result.Context)
-.getAsString());
+  const llvm::StringLiteral DestReturnTypeStr =
+  toStringViewTypeStr(MatchedDecl->getReturnType()
+  .getDesugaredType(*Result.Context)
+  .getAsString());
 
-auto Diag = diag(MatchedDecl->getReturnTypeSourceRange().getBegin(),
- "consider using '%0' to avoid unnecessary "
- "copying and allocations")
-<< DestReturnTypeStr << MatchedDecl;
+  auto Diag = diag(MatchedDecl->getReturnTypeSourceRange().getBegin(),
+   "consider using '%0' to avoid unnecessary "
+   "copying and allocations")
+  << DestReturnTypeStr << MatchedDecl;
 
-for (const auto *FuncDecl = MatchedDecl; FuncDecl != nullptr;
- FuncDecl = FuncDecl->getPreviousDecl()) {
-  Diag << 
FixItHint::CreateReplacement(FuncDecl->getReturnTypeSourceRange(),
-   DestReturnTypeStr);
-}
+  for (const auto *FuncDecl = MatchedDecl; FuncDecl != nullptr;
+   FuncDecl = FuncDecl->getPreviousDecl()) {
+Diag << FixItHint::CreateReplacement(FuncDecl->getReturnTypeSourceRange(),
+ DestReturnTypeStr);
   }
 }
+}
 
 } // namespace clang::tidy::performance

``




https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-15 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From 210ff50ef6a9b5185195970df6ad51587f8e1fc1 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH 1/4] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  74 
 .../performance/ReplaceWithStringViewCheck.h  |  47 +
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  68 +++
 .../performance/replace-with-string-view.cpp  | 171 ++
 8 files changed, 371 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..7f07a46ecaff4
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-15 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From 210ff50ef6a9b5185195970df6ad51587f8e1fc1 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH 1/3] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  74 
 .../performance/ReplaceWithStringViewCheck.h  |  47 +
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  68 +++
 .../performance/replace-with-string-view.cpp  | 171 ++
 8 files changed, 371 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..7f07a46ecaff4
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-15 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From 210ff50ef6a9b5185195970df6ad51587f8e1fc1 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH 1/2] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  74 
 .../performance/ReplaceWithStringViewCheck.h  |  47 +
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  68 +++
 .../performance/replace-with-string-view.cpp  | 171 ++
 8 files changed, 371 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..7f07a46ecaff4
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-15 Thread Baranov Victor via cfe-commits


@@ -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 
+  class basic_string_view {
+  public:
+basic_string_view(const CharT *);
+basic_string_view();
+  };
+  using string_view = basic_string_view;
+  using wstring_view = basic_string_view;
+  using u16string_view = basic_string_view;
+
+  template 
+  class basic_string {
+  public:
+basic_string();
+basic_string(const CharT *);
+basic_string(basic_string_view);
+
+basic_string operator+(const basic_string &) const;
+  };
+  using string = basic_string;
+  using wstring = basic_string;
+  using u16string = basic_string;
+}

vbvictor wrote:

Please reuse some already present mock-header with string and string_view

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-15 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,47 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_REPLACEWITHSTRINGVIEWCHECK_H
+#define 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_PERFORMANCE_REPLACEWITHSTRINGVIEWCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::performance {
+
+/// Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
+/// change it to `std::[...]string_view` if possible and profitable.
+///
+/// Example:
+///
+/// std::string foo(int i) { // < can be replaced to std::string_view 
f(...)
+///   switch(i) {
+/// case 1:
+///   return "case1";
+/// case 2:
+///   return "case2";
+/// default:
+///   return {};
+///   }
+/// }
+///

vbvictor wrote:

```suggestion
```

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-15 Thread Baranov Victor via cfe-commits


@@ -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 
+  class basic_string_view {
+  public:
+basic_string_view(const CharT *);
+basic_string_view();
+  };
+  using string_view = basic_string_view;
+  using wstring_view = basic_string_view;
+  using u16string_view = basic_string_view;
+
+  template 
+  class basic_string {
+  public:
+basic_string();
+basic_string(const CharT *);
+basic_string(basic_string_view);
+
+basic_string operator+(const basic_string &) const;
+  };
+  using string = basic_string;
+  using wstring = basic_string;
+  using u16string = basic_string;
+}
+
+// ==
+// 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`

Please add if not all return-stmt are literals, like

```cpp
foo() {
  if (1)
return "haha"
  return std::string(itoa(42))

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-15 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,
+  returns(IsStdString), hasDescendant(returnStmt()),
+  unless(hasDescendant(
+  returnStmt(hasReturnValue(unless(ignoringImplicit(anyOf(
+  stringLiteral(), IsStdStringView,
+  cxxConstructExpr(
+  hasType(IsStdString),
+  anyOf(argumentCountIs(0),
+hasArgument(0, ignoringParenImpCasts(anyOf(
+   stringLiteral(),
+   IsStdStringView)
+  .bind("func"),
+  this);
+}
+
+void ReplaceWithStringViewCheck::check(const MatchFinder::MatchResult &Result) 
{
+  if (const auto *MatchedDecl = Result.Nodes.getNodeAs("func")) {

vbvictor wrote:

We expect matcher to work, 
```suggestion
  const auto *MatchedDecl = Result.Nodes.getNodeAs("func");
  assert(MatchedDecl);
```

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-15 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,
+  returns(IsStdString), hasDescendant(returnStmt()),
+  unless(hasDescendant(
+  returnStmt(hasReturnValue(unless(ignoringImplicit(anyOf(
+  stringLiteral(), IsStdStringView,
+  cxxConstructExpr(
+  hasType(IsStdString),
+  anyOf(argumentCountIs(0),
+hasArgument(0, ignoringParenImpCasts(anyOf(
+   stringLiteral(),
+   IsStdStringView)
+  .bind("func"),
+  this);
+}
+
+void ReplaceWithStringViewCheck::check(const MatchFinder::MatchResult &Result) 
{
+  if (const auto *MatchedDecl = Result.Nodes.getNodeAs("func")) {
+const llvm::StringLiteral DestReturnTypeStr =
+toStringViewTypeStr(MatchedDecl->getReturnType()
+.getDesugaredType(*Result.Context)
+.getAsString());
+
+auto Diag = diag(MatchedDecl->getReturnTypeSourceRange().getBegin(),
+ "consider using `%0' to avoid unnecessary "

vbvictor wrote:

```suggestion
 "consider using '%0' to avoid unnecessary "
```

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-15 Thread Baranov Victor via cfe-commits


@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,
+  returns(IsStdString), hasDescendant(returnStmt()),

vbvictor wrote:

What if we have
```
std::string foo() {
  []() {
 return "42"; // match?
  }
}
```

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-15 Thread Baranov Victor via cfe-commits


@@ -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 
+  class basic_string_view {
+  public:
+basic_string_view(const CharT *);
+basic_string_view();
+  };
+  using string_view = basic_string_view;
+  using wstring_view = basic_string_view;
+  using u16string_view = basic_string_view;
+
+  template 
+  class basic_string {
+  public:
+basic_string();
+basic_string(const CharT *);
+basic_string(basic_string_view);
+
+basic_string operator+(const basic_string &) const;
+  };
+  using string = basic_string;
+  using wstring = basic_string;
+  using u16string = basic_string;
+}
+
+// ==
+// Positive tests
+// ==
+
+std::string simpleLiteral() {
+// CHECK-MESSAGES:[[@LINE-1]]:1: 
{{.*}}[performance-replace-with-string-view]{{.*}}
+// CHECK-FIXES: std::string_view{{.*}}

vbvictor wrote:

Please match full lines also in fixes

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-15 Thread Baranov Victor via cfe-commits


@@ -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 
+  class basic_string_view {
+  public:
+basic_string_view(const CharT *);
+basic_string_view();
+  };
+  using string_view = basic_string_view;
+  using wstring_view = basic_string_view;
+  using u16string_view = basic_string_view;
+
+  template 
+  class basic_string {
+  public:
+basic_string();
+basic_string(const CharT *);
+basic_string(basic_string_view);
+
+basic_string operator+(const basic_string &) const;
+  };
+  using string = basic_string;
+  using wstring = basic_string;
+  using u16string = basic_string;
+}
+
+// ==
+// Positive tests
+// ==
+
+std::string simpleLiteral() {
+// CHECK-MESSAGES:[[@LINE-1]]:1: 
{{.*}}[performance-replace-with-string-view]{{.*}}

vbvictor wrote:

Please match full meaningful messages here, don't use `{{.*}}`.
We need to check that warning is produces with correct wording of "string_view" 
like "wstring_view"

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-15 Thread Baranov Victor via cfe-commits

vbvictor wrote:

> How about custom classes like `StringRef` in LLVM?

Yes, we should add option `ReplacementStringViewClass` for users to specify a 
custom pre C++-17 class for string_view. It could be `boost::string_view` also, 
which could be used extensively in pre C++-17 codebases.


https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From 210ff50ef6a9b5185195970df6ad51587f8e1fc1 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  74 
 .../performance/ReplaceWithStringViewCheck.h  |  47 +
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  68 +++
 .../performance/replace-with-string-view.cpp  | 171 ++
 8 files changed, 371 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..7f07a46ecaff4
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,
+   

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread via cfe-commits

https://github.com/zeyi2 requested changes to this pull request.


https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread via cfe-commits


@@ -0,0 +1,68 @@
+.. title:: clang-tidy - performance-replace-with-string-view
+
+performance-replace-with-string-view
+
+
+Looks for functions returning ``std::[w|u8|u16|u32]string`` and suggests to
+change it to ``std::[...]string_view`` for performance reasons if possible.
+
+Rationale:
+
+Each time a new ``std::string`` is created from a literal, a copy of that
+literal is allocated either in ``std::string``'s internal buffer
+(for short literals) or in a heap.
+
+For the cases where ``std::string`` is returned from a function,
+such allocations can be eliminated sometimes by using ``std::string_view``
+as a return type.
+
+This check looks for such functions returning ``std::string``
+baked from the literals and suggests replacing the return type to 
``std::string_view``.

zeyi2 wrote:

This line seems longer than 80 chars, please maintain 80 chars limit :)

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From 4bb31cbed54de842481562e2af4dd88a4ba7499d Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  74 
 .../performance/ReplaceWithStringViewCheck.h  |  47 +
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  68 +++
 .../performance/replace-with-string-view.cpp  | 171 ++
 8 files changed, 371 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..7f07a46ecaff4
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,
+   

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

irishrover wrote:

In the last commit I added checks for virtual/override methods - seems they 
should be ignored.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From b52149f48527ec43a5a5279db31322f77ac88dfb Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  74 
 .../performance/ReplaceWithStringViewCheck.h  |  47 +
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  68 
 .../performance/replace-with-string-view.cpp  | 165 ++
 8 files changed, 365 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..7f07a46ecaff4
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(),
+  unless(cxxMethodDecl(anyOf(isOverride(), isVirtual(,
+  

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From e00b44535d6212247013e931631cc8e75e486ba8 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  72 
 .../performance/ReplaceWithStringViewCheck.h  |  47 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  68 
 .../performance/replace-with-string-view.cpp  | 156 ++
 8 files changed, 354 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..08d0a15f7a2ab
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,72 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), returns(IsStdString), hasDescendant(returnStmt()),
+  unless(h

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From fc2bccf7a15b4978efe87bfc5ec73a0bb809771d Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH 1/2] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  72 
 .../performance/ReplaceWithStringViewCheck.h  |  47 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  68 
 .../performance/replace-with-string-view.cpp  | 156 ++
 8 files changed, 354 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..08d0a15f7a2ab
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,72 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), returns(IsStdString), hasDescendant(returnStmt()),
+  unle

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread via cfe-commits


@@ -0,0 +1,68 @@
+.. title:: clang-tidy - performance-replace-with-string-view
+
+performance-replace-with-string-view
+
+
+Looks for functions returning ``std::[w|u8|u16|u32]string`` and suggests to
+change it to ``std::[...]string_view`` for performance reasons if possible.
+
+Rationale:
+
+Each time a new ``std::string`` is created from a literal, a copy of that
+literal is allocated either in ``std::string``'s internal buffer
+(for short literals) or in a heap.
+
+For the cases where ``std::string`` is returned from a function,
+such allocations can be eliminated sometimes by using ``std::string_view``
+as a return type.
+
+This check looks for such functions returning ``std::string``
+baked from the literals and suggests replacing the return type to 
``std::string_view``.
+
+It handles ``std::string``, ``std::wstring``, ``std::u8string``,
+``std::u16string`` and ``std::u32string`` along with their aliases and selects
+the proper kind of ``std::string_view`` to return.
+
+Example:
+
+Consider the following code:
+
+.. code-block:: c++
+
+std::string foo(int i) {
+  switch(i)
+  {
+case 1:
+  return "case 1";
+case 2:
+  return "case 2";
+case 3:
+  return "case 3";
+default:
+  return "default";
+  }
+}
+
+In the code above a new ``std::string`` object is created on each
+function invocation, making a copy of a string literal and possibly
+allocating a memory in a heap.

EugeneZelenko wrote:

```suggestion
In the code above a new ``std::string`` object is created on each function
invocation, making a copy of a string literal and possibly allocating a memory
in a heap.
```

Please use as much space in 80-characters limit as possible.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From fc2bccf7a15b4978efe87bfc5ec73a0bb809771d Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  72 
 .../performance/ReplaceWithStringViewCheck.h  |  47 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  68 
 .../performance/replace-with-string-view.cpp  | 156 ++
 8 files changed, 354 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..08d0a15f7a2ab
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,72 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), returns(IsStdString), hasDescendant(returnStmt()),
+  unless(h

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From eb95ffdff26a5272d5b1552f60c118bd62e8c231 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH 1/3] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  72 
 .../performance/ReplaceWithStringViewCheck.h  |  47 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  68 
 .../performance/replace-with-string-view.cpp  | 156 ++
 8 files changed, 354 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..08d0a15f7a2ab
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,72 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), returns(IsStdString), hasDescendant(returnStmt()),
+  unle

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From eb95ffdff26a5272d5b1552f60c118bd62e8c231 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH 1/2] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  72 
 .../performance/ReplaceWithStringViewCheck.h  |  47 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  68 
 .../performance/replace-with-string-view.cpp  | 156 ++
 8 files changed, 354 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..08d0a15f7a2ab
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,72 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), returns(IsStdString), hasDescendant(returnStmt()),
+  unle

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From eb95ffdff26a5272d5b1552f60c118bd62e8c231 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  72 
 .../performance/ReplaceWithStringViewCheck.h  |  47 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  68 
 .../performance/replace-with-string-view.cpp  | 156 ++
 8 files changed, 354 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..08d0a15f7a2ab
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,72 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), returns(IsStdString), hasDescendant(returnStmt()),
+  unless(h

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread via cfe-commits


@@ -244,6 +244,12 @@ New checks
   Finds virtual function overrides with different visibility than the function
   in the base class.
 
+- New :doc:`performance-replace-with-string-view
+  ` check.
+
+  Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
+  change it to `std::[...]string_view` for performance reasons if possible.

EugeneZelenko wrote:

```suggestion
  Looks for functions returning ``std::[w|u8|u16|u32]string`` and suggests to
  change it to ``std::[...]string_view`` for performance reasons if possible.
```

Double back-ticks for language constructs.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread via cfe-commits


@@ -0,0 +1,68 @@
+.. title:: clang-tidy - performance-replace-with-string-view
+
+performance-replace-with-string-view
+
+
+Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
+change it to `std::[...]string_view` for performance reasons if possible.

EugeneZelenko wrote:

```suggestion
Looks for functions returning ``std::[w|u8|u16|u32]string`` and suggests to
change it to ``std::[...]string_view`` for performance reasons if possible.
```

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

irishrover wrote:

> How about custom classes like `StringRef` in LLVM?

Maybe add an option with for a destination type and set the default to 
`std::string_view`?

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From daec0d3666b26d53667ce29ff924af24d36db748 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  72 +
 .../performance/ReplaceWithStringViewCheck.h  |  47 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  68 +
 .../performance/replace-with-string-view.cpp  | 143 ++
 8 files changed, 341 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..08d0a15f7a2ab
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,72 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), returns(IsStdString), hasDescendant(returnStmt()),
+  unless

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover edited 
https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From a6c418cee372d84760131b742e36efabda7310e2 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

```cpp
 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
```
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  72 +
 .../performance/ReplaceWithStringViewCheck.h  |  47 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  60 
 .../performance/replace-with-string-view.cpp  | 143 ++
 8 files changed, 333 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..08d0a15f7a2ab
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,72 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), returns(IsStdString), hasDescendant(returnStmt()),
+  unless(

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From 09f1a37c5771a756138f07fc68563f7c73e13bfe Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

 std::string foo(int i) { // < can be replaced to `std::string_view 
foo(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  72 +
 .../performance/ReplaceWithStringViewCheck.h  |  47 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  60 
 .../performance/replace-with-string-view.cpp  | 143 ++
 8 files changed, 333 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..08d0a15f7a2ab
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,72 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), returns(IsStdString), hasDescendant(returnStmt()),
+  unless(hasDescenda

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-14 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From 115fb27a6e6f595c7455b54ddbe0d69b59b5df26 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

 std::string foo(int i) { // < can be replaced to `std::string_view f(...) 
{`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  72 +
 .../performance/ReplaceWithStringViewCheck.h  |  47 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  60 
 .../performance/replace-with-string-view.cpp  | 143 ++
 8 files changed, 333 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..08d0a15f7a2ab
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,72 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+static llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), returns(IsStdString), hasDescendant(returnStmt()),
+  unless(hasDescendant

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From 7f9424ab7955031ca3ee343dafa27b4186f5bd48 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH 1/4] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

 std::string foo(int i) { // < can be replaced to `std::string_view f(...) 
{`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  74 +
 .../performance/ReplaceWithStringViewCheck.h  |  47 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  60 
 .../performance/replace-with-string-view.cpp  | 142 ++
 8 files changed, 334 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..0cb11cda8e1aa
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+namespace {
+llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+} // namespace
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), returns(IsStdString), hasDescendant(returnStmt()),
+

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From 7f9424ab7955031ca3ee343dafa27b4186f5bd48 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH 1/3] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

 std::string foo(int i) { // < can be replaced to `std::string_view f(...) 
{`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  74 +
 .../performance/ReplaceWithStringViewCheck.h  |  47 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  60 
 .../performance/replace-with-string-view.cpp  | 142 ++
 8 files changed, 334 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..0cb11cda8e1aa
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+namespace {
+llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+} // namespace
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), returns(IsStdString), hasDescendant(returnStmt()),
+

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover updated 
https://github.com/llvm/llvm-project/pull/172170

>From 7f9424ab7955031ca3ee343dafa27b4186f5bd48 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH 1/2] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

 std::string foo(int i) { // < can be replaced to `std::string_view f(...) 
{`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  74 +
 .../performance/ReplaceWithStringViewCheck.h  |  47 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  60 
 .../performance/replace-with-string-view.cpp  | 142 ++
 8 files changed, 334 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..0cb11cda8e1aa
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+namespace {
+llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+} // namespace
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), returns(IsStdString), hasDescendant(returnStmt()),
+

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover edited 
https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover edited 
https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread via cfe-commits


@@ -244,6 +244,12 @@ New checks
   Finds virtual function overrides with different visibility than the function
   in the base class.
 
+- New :doc:`performance-replace-with-string-view
+  ` check.
+
+  Detects functions returning std::[w|u8|u16|u32]string where
+  return type can be changed to std::[...]string_view.

EugeneZelenko wrote:

```suggestion
  Detects functions returning ``std::[w|u8|u16|u32]string`` where
  return type can be changed to ``std::[...]string_view``.
```

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread via cfe-commits


@@ -0,0 +1,142 @@
+// RUN: %check_clang_tidy -std=c++17-or-later %s 
performance-replace-with-string-view %t -- -- -I %S/Inputs
+
+namespace std {
+  template 
+  class basic_string_view {
+  public:
+basic_string_view(const CharT *);
+basic_string_view();
+  };
+  using string_view = basic_string_view;
+  using wstring_view = basic_string_view;
+  using u16string_view = basic_string_view;
+
+  template 
+  class basic_string {
+  public:
+basic_string();
+basic_string(const CharT *);
+basic_string(basic_string_view);
+
+basic_string operator+(const basic_string &) const;
+  };
+  using string = basic_string;
+  using wstring = basic_string;
+  using u16string = basic_string;
+}
+
+// ==
+// 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";
+  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) {
+  return s;
+}
+
+std::string returnIndirection(const char* ptr) {
+  // TODO: should be convertible to std::string_view
+  return ptr;
+}
+
+std::string passStringView(std::string_view sv) {
+  // TODO: should be convertible to std::string_view
+  return std::string(sv);
+}
+
+std::string explicitConstruction() {
+   // Cannot be std::string_view: returning address of local temporary object
+  return std::string("explicitConstruction");
+}
+

EugeneZelenko wrote:

Excessive new line.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread via cfe-commits


@@ -0,0 +1,60 @@
+.. title:: clang-tidy - performance-replace-with-string-view
+
+performance-replace-with-string-view
+
+
+Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
+change it to `std::[...]string_view` for performance reasons.
+
+Rationale:
+
+Each time a new ``std::string`` is created from a literal, a copy of that
+literal is allocated either in ``std::string``'s internal buffer
+(for short literals) or in a heap.
+
+For the cases where ``std::string`` is returned from a function,
+such allocations can be eliminated sometimes by using std::string_view

EugeneZelenko wrote:

```suggestion
such allocations can be eliminated sometimes by using ``std::string_view``
```

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread via cfe-commits


@@ -0,0 +1,60 @@
+.. title:: clang-tidy - performance-replace-with-string-view
+
+performance-replace-with-string-view
+
+
+Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
+change it to `std::[...]string_view` for performance reasons.
+
+Rationale:
+
+Each time a new ``std::string`` is created from a literal, a copy of that
+literal is allocated either in ``std::string``'s internal buffer
+(for short literals) or in a heap.
+
+For the cases where ``std::string`` is returned from a function,
+such allocations can be eliminated sometimes by using std::string_view
+as a return type.
+
+This check looks for such functions returning ``std::string``
+baked from the literals and suggests replacing the return type to 
``std::string_view``.
+
+It handles std::string,std::wstring, std::u8string, std::u16string and
+std::u16string and properly selects the kind of std::string_view to return.

EugeneZelenko wrote:

```suggestion
It handles ``std::string``, ``std::wstring``, ``std::u8string``, 
``std::u16string`` and
``std::u16string`` and properly selects the kind of ``std::string_view`` to 
return.
```

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread via cfe-commits

https://github.com/EugeneZelenko edited 
https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread via cfe-commits

https://github.com/EugeneZelenko commented:

How about custom classes like `StringRef` in LLVM?

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread via cfe-commits


@@ -0,0 +1,60 @@
+.. title:: clang-tidy - performance-replace-with-string-view
+
+performance-replace-with-string-view
+
+
+Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
+change it to `std::[...]string_view` for performance reasons.

EugeneZelenko wrote:

Please synchronize with statement in Release Notes.

https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code linter, clang-tidy found issues in your code. :warning:



You can test this locally with the following command:


```bash

git diff -U0 origin/main...HEAD -- 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h 
clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp |
python3 clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py   -path build -p1 
-quiet
```





View the output from clang-tidy here.


```
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp:17:21: 
warning: function 'toStringViewTypeStr' is declared in an anonymous namespace; 
prefer using 'static' for restricting visibility 
[llvm-prefer-static-over-anonymous-namespace]
   17 | llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
  | ^
```




https://github.com/llvm/llvm-project/pull/172170
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-tools-extra

Author: Zinovy Nis (irishrover)


Changes

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to 
change it to `std::[...]string_view` if possible and profitable.

 Example:

 std::string foo(int i) { // < can be replaced to `std::string_view 
f(...) {`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }

---
Full diff: https://github.com/llvm/llvm-project/pull/172170.diff


8 Files Affected:

- (modified) clang-tools-extra/clang-tidy/performance/CMakeLists.txt (+1) 
- (modified) clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
(+3) 
- (added) 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp (+74) 
- (added) clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h 
(+47) 
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+6) 
- (modified) clang-tools-extra/docs/clang-tidy/checks/list.rst (+1) 
- (added) 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 (+60) 
- (added) 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp
 (+142) 


``diff
diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..0cb11cda8e1aa
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+namespace {
+llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+} // namespace
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string";
+  const auto IsStdStringView = expr(hasType(hasCanonicalType(
+  hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"));
+
+  Finder->addMatcher(
+  functionDecl(
+  isDefinition(), returns(IsStdString), hasDescendant(returnStmt()),
+  unless(hasDescendant(
+  returnStmt(hasReturnValue(unless(ignoringImplicit(anyOf(
+  stringLiteral(), IsStdStringView,
+  cxxConstructExpr(
+  hasType(IsStdString),
+  anyOf(argumentCountIs(0),
+hasArgum

[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)

2025-12-13 Thread Zinovy Nis via cfe-commits

https://github.com/irishrover created 
https://github.com/llvm/llvm-project/pull/172170

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to 
change it to `std::[...]string_view` if possible and profitable.

 Example:

 std::string foo(int i) { // < can be replaced to `std::string_view f(...) 
{`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }

>From 7f9424ab7955031ca3ee343dafa27b4186f5bd48 Mon Sep 17 00:00:00 2001
From: Zinovy Nis 
Date: Sat, 13 Dec 2025 13:47:01 +0300
Subject: [PATCH] [clang-tidy] Add a new check 'replace-with-string-view'

Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to
change it to `std::[...]string_view` if possible and profitable.

 Example:

 std::string foo(int i) { // < can be replaced to `std::string_view f(...) 
{`
   switch(i) {
 case 1:
   return "case1";
 case 2:
   return "case2";
 default:
   return {};
   }
 }
---
 .../clang-tidy/performance/CMakeLists.txt |   1 +
 .../performance/PerformanceTidyModule.cpp |   3 +
 .../ReplaceWithStringViewCheck.cpp|  74 +
 .../performance/ReplaceWithStringViewCheck.h  |  47 ++
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 .../performance/replace-with-string-view.rst  |  60 
 .../performance/replace-with-string-view.cpp  | 142 ++
 8 files changed, 334 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/performance/replace-with-string-view.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/performance/replace-with-string-view.cpp

diff --git a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
index 9a2f90069edbf..21a9442be69c0 100644
--- a/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/performance/CMakeLists.txt
@@ -21,6 +21,7 @@ add_clang_library(clangTidyPerformanceModule STATIC
   NoexceptMoveConstructorCheck.cpp
   NoexceptSwapCheck.cpp
   PerformanceTidyModule.cpp
+  ReplaceWithStringViewCheck.cpp
   TriviallyDestructibleCheck.cpp
   TypePromotionInMathFnCheck.cpp
   UnnecessaryCopyInitializationCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp 
b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
index 3497ea7316c6b..e17bfc42be58f 100644
--- a/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/performance/PerformanceTidyModule.cpp
@@ -24,6 +24,7 @@
 #include "NoexceptDestructorCheck.h"
 #include "NoexceptMoveConstructorCheck.h"
 #include "NoexceptSwapCheck.h"
+#include "ReplaceWithStringViewCheck.h"
 #include "TriviallyDestructibleCheck.h"
 #include "TypePromotionInMathFnCheck.h"
 #include "UnnecessaryCopyInitializationCheck.h"
@@ -62,6 +63,8 @@ class PerformanceModule : public ClangTidyModule {
 "performance-noexcept-move-constructor");
 CheckFactories.registerCheck(
 "performance-noexcept-swap");
+CheckFactories.registerCheck(
+"performance-replace-with-string-view");
 CheckFactories.registerCheck(
 "performance-trivially-destructible");
 CheckFactories.registerCheck(
diff --git 
a/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
new file mode 100644
index 0..0cb11cda8e1aa
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/performance/ReplaceWithStringViewCheck.cpp
@@ -0,0 +1,74 @@
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "ReplaceWithStringViewCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::performance {
+
+namespace {
+llvm::StringLiteral toStringViewTypeStr(StringRef Type) {
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("wchar_t"))
+return "std::wstring_view";
+  if (Type.contains("char8_t"))
+return "std::u8string_view";
+  if (Type.contains("char16_t"))
+return "std::u16string_view";
+  if (Type.contains("char32_t"))
+return "std::u32string_view";
+  return "std::string_view";
+}
+} // namespace
+
+void ReplaceWithStringViewCheck::registerMatchers(MatchFinder *Finder) {
+  const auto IsStdString = 

  1   2   >