Index: src/ControlStruct/MultiLevelExit.cpp
===================================================================
--- src/ControlStruct/MultiLevelExit.cpp	(revision 2fa0237f52bd8db42015c83dee0d38191a902db4)
+++ src/ControlStruct/MultiLevelExit.cpp	(revision 553f032fc07a39fc4fc69943eb5e97e2504b74a1)
@@ -10,6 +10,6 @@
 // Created On       : Mon Nov  1 13:48:00 2021
 // Last Modified By : Andrew Beach
-// Last Modified On : Wed Sep  6 12:00:00 2023
-// Update Count     : 35
+// Last Modified On : Fri Sep  8 17:04:00 2023
+// Update Count     : 36
 //
 
@@ -27,4 +27,14 @@
 
 namespace {
+
+/// The return context is used to remember if returns are allowed and if
+/// not, why not. It is the nearest local control flow blocking construct.
+enum ReturnContext {
+	MayReturn,
+	InTryWithHandler,
+	InResumeHandler,
+	InTerminateHandler,
+	InFinally,
+};
 
 class Entry {
@@ -126,4 +136,5 @@
 	void previsit( const TryStmt * );
 	void postvisit( const TryStmt * );
+	void previsit( const CatchClause * );
 	void previsit( const FinallyClause * );
 
@@ -134,5 +145,5 @@
 	vector<Entry> enclosing_control_structures;
 	Label break_label;
-	bool inFinally;
+	ReturnContext ret_context;
 
 	template<typename LoopNode>
@@ -144,4 +155,6 @@
 		const list<ptr<Stmt>> & kids, bool caseClause );
 
+	void enterSealedContext( ReturnContext );
+
 	template<typename UnaryPredicate>
 	auto findEnclosingControlStructure( UnaryPredicate pred ) {
@@ -157,5 +170,5 @@
 MultiLevelExitCore::MultiLevelExitCore( const LabelToStmt & lt ) :
 	target_table( lt ), break_label( CodeLocation(), "" ),
-	inFinally( false )
+	ret_context( ReturnContext::MayReturn )
 {}
 
@@ -488,7 +501,24 @@
 
 void MultiLevelExitCore::previsit( const ReturnStmt * stmt ) {
-	if ( inFinally ) {
-		SemanticError( stmt->location, "'return' may not appear in a finally clause" );
-	}
+	char const * context;
+	switch ( ret_context ) {
+	case ReturnContext::MayReturn:
+		return;
+	case ReturnContext::InTryWithHandler:
+		context = "try statement with a catch clause";
+		break;
+	case ReturnContext::InResumeHandler:
+		context = "catchResume clause";
+		break;
+	case ReturnContext::InTerminateHandler:
+		context = "catch clause";
+		break;
+	case ReturnContext::InFinally:
+		context = "finally clause";
+		break;
+	default:
+		assert(0);
+	}
+	SemanticError( stmt->location, toString( "'return' may not appear in a ", context ) );
 }
 
@@ -500,4 +530,11 @@
 		GuardAction([this](){ enclosing_control_structures.pop_back(); } );
 	}
+
+	// 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 );
+		}
+	}
 }
 
@@ -512,8 +549,12 @@
 }
 
+void MultiLevelExitCore::previsit( const CatchClause * clause ) {
+	ReturnContext context = ( ast::Terminate == clause->kind )
+		? ReturnContext::InTerminateHandler : ReturnContext::InResumeHandler;
+	enterSealedContext( context );
+}
+
 void MultiLevelExitCore::previsit( const FinallyClause * ) {
-	GuardAction([this, old = std::move( enclosing_control_structures)](){ enclosing_control_structures = std::move(old); });
-	enclosing_control_structures = vector<Entry>();
-	GuardValue( inFinally ) = true;
+	enterSealedContext( ReturnContext::InFinally );
 }
 
@@ -617,4 +658,10 @@
 }
 
+void MultiLevelExitCore::enterSealedContext( ReturnContext enter_context ) {
+	GuardAction([this, old = std::move(enclosing_control_structures)](){ enclosing_control_structures = std::move(old); });
+	enclosing_control_structures = vector<Entry>();
+	GuardValue( ret_context ) = enter_context;
+}
+
 } // namespace
 
