Index: src/ControlStruct/ExceptTranslate.cc
===================================================================
--- src/ControlStruct/ExceptTranslate.cc	(revision 6b0b624129f6017f7706b516a24a52e382e3a334)
+++ src/ControlStruct/ExceptTranslate.cc	(revision 86d5ba7c5d88e75a531a8a77aa1b549a29ed1f55)
@@ -10,6 +10,6 @@
 // Created On       : Wed Jun 14 16:49:00 2017
 // Last Modified By : Andrew Beach
-// Last Modified On : Tus Jul 18 10:09:00 2017
-// Update Count     : 4
+// Last Modified On : Fri Jul 28 14:03:00 2017
+// Update Count     : 5
 //
 
@@ -21,22 +21,18 @@
 #include "SynTree/Type.h"
 #include "SynTree/Attribute.h"
+#include "SynTree/VarExprReplacer.h"
 
 namespace ControlStruct {
 
-	// This (large) section could probably be moved out of the class
-	// and be static helpers instead.
-
-	// Type(Qualifiers &, false, std::list<Attribute *> &)
-
 	// void (*function)();
-	static FunctionType try_func_t(Type::Qualifiers(), false);
+	static FunctionType try_func_t(noQualifiers, false);
 	// void (*function)(int, exception);
-	static FunctionType catch_func_t(Type::Qualifiers(), false);
+	static FunctionType catch_func_t(noQualifiers, false);
 	// int (*function)(exception);
-	static FunctionType match_func_t(Type::Qualifiers(), false);
+	static FunctionType match_func_t(noQualifiers, false);
 	// bool (*function)(exception);
-	static FunctionType handle_func_t(Type::Qualifiers(), false);
+	static FunctionType handle_func_t(noQualifiers, false);
 	// void (*function)(__attribute__((unused)) void *);
-	static FunctionType finally_func_t(Type::Qualifiers(), false);
+	static FunctionType finally_func_t(noQualifiers, false);
 
 	static void init_func_types() {
@@ -115,13 +111,4 @@
 	}
 
-	template<typename T>
-	void free_all( std::list<T *> &list ) {
-		typename std::list<T *>::iterator it;
-		for ( it = list.begin() ; it != list.end() ; ++it ) {
-			delete *it;
-		}
-		list.clear();
-	}
-
 	void appendDeclStmt( CompoundStmt * block, Declaration * item ) {
 		block->push_back(new DeclStmt(noLabels, item));
@@ -136,4 +123,6 @@
 	Statement * create_given_throw(
 			const char * throwFunc, ThrowStmt * throwStmt ) {
+		// There is an extra copy here we might be able to remove with
+		// references.
 		// { int NAME = EXPR; throwFunc( &NAME ); }
 		CompoundStmt * result = new CompoundStmt( noLabels );
@@ -159,18 +148,34 @@
 		return create_given_throw( "__cfaehm__throw_terminate", throwStmt );
 	}
-	Statement * create_terminate_rethrow( ThrowStmt *throwStmt ) {
-		// __rethrow_terminate();
+
+	Statement * create_terminate_rethrow( ThrowStmt *throwStmt,
+			ObjectDecl *handler_except_decl ) {
+		// { `handler_except_decl` = NULL; __rethrow_terminate(); }
 		assert( nullptr == throwStmt->get_expr() );
-		Statement * result = new ExprStmt(
-			throwStmt->get_labels(),
+		assert( handler_except_decl );
+
+		CompoundStmt * result = new CompoundStmt( throwStmt->get_labels() );
+		result->push_back( new ExprStmt( noLabels, UntypedExpr::createAssign(
+			nameOf( handler_except_decl ),
+			new ConstantExpr( Constant::null(
+				new PointerType(
+					noQualifiers,
+					handler_except_decl->get_type()->clone()
+					)
+				) )
+			) ) );
+		result->push_back( new ExprStmt(
+			noLabels,
 			new UntypedExpr( new NameExpr( "__cfaehm__rethrow_terminate" ) )
-			);
+			) );
 		delete throwStmt;
 		return result;
 	}
+
 	Statement * create_resume_throw( ThrowStmt *throwStmt ) {
 		// __throw_resume( EXPR );
 		return create_given_throw( "__cfaehm__throw_resume", throwStmt );
 	}
+
 	Statement * create_resume_rethrow( ThrowStmt *throwStmt ) {
 		// return false;
@@ -201,5 +206,5 @@
 		FunctionType *func_type = catch_func_t.clone();
 		DeclarationWithType * index_obj = func_type->get_parameters().front();
-	//	DeclarationWithType * except_obj = func_type->get_parameters().back();
+		DeclarationWithType * except_obj = func_type->get_parameters().back();
 
 		// Index 1..{number of handlers}
@@ -213,12 +218,57 @@
 			// case `index`:
 			// {
+			//     `handler.decl` {inserted} = { except_obj };
 			//     `handler.body`
 			// }
 			// return;
-			std::list<Statement *> caseBody;
-			caseBody.push_back( handler->get_body() );
+			CompoundStmt * block = new CompoundStmt( noLabels );
+
+			// Just copy the exception value.
+			// TODO: Or just store an ObjectDecl?
+			ObjectDecl * handler_decl =
+				dynamic_cast<ObjectDecl*>( handler->get_decl() );
+			assert( handler_decl );
+			ObjectDecl * local_except = handler_decl->clone();
+			local_except->set_init(
+				new ListInit({ new SingleInit( nameOf( except_obj ) ) }) );
+#if 0
+			// Virtual Exception Vision
+			// case `index`:
+			// {
+			//     `handler.decl` = { (virtual `decl.type`)`except` };
+			//     `handler.body`;
+			// }
+			// return;
+
+			// Save a cast copy of the exception (should always succeed).
+			ObjectDecl * local_except = handler->get_decl()->clone();
+			local_except.set_init(
+				new ListInit({ new SingleInit(
+					new VirtualCastExpr( nameOf( except_obj ),
+						local_except->get_type()
+						)
+					) }) );
+#endif
+			block->push_back( new DeclStmt( noLabels, local_except ) );
+
+			// Add the cleanup attribute.
+			local_except->get_attributes().push_back( new Attribute(
+				"cleanup",
+				{ new NameExpr( "__cfaehm__cleanup_terminate" ) }
+				) );
+
+			// Update variables in the body to point to this local copy.
+			{
+				VarExprReplacer::DeclMap mapping;
+				mapping[ handler_decl ] = local_except;
+				VarExprReplacer mapper( mapping );
+				handler->get_body()->accept( mapper );
+			}
+
+			block->push_back( handler->get_body() );
 			handler->set_body( nullptr );
-			caseBody.push_back( new ReturnStmt( noLabels, nullptr ) );
-
+
+			std::list<Statement *> caseBody
+					{ block, new ReturnStmt( noLabels, nullptr ) };
 			handler_wrappers.push_back( new CaseStmt(
 				noLabels,
@@ -253,6 +303,31 @@
 		CompoundStmt * block = new CompoundStmt( noLabels );
 
+		ObjectDecl * local_except =
+			dynamic_cast<ObjectDecl *>( modded_handler->get_decl() );
+		assert( local_except );
+		block->push_back( new DeclStmt( noLabels, local_except ) );
+#if 0
+		// Virtual Exception Version
+		// {
+		//     `modded_handler.decl`
+		//     if ( `decl.name = (virtual)`except`
+		//             [&& `modded_handler.cond`] ) {
+		//         `modded_handler.body`
+		//     }
+		// }
+
+		// Check for type match.
+		Expression * cond = UntypedExpr::createAssign( nameOf( local_except ),
+			new VirtualCastExpr( nameOf( except_obj ),
+				local_except->get_type()->clone() ) );
+#endif
+
 		// INTEGERconstant Version
-		assert( nullptr == modded_handler->get_decl() );
+		// {
+		//     `modded_handler.decl` = *`except`
+		//     if ( `decl.name` == `modded_handler.cond` ) {
+		//         `modded_handler.body`
+		//     }
+		// }
 		ConstantExpr * number =
 			dynamic_cast<ConstantExpr*>( modded_handler->get_cond() );
@@ -274,7 +349,9 @@
 		}
 
+		// Add the check on the conditional if it is provided.
 		if ( modded_handler->get_cond() ) {
 			cond = new LogicalExpr( cond, modded_handler->get_cond() );
 		}
+		// Construct the match condition.
 		block->push_back( new IfStmt( noLabels,
 			cond, modded_handler->get_body(), nullptr ) );
@@ -288,4 +365,8 @@
 
 	FunctionDecl * create_terminate_match( CatchList &handlers ) {
+		// int match(exception * except) {
+		//     HANDLER WRAPPERS { return `index`; }
+		// }
+
 		CompoundStmt * body = new CompoundStmt( noLabels );
 
@@ -323,4 +404,5 @@
 			FunctionDecl * terminate_catch,
 			FunctionDecl * terminate_match) {
+		// { __cfaehm__try_terminate(`try`, `catch`, `match`); }
 
 		UntypedExpr * caller = new UntypedExpr( new NameExpr(
@@ -337,4 +419,7 @@
 
 	FunctionDecl * create_resume_handler( CatchList &handlers ) {
+		// bool handle(exception * except) {
+		//     HANDLER WRAPPERS { `hander->body`; return true; }
+		// }
 		CompoundStmt * body = new CompoundStmt( noLabels );
 
@@ -415,4 +500,5 @@
 
 	FunctionDecl * create_finally_wrapper( TryStmt * tryStmt ) {
+		// void finally() { <finally code> }
 		FinallyStmt * finally = tryStmt->get_finally();
 		CompoundStmt * body = finally->get_block();
@@ -462,4 +548,7 @@
 		Context cur_context;
 
+		// The current (innermost) termination handler exception declaration.
+		ObjectDecl * handler_except_decl;
+
 		// We might not need this, but a unique base for each try block's
 		// generated functions might be nice.
@@ -473,5 +562,6 @@
 		ExceptionMutatorCore() :
 			cur_context(NoHandler),
-			node_decl(nullptr), hook_decl(nullptr)
+			handler_except_decl( nullptr ),
+			node_decl( nullptr ), hook_decl( nullptr )
 		{}
 
@@ -481,4 +571,46 @@
 		Statement * postmutate( TryStmt *tryStmt );
 	};
+
+	void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
+		// Currently, we make up the declaration, as there isn't one for
+		// integers.
+		ObjectDecl * tmp = new ObjectDecl(
+			"_hidden_local",
+			Type::StorageClasses(),
+			LinkageSpec::Cforall,
+			nullptr,
+			new PointerType(
+				noQualifiers,
+				new BasicType( noQualifiers, BasicType::SignedInt )
+				),
+			nullptr
+			);
+		catchStmt->set_decl( tmp );
+
+		GuardValue( cur_context );
+		if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
+			cur_context = TerHandler;
+
+			GuardValue( handler_except_decl );
+			handler_except_decl = tmp;
+			//handler_except_decl = catchStmt->get_decl();
+		} else {
+			cur_context = ResHandler;
+		}
+	}
+
+	void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
+		if ( !structDecl->has_body() ) {
+			// Skip children?
+			return;
+		} else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
+			assert( nullptr == node_decl );
+			node_decl = structDecl;
+		} else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
+			assert( nullptr == hook_decl );
+			hook_decl = structDecl;
+		}
+		// Later we might get the exception type as well.
+	}
 
 	Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
@@ -488,5 +620,6 @@
 				return create_terminate_throw( throwStmt );
 			} else if ( TerHandler == cur_context ) {
-				return create_terminate_rethrow( throwStmt );
+				return create_terminate_rethrow(
+					throwStmt, handler_except_decl );
 			} else {
 				assertf(false, "Invalid throw in %s at %i\n",
@@ -560,31 +693,5 @@
 		block->push_back( inner );
 
-		//free_all( termination_handlers );
-		//free_all( resumption_handlers );
-
 		return block;
-	}
-
-	void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
-		GuardValue( cur_context );
-		if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
-			cur_context = TerHandler;
-		} else {
-			cur_context = ResHandler;
-		}
-	}
-
-	void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
-		if ( !structDecl->has_body() ) {
-			// Skip children?
-			return;
-		} else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
-			assert( nullptr == node_decl );
-			node_decl = structDecl;
-		} else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
-			assert( nullptr == hook_decl );
-			hook_decl = structDecl;
-		}
-		// Later we might get the exception type as well.
 	}
 
