Index: libcfa/prelude/extras.c
===================================================================
--- libcfa/prelude/extras.c	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ libcfa/prelude/extras.c	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -3,4 +3,5 @@
 #include <uchar.h>					// char16_t, char32_t
 #include <wchar.h>					// wchar_t
-#include <stdlib.h>					// malloc, free, exit, atexit, abort
+#include <stdlib.h>					// malloc, free, getenv, exit, atexit, abort, printf
 #include <stdio.h>					// printf
+#include <string.h>					// strlen, strcmp, strncmp
Index: libcfa/prelude/extras.regx2
===================================================================
--- libcfa/prelude/extras.regx2	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ libcfa/prelude/extras.regx2	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -1,6 +1,10 @@
 extern void \*malloc[^;]*;
 extern void free[^;]*;
+extern char \*getenv[^;]*;
 extern void exit[^;]*;
 extern int atexit[^;]*;
 extern void abort[^;]*;
 extern int printf[^;]*;
+int strcmp[^;]*;
+int strncmp[^;]*;
+size_t strlen[^;]*;
Index: libcfa/src/clock.hfa
===================================================================
--- libcfa/src/clock.hfa	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ libcfa/src/clock.hfa	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -10,6 +10,6 @@
 // Created On       : Thu Apr 12 14:36:06 2018
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Apr 18 08:12:16 2021
-// Update Count     : 28
+// Last Modified On : Sat Sep  9 14:07:17 2023
+// Update Count     : 30
 //
 
@@ -91,18 +91,18 @@
 	// discontinuous jumps when the OS is not running the kernal thread. A duration is returned because the value is
 	// relative and cannot be converted to real-time (wall-clock) time.
-	Duration processor() {								// non-monotonic duration of kernel thread
+	Duration processor_cpu() {							// non-monotonic duration of kernel thread
 		timespec ts;
 		clock_gettime( CLOCK_THREAD_CPUTIME_ID, &ts );
 		return (Duration){ ts };
-	} // processor
+	} // processor_cpu
 
 	// Program CPU-time watch measures CPU time consumed by all processors (kernel threads) in the UNIX process.  This
 	// watch is affected by discontinuous jumps when the OS is not running the kernel threads. A duration is returned
 	// because the value is relative and cannot be converted to real-time (wall-clock) time.
-	Duration program() {								// non-monotonic duration of program CPU
+	Duration program_cpu() {							// non-monotonic duration of program CPU
 		timespec ts;
 		clock_gettime( CLOCK_PROCESS_CPUTIME_ID, &ts );
 		return (Duration){ ts };
-	} // program
+	} // program_cpu
 
 	// Monotonic duration from machine boot and including system suspension. This watch is unaffected by discontinuous
Index: libcfa/src/concurrency/kernel/cluster.hfa
===================================================================
--- libcfa/src/concurrency/kernel/cluster.hfa	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ libcfa/src/concurrency/kernel/cluster.hfa	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -31,6 +31,6 @@
 
 // warn normally all ints
-#define warn_large_before warnf( !strict || old_avg < 33_000_000_000, "Suspiciously large previous average: %'llu (%llx), %'" PRId64 "ms \n", old_avg, old_avg, program()`ms )
-#define warn_large_after warnf( !strict || ret < 33_000_000_000, "Suspiciously large new average after %'" PRId64 "ms cputime: %'llu (%llx) from %'llu-%'llu (%'llu, %'llu) and %'llu\n", program()`ms, ret, ret, currtsc, intsc, new_val, new_val / 1000000, old_avg )
+#define warn_large_before warnf( !strict || old_avg < 33_000_000_000, "Suspiciously large previous average: %'llu (%llx), %'" PRId64 "ms \n", old_avg, old_avg, program_cpu()`ms )
+#define warn_large_after warnf( !strict || ret < 33_000_000_000, "Suspiciously large new average after %'" PRId64 "ms cputime: %'llu (%llx) from %'llu-%'llu (%'llu, %'llu) and %'llu\n", program_cpu()`ms, ret, ret, currtsc, intsc, new_val, new_val / 1000000, old_avg )
 
 // 8X linear factor is just 8 * x
@@ -42,6 +42,6 @@
 static inline __readyQ_avg_t __to_readyQ_avg(unsigned long long intsc) { if(unlikely(0 == intsc)) return 0.0; else return log2((__readyQ_avg_t)intsc); }
 