Index: sts/exceptions/.expect/finally-error.txt
===================================================================
--- tests/exceptions/.expect/finally-error.txt	(revision 2fa0237f52bd8db42015c83dee0d38191a902db4)
+++ 	(revision )
@@ -1,15 +1,0 @@
-exceptions/finally-error.cfa:7:1 error: 'break' outside a loop, 'switch', or labelled block
-exceptions/finally-error.cfa:15:1 error: 'break' outside a loop, 'switch', or labelled block
-exceptions/finally-error.cfa:23:1 error: 'break' outside a loop, 'switch', or labelled block
-exceptions/finally-error.cfa:31:1 error: 'continue' target must be an enclosing loop: 
-exceptions/finally-error.cfa:48:1 error: 'break' target must be an enclosing control structure: mainLoop
-exceptions/finally-error.cfa:56:1 error: 'continue' target must be an enclosing loop: mainLoop
-exceptions/finally-error.cfa:65:1 error: 'break' outside a loop, 'switch', or labelled block
-exceptions/finally-error.cfa:76:1 error: 'break' outside a loop, 'switch', or labelled block
-exceptions/finally-error.cfa:87:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
-exceptions/finally-error.cfa:98:1 error: 'break' target must be an enclosing control structure: mainBlock
-exceptions/finally-error.cfa:111:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
-exceptions/finally-error.cfa:124:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
-exceptions/finally-error.cfa:133:1 error: 'return' may not appear in a finally clause
-exceptions/finally-error.cfa:139:1 error: 'return' may not appear in a finally clause
-exceptions/finally-error.cfa:148:1 error: 'break' outside a loop, 'switch', or labelled block
Index: tests/exceptions/.expect/try-ctrl-flow.txt
===================================================================
--- tests/exceptions/.expect/try-ctrl-flow.txt	(revision 553f032fc07a39fc4fc69943eb5e97e2504b74a1)
+++ tests/exceptions/.expect/try-ctrl-flow.txt	(revision 553f032fc07a39fc4fc69943eb5e97e2504b74a1)
@@ -0,0 +1,18 @@
+exceptions/try-ctrl-flow.cfa:7:1 error: 'break' outside a loop, 'switch', or labelled block
+exceptions/try-ctrl-flow.cfa:15:1 error: 'break' outside a loop, 'switch', or labelled block
+exceptions/try-ctrl-flow.cfa:23:1 error: 'break' outside a loop, 'switch', or labelled block
+exceptions/try-ctrl-flow.cfa:31:1 error: 'continue' target must be an enclosing loop: 
+exceptions/try-ctrl-flow.cfa:48:1 error: 'break' target must be an enclosing control structure: mainLoop
+exceptions/try-ctrl-flow.cfa:56:1 error: 'continue' target must be an enclosing loop: mainLoop
+exceptions/try-ctrl-flow.cfa:65:1 error: 'break' outside a loop, 'switch', or labelled block
+exceptions/try-ctrl-flow.cfa:76:1 error: 'break' outside a loop, 'switch', or labelled block
+exceptions/try-ctrl-flow.cfa:87:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
+exceptions/try-ctrl-flow.cfa:98:1 error: 'break' target must be an enclosing control structure: mainBlock
+exceptions/try-ctrl-flow.cfa:111:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
+exceptions/try-ctrl-flow.cfa:124:1 error: 'fallthrough' must be enclosed in a 'switch' or 'choose'
+exceptions/try-ctrl-flow.cfa:133:1 error: 'return' may not appear in a finally clause
+exceptions/try-ctrl-flow.cfa:139:1 error: 'return' may not appear in a finally clause
+exceptions/try-ctrl-flow.cfa:148:1 error: 'break' outside a loop, 'switch', or labelled block
+exceptions/try-ctrl-flow.cfa:159:1 error: 'return' may not appear in a try statement with a catch clause
+exceptions/try-ctrl-flow.cfa:187:1 error: 'return' may not appear in a catch clause
+exceptions/try-ctrl-flow.cfa:195:1 error: 'return' may not appear in a catchResume clause
Index: sts/exceptions/finally-error.cfa
===================================================================
--- tests/exceptions/finally-error.cfa	(revision 2fa0237f52bd8db42015c83dee0d38191a902db4)
+++ 	(revision )
@@ -1,156 +1,0 @@
-// All of these should be caught as long as the check remains in the same
-// pass. (Although not even all of the checks are in place yet.)
-
-void break_in_finally() {
-	while (true) {
-		try {} finally {
-			break;
-		}
-	}
-}
-
-void for_break_in_finally() {
-	for (10) {
-		try {} finally {
-			break;
-		}
-	}
-}
-
-void do_while_break_in_finally() {
-	do {
-		try {} finally {
-			break;
-		}
-	} while (false);
-}
-
-void continue_in_finally() {
-	while (true) {
-		try {} finally {
-			continue;
-		}
-	}
-}
-
-void goto_in_finally() {
-	while (true) {
-		try {} finally {
-			goto end_of_function;
-		}
-	}
-	end_of_function: {}
-}
-
-void labelled_break_in_finally() {
-	mainLoop: while (true) {
-		try {} finally {
-			break mainLoop;
-		}
-	}
-}
-
-void labelled_continue_in_finally() {
-	mainLoop: while (true) {
-		try {} finally {
-			continue mainLoop;
-		}
-	}
-}
-
-void switch_break_in_finally() {
-	switch (1) {
-	case 1:
-		try {} finally {
-			break;
-		}
-	default:
-		break;
-	}
-}
-
-void choose_break_in_finally() {
-	choose (1) {
-	case 1:
-		try {} finally {
-			break;
-		}
-	default:
-		break;
-	}
-}
-
-void choose_fallthru_in_finally() {
-	choose (1) {
-	case 1:
-		try {} finally {
-			fallthru;
-		}
-	default:
-		break;
-	}
-}
-
-void labelled_choose_break_in_finally() {
-	mainBlock: choose (1) {
-	case 1:
-		try {} finally {
-			break mainBlock;
-		}
-	case 2:
-		break;
-	default:
-		break;
-	}
-}
-
-void labelled_choose_fallthru_in_finally() {
-	mainBlock: choose (1) {
-	case 1:
-		try {} finally {
-			fallthru mainBlock;
-		}
-	case 2:
-		break;
-	default:
-		break;
-	}
-}
-
-void choose_fallthru_default_in_finally() {
-	choose (1) {
-	case 1:
-		try {} finally {
-			fallthru default;
-		}
-	default:
-		break;
-	}
-}
-
-void void_return_in_finally() {
-	try {} finally {
-		return;
-	}
-}
-
-int value_return_in_finally() {
-	try {} finally {
-		return -7;
-	}
-
-}
-
-// Checked in the same place, make sure it does't break.
-void break_in_function() {
-	while (true) {
-		void inner() {
-			break;
-		}
-	}
-}
-
-void main() {
-	// Should not compile.
-	return 1;
-}
Index: tests/exceptions/try-ctrl-flow.cfa
===================================================================
--- tests/exceptions/try-ctrl-flow.cfa	(revision 553f032fc07a39fc4fc69943eb5e97e2504b74a1)
+++ tests/exceptions/try-ctrl-flow.cfa	(revision 553f032fc07a39fc4fc69943eb5e97e2504b74a1)
@@ -0,0 +1,202 @@
+// Check all the local control flow structures that are "sealed" by some the
+// try statement clauses; where structured programming is stricter.
+
+void break_in_finally() {
+	while (true) {
+		try {} finally {
+			break;
+		}
+	}
+}
+
+void for_break_in_finally() {
+	for (10) {
+		try {} finally {
+			break;
+		}
+	}
+}
+
+void do_while_break_in_finally() {
+	do {
+		try {} finally {
+			break;
+		}
+	} while (false);
+}
+
+void continue_in_finally() {
+	while (true) {
+		try {} finally {
+			continue;
+		}
+	}
+}
+
+void goto_in_finally() {
+	while (true) {
+		try {} finally {
+			goto end_of_function;
+		}
+	}
+	end_of_function: {}
+}
+
+void labelled_break_in_finally() {
+	mainLoop: while (true) {
+		try {} finally {
+			break mainLoop;
+		}
+	}
+}
+
+void labelled_continue_in_finally() {
+	mainLoop: while (true) {
+		try {} finally {
+			continue mainLoop;
+		}
+	}
+}
+
+void switch_break_in_finally() {
+	switch (1) {
+	case 1:
+		try {} finally {
+			break;
+		}
+	default:
+		break;
+	}
+}
+
+void choose_break_in_finally() {
+	choose (1) {
+	case 1:
+		try {} finally {
+			break;
+		}
+	default:
+		break;
+	}
+}
+
+void choose_fallthru_in_finally() {
+	choose (1) {
+	case 1:
+		try {} finally {
+			fallthru;
+		}
+	default:
+		break;
+	}
+}
+
+void labelled_choose_break_in_finally() {
+	mainBlock: choose (1) {
+	case 1:
+		try {} finally {
+			break mainBlock;
+		}
+	case 2:
+		break;
+	default:
+		break;
+	}
+}
+
+void labelled_choose_fallthru_in_finally() {
+	mainBlock: choose (1) {
+	case 1:
+		try {} finally {
+			fallthru mainBlock;
+		}
+	case 2:
+		break;
+	default:
+		break;
+	}
+}
+
+void choose_fallthru_default_in_finally() {
+	choose (1) {
+	case 1:
+		try {} finally {
+			fallthru default;
+		}
+	default:
+		break;
+	}
+}
+
+void void_return_in_finally() {
+	try {} finally {
+		return;
+	}
+}
+
+int value_return_in_finally() {
+	try {} finally {
+		return -7;
+	}
+
+}
+
+// Checked in the same place, make sure it does't break.
+void break_in_function() {
+	while (true) {
+		void inner() {
+			break;
+		}
+	}
+}
+
+// Now just use return to test the other try control flow interactions.
+
+exception nil_exception {};
+
+void return_in_try_with_catch() {
+	try {
+		return;
+	} catch (nil_exception *) {
+		;
+	}
+}
+
+// Allowed.
+void return_in_try_with_catchReturn() {
+	try {
+		return;
+	} catchResume (nil_exception *) {
+		;
+	}
+}
+
+// Allowed.
+void return_in_try_with_finally() {
+	try {
+		return;
+	} finally {
+		;
+	}
+}
+
+void return_in_catch() {
+	try {
+		;
+	} catch (nil_exception *) {
+		return;
+	}
+}
+
+void return_in_catchResume() {
+	try {
+		;
+	} catchResume (nil_exception *) {
+		return;
+	}
+}
+
+void main() {
+	// Should not compile.
+	return 1;
+}
