Index: Jenkins/FullBuild
===================================================================
--- Jenkins/FullBuild	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ Jenkins/FullBuild	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -17,6 +17,6 @@
 
 				parallel (
-					clang_x86: { trigger_build( 'gcc-8',   'x86' ) },
-					gcc_5_x86: { trigger_build( 'gcc-7',   'x86' ) },
+					gcc_8_x86: { trigger_build( 'gcc-8',   'x86' ) },
+					gcc_7_x86: { trigger_build( 'gcc-7',   'x86' ) },
 					gcc_6_x86: { trigger_build( 'gcc-6',   'x86' ) },
 					gcc_9_x64: { trigger_build( 'gcc-9',   'x64' ) },
Index: Jenkinsfile
===================================================================
--- Jenkinsfile	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ Jenkinsfile	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -127,5 +127,7 @@
 			}
 
-			sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} AR=gcc-ar RANLIB=gcc-ranlib ${targets} --quiet --prefix=${BuildDir}"
+			ast = Settings.NewAST ? "--enable-new-ast" : "--disable-new-ast"
+
+			sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} AR=gcc-ar RANLIB=gcc-ranlib ${targets} ${ast} --quiet --prefix=${BuildDir}"
 
 			// Configure libcfa
@@ -359,4 +361,5 @@
 	public final CC_Desc Compiler
 	public final Arch_Desc Architecture
+	public final Boolean NewAST
 	public final Boolean RunAllTests
 	public final Boolean RunBenchmark
@@ -392,5 +395,5 @@
 			break
 			case 'clang':
-				this.Compiler = new CC_Desc('clang', 'clang++-6.0', 'gcc-6', '-flto=thin -flto-jobs=0')
+				this.Compiler = new CC_Desc('clang', 'clang++-10', 'gcc-9', '-flto=thin -flto-jobs=0')
 			break
 			default :
@@ -410,4 +413,5 @@
 
 		this.IsSandbox          = (branch == "jenkins-sandbox")
+		this.NewAST             = param.NewAST
 		this.RunAllTests        = param.RunAllTests
 		this.RunBenchmark       = param.RunBenchmark
