https://github.com/voyager-jhk updated https://github.com/llvm/llvm-project/pull/227984
>From ba90c5aab9d3709126a94173a1e1e44516f36e8a Mon Sep 17 00:00:00 2001 From: voyager-jhk <[email protected]> Date: Thu, 1 Oct 2026 15:20:28 +0800 Subject: [PATCH 1/2] [clang-tidy] Fix invalid fix-it for macro expansions Do not offer a fix-it for one-character strings from macro expansions. Fixes #222970 --- .../performance/PreferSingleCharOverloadsCheck.cpp | 13 ++++++++----- clang-tools-extra/docs/ReleaseNotes.md | 5 +++++ .../performance/prefer-single-char-overloads.cpp | 10 ++++++++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/performance/PreferSingleCharOverloadsCheck.cpp b/clang-tools-extra/clang-tidy/performance/PreferSingleCharOverloadsCheck.cpp index d5d1784c0a0b7..a62ef1254e806 100644 --- a/clang-tools-extra/clang-tidy/performance/PreferSingleCharOverloadsCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/PreferSingleCharOverloadsCheck.cpp @@ -101,11 +101,14 @@ void PreferSingleCharOverloadsCheck::check( if (!Replacement) return; - diag(Literal->getBeginLoc(), "%0 called with a string literal consisting of " - "a single character; consider using the more " - "efficient overload accepting a character") - << FindFunc - << FixItHint::CreateReplacement(Literal->getSourceRange(), *Replacement); + const auto Diag = diag(Literal->getBeginLoc(), + "%0 called with a string literal consisting of " + "a single character; consider using the more " + "efficient overload accepting a character") + << FindFunc; + if (!Literal->getBeginLoc().isMacroID() && !Literal->getEndLoc().isMacroID()) + Diag << FixItHint::CreateReplacement(Literal->getSourceRange(), + *Replacement); } } // namespace clang::tidy::performance diff --git a/clang-tools-extra/docs/ReleaseNotes.md b/clang-tools-extra/docs/ReleaseNotes.md index 5ad0b2d3718b9..84cffb9fe4222 100644 --- a/clang-tools-extra/docs/ReleaseNotes.md +++ b/clang-tools-extra/docs/ReleaseNotes.md @@ -257,6 +257,11 @@ infrastructure are described first, followed by tool-specific sections. offered when an argument covers only part of a macro expansion, as it then has no source text of its own. +- Improved {doc}`performance-prefer-single-char-overloads + <clang-tidy/checks/performance/prefer-single-char-overloads>` check to + avoid offering fix-its for string literals originating from macro + expansions. + - Improved {doc}`readability-convert-member-functions-to-static <clang-tidy/checks/readability/convert-member-functions-to-static>` check by fixing a crash when checking a const-qualified method declared with the diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance/prefer-single-char-overloads.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance/prefer-single-char-overloads.cpp index 46bbf3c20f8fd..14af39aded0b6 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/performance/prefer-single-char-overloads.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/performance/prefer-single-char-overloads.cpp @@ -146,6 +146,16 @@ int Macros() { // CHECK-MESSAGES: [[@LINE-2]]:37: warning: 'find' called with a string literal } +#define TOKEN_SEPARATING_CHARACTER "_" +// CHECK-FIXES: #define TOKEN_SEPARATING_CHARACTER "_" + +void foo() { + std::string a; + a += TOKEN_SEPARATING_CHARACTER; + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: 'operator+=' called with a + // CHECK-FIXES: a += TOKEN_SEPARATING_CHARACTER; +} + void SubstitutedTemplateType() { Wrapper<std::string>().value.find("a"); // CHECK-MESSAGES: [[@LINE-1]]:37: warning: 'find' called with a string literal >From 782a8e332f5711b74b38ff9323ef3c5abdff71bb Mon Sep 17 00:00:00 2001 From: voyager-jhk <[email protected]> Date: Mon, 5 Oct 2026 15:11:53 +0800 Subject: [PATCH 2/2] Check all concatenated string tokens for macro expansions --- .../performance/PreferSingleCharOverloadsCheck.cpp | 4 +++- .../performance/prefer-single-char-overloads.cpp | 10 ++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/performance/PreferSingleCharOverloadsCheck.cpp b/clang-tools-extra/clang-tidy/performance/PreferSingleCharOverloadsCheck.cpp index a62ef1254e806..4f62bd2be7d83 100644 --- a/clang-tools-extra/clang-tidy/performance/PreferSingleCharOverloadsCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/PreferSingleCharOverloadsCheck.cpp @@ -11,6 +11,7 @@ #include "../utils/OptionsUtils.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> #include <optional> using namespace clang::ast_matchers; @@ -106,7 +107,8 @@ void PreferSingleCharOverloadsCheck::check( "a single character; consider using the more " "efficient overload accepting a character") << FindFunc; - if (!Literal->getBeginLoc().isMacroID() && !Literal->getEndLoc().isMacroID()) + if (std::none_of(Literal->tokloc_begin(), Literal->tokloc_end(), + [](SourceLocation Loc) { return Loc.isMacroID(); })) Diag << FixItHint::CreateReplacement(Literal->getSourceRange(), *Replacement); } diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance/prefer-single-char-overloads.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance/prefer-single-char-overloads.cpp index 14af39aded0b6..58f28f8ff9ecf 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/performance/prefer-single-char-overloads.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/performance/prefer-single-char-overloads.cpp @@ -156,6 +156,16 @@ void foo() { // CHECK-FIXES: a += TOKEN_SEPARATING_CHARACTER; } +#define SEP "_" +// CHECK-FIXES: #define SEP "_" + +void ConcatenatedMacro() { + std::string s; + s += "" SEP ""; + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: 'operator+=' called with a + // CHECK-FIXES: s += "" SEP ""; +} + void SubstitutedTemplateType() { Wrapper<std::string>().value.find("a"); // CHECK-MESSAGES: [[@LINE-1]]:37: warning: 'find' called with a string literal _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
