Index: benchmark/process-mutilate.py
===================================================================
--- benchmark/process-mutilate.py	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ benchmark/process-mutilate.py	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -32,5 +32,5 @@
 
 	try:
-		latAvs = fields[6]
+		latAvs = fields[1]
 		lat50s = fields[6]
 		lat99s = fields[9]
@@ -45,5 +45,5 @@
 		raise Warning("Warning: \"{}\" \"{}\"! can't convert to float".format(lat50s, lat99s))
 
-	return lat50, lat99
+	return latAv, lat50, lat99
 
 def want0(line):
Index: benchmark/readyQ/bench.go
===================================================================
--- benchmark/readyQ/bench.go	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ benchmark/readyQ/bench.go	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -71,5 +71,5 @@
 		duration = 5
 		clock_mode = true
-		fmt.Printf("Running for %f seconds\n", duration)
+		fmt.Printf("Running for %f seconds (default)\n", duration)
 	}
 
Index: benchmark/readyQ/churn.cpp
===================================================================
--- benchmark/readyQ/churn.cpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ benchmark/readyQ/churn.cpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -54,5 +54,6 @@
 			Fibre * threads[nthreads];
 			for(unsigned i = 0; i < nthreads; i++) {
-				threads[i] = new Fibre( reinterpret_cast<void (*)(void *)>(churner_main), &thddata[i] );
+				threads[i] = new Fibre();
+				threads[i]->run(churner_main, &thddata[i]);
 			}
 			printf("Starting\n");
Index: benchmark/readyQ/cycle.cpp
===================================================================
--- benchmark/readyQ/cycle.cpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ benchmark/readyQ/cycle.cpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -46,5 +46,6 @@
 			}
 			for(unsigned i = 0; i < tthreads; i++) {
-				threads[i] = new Fibre( reinterpret_cast<void (*)(void *)>(partner_main), &thddata[i] );
+				threads[i] = new Fibre();
+				threads[i]->run( partner_main, &thddata[i] );
 			}
 			printf("Starting\n");
Index: benchmark/readyQ/rq_bench.hpp
===================================================================
--- benchmark/readyQ/rq_bench.hpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ benchmark/readyQ/rq_bench.hpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -143,5 +143,25 @@
 	}
 
+	if(strcmp(arg, "Y") == 0) {
+		value = true;
+		return true;
+	}
+
+	if(strcmp(arg, "y") == 0) {
+		value = true;
+		return true;
+	}
+
 	if(strcmp(arg, "no") == 0) {
+		value = false;
+		return true;
+	}
+
+	if(strcmp(arg, "N") == 0) {
+		value = false;
+		return true;
+	}
+
+	if(strcmp(arg, "n") == 0) {
 		value = false;
 		return true;
Index: benchmark/readyQ/transfer.cfa
===================================================================
--- benchmark/readyQ/transfer.cfa	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ benchmark/readyQ/transfer.cfa	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -14,4 +14,6 @@
 
 bool exhaust = false;
+volatile bool estop = false;
+
 
 thread$ * the_main;
@@ -35,5 +37,5 @@
 static void waitgroup() {
 	Time start = timeHiRes();
-	for(i; nthreads) {
+	OUTER: for(i; nthreads) {
 		PRINT( sout | "Waiting for :" | i | "(" | threads[i]->idx | ")"; )
 		while( threads[i]->idx != lead_idx ) {
@@ -42,5 +44,7 @@
 				print_stats_now( bench_cluster, CFA_STATS_READY_Q | CFA_STATS_IO );
 				serr | "Programs has been blocked for more than 5 secs";
-				exit(1);
+				estop = true;
+				unpark( the_main );
+				break OUTER;
 			}
 		}
@@ -59,5 +63,5 @@
 static void lead(MyThread & this) {
 	this.idx = ++lead_idx;
-	if(lead_idx > stop_count) {
+	if(lead_idx > stop_count || estop) {
 		PRINT( sout | "Leader" | this.id | "done"; )
 		unpark( the_main );
@@ -100,5 +104,5 @@
 			wait( this );
 		}
-		if(lead_idx > stop_count) break;
+		if(lead_idx > stop_count || estop) break;
 	}
 }
@@ -172,7 +176,8 @@
 	sout | "Number of processors    : " | nprocs;
 	sout | "Number of threads       : " | nthreads;
-	sout | "Total Operations(ops)   : " | stop_count;
+	sout | "Total Operations(ops)   : " | lead_idx - 1;
 	sout | "Threads parking on wait : " | (exhaust ? "yes" : "no");
 	sout | "Rechecking              : " | rechecks;
+	sout | "ns per transfer         : " | (end - start)`dms / lead_idx;
 
 
Index: benchmark/readyQ/transfer.cpp
===================================================================
--- benchmark/readyQ/transfer.cpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ benchmark/readyQ/transfer.cpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -12,4 +12,5 @@
 
 bool exhaust = false;
+volatile bool estop = false;
 
 bench_sem the_main;
@@ -42,8 +43,11 @@
 				if( to_miliseconds(timeHiRes() - start) > 5'000 ) {
 					std::cerr << "Programs has been blocked for more than 5 secs" << std::endl;
-					std::exit(1);
+					estop = true;
+					the_main.post();
+					goto END;
 				}
 			}
 		}
+		END:;
 		PRINT( std::cout | "Waiting done"; )
 	}
@@ -59,5 +63,5 @@
 	void lead() {
 		this->idx = ++lead_idx;
-		if(lead_idx > stop_count) {
+		if(lead_idx > stop_count || estop) {
 			PRINT( std::cout << "Leader " << this->id << " done" << std::endl; )
 			the_main.post();
@@ -88,6 +92,6 @@
 	}
 
-	static void main(void * arg) {
-		MyThread & self = *reinterpret_cast<MyThread*>(arg);
+	static void main(MyThread * arg) {
+		MyThread & self = *arg;
 		self.park();
 
@@ -101,5 +105,5 @@
 				self.wait();
 			}
-			if(lead_idx > stop_count) break;
+			if(lead_idx > stop_count || estop) break;
 		}
 	}
@@ -144,5 +148,6 @@
 			for(size_t i = 0; i < nthreads; i++) {
 				threads[i] = new MyThread( i );
-				handles[i] = new Fibre( MyThread::main, threads[i] );
+				handles[i] = new Fibre();
+				handles[i]->run( MyThread::main, threads[i] );
 			}
 
@@ -164,5 +169,4 @@
 				PRINT( std::cout << i << " joined" << std::endl; )
 				rechecks += thrd.rechecks;
-				// delete( handles[i] );
 				delete( threads[i] );
 			}
@@ -176,7 +180,8 @@
 	std::cout << "Number of processors    : " << nprocs << std::endl;
 	std::cout << "Number of threads       : " << nthreads << std::endl;
-	std::cout << "Total Operations(ops)   : " << stop_count << std::endl;
+	std::cout << "Total Operations(ops)   : " << (lead_idx - 1) << std::endl;
 	std::cout << "Threads parking on wait : " << (exhaust ? "yes" : "no") << std::endl;
 	std::cout << "Rechecking              : " << rechecks << std::endl;
+	std::cout << "ns per transfer         : " << std::fixed << (((double)(end - start)) / (lead_idx)) << std::endl;
 
 
Index: benchmark/readyQ/transfer.go
===================================================================
--- benchmark/readyQ/transfer.go	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ benchmark/readyQ/transfer.go	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -6,4 +6,5 @@
 	"math/rand"
 	"os"
+	"regexp"
 	"runtime"
 	"sync/atomic"
@@ -16,4 +17,5 @@
 	id uint64
 	idx uint64
+	estop uint64
 	seed uint64
 }
@@ -34,5 +36,5 @@
 
 func NewLeader(size uint64) (*LeaderInfo) {
-	this := &LeaderInfo{0, 0, uint64(os.Getpid())}
+	this := &LeaderInfo{0, 0, 0, uint64(os.Getpid())}
 
 	r := rand.Intn(10)
@@ -51,6 +53,7 @@
 }
 
-func waitgroup(idx uint64, threads [] MyThread) {
+func waitgroup(leader * LeaderInfo, idx uint64, threads [] MyThread, main_sem chan struct {}) {
 	start := time.Now()
+	Outer:
 	for i := 0; i < len(threads); i++ {
 		// fmt.Fprintf(os.Stderr, "Waiting for :%d (%d)\n", threads[i].id, atomic.LoadUint64(&threads[i].idx) );
@@ -61,5 +64,7 @@
 			if delta.Seconds() > 5 {
 				fmt.Fprintf(os.Stderr, "Programs has been blocked for more than 5 secs")
-				os.Exit(1)
+				atomic.StoreUint64(&leader.estop, 1);
+				main_sem <- (struct {}{})
+				break Outer
 			}
 		}
@@ -74,4 +79,9 @@
 		if i != me {
 			// debug!( "Leader waking {}", i);
+			defer func() {
+				if err := recover(); err != nil {
+					fmt.Fprintf(os.Stderr, "Panic occurred: %s\n", err)
+				}
+			}()
 			threads[i].sem <- (struct {}{})
 		}
@@ -84,5 +94,5 @@
 	atomic.StoreUint64(&leader.idx, nidx);
 
-	if nidx > stop_count {
+	if nidx > stop_count || atomic.LoadUint64(&leader.estop) != 0 {
 		// debug!( "Leader {} done", this.id);
 		main_sem <- (struct {}{})
@@ -92,5 +102,5 @@
 	// debug!( "====================\nLeader no {} : {}", nidx, this.id);
 
-	waitgroup(nidx, threads);
+	waitgroup(leader, nidx, threads, main_sem);
 
 	leader.next( uint64(len(threads)) );
@@ -146,5 +156,5 @@
 			waitleader( exhaust, leader, &threads[me], &r )
 		}
-		if atomic.LoadUint64(&leader.idx) > stop_count { break; }
+		if atomic.LoadUint64(&leader.idx) > stop_count || atomic.LoadUint64(&leader.estop) != 0 { break; }
 	}
 
@@ -155,12 +165,25 @@
 func main() {
 	// Benchmark specific command line arguments
-	exhaustOpt := flag.Bool("e", false, "Whether or not threads that have seen the new epoch should park instead of yielding.")
+	exhaustOpt := flag.String("e", "no", "Whether or not threads that have seen the new epoch should park instead of yielding.")
 
 	// General benchmark initialization and deinitialization
-	defer bench_init()()
-
-	exhaust := *exhaustOpt;
+	bench_init()
+
+	exhaustVal := *exhaustOpt;
+
+	var exhaust bool
+	re_yes := regexp.MustCompile("[Yy]|[Yy][Ee][Ss]")
+	re_no  := regexp.MustCompile("[Nn]|[Nn][Oo]")
+	if re_yes.Match([]byte(exhaustVal)) {
+		exhaust = true
+	} else if re_no.Match([]byte(exhaustVal)) {
+		exhaust = false
+	} else {
+		fmt.Fprintf(os.Stderr, "Unrecognized exhaust(-e) option '%s'\n", exhaustVal)
+		os.Exit(1)
+	}
+
 	if clock_mode {
-		fmt.Fprintf(os.Stderr, "Programs does not support fixed duration mode")
+		fmt.Fprintf(os.Stderr, "Programs does not support fixed duration mode\n")
 		os.Exit(1)
 	}
@@ -215,9 +238,10 @@
 		ws = "no"
 	}
-	p.Printf("Duration (ms)           : %f\n", delta.Milliseconds() )
+	p.Printf("Duration (ms)           : %d\n", delta.Milliseconds() )
 	p.Printf("Number of processors    : %d\n", nprocs )
 	p.Printf("Number of threads       : %d\n", nthreads )
-	p.Printf("Total Operations(ops)   : %15d\n", stop_count )
+	p.Printf("Total Operations(ops)   : %15d\n", (leader.idx - 1) )
 	p.Printf("Threads parking on wait : %s\n", ws)
 	p.Printf("Rechecking              : %d\n", rechecks )
-}
+	p.Printf("ns per transfer         : %f\n", float64(delta.Nanoseconds()) / float64(leader.idx) )
+}
Index: benchmark/readyQ/transfer.rs
===================================================================
--- benchmark/readyQ/transfer.rs	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ benchmark/readyQ/transfer.rs	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -6,5 +6,5 @@
 use std::hint;
 use std::sync::Arc;
-use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
 use std::time::{Instant,Duration};
 
@@ -44,5 +44,9 @@
 			match val {
 				"yes" => true,
+				"Y" => true,
+				"y" => true,
 				"no"  => false,
+				"N"  => false,
+				"n"  => false,
 				"maybe" | "I don't know" | "Can you repeat the question?" => {
 					eprintln!("Lines for 'Malcolm in the Middle' are not acceptable values of parameter 'exhaust'");
@@ -64,4 +68,5 @@
 	id: AtomicUsize,
 	idx: AtomicUsize,
+	estop: AtomicBool,
 	seed: u128,
 }
@@ -72,4 +77,5 @@
 			id: AtomicUsize::new(nthreads),
 			idx: AtomicUsize::new(0),
+			estop: AtomicBool::new(false),
 			seed: process::id() as u128
 		};
@@ -100,7 +106,7 @@
 }
 
-fn waitgroup(idx: usize, threads: &Vec<Arc<MyThread>>) {
+fn waitgroup(leader: &LeaderInfo, idx: usize, threads: &Vec<Arc<MyThread>>, main_sem: &sync::Semaphore) {
 	let start = Instant::now();
-	for t in threads {
+	'outer: for t in threads {
 		debug!( "Waiting for :{} ({})", t.id, t.idx.load(Ordering::Relaxed) );
 		while t.idx.load(Ordering::Relaxed) != idx {
@@ -108,5 +114,7 @@
 			if start.elapsed() > Duration::from_secs(5) {
 				eprintln!("Programs has been blocked for more than 5 secs");
-				std::process::exit(1);
+				leader.estop.store(true, Ordering::Relaxed);
+				main_sem.add_permits(1);
+				break 'outer;
 			}
 		}
@@ -131,5 +139,5 @@
 	leader.idx.store(nidx, Ordering::Relaxed);
 
-	if nidx as u64 > exp.stop_count {
+	if nidx as u64 > exp.stop_count || leader.estop.load(Ordering::Relaxed) {
 		debug!( "Leader {} done", this.id);
 		main_sem.add_permits(1);
@@ -139,5 +147,5 @@
 	debug!( "====================\nLeader no {} : {}", nidx, this.id);
 
-	waitgroup(nidx, threads);
+	waitgroup(leader, nidx, threads, main_sem);
 
 	leader.next( threads.len() );
@@ -192,5 +200,5 @@
 			wait( exhaust, &leader, &threads[me], &mut rechecks ).await;
 		}
-		if leader.idx.load(Ordering::Relaxed) as u64 > exp.stop_count { break; }
+		if leader.idx.load(Ordering::Relaxed) as u64 > exp.stop_count || leader.estop.load(Ordering::Relaxed) { break; }
 	}
 
@@ -273,6 +281,8 @@
 	println!("Number of processors    : {}", (nprocs).to_formatted_string(&Locale::en));
 	println!("Number of threads       : {}", (nthreads).to_formatted_string(&Locale::en));
-	println!("Total Operations(ops)   : {:>15}", (exp.stop_count).to_formatted_string(&Locale::en));
+	println!("Total Operations(ops)   : {:>15}", (leader.idx.load(Ordering::Relaxed) - 1).to_formatted_string(&Locale::en));
 	println!("Threads parking on wait : {}", if exhaust { "yes" } else { "no" });
 	println!("Rechecking              : {}", rechecks );
-}
+	println!("ns per transfer         : {}", ((duration.as_nanos() as f64) / leader.idx.load(Ordering::Relaxed) as f64));
+
+}
Index: benchmark/readyQ/yield.cpp
===================================================================
--- benchmark/readyQ/yield.cpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ benchmark/readyQ/yield.cpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -10,5 +10,5 @@
 	unsigned long long count = 0;
 	for(;;) {
-		Fibre::forceYield();
+		Fibre::yield();
 		count++;
 		if( clock_mode && stop) break;
@@ -35,5 +35,6 @@
 			Fibre * threads[nthreads];
 			for(unsigned i = 0; i < nthreads; i++) {
-				threads[i] = new Fibre( reinterpret_cast<void (*)(void *)>(fibre_main), nullptr );
+				threads[i] = new Fibre();
+				threads[i]->run(fibre_main);
 			}
 			printf("Starting\n");
Index: benchmark/rmit.py
===================================================================
--- benchmark/rmit.py	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ benchmark/rmit.py	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -46,5 +46,7 @@
 		pass
 
-	if re.search("^[0-9-,]+$", values):
+	if values.startswith('\\'):
+		return key, values[1:].split(',')
+	elif re.search("^[0-9-,]+$", values):
 		values = parse_range(values)
 		return key, [v for v in values]
Index: libcfa/src/concurrency/io.cfa
===================================================================
--- libcfa/src/concurrency/io.cfa	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ libcfa/src/concurrency/io.cfa	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -244,5 +244,5 @@
 
 					remote = true;
-					__STATS__( false, io.calls.helped++; )
+					__STATS__( true, io.calls.helped++; )
 				}
 				proc->io.target = MAX;
Index: libcfa/src/concurrency/ready_subqueue.hfa
===================================================================
--- libcfa/src/concurrency/ready_subqueue.hfa	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ libcfa/src/concurrency/ready_subqueue.hfa	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -83,4 +83,5 @@
 	/* paranoid */ verify( node->link.ts   != 0  );
 	/* paranoid */ verify( this.anchor.ts  != 0  );
+	/* paranoid */ verify( (this.anchor.ts  == MAX) == is_empty );
 	return [node, this.anchor.ts];
 }
@@ -93,5 +94,5 @@
 // Return the timestamp
 static inline unsigned long long ts(__intrusive_lane_t & this) {
-	// Cannot verify here since it may not be locked
+	// Cannot verify 'emptiness' here since it may not be locked
 	/* paranoid */ verify(this.anchor.ts != 0);
 	return this.anchor.ts;
Index: libcfa/src/parseargs.cfa
===================================================================
--- libcfa/src/parseargs.cfa	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ libcfa/src/parseargs.cfa	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -208,5 +208,25 @@
 	}
 
+	if(strcmp(arg, "Y") == 0) {
+		value = true;
+		return true;
+	}
+
+	if(strcmp(arg, "y") == 0) {
+		value = true;
+		return true;
+	}
+
 	if(strcmp(arg, "no") == 0) {
+		value = false;
+		return true;
+	}
+
+	if(strcmp(arg, "N") == 0) {
+		value = false;
+		return true;
+	}
+
+	if(strcmp(arg, "n") == 0) {
 		value = false;
 		return true;
Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/AST/Convert.cpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -93,8 +93,8 @@
 	};
 
-    template<typename T>
-    Getter<T> get() {
-        return Getter<T>{ *this };
-    }
+	template<typename T>
+	Getter<T> get() {
+		return Getter<T>{ *this };
+	}
 
 	Label makeLabel(Statement * labelled, const ast::Label& label) {
@@ -1651,4 +1651,5 @@
 			// GET_ACCEPT_1(type, FunctionType),
 			std::move(forall),
+			std::move(assertions),
 			std::move(paramVars),
 			std::move(returnVars),
@@ -1664,5 +1665,4 @@
 		cache.emplace( old, decl );
 
-		decl->assertions = std::move(assertions);
 		decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
 		decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
Index: src/AST/Copy.cpp
===================================================================
--- src/AST/Copy.cpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/AST/Copy.cpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -10,6 +10,6 @@
 // Created On       : Thr Nov 11  9:16:00 2019
 // Last Modified By : Andrew Beach
-// Last Modified On : Thr Nov 11  9:28:00 2021
-// Update Count     : 0
+// Last Modified On : Tue May  3 16:28:00 2022
+// Update Count     : 1
 //
 
@@ -77,4 +77,8 @@
 	}
 
+	void postvisit( const UniqueExpr * node ) {
+		readonlyInsert( &node->object );
+	}
+
 	void postvisit( const MemberExpr * node ) {
 		readonlyInsert( &node->member );
Index: src/AST/Decl.cpp
===================================================================
--- src/AST/Decl.cpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/AST/Decl.cpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -9,7 +9,7 @@
 // Author           : Aaron B. Moss
 // Created On       : Thu May 9 10:00:00 2019
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jan 12 16:54:55 2021
-// Update Count     : 23
+// Last Modified By : Andrew Beach
+// Last Modified On : Thu May  5 12:10:00 2022
+// Update Count     : 24
 //
 
@@ -53,5 +53,5 @@
 // --- FunctionDecl
 
-FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name, 
+FunctionDecl::FunctionDecl( const CodeLocation & loc, const std::string & name,
 	std::vector<ptr<TypeDecl>>&& forall,
 	std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
@@ -74,4 +74,30 @@
 	}
 	this->type = ftype;
+}
+
+FunctionDecl::FunctionDecl( const CodeLocation & location, const std::string & name,
+	std::vector<ptr<TypeDecl>>&& forall, std::vector<ptr<DeclWithType>>&& assertions,
+	std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
+	CompoundStmt * stmts, Storage::Classes storage, Linkage::Spec linkage,
+	std::vector<ptr<Attribute>>&& attrs, Function::Specs fs, bool isVarArgs)
+: DeclWithType( location, name, storage, linkage, std::move(attrs), fs ),
+		params( std::move(params) ), returns( std::move(returns) ),
+		type_params( std::move( forall) ), assertions( std::move( assertions ) ),
+		type( nullptr ), stmts( stmts ) {
+	FunctionType * type = new FunctionType( (isVarArgs) ? VariableArgs : FixedArgs );
+	for ( auto & param : this->params ) {
+		type->params.emplace_back( param->get_type() );
+	}
+	for ( auto & ret : this->returns ) {
+		type->returns.emplace_back( ret->get_type() );
+	}
+	for ( auto & param : this->type_params ) {
+		type->forall.emplace_back( new TypeInstType( param ) );
+	}
+	for ( auto & assertion : this->assertions ) {
+		type->assertions.emplace_back(
+			new VariableExpr( assertion->location, assertion ) );
+	}
+	this->type = type;
 }
 
Index: src/AST/Decl.hpp
===================================================================
--- src/AST/Decl.hpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/AST/Decl.hpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -9,7 +9,7 @@
 // Author           : Aaron B. Moss
 // Created On       : Thu May 9 10:00:00 2019
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Mar 12 18:25:05 2021
-// Update Count     : 32
+// Last Modified By : Andrew Beach
+// Last Modified On : Thu May  5 12:09:00 2022
+// Update Count     : 33
 //
 
@@ -135,10 +135,20 @@
 	std::vector< ptr<Expr> > withExprs;
 
+	// The difference between the two constructors is in how they handle
+	// assertions. The first constructor uses the assertions from the type
+	// parameters, in the style of the old ast, and puts them on the type.
+	// The second takes an explicite list of assertions and builds a list of
+	// references to them on the type.
+
 	FunctionDecl( const CodeLocation & loc, const std::string & name, std::vector<ptr<TypeDecl>>&& forall,
 		std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
 		CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C,
 		std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);
-	// : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), params(std::move(params)), returns(std::move(returns)),
-	//  stmts( stmts ) {}
+
+	FunctionDecl( const CodeLocation & location, const std::string & name,
+		std::vector<ptr<TypeDecl>>&& forall, std::vector<ptr<DeclWithType>>&& assertions,
+		std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
+		CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C,
+		std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, bool isVarArgs = false);
 
 	const Type * get_type() const override;
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/AST/Expr.hpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -784,5 +784,5 @@
 public:
 	ptr<Expr> expr;
-	ptr<ObjectDecl> object;
+	readonly<ObjectDecl> object;
 	ptr<VariableExpr> var;
 	unsigned long long id;
Index: src/AST/Label.hpp
===================================================================
--- src/AST/Label.hpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/AST/Label.hpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -34,5 +34,5 @@
 	std::vector< ptr<Attribute> > attributes;
 
-	Label( CodeLocation loc, const std::string& name = "",
+	Label( const CodeLocation& loc, const std::string& name = "",
 		std::vector<ptr<Attribute>> && attrs = std::vector<ptr<Attribute>>{} )
 	: location( loc ), name( name ), attributes( attrs ) {}
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/AST/Node.hpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 8 10:27:04 2019
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri Mar 25 10:33:00 2022
-// Update Count     : 7
+// Last Modified On : Mon May  9 10:20:00 2022
+// Update Count     : 8
 //
 
@@ -49,5 +49,9 @@
 
 	bool unique() const { return strong_count == 1; }
-	bool isManaged() const {return strong_count > 0; }
+	bool isManaged() const { return strong_count > 0; }
+	bool isReferenced() const { return weak_count > 0; }
+	bool isStable() const {
+		return (1 == strong_count || (1 < strong_count && 0 == weak_count));
+	}
 
 private:
Index: src/AST/Pass.proto.hpp
===================================================================
--- src/AST/Pass.proto.hpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/AST/Pass.proto.hpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -131,6 +131,6 @@
 	template< typename node_t >
 	struct result1 {
-		bool differs;
-		const node_t * value;
+		bool differs = false;
+		const node_t * value = nullptr;
 
 		template< typename object_t, typename super_t, typename field_t >
@@ -151,5 +151,5 @@
 		};
 
-		bool differs;
+		bool differs = false;
 		container_t< delta > values;
 
@@ -167,5 +167,5 @@
 	template< template<class...> class container_t, typename node_t >
 	struct resultN {
-		bool differs;
+		bool differs = false;
 		container_t<ptr<node_t>> values;
 
Index: src/AST/Stmt.cpp
===================================================================
--- src/AST/Stmt.cpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/AST/Stmt.cpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -9,12 +9,12 @@
 // Author           : Aaron B. Moss
 // Created On       : Wed May  8 13:00:00 2019
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  2 19:01:20 2022
-// Update Count     : 3
+// Last Modified By : Andrew Beach
+// Last Modified On : Tue May  3 15:18:20 2022
+// Update Count     : 4
 //
 
 #include "Stmt.hpp"
 
-
+#include "Copy.hpp"
 #include "DeclReplacer.hpp"
 #include "Type.hpp"
@@ -23,5 +23,17 @@
 
 // --- CompoundStmt
-CompoundStmt::CompoundStmt( const CompoundStmt& other ) : Stmt(other), kids(other.kids) {
+CompoundStmt::CompoundStmt( const CompoundStmt& other ) : Stmt(other), kids() {
+	// Statements can have weak references to them, if that happens inserting
+	// the original node into the new list will put the original node in a
+	// bad state, where it cannot be mutated. To avoid this, just perform an
+	// additional shallow copy on the statement.
+	for ( const Stmt * kid : other.kids ) {
+		if ( kid->isReferenced() ) {
+			kids.emplace_back( ast::shallowCopy( kid ) );
+		} else {
+			kids.emplace_back( kid );
+		}
+	}
+
 	// when cloning a compound statement, we may end up cloning declarations which
 	// are referred to by VariableExprs throughout the block. Cloning a VariableExpr
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/AST/Stmt.hpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -58,5 +58,5 @@
 	// cannot be, they are sub-types of this type, for organization.
 
-    StmtClause( const CodeLocation & loc )
+	StmtClause( const CodeLocation & loc )
 		: ParseNode(loc) {}
 
@@ -396,16 +396,16 @@
 class WaitForClause final : public StmtClause {
   public:
-    ptr<Expr> target_func;
-    std::vector<ptr<Expr>> target_args;
-    ptr<Stmt> stmt;
-    ptr<Expr> cond;
-
-    WaitForClause( const CodeLocation & loc )
+	ptr<Expr> target_func;
+	std::vector<ptr<Expr>> target_args;
+	ptr<Stmt> stmt;
+	ptr<Expr> cond;
+
+	WaitForClause( const CodeLocation & loc )
 		: StmtClause( loc ) {}
 
 	const WaitForClause * accept( Visitor & v ) const override { return v.visit( this ); }
   private:
-    WaitForClause * clone() const override { return new WaitForClause{ *this }; }
-    MUTATE_FRIEND
+	WaitForClause * clone() const override { return new WaitForClause{ *this }; }
+	MUTATE_FRIEND
 };
 
Index: src/AST/Util.cpp
===================================================================
--- src/AST/Util.cpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/AST/Util.cpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -5,11 +5,11 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Util.hpp -- General utilities for working with the AST.
+// Util.cpp -- General utilities for working with the AST.
 //
 // Author           : Andrew Beach
 // Created On       : Wed Jan 19  9:46:00 2022
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri Mar 11 18:07:00 2022
-// Update Count     : 1
+// Last Modified On : Wed May 11 16:16:00 2022
+// Update Count     : 3
 //
 
@@ -46,9 +46,40 @@
 
 /// Check that every note that can has a set CodeLocation.
-struct SetCodeLocationsCore {
-	void previsit( const ParseNode * node ) {
-		assert( node->location.isSet() );
+void isCodeLocationSet( const ParseNode * node ) {
+	assert( node->location.isSet() );
+}
+
+void areLabelLocationsSet( const Stmt * stmt ) {
+	for ( const Label& label : stmt->labels ) {
+		assert( label.location.isSet() );
 	}
-};
+}
+
+/// Make sure the reference counts are in a valid combination.
+void isStable( const Node * node ) {
+	assert( node->isStable() );
+}
+
+/// Check that a FunctionDecl is synchronized with it's FunctionType.
+void functionDeclMatchesType( const FunctionDecl * decl ) {
+	// The type is a cache of sorts, if it is missing that is only a
+	// problem if isTypeFixed is set.
+	if ( decl->isTypeFixed ) {
+		assert( decl->type );
+	} else if ( !decl->type ) {
+		return;
+	}
+
+	const FunctionType * type = decl->type;
+
+	// Check that `type->forall` corresponds with `decl->type_params`.
+	assert( type->forall.size() == decl->type_params.size() );
+	// Check that `type->assertions` corresponds with `decl->assertions`.
+	assert( type->assertions.size() == decl->assertions.size() );
+	// Check that `type->params` corresponds with `decl->params`.
+	assert( type->params.size() == decl->params.size() );
+	// Check that `type->returns` corresponds with `decl->returns`.
+	assert( type->returns.size() == decl->returns.size() );
+}
 
 struct InvariantCore {
@@ -56,13 +87,23 @@
 	// None of the passes should make changes so ordering doesn't matter.
 	NoStrongCyclesCore no_strong_cycles;
-	SetCodeLocationsCore set_code_locations;
 
 	void previsit( const Node * node ) {
 		no_strong_cycles.previsit( node );
+		isStable( node );
 	}
 
 	void previsit( const ParseNode * node ) {
-		no_strong_cycles.previsit( node );
-		set_code_locations.previsit( node );
+		previsit( (const Node *)node );
+		isCodeLocationSet( node );
+	}
+
+	void previsit( const FunctionDecl * node ) {
+		previsit( (const ParseNode *)node );
+		functionDeclMatchesType( node );
+	}
+
+	void previsit( const Stmt * node ) {
+		previsit( (const ParseNode *)node );
+		areLabelLocationsSet( node );
 	}
 
Index: src/Common/CodeLocationTools.cpp
===================================================================
--- src/Common/CodeLocationTools.cpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/Common/CodeLocationTools.cpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -10,6 +10,6 @@
 // Created On       : Fri Dec  4 15:42:00 2020
 // Last Modified By : Andrew Beach
-// Last Modified On : Mon Mar 14 15:14:00 2022
-// Update Count     : 4
+// Last Modified On : Wed May 11 16:16:00 2022
+// Update Count     : 5
 //
 
@@ -24,64 +24,71 @@
 namespace {
 
-// There are a lot of helpers in this file that could be used much more
-// generally if anyone has another use for them.
-
-// Check if a node type has a code location.
-template<typename node_t>
-struct has_code_location : public std::is_base_of<ast::ParseNode, node_t> {};
-
-template<typename node_t, bool has_location>
-struct __GetCL;
-
-template<typename node_t>
-struct __GetCL<node_t, true> {
-	static inline CodeLocation const * get( node_t const * node ) {
-		return &node->location;
-	}
-
-	static inline CodeLocation * get( node_t * node ) {
-		return &node->location;
-	}
-};
-
-template<typename node_t>
-struct __GetCL<node_t, false> {
-	static inline CodeLocation * get( node_t const * ) {
-		return nullptr;
-	}
-};
-
-template<typename node_t>
-CodeLocation const * get_code_location( node_t const * node ) {
-	return __GetCL< node_t, has_code_location< node_t >::value >::get( node );
-}
-
-template<typename node_t>
-CodeLocation * get_code_location( node_t * node ) {
-	return __GetCL< node_t, has_code_location< node_t >::value >::get( node );
-}
-
 // Fill every location with a nearby (parent) location.
 class FillCore : public ast::WithGuards {
 	CodeLocation const * parent;
+
+	template<typename node_t>
+	node_t const * parse_visit( node_t const * node ) {
+		if ( node->location.isUnset() ) {
+			assert( parent );
+			node_t * newNode = ast::mutate( node );
+			newNode->location = *parent;
+			return newNode;
+		}
+		GuardValue( parent ) = &node->location;
+		return node;
+	}
+
+	bool hasUnsetLabels( const ast::Stmt * stmt ) {
+		for ( const ast::Label& label : stmt->labels ) {
+			if ( label.location.isUnset() ) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	template<typename node_t>
+	node_t const * stmt_visit( node_t const * node ) {
+		assert( node->location.isSet() );
+
+		if ( hasUnsetLabels( node ) ) {
+			node_t * newNode = ast::mutate( node );
+			for ( ast::Label& label : newNode->labels ) {
+				if ( label.location.isUnset() ) {
+					label.location = newNode->location;
+				}
+			}
+			return newNode;
+		}
+		return node;
+	}
+
+	template<typename node_t>
+	auto visit( node_t const * node, long ) {
+		return node;
+	}
+
+	template<typename node_t>
+	auto visit( node_t const * node, int ) -> typename
+			std::remove_reference< decltype( node->location, node ) >::type {
+		return parse_visit( node );
+	}
+
+	template<typename node_t>
+	auto visit( node_t const * node, char ) -> typename
+			std::remove_reference< decltype( node->labels, node ) >::type {
+		return stmt_visit( parse_visit( node ) );
+	}
+
 public:
 	FillCore() : parent( nullptr ) {}
+	FillCore( const CodeLocation& location ) : parent( &location ) {
+		assert( location.isSet() );
+	}
 
 	template<typename node_t>
 	node_t const * previsit( node_t const * node ) {
-		GuardValue( parent );
-		CodeLocation const * location = get_code_location( node );
-		if ( location && location->isUnset() ) {
-			assert( parent );
-			node_t * newNode = ast::mutate( node );
-			CodeLocation * newLocation = get_code_location( newNode );
-			assert( newLocation );
-			*newLocation = *parent;
-			parent = newLocation;
-			return newNode;
-		} else if ( location ) {
-			parent = location;
-		}
-		return node;
+		return visit( node, '\0' );
 	}
 };
@@ -233,29 +240,7 @@
 
 	template<typename node_t>
-	void previsit( node_t const * node ) {
-		CodeLocation const * location = get_code_location( node );
-		if ( location && location->isUnset() ) {
+	auto previsit( node_t const * node ) -> decltype( node->location, void() ) {
+		if ( node->location.isUnset() ) {
 			unset.push_back( node );
-		}
-	}
-};
-
-class LocalFillCore : public ast::WithGuards {
-	CodeLocation const * parent;
-public:
-	LocalFillCore( CodeLocation const & location ) : parent( &location ) {
-		assert( location.isSet() );
-	}
-
-	template<typename node_t>
-	auto previsit( node_t const * node )
-			-> typename std::enable_if<has_code_location<node_t>::value, node_t const *>::type {
-		if ( node->location.isSet() ) {
-			GuardValue( parent ) = &node->location;
-			return node;
-		} else {
-			node_t * mut = ast::mutate( node );
-			mut->location = *parent;
-			return mut;
 		}
 	}
@@ -304,5 +289,5 @@
 ast::Node const * localFillCodeLocations(
 		CodeLocation const & location , ast::Node const * node ) {
-	ast::Pass<LocalFillCore> visitor( location );
+	ast::Pass<FillCore> visitor( location );
 	return node->accept( visitor );
 }
Index: src/ControlStruct/LabelGeneratorNew.hpp
===================================================================
--- src/ControlStruct/LabelGeneratorNew.hpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/ControlStruct/LabelGeneratorNew.hpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -18,5 +18,5 @@
 #include <string>										// for string
 
-class CodeLocation;
+struct CodeLocation;
 
 namespace ast {
Index: src/ControlStruct/MultiLevelExit.cpp
===================================================================
--- src/ControlStruct/MultiLevelExit.cpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/ControlStruct/MultiLevelExit.cpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -18,4 +18,5 @@
 #include "AST/Pass.hpp"
 #include "AST/Stmt.hpp"
+#include "Common/CodeLocationTools.hpp"
 #include "LabelGeneratorNew.hpp"
 
@@ -228,77 +229,77 @@
 	// Labels on different stmts require different approaches to access
 	switch ( stmt->kind ) {
-	  case BranchStmt::Goto:
+	case BranchStmt::Goto:
 		return stmt;
-	  case BranchStmt::Continue:
-	  case BranchStmt::Break: {
-		  bool isContinue = stmt->kind == BranchStmt::Continue;
-		  // Handle unlabeled break and continue.
-		  if ( stmt->target.empty() ) {
-			  if ( isContinue ) {
-				  targetEntry = findEnclosingControlStructure( isContinueTarget );
-			  } else {
-				  if ( enclosing_control_structures.empty() ) {
+	case BranchStmt::Continue:
+	case BranchStmt::Break: {
+		bool isContinue = stmt->kind == BranchStmt::Continue;
+		// Handle unlabeled break and continue.
+		if ( stmt->target.empty() ) {
+			if ( isContinue ) {
+				targetEntry = findEnclosingControlStructure( isContinueTarget );
+			} else {
+				if ( enclosing_control_structures.empty() ) {
 					  SemanticError( stmt->location,
 									 "'break' outside a loop, 'switch', or labelled block" );
-				  }
-				  targetEntry = findEnclosingControlStructure( isBreakTarget );
-			  }
-			  // Handle labeled break and continue.
-		  } else {
-			  // Lookup label in table to find attached control structure.
-			  targetEntry = findEnclosingControlStructure(
-				  [ targetStmt = target_table.at(stmt->target) ](auto entry){
+				}
+				targetEntry = findEnclosingControlStructure( isBreakTarget );
+			}
+			// Handle labeled break and continue.
+		} else {
+			// Lookup label in table to find attached control structure.
+			targetEntry = findEnclosingControlStructure(
+				[ targetStmt = target_table.at(stmt->target) ](auto entry){
 					  return entry.stmt == targetStmt;
-				  } );
-		  }
-		  // Ensure that selected target is valid.
-		  if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) {
-			  SemanticError( stmt->location, toString( (isContinue ? "'continue'" : "'break'"),
+				} );
+		}
+		// Ensure that selected target is valid.
+		if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) {
+			SemanticError( stmt->location, toString( (isContinue ? "'continue'" : "'break'"),
 							" target must be an enclosing ", (isContinue ? "loop: " : "control structure: "),
 							stmt->originalTarget ) );
-		  }
-		  break;
-	  }
-	  // handle fallthrough in case/switch stmts
-	  case BranchStmt::FallThrough: {
-		  targetEntry = findEnclosingControlStructure( isFallthroughTarget );
-		  // Check that target is valid.
-		  if ( targetEntry == enclosing_control_structures.rend() ) {
-			  SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
-		  }
-		  if ( ! stmt->target.empty() ) {
-			  // Labelled fallthrough: target must be a valid fallthough label.
-			  if ( ! fallthrough_labels.count( stmt->target ) ) {
-				  SemanticError( stmt->location, toString( "'fallthrough' target must be a later case statement: ",
+		}
+		break;
+	}
+	// handle fallthrough in case/switch stmts
+	case BranchStmt::FallThrough: {
+		targetEntry = findEnclosingControlStructure( isFallthroughTarget );
+		// Check that target is valid.
+		if ( targetEntry == enclosing_control_structures.rend() ) {
+			SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
+		}
+		if ( ! stmt->target.empty() ) {
+			// Labelled fallthrough: target must be a valid fallthough label.
+			if ( ! fallthrough_labels.count( stmt->target ) ) {
+				SemanticError( stmt->location, toString( "'fallthrough' target must be a later case statement: ",
 														   stmt->originalTarget ) );
-			  }
-			  return new BranchStmt( stmt->location, BranchStmt::Goto, stmt->originalTarget );
-		  }
-		  break;
-	  }
-	  case BranchStmt::FallThroughDefault: {
-		  targetEntry = findEnclosingControlStructure( isFallthroughDefaultTarget );
-
-		  // Check if in switch or choose statement.
-		  if ( targetEntry == enclosing_control_structures.rend() ) {
-			  SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
-		  }
-
-		  // Check if switch or choose has default clause.
-		  auto switchStmt = strict_dynamic_cast< const SwitchStmt * >( targetEntry->stmt );
-		  bool foundDefault = false;
-		  for ( auto caseStmt : switchStmt->cases ) {
-			  if ( caseStmt->isDefault() ) {
-				  foundDefault = true;
-				  break;
-			  }
-		  }
-		  if ( ! foundDefault ) {
-			  SemanticError( stmt->location, "'fallthrough default' must be enclosed in a 'switch' or 'choose'"
-							 "control structure with a 'default' clause" );
-		  }
-		  break;
-	  }
-	  default:
+			}
+			return new BranchStmt( stmt->location, BranchStmt::Goto, stmt->originalTarget );
+		}
+		break;
+	}
+	case BranchStmt::FallThroughDefault: {
+		targetEntry = findEnclosingControlStructure( isFallthroughDefaultTarget );
+
+		// Check if in switch or choose statement.
+		if ( targetEntry == enclosing_control_structures.rend() ) {
+			SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
+		}
+
+		// Check if switch or choose has default clause.
+		auto switchStmt = strict_dynamic_cast< const SwitchStmt * >( targetEntry->stmt );
+		bool foundDefault = false;
+		for ( auto caseStmt : switchStmt->cases ) {
+			if ( caseStmt->isDefault() ) {
+				foundDefault = true;
+				break;
+			}
+		}
+		if ( ! foundDefault ) {
+			SemanticError( stmt->location, "'fallthrough default' must be enclosed in a 'switch' or 'choose'"
+						   "control structure with a 'default' clause" );
+		}
+		break;
+	}
+	default:
 		assert( false );
 	}
@@ -307,17 +308,17 @@
 	Label exitLabel( CodeLocation(), "" );
 	switch ( stmt->kind ) {
-	  case BranchStmt::Break:
+	case BranchStmt::Break:
 		assert( ! targetEntry->useBreakExit().empty() );
 		exitLabel = targetEntry->useBreakExit();
 		break;
-	  case BranchStmt::Continue:
+	case BranchStmt::Continue:
 		assert( ! targetEntry->useContExit().empty() );
 		exitLabel = targetEntry->useContExit();
 		break;
-	  case BranchStmt::FallThrough:
+	case BranchStmt::FallThrough:
 		assert( ! targetEntry->useFallExit().empty() );
 		exitLabel = targetEntry->useFallExit();
 		break;
-	  case BranchStmt::FallThroughDefault:
+	case BranchStmt::FallThroughDefault:
 		assert( ! targetEntry->useFallDefaultExit().empty() );
 		exitLabel = targetEntry->useFallDefaultExit();
@@ -327,5 +328,5 @@
 		}
 		break;
-	  default:
+	default:
 		assert(0);
 	}
@@ -633,5 +634,7 @@
 	Pass<MultiLevelExitCore> visitor( labelTable );
 	const CompoundStmt * ret = stmt->accept( visitor );
-	return ret;
+	// There are some unset code locations slipping in, possibly by Labels.
+	const Node * node = localFillCodeLocations( ret->location, ret );
+	return strict_dynamic_cast<const CompoundStmt *>( node );
 }
 } // namespace ControlStruct
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/Parser/parser.yy	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -10,6 +10,6 @@
 // Created On       : Sat Sep  1 20:22:55 2001
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed May  4 14:25:20 2022
-// Update Count     : 5277
+// Last Modified On : Wed May  4 17:22:48 2022
+// Update Count     : 5279
 //
 
@@ -1224,5 +1224,8 @@
 		{ $$ = new StatementNode( build_while( new CondCtl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) ); }
 	| WHILE '(' ')' statement ELSE statement			// CFA
-		{ $$ = new StatementNode( build_while( new CondCtl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) ); SemanticWarning( yylloc, Warning::SuperfluousElse ); }
+		{
+			$$ = new StatementNode( build_while( new CondCtl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) );
+			SemanticWarning( yylloc, Warning::SuperfluousElse );
+		}
 	| WHILE '(' conditional_declaration ')' statement	%prec THEN
 		{ $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); }
@@ -1232,13 +1235,19 @@
 		{ $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) ); }
 	| DO statement WHILE '(' ')' ELSE statement			// CFA
-		{ $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) ); SemanticWarning( yylloc, Warning::SuperfluousElse ); }
-	| DO statement WHILE '(' comma_expression ')' ';'	%prec THEN
+		{
+			$$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) );
+			SemanticWarning( yylloc, Warning::SuperfluousElse );
+		}
+	| DO statement WHILE '(' comma_expression ')' ';'
 		{ $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
 	| DO statement WHILE '(' comma_expression ')' ELSE statement // CFA
 		{ $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); }
-	| FOR '(' ')' statement								// CFA => for ( ;; )
+	| FOR '(' ')' statement								%prec THEN // CFA => for ( ;; )
 		{ $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); }
-	| FOR '(' ')' statement ELSE statement			// CFA
-		{ $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); SemanticWarning( yylloc, Warning::SuperfluousElse ); }
+	| FOR '(' ')' statement ELSE statement				// CFA
+		{
+			$$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) );
+			SemanticWarning( yylloc, Warning::SuperfluousElse );
+		}
 	| FOR '(' for_control_expression_list ')' statement	%prec THEN
 	  	{ $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
Index: src/Validate/Autogen.cpp
===================================================================
--- src/Validate/Autogen.cpp	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ src/Validate/Autogen.cpp	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -350,4 +350,5 @@
 		name,
 		std::move( type_params ),
+		std::move( assertions ),
 		std::move( params ),
 		std::move( returns ),
@@ -360,5 +361,4 @@
 		// Auto-generated routines are inline to avoid conflicts.
 		ast::Function::Specs( ast::Function::Inline ) );
-	decl->assertions = std::move( assertions );
 	decl->fixUniqueId();
 	return decl;
Index: tests/include/.expect/includes.nast.txt
===================================================================
--- tests/include/.expect/includes.nast.txt	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ tests/include/.expect/includes.nast.txt	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -1,1 +1,1 @@
-include/includes.cfa:153:25: warning: Compiled
+include/includes.cfa:169:25: warning: Compiled
Index: tests/include/includes.cfa
===================================================================
--- tests/include/includes.cfa	(revision f75e25bacd14e7d28dac1228e86806938c10a4a1)
+++ tests/include/includes.cfa	(revision e5628dbbd06f42c13a66ca24c78badc52314ffdf)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 27 17:56:53 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Feb  3 22:06:07 2022
-// Update Count     : 774
+// Last Modified On : Tue May 10 16:36:44 2022
+// Update Count     : 776
 //
 
@@ -32,5 +32,7 @@
 #include <crypt.h>
 #include <ctype.h>
-//#include <curses.h>										// may not be installed
+#if __has_include( "curses.h" )
+#include <curses.h>										// may not be installed
+#endif
 #include <dirent.h>
 #include <dlfcn.h>
@@ -41,5 +43,7 @@
 #include <errno.h>
 #include <error.h>
-//#include <eti.h>										// may not be installed, comes with ncurses
+#if __has_include( "eti.h" )
+#include <eti.h>										// may not be installed, comes with ncurses
+#endif
 #include <execinfo.h>
 #include <expat.h>
@@ -50,5 +54,7 @@
 #include <fmtmsg.h>
 #include <fnmatch.h>
-//#include <form.h>										// may not be installed, comes with ncurses
+#if __has_include( "form.h" )
+#include <form.h>										// may not be installed, comes with ncurses
+#endif
 #include <fstab.h>
 #include <fts.h>
@@ -78,14 +84,20 @@
 #include <mcheck.h>
 #include <memory.h>
-//#include <menu.h>										// may not be installed, comes with ncurses
+#if __has_include( "menu.h" )
+#include <menu.h>										// may not be installed, comes with ncurses
+#endif
 #include <mntent.h>
 #include <monetary.h>
 #include <mqueue.h>
-//#include <ncurses_dll.h>								// may not be installed, comes with ncurses
+#if __has_include( "ncurses_dll.h" )
+#include <ncurses_dll.h>								// may not be installed, comes with ncurses
+#endif
 #include <netdb.h>
 #include <nl_types.h>
 #include <nss.h>
 #include <obstack.h>
-//#include <panel.h>										// may not be installed, comes with ncurses
+#if __has_include( "panel.h" )
+#include <panel.h>										// may not be installed, comes with ncurses
+#endif
 #include <paths.h>
 #include <poll.h>
@@ -118,6 +130,8 @@
 #include <syslog.h>
 #include <tar.h>
-//#include <term.h>										// may not be installed, comes with ncurses
-//#include <termcap.h>									// may not be installed, comes with ncurses
+#if __has_include( "term.h" )
+#include <term.h>										// may not be installed, comes with ncurses
+#include <termcap.h>									// may not be installed, comes with ncurses
+#endif
 #include <termio.h>
 #include <termios.h>
@@ -131,5 +145,7 @@
 #include <ucontext.h>
 #include <ulimit.h>
-//#include <unctrl.h>										// may not be installed, comes with ncurses
+#if __has_include( "unctrl.h" )
+#include <unctrl.h>										// may not be installed, comes with ncurses
+#endif
 #include <unistd.h>
 #include <utime.h>
