Index: src/ControlStruct/ExceptTranslate.cpp
===================================================================
--- src/ControlStruct/ExceptTranslate.cpp	(revision 9fba8e65fbf69e0f9a9b68e4f545f5f92c1e878e)
+++ src/ControlStruct/ExceptTranslate.cpp	(revision 0a6d20453ce0f1bf1bb35cbe740e036d4d380116)
@@ -151,6 +151,7 @@
 		const ast::DeclWithType * except_obj, ast::CatchClause * modded_handler );
 	ast::FunctionDecl * create_terminate_match( CatchList &handlers );
-	ast::CompoundStmt * create_terminate_caller( CodeLocation loc, ast::FunctionDecl * try_wrapper,
-		ast::FunctionDecl * terminate_catch, ast::FunctionDecl * terminate_match );
+	ast::CompoundStmt * create_terminate_caller( const CodeLocation & location,
+		ast::FunctionDecl * try_wrapper, ast::FunctionDecl * terminate_match,
+		CatchList & terminate_handlers );
 	ast::FunctionDecl * create_resume_handler( CatchList &handlers );
 	ast::CompoundStmt * create_resume_wrapper(
@@ -264,5 +265,5 @@
 	//     `handler.body`;
 	// }
-	// return;
+	// break;
 	const CodeLocation & location = clause->location;
 
@@ -295,5 +296,6 @@
 				body,
 			} ),
-			new ast::ReturnStmt( location, nullptr ),
+			new ast::BranchStmt( location, ast::BranchStmt::Break,
+				ast::Label( location ) ),
 		}
 	);
@@ -391,20 +393,14 @@
 	// Index 1..{number of handlers}
 	int index = 0;
-	CatchList::iterator it;
-	for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
+	for ( ast::CatchClause * handler : handlers ) {
 		++index;
-		ast::CatchClause * handler = *it;
-
-		// Body should have been taken by create_terminate_catch.
-		// xxx - just ignore it?
-		// assert( nullptr == handler->get_body() );
-
-		// Create new body.
-		handler->body = new ast::ReturnStmt( handler->location,
+
+		ast::ptr<ast::Stmt> other_body = new ast::ReturnStmt( handler->location,
 			ast::ConstantExpr::from_int( handler->location, index ) );
-
-		// Create the handler.
+		handler->body.swap( other_body );
+
 		body->push_back( create_single_matcher( except_obj, handler ) );
-		*it = nullptr;
+
+		handler->body.swap( other_body );
 	}
 
@@ -425,8 +421,8 @@
 
 ast::CompoundStmt * TryMutatorCore::create_terminate_caller(
-		CodeLocation loc,
+		const CodeLocation & loc,
 		ast::FunctionDecl * try_wrapper,
-		ast::FunctionDecl * terminate_catch,
-		ast::FunctionDecl * terminate_match ) {
+		ast::FunctionDecl * terminate_match,
+		CatchList & terminate_handlers ) {
 	// {
 	//     int __handler_index = __cfaehm_try_terminate(`try`, `match`);
@@ -447,19 +443,27 @@
 	);
 
+	ast::ObjectDecl * except = make_exception_object( loc );
+	except->init = new ast::SingleInit( loc,
+		new ast::UntypedExpr( loc,
+			new ast::NameExpr( loc, "__cfaehm_get_current_termination" )
+		)
+	);
+
+	std::vector<ast::ptr<ast::CaseClause>> cases;
+	for ( auto const & [index, handler] : enumerate( terminate_handlers ) ) {
+		cases.emplace_back(
+			create_terminate_catch_case( except, index + 1, handler ) );
+	}
+	auto switch_stmt = new ast::SwitchStmt( loc,
+		new ast::VariableExpr( loc, index ), std::move( cases ) );
+
 	return new ast::CompoundStmt( loc, {
 		new ast::DeclStmt( loc, index ),
 		new ast::IfStmt( loc,
 			new ast::VariableExpr( loc, index ),
-			new ast::ExprStmt( loc,
-				new ast::UntypedExpr( loc,
-					new ast::VariableExpr( loc, terminate_catch ),
-					{
-						new ast::VariableExpr( loc, index ),
-						new ast::UntypedExpr( loc,
-							new ast::NameExpr( loc, "__cfaehm_get_current_termination" )
-						),
-					}
-				)
-			)
+			new ast::CompoundStmt( loc, {
+				new ast::DeclStmt( loc, except ),
+				switch_stmt,
+			} )
 		),
 	} );
@@ -663,10 +667,7 @@
 
 	if ( termination_handlers.size() ) {
-		// Define the three helper functions.
+		// Define the two helper functions.
 		ast::FunctionDecl * try_wrapper = create_try_wrapper( inner );
 		appendDeclStmt( block, try_wrapper );
-		ast::FunctionDecl * terminate_catch =
-			create_terminate_catch( termination_handlers );
-		appendDeclStmt( block, terminate_catch );
 		ast::FunctionDecl * terminate_match =
 			create_terminate_match( termination_handlers );
@@ -674,5 +675,5 @@
 		// Build the call to the try wrapper.
 		inner = create_terminate_caller(inner->location,
-			try_wrapper, terminate_catch, terminate_match );
+			try_wrapper, terminate_match, termination_handlers );
 	}
 
