Skip to content

An empty catch clause catches - #597

Merged
ASDAlexander77 merged 1 commit into
mainfrom
fix-empty-catch-clause
Oct 17, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
fix-empty-catch-clause

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

An empty catch clause did not catch anything. This program died with tslang: error: uncaught exception under every -mm:

function h() { throw 1; }
function k() { try { h(); } catch { } }
function main() { k(); print("end"); }

Cause. An untyped catch { } puts no ops in the TryOp's catches region. TryOpLowering set catchHasOps from whether that region held anything besides its terminator. So it treated the empty catch as "no catch clause", which is what the TryOps that only wrap a scope for its cleanup look like. It made no landing pad, and the exception went uncaught.

Fix. mlirGen(TryStatement) now marks a TryOp that has a catch clause with a HAS_CATCH_ATTR_NAME unit attribute. TryOpLowering treats a marked TryOp as having a catch even when the region is empty. The cleanup-only TryOps (block/using wraps) stay unmarked, so for them an empty region still means "no catch".

Test. 00try_empty_catch.ts covers:

  • an empty catch { }, catch (e) { } and catch { ; }
  • an empty catch followed by finally
  • an owned local in the try
  • nested empty catches
  • an empty catch in a loop
  • a try that does not throw
  • an empty catch in a method

It is registered for compile, JIT and TSLANG_CORPUS.

The repro prints "end" under gc, rc, none and own. Full ctest -C Release -j 8 --timeout 300 passes: 4138 tests, 0 failures.

Found while working on #596.

🤖 Generated with Claude Code

An untyped `catch { }` emits no ops into the TryOp's catches region, and
TryOpLowering took a region holding only its terminator for "no catch
clause" - the shape of the TryOps that only wrap a scope for its cleanup -
so it made no landing pad and the exception went uncaught.

mlirGen(TryStatement) now marks a TryOp that has a catch clause with
HAS_CATCH_ATTR_NAME, and TryOpLowering treats a marked TryOp as having a
catch whatever its region holds. The cleanup-only TryOps stay unmarked.

Test 00try_empty_catch.ts (compile, JIT, corpus).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ASDAlexander77
ASDAlexander77 merged commit 3459b7a into main Oct 17, 2026
2 checks passed
@ASDAlexander77
ASDAlexander77 deleted the fix-empty-catch-clause branch October 17, 2026 19:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant