[clang-tools-extra] [clang-tidy] Make `readability-redundant-control-flow` not suggest deleting unrelated lines (PR #171287)
Victor Chernyakin via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 9 18:50:43 PST 2025
https://github.com/localspook updated https://github.com/llvm/llvm-project/pull/171287
>From ef8d31e5b88f03c2703a00f8801e525b6c30e825 Mon Sep 17 00:00:00 2001
From: Victor Chernyakin <chernyakin.victor.j at outlook.com>
Date: Tue, 9 Dec 2025 00:21:21 -0800
Subject: [PATCH 1/2] [clang-tidy] Make `readability-redundant-control-flow`
not suggest deleting unrelated lines
---
.../readability/RedundantControlFlowCheck.cpp | 18 ++++-------
clang-tools-extra/docs/ReleaseNotes.rst | 5 ++++
.../readability/redundant-control-flow.cpp | 30 +++++++++++++++++++
3 files changed, 40 insertions(+), 13 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
index 132b7ddc4311b..b77108c49f53c 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
@@ -71,19 +71,11 @@ void RedundantControlFlowCheck::issueDiagnostic(
if (isLocationInMacroExpansion(SM, StmtRange.getBegin()))
return;
- const CompoundStmt::const_reverse_body_iterator Previous =
- ++Block->body_rbegin();
- SourceLocation Start;
- if (Previous != Block->body_rend())
- Start = Lexer::findLocationAfterToken(
- cast<Stmt>(*Previous)->getEndLoc(), tok::semi, SM, getLangOpts(),
- /*SkipTrailingWhitespaceAndNewLine=*/true);
- if (!Start.isValid())
- Start = StmtRange.getBegin();
- auto RemovedRange = CharSourceRange::getCharRange(
- Start, Lexer::findLocationAfterToken(
- StmtRange.getEnd(), tok::semi, SM, getLangOpts(),
- /*SkipTrailingWhitespaceAndNewLine=*/true));
+ const auto RemovedRange = CharSourceRange::getCharRange(
+ StmtRange.getBegin(),
+ Lexer::findLocationAfterToken(StmtRange.getEnd(), tok::semi, SM,
+ getLangOpts(),
+ /*SkipTrailingWhitespaceAndNewLine=*/true));
diag(StmtRange.getBegin(), Diag) << FixItHint::CreateRemoval(RemovedRange);
}
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index d1fb1cba3e45a..9f72f31b3cfa9 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -581,6 +581,11 @@ Changes in existing checks
<clang-tidy/checks/readability/redundant-casting>` check by fixing false
negatives when explicitly cast from function pointer.
+- Improved :doc:`readability-redundant-control-flow
+ <clang-tidy/checks/readability/redundant-control-flow>` by fixing an issue
+ where the check would sometimes suggest deleting not only a redundant
+ ``return`` or ``continue``, but also unrelated lines preceding it.
+
- Improved :doc:`readability-uppercase-literal-suffix
<clang-tidy/checks/readability/uppercase-literal-suffix>` check to recognize
literal suffixes added in C++23 and C23.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-control-flow.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-control-flow.cpp
index 77644902e7772..0083b5e921bc9 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-control-flow.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-control-flow.cpp
@@ -222,3 +222,33 @@ void call_templates() {
template_loop(10L);
template_loop(10U);
}
+
+void dont_delete_lines_before_return_statement() {
+ do {} while (0);
+#ifdef FOO
+#endif
+ return;
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:3: warning: redundant return statement
+// CHECK-FIXES: void dont_delete_lines_before_return_statement() {
+// CHECK-FIXES-NEXT: do {} while (0);
+// CHECK-FIXES-NEXT: #ifdef FOO
+// CHECK-FIXES-NEXT: #endif
+// CHECK-FIXES-NEXT: }
+
+void dont_delete_lines_before_continue_statement() {
+ for (;;) {
+ do {} while (0);
+#ifdef BAR
+#endif
+ continue;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-3]]:5: warning: redundant continue statement
+// CHECK-FIXES: void dont_delete_lines_before_continue_statement() {
+// CHECK-FIXES-NEXT: for (;;) {
+// CHECK-FIXES-NEXT: do {} while (0);
+// CHECK-FIXES-NEXT: #ifdef BAR
+// CHECK-FIXES-NEXT: #endif
+// CHECK-FIXES-NEXT: }
+// CHECK-FIXES-NEXT: }
>From f6a4025c84f4e9d292f6286980237733cf2369ea Mon Sep 17 00:00:00 2001
From: Victor Chernyakin <chernyakin.victor.j at outlook.com>
Date: Tue, 9 Dec 2025 18:49:23 -0800
Subject: [PATCH 2/2] add tests with wandering semicolon
---
.../readability/redundant-control-flow.cpp | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-control-flow.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-control-flow.cpp
index 0083b5e921bc9..5923f0db5c090 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-control-flow.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/redundant-control-flow.cpp
@@ -252,3 +252,23 @@ void dont_delete_lines_before_continue_statement() {
// CHECK-FIXES-NEXT: #endif
// CHECK-FIXES-NEXT: }
// CHECK-FIXES-NEXT: }
+
+void semicolon_far_from_return() {
+ return
+
+ ;
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:3: warning: redundant return statement at the end of a function with a void return type [readability-redundant-control-flow]
+// CHECK-FIXES: void semicolon_far_from_return() {
+// CHECK-FIXES-NEXT: }
+
+void semicolon_far_from_continue() {
+ for (int i = 0; i < 20; ++i) {
+ continue
+
+ ;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-5]]:5: warning: redundant continue statement at the end of loop statement
+// CHECK-FIXES: for (int i = 0; i < 20; ++i) {
+// CHECK-FIXES-NEXT: }
More information about the cfe-commits
mailing list