[clang-tools-extra] [clang-tidy] Add a new check 'replace-with-string-view' (PR #172170)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
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)
@@ -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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
@@ -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)
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)
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)
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)
@@ -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)
@@ -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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
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)
@@ -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)
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)
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)
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)
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)
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)
@@ -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)
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)
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)
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)
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)
@@ -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)
@@ -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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
@@ -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)
@@ -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)
@@ -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)
@@ -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)
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)
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)
@@ -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)
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)
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)
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 =
