From 341351eff91498e85223a5b914b8e2890e5755ef Mon Sep 17 00:00:00 2001 From: tobiichi3227 Date: Tue, 21 Jul 2026 19:46:26 +0800 Subject: [PATCH 1/2] Fix empty for-loop continue back edges The for-loop parser only connected an empty increment block back to the condition when the loop body had a normal fallthrough. A continue statement can also make that block reachable, even when the body ends in break or return. Leaving that reachable increment block without a back edge creates a CFG path that cannot reach the function exit. Reverse-dominator construction then leaves the block without an r_idom, and RDF construction eventually walks through a NULL runner. This occurred during stage2 when shecc compiled a declaration-specifier loop containing continue statements. Connect the increment block whenever it has a predecessor. This keeps unreachable empty increment blocks while restoring the back edge for normal fallthrough and continue paths. --- src/parser.c | 29 +++++++++++++++++++++++------ tests/driver.sh | 6 ++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/parser.c b/src/parser.c index 6af0a77b..74d75a30 100644 --- a/src/parser.c +++ b/src/parser.c @@ -4027,14 +4027,31 @@ basic_block_t *read_body_statement(block_t *parent, basic_block_t *bb) bb_connect(cond_, body_, THEN); body_ = read_body_statement(blk, body_); - if (body_) { + /* Normal fallthrough from the loop body goes through the increment + * block. A continue statement may already have connected another + * predecessor to inc_. + */ + if (body_) bb_connect(body_, inc_, NEXT); - bb_connect(inc_, cond_start, NEXT); - } else if (inc_->insn_list.head) { - bb_connect(inc_, cond_start, NEXT); - } else { - /* Empty increment block - cleanup handled by arena allocator */ + + /* An empty increment block still needs its back-edge when it is + * reachable through normal fallthrough or continue. + * + * Do not connect a completely unreachable increment block, such as: + * + * for (;;) { + * break; + * } + */ + bool has_pred = false; + for (int i = 0; i < MAX_BB_PRED; i++) { + if (inc_->prev[i].bb) { + has_pred = true; + break; + } } + if (has_pred) + bb_connect(inc_, cond_start, NEXT); /* jump to increment */ continue_pos_idx--; diff --git a/tests/driver.sh b/tests/driver.sh index eb8125b9..5e711a03 100755 --- a/tests/driver.sh +++ b/tests/driver.sh @@ -910,6 +910,12 @@ items 10 "for(;;) break; return 10;" items 0 "int x; for(x = 10; x > 0; x--); return x;" items 30 "int i; int acc; i = 0; acc = 0; do { i = i + 1; if (i - 1 < 5) continue; acc = acc + i; if (i == 9) break; } while (i < 10); return acc;" items 26 "int acc; acc = 0; int i; for (i = 0; i < 100; i++) { if (i < 5) continue; if (i == 9) break; acc = acc + i; } return acc;" +items 1 "int i = 0; for (;;) { i++; if (i < 4) { continue; } break; } return i == 4;" +items 14 "int n = 0; for (int i = 0;;) { i++; if (i < 14) { continue; } n = i; break; } return n;" +items 14 "int i = 0; for (; i < 20;) { i++; if (i < 14) { continue; } break; } return i;" +items 14 "int n = 0; for (int i = 0; i < 20;) { i++; if (i < 14) { continue; } n = i; break; } return n;" +items 14 "int i = 0; for (; i < 14;) { i++; } return i;" +items 0 "int i = 0; for (;; i++) { break; } return i;" # Category: Comments begin_category "Comments" "Testing C-style and C++-style comment parsing" From fe202cd0a395048babe9e69ce4cd704e04d8a832 Mon Sep 17 00:00:00 2001 From: tobiichi3227 Date: Tue, 21 Jul 2026 22:56:34 +0800 Subject: [PATCH 2/2] Remove trailing whitespace --- tests/driver.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/driver.sh b/tests/driver.sh index 5e711a03..7636cc6d 100755 --- a/tests/driver.sh +++ b/tests/driver.sh @@ -1431,7 +1431,7 @@ int main() { } EOF -# Test reverse pointer difference +# Test reverse pointer difference try_ 5 << EOF int main() { char data[50]; @@ -1989,7 +1989,7 @@ int main() { } EOF -# Test 6: Non-const pointer to const data +# Test 6: Non-const pointer to const data try_ 35 << EOF int main() { const int value = 35;