Index: src/tests/except-0.c
===================================================================
--- src/tests/except-0.c	(revision fcc88a4758ef6ae240a457212a6e494379cf4268)
+++ src/tests/except-0.c	(revision e9145a3d441a8ec02e96bb8f4c48446e11570f7b)
@@ -7,4 +7,10 @@
 #include <stdio.h>
 #include <stdbool.h>
+
+#include "except-mac.h"
+TRIVIAL_EXCEPTION(yin)
+TRIVIAL_EXCEPTION(yang)
+TRIVIAL_EXCEPTION(zen)
+
 
 // Local type to mark exits from scopes. (see ERROR)
@@ -23,34 +29,16 @@
 
 
-// Local Exception Types and manual vtable types.
-//#define TRIVIAL_EXCEPTION(name) //TRIVAL_EXCEPTION(yin)
-struct yin;
-struct yin_vtable {
-	struct exception_t_vtable const * parent;
-	size_t size;
-    void (*copy)(yin *this, yin * other);
-    void (*free)(yin *this);
-    const char (*msg)(yin *this);
-};
-struct yin {
-	struct yin_vtable const * parent;
-};
-void yin_msg(yin) {
-	return "in";
-}
-yin_vtable _yin_vtable_instance = {
-	&_exception_t_vtable_instance, sizeof(yin), ?{}, ^?{}, yin_msg
-}
-
-
-void terminate(exception * except_value) {
+// Mark throws: make sure to only pass in exception types.
+forall(dtype T)
+void terminate(T * except_value) {
 	signal_exit a = {"terminate function"};
-	throw except_value;
+	THROW(except_value);
 	printf("terminate returned\n");
 }
 
-void resume(exception * except_value) {
+forall(dtype T)
+void resume(T * except_value) {
 	signal_exit a = {"resume function"};
-	throwResume except_value;
+	THROW_RESUME(except_value);
 	printf("resume returned\n");
 }
@@ -60,7 +48,7 @@
 	signal_exit a = {"bar function"};
 	try {
-		terminate(4);
-	} catch (3) {
-		printf("bar caught exception 3.\n");
+		terminate(&(zen){});
+	} catch (yin * error) {
+		printf("bar caught exception yin.\n");
 	}
 }
@@ -70,8 +58,8 @@
 	try {
 		bar();
-	} catch (4) {
-		printf("foo caught exception 4.\n");
-	} catch (2) {
-		printf("foo caught exception 2.\n");
+	} catch (yang * error) {
+		printf("foo caught exception yang.\n");
+	} catch (zen * error) {
+		printf("foo caught exception zen.\n");
 	}
 }
@@ -81,7 +69,8 @@
 	signal_exit a = {"beta function"};
 	try {
-		resume(4);
-	} catchResume (3) {
-		printf("beta caught exception 3\n");
+		zen x;
+		resume(&x);
+	} catchResume (yin * error) {
+		printf("beta caught exception yin\n");
 	}
 }
@@ -91,8 +80,8 @@
 	try {
 		beta();
-	} catchResume (2) {
-		printf("alpha caught exception 2\n");
-	} catchResume (4) {
-		printf("alpha caught exception 4\n");
+	} catchResume (yang * error) {
+		printf("alpha caught exception yang\n");
+	} catchResume (zen * error) {
+		printf("alpha caught exception zen\n");
 	}
 }
@@ -117,7 +106,8 @@
 void fallback() {
 	try {
-		resume(2);
-	} catch (2) {
-		printf("fallback caught termination 2\n");
+		zen x;
+		resume(&x);
+	} catch (zen * error) {
+		printf("fallback caught termination zen\n");
 	}
 }
@@ -127,7 +117,9 @@
 	signal_exit a = {"terminate_swap"};
 	try {
-		terminate(2);
-	} catch (2) {
-		terminate(3);
+		yin x;
+		terminate(&x);
+	} catch (yin * error) {
+		yang y;
+		terminate(&y);
 	}
 }
@@ -137,6 +129,6 @@
 	try {
 		terminate_swap();
-	} catch (3) {
-		printf("terminate_swapped caught exception 3\n");
+	} catch (yang * error) {
+		printf("terminate_swapped caught exception yang\n");
 	}
 }
