[clang-tools-extra] [clang-tidy] Fix invalid avoid-c-style-cast fix-it after keywords (PR #206239)
Zeyi Xu via cfe-commits
cfe-commits at lists.llvm.org
Sat Jun 27 04:02:37 PDT 2026
https://github.com/zeyi2 created https://github.com/llvm/llvm-project/pull/206239
None
>From 75b09858013ea79402fee3bd50f0f55e9984e12c Mon Sep 17 00:00:00 2001
From: Zeyi Xu <mitchell.xu2 at gmail.com>
Date: Sat, 27 Jun 2026 19:02:22 +0800
Subject: [PATCH] [clang-tidy] Fix invalid avoid-c-style-cast fix-it after
keywords
---
.../modernize/AvoidCStyleCastCheck.cpp | 24 +++++++++++++++++++
clang-tools-extra/docs/ReleaseNotes.rst | 5 ++++
.../checkers/modernize/avoid-c-style-cast.cpp | 6 +++++
3 files changed, 35 insertions(+)
diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidCStyleCastCheck.cpp b/clang-tools-extra/clang-tidy/modernize/AvoidCStyleCastCheck.cpp
index 7010b8774deca..f374aa3440ba3 100644
--- a/clang-tools-extra/clang-tidy/modernize/AvoidCStyleCastCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/AvoidCStyleCastCheck.cpp
@@ -69,6 +69,28 @@ static CharSourceRange getReplaceRange(const ExplicitCastExpr *Expr) {
llvm_unreachable("Unsupported CastExpr");
}
+static bool needsLeadingSpace(CharSourceRange Range, StringRef ReplacementText,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ if (ReplacementText.empty())
+ return false;
+
+ SourceLocation Begin = Range.getBegin();
+ if (Begin.isInvalid() || Begin.isMacroID())
+ return false;
+
+ auto BeginInfo = SM.getDecomposedLoc(Begin);
+ bool Invalid = false;
+ StringRef Buffer = SM.getBufferData(BeginInfo.first, &Invalid);
+ if (Invalid || BeginInfo.second == 0)
+ return false;
+
+ return Lexer::isAsciiIdentifierContinueChar(Buffer[BeginInfo.second - 1],
+ LangOpts) &&
+ Lexer::isAsciiIdentifierContinueChar(ReplacementText.front(),
+ LangOpts);
+}
+
static StringRef getDestTypeString(const SourceManager &SM,
const LangOptions &LangOpts,
const ExplicitCastExpr *Expr) {
@@ -196,6 +218,8 @@ void AvoidCStyleCastCheck::check(const MatchFinder::MatchResult &Result) {
getLangOpts()),
")");
}
+ if (needsLeadingSpace(ReplaceRange, CastText, SM, getLangOpts()))
+ CastText.insert(CastText.begin(), ' ');
Diag << FixItHint::CreateReplacement(ReplaceRange, CastText);
};
auto ReplaceWithNamedCast = [&](StringRef CastType) {
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 81e5de4e0a868..f6026a0c43ed1 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -601,6 +601,11 @@ Changes in existing checks
Because it only sees one file at a time, the check can't be sure
such entities aren't referenced in any other files of that module.
+- Improved :doc:`modernize-avoid-c-style-cast
+ <clang-tidy/checks/modernize/avoid-c-style-cast>` check by fixing an invalid
+ fix-it generated when replacing casts that directly follow a keyword or
+ identifier.
+
- Improved :doc:`modernize-deprecated-headers
<clang-tidy/checks/modernize/deprecated-headers>` check by avoiding false
positives on project headers that use the same name as a standard library
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-style-cast.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-style-cast.cpp
index 52b4d471bda9b..4b30d67b3b82e 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-style-cast.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-style-cast.cpp
@@ -156,6 +156,12 @@ void f(int a, double b, const char *cpc, const void *cpv, X *pX) {
return (void)g();
}
+int cast_after_return(double d) {
+ return(int)d;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: C-style casts are discouraged; use static_cast [
+ // CHECK-FIXES: return static_cast<int>(d);
+}
+
template <typename T>
void template_function(T t, int n) {
int i = (int)t;
More information about the cfe-commits
mailing list