[clang-tools-extra] b0cb331 - [clang-tidy] Avoid brace fix-it crash in macro body expansion (#198788)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jun 4 01:29:11 PDT 2026
Author: Zeyi Xu
Date: 2026-06-04T16:29:06+08:00
New Revision: b0cb331995d494dda75d5fd967e160ec0c32caf1
URL: https://github.com/llvm/llvm-project/commit/b0cb331995d494dda75d5fd967e160ec0c32caf1
DIFF: https://github.com/llvm/llvm-project/commit/b0cb331995d494dda75d5fd967e160ec0c32caf1.diff
LOG: [clang-tidy] Avoid brace fix-it crash in macro body expansion (#198788)
`readability-braces-around-statements `could assert when diagnosing an
unbraced statement that ends in the middle of a macro body expansion. It
would be hard/unsafe to give fix-its for such cases, so treat them as
diagnostic-only.
Closes https://github.com/llvm/llvm-project/issues/198711
Added:
Modified:
clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
clang-tools-extra/clang-tidy/utils/BracesAroundStatement.cpp
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/test/clang-tidy/checkers/readability/braces-around-statements-same-line.cpp
clang-tools-extra/test/clang-tidy/checkers/readability/braces-around-statements.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp b/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
index 1864dfcbd29c2..710b538317626 100644
--- a/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/BracesAroundStatementsCheck.cpp
@@ -154,7 +154,8 @@ bool BracesAroundStatementsCheck::checkStmt(
S, Result.Context->getLangOpts(), *Result.SourceManager, StartLoc,
EndLocHint);
if (BraceInsertionHints) {
- if (ShortStatementLines && !ForceBracesStmts.erase(S) &&
+ if (ShortStatementLines && BraceInsertionHints.offersFixIts() &&
+ !ForceBracesStmts.erase(S) &&
BraceInsertionHints.resultingCompoundLineExtent(*Result.SourceManager) <
ShortStatementLines)
return false;
diff --git a/clang-tools-extra/clang-tidy/utils/BracesAroundStatement.cpp b/clang-tools-extra/clang-tidy/utils/BracesAroundStatement.cpp
index d51bfd9362eb7..151fec67228c7 100644
--- a/clang-tools-extra/clang-tidy/utils/BracesAroundStatement.cpp
+++ b/clang-tools-extra/clang-tidy/utils/BracesAroundStatement.cpp
@@ -110,7 +110,9 @@ BraceInsertionHints getBraceInsertionsHints(const Stmt *const S,
// 2) If there's a multi-line block comment starting on the same line after
// the location we're inserting the closing brace at, or there's a non-comment
// token, the check inserts "\n}" right before that token.
- // 3) Otherwise the check finds the end of line (possibly after some block or
+ // 3) If the statement ends in the middle of a macro body expansion, the check
+ // emits a diagnostic without a fix-it.
+ // 4) Otherwise the check finds the end of line (possibly after some block or
// line comments) and inserts "\n}" right before that EOL.
if (!S || isa<CompoundStmt>(S)) {
// Already inside braces.
@@ -157,6 +159,12 @@ BraceInsertionHints getBraceInsertionsHints(const Stmt *const S,
EndLoc = EndLocHint;
ClosingInsertion = "} ";
} else {
+ const SourceLocation StmtEndLoc = S->getEndLoc();
+ if (StmtEndLoc.isMacroID() && SM.isMacroBodyExpansion(StmtEndLoc) &&
+ !Lexer::isAtEndOfMacroExpansion(StmtEndLoc, SM, LangOpts)) {
+ // No safe fix-it for a statement ending in the middle of a macro body.
+ return {StartLoc};
+ }
EndLoc = findEndLocation(*S, SM, LangOpts);
ClosingInsertion = "\n}";
}
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 71ddb9bcbe497..53d28b439c97b 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -672,6 +672,11 @@ Changes in existing checks
false positives when a class is seen through both a header include and
a C++20 module import.
+- Improved :doc:`readability-braces-around-statements
+ <clang-tidy/checks/readability/braces-around-statements>` check by fixing a
+ crash when diagnosing a statement that ends in the middle of a macro body
+ expansion.
+
- Improved :doc:`readability-container-size-empty
<clang-tidy/checks/readability/container-size-empty>` check:
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/braces-around-statements-same-line.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/braces-around-statements-same-line.cpp
index 50456c6de0c89..0b2cf6e3fb072 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/braces-around-statements-same-line.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/braces-around-statements-same-line.cpp
@@ -2,6 +2,10 @@
void do_something(const char *) {}
+#define BAD_MACRO(x) \
+ do_something(x); \
+ do_something(x)
+
bool cond(const char *) {
return false;
}
@@ -33,4 +37,8 @@ void test() {
// CHECK-MESSAGES: :[[@LINE-7]]:31: warning: statement should be inside braces
// CHECK-FIXES: if (cond("if4") /*comment*/) {
// CHECK-FIXES: }
+
+ if (cond("macro"))
+ BAD_MACRO("macro");
+ // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: statement should be inside braces
}
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/braces-around-statements.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/braces-around-statements.cpp
index f1bb4ed988d7d..6f15500040905 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/braces-around-statements.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/braces-around-statements.cpp
@@ -415,6 +415,14 @@ int test_macros(bool b) {
// CHECK-FIXES-NEXT: do_something("for in wrapping macro 3")
// CHECK-FIXES-NEXT: );
+ #define BAD_MACRO(x) \
+ do_something(x); \
+ do_something(x)
+
+ if (b)
+ BAD_MACRO("macro body");
+ // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: statement should be inside braces
+
// Taken from https://bugs.llvm.org/show_bug.cgi?id=22785
int i;
#define MACRO_1 i++
More information about the cfe-commits
mailing list