-#define warn_large_before warnf( !strict || old_avg < 35.0, "Suspiciously large previous average: %'lf, %'" PRId64 "ms \n", old_avg, program()`ms )
-#define warn_large_after warnf( !strict || ret < 35.3, "Suspiciously large new average after %'" PRId64 "ms cputime: %'lf from %'llu-%'llu (%'llu, %'llu) and %'lf\n", program()`ms, ret, currtsc, intsc, new_val, new_val / 1000000, old_avg ); \
+#define warn_large_before warnf( !strict || old_avg < 35.0, "Suspiciously large previous average: %'lf, %'" PRId64 "ms \n", old_avg, program_cpu()`ms )
+#define warn_large_after warnf( !strict || ret < 35.3, "Suspiciously large new average after %'" PRId64 "ms cputime: %'lf from %'llu-%'llu (%'llu, %'llu) and %'lf\n", program_cpu()`ms, ret, currtsc, intsc, new_val, new_val / 1000000, old_avg ); \
 verify(ret >= 0)
 
Index: libcfa/src/heap.cfa
===================================================================
--- libcfa/src/heap.cfa	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ libcfa/src/heap.cfa	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -10,6 +10,6 @@
 // Created On       : Tue Dec 19 21:58:35 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Aug  2 18:48:30 2023
-// Update Count     : 1614
+// Last Modified On : Mon Sep 11 11:21:10 2023
+// Update Count     : 1615
 //
 
@@ -691,4 +691,16 @@
 	return stats;
 } // collectStats
+
+static inline void clearStats() {
+	lock( mgrLock );
+
+	// Zero the heap master and all active thread heaps.
+	HeapStatisticsCtor( heapMaster.stats );
+	for ( Heap * heap = heapMaster.heapManagersList; heap; heap = heap->nextHeapManager ) {
+		HeapStatisticsCtor( heap->stats );
+	} // for
+
+	unlock( mgrLock );
+} // clearStats
 #endif // __STATISTICS__
 
@@ -1556,4 +1568,17 @@
 
 
+	// Zero the heap master and all active thread heaps.
+	void malloc_stats_clear() {
+		#ifdef __STATISTICS__
+		clearStats();
+		#else
+		#define MALLOC_STATS_MSG "malloc_stats statistics disabled.\n"
+		if ( write( STDERR_FILENO, MALLOC_STATS_MSG, sizeof( MALLOC_STATS_MSG ) - 1 /* size includes '\0' */ ) == -1 ) {
+			abort( "**** Error **** write failed in malloc_stats" );
+		} // if
+		#endif // __STATISTICS__
+	} // malloc_stats_clear
+
+
 	// Changes the file descriptor where malloc_stats() writes statistics.
 	int malloc_stats_fd( int fd __attribute__(( unused )) ) libcfa_public {
Index: libcfa/src/heap.hfa
===================================================================
--- libcfa/src/heap.hfa	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ libcfa/src/heap.hfa	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -10,6 +10,6 @@
 // Created On       : Tue May 26 11:23:55 2020
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Oct  4 19:08:55 2022
-// Update Count     : 23
+// Last Modified On : Mon Sep 11 11:18:18 2023
+// Update Count     : 24
 // 
 
@@ -43,4 +43,5 @@
 	size_t malloc_mmap_start();							// crossover allocation size from sbrk to mmap
 	size_t malloc_unfreed();							// heap unfreed size (bytes)
+	void malloc_stats_clear();							// clear heap statistics
 } // extern "C"
 
Index: libcfa/src/iostream.cfa
===================================================================
--- libcfa/src/iostream.cfa	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ libcfa/src/iostream.cfa	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -1,2 +1,3 @@
+
 //
 // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
@@ -976,5 +977,10 @@
 		if ( f.flags.ignore ) { fmtstr[1] = '*'; start += 1; }
 		// no maximum width necessary because text ignored => width is read width
-		if ( f.wd != -1 ) { start += sprintf( &fmtstr[start], "%d", f.wd ); }
+		if ( f.wd != -1 ) {
+			// wd is buffer bytes available (for input chars + null terminator)
+			// rwd is count of input chars
+			int rwd = f.flags.rwd ? f.wd : (f.wd - 1);
+			start += sprintf( &fmtstr[start], "%d", rwd );
+		}
 
 		if ( ! scanset ) {
@@ -993,5 +999,5 @@
 		} // if
 
-		int check = f.wd - 1;
+		int check = f.wd - 2;
 		if ( ! f.flags.rwd ) f.s[check] = '\0';			// insert sentinel
 		len = fmt( is, fmtstr, f.s );
Index: src/ControlStruct/MultiLevelExit.cpp
===================================================================
--- src/ControlStruct/MultiLevelExit.cpp	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ src/ControlStruct/MultiLevelExit.cpp	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -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: tests/concurrency/waituntil/locks.cfa
===================================================================
--- tests/concurrency/waituntil/locks.cfa	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ tests/concurrency/waituntil/locks.cfa	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -73,2 +73,3 @@
     printf("done\n");
 }
+
Index: sts/exceptions/.expect/finally-error.txt
===================================================================
--- tests/exceptions/.expect/finally-error.txt	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ 	(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 c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
+++ tests/exceptions/.expect/try-ctrl-flow.txt	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -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 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ 	(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 c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
+++ tests/exceptions/try-ctrl-flow.cfa	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -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;
+}
Index: tests/io/.expect/manipulatorsInput.arm64.txt
===================================================================
--- tests/io/.expect/manipulatorsInput.arm64.txt	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ tests/io/.expect/manipulatorsInput.arm64.txt	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -1,2 +1,5 @@
+pre1 "123456", canary ok
+pre2a "1234567", exception occurred, canary ok
+pre2b "89", canary ok
 1 yyyyyyyyyyyyyyyyyyyy
 2 abcxxx
Index: tests/io/.expect/manipulatorsInput.x64.txt
===================================================================
--- tests/io/.expect/manipulatorsInput.x64.txt	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ tests/io/.expect/manipulatorsInput.x64.txt	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -1,2 +1,5 @@
+pre1 "123456", canary ok
+pre2a "1234567", exception occurred, canary ok
+pre2b "89", canary ok
 1 yyyyyyyyyyyyyyyyyyyy
 2 abcxxx
Index: tests/io/.expect/manipulatorsInput.x86.txt
===================================================================
--- tests/io/.expect/manipulatorsInput.x86.txt	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ tests/io/.expect/manipulatorsInput.x86.txt	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -1,2 +1,5 @@
+pre1 "123456", canary ok
+pre2a "1234567", exception occurred, canary ok
+pre2b "89", canary ok
 1 yyyyyyyyyyyyyyyyyyyy
 2 abcxxx
Index: tests/io/.in/manipulatorsInput.txt
===================================================================
--- tests/io/.in/manipulatorsInput.txt	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ tests/io/.in/manipulatorsInput.txt	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -1,2 +1,4 @@
+123456
+123456789
 abc 
 abc 
Index: tests/io/manipulatorsInput.cfa
===================================================================
--- tests/io/manipulatorsInput.cfa	(revision 9509d67a48906b243fdd5104ab679d3e1ea4a532)
+++ tests/io/manipulatorsInput.cfa	(revision c8ec58e70ef94c1c6a9bdfc71210e7f863368795)
@@ -15,4 +15,39 @@
 
 int main() {
+	{
+		// Upfront checks to ensure buffer safety.  Once these pass, the simpler `wdi(sizeof(s),s)`
+		// usage, as in the scanf alignment cases below, is justified.
+		struct {
+			char buf[8];
+			char canary;
+		} data;
+		static_assert( sizeof(data.buf) == 8 );
+		static_assert( &data.buf[8] == &data.canary );  // canary comes right after buf
+
+		void rep(const char* casename) {
+			data.canary = 42;
+			bool caught = false;
+			try {
+				sin | wdi( sizeof(data.buf), data.buf );
+			} catch (cstring_length*) {
+				caught = true;
+			}
+			printf( "%s \"%s\"", casename, data.buf );
+			if ( caught ) {
+				printf(", exception occurred");
+			}
+			if ( data.canary == 42 ) {
+				printf(", canary ok");
+			} else {
+				printf(", canary overwritten to %d", data.canary);
+			}
+			printf("\n");
+		}
+
+		rep("pre1");
+		rep("pre2a");
+		rep("pre2b");
+		scanf("\n");  // next test does not start with %s so does not tolerate leading whitespace
+	}
 	{
 		char s[] = "yyyyyyyyyyyyyyyyyyyy";
