Author: Peiqi Li
Date: 2026-10-08T15:33:03+08:00
New Revision: 66cc20a0b4356d2b5d2278e68bfe5b16ad4e87dd

URL: 
https://github.com/llvm/llvm-project/commit/66cc20a0b4356d2b5d2278e68bfe5b16ad4e87dd
DIFF: 
https://github.com/llvm/llvm-project/commit/66cc20a0b4356d2b5d2278e68bfe5b16ad4e87dd.diff

LOG: [clang-tidy] Fix invalid fix-it for macro expansions (#227984)

Do not offer a fix-it for one-character strings from macro expansions.

Fixes #222970

Added: 
    

Modified: 
    clang-tools-extra/clang-tidy/performance/PreferSingleCharOverloadsCheck.cpp
    clang-tools-extra/docs/ReleaseNotes.md
    
clang-tools-extra/test/clang-tidy/checkers/performance/prefer-single-char-overloads.cpp

Removed: 
    


################################################################################
diff  --git 
a/clang-tools-extra/clang-tidy/performance/PreferSingleCharOverloadsCheck.cpp 
b/clang-tools-extra/clang-tidy/performance/PreferSingleCharOverloadsCheck.cpp
index d5d1784c0a0b7..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;
@@ -101,11 +102,15 @@ 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 (std::none_of(Literal->tokloc_begin(), Literal->tokloc_end(),
+                   [](SourceLocation Loc) { return Loc.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 94e0f279d1c6c..8b32c22542aeb 100644
--- a/clang-tools-extra/docs/ReleaseNotes.md
+++ b/clang-tools-extra/docs/ReleaseNotes.md
@@ -295,6 +295,11 @@ infrastructure are described first, followed by 
tool-specific sections.
   {option}`ForRangeLoopClasses` to configure container classes that can be used
   as sources in range-based `for` loops.
 
+- 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..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
@@ -146,6 +146,26 @@ 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;
+}
+
+#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

Reply via email to