Index: src/ControlStruct/MultiLevelExit.cpp
===================================================================
--- src/ControlStruct/MultiLevelExit.cpp	(revision 9fba8e65fbf69e0f9a9b68e4f545f5f92c1e878e)
+++ src/ControlStruct/MultiLevelExit.cpp	(revision 0a6d20453ce0f1bf1bb35cbe740e036d4d380116)
@@ -35,5 +35,4 @@
 	InTryWithHandler,
 	InResumeHandler,
-	InTerminateHandler,
 	InFinally,
 };
@@ -512,7 +511,4 @@
 		context = "catchResume clause";
 		break;
-	case ReturnContext::InTerminateHandler:
-		context = "catch clause";
-		break;
 	case ReturnContext::InFinally:
 		context = "finally clause";
@@ -524,5 +520,14 @@
 }
 
+bool hasTerminate( const TryStmt * stmt ) {
+	for ( auto clause : stmt->handlers ) {
+		if ( ast::Terminate == clause->kind ) return true;
+	}
+	return false;
+}
+
 void MultiLevelExitCore::previsit( const TryStmt * stmt ) {
+	visit_children = false;
+
 	bool isLabeled = ! stmt->labels.empty();
 	if ( isLabeled ) {
@@ -533,9 +538,18 @@
 
 	// Try statements/try blocks are only sealed with a termination handler.
-	for ( auto clause : stmt->handlers ) {
-		if ( ast::Terminate == clause->kind ) {
-			return enterSealedContext( ReturnContext::InTryWithHandler );
-		}
-	}
+	if ( hasTerminate( stmt ) ) {
+		// This is just enterSealedContext except scoped to the block.
+		// And that is because the state must change for a single field.
+		ValueGuard< ReturnContext > guard0( ret_context );
+		ret_context = ReturnContext::InTryWithHandler;
+		auto guard = makeFuncGuard( [](){}, [this, old = std::move(enclosing_control_structures)](){ enclosing_control_structures = std::move(old); });
+		enclosing_control_structures = vector<Entry>();
+		visitor->maybe_accept( stmt, &TryStmt::body );
+	} else {
+		visitor->maybe_accept( stmt, &TryStmt::body );
+	}
+
+	visitor->maybe_accept( stmt, &TryStmt::handlers );
+	visitor->maybe_accept( stmt, &TryStmt::finally );
 }
 
@@ -551,7 +565,7 @@
 
 void MultiLevelExitCore::previsit( const CatchClause * clause ) {
-	ReturnContext context = ( ast::Terminate == clause->kind )
-		? ReturnContext::InTerminateHandler : ReturnContext::InResumeHandler;
-	enterSealedContext( context );
+	if ( ast::Resume == clause->kind ) {
+		enterSealedContext( ReturnContext::InResumeHandler );
+	}
 }
 
