Repository navigation
continue a in a: b: for goes on to the next iteration; labelled for-of no longer crashes - #590
Merged
Merged
Conversation
`a`'s statement is another label, so `a` got a LabelOp of its own around the loop, and `continue a` restarted that region: the loop from its initializer, skipping the incrementor (an endless loop). The outer labels of a chain that ends in a loop are now other names for the innermost one, the label the loop carries; a chain that ends in a block keeps its LabelOps. A labelled for-of crashed the compiler on `continue`/`break` to its label: generating the iterated value's iterator generated loops of its own, which took the pending label before the `for` the loop is made into existed. `for` and for-of now take the label on entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nto fix-nested-label-continue # Conflicts: # tslang/lib/TypeScript/MLIRGenStatements.cpp
Under rc a jump out of a labelled block releases the function's owned locals (open, not from this change); the string the case built was read after it was freed, which Linux CI caught. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes two labelled-loop miscompiles found while fixing silently-accepted bad code (#583 added the unknown-label check; the codegen was already wrong).
a: b: for (...) { continue a; }looped forever.a's statement is another label, somlirGen(LabeledStatement)made aLabelOpforaaround the loop, andcontinue arestarted that region, which runs the loop again from its initializer and skips the incrementor. The outer labels of a chain that ends in a loop are now other names for the innermost one (loopLabelAliases, resolved bybreak/continue), so the loop carries the only label. A chain that ends in a block keeps itsLabelOps, socontinueto a labelled block still restarts it (00break_continue.ts). A labelled for-of crashed the compiler oncontinue b/break b, even with one label (b: for (const v of [1, 2, 3])). Generating the iterated value's iterator generated loops of its own, and they took the pendinglabelbefore theforthat the for-of is made into existed.forand for-of now take the label on entry. Thefordoes this before its initializer, which can generate loops too. Merged with main's #583 label check:break/continuecheck the label as written, then resolve the alias. LikeactiveLabels, the aliases are set aside while a nested function is generated, so a function's owna: forinside an outera: b: forkeeps itsa.Expected output is what TypeScript gives: the repro prints
0 2 done. New test00label_chain_loop.ts(compile + JIT, and inTSLANG_CORPUS):for/while/do/for-of chains,continue afrom a nested loop, a one-label for-of over a literal and over an array variable, and a label chain on a block. ### Checked, not fixed hereGenContext::loopLabelis always"", as suspected. It is load-bearing (see the comment atscopeExitContinuesOutwards, extended here), and it hides two real scope-exit bugs that need their own change: -continue outerwritten inside anifin an inner loop stops the scope-exit walk at the inner loop's body, so ausingin the outer body is never disposed. - under-mm=rc,a: { s += "x"; break a; } return s;returns"": a break out of a labelled block walks past the function's locals and releases them. This happens with one label too, so it is not from this change, which is why the test's block case has nobreak. Storing real labels alone is wrong, because the inner loop's context stands in for the outer body scope in that walk. Fullctest -C Release -j 8 --timeout 300: 4098/4098 passed. 🤖 Generated with Claude Code