[clang-tools-extra] [clang-tidy] Do not diagnose continue of outer loop (PR #222485)
Junior Rantila via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 10 07:03:13 PDT 2026
https://github.com/juniorrantila updated https://github.com/llvm/llvm-project/pull/222485
>From 4a9900b139598537a563e81c232bb83820d4d64e Mon Sep 17 00:00:00 2001
From: Junior Rantila <junior.rantila at gmail.com>
Date: Thu, 10 Sep 2026 02:05:52 +0200
Subject: [PATCH] [clang-tidy] Do not diagnose continue of outer loop
This patch ensures that "readability-redundant-control-flow"
does not trigger a diagnostic when continuing an outer loop
at the end of an inner loop.
```
int robin = 0;
next_client: for (;;) {
int client = accept(sock);
for (int i = 0; i < worker_count; i++) {
robin = (robin + 1) % worker_count;
Worker* worker = &workers[robin];
if (worker->is_full())
continue;
worker->push(client);
continue next_client; // This would previously emit diagnostic.
}
handle_request(client);
}
```
---
.../readability/RedundantControlFlowCheck.cpp | 12 +++++++++++-
.../readability/redundant-control-flow.cpp | 19 +++++++++++++++++++
2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
index 46cbaa1f70301..48d99db2ee79a 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantControlFlowCheck.cpp
@@ -39,7 +39,8 @@ void RedundantControlFlowCheck::registerMatchers(MatchFinder *Finder) {
this);
Finder->addMatcher(mapAnyOf(forStmt, cxxForRangeStmt, whileStmt, doStmt)
.with(hasBody(compoundStmt(
- hasFinalStmt(continueStmt().bind("stmt"))))),
+ hasFinalStmt(continueStmt().bind("stmt")))))
+ .bind("loop"),
this);
}
@@ -50,6 +51,15 @@ void RedundantControlFlowCheck::check(const MatchFinder::MatchResult &Result) {
if (StmtRange.getBegin().isMacroID())
return;
+ if (const auto *Continue = dyn_cast<ContinueStmt>(&RedundantStmt)) {
+ if (const auto *Label = Continue->getLabelDecl()) {
+ const auto *Loop = Result.Nodes.getNodeAs<Stmt>("loop");
+ const auto *ContinueLoop = Label->getStmt()->getSubStmt();
+ if (Loop != ContinueLoop)
+ return;
+ }
+ }
+
const auto RemovedRange = CharSourceRange::getCharRange(
StmtRange.getBegin(),
Lexer::findLocationAfterToken(StmtRange.getEnd(), tok::semi,
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 e157e99c5bf0b..0b1755e306a49 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
@@ -272,3 +272,22 @@ void semicolon_far_from_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: }
+
+void continue_labeled_loop() {
+ loop:
+ for (int i = 0; i < 10; ++i) {
+ continue loop;
+ }
+}
+// CHECK-MESSAGES: :[[@LINE-4]]:5: warning: redundant continue statement at the end of loop statement
+// CHECK-FIXES: for (int i = 0; i < 10; ++i) {
+// CHECK-FIXES-NEXT: }
+
+void continue_outer_labeled_loop() {
+ outer:
+ for (int i = 0; i < 10; ++i) {
+ for (int j = 0; j < 10; ++j) {
+ continue outer;
+ }
+ }
+}
More information about the cfe-commits
mailing list