@@ -146,7 +138,9 @@
 	signal_exit a = {"resume_swap"};
 	try {
-		resume(2);
-	} catchResume (2) {
-		resume(3);
+		yin x;
+		resume(&x);
+	} catchResume (yin * error) {
+		yang y;
+		resume(&y);
 	}
 }
@@ -155,6 +149,6 @@
 	try {
 		resume_swap();
-	} catchResume (3) {
-		printf("resume_swapped caught exception 3\n");
+	} catchResume (yang * error) {
+		printf("resume_swapped caught exception yang\n");
 	}
 }
@@ -164,12 +158,13 @@
 	try {
 		try {
-			terminate(2);
-		} catch (2) {
-			printf("reterminate 2 caught and "
-			       "will rethrow exception 2\n");
+			zen x;
+			terminate(&x);
+		} catch (zen * error) {
+			printf("reterminate zen caught and "
+			       "will rethrow exception zen\n");
 			throw;
 		}
-	} catch (2) {
-		printf("reterminate 1 caught exception 2\n");
+	} catch (zen * error) {
+		printf("reterminate 1 caught exception zen\n");
 	}
 }
@@ -179,11 +174,12 @@
 	try {
 		try {
-			resume(2);
-		} catchResume (2) {
-			printf("reresume 2 caught and rethrows exception 2\n");
+			zen x;
+			resume(&x);
+		} catchResume (zen * error) {
+			printf("reresume zen caught and rethrows exception zen\n");
 			throwResume;
 		}
-	} catchResume (2) {
-		printf("reresume 1 caught exception 2\n");
+	} catchResume (zen * error) {
+		printf("reresume 1 caught exception zen\n");
 	}
 }
@@ -193,7 +189,8 @@
 	// terminate block, call resume
 	try {
-		resume(3);
-	} catch (3) {
-		printf("fum caught exception 3\n");
+		zen x;
+		resume(&x);
+	} catch (zen * error) {
+		printf("fum caught exception zen\n");
 	}
 }
@@ -202,7 +199,8 @@
 	// resume block, call terminate
 	try {
-		terminate(3);
-	} catchResume (3) {
-		printf("foe caught exception 3\n");
+		zen y;
+		terminate(&y);
+	} catchResume (zen * error) {
+		printf("foe caught exception zen\n");
 	}
 }
@@ -212,6 +210,6 @@
 	try {
 		foe();
-	} catch (3) {
-		printf("fy caught exception 3\n");
+	} catch (zen * error) {
+		printf("fy caught exception zen\n");
 		fum();
 	}
@@ -222,6 +220,6 @@
 	try {
 		fy();
-	} catchResume (3) {
-		printf("fee caught exception 3\n");
+	} catchResume (zen * error) {
+		printf("fee caught exception zen\n");
 	}
 }
@@ -242,5 +240,8 @@
 	reresume(); printf("\n");
 	fee(); printf("\n");
+
 	// Uncaught termination test.
-	terminate(7);
-}
+	printf("Throw uncaught.\n");
+	yang z;
+	terminate(&z);
+}
Index: src/tests/except-1.c
===================================================================
--- src/tests/except-1.c	(revision fcc88a4758ef6ae240a457212a6e494379cf4268)
+++ src/tests/except-1.c	(revision e9145a3d441a8ec02e96bb8f4c48446e11570f7b)
@@ -5,15 +5,21 @@
 #include <stdio.h>
 
