https://github.com/irishrover updated https://github.com/llvm/llvm-project/pull/172170
>From 1fee7b64e24f811b868ce4efec001fd49d51971d Mon Sep 17 00:00:00 2001 From: Zinovy Nis <[email protected]> Date: Sat, 13 Dec 2025 13:47:01 +0300 Subject: [PATCH 1/6] [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<UseNoexceptCheck>("modernize-use-noexcept"); CheckFactories.registerCheck<UseNullptrCheck>("modernize-use-nullptr"); CheckFactories.registerCheck<UseOverrideCheck>("modernize-use-override"); + CheckFactories.registerCheck<UseStringViewCheck>( + "modernize-use-string-view"); CheckFactories.registerCheck<UseTrailingReturnTypeCheck>( "modernize-use-trailing-return-type"); CheckFactories.registerCheck<UseTransparentFunctorsCheck>( 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 0000000000000..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::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<FunctionDecl>("func"); + assert(MatchedDecl); + const llvm::StringRef DestReturnTypeStr = toStringViewTypeStr( + MatchedDecl->getReturnType().getCanonicalType().getAsString()); + + auto Diag = diag(MatchedDecl->getTypeSpecStartLoc(), + "consider using '%0' to avoid unnecessary " + "copying and allocations") + << DestReturnTypeStr; + + for (const auto *FuncDecl : MatchedDecl->redecls()) + Diag << FixItHint::CreateReplacement(FuncDecl->getReturnTypeSourceRange(), + DestReturnTypeStr); +} + +} // namespace clang::tidy::modernize diff --git a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.h b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.h new file mode 100644 index 0000000000000..056bcd823a1ac --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// 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_MODERNIZE_USESTRINGVIEWCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USESTRINGVIEWCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::modernize { + +/// Looks for functions returning `std::[w|u8|u16|u32]string` and suggests to +/// change it to `std::[...]string_view` if possible and profitable. +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/modernize/use-string-view.html +class UseStringViewCheck : public ClangTidyCheck { +public: + UseStringViewCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus17; + } +}; + +} // namespace clang::tidy::modernize + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USESTRINGVIEWCHECK_H diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 924b2c03cfd18..da5745a235711 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -107,10 +107,10 @@ Hover Code completion ^^^^^^^^^^^^^^^ -- Added a new ``MacroFilter`` configuration option to ``Completion`` to - allow fuzzy-matching with the ``FuzzyMatch`` option when suggesting - macros. ``ExactPrefix`` is the default, which retains previous - behavior of suggesting macros which match the prefix exactly. +- Added a new ``MacroFilter`` configuration option to ``Completion`` to + allow fuzzy-matching with the ``FuzzyMatch`` option when suggesting + macros. ``ExactPrefix`` is the default, which retains previous + behavior of suggesting macros which match the prefix exactly. Code actions ^^^^^^^^^^^^ @@ -201,7 +201,7 @@ Improvements to clang-tidy - Improved :program:`clang-tidy` by adding the `--removed-arg` option to remove arguments sent to the compiler when invoking Clang-Tidy. This option was also - added to :program:`run-clang-tidy.py` and :program:`clang-tidy-diff.py` and + added to :program:`run-clang-tidy.py` and :program:`clang-tidy-diff.py` and can be configured in the config file through the `RemovedArgs` option. - Deprecated the :program:`clang-tidy` ``zircon`` module. All checks have been @@ -261,6 +261,12 @@ New checks Finds virtual function overrides with different visibility than the function in the base class. +- New :doc:`modernize-use-string-view + <clang-tidy/checks/modernize/use-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. + - New :doc:`readability-redundant-parentheses <clang-tidy/checks/readability/redundant-parentheses>` check. diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index e5e77b5cc418b..d61316f022a8c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -330,6 +330,7 @@ Clang-Tidy Checks :doc:`modernize-use-std-format <modernize/use-std-format>`, "Yes" :doc:`modernize-use-std-numbers <modernize/use-std-numbers>`, "Yes" :doc:`modernize-use-std-print <modernize/use-std-print>`, "Yes" + :doc:`modernize-use-string-view <modernize/use-string-view>`, "Yes" :doc:`modernize-use-trailing-return-type <modernize/use-trailing-return-type>`, "Yes" :doc:`modernize-use-transparent-functors <modernize/use-transparent-functors>`, "Yes" :doc:`modernize-use-uncaught-exceptions <modernize/use-uncaught-exceptions>`, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst new file mode 100644 index 0000000000000..1b3bdc58db5ab --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst @@ -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"; + } + } + +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. + +The check gets this code transformed into: + +.. code-block:: c++ + + std::string_view foo(int i) { + switch(i) + { + case 1: + return "case 1"; + case 2: + return "case 2"; + case 3: + return "case 3"; + default: + return "default"; + } + } + +New version re-uses statically allocated literals without additional overhead. diff --git a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string index 6cedda4202f14..c792b6e43836a 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string +++ b/clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/string @@ -22,6 +22,7 @@ struct basic_string { typedef size_t size_type; typedef basic_string<C, T, A> _Type; basic_string(); + basic_string(basic_string_view<C, T>); basic_string(const C *p, const A &a = A()); basic_string(const C *p, size_type count); basic_string(const C *b, const C *e); @@ -90,8 +91,14 @@ struct basic_string { typedef basic_string<char> string; typedef basic_string<wchar_t> wstring; +#if __cplusplus >= 202002L +typedef basic_string<char8_t> u8string; +typedef basic_string<char16_t> u16string; +typedef basic_string<char32_t> u32string; +#else typedef basic_string<char16> u16string; typedef basic_string<char32> u32string; +#endif template <typename C, typename T> struct basic_string_view { @@ -136,8 +143,14 @@ struct basic_string_view { typedef basic_string_view<char> string_view; typedef basic_string_view<wchar_t> wstring_view; +#if __cplusplus >= 202002L +typedef basic_string_view<char8_t> u8string_view; +typedef basic_string_view<char16_t> u16string_view; +typedef basic_string_view<char32_t> u32string_view; +#else typedef basic_string_view<char16> u16string_view; typedef basic_string_view<char32> u32string_view; +#endif std::string operator+(const std::string&, const std::string&); std::string operator+(const std::string&, const char*); diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view.cpp new file mode 100644 index 0000000000000..b90f36eec26cc --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view.cpp @@ -0,0 +1,339 @@ +// RUN: %check_clang_tidy -std=c++20-or-later %s modernize-use-string-view %t -- -- -isystem %clang_tidy_headers + +#include <string> + +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 <class T, class U> struct is_same { static constexpr bool value = false; }; +template <class T> struct is_same<T, T> { static constexpr bool value = true; }; +template <class T, class U> constexpr bool is_same_v = is_same<T, U>::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 + return "Trailing"; +} + +std::string emptyReturn() { +// 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 emptyReturn() { + return {}; +} + +std::string ctorReturn() { +// 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 ctorReturn() { + return std::string(); +} + +std::string initList() { +// 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 initList() { + return {"list"}; +} + +std::string switchCaseTest(int i) { +// 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 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 [modernize-use-string-view] +// CHECK-FIXES: std::string_view ifElseTest(bool flag) { + if (flag) + return "true"; + return "false"; +} + +class A { + std::string classMethodInt() { return "internal"; } +// CHECK-MESSAGES:[[@LINE-1]]:3: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view] +// CHECK-FIXES: std::string_view classMethodInt() { return "internal"; } + + std::string classMethodExt(); +// CHECK-FIXES: std::string_view classMethodExt(); +}; + +std::string A::classMethodExt() { return "external"; } +// 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 A::classMethodExt() { return "external"; } + +#define MACRO "MACRO LITERAL" +std::string macro() { +// 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 macro() { + return MACRO; +} + +#define my_string std::string +my_string macro_type() { +// 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 macro_type() { + return "MACTO LITERAL"; +} + +// ========================================================== +// 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 ternary(bool flag) { + return flag ? "true" : "false"; +} + +std::string_view alreadyGood() { + return "alreadyGood"; +} + +std::wstring_view alreadyGoodW() { + return L"alreadyGood"; +} + +std::u8string_view alreadyGoodU8() { + return u8"alreadyGood"; +} + +std::u16string_view alreadyGoodU16() { + return u"alreadyGood"; +} + +std::u32string_view alreadyGoodU32() { + return U"alreadyGood"; +} + +std::string simpleLiteralS() { + // TODO: replace ""s to literal and return string_view + using namespace std::literals::string_literals; + return "simpleLiteral"s; +} + +std::string_view alreadyGoodSV() { + using namespace std::literals::string_view_literals; + return "alreadyGood"sv; +} + +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"; } + +std::string lambda() { + // TODO: extract and return literal from lambda + return []() { + return "lambda"; + }(); +} + +struct TemplateString { + static constexpr char* val = "TEMPLATE"; + template<typename T> + // TODO: extract and return literal + std::string templateFunc() { return T::val; } + std::string templateFuncCall() { + return templateFunc<TemplateString>(); + } +}; + +template <class T> +std::basic_string<T> templateStringConditional() { + if constexpr(std::is_same_v<T, wchar_t>) { + return L"TEMPLATE"; + } else { + return "TEMPLATE"; + } +} + +template <class T> +std::basic_string<T> templateStringMixedConditional() { + if constexpr(std::is_same_v<T, wchar_t>) { + return L"TEMPLATE"; + } else { + std::string s = "haha"; + return s; + } +} + +void UseTemplateStringConditional() { + templateStringConditional<char>(); + templateStringConditional<wchar_t>(); + + templateStringMixedConditional<char>(); + templateStringMixedConditional<wchar_t>(); +} + +std::string& Ref() { + static std::string s = "Ref"; + return s; +} + +const std::string& ConstRef() { + static std::string s = "ConstRef"; + return s; +} + +auto autoReturn() { + // Deduced to const char* + return "autoReturn"; +} + +template <class T> +std::basic_string<T> templateString() { +// Intentionally skip templates + return L"TEMPLATE"; +} +std::wstring returnTemplateString() { + return templateString<wchar_t>(); +} + +template <typename R> R f() { +// Intentionally skip templates + return "str"; +} +template std::string f(); + +struct stringOperator { + operator std::string() const { + return "conversion"; + } +}; + +std::string safeFunctionWithLambda() { + auto lambda = []() -> std::string { + std::string local = "unsafe"; + return local; + }; + // TODO: fix hasDescendant(returnStmt(hasReturnValue... which is too strict + return "safe literal"; +} \ No newline at end of file >From 754547f8c6bf480c82fae1b24358d6cd3bda34f2 Mon Sep 17 00:00:00 2001 From: Zinovy Nis <[email protected]> Date: Sun, 21 Dec 2025 10:24:51 +0300 Subject: [PATCH 2/6] Auto-fix remarks Co-authored-by: Baranov Victor <[email protected]> --- .../clang-tidy/modernize/UseStringViewCheck.cpp | 4 ++-- .../clang-tidy/checks/modernize/use-string-view.rst | 12 ++---------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp index 1ccf21cad91d6..0bfc56d2fbd0c 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp @@ -23,7 +23,7 @@ AST_MATCHER(NamedDecl, isOperatorDecl) { } } // namespace -static llvm::StringRef toStringViewTypeStr(StringRef Type) { +static StringRef toStringViewTypeStr(StringRef Type) { if (Type.contains("wchar_t")) return "std::wstring_view"; if (Type.contains("char8_t")) @@ -68,7 +68,7 @@ void UseStringViewCheck::registerMatchers(MatchFinder *Finder) { void UseStringViewCheck::check(const MatchFinder::MatchResult &Result) { const auto *MatchedDecl = Result.Nodes.getNodeAs<FunctionDecl>("func"); assert(MatchedDecl); - const llvm::StringRef DestReturnTypeStr = toStringViewTypeStr( + const StringRef DestReturnTypeStr = toStringViewTypeStr( MatchedDecl->getReturnType().getCanonicalType().getAsString()); auto Diag = diag(MatchedDecl->getTypeSpecStartLoc(), diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst index 1b3bdc58db5ab..70dd2726e5f0a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst @@ -1,13 +1,11 @@ .. 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. @@ -23,9 +21,7 @@ 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: +Consider the following example: .. code-block:: c++ @@ -34,10 +30,6 @@ Consider the following code: { case 1: return "case 1"; - case 2: - return "case 2"; - case 3: - return "case 3"; default: return "default"; } >From bc03ac7407ebcff8062bdc55fed31f5e0b46c4da Mon Sep 17 00:00:00 2001 From: Zinovy Nis <[email protected]> Date: Sun, 21 Dec 2025 11:07:21 +0300 Subject: [PATCH 3/6] Fix remarks --- .../modernize/UseStringViewCheck.cpp | 51 ++++---- .../clang-tidy/modernize/UseStringViewCheck.h | 15 ++- .../checks/modernize/use-string-view.rst | 25 ++-- .../modernize/use-string-view-cxx20.cpp | 42 +++++++ .../modernize/use-string-view-ignored.cpp | 56 +++++++++ .../checkers/modernize/use-string-view.cpp | 116 +++++++++++------- 6 files changed, 227 insertions(+), 78 deletions(-) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view-cxx20.cpp create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view-ignored.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp index 0bfc56d2fbd0c..d1b6223f971e0 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "UseStringViewCheck.h" +#include "../utils/Matchers.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/ASTMatchers/ASTMatchers.h" @@ -14,15 +15,6 @@ 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 StringRef toStringViewTypeStr(StringRef Type) { if (Type.contains("wchar_t")) return "std::wstring_view"; @@ -42,25 +34,26 @@ static auto getStringTypeMatcher(StringRef CharType) { void UseStringViewCheck::registerMatchers(MatchFinder *Finder) { const auto IsStdString = getStringTypeMatcher("::std::basic_string"); const auto IsStdStringView = getStringTypeMatcher("::std::basic_string_view"); - + const auto IgnoredFunctionsMatcher = + matchers::matchesAnyListedName(IgnoredFunctions); + const auto TernaryOperator = conditionalOperator( + hasTrueExpression(ignoringParenImpCasts(stringLiteral())), + hasFalseExpression(ignoringParenImpCasts(stringLiteral()))); + const auto VirtualOrOperator = + cxxMethodDecl(anyOf(cxxConversionDecl(), isVirtual())); 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))))))))))))))) + isDefinition(), unless(VirtualOrOperator), + unless(IgnoredFunctionsMatcher), returns(IsStdString), + hasDescendant(returnStmt()), + unless(hasDescendant(returnStmt(hasReturnValue(unless( + anyOf(stringLiteral(), hasType(IsStdStringView), TernaryOperator, + cxxConstructExpr(anyOf( + allOf(hasType(IsStdString), argumentCountIs(0)), + allOf(isListInitialization(), + unless(cxxTemporaryObjectExpr()), + hasArgument(0, ignoringParenImpCasts( + stringLiteral())))))))))))) .bind("func"), this); } @@ -77,8 +70,10 @@ void UseStringViewCheck::check(const MatchFinder::MatchResult &Result) { << DestReturnTypeStr; for (const auto *FuncDecl : MatchedDecl->redecls()) - Diag << FixItHint::CreateReplacement(FuncDecl->getReturnTypeSourceRange(), - DestReturnTypeStr); + if (const SourceRange ReturnTypeRange = + FuncDecl->getReturnTypeSourceRange(); + ReturnTypeRange.isValid()) + Diag << FixItHint::CreateReplacement(ReturnTypeRange, DestReturnTypeStr); } } // namespace clang::tidy::modernize diff --git a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.h b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.h index 056bcd823a1ac..0658ba081c7bf 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.h +++ b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.h @@ -10,6 +10,7 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USESTRINGVIEWCHECK_H #include "../ClangTidyCheck.h" +#include "../utils/OptionsUtils.h" namespace clang::tidy::modernize { @@ -21,12 +22,24 @@ namespace clang::tidy::modernize { class UseStringViewCheck : public ClangTidyCheck { public: UseStringViewCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + : ClangTidyCheck(Name, Context), + IgnoredFunctions(utils::options::parseStringList(Options.get( + "IgnoredFunctions", "toString$;ToString$;to_string$;to_s$"))) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { return LangOpts.CPlusPlus17; } + std::optional<TraversalKind> getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } + void storeOptions(ClangTidyOptions::OptionMap &Opts) override { + Options.store(Opts, "IgnoredFunctions", + utils::options::serializeStringList(IgnoredFunctions)); + } + +private: + const std::vector<StringRef> IgnoredFunctions; }; } // namespace clang::tidy::modernize diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst index 70dd2726e5f0a..1eac38be8af2a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst @@ -26,10 +26,10 @@ Consider the following example: .. code-block:: c++ std::string foo(int i) { - switch(i) - { + switch(i) { case 1: return "case 1"; + ... default: return "default"; } @@ -44,17 +44,26 @@ The check gets this code transformed into: .. code-block:: c++ std::string_view foo(int i) { - switch(i) - { + switch(i) { case 1: return "case 1"; - case 2: - return "case 2"; - case 3: - return "case 3"; + ... default: return "default"; } } New version re-uses statically allocated literals without additional overhead. + +Options +------- + +.. option:: IgnoredFunctions + + A semicolon-separated list of the names of functions or methods to be + ignored. Regular expressions are accepted, e.g. ``[Rr]ef(erence)?$`` matches + every type with suffix ``Ref``, ``ref``, ``Reference`` and ``reference``. + The default is {``toString$;ToString$;to_string$;to_s$``}. If a + name in the list contains the sequence `::` it is matched against the + qualified type name (i.e. ``namespace::Type``), otherwise it is matched + against only the type name (i.e. ``Type``). diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view-cxx20.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view-cxx20.cpp new file mode 100644 index 0000000000000..65f94c5354f38 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view-cxx20.cpp @@ -0,0 +1,42 @@ +// RUN: %check_clang_tidy -std=c++20-or-later %s modernize-use-string-view %t -- -- -isystem %clang_tidy_headers + +#include <string> + +// ========================================================== +// 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"; +} + +// ========================================================== +// Negative tests +// ========================================================== + diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view-ignored.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view-ignored.cpp new file mode 100644 index 0000000000000..642d804a745a1 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view-ignored.cpp @@ -0,0 +1,56 @@ +// RUN: %check_clang_tidy \ +// RUN: -std=c++17-or-later %s modernize-use-string-view %t -- \ +// RUN: --config="{CheckOptions: {modernize-use-string-view.IgnoredFunctions: 'GoodButIgnored;GoodTooButAlsoIgnored'}}" \ +// RUN: -- -isystem %clang_tidy_headers + +#include <string> + +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 <class T, class U> struct is_same { static constexpr bool value = false; }; +template <class T> struct is_same<T, T> { static constexpr bool value = true; }; +template <class T, class U> constexpr bool is_same_v = is_same<T, U>::value; +} // namespace std + + +// ========================================================== +// Positive tests +// ========================================================== + +std::string toString() { +// 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 toString() { + return "not ignored by custom options"; +} + +std::string ToString() { +// 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 ToString() { + return "not ignored by custom options"; +} + +std::string to_string() { +// 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 to_string() { + return "not ignored by custom options"; +} + +// ========================================================== +// Negative tests +// ========================================================== + +std::string GoodButIgnored() { + return "ignored by explicit options"; +} + +std::string GoodTooButAlsoIgnored() { + return "also ignored by explicit options"; +} + diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view.cpp index b90f36eec26cc..3e66ecfdaf614 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-string-view.cpp @@ -1,4 +1,6 @@ -// RUN: %check_clang_tidy -std=c++20-or-later %s modernize-use-string-view %t -- -- -isystem %clang_tidy_headers +// RUN: %check_clang_tidy \ +// RUN: -std=c++17-or-later %s modernize-use-string-view %t -- \ +// RUN: -- -isystem %clang_tidy_headers #include <string> @@ -33,24 +35,6 @@ std::wstring 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() { @@ -75,10 +59,10 @@ auto Trailing() -> std::string { return "Trailing"; } -std::string emptyReturn() { +std::string initList() { // 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 emptyReturn() { - return {}; +// CHECK-FIXES: std::string_view initList() { + return {"list"}; } std::string ctorReturn() { @@ -87,10 +71,16 @@ std::string ctorReturn() { return std::string(); } -std::string initList() { +std::string ctorWithInitListReturn() { // 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 initList() { - return {"list"}; +// CHECK-FIXES: std::string_view ctorWithInitListReturn() { + return std::string{}; +} + +std::string emptyReturn() { +// 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 emptyReturn() { + return {}; } std::string switchCaseTest(int i) { @@ -116,6 +106,12 @@ std::string ifElseTest(bool flag) { return "false"; } +std::string ternary(bool flag) { +// 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 ternary(bool flag) { + return flag ? "true" : "false"; +} + class A { std::string classMethodInt() { return "internal"; } // CHECK-MESSAGES:[[@LINE-1]]:3: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view] @@ -143,10 +139,28 @@ my_string macro_type() { return "MACTO LITERAL"; } +#define my_definition std::string function_inside_macro() +my_definition { +// CHECK-MESSAGES:[[@LINE-1]]:1: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view] + return "literal"; +} + // ========================================================== // Negative tests // ========================================================== +std::string toString() { + return "ignored by default options"; +} + +std::string ToString() { + return "ignored by default options"; +} + +std::string to_string() { + return "ignored by default options"; +} + std::string localVariable() { std::string s = "local variable"; // TODO: extract and return literal @@ -166,8 +180,9 @@ std::string mixedReturns(bool flag) { return s; } -std::string ternary(bool flag) { - return flag ? "true" : "false"; +std::string stringTernary(bool flag) { + // TODO: extract literals + return flag ? std::string("true") : std::string("false"); } std::string_view alreadyGood() { @@ -178,18 +193,6 @@ std::wstring_view alreadyGoodW() { return L"alreadyGood"; } -std::u8string_view alreadyGoodU8() { - return u8"alreadyGood"; -} - -std::u16string_view alreadyGoodU16() { - return u"alreadyGood"; -} - -std::u32string_view alreadyGoodU32() { - return U"alreadyGood"; -} - std::string simpleLiteralS() { // TODO: replace ""s to literal and return string_view using namespace std::literals::string_literals; @@ -224,7 +227,7 @@ std::string returnConstVar() { } std::string passStringView(std::string_view sv) { - // Can be unsafe or intentional, like converting string_view into string + // TODO: Can be unsafe or intentional, like converting string_view into string return std::string(sv); } @@ -234,6 +237,20 @@ std::string explicitConstruction() { return std::string("explicitConstruction"); } +std::string explicitConstructionWithInitList() { + // Cannot be std::string_view: returning address of local temporary object + // TODO: extract and return literal + return std::string{"explicitConstruction"}; +} + +std::string explicitConstructionEmpty() { + return std::string(""); +} + +std::string explicitConstructionWithInitListEmpty() { + return std::string{""}; +} + struct B { virtual ~B() = default; virtual std::string virtMethod1() { return "B::virtual1"; } @@ -252,7 +269,7 @@ std::string C::virtMethod2() { return "C::virtual"; } std::string lambda() { // TODO: extract and return literal from lambda return []() { - return "lambda"; + return "lambda"; }(); } @@ -336,4 +353,21 @@ std::string safeFunctionWithLambda() { }; // TODO: fix hasDescendant(returnStmt(hasReturnValue... which is too strict return "safe literal"; +} + +using Handle = std::wstring; + +#ifdef HANDLE_SUPPORTED +Handle handle_or_string(); +#else +std::string handle_or_string(); +#endif + +#ifdef HANDLE_SUPPORTED +Handle +#else +std::string +#endif +my_function() { + return handle_or_string(); } \ No newline at end of file >From 4bcf80ab010c3a07c83f885be59048ce292f6e35 Mon Sep 17 00:00:00 2001 From: Zinovy Nis <[email protected]> Date: Mon, 22 Dec 2025 07:55:28 +0300 Subject: [PATCH 4/6] Update clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst Co-authored-by: EugeneZelenko <[email protected]> --- .../docs/clang-tidy/checks/modernize/use-string-view.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst index 1eac38be8af2a..c435c68852769 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst @@ -61,7 +61,7 @@ Options .. option:: IgnoredFunctions A semicolon-separated list of the names of functions or methods to be - ignored. Regular expressions are accepted, e.g. ``[Rr]ef(erence)?$`` matches + ignored. Regular expressions are accepted, e.g. `[Rr]ef(erence)?$` matches every type with suffix ``Ref``, ``ref``, ``Reference`` and ``reference``. The default is {``toString$;ToString$;to_string$;to_s$``}. If a name in the list contains the sequence `::` it is matched against the >From f33310be2d8da2c54221cb315c10ebc7be5afc11 Mon Sep 17 00:00:00 2001 From: Zinovy Nis <[email protected]> Date: Mon, 22 Dec 2025 07:55:54 +0300 Subject: [PATCH 5/6] Update clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst Co-authored-by: EugeneZelenko <[email protected]> --- .../docs/clang-tidy/checks/modernize/use-string-view.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst index c435c68852769..f1455660bcf54 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst @@ -63,7 +63,7 @@ Options A semicolon-separated list of the names of functions or methods to be ignored. Regular expressions are accepted, e.g. `[Rr]ef(erence)?$` matches every type with suffix ``Ref``, ``ref``, ``Reference`` and ``reference``. - The default is {``toString$;ToString$;to_string$;to_s$``}. If a + The default is {`toString$;ToString$;to_string$;to_s$`}. If a name in the list contains the sequence `::` it is matched against the qualified type name (i.e. ``namespace::Type``), otherwise it is matched against only the type name (i.e. ``Type``). >From 62b36f5880d59b0d390c58c6a6308c5b36292f22 Mon Sep 17 00:00:00 2001 From: Zinovy Nis <[email protected]> Date: Mon, 22 Dec 2025 13:33:25 +0300 Subject: [PATCH 6/6] Update clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst Co-authored-by: Baranov Victor <[email protected]> --- .../docs/clang-tidy/checks/modernize/use-string-view.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst index f1455660bcf54..f025bfff3a7d8 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-string-view.rst @@ -67,3 +67,4 @@ Options name in the list contains the sequence `::` it is matched against the qualified type name (i.e. ``namespace::Type``), otherwise it is matched against only the type name (i.e. ``Type``). + The default is `toString$;ToString$;to_string$`. _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