@@ -470,8 +474,13 @@
 				],												\
 				[$class: 'BooleanParameterDefinition',  						\
+					description: 'If true, build compiler using new AST', 		\
+					name: 'NewAST', 									\
+					defaultValue: false,  								\
+				], 												\
+				[$class: 'BooleanParameterDefinition',  						\
 					description: 'If false, only the quick test suite is ran', 		\
 					name: 'RunAllTests', 								\
 					defaultValue: false,  								\
-				], 												\
+				],
 				[$class: 'BooleanParameterDefinition',  						\
 					description: 'If true, jenkins also runs benchmarks', 		\
Index: c/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/cforall.cpp
===================================================================
--- doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/cforall.cpp	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ 	(revision )
@@ -1,43 +1,0 @@
-#include <cassert>
-#include <clib/cfathread.h>
-
-typedef cfathread_t thread_t;
-static_assert(sizeof(thread_t) == sizeof(void*), "thread_t musst be of same size as void*");
-
-#if !defined(__cplusplus)
-#error no __cplusplus define!
-#endif
-
-extern "C" {
-	//--------------------
-	// Basic thread support
-	thread_t thrdlib_create( void (*the_main)( thread_t ) ) {
-		return cfathread_create( the_main );
-	}
-
-	void thrdlib_join( thread_t handle ) {
-		cfathread_join( handle );
-	}
-
-	void thrdlib_park( thread_t ) {
-		cfathread_park();
-	}
-
-	void thrdlib_unpark( thread_t handle ) {
-		cfathread_unpark( handle );
-	}
-
-	void thrdlib_yield( void ) {
-		cfathread_yield();
-	}
-
-	//--------------------
-	// Basic kernel features
-	void thrdlib_init( int procs ) {
-		cfathread_setproccnt(procs);
-	}
-
-	void thrdlib_clean( void ) {
-		cfathread_setproccnt(1);
-	}
-}
Index: doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/cforall.hpp
===================================================================
--- doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/cforall.hpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
+++ doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/cforall.hpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -0,0 +1,43 @@
+#include <cassert>
+#include <clib/cfathread.h>
+
+typedef cfathread_t thread_t;
+static_assert(sizeof(thread_t) == sizeof(void*), "thread_t musst be of same size as void*");
+
+#if !defined(__cplusplus)
+#error no __cplusplus define!
+#endif
+
+extern "C" {
+	//--------------------
+	// Basic thread support
+	thread_t thrdlib_create( void (*the_main)( thread_t ) ) {
+		return cfathread_create( the_main );
+	}
+
+	void thrdlib_join( thread_t handle ) {
+		cfathread_join( handle );
+	}
+
+	void thrdlib_park( thread_t ) {
+		cfathread_park();
+	}
+
+	void thrdlib_unpark( thread_t handle ) {
+		cfathread_unpark( handle );
+	}
+
+	void thrdlib_yield( void ) {
+		cfathread_yield();
+	}
+
+	//--------------------
+	// Basic kernel features
+	void thrdlib_init( int procs ) {
+		cfathread_setproccnt(procs);
+	}
+
+	void thrdlib_clean( void ) {
+		cfathread_setproccnt(1);
+	}
+}
Index: c/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/fibre.cpp
===================================================================
--- doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/fibre.cpp	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ 	(revision )
@@ -1,48 +1,0 @@
-#include <cassert>
-#include <libfibre/cfibre.h>
-
-typedef cfibre_t thread_t;
-static_assert(sizeof(thread_t) == sizeof(void*), "thread_t musst be of same size as void*");
-
-void * fibre_runner(void * arg) {
-	auto the_main = (void (*)( thread_t ))arg;
-	the_main( cfibre_self() );
-	return nullptr;
-}
-
-extern "C" {
-	//--------------------
-	// Basic thread support
-	thread_t thrdlib_create( void (*the_main)( thread_t ) ) {
-		thread_t fibre;
-		cfibre_create( &fibre, nullptr, fibre_runner, (void*)the_main );
-		return fibre;
-	}
-
-	void thrdlib_join( thread_t handle ) {
-		cfibre_join( handle, nullptr );
-	}
-
-	void thrdlib_park( thread_t handle ) {
-		assert( handle == cfibre_self() );
-		cfibre_park();
-	}
-
-	void thrdlib_unpark( thread_t handle ) {
-		cfibre_unpark( handle );
-	}
-
-	void thrdlib_yield( void ) {
-		cfibre_yield();
-	}
-
-	//--------------------
-	// Basic kernel features
-	void thrdlib_init( int procs ) {
-		cfibre_init_n(1, procs );
-	}
-
-	void thrdlib_clean( void ) {
-
-	}
-}
Index: doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/fibre.hpp
===================================================================
--- doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/fibre.hpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
+++ doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/fibre.hpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -0,0 +1,48 @@
+#include <cassert>
+#include <libfibre/cfibre.h>
+
+typedef cfibre_t thread_t;
+static_assert(sizeof(thread_t) == sizeof(void*), "thread_t musst be of same size as void*");
+
+void * fibre_runner(void * arg) {
+	auto the_main = (void (*)( thread_t ))arg;
+	the_main( cfibre_self() );
+	return nullptr;
+}
+
+extern "C" {
+	//--------------------
+	// Basic thread support
+	thread_t thrdlib_create( void (*the_main)( thread_t ) ) {
+		thread_t fibre;
+		cfibre_create( &fibre, nullptr, fibre_runner, (void*)the_main );
+		return fibre;
+	}
+
+	void thrdlib_join( thread_t handle ) {
+		cfibre_join( handle, nullptr );
+	}
+
+	void thrdlib_park( thread_t handle ) {
+		assert( handle == cfibre_self() );
+		cfibre_park();
+	}
+
+	void thrdlib_unpark( thread_t handle ) {
+		cfibre_unpark( handle );
+	}
+
+	void thrdlib_yield( void ) {
+		cfibre_yield();
+	}
+
+	//--------------------
+	// Basic kernel features
+	void thrdlib_init( int procs ) {
+		cfibre_init_n(1, procs );
+	}
+
+	void thrdlib_clean( void ) {
+
+	}
+}
Index: c/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/pthread.cpp
===================================================================
--- doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/pthread.cpp	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ 	(revision )
@@ -1,99 +1,0 @@
-#include <pthread.h>
-#include <errno.h>
-#include <cstring>
-#include <cstdio>
-#include <iostream>
-
-#define CHECKED(x) { int err = x; if( err != 0 ) { std::cerr << "KERNEL ERROR: Operation \"" #x "\" return error " << err << " - " << strerror(err) << std::endl; std::abort(); } }
-
-struct __bin_sem_t {
-	pthread_mutex_t 	lock;
-	pthread_cond_t  	cond;
-	int     		val;
-
-	__bin_sem_t() {
-		// Create the mutex with error checking
-		pthread_mutexattr_t mattr;
-		pthread_mutexattr_init( &mattr );
-		pthread_mutexattr_settype( &mattr, PTHREAD_MUTEX_ERRORCHECK_NP);
-		pthread_mutex_init(&lock, &mattr);
-
-		pthread_cond_init (&cond, nullptr);
-		val = 0;
-	}
-
-	~__bin_sem_t() {
-		CHECKED( pthread_mutex_destroy(&lock) );
-		CHECKED( pthread_cond_destroy (&cond) );
-	}
-
-	void wait() {
-		CHECKED( pthread_mutex_lock(&lock) );
-			while(val < 1) {
-				pthread_cond_wait(&cond, &lock);
-			}
-			val -= 1;
-		CHECKED( pthread_mutex_unlock(&lock) );
-	}
-
-	bool post() {
-		bool needs_signal = false;
-
-		CHECKED( pthread_mutex_lock(&lock) );
-			if(val < 1) {
-				val += 1;
-				pthread_cond_signal(&cond);
-				needs_signal = true;
-			}
-		CHECKED( pthread_mutex_unlock(&lock) );
-
-		return needs_signal;
-	}
-};
-
-#undef CHECKED
-
-//--------------------
-// Basic types
-struct pthread_runner_t {
-	pthread_t handle;
-	__bin_sem_t sem;
-};
-typedef pthread_runner_t * thread_t;
-
-static_assert(sizeof(thread_t) == sizeof(void*), "thread_t musst be of same size as void*");
-
-extern "C" {
-	//--------------------
-	// Basic thread support
-	thread_t thrdlib_create( void (*main)( thread_t ) ) {
-		thread_t thrd = new pthread_runner_t();
-		int r = pthread_create( &thrd->handle, nullptr, (void *(*)(void *))main, thrd );
-		if( r != 0 ) std::abort();
-		return thrd;
-	}
-
-	void thrdlib_join( thread_t handle ) {
-		void * ret;
-		int r = pthread_join( handle->handle, &ret );
-		if( r != 0 ) std::abort();
-		delete handle;
-	}
-
-	void thrdlib_park( thread_t handle ) {
-		handle->sem.wait();
-	}
-
-	void thrdlib_unpark( thread_t handle ) {
-		handle->sem.post();
-	}
-
-	void thrdlib_yield( void ) {
-		int r = pthread_yield();
-		if( r != 0 ) std::abort();
-	}
-
-	//--------------------
-	// Basic kernel features
-	void thrdlib_init( int ) {}
-}
Index: doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/pthread.hpp
===================================================================
--- doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/pthread.hpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
+++ doc/theses/thierry_delisle_PhD/code/readQ_example/thrdlib/pthread.hpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -0,0 +1,99 @@
+#include <pthread.h>
+#include <errno.h>
+#include <cstring>
+#include <cstdio>
+#include <iostream>
+
+#define CHECKED(x) { int err = x; if( err != 0 ) { std::cerr << "KERNEL ERROR: Operation \"" #x "\" return error " << err << " - " << strerror(err) << std::endl; std::abort(); } }
+
+struct __bin_sem_t {
+	pthread_mutex_t 	lock;
+	pthread_cond_t  	cond;
+	int     		val;
+
+	__bin_sem_t() {
+		// Create the mutex with error checking
+		pthread_mutexattr_t mattr;
+		pthread_mutexattr_init( &mattr );
+		pthread_mutexattr_settype( &mattr, PTHREAD_MUTEX_ERRORCHECK_NP);
+		pthread_mutex_init(&lock, &mattr);
+
+		pthread_cond_init (&cond, nullptr);
+		val = 0;
+	}
+
+	~__bin_sem_t() {
+		CHECKED( pthread_mutex_destroy(&lock) );
+		CHECKED( pthread_cond_destroy (&cond) );
+	}
+
+	void wait() {
+		CHECKED( pthread_mutex_lock(&lock) );
+			while(val < 1) {
+				pthread_cond_wait(&cond, &lock);
+			}
+			val -= 1;
+		CHECKED( pthread_mutex_unlock(&lock) );
+	}
+
+	bool post() {
+		bool needs_signal = false;
+
+		CHECKED( pthread_mutex_lock(&lock) );
+			if(val < 1) {
+				val += 1;
+				pthread_cond_signal(&cond);
+				needs_signal = true;
+			}
+		CHECKED( pthread_mutex_unlock(&lock) );
+
+		return needs_signal;
+	}
+};
+
+#undef CHECKED
+
+//--------------------
+// Basic types
+struct pthread_runner_t {
+	pthread_t handle;
+	__bin_sem_t sem;
+};
+typedef pthread_runner_t * thread_t;
+
+static_assert(sizeof(thread_t) == sizeof(void*), "thread_t musst be of same size as void*");
+
+extern "C" {
+	//--------------------
+	// Basic thread support
+	thread_t thrdlib_create( void (*main)( thread_t ) ) {
+		thread_t thrd = new pthread_runner_t();
+		int r = pthread_create( &thrd->handle, nullptr, (void *(*)(void *))main, thrd );
+		if( r != 0 ) std::abort();
+		return thrd;
+	}
+
+	void thrdlib_join( thread_t handle ) {
+		void * ret;
+		int r = pthread_join( handle->handle, &ret );
+		if( r != 0 ) std::abort();
+		delete handle;
+	}
+
+	void thrdlib_park( thread_t handle ) {
+		handle->sem.wait();
+	}
+
+	void thrdlib_unpark( thread_t handle ) {
+		handle->sem.post();
+	}
+
+	void thrdlib_yield( void ) {
+		int r = pthread_yield();
+		if( r != 0 ) std::abort();
+	}
+
+	//--------------------
+	// Basic kernel features
+	void thrdlib_init( int ) {}
+}
Index: libcfa/prelude/builtins.c
===================================================================
--- libcfa/prelude/builtins.c	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/prelude/builtins.c	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -10,6 +10,6 @@
 // Created On       : Fri Jul 21 16:21:03 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Jul 13 21:10:02 2020
-// Update Count     : 109
+// Last Modified On : Fri Oct  9 18:26:19 2020
+// Update Count     : 110
 //
 
@@ -94,4 +94,5 @@
 // universal typed pointer constant
 static inline forall( dtype DT ) DT * intptr( uintptr_t addr ) { return (DT *)addr; }
+static inline forall( ftype FT ) FT * intptr( uintptr_t addr ) { return (FT *)addr; }
 
 #if defined(__SIZEOF_INT128__)
Index: libcfa/src/concurrency/coroutine.cfa
===================================================================
--- libcfa/src/concurrency/coroutine.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/src/concurrency/coroutine.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -47,6 +47,5 @@
 
 //-----------------------------------------------------------------------------
-FORALL_DATA_INSTANCE(CoroutineCancelled,
-		(dtype coroutine_t | sized(coroutine_t)), (coroutine_t))
+FORALL_DATA_INSTANCE(CoroutineCancelled, (dtype coroutine_t), (coroutine_t))
 
 struct __cfaehm_node {
@@ -59,5 +58,5 @@
 void mark_exception(CoroutineCancelled(T) *) {}
 
-forall(dtype T | sized(T))
+forall(dtype T)
 void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src) {
 	dst->the_coroutine = src->the_coroutine;
@@ -77,5 +76,7 @@
 	exception_t * except = (exception_t *)(1 + (__cfaehm_node *)desc->cancellation);
 
+	// TODO: Remove explitate vtable set once trac#186 is fixed.
 	CoroutineCancelled(T) except;
+	except.virtual_table = &get_exception_vtable(&except);
 	except.the_coroutine = &cor;
 	except.the_exception = except;
@@ -91,5 +92,5 @@
 
 // minimum feasible stack size in bytes
-#define MinStackSize 1000
+static const size_t MinStackSize = 1000;
 extern size_t __page_size;				// architecture pagesize HACK, should go in proper runtime singleton
 
Index: libcfa/src/concurrency/coroutine.hfa
===================================================================
--- libcfa/src/concurrency/coroutine.hfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/src/concurrency/coroutine.hfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -22,7 +22,5 @@
 //-----------------------------------------------------------------------------
 // Exception thrown from resume when a coroutine stack is cancelled.
-// Should not have to be be sized (see trac #196).
-FORALL_DATA_EXCEPTION(CoroutineCancelled,
-		(dtype coroutine_t | sized(coroutine_t)), (coroutine_t)) (
+FORALL_DATA_EXCEPTION(CoroutineCancelled, (dtype coroutine_t), (coroutine_t)) (
 	coroutine_t * the_coroutine;
 	exception_t * the_exception;
@@ -30,7 +28,4 @@
 
 forall(dtype T)
-void mark_exception(CoroutineCancelled(T) *);
-
-forall(dtype T | sized(T))
 void copy(CoroutineCancelled(T) * dst, CoroutineCancelled(T) * src);
 
@@ -42,7 +37,5 @@
 // Anything that implements this trait can be resumed.
 // Anything that is resumed is a coroutine.
-trait is_coroutine(dtype T | sized(T)
-		| is_resumption_exception(CoroutineCancelled(T))
-		| VTABLE_ASSERTION(CoroutineCancelled, (T))) {
+trait is_coroutine(dtype T | IS_RESUMPTION_EXCEPTION(CoroutineCancelled, (T))) {
 	void main(T & this);
 	$coroutine * get_coroutine(T & this);
Index: libcfa/src/concurrency/io.cfa
===================================================================
--- libcfa/src/concurrency/io.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/src/concurrency/io.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -134,5 +134,5 @@
 		int ret = 0;
 		if( need_sys_to_submit || need_sys_to_complete ) {
-			ret = syscall( __NR_io_uring_enter, ring.fd, to_submit, 0, flags, 0p, _NSIG / 8);
+			ret = syscall( __NR_io_uring_enter, ring.fd, to_submit, 0, flags, (sigset_t *)0p, _NSIG / 8);
 			if( ret < 0 ) {
 				switch((int)errno) {
Index: libcfa/src/concurrency/io/call.cfa.in
===================================================================
--- libcfa/src/concurrency/io/call.cfa.in	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/src/concurrency/io/call.cfa.in	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -47,37 +47,30 @@
 	#include "kernel/fwd.hfa"
 
-	#if defined(CFA_HAVE_IOSQE_FIXED_FILE) && defined(CFA_HAVE_IOSQE_IO_DRAIN) && defined(CFA_HAVE_IOSQE_ASYNC)
-		#define REGULAR_FLAGS (IOSQE_FIXED_FILE | IOSQE_IO_DRAIN | IOSQE_ASYNC)
-	#elif defined(CFA_HAVE_IOSQE_FIXED_FILE) && defined(CFA_HAVE_IOSQE_ASYNC)
-		#define REGULAR_FLAGS (IOSQE_FIXED_FILE | IOSQE_ASYNC)
-	#elif defined(CFA_HAVE_IOSQE_FIXED_FILE) && defined(CFA_HAVE_IOSQE_IO_DRAIN)
-		#define REGULAR_FLAGS (IOSQE_FIXED_FILE | IOSQE_IO_DRAIN)
-	#elif defined(CFA_HAVE_IOSQE_IO_DRAIN) && defined(CFA_HAVE_IOSQE_ASYNC)
-		#define REGULAR_FLAGS (IOSQE_IO_DRAIN | IOSQE_ASYNC)
-	#elif defined(CFA_HAVE_IOSQE_FIXED_FILE)
-		#define REGULAR_FLAGS (IOSQE_FIXED_FILE)
-	#elif defined(CFA_HAVE_IOSQE_IO_DRAIN)
-		#define REGULAR_FLAGS (IOSQE_IO_DRAIN)
-	#elif defined(CFA_HAVE_IOSQE_ASYNC)
-		#define REGULAR_FLAGS (IOSQE_ASYNC)
-	#else
-		#define REGULAR_FLAGS (0)
-	#endif
-
-	#if defined(CFA_HAVE_IOSQE_IO_LINK) && defined(CFA_HAVE_IOSQE_IO_HARDLINK)
-		#define LINK_FLAGS (IOSQE_IO_LINK | IOSQE_IO_HARDLINK)
-	#elif defined(CFA_HAVE_IOSQE_IO_LINK)
-		#define LINK_FLAGS (IOSQE_IO_LINK)
-	#elif defined(CFA_HAVE_IOSQE_IO_HARDLINK)
-		#define LINK_FLAGS (IOSQE_IO_HARDLINK)
-	#else
-		#define LINK_FLAGS (0)
-	#endif
-
-	#if defined(CFA_HAVE_SPLICE_F_FD_IN_FIXED)
-		#define SPLICE_FLAGS (SPLICE_F_FD_IN_FIXED)
-	#else
-		#define SPLICE_FLAGS (0)
-	#endif
+	static const __u8 REGULAR_FLAGS = 0
+		#if defined(CFA_HAVE_IOSQE_FIXED_FILE)
+			| IOSQE_FIXED_FILE
+		#endif
+		#if defined(CFA_HAVE_IOSQE_IO_DRAIN)
+			| IOSQE_IO_DRAIN
+		#endif
+		#if defined(CFA_HAVE_IOSQE_ASYNC)
+			| IOSQE_ASYNC
+		#endif
+	;
+
+	static const __u32 LINK_FLAGS = 0
+		#if defined(CFA_HAVE_IOSQE_IO_LINK)
+			| IOSQE_IO_LINK
+		#endif
+		#if defined(CFA_HAVE_IOSQE_IO_HARDLINK)
+			| IOSQE_IO_HARDLINK
+		#endif
+	;
+
+	static const __u32 SPLICE_FLAGS = 0
+		#if defined(CFA_HAVE_SPLICE_F_FD_IN_FIXED)
+			| SPLICE_F_FD_IN_FIXED
+		#endif
+	;
 
 	extern [* struct io_uring_sqe, __u32] __submit_alloc( struct __io_data & ring, __u64 data );
Index: libcfa/src/concurrency/kernel.cfa
===================================================================
--- libcfa/src/concurrency/kernel.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/src/concurrency/kernel.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -252,4 +252,5 @@
 		/* paranoid */ verify( kernelTLS.this_thread == thrd_dst );
 		/* paranoid */ verify( thrd_dst->context.SP );
+		/* paranoid */ verify( thrd_dst->state != Halted );
 		/* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) < ((uintptr_t)__get_stack(thrd_dst->curr_cor)->base ) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too small.\n", thrd_dst ); // add escape condition if we are setting up the processor
 		/* paranoid */ verifyf( ((uintptr_t)thrd_dst->context.SP) > ((uintptr_t)__get_stack(thrd_dst->curr_cor)->limit) || thrd_dst->curr_cor == proc_cor, "ERROR : Destination $thread %p has been corrupted.\n StackPointer too large.\n", thrd_dst ); // add escape condition if we are setting up the processor
@@ -287,7 +288,6 @@
 		if(unlikely(thrd_dst->state == Halted)) {
 			// The thread has halted, it should never be scheduled/run again
-			// We may need to wake someone up here since
-			unpark( this->destroyer );
-			this->destroyer = 0p;
+			// finish the thread
+			__thread_finish( thrd_dst );
 			break RUNNING;
 		}
@@ -448,9 +448,28 @@
 }
 
-// KERNEL ONLY
-void __leave_thread() {
-	/* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
-	returnToKernel();
-	abort();
+extern "C" {
+	// Leave the thread monitor
+	// last routine called by a thread.
+	// Should never return
+	void __cfactx_thrd_leave() {
+		$thread * thrd = TL_GET( this_thread );
+		$monitor * this = &thrd->self_mon;
+
+		// Lock the monitor now
+		lock( this->lock __cfaabi_dbg_ctx2 );
+
+		disable_interrupts();
+
+		thrd->state = Halted;
+
+		if( thrd != this->owner || this->recursion != 1) { abort( "Thread internal monitor has unbalanced recursion" ); }
+
+		// Leave the thread
+		/* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
+		returnToKernel();
+		abort();
+
+		// Control flow should never reach here!
+	}
 }
 
Index: libcfa/src/concurrency/kernel.hfa
===================================================================
--- libcfa/src/concurrency/kernel.hfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/src/concurrency/kernel.hfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -79,8 +79,4 @@
 	// Handle to pthreads
 	pthread_t kernel_thread;
-
-	// RunThread data
-	// Action to do after a thread is ran
-	$thread * destroyer;
 
 	// Preemption data
Index: libcfa/src/concurrency/kernel/startup.cfa
===================================================================
--- libcfa/src/concurrency/kernel/startup.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/src/concurrency/kernel/startup.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -474,5 +474,4 @@
 	this.cltr = &_cltr;
 	full_proc = true;
-	destroyer = 0p;
 	do_terminate = false;
 	preemption_alarm = 0p;
Index: libcfa/src/concurrency/kernel_private.hfa
===================================================================
--- libcfa/src/concurrency/kernel_private.hfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/src/concurrency/kernel_private.hfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -39,6 +39,6 @@
 ;
 
-//Block current thread and release/wake-up the following resources
-void __leave_thread() __attribute__((noreturn));
+//release/wake-up the following resources
+void __thread_finish( $thread * thrd );
 
 //-----------------------------------------------------------------------------
Index: libcfa/src/concurrency/monitor.cfa
===================================================================
--- libcfa/src/concurrency/monitor.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/src/concurrency/monitor.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -281,47 +281,29 @@
 }
 
-extern "C" {
-	// Leave the thread monitor
-	// last routine called by a thread.
-	// Should never return
-	void __cfactx_thrd_leave() {
-		$thread * thrd = TL_GET( this_thread );
-		$monitor * this = &thrd->self_mon;
-
-		// Lock the monitor now
-		lock( this->lock __cfaabi_dbg_ctx2 );
-
-		disable_interrupts();
-
-		thrd->state = Halted;
-
-		/* paranoid */ verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
-
-		// Leaving a recursion level, decrement the counter
-		this->recursion -= 1;
-
-		// If we haven't left the last level of recursion
-		// it must mean there is an error
-		if( this->recursion != 0) { abort( "Thread internal monitor has unbalanced recursion" ); }
-
-		// Fetch the next thread, can be null
-		$thread * new_owner = next_thread( this );
-
-		// Release the monitor lock
-		unlock( this->lock );
-
-		// Unpark the next owner if needed
-		/* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
-		/* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
-		/* paranoid */ verify( ! kernelTLS.this_processor->destroyer );
-		/* paranoid */ verify( thrd->state == Halted );
-
-		kernelTLS.this_processor->destroyer = new_owner;
-
-		// Leave the thread
-		__leave_thread();
-
-		// Control flow should never reach here!
-	}
+void __thread_finish( $thread * thrd ) {
+	$monitor * this = &thrd->self_mon;
+
+	// Lock the monitor now
+	/* paranoid */ verify( this->lock.lock );
+	/* paranoid */ verifyf( thrd == this->owner, "Expected owner to be %p, got %p (r: %i, m: %p)", thrd, this->owner, this->recursion, this );
+	/* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
+	/* paranoid */ verify( thrd->state == Halted );
+	/* paranoid */ verify( this->recursion == 1 );
+
+	// Leaving a recursion level, decrement the counter
+	this->recursion -= 1;
+	this->owner = 0p;
+
+	// Fetch the next thread, can be null
+	$thread * new_owner = next_thread( this );
+
+	// Release the monitor lock
+	unlock( this->lock );
+
+	// Unpark the next owner if needed
+	/* paranoid */ verifyf( !new_owner || new_owner == this->owner, "Expected owner to be %p, got %p (m: %p)", new_owner, this->owner, this );
+	/* paranoid */ verify( ! kernelTLS.preemption_state.enabled );
+	/* paranoid */ verify( thrd->state == Halted );
+	unpark( new_owner );
 }
 
Index: libcfa/src/concurrency/snzi.hfa
===================================================================
--- libcfa/src/concurrency/snzi.hfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/src/concurrency/snzi.hfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -36,5 +36,5 @@
 static inline void depart( __snzi_node_t & );
 
-#define __snzi_half -1
+static const int __snzi_half = -1;
 
 //--------------------------------------------------
Index: libcfa/src/exception.h
===================================================================
--- libcfa/src/exception.h	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/src/exception.h	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -76,21 +76,21 @@
 // implemented in the .c file either so they all have to be inline.
 
-trait is_exception(dtype exceptT) {
+trait is_exception(dtype exceptT, dtype virtualT) {
 	/* The first field must be a pointer to a virtual table.
-	 * That virtual table must be a decendent of the base exception virtual tab$
+	 * That virtual table must be a decendent of the base exception virtual table.
 	 */
-	void mark_exception(exceptT *);
-	// This is never used and should be a no-op.
+	virtualT const & get_exception_vtable(exceptT *);
+	// Always returns the virtual table for this type (associated types hack).
 };
 
-trait is_termination_exception(dtype exceptT | is_exception(exceptT)) {
+trait is_termination_exception(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT)) {
 	void defaultTerminationHandler(exceptT &);
 };
 
-trait is_resumption_exception(dtype exceptT | is_exception(exceptT)) {
+trait is_resumption_exception(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT)) {
 	void defaultResumptionHandler(exceptT &);
 };
 
-forall(dtype exceptT | is_termination_exception(exceptT))
+forall(dtype exceptT, dtype virtualT | is_termination_exception(exceptT, virtualT))
 static inline void $throw(exceptT & except) {
 	__cfaehm_throw_terminate(
@@ -100,5 +100,5 @@
 }
 
-forall(dtype exceptT | is_resumption_exception(exceptT))
+forall(dtype exceptT, dtype virtualT | is_resumption_exception(exceptT, virtualT))
 static inline void $throwResume(exceptT & except) {
 	__cfaehm_throw_resume(
@@ -108,15 +108,15 @@
 }
 
-forall(dtype exceptT | is_exception(exceptT))
+forall(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT))
 static inline void cancel_stack(exceptT & except) __attribute__((noreturn)) {
 	__cfaehm_cancel_stack( (exception_t *)&except );
 }
 
-forall(dtype exceptT | is_exception(exceptT))
+forall(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT))
 static inline void defaultTerminationHandler(exceptT & except) {
 	return cancel_stack( except );
 }
 
-forall(dtype exceptT | is_exception(exceptT))
+forall(dtype exceptT, dtype virtualT | is_exception(exceptT, virtualT))
 static inline void defaultResumptionHandler(exceptT & except) {
 	throw except;
Index: libcfa/src/exception.hfa
===================================================================
--- libcfa/src/exception.hfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/src/exception.hfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -95,5 +95,5 @@
 // visible anywhere you use the instantiation of the exception is used.
 #define POLY_VTABLE_DECLARATION(exception_name, ...) \
-	void mark_exception(exception_name(__VA_ARGS__) *); \
+	VTABLE_TYPE(exception_name)(__VA_ARGS__) const & get_exception_vtable(exception_name(__VA_ARGS__) *); \
 	extern VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name)
 
@@ -125,4 +125,13 @@
 #define VTABLE_ASSERTION(exception_name, parameters) \
 	{ VTABLE_TYPE(exception_name) parameters VTABLE_NAME(exception_name); }
+
+// IS_EXCEPTION(exception_name [, (...parameters)])
+// IS_RESUMPTION_EXCEPTION(exception_name [, (parameters...)])
+// IS_TERMINATION_EXCEPTION(exception_name [, (parameters...)])
+// Create an assertion that exception_name, possibly with the qualifing parameters, is the given
+// kind of exception with the standard vtable with the same parameters if applicable.
+#define IS_EXCEPTION(...) _IS_EXCEPTION(is_exception, __VA_ARGS__, , ~)
+#define IS_RESUMPTION_EXCEPTION(...) _IS_EXCEPTION(is_resumption_exception, __VA_ARGS__, , ~)
+#define IS_TERMINATION_EXCEPTION(...) _IS_EXCEPTION(is_termination_exception, __VA_ARGS__, , ~)
 
 // All internal helper macros begin with an underscore.
@@ -160,10 +169,11 @@
 
 #define _FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) \
-	forall(_UNPACK assertions | VTABLE_ASSERTION(exception_name, parameters) ) \
+	forall(_UNPACK assertions | \
+		is_exception(exception_name parameters, VTABLE_TYPE(exception_name) parameters)) \
 	void ?{}(exception_name parameters & this)
 
 #define _FORALL_CTOR0_INSTANCE(exception_name, assertions, parameters) \
 	_FORALL_CTOR0_DECLARATION(exception_name, assertions, parameters) { \
-		VTABLE_INIT(this, exception_name); \
+		(this).virtual_table = &get_exception_vtable(&this); \
 	}
 
@@ -185,6 +195,6 @@
 #define _VTABLE_DECLARATION(exception_name, parent_name, ...) \
 	struct exception_name; \
-	void mark_exception(exception_name *); \
 	VTABLE_TYPE(exception_name); \
+	VTABLE_TYPE(exception_name) const & get_exception_vtable(exception_name *); \
 	extern VTABLE_TYPE(exception_name) VTABLE_NAME(exception_name); \
 	VTABLE_TYPE(exception_name) { \
@@ -197,5 +207,7 @@
 
 #define _VTABLE_INSTANCE(exception_name, parent_name, ...) \
-	void mark_exception(exception_name *) {} \
+	VTABLE_TYPE(exception_name) const & get_exception_vtable(exception_name *) { \
+		return VTABLE_NAME(exception_name); \
+	} \
 	void _GLUE2(exception_name,_copy)(exception_name * this, exception_name * other) { \
 		*this = *other; \
@@ -218,5 +230,9 @@
 
 #define _POLY_VTABLE_INSTANCE(exception_name, parent_name, ...) \
-	void mark_exception(exception_name(__VA_ARGS__) *) {} \
+	extern VTABLE_TYPE(exception_name)(__VA_ARGS__) VTABLE_NAME(exception_name); \
+	VTABLE_TYPE(exception_name)(__VA_ARGS__) const & get_exception_vtable( \
+			exception_name(__VA_ARGS__) *) { \
+		return VTABLE_NAME(exception_name); \
+	} \
 	void _GLUE2(exception_name,_copy)( \
 			exception_name(__VA_ARGS__) * this, exception_name(__VA_ARGS__) * other) { \
@@ -227,2 +243,5 @@
 		_GLUE2(exception_name,_copy), ^?{}, \
 		_CLOSE
+
+#define _IS_EXCEPTION(kind, exception_name, parameters, ...) \
+	kind(exception_name parameters, VTABLE_TYPE(exception_name) parameters)
Index: libcfa/src/limits.cfa
===================================================================
--- libcfa/src/limits.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/src/limits.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -10,6 +10,6 @@
 // Created On       : Wed Apr  6 18:06:52 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Sep 30 22:56:32 2020
-// Update Count     : 76
+// Last Modified On : Thu Mar  1 16:22:51 2018
+// Update Count     : 74
 //
 
@@ -23,131 +23,131 @@
 // Integral Constants
 
-signed char MIN = SCHAR_MIN;
-unsigned char MIN = 0;
-short int MIN = SHRT_MIN;
-unsigned short int MIN = 0;
-int MIN = INT_MIN;
-unsigned int MIN = 0;
-long int MIN = LONG_MIN;
-unsigned long int MIN = 0;
-long long int MIN = LLONG_MIN;
-unsigned long long int MIN = 0;
+const signed char MIN = SCHAR_MIN;
+const unsigned char MIN = 0;
+const short int MIN = SHRT_MIN;
+const unsigned short int MIN = 0;
+const int MIN = INT_MIN;
+const unsigned int MIN = 0;
+const long int MIN = LONG_MIN;
+const unsigned long int MIN = 0;
+const long long int MIN = LLONG_MIN;
+const unsigned long long int MIN = 0;
 
-signed char MAX = SCHAR_MAX;
-unsigned char MAX = UCHAR_MAX;
-short int MAX = SHRT_MAX;
-unsigned short int MAX = USHRT_MAX;
-int MAX = INT_MAX;
-unsigned int MAX = UINT_MAX;
-long int MAX = LONG_MAX;
-unsigned long int MAX = ULONG_MAX;
-long long int MAX = LLONG_MAX;
-unsigned long long int MAX = ULLONG_MAX;
+const signed char MAX = SCHAR_MAX;
+const unsigned char MAX = UCHAR_MAX;
+const short int MAX = SHRT_MAX;
+const unsigned short int MAX = USHRT_MAX;
+const int MAX = INT_MAX;
+const unsigned int MAX = UINT_MAX;
+const long int MAX = LONG_MAX;
+const unsigned long int MAX = ULONG_MAX;
+const long long int MAX = LLONG_MAX;
+const unsigned long long int MAX = ULLONG_MAX;
 
 // Floating-Point Constants
 
-float MIN = FLT_MIN;
-double MIN = DBL_MIN;
-long double MIN = LDBL_MIN;
-float _Complex MIN = __FLT_MIN__ + __FLT_MIN__ * I;
-double _Complex MIN = DBL_MIN +  DBL_MIN * I;
-long double _Complex MIN = LDBL_MIN + LDBL_MIN * I;
+const float MIN = FLT_MIN;
+const double MIN = DBL_MIN;
+const long double MIN = LDBL_MIN;
+const float _Complex MIN = __FLT_MIN__ + __FLT_MIN__ * I;
+const double _Complex MIN = DBL_MIN +  DBL_MIN * I;
+const long double _Complex MIN = LDBL_MIN + LDBL_MIN * I;
 
-float MAX = FLT_MAX;
-double MAX = DBL_MAX;
-long double MAX = LDBL_MAX;
-float _Complex MAX = FLT_MAX + FLT_MAX * I;
-double _Complex MAX = DBL_MAX + DBL_MAX * I;
-long double _Complex MAX = LDBL_MAX + LDBL_MAX * I;
+const float MAX = FLT_MAX;
+const double MAX = DBL_MAX;
+const long double MAX = LDBL_MAX;
+const float _Complex MAX = FLT_MAX + FLT_MAX * I;
+const double _Complex MAX = DBL_MAX + DBL_MAX * I;
+const long double _Complex MAX = LDBL_MAX + LDBL_MAX * I;
 
-float PI = (float)M_PI;									// pi
-float PI_2 = (float)M_PI_2;								// pi / 2
-float PI_4 = (float)M_PI_4;								// pi / 4
-float _1_PI = (float)M_1_PI;							// 1 / pi
-float _2_PI = (float)M_2_PI;							// 2 / pi
-float _2_SQRT_PI = (float)M_2_SQRTPI;					// 2 / sqrt(pi)
+const float PI = (float)M_PI;							// pi
+const float PI_2 = (float)M_PI_2;						// pi / 2
+const float PI_4 = (float)M_PI_4;						// pi / 4
+const float _1_PI = (float)M_1_PI;						// 1 / pi
+const float _2_PI = (float)M_2_PI;						// 2 / pi
+const float _2_SQRT_PI = (float)M_2_SQRTPI;				// 2 / sqrt(pi)
 
-double PI = M_PI;										// pi
-double PI_2 = M_PI_2;									// pi / 2
-double PI_4 = M_PI_4;									// pi / 4
-double _1_PI = M_1_PI;									// 1 / pi
-double _2_PI = M_2_PI;									// 2 / pi
-double _2_SQRT_PI = M_2_SQRTPI;							// 2 / sqrt(pi)
+const double PI = M_PI;									// pi
+const double PI_2 = M_PI_2;								// pi / 2
+const double PI_4 = M_PI_4;								// pi / 4
+const double _1_PI = M_1_PI;							// 1 / pi
+const double _2_PI = M_2_PI;							// 2 / pi
+const double _2_SQRT_PI = M_2_SQRTPI;					// 2 / sqrt(pi)
 
-long double PI = M_PIl;									// pi
-long double PI_2 = M_PI_2l;								// pi / 2
-long double PI_4 = M_PI_4l;								// pi / 4
-long double _1_PI = M_1_PIl;							// 1 / pi
-long double _2_PI = M_2_PIl;							// 2 / pi
-long double _2_SQRT_PI = M_2_SQRTPIl;					// 2 / sqrt(pi)
+const long double PI = M_PIl;							// pi
+const long double PI_2 = M_PI_2l;						// pi / 2
+const long double PI_4 = M_PI_4l;						// pi / 4
+const long double _1_PI = M_1_PIl;						// 1 / pi
+const long double _2_PI = M_2_PIl;						// 2 / pi
+const long double _2_SQRT_PI = M_2_SQRTPIl;				// 2 / sqrt(pi)
 
-float _Complex PI = (float)M_PI + 0.0_iF;				// pi
-float _Complex PI_2 = (float)M_PI_2 + 0.0_iF;			// pi / 2
-float _Complex PI_4 = (float)M_PI_4 + 0.0_iF;			// pi / 4
-float _Complex _1_PI = (float)M_1_PI + 0.0_iF;			// 1 / pi
-float _Complex _2_PI = (float)M_2_PI + 0.0_iF;			// 2 / pi
-float _Complex _2_SQRT_PI = (float)M_2_SQRTPI + 0.0_iF; // 2 / sqrt(pi)
+const float _Complex PI = (float)M_PI + 0.0_iF;			// pi
+const float _Complex PI_2 = (float)M_PI_2 + 0.0_iF;		// pi / 2
+const float _Complex PI_4 = (float)M_PI_4 + 0.0_iF;		// pi / 4
+const float _Complex _1_PI = (float)M_1_PI + 0.0_iF;	// 1 / pi
+const float _Complex _2_PI = (float)M_2_PI + 0.0_iF;	// 2 / pi
+const float _Complex _2_SQRT_PI = (float)M_2_SQRTPI + 0.0_iF; // 2 / sqrt(pi)
 
-double _Complex PI = M_PI + 0.0_iD;						// pi
-double _Complex PI_2 = M_PI_2 + 0.0_iD;					// pi / 2
-double _Complex PI_4 = M_PI_4 + 0.0_iD;					// pi / 4
-double _Complex _1_PI = M_1_PI + 0.0_iD;				// 1 / pi
-double _Complex _2_PI = M_2_PI + 0.0_iD;				// 2 / pi
-double _Complex _2_SQRT_PI = M_2_SQRTPI + 0.0_iD;		// 2 / sqrt(pi)
+const double _Complex PI = M_PI + 0.0_iD;				// pi
+const double _Complex PI_2 = M_PI_2 + 0.0_iD;			// pi / 2
+const double _Complex PI_4 = M_PI_4 + 0.0_iD;			// pi / 4
+const double _Complex _1_PI = M_1_PI + 0.0_iD;			// 1 / pi
+const double _Complex _2_PI = M_2_PI + 0.0_iD;			// 2 / pi
+const double _Complex _2_SQRT_PI = M_2_SQRTPI + 0.0_iD;	// 2 / sqrt(pi)
 
-long double _Complex PI = M_PIl + 0.0_iL;				// pi
-long double _Complex PI_2 = M_PI_2l + 0.0_iL;			// pi / 2
-long double _Complex PI_4 = M_PI_4l + 0.0_iL;			// pi / 4
-long double _Complex _1_PI = M_1_PIl + 0.0_iL;			// 1 / pi
-long double _Complex _2_PI = M_2_PIl + 0.0_iL;			// 2 / pi
-long double _Complex _2_SQRT_PI = M_2_SQRTPIl + 0.0_iL; // 2 / sqrt(pi)
+const long double _Complex PI = M_PIl + 0.0_iL;			// pi
+const long double _Complex PI_2 = M_PI_2l + 0.0_iL;		// pi / 2
+const long double _Complex PI_4 = M_PI_4l + 0.0_iL;		// pi / 4
+const long double _Complex _1_PI = M_1_PIl + 0.0_iL;	// 1 / pi
+const long double _Complex _2_PI = M_2_PIl + 0.0_iL;	// 2 / pi
+const long double _Complex _2_SQRT_PI = M_2_SQRTPIl + 0.0_iL; // 2 / sqrt(pi)
 
-float E = (float)M_E;									// e
-float LOG2_E = (float)M_LOG2E;							// log_2(e)
-float LOG10_E = (float)M_LOG10E;						// log_10(e)
-float LN_2 = (float)M_LN2;								// log_e(2)
-float LN_10 = (float)M_LN10;							// log_e(10)
-float SQRT_2 = (float)M_SQRT2;							// sqrt(2)
-float _1_SQRT_2 = (float)M_SQRT1_2;						// 1 / sqrt(2)
+const float E = (float)M_E;								// e
+const float LOG2_E = (float)M_LOG2E;					// log_2(e)
+const float LOG10_E = (float)M_LOG10E;					// log_10(e)
+const float LN_2 = (float)M_LN2;						// log_e(2)
+const float LN_10 = (float)M_LN10;						// log_e(10)
+const float SQRT_2 = (float)M_SQRT2;					// sqrt(2)
+const float _1_SQRT_2 = (float)M_SQRT1_2;				// 1 / sqrt(2)
 
-double E = M_E;											// e
-double LOG2_E = M_LOG2E;								// log_2(e)
-double LOG10_E = M_LOG10E;								// log_10(e)
-double LN_2 = M_LN2;									// log_e(2)
-double LN_10 = M_LN10;									// log_e(10)
-double SQRT_2 = M_SQRT2;								// sqrt(2)
-double _1_SQRT_2 = M_SQRT1_2;							// 1 / sqrt(2)
+const double E = M_E;									// e
+const double LOG2_E = M_LOG2E;							// log_2(e)
+const double LOG10_E = M_LOG10E;						// log_10(e)
+const double LN_2 = M_LN2;								// log_e(2)
+const double LN_10 = M_LN10;							// log_e(10)
+const double SQRT_2 = M_SQRT2;							// sqrt(2)
+const double _1_SQRT_2 = M_SQRT1_2;						// 1 / sqrt(2)
 
-long double E = M_El;									// e
-long double LOG2_E = M_LOG2El;							// log_2(e)
-long double LOG10_E = M_LOG10El;						// log_10(e)
-long double LN_2 = M_LN2l;								// log_e(2)
-long double LN_10 = M_LN10l;							// log_e(10)
-long double SQRT_2 = M_SQRT2l;							// sqrt(2)
-long double _1_SQRT_2 = M_SQRT1_2l;						// 1 / sqrt(2)
+const long double E = M_El;								// e
+const long double LOG2_E = M_LOG2El;					// log_2(e)
+const long double LOG10_E = M_LOG10El;					// log_10(e)
+const long double LN_2 = M_LN2l;						// log_e(2)
+const long double LN_10 = M_LN10l;						// log_e(10)
+const long double SQRT_2 = M_SQRT2l;					// sqrt(2)
+const long double _1_SQRT_2 = M_SQRT1_2l;				// 1 / sqrt(2)
 
-float _Complex E = M_E + 0.0_iF;						// e
-float _Complex LOG2_E = M_LOG2E + 0.0_iF;				// log_2(e)
-float _Complex LOG10_E = M_LOG10E + 0.0_iF;				// log_10(e)
-float _Complex LN_2 = M_LN2 + 0.0_iF;					// log_e(2)
-float _Complex LN_10 = M_LN10 + 0.0_iF;					// log_e(10)
-float _Complex SQRT_2 = M_SQRT2 + 0.0_iF;				// sqrt(2)
-float _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iF;			// 1 / sqrt(2)
+const float _Complex E = M_E + 0.0_iF;					// e
+const float _Complex LOG2_E = M_LOG2E + 0.0_iF;			// log_2(e)
+const float _Complex LOG10_E = M_LOG10E + 0.0_iF;		// log_10(e)
+const float _Complex LN_2 = M_LN2 + 0.0_iF;				// log_e(2)
+const float _Complex LN_10 = M_LN10 + 0.0_iF;			// log_e(10)
+const float _Complex SQRT_2 = M_SQRT2 + 0.0_iF;			// sqrt(2)
+const float _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iF;	// 1 / sqrt(2)
 
-double _Complex E = M_E + 0.0_iD;						// e
-double _Complex LOG2_E = M_LOG2E + 0.0_iD;				// log_2(e)
-double _Complex LOG10_E = M_LOG10E + 0.0_iD;			// log_10(e)
-double _Complex LN_2 = M_LN2 + 0.0_iD;					// log_e(2)
-double _Complex LN_10 = M_LN10 + 0.0_iD;				// log_e(10)
-double _Complex SQRT_2 = M_SQRT2 + 0.0_iD;				// sqrt(2)
-double _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iD;			// 1 / sqrt(2)
+const double _Complex E = M_E + 0.0_iD;					// e
+const double _Complex LOG2_E = M_LOG2E + 0.0_iD;		// log_2(e)
+const double _Complex LOG10_E = M_LOG10E + 0.0_iD;		// log_10(e)
+const double _Complex LN_2 = M_LN2 + 0.0_iD;			// log_e(2)
+const double _Complex LN_10 = M_LN10 + 0.0_iD;			// log_e(10)
+const double _Complex SQRT_2 = M_SQRT2 + 0.0_iD;		// sqrt(2)
+const double _Complex _1_SQRT_2 = M_SQRT1_2 + 0.0_iD;	// 1 / sqrt(2)
 
-long double _Complex E = M_El + 0.0_iL;					// e
-long double _Complex LOG2_E = M_LOG2El + 0.0_iL;		// log_2(e)
-long double _Complex LOG10_E = M_LOG10El + 0.0_iL;		// log_10(e)
-long double _Complex LN_2 = M_LN2l + 0.0_iL;			// log_e(2)
-long double _Complex LN_10 = M_LN10l + 0.0_iL;			// log_e(10)
-long double _Complex SQRT_2 = M_SQRT2l + 0.0_iL;		// sqrt(2)
-long double _Complex _1_SQRT_2 = M_SQRT1_2l + 0.0_iL;	// 1 / sqrt(2)
+const long double _Complex E = M_El + 0.0_iL;			// e
+const long double _Complex LOG2_E = M_LOG2El + 0.0_iL;	// log_2(e)
+const long double _Complex LOG10_E = M_LOG10El + 0.0_iL; // log_10(e)
+const long double _Complex LN_2 = M_LN2l + 0.0_iL;		// log_e(2)
+const long double _Complex LN_10 = M_LN10l + 0.0_iL;	// log_e(10)
+const long double _Complex SQRT_2 = M_SQRT2l + 0.0_iL;	// sqrt(2)
+const long double _Complex _1_SQRT_2 = M_SQRT1_2l + 0.0_iL; // 1 / sqrt(2)
 
 // Local Variables: //
Index: libcfa/src/limits.hfa
===================================================================
--- libcfa/src/limits.hfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ libcfa/src/limits.hfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -10,6 +10,6 @@
 // Created On       : Wed Apr  6 18:06:52 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Sep 30 22:56:35 2020
-// Update Count     : 15
+// Last Modified On : Thu Mar  1 16:20:54 2018
+// Update Count     : 13
 //
 
@@ -18,131 +18,131 @@
 // Integral Constants
 
-extern signed char MIN;
-extern unsigned char MIN;
-extern short int MIN;
-extern unsigned short int MIN;
-extern int MIN;
-extern unsigned int MIN;
-extern long int MIN;
-extern unsigned long int MIN;
-extern long long int MIN;
-extern unsigned long long int MIN;
+extern const signed char MIN;
+extern const unsigned char MIN;
+extern const short int MIN;
+extern const unsigned short int MIN;
+extern const int MIN;
+extern const unsigned int MIN;
+extern const long int MIN;
+extern const unsigned long int MIN;
+extern const long long int MIN;
+extern const unsigned long long int MIN;
 
-extern signed char MAX;
-extern unsigned char MAX;
-extern short int MAX;
-extern unsigned short int MAX;
-extern int MAX;
-extern unsigned int MAX;
-extern long int MAX;
-extern unsigned long int MAX;
-extern long long int MAX;
-extern unsigned long long int MAX;
+extern const signed char MAX;
+extern const unsigned char MAX;
+extern const short int MAX;
+extern const unsigned short int MAX;
+extern const int MAX;
+extern const unsigned int MAX;
+extern const long int MAX;
+extern const unsigned long int MAX;
+extern const long long int MAX;
+extern const unsigned long long int MAX;
 
 // Floating-Point Constants
 
-extern float MIN;
-extern double MIN;
-extern long double MIN;
-extern float _Complex MIN;
-extern double _Complex MIN;
-extern long double _Complex MIN;
+extern const float MIN;
+extern const double MIN;
+extern const long double MIN;
+extern const float _Complex MIN;
+extern const double _Complex MIN;
+extern const long double _Complex MIN;
 
-extern float MAX;
-extern double MAX;
-extern long double MAX;
-extern float _Complex MAX;
-extern double _Complex MAX;
-extern long double _Complex MAX;
+extern const float MAX;
+extern const double MAX;
+extern const long double MAX;
+extern const float _Complex MAX;
+extern const double _Complex MAX;
+extern const long double _Complex MAX;
 
-extern float PI;										// pi
-extern float PI_2;										// pi / 2
-extern float PI_4;										// pi / 4
-extern float _1_PI;										// 1 / pi
-extern float _2_PI;										// 2 / pi
-extern float _2_SQRT_PI;								// 2 / sqrt(pi)
+extern const float PI;									// pi
+extern const float PI_2;								// pi / 2
+extern const float PI_4;								// pi / 4
+extern const float _1_PI;								// 1 / pi
+extern const float _2_PI;								// 2 / pi
+extern const float _2_SQRT_PI;							// 2 / sqrt(pi)
 
-extern double PI;										// pi
-extern double PI_2;										// pi / 2
-extern double PI_4;										// pi / 4
-extern double _1_PI;									// 1 / pi
-extern double _2_PI;									// 2 / pi
-extern double _2_SQRT_PI;								// 2 / sqrt(pi)
+extern const double PI;									// pi
+extern const double PI_2;								// pi / 2
+extern const double PI_4;								// pi / 4
+extern const double _1_PI;								// 1 / pi
+extern const double _2_PI;								// 2 / pi
+extern const double _2_SQRT_PI;							// 2 / sqrt(pi)
 
-extern long double PI;									// pi
-extern long double PI_2;								// pi / 2
-extern long double PI_4;								// pi / 4
-extern long double _1_PI;								// 1 / pi
-extern long double _2_PI;								// 2 / pi
-extern long double _2_SQRT_PI;							// 2 / sqrt(pi)
+extern const long double PI;							// pi
+extern const long double PI_2;							// pi / 2
+extern const long double PI_4;							// pi / 4
+extern const long double _1_PI;							// 1 / pi
+extern const long double _2_PI;							// 2 / pi
+extern const long double _2_SQRT_PI;					// 2 / sqrt(pi)
 
-extern float _Complex PI;								// pi
-extern float _Complex PI_2;								// pi / 2
-extern float _Complex PI_4;								// pi / 4
-extern float _Complex _1_PI;							// 1 / pi
-extern float _Complex _2_PI;							// 2 / pi
-extern float _Complex _2_SQRT_PI;						// 2 / sqrt(pi)
+extern const float _Complex PI;							// pi
+extern const float _Complex PI_2;						// pi / 2
+extern const float _Complex PI_4;						// pi / 4
+extern const float _Complex _1_PI;						// 1 / pi
+extern const float _Complex _2_PI;						// 2 / pi
+extern const float _Complex _2_SQRT_PI;					// 2 / sqrt(pi)
 
-extern double _Complex PI;								// pi
-extern double _Complex PI_2;							// pi / 2
-extern double _Complex PI_4;							// pi / 4
-extern double _Complex _1_PI;							// 1 / pi
-extern double _Complex _2_PI;							// 2 / pi
-extern double _Complex _2_SQRT_PI;						// 2 / sqrt(pi)
+extern const double _Complex PI;						// pi
+extern const double _Complex PI_2;						// pi / 2
+extern const double _Complex PI_4;						// pi / 4
+extern const double _Complex _1_PI;						// 1 / pi
+extern const double _Complex _2_PI;						// 2 / pi
+extern const double _Complex _2_SQRT_PI;				// 2 / sqrt(pi)
 
-extern long double _Complex PI;							// pi
-extern long double _Complex PI_2;						// pi / 2
-extern long double _Complex PI_4;						// pi / 4
-extern long double _Complex _1_PI;						// 1 / pi
-extern long double _Complex _2_PI;						// 2 / pi
-extern long double _Complex _2_SQRT_PI;					// 2 / sqrt(pi)
+extern const long double _Complex PI;					// pi
+extern const long double _Complex PI_2;					// pi / 2
+extern const long double _Complex PI_4;					// pi / 4
+extern const long double _Complex _1_PI;				// 1 / pi
+extern const long double _Complex _2_PI;				// 2 / pi
+extern const long double _Complex _2_SQRT_PI;			// 2 / sqrt(pi)
 
-extern float E;											// e
-extern float LOG2_E;									// log_2(e)
-extern float LOG10_E;									// log_10(e)
-extern float LN_2;										// log_e(2)
-extern float LN_10;										// log_e(10)
-extern float SQRT_2;									// sqrt(2)
-extern float _1_SQRT_2;									// 1 / sqrt(2)
+extern const float E;									// e
+extern const float LOG2_E;								// log_2(e)
+extern const float LOG10_E;								// log_10(e)
+extern const float LN_2;								// log_e(2)
+extern const float LN_10;								// log_e(10)
+extern const float SQRT_2;								// sqrt(2)
+extern const float _1_SQRT_2;							// 1 / sqrt(2)
 
-extern double E;										// e
-extern double LOG2_E;									// log_2(e)
-extern double LOG10_E;									// log_10(e)
-extern double LN_2;										// log_e(2)
-extern double LN_10;									// log_e(10)
-extern double SQRT_2;									// sqrt(2)
-extern double _1_SQRT_2;								// 1 / sqrt(2)
+extern const double E;									// e
+extern const double LOG2_E;								// log_2(e)
+extern const double LOG10_E;							// log_10(e)
+extern const double LN_2;								// log_e(2)
+extern const double LN_10;								// log_e(10)
+extern const double SQRT_2;								// sqrt(2)
+extern const double _1_SQRT_2;							// 1 / sqrt(2)
 
-extern long double E;									// e
-extern long double LOG2_E;								// log_2(e)
-extern long double LOG10_E;								// log_10(e)
-extern long double LN_2;								// log_e(2)
-extern long double LN_10;								// log_e(10)
-extern long double SQRT_2;								// sqrt(2)
-extern long double _1_SQRT_2;							// 1/sqrt(2)
+extern const long double E;								// e
+extern const long double LOG2_E;						// log_2(e)
+extern const long double LOG10_E;						// log_10(e)
+extern const long double LN_2;							// log_e(2)
+extern const long double LN_10;							// log_e(10)
+extern const long double SQRT_2;						// sqrt(2)
+extern const long double _1_SQRT_2;						// 1/sqrt(2)
 
-extern float _Complex E;								// e
-extern float _Complex LOG2_E;							// log_2(e)
-extern float _Complex LOG10_E;							// log_10(e)
-extern float _Complex LN_2;								// log_e(2)
-extern float _Complex LN_10;							// log_e(10)
-extern float _Complex SQRT_2;							// sqrt(2)
-extern float _Complex _1_SQRT_2;						// 1 / sqrt(2)
+extern const float _Complex E;							// e
+extern const float _Complex LOG2_E;						// log_2(e)
+extern const float _Complex LOG10_E;					// log_10(e)
+extern const float _Complex LN_2;						// log_e(2)
+extern const float _Complex LN_10;						// log_e(10)
+extern const float _Complex SQRT_2;						// sqrt(2)
+extern const float _Complex _1_SQRT_2;					// 1 / sqrt(2)
 
-extern double _Complex E;								// e
-extern double _Complex LOG2_E;							// log_2(e)
-extern double _Complex LOG10_E;							// log_10(e)
-extern double _Complex LN_2;							// log_e(2)
-extern double _Complex LN_10;							// log_e(10)
-extern double _Complex SQRT_2;							// sqrt(2)
-extern double _Complex _1_SQRT_2;						// 1 / sqrt(2)
+extern const double _Complex E;							// e
+extern const double _Complex LOG2_E;					// log_2(e)
+extern const double _Complex LOG10_E;					// log_10(e)
+extern const double _Complex LN_2;						// log_e(2)
+extern const double _Complex LN_10;						// log_e(10)
+extern const double _Complex SQRT_2;					// sqrt(2)
+extern const double _Complex _1_SQRT_2;					// 1 / sqrt(2)
 
-extern long double _Complex E;							// e
-extern long double _Complex LOG2_E;						// log_2(e)
-extern long double _Complex LOG10_E;					// log_10(e)
-extern long double _Complex LN_2;						// log_e(2)
-extern long double _Complex LN_10;						// log_e(10)
-extern long double _Complex SQRT_2;						// sqrt(2)
-extern long double _Complex _1_SQRT_2;					// 1 / sqrt(2)
+extern const long double _Complex E;					// e
+extern const long double _Complex LOG2_E;				// log_2(e)
+extern const long double _Complex LOG10_E;				// log_10(e)
+extern const long double _Complex LN_2;					// log_e(2)
+extern const long double _Complex LN_10;				// log_e(10)
+extern const long double _Complex SQRT_2;				// sqrt(2)
+extern const long double _Complex _1_SQRT_2;			// 1 / sqrt(2)
 
 // Local Variables: //
Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/AST/Expr.cpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -102,4 +102,29 @@
 	}
 	return ret;
+}
+
+// --- VariableExpr
+
+VariableExpr::VariableExpr( const CodeLocation & loc )
+: Expr( loc ), var( nullptr ) {}
+
+VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
+: Expr( loc ), var( v ) {
+	assert( var );
+	assert( var->get_type() );
+	result = shallowCopy( var->get_type() );
+}
+
+bool VariableExpr::get_lvalue() const {
+	// It isn't always an lvalue, but it is never an rvalue.
+	return true;
+}
+
+VariableExpr * VariableExpr::functionPointer(
+		const CodeLocation & loc, const FunctionDecl * decl ) {
+	// wrap usually-determined result type in a pointer
+	VariableExpr * funcExpr = new VariableExpr{ loc, decl };
+	funcExpr->result = new PointerType{ funcExpr->result };
+	return funcExpr;
 }
 
@@ -238,29 +263,4 @@
 }
 
-// --- VariableExpr
-
-VariableExpr::VariableExpr( const CodeLocation & loc )
-: Expr( loc ), var( nullptr ) {}
-
-VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
-: Expr( loc ), var( v ) {
-	assert( var );
-	assert( var->get_type() );
-	result = shallowCopy( var->get_type() );
-}
-
-bool VariableExpr::get_lvalue() const {
-	// It isn't always an lvalue, but it is never an rvalue.
-	return true;
-}
-
-VariableExpr * VariableExpr::functionPointer(
-		const CodeLocation & loc, const FunctionDecl * decl ) {
-	// wrap usually-determined result type in a pointer
-	VariableExpr * funcExpr = new VariableExpr{ loc, decl };
-	funcExpr->result = new PointerType{ funcExpr->result };
-	return funcExpr;
-}
-
 // --- ConstantExpr
 
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/AST/Expr.hpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -250,4 +250,23 @@
 };
 
+/// A reference to a named variable.
+class VariableExpr final : public Expr {
+public:
+	readonly<DeclWithType> var;
+
+	VariableExpr( const CodeLocation & loc );
+	VariableExpr( const CodeLocation & loc, const DeclWithType * v );
+
+	bool get_lvalue() const final;
+
+	/// generates a function pointer for a given function
+	static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
+
+	const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	VariableExpr * clone() const override { return new VariableExpr{ *this }; }
+	MUTATE_FRIEND
+};
+
 /// Address-of expression `&e`
 class AddressExpr final : public Expr {
@@ -390,23 +409,4 @@
 	friend class ::ConverterOldToNew;
 	friend class ::ConverterNewToOld;
-};
-
-/// A reference to a named variable.
-class VariableExpr final : public Expr {
-public:
-	readonly<DeclWithType> var;
-
-	VariableExpr( const CodeLocation & loc );
-	VariableExpr( const CodeLocation & loc, const DeclWithType * v );
-
-	bool get_lvalue() const final;
-
-	/// generates a function pointer for a given function
-	static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
-
-	const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
-	VariableExpr * clone() const override { return new VariableExpr{ *this }; }
-	MUTATE_FRIEND
 };
 
Index: src/AST/Type.cpp
===================================================================
--- src/AST/Type.cpp	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/AST/Type.cpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -157,4 +157,10 @@
 
 template<typename decl_t>
+SueInstType<decl_t>::SueInstType(
+	const base_type * b, std::vector<ptr<Expr>> && params,
+	CV::Qualifiers q, std::vector<ptr<Attribute>> && as )
+: BaseInstType( b->name, std::move(params), q, std::move(as) ), base( b ) {}
+
+template<typename decl_t>
 bool SueInstType<decl_t>::isComplete() const {
 	return base ? base->body : false;
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/AST/Type.hpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -302,7 +302,4 @@
 class FunctionType final : public ParameterizedType {
 public:
-//	std::vector<ptr<DeclWithType>> returns;
-//	std::vector<ptr<DeclWithType>> params;
-
 	std::vector<ptr<Type>> returns;
 	std::vector<ptr<Type>> params;
@@ -345,4 +342,9 @@
 	: ParameterizedType(q, std::move(as)), params(), name(n) {}
 
+	BaseInstType(
+		const std::string& n, std::vector<ptr<Expr>> && params,
+		CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
+	: ParameterizedType(q, std::move(as)), params(std::move(params)), name(n) {}
+
 	BaseInstType( const BaseInstType & o );
 
@@ -369,5 +371,9 @@
 
 	SueInstType(
-		const decl_t * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
+		const base_type * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
+
+	SueInstType(
+		const base_type * b, std::vector<ptr<Expr>> && params,
+		CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
 
 	bool isComplete() const override;
Index: src/AST/porting.md
===================================================================
--- src/AST/porting.md	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/AST/porting.md	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -30,4 +30,8 @@
   * Base nodes now override `const Node * accept( Visitor & v ) const = 0` with, e.g. `const Stmt * accept( Visitor & v ) const override = 0`
 * `PassVisitor` is replaced with `ast::Pass`
+  * Most one shot uses can use `ast::Pass::run` and `ast::Pass::read`.
+
+`WithConstTypeSubstitution`
+* `env` => `typeSubs`
 
 ## Structural Changes ##
@@ -146,4 +150,9 @@
   * allows `newObject` as just default settings
 
+`FunctionDecl`
+* `params` and `returns` added.
+  * Contain the declarations of the parameters and return variables.
+  * Types should match (even be shared with) the fields of `type`.
+
 `NamedTypeDecl`
 * `parameters` => `params`
@@ -154,4 +163,7 @@
 `AggregateDecl`
 * `parameters` => `params`
+
+`StructDecl`
+* `makeInst` replaced by better constructor on `StructInstType`.
 
 `Expr`
@@ -245,5 +257,5 @@
 * **TODO** move `kind`, `typeNames` into code generator
 
-`ReferenceToType`
+`ReferenceToType` => `BaseInstType`
 * deleted `get_baseParameters()` from children
   * replace with `aggr() ? aggr()->params : nullptr`
@@ -261,5 +273,10 @@
 * `returnVals` => `returns`
 * `parameters` => `params`
+  * Both now just point at types.
 * `bool isVarArgs;` => `enum ArgumentFlag { FixedArgs, VariableArgs }; ArgumentFlag isVarArgs;`
+
+`SueInstType`
+* Template class, with specializations and using to implement some other types:
+  * `StructInstType`, `UnionInstType` & `EnumInstType`
 
 `TypeInstType`
Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/Concurrency/Keywords.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -66,5 +66,6 @@
 			bool needs_main, AggregateDecl::Aggregate cast_target ) :
 		  type_name( type_name ), field_name( field_name ), getter_name( getter_name ),
-		  context_error( context_error ), vtable_name( getVTableName( exception_name ) ),
+		  context_error( context_error ), exception_name( exception_name ),
+		  vtable_name( getVTableName( exception_name ) ),
 		  needs_main( needs_main ), cast_target( cast_target ) {}
 
@@ -89,4 +90,5 @@
 		const std::string getter_name;
 		const std::string context_error;
+		const std::string exception_name;
 		const std::string vtable_name;
 		bool needs_main;
@@ -95,4 +97,5 @@
 		StructDecl   * type_decl = nullptr;
 		FunctionDecl * dtor_decl = nullptr;
+		StructDecl * except_decl = nullptr;
 		StructDecl * vtable_decl = nullptr;
 	};
@@ -376,4 +379,7 @@
 		else if ( is_target(decl) ) {
 			handle( decl );
+		}
+		else if ( !except_decl && exception_name == decl->name && decl->body ) {
+			except_decl = decl;
 		}
 		else if ( !vtable_decl && vtable_name == decl->name && decl->body ) {
@@ -398,7 +404,11 @@
 			assert( struct_type );
 
-			declsToAddAfter.push_back( Virtual::makeVtableInstance( vtable_decl, {
-				new TypeExpr( struct_type->clone() ),
-			}, struct_type, nullptr ) );
+			std::list< Expression * > poly_args = { new TypeExpr( struct_type->clone() ) };
+			ObjectDecl * vtable_object = Virtual::makeVtableInstance(
+				vtable_decl->makeInst( poly_args ), struct_type, nullptr );
+			declsToAddAfter.push_back( vtable_object );
+			declsToAddAfter.push_back( Virtual::makeGetExceptionFunction(
+				vtable_object, except_decl->makeInst( std::move( poly_args ) )
+			) );
 		}
 
@@ -434,7 +444,13 @@
 	void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) {
 		if ( vtable_decl ) {
-			declsToAddBefore.push_back( Virtual::makeVtableForward( vtable_decl, {
+			std::list< Expression * > poly_args = {
 				new TypeExpr( new StructInstType( noQualifiers, decl ) ),
-			} ) );
+			};
+			declsToAddBefore.push_back( Virtual::makeGetExceptionForward(
+				vtable_decl->makeInst( poly_args ),
+				except_decl->makeInst( poly_args )
+			) );
+			declsToAddBefore.push_back( Virtual::makeVtableForward(
+				vtable_decl->makeInst( move( poly_args ) ) ) );
 		// Its only an error if we want a vtable and don't have one.
 		} else if ( ! vtable_name.empty() ) {
Index: src/InitTweak/FixGlobalInit.cc
===================================================================
--- src/InitTweak/FixGlobalInit.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/InitTweak/FixGlobalInit.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -153,4 +153,5 @@
 			} // if
 			if ( Statement * ctor = ctorInit->ctor ) {
+				addDataSectonAttribute( objDecl );
 				initStatements.push_back( ctor );
 				objDecl->init = nullptr;
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/InitTweak/FixInit.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -802,4 +802,10 @@
 				if ( Statement * ctor = ctorInit->get_ctor() ) {
 					if ( objDecl->get_storageClasses().is_static ) {
+
+						// The ojbect needs to go in the data section, regardless of dtor complexity below.
+						// The attribute works, and is meant to apply, both for leaving the static local alone,
+						// and for hoisting it out as a static global.
+						addDataSectonAttribute( objDecl );
+
 						// originally wanted to take advantage of gcc nested functions, but
 						// we get memory errors with this approach. To remedy this, the static
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/InitTweak/InitTweak.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -1103,3 +1103,13 @@
 		return isCopyFunction( decl, "?{}" );
 	}
+
+	void addDataSectonAttribute( ObjectDecl * objDecl ) {
+		Type *strLitT = new PointerType( Type::Qualifiers( ),
+			new BasicType( Type::Qualifiers( ), BasicType::Char ) );
+		std::list< Expression * > attr_params;
+		attr_params.push_back( 
+			new ConstantExpr( Constant( strLitT, "\".data#\"", std::nullopt ) ) );
+		objDecl->attributes.push_back(new Attribute("section", attr_params));
+	}
+
 }
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/InitTweak/InitTweak.h	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -108,4 +108,15 @@
 	bool isConstExpr( Initializer * init );
 
+	/// Modifies objDecl to have:
+	///    __attribute__((section (".data#")))
+	/// which makes gcc put the declared variable in the data section,
+	/// which is helpful for global constants on newer gcc versions,
+	/// so that CFA's generated initialization won't segfault when writing it via a const cast.
+	/// The trailing # is an injected assembly comment, to suppress the "a" in
+	///    .section .data,"a"
+	///    .section .data#,"a"
+	/// to avoid assembler warning "ignoring changed section attributes for .data"
+	void addDataSectonAttribute( ObjectDecl * objDecl );
+
 	class InitExpander_old {
 	public:
Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/Parser/DeclarationNode.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -10,6 +10,6 @@
 // Created On       : Sat May 16 12:34:05 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jun  9 20:26:55 2020
-// Update Count     : 1134
+// Last Modified On : Thu Oct  8 08:03:38 2020
+// Update Count     : 1135
 //
 
@@ -1016,5 +1016,5 @@
 			if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
 				dwt->location = cur->location;
-				* out++ = dwt;
+				*out++ = dwt;
 			} else if ( StructDecl * agg = dynamic_cast< StructDecl * >( decl ) ) {
 				// e.g., int foo(struct S) {}
@@ -1022,5 +1022,5 @@
 				auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
 				obj->location = cur->location;
-				* out++ = obj;
+				*out++ = obj;
 				delete agg;
 			} else if ( UnionDecl * agg = dynamic_cast< UnionDecl * >( decl ) ) {
@@ -1029,5 +1029,5 @@
 				auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
 				obj->location = cur->location;
-				* out++ = obj;
+				*out++ = obj;
 			} else if ( EnumDecl * agg = dynamic_cast< EnumDecl * >( decl ) ) {
 				// e.g., int foo(enum E) {}
@@ -1035,5 +1035,5 @@
 				auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
 				obj->location = cur->location;
-				* out++ = obj;
+				*out++ = obj;
 			} // if
 		} catch( SemanticErrorException & e ) {
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/Parser/parser.yy	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -10,6 +10,6 @@
 // Created On       : Sat Sep  1 20:22:55 2001
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Oct  6 18:24:18 2020
-// Update Count     : 4610
+// Last Modified On : Fri Oct  9 18:09:09 2020
+// Update Count     : 4614
 //
 
@@ -204,8 +204,8 @@
 			return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );
 		} else {
-			SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed" ); return nullptr;
+			SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed." ); return nullptr;
 		} // if
 	} else {
-		SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed" ); return nullptr;
+		SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed." ); return nullptr;
 	} // if
 } // forCtrl
@@ -2412,5 +2412,5 @@
 // Overloading: function, data, and operator identifiers may be overloaded.
 //
-// Type declarations: "type" is used to generate new types for declaring objects. Similarly, "dtype" is used for object
+// Type declarations: "otype" is used to generate new types for declaring objects. Similarly, "dtype" is used for object
 //     and incomplete types, and "ftype" is used for function types. Type declarations with initializers provide
 //     definitions of new types. Type declarations with storage class "extern" provide opaque types.
@@ -2441,5 +2441,5 @@
 	type_class identifier_or_type_name
 		{ typedefTable.addToScope( *$2, TYPEDEFname, "9" ); }
-	  type_initializer_opt assertion_list_opt
+	type_initializer_opt assertion_list_opt
 		{ $$ = DeclarationNode::newTypeParam( $1, $2 )->addTypeInitializer( $4 )->addAssertions( $5 ); }
 	| type_specifier identifier_parameter_declarator
@@ -2468,5 +2468,5 @@
 	assertion
 	| assertion_list assertion
-		{ $$ = $1 ? $1->appendList( $2 ) : $2; }
+		{ $$ = $1->appendList( $2 ); }
 	;
 
Index: src/SynTree/AggregateDecl.cc
===================================================================
--- src/SynTree/AggregateDecl.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/SynTree/AggregateDecl.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -21,4 +21,5 @@
 #include "Common/utility.h"      // for printAll, cloneAll, deleteAll
 #include "Declaration.h"         // for AggregateDecl, TypeDecl, Declaration
+#include "Expression.h"
 #include "Initializer.h"
 #include "LinkageSpec.h"         // for Spec, linkageName, Cforall
@@ -88,4 +89,17 @@
 const char * StructDecl::typeString() const { return aggrString( kind ); }
 
+StructInstType * StructDecl::makeInst( std::list< Expression * > const & new_parameters ) {
+	std::list< Expression * > copy_parameters;
+	cloneAll( new_parameters, copy_parameters );
+	return makeInst( move( copy( copy_parameters ) ) );
+}
+
+StructInstType * StructDecl::makeInst( std::list< Expression * > && new_parameters ) {
+	assert( parameters.size() == new_parameters.size() );
+	StructInstType * type = new StructInstType( noQualifiers, this );
+	type->parameters = std::move( new_parameters );
+	return type;
+}
+
 const char * UnionDecl::typeString() const { return aggrString( Union ); }
 
Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/SynTree/Declaration.h	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -306,4 +306,8 @@
 	bool is_thread   () { return kind == Thread   ; }
 
+	// Make a type instance of this declaration.
+	StructInstType * makeInst( std::list< Expression * > const & parameters );
+	StructInstType * makeInst( std::list< Expression * > && parameters );
+
 	virtual StructDecl * clone() const override { return new StructDecl( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/SynTree/Expression.h	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -163,4 +163,29 @@
 };
 
+/// VariableExpr represents an expression that simply refers to the value of a named variable.
+/// Does not take ownership of var.
+class VariableExpr : public Expression {
+  public:
+	DeclarationWithType * var;
+
+	VariableExpr();
+	VariableExpr( DeclarationWithType * var );
+	VariableExpr( const VariableExpr & other );
+	virtual ~VariableExpr();
+
+	bool get_lvalue() const final;
+
+	DeclarationWithType * get_var() const { return var; }
+	void set_var( DeclarationWithType * newValue ) { var = newValue; }
+
+	static VariableExpr * functionPointer( FunctionDecl * decl );
+
+	virtual VariableExpr * clone() const override { return new VariableExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
+};
+
 // The following classes are used to represent expression types that cannot be converted into
 // function-call format.
@@ -329,29 +354,4 @@
 };
 
-/// VariableExpr represents an expression that simply refers to the value of a named variable.
-/// Does not take ownership of var.
-class VariableExpr : public Expression {
-  public:
-	DeclarationWithType * var;
-
-	VariableExpr();
-	VariableExpr( DeclarationWithType * var );
-	VariableExpr( const VariableExpr & other );
-	virtual ~VariableExpr();
-
-	bool get_lvalue() const final;
-
-	DeclarationWithType * get_var() const { return var; }
-	void set_var( DeclarationWithType * newValue ) { var = newValue; }
-
-	static VariableExpr * functionPointer( FunctionDecl * decl );
-
-	virtual VariableExpr * clone() const override { return new VariableExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
 /// ConstantExpr represents an expression that simply refers to the value of a constant
 class ConstantExpr : public Expression {
Index: src/SynTree/TypeDecl.cc
===================================================================
--- src/SynTree/TypeDecl.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/SynTree/TypeDecl.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Dec 13 15:26:14 2019
-// Update Count     : 21
+// Last Modified On : Thu Oct  8 18:18:55 2020
+// Update Count     : 22
 //
 
@@ -21,5 +21,6 @@
 #include "Type.h"            // for Type, Type::StorageClasses
 
-TypeDecl::TypeDecl( const std::string & name, Type::StorageClasses scs, Type * type, Kind kind, bool sized, Type * init ) : Parent( name, scs, type ), kind( kind ), sized( kind == Ttype || sized ), init( init ) {
+TypeDecl::TypeDecl( const std::string & name, Type::StorageClasses scs, Type * type, Kind kind, bool sized, Type * init ) :
+	Parent( name, scs, type ), kind( kind ), sized( kind == Ttype || sized ), init( init ) {
 }
 
Index: src/Virtual/Tables.cc
===================================================================
--- src/Virtual/Tables.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/Virtual/Tables.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -14,6 +14,8 @@
 //
 
+#include <SynTree/Attribute.h>
 #include <SynTree/Declaration.h>
 #include <SynTree/Expression.h>
+#include <SynTree/Statement.h>
 #include <SynTree/Type.h>
 
@@ -38,14 +40,4 @@
 }
 
-// Fuse base polymorphic declaration and forall arguments into a new type.
-static StructInstType * vtableInstType(
-		StructDecl * polyDecl, std::list< Expression * > && parameters ) {
-	assert( parameters.size() == polyDecl->parameters.size() );
-	StructInstType * type = new StructInstType(
-			Type::Qualifiers( /* Type::Const */ ), polyDecl );
-	type->parameters = std::move( parameters );
-	return type;
-}
-
 static ObjectDecl * makeVtableDeclaration(
 		StructInstType * type, Initializer * init ) {
@@ -66,14 +58,12 @@
 
 ObjectDecl * makeVtableForward( StructInstType * type ) {
+	assert( type );
 	return makeVtableDeclaration( type, nullptr );
 }
 
-ObjectDecl * makeVtableForward(
-		StructDecl * polyDecl, std::list< Expression * > && parameters ) {
-	return makeVtableForward( vtableInstType( polyDecl, std::move( parameters ) ) );
-}
-
 ObjectDecl * makeVtableInstance(
-		StructInstType * vtableType, Type * vobject_type, Initializer * init ) {
+		StructInstType * vtableType, Type * objectType, Initializer * init ) {
+	assert( vtableType );
+	assert( objectType );
 	StructDecl * vtableStruct = vtableType->baseStruct;
 	// Build the initialization
@@ -92,7 +82,7 @@
 						new SingleInit( new AddressExpr( new NameExpr( parentInstance ) ) ) );
 			} else if ( std::string( "size" ) == field->name ) {
-				inits.push_back( new SingleInit( new SizeofExpr( vobject_type->clone() ) ) );
+				inits.push_back( new SingleInit( new SizeofExpr( objectType->clone() ) ) );
 			} else if ( std::string( "align" ) == field->name ) {
-				inits.push_back( new SingleInit( new AlignofExpr( vobject_type->clone() ) ) );
+				inits.push_back( new SingleInit( new AlignofExpr( objectType->clone() ) ) );
 			} else {
 				inits.push_back( new SingleInit( new NameExpr( field->name ) ) );
@@ -108,9 +98,51 @@
 }
 
-ObjectDecl * makeVtableInstance(
-		StructDecl * polyDecl, std::list< Expression * > && parameters,
-		Type * vobject, Initializer * init ) {
-	return makeVtableInstance(
-		vtableInstType( polyDecl, std::move( parameters ) ), vobject, init );
+namespace {
+	std::string const functionName = "get_exception_vtable";
+}
+
+FunctionDecl * makeGetExceptionForward(
+		Type * vtableType, Type * exceptType ) {
+	assert( vtableType );
+	assert( exceptType );
+	FunctionType * type = new FunctionType( noQualifiers, false );
+	vtableType->tq.is_const = true;
+	type->returnVals.push_back( new ObjectDecl(
+		"_retvalue",
+		noStorageClasses,
+		LinkageSpec::Cforall,
+		nullptr,
+		new ReferenceType( noQualifiers, vtableType ),
+		nullptr,
+        { new Attribute("unused") }
+	) );
+	type->parameters.push_back( new ObjectDecl(
+		"__unused",
+		noStorageClasses,
+		LinkageSpec::Cforall,
+		nullptr,
+		new PointerType( noQualifiers, exceptType ),
+		nullptr,
+		{ new Attribute("unused") }
+	) );
+	return new FunctionDecl(
+		functionName,
+		noStorageClasses,
+		LinkageSpec::Cforall,
+		type,
+		nullptr
+	);
+}
+
+FunctionDecl * makeGetExceptionFunction(
+		ObjectDecl * vtableInstance, Type * exceptType ) {
+	assert( vtableInstance );
+	assert( exceptType );
+	FunctionDecl * func = makeGetExceptionForward(
+		vtableInstance->type->clone(), exceptType );
+	func->statements = new CompoundStmt( {
+		new ReturnStmt( new VariableExpr( vtableInstance ) ),
+	} );
+	return func;
 }
 
Index: src/Virtual/Tables.h
===================================================================
--- src/Virtual/Tables.h	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/Virtual/Tables.h	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -27,25 +27,25 @@
 bool isVTableInstanceName( std::string const & name );
 
-/// Converts exceptions into regular structures.
-//void ( std::list< Declaration * > & translationUnit );
-
-ObjectDecl * makeVtableForward( StructInstType * );
-ObjectDecl * makeVtableForward( StructDecl *, std::list< Expression * > && );
-/* Create a forward definition of a vtable of the given type.
- *
- * Instead of the virtual table type you may provide the declaration and all
- * the forall parameters.
+ObjectDecl * makeVtableForward( StructInstType * vtableType );
+/* Create a forward declaration of a vtable of the given type.
+ * vtableType node is consumed.
  */
 
-ObjectDecl * makeVtableInstance( StructInstType *, Type *, Initializer * );
-ObjectDecl * makeVtableInstance(
-	StructDecl *, std::list< Expression * > &&, Type *, Initializer * );
+ObjectDecl * makeVtableInstance( StructInstType * vtableType, Type * objectType,
+	Initializer * init = nullptr );
 /* Create an initialized definition of a vtable.
- *
- * The parameters are the virtual table type (or the base declaration and the
- * forall parameters), the object type and optionally an initializer.
- *
- * Instead of the virtual table type you may provide the declaration and all
- * the forall parameters.
+ * vtableType and init (if provided) nodes are consumed.
+ */
+
+// Some special code for how exceptions interact with virtual tables.
+FunctionDecl * makeGetExceptionForward( Type * vtableType, Type * exceptType );
+/* Create a forward declaration of the exception virtual function
+ * linking the vtableType to the exceptType. Both nodes are consumed.
+ */
+
+FunctionDecl * makeGetExceptionFunction(
+	ObjectDecl * vtableInstance, Type * exceptType );
+/* Create the definition of the exception virtual function.
+ * exceptType node is consumed.
  */
 
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/main.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -9,7 +9,7 @@
 // Author           : Peter Buhr and Rob Schluntz
 // Created On       : Fri May 15 23:12:02 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Tue May 19 12:03:00 2020
-// Update Count     : 634
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Thu Oct  8 18:17:46 2020
+// Update Count     : 637
 //
 
@@ -458,5 +458,5 @@
 
 
-static const char optstring[] = ":c:ghlLmNnpdP:S:twW:D:";
+static const char optstring[] = ":c:ghlLmNnpdOAP:S:twW:D:";
 
 enum { PreludeDir = 128 };
@@ -485,23 +485,23 @@
 
 static const char * description[] = {
-	"diagnostic color: never, always, or auto.",          // -c
-	"wait for gdb to attach",                             // -g
-	"print help message",                                 // -h
-	"generate libcfa.c",                                  // -l
-	"generate line marks",                                // -L
-	"do not replace main",                                // -m
-	"do not generate line marks",                         // -N
-	"do not read prelude",                                // -n
+	"diagnostic color: never, always, or auto.",		// -c
+	"wait for gdb to attach",							// -g
+	"print help message",								// -h
+	"generate libcfa.c",								// -l
+	"generate line marks",								// -L
+	"do not replace main",								// -m
+	"do not generate line marks",						// -N
+	"do not read prelude",								// -n
 	"generate prototypes for prelude functions",		// -p
-	"don't print output that isn't deterministic",        // -d
-	"Use the old-ast",                                    // -O
-	"Use the new-ast",                                    // -A
-	"print",                                              // -P
+	"only print deterministic output",                  // -d
+	"Use the old-ast",									// -O
+	"Use the new-ast",									// -A
+	"print",											// -P
 	"<directory> prelude directory for debug/nodebug",	// no flag
 	"<option-list> enable profiling information:\n          counters,heap,time,all,none", // -S
-	"building cfa standard lib",                          // -t
-	"",                                                   // -w
-	"",                                                   // -W
-	"",                                                   // -D
+	"building cfa standard lib",						// -t
+	"",													// -w
+	"",													// -W
+	"",													// -D
 }; // description
 
Index: tests/.expect/const-init.txt
===================================================================
--- tests/.expect/const-init.txt	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
+++ tests/.expect/const-init.txt	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -0,0 +1,2 @@
+almost done
+dtor
Index: tests/.expect/init1-ERROR.txt
===================================================================
--- tests/.expect/init1-ERROR.txt	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
+++ tests/.expect/init1-ERROR.txt	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -0,0 +1,47 @@
+error: No reasonable alternatives for expression Untyped Init Expression
+  Name: rx  InitAlternative: reference to signed int
+error: No reasonable alternatives for expression Untyped Init Expression
+  Name: px  InitAlternative: pointer to signed int
+error: No reasonable alternatives for expression Untyped Init Expression
+  Name: crx  InitAlternative: reference to float
+error: No reasonable alternatives for expression Untyped Init Expression
+  Name: cpx  InitAlternative: pointer to float
+init1.cfa:104:1 error: No reasonable alternatives for expression Generated Cast of:
+  Name: rx
+... to:
+  reference to signed int
+init1.cfa:107:1 error: No reasonable alternatives for expression Applying untyped:
+  Name: ?{}
+...to:
+  Generated Cast of:
+    Variable Expression: _retval_f_py: pointer to signed int
+  ... to:
+    reference to pointer to signed int
+  Name: px
+
+init1.cfa:114:1 error: No reasonable alternatives for expression Generated Cast of:
+  Name: crx
+... to:
+  reference to float
+init1.cfa:117:1 error: No reasonable alternatives for expression Applying untyped:
+  Name: ?{}
+...to:
+  Generated Cast of:
+    Variable Expression: _retval_f_py2: pointer to float
+  ... to:
+    reference to pointer to float
+  Name: cpx
+
+init1.cfa:124:1 error: No reasonable alternatives for expression Generated Cast of:
+  Name: s
+... to:
+  reference to instance of type T (not function type)
+init1.cfa:128:1 error: No reasonable alternatives for expression Applying untyped:
+  Name: ?{}
+...to:
+  Generated Cast of:
+    Variable Expression: _retval_anycvt: pointer to instance of type T (not function type)
+  ... to:
+    reference to pointer to instance of type T (not function type)
+  Name: s
+
Index: tests/.expect/init1.txt
===================================================================
--- tests/.expect/init1.txt	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/.expect/init1.txt	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -1,47 +1,2 @@
-error: No reasonable alternatives for expression Untyped Init Expression
-  Name: rx  InitAlternative: reference to signed int
-error: No reasonable alternatives for expression Untyped Init Expression
-  Name: px  InitAlternative: pointer to signed int
-error: No reasonable alternatives for expression Untyped Init Expression
-  Name: crx  InitAlternative: reference to float
-error: No reasonable alternatives for expression Untyped Init Expression
-  Name: cpx  InitAlternative: pointer to float
-init1.cfa:94:1 error: No reasonable alternatives for expression Generated Cast of:
-  Name: rx
-... to:
-  reference to signed int
-init1.cfa:97:1 error: No reasonable alternatives for expression Applying untyped:
-  Name: ?{}
-...to:
-  Generated Cast of:
-    Variable Expression: _retval_f_py: pointer to signed int
-  ... to:
-    reference to pointer to signed int
-  Name: px
-
-init1.cfa:104:1 error: No reasonable alternatives for expression Generated Cast of:
-  Name: crx
-... to:
-  reference to float
-init1.cfa:107:1 error: No reasonable alternatives for expression Applying untyped:
-  Name: ?{}
-...to:
-  Generated Cast of:
-    Variable Expression: _retval_f_py2: pointer to float
-  ... to:
-    reference to pointer to float
-  Name: cpx
-
-init1.cfa:114:1 error: No reasonable alternatives for expression Generated Cast of:
-  Name: s
-... to:
-  reference to instance of type T (not function type)
-init1.cfa:118:1 error: No reasonable alternatives for expression Applying untyped:
-  Name: ?{}
-...to:
-  Generated Cast of:
-    Variable Expression: _retval_anycvt: pointer to instance of type T (not function type)
-  ... to:
-    reference to pointer to instance of type T (not function type)
-  Name: s
-
+init1.cfa: In function '_X4mainFi___1':
+init1.cfa:136:9: note: #pragma message: Compiled
Index: tests/.expect/limits.txt
===================================================================
--- tests/.expect/limits.txt	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/.expect/limits.txt	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -1,2 +1,2 @@
 limits.cfa: In function '_X4mainFi_iPPKc__1':
-limits.cfa:151:9: note: #pragma message: Compiled
+limits.cfa:154:9: note: #pragma message: Compiled
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/Makefile.am	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -11,6 +11,6 @@
 ## Created On       : Sun May 31 09:08:15 2015
 ## Last Modified By : Peter A. Buhr
-## Last Modified On : Sun Sep 27 19:01:41 2020
-## Update Count     : 84
+## Last Modified On : Fri Oct  9 23:13:07 2020
+## Update Count     : 86
 ###############################################################################
 
@@ -141,5 +141,5 @@
 
 SYNTAX_ONLY_CODE = expression typedefRedef variableDeclarator switch numericConstants identFuncDeclarator forall \
-	limits nested-types stdincludes cast labelledExit array builtins/sync warnings/self-assignment
+	init1 limits nested-types stdincludes cast labelledExit array builtins/sync warnings/self-assignment
 $(SYNTAX_ONLY_CODE): % : %.cfa $(CFACCBIN)
 	$(CFACOMPILE_SYNTAX)
@@ -149,4 +149,8 @@
 # use custom target since they require a custom define *and* have a name that doesn't match the file
 alloc-ERROR : alloc.cfa $(CFACCBIN)
+	$(CFACOMPILE_SYNTAX) -DERR1
+	-cp $(test) $(abspath ${@})
+
+init1-ERROR : init1.cfa $(CFACCBIN)
 	$(CFACOMPILE_SYNTAX) -DERR1
 	-cp $(test) $(abspath ${@})
Index: tests/alloc.cfa
===================================================================
--- tests/alloc.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/alloc.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -10,6 +10,6 @@
 // Created On       : Wed Feb  3 07:56:22 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Aug 14 16:59:59 2020
-// Update Count     : 430
+// Last Modified On : Fri Oct  9 23:03:11 2020
+// Update Count     : 431
 //
 
@@ -362,5 +362,5 @@
 	ip = memset( stp, 10 );
 	ip = memcpy( &st1, &st );
-#endif
+#endif // ERR1
 } // main
 
Index: tests/complex.cfa
===================================================================
--- tests/complex.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/complex.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -14,5 +14,4 @@
 //
 
-#include <stdio.h>
 #include <complex.h>
 #ifdef __CFA__
Index: tests/const-init.cfa
===================================================================
--- tests/const-init.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
+++ tests/const-init.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -0,0 +1,60 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2020 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// const-init.cfa -- tests of initializing constants
+//
+// Author           : Michael Brooks
+// Created On       : Tue Oct 06 22:00:00 2020
+// Last Modified By : Michael Brooks
+// Last Modified On : Tue Oct 06 22:00:00 2020
+// Update Count     : 1
+//
+
+/*
+
+These tests show non-crashing of generated code for constants with interesting initializers.
+The potential for these to crash is compiler dependent.
+
+There are two cases:
+1. static constants in one compilation unit (tested here, in a few sub-cases)
+2. extern constants across compilation units (tested by libcfa being loadable, specifically
+   the constant definitions in libcfa/src/limits.cfa, which almost every test exercises,
+   including "hello;" but notably, the "limits" test does not exercise it because that test
+   is compile-only)
+
+Crashes that we have obsrved (#182 and build failures September 2020) are because the libcfa
+initialization is writing to a global variable (which the declaring program wants typed as 
+constant), while the compiler has placed this global in a read-only section.
+
+Compiler dependence includes:
+
+                          Case 1           Case 2
+GCC-6  on Ubuntu 16.04    Never crashed    Never crashed
+GCC-8  on both            Has crashed      Never crashed
+GCC-10 on Ubuntu 20.04    Has crashed      Has crashed
+
+For this test to fail, with most other tests passing, would be a situation only ever
+observed with GCC-8.
+
+*/
+
+// initailized by generated function, called before main
+static const char foo = -1;
+
+struct thing{};
+void ^?{}( thing & ) { printf("dtor\n"); }
+
+int main() {
+    // foo is already initialized
+
+    // no dtor => stays a (static) local, initialized here
+    static const char bar = -1;
+
+    // has dtor => becomes a global, ctor called here, dtor called at exit
+    static const thing it;
+
+    printf("almost done\n");
+}
Index: tests/errors/.expect/completeType.x64.txt
===================================================================
--- tests/errors/.expect/completeType.x64.txt	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/errors/.expect/completeType.x64.txt	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -132,8 +132,8 @@
 ?=?: pointer to function
         ... with parameters
-          reference to instance of type _109_0_T (not function type)
-          instance of type _109_0_T (not function type)
+          reference to instance of type _110_0_T (not function type)
+          instance of type _110_0_T (not function type)
         ... returning
-          _retval__operator_assign: instance of type _109_0_T (not function type)
+          _retval__operator_assign: instance of type _110_0_T (not function type)
           ... with attributes:
             Attribute with name: unused
Index: tests/errors/.expect/completeType.x86.txt
===================================================================
--- tests/errors/.expect/completeType.x86.txt	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/errors/.expect/completeType.x86.txt	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -132,8 +132,8 @@
 ?=?: pointer to function
         ... with parameters
-          reference to instance of type _108_0_T (not function type)
-          instance of type _108_0_T (not function type)
+          reference to instance of type _109_0_T (not function type)
+          instance of type _109_0_T (not function type)
         ... returning
-          _retval__operator_assign: instance of type _108_0_T (not function type)
+          _retval__operator_assign: instance of type _109_0_T (not function type)
           ... with attributes:
             Attribute with name: unused
Index: tests/exceptions/cancel/coroutine.cfa
===================================================================
--- tests/exceptions/cancel/coroutine.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/exceptions/cancel/coroutine.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -1,5 +1,4 @@
 // Try cancelling a coroutine.
 
-#include <stdio.h>
 #include <coroutine.hfa>
 #include <exception.hfa>
Index: tests/exceptions/conditional.cfa
===================================================================
--- tests/exceptions/conditional.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/exceptions/conditional.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -5,5 +5,4 @@
 
 #include <exception.hfa>
-#include <stdio.h>
 
 VTABLE_DECLARATION(num_error)(
Index: tests/exceptions/defaults.cfa
===================================================================
--- tests/exceptions/defaults.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/exceptions/defaults.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -55,5 +55,5 @@
 
 void unhandled_test(void) {
-	forall(dtype T | is_exception(T))
+	forall(dtype T, dtype V | is_exception(T, V))
 	void defaultTerminationHandler(T &) {
 		throw (unhandled_exception){};
Index: tests/exceptions/except-io.hfa
===================================================================
--- tests/exceptions/except-io.hfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/exceptions/except-io.hfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -1,5 +1,3 @@
 // Common tools for the exception tests.
-
-#include <stdio.h>
 
 // Echo when a destructor is run and an area/block is left.
Index: tests/exceptions/trash.cfa
===================================================================
--- tests/exceptions/trash.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/exceptions/trash.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -2,5 +2,4 @@
 
 #include <exception.hfa>
-#include <stdio.h>
 
 TRIVIAL_EXCEPTION(yin);
Index: tests/global-monomorph.cfa
===================================================================
--- tests/global-monomorph.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/global-monomorph.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -1,6 +1,3 @@
-// Crea
-
-#include <stdlib.hfa>
-#include <stdio.h>
+// Create monomorphic instances of polymorphic types at global scope.
 
 forall(dtype T)
Index: tests/init1.cfa
===================================================================
--- tests/init1.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/init1.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -9,7 +9,7 @@
 // Author           : Michael Brooks
 // Created On       : Thu Jul 16 22:00:00 2020
-// Last Modified By : Michael Brooks
-// Last Modified On : Thu Jul 16 22:00:00 2020
-// Update Count     : 1
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sun Oct 11 10:26:50 2020
+// Update Count     : 8
 //
 
@@ -41,8 +41,16 @@
     const float * cpx2 = cpx;
 
+    // FIX ME: Code gen not producing correct cast.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
+    int (* fp)( int ) = 0p;
+    fp = 0p;
+#pragma GCC diagnostic pop
+
     //
     // unsound initializations
     //
 
+    #ifdef ERR1
     // mismatched referenced type
     int & ry = rx;
@@ -52,4 +60,5 @@
     float & ry2 = crx;
     float * py2 = cpx;
+    #endif // ERR1
 }
 
@@ -90,4 +99,5 @@
 //
 
+#ifdef ERR1
 int & f_ry() { 
     float & rx = *0p;
@@ -119,2 +129,7 @@
     return s;               // mismatched referenced type
 }
+#endif // ERR1
+
+int main() {
+    #pragma message( "Compiled" )			// force non-empty .expect file
+}
Index: tests/limits.cfa
===================================================================
--- tests/limits.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/limits.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -13,4 +13,7 @@
 // Update Count     : 10
 //
+
+// Note: For testing the ability to load the constants defined in libcfa/src/limits.cfa,
+// see discussion in test const-init.
 
 #include <limits.hfa>
Index: tests/poly-d-cycle.cfa
===================================================================
--- tests/poly-d-cycle.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/poly-d-cycle.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -1,5 +1,3 @@
 // Check that a cycle of polymorphic dtype structures can be instancated.
-
-#include <stdio.h>
 
 forall(dtype T)
Index: tests/poly-o-cycle.cfa
===================================================================
--- tests/poly-o-cycle.cfa	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ tests/poly-o-cycle.cfa	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -1,5 +1,3 @@
 // Check that a cycle of polymorphic otype structures can be instancated.
-
-#include <stdio.h>
 
 forall(otype T)
