https://github.com/irishrover updated https://github.com/llvm/llvm-project/pull/183921
>From 69736c0da2dfe630870d8798fb5b8e19557f6b0e Mon Sep 17 00:00:00 2001 From: Zinovy Nis <[email protected]> Date: Sat, 28 Feb 2026 17:33:50 +0300 Subject: [PATCH 1/2] [clang-tidy] Skip overloaded functions in modernize-use-string-view --- .../modernize/UseStringViewCheck.cpp | 24 +++++++++++++++++++ .../checkers/modernize/use-string-view.cpp | 7 ++++++ 2 files changed, 31 insertions(+) diff --git a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp index f5a51c0baba33..4d71a4a0ceb18 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp @@ -21,6 +21,29 @@ using namespace clang::ast_matchers; namespace clang::tidy::modernize { +namespace { +AST_MATCHER(FunctionDecl, isOverloaded) { + const DeclarationName Name = Node.getDeclName(); + // Skip lambda-like functions + if (Name.isEmpty()) + return false; + const DeclContext *DC = Node.getDeclContext(); + auto LookupResult = DC->lookup(Name); + size_t UniqueSignatures = 0; + llvm::SmallPtrSet<const FunctionDecl *, 2> SeenFunctions; + for (NamedDecl *ND : LookupResult) { + if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { + if (SeenFunctions.insert(FD->getCanonicalDecl()).second) { + UniqueSignatures++; + if (UniqueSignatures > 1) + return true; + } + } + } + return false; +} +} // namespace + static constexpr StringRef StringViewClassKey = "string"; static constexpr StringRef WStringViewClassKey = "wstring"; static constexpr StringRef U8StringViewClassKey = "u8string"; @@ -81,6 +104,7 @@ void UseStringViewCheck::registerMatchers(MatchFinder *Finder) { functionDecl( isDefinition(), unless(anyOf(VirtualOrOperator, IgnoredFunctionsMatcher, + isOverloaded(), ast_matchers::isExplicitTemplateSpecialization())), returns(IsStdString), hasDescendant(returnStmt()), unless(hasDescendant(returnStmt(hasReturnValue(unless( 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 26a72c1c242e1..81d779859f8bd 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 @@ -357,6 +357,13 @@ std::string lambda() { }(); } +namespace overloads { +std::string dbl2str(double f); +std::string overload(int) { return "int"; } +std::string overload(double f) { return "f=" + dbl2str(f); } +std::string overload(std::string) { return "string"; } +} + struct TemplateString { static constexpr char* val = "TEMPLATE"; template<typename T> >From 2507e994931bbb1cdf90ac5a053e7f2a414a884c Mon Sep 17 00:00:00 2001 From: Zinovy Nis <[email protected]> Date: Thu, 5 Mar 2026 21:38:56 +0300 Subject: [PATCH 2/2] Extend the tests --- .../modernize/UseStringViewCheck.cpp | 23 ++++-- .../checks/modernize/use-string-view.rst | 1 + .../checkers/modernize/use-string-view.cpp | 76 ++++++++++++++++++- 3 files changed, 92 insertions(+), 8 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp index 4d71a4a0ceb18..29e5bdb65632e 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseStringViewCheck.cpp @@ -24,7 +24,7 @@ namespace clang::tidy::modernize { namespace { AST_MATCHER(FunctionDecl, isOverloaded) { const DeclarationName Name = Node.getDeclName(); - // Skip lambda-like functions + // Sanity check if (Name.isEmpty()) return false; const DeclContext *DC = Node.getDeclContext(); @@ -32,12 +32,21 @@ AST_MATCHER(FunctionDecl, isOverloaded) { size_t UniqueSignatures = 0; llvm::SmallPtrSet<const FunctionDecl *, 2> SeenFunctions; for (NamedDecl *ND : LookupResult) { - if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { - if (SeenFunctions.insert(FD->getCanonicalDecl()).second) { - UniqueSignatures++; - if (UniqueSignatures > 1) - return true; - } + const FunctionDecl *FD = nullptr; + if (const auto *Func = dyn_cast<FunctionDecl>(ND)) { + // Regular functions + FD = Func; + } else if (const auto *USD = dyn_cast<UsingShadowDecl>(ND)) { + // Overloads via "using ns::func_name" + FD = dyn_cast<FunctionDecl>(USD->getTargetDecl()); + } else if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND)) { + // Templated functions + FD = FTD->getTemplatedDecl(); + } + if (FD && SeenFunctions.insert(FD->getCanonicalDecl()).second) { + UniqueSignatures++; + if (UniqueSignatures > 1) + return true; } } return false; 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 157bb1f52092e..c72a0480c0eb8 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 @@ -83,6 +83,7 @@ Limitations * ``auto Trailing() -> std::string { return "Trailing"; }`` warns, doesn't fix * returnings from lambda * complicated macro and templated code + * overloaded functions and methods In some cases the fixed code will not compile due to lack of conversion from ``std::string_view`` to ``std::string``. It can be fixed (preferably) by 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 81d779859f8bd..61e8a63eb6421 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 @@ -203,6 +203,34 @@ MyString<wchar_t> aliasedWChar() { return L"aliasedWChar"; } +namespace overload_funcs_redeclared { +std::basic_string<char> overload(int); +std::string overload(int); +std::string overload(int) { return "int"; } +// 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 overload(int) { return "int"; } +} + +namespace overload_non_func { +struct overload {}; +std::string overload(int) { return "int"; } +// 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 overload(int) { return "int"; } +} + +namespace overload_with_inline { + inline namespace inline_namespace { + std::string overload(int) { return "int"; } +// CHECK-MESSAGES:[[@LINE-1]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view] +// CHECK-FIXES: std::string_view overload(int) { return "int"; } + } + inline namespace regular_namespace { + std::string overload(int) { return "int"; } +// CHECK-MESSAGES:[[@LINE-1]]:5: warning: consider using 'std::string_view' to avoid unnecessary copying and allocations [modernize-use-string-view] +// CHECK-FIXES: std::string_view overload(int) { return "int"; } + } +} + // ========================================================== // Negative tests // ========================================================== @@ -357,13 +385,59 @@ std::string lambda() { }(); } -namespace overloads { +namespace overload_funcs { std::string dbl2str(double f); +// Skip overloaded functions std::string overload(int) { return "int"; } +// Because of this overload (non-literal return) the fix should not be applied std::string overload(double f) { return "f=" + dbl2str(f); } std::string overload(std::string) { return "string"; } } +namespace overload_methods { +struct Foo { + // Skip overloaded methods + std::string overload(int) { return "int"; } + std::string overload(double f) { return "double"; } + std::string overload(std::string) { return "string"; } +}; +} + +namespace overload_methods_nested_classes { +struct Bar { + std::string overload(int) { return "int"; } + std::string overload(std::string) { return "string"; } + + struct FooBar { + std::string overload(char*) { return "char*"; } + std::string overload(double f) { return "double"; } + }; +}; +} + +namespace overload_methods_nested_namespaces { +namespace foo { + std::string overload(int) { return "int"; } + std::string overload(std::string) { return "string"; } +} +using foo::overload; +std::string overload(char*) { return "char*"; } +} + +namespace overload_methods_templated { + template <typename T> + std::string overload(T value) { return "T";} + std::string overload(int value) { return "int"; } +} + +namespace two_overloads_with_inline { + inline namespace inline_namespace { + std::string overload(int) { return "int"; } + std::string overload(double) { return "double"; } + } + std::string overload(int) { return "int"; } +} + struct TemplateString { static constexpr char* val = "TEMPLATE"; template<typename T> _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