+#include "except-mac.h"
+TRIVIAL_EXCEPTION(yin)
+TRIVIAL_EXCEPTION(yang)
+
 int main()
 {
 	try {
-		throw 3;
+		yin a;
+		THROW(&a);
 	}
-	catch( 3 ) {
+	catch( yin * err ) {
 		printf("First Caught\n");
 		try {
-			throw 4;
+			yang b;
+			THROW(&b);
 		}
-		catch( 4 ) {
+		catch( yang * err ) {
 			printf("Both Caught\n");
 		}
@@ -23,12 +29,13 @@
 	try {
 		try {
-			throw 2;
+			yang c;
+			THROW(&c);
 		}
-		catch( 2 ) {
+		catch( yang * err ) {
 			printf("First Catch and rethrow\n");
 			throw;
 		}
 	}
-	catch( 2 ) {
+	catch( yang * err ) {
 		printf("Second Catch\n");
 	}
@@ -37,12 +44,14 @@
 	try {
 		try {
-			throw 5;
+			yin d;
+			THROW(&d);
 		}
-		catch( 5 ) {
+		catch( yin * err ) {
 			printf("Throw before cleanup\n");
-			throw 6;
+			yang e;
+			THROW(&e);
 		}
 	}
-	catch( 6 ) {
+	catch( yang * err ) {
 		printf("Catch after cleanup\n");
 	}
@@ -51,12 +60,14 @@
 	try {
 		try {
-			throw 7;
+			yin f;
+			THROW(&f);
 		}
-		catch( 7 ) {
+		catch( yin * err ) {
 			printf("Caught initial throw.\n");
 			try {
-				throw 8;
+				yang g;
+				THROW(&g);
 			}
-			catch( 8 ) {
+			catch( yang * err ) {
 				printf("Caught intermediate throw.\n");
 			}
@@ -64,5 +75,5 @@
 		}
 	}
-	catch( 7 ) {
+	catch( yin * err ) {
 		printf("Caught final throw.\n");
 	}
Index: src/tests/except-2.c
===================================================================
--- src/tests/except-2.c	(revision fcc88a4758ef6ae240a457212a6e494379cf4268)
+++ src/tests/except-2.c	(revision e9145a3d441a8ec02e96bb8f4c48446e11570f7b)
@@ -2,39 +2,7 @@
 
 
-#include <string.h>
+#include <stdlib>
+#include "except-mac.h"
 
-// Local Exception Types and manual vtable types.
-#define GLUE2(left, right) left##right
-#define GLUE3(left, middle, right) left##middle##right
-#define BASE_EXCEPT __cfaehm__base_exception_t
-#define TABLE(name) GLUE2(name,_vtable)
-#define INSTANCE(name) GLUE3(_,name,_vtable_instance)
-#define TRIVIAL_EXCEPTION(name) \
-struct name; \
-struct TABLE(name) { \
-	struct TABLE(BASE_EXCEPT) const * parent; \
-	size_t size; \
-	void (*copy)(name *this, name * other); \
-	void (*free)(name *this); \
-	const char * (*msg)(name *this); \
-}; \
-extern TABLE(name) INSTANCE(name); \
-struct name { \
-	struct TABLE(name) const * virtual_table; \
-}; \
-const char * name##_msg(name * this) { \
-	return #name; \
-} \
-void name##_copy(name * this, name * other) { \
-	this->virtual_table = other->virtual_table; \
-} \
-TABLE(name) INSTANCE(name) @= { \
-	.parent : &INSTANCE(BASE_EXCEPT), \
-	.size : sizeof(name), .copy : name##_copy, \
-	.free : ^?{}, .msg : name##_msg \
-}; \
-void ?{}(name * this) { \
-	this->virtual_table = &INSTANCE(name); \
-}
 TRIVIAL_EXCEPTION(yin)
 TRIVIAL_EXCEPTION(yang)
@@ -50,4 +18,5 @@
 };
 extern num_error_vtable INSTANCE(num_error);
+
 struct num_error {
 	struct num_error_vtable const * virtual_table;
@@ -55,8 +24,10 @@
 	int num;
 };
+
 void num_error_msg(num_error * this) {
 	if ( ! this->msg ) {
-		const char * base = "Num Error with code: X";
-		this->msg = strdup( base );
+		static const char * base = "Num Error with code: X";
+		this->msg = malloc(22);
+		for (int i = 0 ; (this->msg[i] = base[i]) ; ++i);
 	}
 	this->msg[21] = '0' + this->num;
@@ -90,5 +61,5 @@
 	try {
 		yin black;
-		throw (BASE_EXCEPT *)&black;
+		THROW(&black);
 	} catch ( yin * error ) {
 		printf("throw yin caught.\n");
@@ -97,5 +68,5 @@
 	try {
 		yang white;
-		throwResume (BASE_EXCEPT *)&white;
+		THROW_RESUME(&white);
 		printf("> throwResume returned.\n");
 	} catchResume ( yang * error ) {
@@ -105,5 +76,5 @@
 	try {
 		num_error x = { 2 };
-		throw (BASE_EXCEPT *)&x;
+		THROW(&x);
 	}
 	catch (num_error * error ; 3 == error->virtual_table->code( error ) ) {
Index: src/tests/except-3.c
===================================================================
--- src/tests/except-3.c	(revision e9145a3d441a8ec02e96bb8f4c48446e11570f7b)
+++ src/tests/except-3.c	(revision e9145a3d441a8ec02e96bb8f4c48446e11570f7b)
@@ -0,0 +1,18 @@
+// Test that __attribute__((cleanup(...))) is working.
+
+#include <stdio.h>
+#include "except-mac.h"
+TRIVIAL_EXCEPTION(myth)
+
+int main (int argc, char * argv[]) {
+	try {
+		try {
+			printf("throw [");
+			THROW(&(myth){});
+		} finally {
+			printf("] unwind <");
+		}
+	} catch (myth * error) {
+		printf("> catch\n");
+	}
+}
Index: src/tests/except-mac.h
===================================================================
--- src/tests/except-mac.h	(revision e9145a3d441a8ec02e96bb8f4c48446e11570f7b)
+++ src/tests/except-mac.h	(revision e9145a3d441a8ec02e96bb8f4c48446e11570f7b)
@@ -0,0 +1,78 @@
+// Macros to try and make declaring and using exceptions easier
+// No, these are not part of the language, they replace the virtual system.
+
+// Internal use:
+#define GLUE2(left, right) left##right
+#define GLUE3(left, middle, right) left##middle##right
+
+// The fully (perhaps overly) qualified name of the base exception type:
+#define BASE_EXCEPT __cfaehm__base_exception_t
+
+// Get the name of the vtable type and vtable instance for an exception type:
+#define TABLE(name) GLUE2(name,_vtable)
+#define INSTANCE(name) GLUE3(_,name,_vtable_instance)
+
+// Throws and the bit of overhead:
+#define THROW(expr) throw ((BASE_EXCEPT *)(expr))
+#define THROW_RESUME(expr) throwResume ((BASE_EXCEPT *)(expr))
+
+
+
+// The following macros are for defining your own new exception types.
+
+// Declare vtable and forward declare the exception type and vtable instance.
+// This should start a new exception declaration.
+// ... argument is the additional vtable fields.
+#define DECLARE_EXCEPT(except_name,parent_name,...) \
+struct except_name; \
+struct TABLE(except_name) { \
+	struct TABLE(parent_name) const * parent; \
+	size_t size; \
+	void (*copy)(except_name *this, except_name * other); \
+	void (*free)(except_name *this); \
+	const char * (*msg)(except_name *this); \
+	__VA_ARGS__ \
+}; \
+extern TABLE(except_name) INSTANCE(except_name);
+
+// The first field of the exception structure should be created with this.
+#define VTABLE_FIELD(except_name) \
+struct TABLE(except_name) const * virtual_table
+
+// In each constructor the vtable must be initialized.
+#define VTABLE_INIT(this_name,except_name) \
+this_name->virtual_table = &INSTANCE(except_name)
+
+// Declare the vtable instance. This should end an exception declaration.
+// ... argument is the remaining vtable field values.
+#define VTABLE_INSTANCE(except_name,parent_name,copy,free,msg,...) \
+TABLE(except_name) INSTANCE(except_name) @= { \
+	&INSTANCE(parent_name), sizeof(except_name), \
+	copy, free, msg, ## __VA_ARGS__ \
+};
+
+// Same, but used declarators for arguments.
+#define VTABLE_INSTANCE_KEY(except_name,parent_name,copy,free,msg,...) \
+TABLE(except_name) INSTANCE(except_name) @= { \
+	.parent : &INSTANCE(parent_name), .size : sizeof(except_name), \
+	.copy : copy, .free : free, .msg : msg, ## __VA_ARGS__ \
+};
+
+
+
+// Declare a trivial exception, one that adds no features:
+#define TRIVIAL_EXCEPTION(name) \
+DECLARE_EXCEPT(name,BASE_EXCEPT,) \
+struct name { \
+	VTABLE_FIELD(name); \
+}; \
+const char * GLUE2(name,_msg)(name * this) { \
+    return #name; \
+} \
+void GLUE2(name,_copy)(name * this, name * other) { \
+    this->virtual_table = other->virtual_table; \
+} \
+void ?{}(name * this) { \
+	VTABLE_INIT(this,name); \
+} \
+VTABLE_INSTANCE(name,BASE_EXCEPT,GLUE2(name,_copy),^?{},GLUE2(name,_msg),)
