From ef8d31e5b88f03c2703a00f8801e525b6c30e825 Mon Sep 17 00:00:00 2001 From: Victor Chernyakin 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(*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 ` check by fixing false negatives when explicitly cast from function pointer. +- Improved :doc:`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 ` 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 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: }