Index: src/ControlStruct/ExceptDecl.cpp
===================================================================
--- src/ControlStruct/ExceptDecl.cpp	(revision 4dc3b8c90f62876e9e5e2b84283aebb28622582a)
+++ src/ControlStruct/ExceptDecl.cpp	(revision 4dc3b8c90f62876e9e5e2b84283aebb28622582a)
@@ -0,0 +1,515 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// ExceptDecl.cpp --
+//
+// Author           : Andrew Beach
+// Created On       : Tue Jul 12 15:50:00 2022
+// Last Modified By : Andrew Beach
+// Last Modified On : Mon Jul 18 11:01:00 2022
+// Update Count     : 0
+//
+
+#include "ExceptDecl.h"
+
+#include <sstream>
+
+#include "AST/Copy.hpp"
+#include "AST/Decl.hpp"
+#include "AST/Pass.hpp"
+#include "AST/Print.hpp"
+#include "AST/Type.hpp"
+#include "Virtual/Tables.h"
+
+namespace ControlStruct {
+
+namespace {
+
+std::vector<ast::ptr<ast::Expr>> forallToParams(
+		std::vector<ast::ptr<ast::TypeDecl>> const & forall ) {
+	return map_range<std::vector<ast::ptr<ast::Expr>>>( forall,
+		[]( ast::ptr<ast::TypeDecl> const & decl ) {
+			return new ast::TypeExpr( decl->location,
+				new ast::TypeInstType( decl->name, decl->kind ) );
+		}
+	);
+}
+
+// A slightly argumented extra constructor, adds a deepCopy.
+ast::StructInstType * namedStructInstType(
+		std::string const & name, ast::CV::Qualifiers qualifiers,
+		std::vector<ast::ptr<ast::Expr>> const & params ) {
+	ast::StructInstType * type = new ast::StructInstType( name, qualifiers );
+	for ( ast::ptr<ast::Expr> const & param : params ) {
+		type->params.push_back( ast::deepCopy( param ) );
+	}
+	return type;
+}
+
+ast::StructInstType * createExceptionInstType(
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::Expr>> const & params ) {
+	return namedStructInstType( exceptionName, ast::CV::Qualifiers(), params );
+}
+
+ast::StructInstType * createVTableInstType(
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::Expr>> const & params ) {
+	std::string name = Virtual::vtableTypeName( exceptionName );
+	return namedStructInstType( name, ast::CV::Const, params );
+}
+
+ast::StructInstType * createTypeIdInstType(
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::Expr>> const & params ) {
+	std::string name = Virtual::typeIdType( exceptionName );
+	return namedStructInstType( name, ast::CV::Const, params );
+}
+
+ast::FunctionType const * createCopyFuncType(
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::Expr>> const & params ) {
+	ast::FunctionType * type = new ast::FunctionType( ast::FixedArgs );
+	type->params.push_back( new ast::PointerType(
+		createExceptionInstType( exceptionName, params ) ) );
+	type->params.push_back( new ast::PointerType(
+		createExceptionInstType( exceptionName, params ) ) );
+	type->returns.push_back( new ast::VoidType() );
+	return type;
+}
+
+ast::FunctionType const * createDtorFuncType(
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::Expr>> const & params ) {
+	ast::FunctionType * type = new ast::FunctionType( ast::FixedArgs );
+	type->params.push_back( new ast::ReferenceType(
+		createExceptionInstType( exceptionName, params ) ) );
+	type->returns.push_back( new ast::VoidType() );
+	return type;
+}
+
+ast::FunctionType const * createMsgFuncType(
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::Expr>> const & params ) {
+	ast::FunctionType * type = new ast::FunctionType( ast::FixedArgs );
+	type->params.push_back( new ast::PointerType(
+		createExceptionInstType( exceptionName, params ) ) );
+	type->returns.push_back( new ast::PointerType(
+		new ast::BasicType( ast::BasicType::Char, ast::CV::Const ) ) );
+	return type;
+}
+
+ast::StructDecl const * createTypeIdStruct(
+		CodeLocation const & location,
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::TypeDecl>> const & forallClause ) {
+	ast::StructDecl * decl = new ast::StructDecl( location,
+			Virtual::typeIdType( exceptionName ) );
+	decl->members.push_back( new ast::ObjectDecl(
+		location,
+		"parent",
+		new ast::PointerType(
+			new ast::StructInstType( "__cfavir_type_info", ast::CV::Const ) )
+	) );
+	decl->body = true;
+	for ( ast::ptr<ast::TypeDecl> const & param : forallClause ) {
+		decl->params.push_back( ast::deepCopy( param ) );
+	}
+	return decl;
+}
+
+ast::ObjectDecl const * createTypeIdValue(
+		CodeLocation const & location,
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::Expr>> const & params ) {
+	ast::StructInstType * typeIdType =
+		createTypeIdInstType( exceptionName, params );
+	return new ast::ObjectDecl(
+		location,
+		Virtual::typeIdName( exceptionName ),
+		typeIdType,
+		new ast::ListInit( location, {
+			new ast::SingleInit( location,
+				new ast::AddressExpr( location,
+					new ast::NameExpr( location, "__cfatid_exception_t" ) ),
+				ast::MaybeConstruct ),
+		}, {}, ast::MaybeConstruct ),
+		ast::Storage::Classes(),
+		ast::Linkage::Cforall,
+		nullptr,
+		{ new ast::Attribute( "cfa_linkonce" ) }
+	);
+}
+
+ast::StructDecl const * createExceptionStructForward(
+		CodeLocation const & location,
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::TypeDecl>> const & forall ) {
+	ast::StructDecl * decl = new ast::StructDecl( location, exceptionName );
+	for ( ast::ptr<ast::TypeDecl> const & param : forall ) {
+		decl->params.push_back( ast::deepCopy( param ) );
+	}
+	return decl;
+}
+
+ast::StructDecl const * createVirtualTableStruct(
+		CodeLocation const & location,
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::TypeDecl>> const & forall,
+		std::vector<ast::ptr<ast::Expr>> const & params ) {
+	ast::StructInstType * typeIdType =
+		createTypeIdInstType( exceptionName, params );
+	ast::ObjectDecl * typeId = new ast::ObjectDecl(
+		location,
+		"__cfavir_typeid",
+		new ast::PointerType( typeIdType )
+	);
+	ast::ObjectDecl * size = new ast::ObjectDecl(
+		location,
+		"size",
+		new ast::TypeInstType( "size_t", ast::TypeDecl::Dtype )
+	);
+	ast::ObjectDecl * copy = new ast::ObjectDecl(
+		location,
+		"copy",
+		new ast::PointerType( createCopyFuncType( exceptionName, params ) )
+	);
+	ast::ObjectDecl * dtor = new ast::ObjectDecl(
+		location,
+		"^?{}",
+		new ast::PointerType( createDtorFuncType( exceptionName, params ) )
+	);
+	ast::ObjectDecl * msg = new ast::ObjectDecl(
+		location,
+		"msg",
+		new ast::PointerType( createMsgFuncType( exceptionName, params ) )
+	);
+	ast::StructDecl * decl = new ast::StructDecl(
+		location,
+		Virtual::vtableTypeName( exceptionName ) );
+	decl->members.push_back( typeId );
+	decl->members.push_back( size );
+	decl->members.push_back( copy );
+	decl->members.push_back( dtor );
+	decl->members.push_back( msg );
+	decl->body = true;
+	for ( ast::ptr<ast::TypeDecl> const & param : forall ) {
+		decl->params.push_back( param );
+	}
+	return decl;
+}
+
+ast::StructDecl const * createExceptionStruct(
+		CodeLocation const & location,
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::TypeDecl>> const & forallClause,
+		std::vector<ast::ptr<ast::Expr>> const & params,
+		std::vector<ast::ptr<ast::Decl>> const & members ) {
+	ast::StructDecl * decl = new ast::StructDecl( location, exceptionName );
+	decl->members.push_back( new ast::ObjectDecl(
+		location,
+		"virtual_table",
+		new ast::PointerType(
+			createVTableInstType( exceptionName, params ) )
+	) );
+	for ( ast::ptr<ast::Decl> const & member : members ) {
+		decl->members.push_back( ast::deepCopy( member ) );
+	}
+	decl->body = true;
+	for ( ast::ptr<ast::TypeDecl> const & param : forallClause ) {
+		decl->params.push_back( ast::deepCopy( param ) );
+	}
+	return decl;
+}
+
+ast::ObjectDecl const * createExternTypeId(
+		CodeLocation const & location,
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::Expr>> const & params ) {
+	return new ast::ObjectDecl(
+		location,
+		Virtual::typeIdName( exceptionName ),
+		createVTableInstType( exceptionName, params ),
+		nullptr,
+		ast::Storage::Extern,
+		ast::Linkage::Cforall,
+		nullptr,
+		{ new ast::Attribute( "cfa_linkonce" ) }
+	);
+}
+
+ast::ObjectDecl * createExternVTable(
+		CodeLocation const & location,
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::Expr>> const & params,
+		std::string const & tableName ) {
+	return new ast::ObjectDecl(
+		location,
+		tableName,
+		createVTableInstType( exceptionName, params ),
+		nullptr,
+		ast::Storage::Extern,
+		ast::Linkage::Cforall
+	);
+}
+
+ast::FunctionDecl const * createCopy(
+		CodeLocation const & location,
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::Expr>> const & params ) {
+	return new ast::FunctionDecl(
+		location,
+		"copy",
+		{/* forall */},
+		{/* assertions */},
+		{
+			new ast::ObjectDecl(
+				location,
+				"this",
+				new ast::PointerType(
+					createExceptionInstType( exceptionName, params ) )
+			),
+			new ast::ObjectDecl(
+				location,
+				"that",
+				new ast::PointerType(
+					createExceptionInstType( exceptionName, params ) )
+			),
+		},
+		{
+			new ast::ObjectDecl( location, "", new ast::VoidType() ),
+		},
+		new ast::CompoundStmt( location, {
+			new ast::ExprStmt( location,
+				new ast::UntypedExpr( location,
+					new ast::NameExpr( location, "?=?" ),
+					{
+						new ast::UntypedExpr( location,
+							new ast::NameExpr( location, "*?" ),
+							{ new ast::NameExpr( location, "this" ) } ),
+						new ast::UntypedExpr( location,
+							new ast::NameExpr( location, "*?" ),
+							{ new ast::NameExpr( location, "that" ) } ),
+					}
+				)
+			),
+		} ),
+		ast::Storage::Classes(),
+		ast::Linkage::Cforall,
+		{ new ast::Attribute( "cfa_linkonce" ) }
+	);
+}
+
+ast::FunctionDecl const * createMsg(
+		CodeLocation const & location,
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::Expr>> const & params ) {
+	std::stringstream msg;
+	msg << exceptionName;
+	// The forall variant, add parameters to the string.
+	if ( !params.empty() ) {
+		msg << "(";
+		bool first = true;
+		for ( auto & param : params ) {
+			// Seperator Logic: A comma proceeds all but the first object.
+			if ( first ) {
+				first = false;
+			} else {
+				msg << ", ";
+			}
+
+			ast::print( msg, param.get() );
+		}
+		msg << ")";
+	}
+	return new ast::FunctionDecl(
+		location,
+		"msg",
+		{/* forall */},
+		{/* assertions */},
+		{
+			new ast::ObjectDecl(
+				location,
+				"this",
+				new ast::PointerType(
+					createExceptionInstType( exceptionName, params ) )
+			),
+		},
+		{
+			new ast::ObjectDecl(
+				location,
+				"",
+				new ast::PointerType(
+					new ast::BasicType( ast::BasicType::Char, ast::CV::Const ) )
+			),
+		},
+		new ast::CompoundStmt( location, {
+			new ast::ReturnStmt( location,
+				ast::ConstantExpr::from_string( location, msg.str() )
+			),
+		} ),
+		ast::Storage::Classes(),
+		ast::Linkage::Cforall,
+		{ new ast::Attribute( "cfa_linkonce" ) }
+	);
+}
+
+ast::ObjectDecl * createVirtualTable(
+		CodeLocation const & location,
+		std::string const & exceptionName,
+		std::vector<ast::ptr<ast::Expr>> const & params,
+		std::string const & tableName ) {
+	ast::StructInstType * sizeType = new ast::StructInstType( exceptionName );
+	for ( ast::ptr<ast::Expr> const & param : params ) {
+		sizeType->params.push_back( ast::deepCopy( param ) );
+	}
+	std::vector<ast::ptr<ast::Init>> inits {
+		new ast::SingleInit( location,
+			new ast::AddressExpr( location,
+				new ast::NameExpr( location,
+					Virtual::typeIdName( exceptionName ) ) ) ),
+		new ast::SingleInit( location,
+			new ast::SizeofExpr( location, sizeType )  ),
+		new ast::SingleInit( location,
+			new ast::NameExpr( location, "copy" ) ),
+		new ast::SingleInit( location,
+			new ast::NameExpr( location, "^?{}" ) ),
+		new ast::SingleInit( location,
+			new ast::NameExpr( location, "msg" ) ),
+	};
+	std::vector<ast::ptr<ast::Designation>> dsigs {
+		new ast::Designation( location, {
+			new ast::NameExpr( location, "__cfavir_typeid" ) } ),
+		new ast::Designation( location, {
+			new ast::NameExpr( location, "size" ) } ),
+		new ast::Designation( location, {
+			new ast::NameExpr( location, "copy" ) } ),
+		new ast::Designation( location, {
+			new ast::NameExpr( location, "^?{}" ) } ),
+		new ast::Designation( location, {
+			new ast::NameExpr( location, "msg" ) } ),
+	};
+	return new ast::ObjectDecl(
+		location,
+		tableName,
+		createVTableInstType( exceptionName, params ),
+		new ast::ListInit( location, std::move( inits ), std::move( dsigs ) )
+	);
+}
+
+struct ExceptDeclCore : public ast::WithDeclsToAdd<> {
+	ast::StructDecl const * transformExcept( ast::StructDecl const * decl );
+	ast::ObjectDecl const * transformVTable(
+		ast::ObjectDecl const * decl, ast::VTableType const * type );
+
+	ast::StructDecl const * postvisit( ast::StructDecl const * decl ) {
+		// Exceptions don't get their own node type, so filter that.
+		if ( ast::AggregateDecl::Exception == decl->kind ) {
+			return transformExcept( decl );
+		}
+		return decl;
+	}
+
+	ast::ObjectDecl const * postvisit( ast::ObjectDecl const * decl ) {
+		// Modify remaining objects that have a vtable type.
+		if ( auto * type = decl->type.as<ast::VTableType>() ) {
+			return transformVTable( decl, type );
+		}
+		return decl;
+	}
+};
+
+ast::StructDecl const * ExceptDeclCore::transformExcept(
+		ast::StructDecl const * decl ) {
+	CodeLocation const & location = decl->location;
+	std::string const & exceptionName = decl->name;
+	std::vector<ast::ptr<ast::TypeDecl>> const & forall = decl->params;
+	std::vector<ast::ptr<ast::Expr>> params = forallToParams( forall );
+	std::vector<ast::ptr<ast::Decl>> const & members = decl->members;
+
+	declsToAddBefore.push_back(
+		createTypeIdStruct( location, exceptionName, forall ) );
+	if ( forall.empty() ) {
+		// Non-forall variant.
+		declsToAddBefore.push_back(
+			createTypeIdValue( location, exceptionName, params ) );
+	}
+	declsToAddBefore.push_back(
+		createExceptionStructForward( location, exceptionName, forall ) );
+	declsToAddBefore.push_back(
+		createVirtualTableStruct( location, exceptionName, forall, params ) );
+	return createExceptionStruct( location, exceptionName, forall, params, members );
+}
+
+ast::ObjectDecl const * ExceptDeclCore::transformVTable(
+		ast::ObjectDecl const * decl, ast::VTableType const * type ) {
+	CodeLocation const & location = decl->location;
+	auto base = type->base.strict_as<ast::TypeInstType>();
+	std::string const & exceptionName = base->name;
+	std::vector<ast::ptr<ast::Expr>> const & params = base->params;
+	std::string const & tableName = decl->name;
+
+	ast::ObjectDecl * retDecl;
+	if ( decl->storage.is_extern ) {
+		// Unique type-ids are only needed for polymorphic instances.
+		if ( !params.empty() ) {
+			declsToAddBefore.push_back(
+				createExternTypeId( location, exceptionName, params ) );
+		}
+		retDecl = createExternVTable( location, exceptionName, params, tableName );
+	} else {
+		// Unique type-ids are only needed for polymorphic instances.
+		if ( !params.empty() ) {
+			declsToAddBefore.push_back(
+				createTypeIdValue( location, exceptionName, params ) );
+		}
+		declsToAddBefore.push_back(
+			createCopy( location, exceptionName, params ) );
+		declsToAddBefore.push_back(
+			createMsg( location, exceptionName, params ) );
+		retDecl = createVirtualTable(
+			location, exceptionName, params, tableName );
+	}
+
+	for ( ast::ptr<ast::Attribute> const & attr : decl->attributes ) {
+		retDecl->attributes.push_back( attr );
+	}
+
+	return retDecl;
+}
+
+struct VTableCore {
+	ast::StructInstType const * postvisit( ast::VTableType const * type ) {
+		auto inst = type->base.as<ast::BaseInstType>();
+
+		std::string vtableName = Virtual::vtableTypeName( inst->name );
+
+		auto newType = new ast::StructInstType( vtableName );
+		for ( ast::ptr<ast::Expr> const & param : inst->params ) {
+			newType->params.push_back( param );
+		}
+
+		return newType;
+	}
+};
+
+} // namespace
+
+void translateExcept( ast::TranslationUnit & translationUnit ) {
+	// Can I combine these?
+	// Second pass really only covers what the first has missed.
+	// Maybe if the first one is all previsits and the second all postvisit.
+	ast::Pass<ExceptDeclCore>::run( translationUnit );
+	ast::Pass<VTableCore>::run( translationUnit );
+}
+
+} // namespace ControlStruct
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/ControlStruct/ExceptDeclNew.cpp
===================================================================
--- src/ControlStruct/ExceptDeclNew.cpp	(revision 37273c8cb34ce14d7da1cb9d4d43491327ff6807)
+++ 	(revision )
@@ -1,515 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// ExceptDeclNew.cpp --
-//
-// Author           : Andrew Beach
-// Created On       : Tue Jul 12 15:50:00 2022
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Jul 18 11:01:00 2022
-// Update Count     : 0
-//
-
-#include "ExceptDecl.h"
-
-#include <sstream>
-
-#include "AST/Copy.hpp"
-#include "AST/Decl.hpp"
-#include "AST/Pass.hpp"
-#include "AST/Print.hpp"
-#include "AST/Type.hpp"
-#include "Virtual/Tables.h"
-
-namespace ControlStruct {
-
-namespace {
-
-std::vector<ast::ptr<ast::Expr>> forallToParams(
-		std::vector<ast::ptr<ast::TypeDecl>> const & forall ) {
-	return map_range<std::vector<ast::ptr<ast::Expr>>>( forall,
-		[]( ast::ptr<ast::TypeDecl> const & decl ) {
-			return new ast::TypeExpr( decl->location,
-				new ast::TypeInstType( decl->name, decl->kind ) );
-		}
-	);
-}
-
-// A slightly argumented extra constructor, adds a deepCopy.
-ast::StructInstType * namedStructInstType(
-		std::string const & name, ast::CV::Qualifiers qualifiers,
-		std::vector<ast::ptr<ast::Expr>> const & params ) {
-	ast::StructInstType * type = new ast::StructInstType( name, qualifiers );
-	for ( ast::ptr<ast::Expr> const & param : params ) {
-		type->params.push_back( ast::deepCopy( param ) );
-	}
-	return type;
-}
-
-ast::StructInstType * createExceptionInstType(
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::Expr>> const & params ) {
-	return namedStructInstType( exceptionName, ast::CV::Qualifiers(), params );
-}
-
-ast::StructInstType * createVTableInstType(
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::Expr>> const & params ) {
-	std::string name = Virtual::vtableTypeName( exceptionName );
-	return namedStructInstType( name, ast::CV::Const, params );
-}
-
-ast::StructInstType * createTypeIdInstType(
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::Expr>> const & params ) {
-	std::string name = Virtual::typeIdType( exceptionName );
-	return namedStructInstType( name, ast::CV::Const, params );
-}
-
-ast::FunctionType const * createCopyFuncType(
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::Expr>> const & params ) {
-	ast::FunctionType * type = new ast::FunctionType( ast::FixedArgs );
-	type->params.push_back( new ast::PointerType(
-		createExceptionInstType( exceptionName, params ) ) );
-	type->params.push_back( new ast::PointerType(
-		createExceptionInstType( exceptionName, params ) ) );
-	type->returns.push_back( new ast::VoidType() );
-	return type;
-}
-
-ast::FunctionType const * createDtorFuncType(
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::Expr>> const & params ) {
-	ast::FunctionType * type = new ast::FunctionType( ast::FixedArgs );
-	type->params.push_back( new ast::ReferenceType(
-		createExceptionInstType( exceptionName, params ) ) );
-	type->returns.push_back( new ast::VoidType() );
-	return type;
-}
-
-ast::FunctionType const * createMsgFuncType(
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::Expr>> const & params ) {
-	ast::FunctionType * type = new ast::FunctionType( ast::FixedArgs );
-	type->params.push_back( new ast::PointerType(
-		createExceptionInstType( exceptionName, params ) ) );
-	type->returns.push_back( new ast::PointerType(
-		new ast::BasicType( ast::BasicType::Char, ast::CV::Const ) ) );
-	return type;
-}
-
-ast::StructDecl const * createTypeIdStruct(
-		CodeLocation const & location,
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::TypeDecl>> const & forallClause ) {
-	ast::StructDecl * decl = new ast::StructDecl( location,
-			Virtual::typeIdType( exceptionName ) );
-	decl->members.push_back( new ast::ObjectDecl(
-		location,
-		"parent",
-		new ast::PointerType(
-			new ast::StructInstType( "__cfavir_type_info", ast::CV::Const ) )
-	) );
-	decl->body = true;
-	for ( ast::ptr<ast::TypeDecl> const & param : forallClause ) {
-		decl->params.push_back( ast::deepCopy( param ) );
-	}
-	return decl;
-}
-
-ast::ObjectDecl const * createTypeIdValue(
-		CodeLocation const & location,
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::Expr>> const & params ) {
-	ast::StructInstType * typeIdType =
-		createTypeIdInstType( exceptionName, params );
-	return new ast::ObjectDecl(
-		location,
-		Virtual::typeIdName( exceptionName ),
-		typeIdType,
-		new ast::ListInit( location, {
-			new ast::SingleInit( location,
-				new ast::AddressExpr( location,
-					new ast::NameExpr( location, "__cfatid_exception_t" ) ),
-				ast::MaybeConstruct ),
-		}, {}, ast::MaybeConstruct ),
-		ast::Storage::Classes(),
-		ast::Linkage::Cforall,
-		nullptr,
-		{ new ast::Attribute( "cfa_linkonce" ) }
-	);
-}
-
-ast::StructDecl const * createExceptionStructForward(
-		CodeLocation const & location,
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::TypeDecl>> const & forall ) {
-	ast::StructDecl * decl = new ast::StructDecl( location, exceptionName );
-	for ( ast::ptr<ast::TypeDecl> const & param : forall ) {
-		decl->params.push_back( ast::deepCopy( param ) );
-	}
-	return decl;
-}
-
-ast::StructDecl const * createVirtualTableStruct(
-		CodeLocation const & location,
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::TypeDecl>> const & forall,
-		std::vector<ast::ptr<ast::Expr>> const & params ) {
-	ast::StructInstType * typeIdType =
-		createTypeIdInstType( exceptionName, params );
-	ast::ObjectDecl * typeId = new ast::ObjectDecl(
-		location,
-		"__cfavir_typeid",
-		new ast::PointerType( typeIdType )
-	);
-	ast::ObjectDecl * size = new ast::ObjectDecl(
-		location,
-		"size",
-		new ast::TypeInstType( "size_t", ast::TypeDecl::Dtype )
-	);
-	ast::ObjectDecl * copy = new ast::ObjectDecl(
-		location,
-		"copy",
-		new ast::PointerType( createCopyFuncType( exceptionName, params ) )
-	);
-	ast::ObjectDecl * dtor = new ast::ObjectDecl(
-		location,
-		"^?{}",
-		new ast::PointerType( createDtorFuncType( exceptionName, params ) )
-	);
-	ast::ObjectDecl * msg = new ast::ObjectDecl(
-		location,
-		"msg",
-		new ast::PointerType( createMsgFuncType( exceptionName, params ) )
-	);
-	ast::StructDecl * decl = new ast::StructDecl(
-		location,
-		Virtual::vtableTypeName( exceptionName ) );
-	decl->members.push_back( typeId );
-	decl->members.push_back( size );
-	decl->members.push_back( copy );
-	decl->members.push_back( dtor );
-	decl->members.push_back( msg );
-	decl->body = true;
-	for ( ast::ptr<ast::TypeDecl> const & param : forall ) {
-		decl->params.push_back( param );
-	}
-	return decl;
-}
-
-ast::StructDecl const * createExceptionStruct(
-		CodeLocation const & location,
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::TypeDecl>> const & forallClause,
-		std::vector<ast::ptr<ast::Expr>> const & params,
-		std::vector<ast::ptr<ast::Decl>> const & members ) {
-	ast::StructDecl * decl = new ast::StructDecl( location, exceptionName );
-	decl->members.push_back( new ast::ObjectDecl(
-		location,
-		"virtual_table",
-		new ast::PointerType(
-			createVTableInstType( exceptionName, params ) )
-	) );
-	for ( ast::ptr<ast::Decl> const & member : members ) {
-		decl->members.push_back( ast::deepCopy( member ) );
-	}
-	decl->body = true;
-	for ( ast::ptr<ast::TypeDecl> const & param : forallClause ) {
-		decl->params.push_back( ast::deepCopy( param ) );
-	}
-	return decl;
-}
-
-ast::ObjectDecl const * createExternTypeId(
-		CodeLocation const & location,
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::Expr>> const & params ) {
-	return new ast::ObjectDecl(
-		location,
-		Virtual::typeIdName( exceptionName ),
-		createVTableInstType( exceptionName, params ),
-		nullptr,
-		ast::Storage::Extern,
-		ast::Linkage::Cforall,
-		nullptr,
-		{ new ast::Attribute( "cfa_linkonce" ) }
-	);
-}
-
-ast::ObjectDecl * createExternVTable(
-		CodeLocation const & location,
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::Expr>> const & params,
-		std::string const & tableName ) {
-	return new ast::ObjectDecl(
-		location,
-		tableName,
-		createVTableInstType( exceptionName, params ),
-		nullptr,
-		ast::Storage::Extern,
-		ast::Linkage::Cforall
-	);
-}
-
-ast::FunctionDecl const * createCopy(
-		CodeLocation const & location,
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::Expr>> const & params ) {
-	return new ast::FunctionDecl(
-		location,
-		"copy",
-		{/* forall */},
-		{/* assertions */},
-		{
-			new ast::ObjectDecl(
-				location,
-				"this",
-				new ast::PointerType(
-					createExceptionInstType( exceptionName, params ) )
-			),
-			new ast::ObjectDecl(
-				location,
-				"that",
-				new ast::PointerType(
-					createExceptionInstType( exceptionName, params ) )
-			),
-		},
-		{
-			new ast::ObjectDecl( location, "", new ast::VoidType() ),
-		},
-		new ast::CompoundStmt( location, {
-			new ast::ExprStmt( location,
-				new ast::UntypedExpr( location,
-					new ast::NameExpr( location, "?=?" ),
-					{
-						new ast::UntypedExpr( location,
-							new ast::NameExpr( location, "*?" ),
-							{ new ast::NameExpr( location, "this" ) } ),
-						new ast::UntypedExpr( location,
-							new ast::NameExpr( location, "*?" ),
-							{ new ast::NameExpr( location, "that" ) } ),
-					}
-				)
-			),
-		} ),
-		ast::Storage::Classes(),
-		ast::Linkage::Cforall,
-		{ new ast::Attribute( "cfa_linkonce" ) }
-	);
-}
-
-ast::FunctionDecl const * createMsg(
-		CodeLocation const & location,
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::Expr>> const & params ) {
-	std::stringstream msg;
-	msg << exceptionName;
-	// The forall variant, add parameters to the string.
-	if ( !params.empty() ) {
-		msg << "(";
-		bool first = true;
-		for ( auto & param : params ) {
-			// Seperator Logic: A comma proceeds all but the first object.
-			if ( first ) {
-				first = false;
-			} else {
-				msg << ", ";
-			}
-
-			ast::print( msg, param.get() );
-		}
-		msg << ")";
-	}
-	return new ast::FunctionDecl(
-		location,
-		"msg",
-		{/* forall */},
-		{/* assertions */},
-		{
-			new ast::ObjectDecl(
-				location,
-				"this",
-				new ast::PointerType(
-					createExceptionInstType( exceptionName, params ) )
-			),
-		},
-		{
-			new ast::ObjectDecl(
-				location,
-				"",
-				new ast::PointerType(
-					new ast::BasicType( ast::BasicType::Char, ast::CV::Const ) )
-			),
-		},
-		new ast::CompoundStmt( location, {
-			new ast::ReturnStmt( location,
-				ast::ConstantExpr::from_string( location, msg.str() )
-			),
-		} ),
-		ast::Storage::Classes(),
-		ast::Linkage::Cforall,
-		{ new ast::Attribute( "cfa_linkonce" ) }
-	);
-}
-
-ast::ObjectDecl * createVirtualTable(
-		CodeLocation const & location,
-		std::string const & exceptionName,
-		std::vector<ast::ptr<ast::Expr>> const & params,
-		std::string const & tableName ) {
-	ast::StructInstType * sizeType = new ast::StructInstType( exceptionName );
-	for ( ast::ptr<ast::Expr> const & param : params ) {
-		sizeType->params.push_back( ast::deepCopy( param ) );
-	}
-	std::vector<ast::ptr<ast::Init>> inits {
-		new ast::SingleInit( location,
-			new ast::AddressExpr( location,
-				new ast::NameExpr( location,
-					Virtual::typeIdName( exceptionName ) ) ) ),
-		new ast::SingleInit( location,
-			new ast::SizeofExpr( location, sizeType )  ),
-		new ast::SingleInit( location,
-			new ast::NameExpr( location, "copy" ) ),
-		new ast::SingleInit( location,
-			new ast::NameExpr( location, "^?{}" ) ),
-		new ast::SingleInit( location,
-			new ast::NameExpr( location, "msg" ) ),
-	};
-	std::vector<ast::ptr<ast::Designation>> dsigs {
-		new ast::Designation( location, {
-			new ast::NameExpr( location, "__cfavir_typeid" ) } ),
-		new ast::Designation( location, {
-			new ast::NameExpr( location, "size" ) } ),
-		new ast::Designation( location, {
-			new ast::NameExpr( location, "copy" ) } ),
-		new ast::Designation( location, {
-			new ast::NameExpr( location, "^?{}" ) } ),
-		new ast::Designation( location, {
-			new ast::NameExpr( location, "msg" ) } ),
-	};
-	return new ast::ObjectDecl(
-		location,
-		tableName,
-		createVTableInstType( exceptionName, params ),
-		new ast::ListInit( location, std::move( inits ), std::move( dsigs ) )
-	);
-}
-
-struct ExceptDeclCore : public ast::WithDeclsToAdd<> {
-	ast::StructDecl const * transformExcept( ast::StructDecl const * decl );
-	ast::ObjectDecl const * transformVTable(
-		ast::ObjectDecl const * decl, ast::VTableType const * type );
-
-	ast::StructDecl const * postvisit( ast::StructDecl const * decl ) {
-		// Exceptions don't get their own node type, so filter that.
-		if ( ast::AggregateDecl::Exception == decl->kind ) {
-			return transformExcept( decl );
-		}
-		return decl;
-	}
-
-	ast::ObjectDecl const * postvisit( ast::ObjectDecl const * decl ) {
-		// Modify remaining objects that have a vtable type.
-		if ( auto * type = decl->type.as<ast::VTableType>() ) {
-			return transformVTable( decl, type );
-		}
-		return decl;
-	}
-};
-
-ast::StructDecl const * ExceptDeclCore::transformExcept(
-		ast::StructDecl const * decl ) {
-	CodeLocation const & location = decl->location;
-	std::string const & exceptionName = decl->name;
-	std::vector<ast::ptr<ast::TypeDecl>> const & forall = decl->params;
-	std::vector<ast::ptr<ast::Expr>> params = forallToParams( forall );
-	std::vector<ast::ptr<ast::Decl>> const & members = decl->members;
-
-	declsToAddBefore.push_back(
-		createTypeIdStruct( location, exceptionName, forall ) );
-	if ( forall.empty() ) {
-		// Non-forall variant.
-		declsToAddBefore.push_back(
-			createTypeIdValue( location, exceptionName, params ) );
-	}
-	declsToAddBefore.push_back(
-		createExceptionStructForward( location, exceptionName, forall ) );
-	declsToAddBefore.push_back(
-		createVirtualTableStruct( location, exceptionName, forall, params ) );
-	return createExceptionStruct( location, exceptionName, forall, params, members );
-}
-
-ast::ObjectDecl const * ExceptDeclCore::transformVTable(
-		ast::ObjectDecl const * decl, ast::VTableType const * type ) {
-	CodeLocation const & location = decl->location;
-	auto base = type->base.strict_as<ast::TypeInstType>();
-	std::string const & exceptionName = base->name;
-	std::vector<ast::ptr<ast::Expr>> const & params = base->params;
-	std::string const & tableName = decl->name;
-
-	ast::ObjectDecl * retDecl;
-	if ( decl->storage.is_extern ) {
-		// Unique type-ids are only needed for polymorphic instances.
-		if ( !params.empty() ) {
-			declsToAddBefore.push_back(
-				createExternTypeId( location, exceptionName, params ) );
-		}
-		retDecl = createExternVTable( location, exceptionName, params, tableName );
-	} else {
-		// Unique type-ids are only needed for polymorphic instances.
-		if ( !params.empty() ) {
-			declsToAddBefore.push_back(
-				createTypeIdValue( location, exceptionName, params ) );
-		}
-		declsToAddBefore.push_back(
-			createCopy( location, exceptionName, params ) );
-		declsToAddBefore.push_back(
-			createMsg( location, exceptionName, params ) );
-		retDecl = createVirtualTable(
-			location, exceptionName, params, tableName );
-	}
-
-	for ( ast::ptr<ast::Attribute> const & attr : decl->attributes ) {
-		retDecl->attributes.push_back( attr );
-	}
-
-	return retDecl;
-}
-
-struct VTableCore {
-	ast::StructInstType const * postvisit( ast::VTableType const * type ) {
-		auto inst = type->base.as<ast::BaseInstType>();
-
-		std::string vtableName = Virtual::vtableTypeName( inst->name );
-
-		auto newType = new ast::StructInstType( vtableName );
-		for ( ast::ptr<ast::Expr> const & param : inst->params ) {
-			newType->params.push_back( param );
-		}
-
-		return newType;
-	}
-};
-
-} // namespace
-
-void translateExcept( ast::TranslationUnit & translationUnit ) {
-	// Can I combine these?
-	// Second pass really only covers what the first has missed.
-	// Maybe if the first one is all previsits and the second all postvisit.
-	ast::Pass<ExceptDeclCore>::run( translationUnit );
-	ast::Pass<VTableCore>::run( translationUnit );
-}
-
-} // namespace ControlStruct
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/ControlStruct/ExceptTranslate.cpp
===================================================================
--- src/ControlStruct/ExceptTranslate.cpp	(revision 4dc3b8c90f62876e9e5e2b84283aebb28622582a)
+++ src/ControlStruct/ExceptTranslate.cpp	(revision 4dc3b8c90f62876e9e5e2b84283aebb28622582a)
@@ -0,0 +1,725 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// ExceptTranslate.cpp -- Conversion of exception control flow structures.
+//
+// Author           : Andrew Beach
+// Created On       : Mon Nov  8 11:53:00 2021
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Mar 11 17:51:00 2022
+// Update Count     : 2
+//
+
+#include "ExceptTranslate.h"
+
+#include "AST/Expr.hpp"
+#include "AST/Pass.hpp"
+#include "AST/Stmt.hpp"
+#include "AST/TranslationUnit.hpp"
+#include "AST/DeclReplacer.hpp"
+
+namespace ControlStruct {
+
+namespace {
+
+	typedef std::list<ast::CatchClause*> CatchList;
+
+	void appendDeclStmt( ast::CompoundStmt * block, ast::DeclWithType * item ) {
+		block->push_back(new ast::DeclStmt(block->location, item));
+	}
+
+class TranslateThrowsCore final : public ast::WithGuards {
+	const ast::ObjectDecl * terminateHandlerExcept;
+	enum Context { NoHandler, TerHandler, ResHandler } currentContext;
+
+	const ast::Stmt * createEitherThrow(
+		const ast::ThrowStmt * throwStmt, const char * funcName );
+	const ast::Stmt * createTerminateRethrow( const ast::ThrowStmt * );
+
+public:
+	TranslateThrowsCore() :
+		terminateHandlerExcept( nullptr ), currentContext( NoHandler )
+	{}
+
+	void previsit( const ast::CatchClause * stmt );
+	const ast::Stmt * postvisit( const ast::ThrowStmt * stmt );
+};
+
+const ast::Stmt * TranslateThrowsCore::createEitherThrow(
+		const ast::ThrowStmt * throwStmt, const char * funcName ) {
+	// `throwFunc`( `throwStmt->name` );
+	ast::UntypedExpr * call = new ast::UntypedExpr( throwStmt->location,
+		new ast::NameExpr( throwStmt->location, funcName )
+	);
+	call->args.push_back( throwStmt->expr );
+	return new ast::ExprStmt( throwStmt->location, call );
+}
+
+ast::VariableExpr * varOf( const ast::DeclWithType * decl ) {
+	return new ast::VariableExpr( decl->location, decl );
+}
+
+const ast::Stmt * TranslateThrowsCore::createTerminateRethrow(
+		const ast::ThrowStmt * stmt ) {
+	// { `terminate_handler_except` = 0p; __rethrow_terminate(); }
+	assert( nullptr == stmt->expr );
+	assert( terminateHandlerExcept );
+
+	ast::CompoundStmt * result = new ast::CompoundStmt(
+		stmt->location, {}, std::vector<ast::Label>( stmt->labels ) );
+	result->push_back( new ast::ExprStmt( stmt->location,
+		ast::UntypedExpr::createAssign(
+			stmt->location,
+			varOf( terminateHandlerExcept ),
+			ast::ConstantExpr::null(
+				stmt->location,
+				terminateHandlerExcept->type
+			)
+		)
+	) );
+	result->push_back( new ast::ExprStmt( stmt->location, new ast::UntypedExpr(
+		stmt->location,
+		new ast::NameExpr( stmt->location, "__cfaehm_rethrow_terminate" )
+	) ) );
+	return result;
+}
+
+void TranslateThrowsCore::previsit( const ast::CatchClause * stmt ) {
+	// Validate the statement's form.
+	const ast::ObjectDecl * decl = stmt->decl.as<ast::ObjectDecl>();
+	// Also checking the type would be nice.
+	if ( !decl || !decl->type.as<ast::PointerType>() ) {
+		std::string kind = (ast::Terminate == stmt->kind) ? "catch" : "catchResume";
+		SemanticError( stmt->location, kind + " must have pointer to an exception type" );
+	}
+
+	// Track the handler context.
+	if ( ast::Terminate == stmt->kind ) {
+		GuardValue( currentContext ) = TerHandler;
+		GuardValue( terminateHandlerExcept ) = decl;
+	} else {
+		GuardValue( currentContext ) = ResHandler;
+	}
+}
+
+const ast::Stmt * TranslateThrowsCore::postvisit(
+		const ast::ThrowStmt * stmt ) {
+	// Ignoring ThrowStmt::target for now.
+	// Handle Termination (Raise, Reraise, Error):
+	if ( ast::Terminate == stmt->kind ) {
+		if ( stmt->expr ) {
+			return createEitherThrow( stmt, "$throw" );
+		} else if ( TerHandler == currentContext ) {
+			return createTerminateRethrow( stmt );
+		} else {
+			abort( "Invalid throw in %s at %i\n",
+				stmt->location.filename.c_str(),
+				stmt->location.first_line);
+		}
+	// Handle Resumption (Raise, Reraise, Error):
+	} else {
+		if ( stmt->expr ) {
+			return createEitherThrow( stmt, "$throwResume" );
+		} else if ( ResHandler == currentContext ) {
+			// This has to be handled later.
+			return stmt;
+		} else {
+			abort( "Invalid throwResume in %s at %i\n",
+				stmt->location.filename.c_str(),
+				stmt->location.first_line);
+		}
+	}
+}
+
+
+class TryMutatorCore final {
+	// The built in types used in translation.
+	const ast::StructDecl * except_decl;
+	const ast::StructDecl * node_decl;
+	const ast::StructDecl * hook_decl;
+
+	// The many helper functions for code/syntree generation.
+	ast::CompoundStmt * take_try_block( ast::TryStmt * tryStmt );
+	ast::FunctionDecl * create_try_wrapper( const ast::CompoundStmt * body );
+	ast::FunctionDecl * create_terminate_catch( CatchList &handlers );
+	ast::CompoundStmt * create_single_matcher(
+		const ast::DeclWithType * except_obj, ast::CatchClause * modded_handler );
+	ast::FunctionDecl * create_terminate_match( CatchList &handlers );
+	ast::CompoundStmt * create_terminate_caller( CodeLocation loc, ast::FunctionDecl * try_wrapper,
+		ast::FunctionDecl * terminate_catch, ast::FunctionDecl * terminate_match );
+	ast::FunctionDecl * create_resume_handler( CatchList &handlers );
+	ast::CompoundStmt * create_resume_wrapper(
+		const ast::Stmt * wraps, const ast::FunctionDecl * resume_handler );
+	ast::FunctionDecl * create_finally_wrapper( ast::TryStmt * tryStmt );
+	ast::ObjectDecl * create_finally_hook( ast::FunctionDecl * finally_wrapper );
+	ast::Stmt * create_resume_rethrow( const ast::ThrowStmt * throwStmt );
+
+	// Types used in translation, first group are internal.
+	ast::ObjectDecl * make_index_object( CodeLocation const & ) const;
+	ast::ObjectDecl * make_exception_object( CodeLocation const & ) const;
+	ast::ObjectDecl * make_bool_object( CodeLocation const & ) const;
+	ast::ObjectDecl * make_voidptr_object( CodeLocation const & ) const;
+	ast::ObjectDecl * make_unused_index_object( CodeLocation const & ) const;
+	// void (*function)();
+	ast::FunctionDecl * make_try_function( CodeLocation const & ) const;
+	// void (*function)(int, exception);
+	ast::FunctionDecl * make_catch_function( CodeLocation const & ) const;
+	// int (*function)(exception);
+	ast::FunctionDecl * make_match_function( CodeLocation const & ) const;
+	// bool (*function)(exception);
+	ast::FunctionDecl * make_handle_function( CodeLocation const & ) const;
+	// void (*function)(__attribute__((unused)) void *);
+	ast::FunctionDecl * make_finally_function( CodeLocation const & ) const;
+
+public:
+	TryMutatorCore() :
+		except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr )
+	{}
+
+	void previsit( const ast::StructDecl *structDecl );
+	ast::Stmt * postvisit( const ast::TryStmt *tryStmt );
+	ast::Stmt * postvisit( const ast::ThrowStmt *throwStmt );
+};
+
+ast::ObjectDecl * TryMutatorCore::make_index_object(
+		CodeLocation const & location ) const {
+	return new ast::ObjectDecl(
+		location,
+		"__handler_index",
+		new ast::BasicType( ast::BasicType::SignedInt )
+		);
+}
+
+ast::ObjectDecl * TryMutatorCore::make_exception_object(
+		CodeLocation const & location ) const {
+	assert( except_decl );
+	return new ast::ObjectDecl(
+		location,
+		"__exception_inst",
+		new ast::PointerType( new ast::StructInstType( except_decl ) )
+		);
+}
+
+ast::ObjectDecl * TryMutatorCore::make_bool_object(
+		CodeLocation const & location ) const {
+	return new ast::ObjectDecl(
+		location,
+		"__ret_bool",
+		new ast::BasicType( ast::BasicType::Bool ),
+		nullptr, //init
+		ast::Storage::Classes{},
+		ast::Linkage::Cforall,
+		nullptr, //width
+		std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
+		);
+}
+
+ast::ObjectDecl * TryMutatorCore::make_voidptr_object(
+		CodeLocation const & location ) const {
+	return new ast::ObjectDecl(
+		location,
+		"__hook",
+		new ast::PointerType(
+			new ast::VoidType()
+		),
+		nullptr, //init
+		ast::Storage::Classes{},
+		ast::Linkage::Cforall,
+		nullptr, //width
+		std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
+		);
+}
+
+ast::ObjectDecl * TryMutatorCore::make_unused_index_object(
+		CodeLocation const & location ) const {
+	return new ast::ObjectDecl(
+		location,
+		"__handler_index",
+		new ast::BasicType(ast::BasicType::SignedInt),
+		nullptr,
+		ast::Storage::Classes{},
+		ast::Linkage::Cforall,
+		nullptr, //width
+		std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
+	);
+}
+
+ast::FunctionDecl * TryMutatorCore::make_try_function(
+		CodeLocation const & location ) const {
+	return new ast::FunctionDecl(
+		location,
+		"try",
+		{}, //no param
+		{}, //no return
+		nullptr,
+		ast::Storage::Classes{},
+		ast::Linkage::Cforall
+	);
+}
+
+ast::FunctionDecl * TryMutatorCore::make_catch_function(
+		CodeLocation const & location ) const {
+	return new ast::FunctionDecl(
+		location,
+		"catch",
+		{ make_index_object( location ), make_exception_object( location ) },
+		{}, //return void
+		nullptr,
+		ast::Storage::Classes{},
+		ast::Linkage::Cforall
+	);
+}
+
+ast::FunctionDecl * TryMutatorCore::make_match_function(
+		CodeLocation const & location ) const {
+	return new ast::FunctionDecl(
+		location,
+		"match",
+		{ make_exception_object( location ) },
+		{ make_unused_index_object( location ) },
+		nullptr,
+		ast::Storage::Classes{},
+		ast::Linkage::Cforall
+	);
+}
+
+ast::FunctionDecl * TryMutatorCore::make_handle_function(
+		CodeLocation const & location ) const {
+	return new ast::FunctionDecl(
+		location,
+		"handle",
+		{ make_exception_object( location ) },
+		{ make_bool_object( location ) },
+		nullptr,
+		ast::Storage::Classes{},
+		ast::Linkage::Cforall
+	);
+}
+
+ast::FunctionDecl * TryMutatorCore::make_finally_function(
+		CodeLocation const & location ) const {
+	return new ast::FunctionDecl(
+		location,
+		"finally",
+		{ make_voidptr_object( location ) },
+		{}, //return void
+		nullptr,
+		ast::Storage::Classes{},
+		ast::Linkage::Cforall,
+		{},
+		{ ast::Function::Inline }
+	);
+}
+
+// TryStmt Mutation Helpers
+
+ast::FunctionDecl * TryMutatorCore::create_try_wrapper(
+		const ast::CompoundStmt *body ) {
+
+	ast::FunctionDecl * ret = make_try_function( body->location );
+	ret->stmts = body;
+	return ret;
+}
+
+ast::FunctionDecl * TryMutatorCore::create_terminate_catch(
+		CatchList &handlers ) {
+	std::vector<ast::ptr<ast::CaseClause>> handler_wrappers;
+
+	assert (!handlers.empty());
+	const CodeLocation loc = handlers.front()->location;
+
+	ast::FunctionDecl * func_t = make_catch_function( loc );
+	const ast::DeclWithType * index_obj = func_t->params.front();
+	const ast::DeclWithType * except_obj = func_t->params.back();
+
+	// Index 1..{number of handlers}
+	int index = 0;
+	CatchList::iterator it = handlers.begin();
+	for ( ; it != handlers.end() ; ++it ) {
+		++index;
+		ast::CatchClause * handler = *it;
+		const CodeLocation loc = handler->location;
+
+		// case `index`:
+		// {
+		//     `handler.decl` = { (virtual `decl.type`)`except` };
+		//     `handler.body`;
+		// }
+		// return;
+		ast::CompoundStmt * block = new ast::CompoundStmt(loc);
+
+		// Just copy the exception value. (Post Validation)
+		const ast::ObjectDecl * handler_decl =
+			handler->decl.strict_as<ast::ObjectDecl>();
+		ast::ObjectDecl * local_except = ast::deepCopy(handler_decl);
+		ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc,
+			new ast::VariableExpr( loc, except_obj ),
+			local_except->get_type()
+			);
+		vcex->location = handler->location;
+		local_except->init = new ast::ListInit(loc, { new ast::SingleInit( loc, vcex ) });
+		block->push_back( new ast::DeclStmt( loc, local_except ) );
+
+		// Add the cleanup attribute.
+		local_except->attributes.push_back( new ast::Attribute(
+			"cleanup",
+			{ new ast::NameExpr( loc, "__cfaehm_cleanup_terminate" ) }
+			) );
+
+		ast::DeclReplacer::DeclMap mapping;
+		mapping[handler_decl] = local_except;
+		const ast::Stmt * mutBody = strict_dynamic_cast<const ast::Stmt *>(
+			ast::DeclReplacer::replace(handler->body, mapping));
+
+
+		block->push_back( mutBody );
+		// handler->body = nullptr;
+
+		handler_wrappers.push_back( new ast::CaseClause(loc,
+			ast::ConstantExpr::from_int(loc, index) ,
+			{ block, new ast::ReturnStmt( loc, nullptr ) }
+			));
+	}
+	// TODO: Some sort of meaningful error on default perhaps?
+
+	ast::SwitchStmt * handler_lookup = new ast::SwitchStmt( loc,
+		new ast::VariableExpr( loc, index_obj ),
+		std::move(handler_wrappers)
+		);
+	ast::CompoundStmt * body = new ast::CompoundStmt( loc, {handler_lookup} );
+
+	func_t->stmts = body;
+	return func_t;
+}
+
+// Create a single check from a moddified handler.
+// except_obj is referenced, modded_handler will be freed.
+ast::CompoundStmt * TryMutatorCore::create_single_matcher(
+		const ast::DeclWithType * except_obj, ast::CatchClause * modded_handler ) {
+	// {
+	//     `modded_handler.decl`
+	//     if ( `decl.name = (virtual `decl.type`)`except`
+	//             [&& `modded_handler.cond`] ) {
+	//         `modded_handler.body`
+	//     }
+	// }
+
+	const CodeLocation loc = modded_handler->location;
+	ast::CompoundStmt * block = new ast::CompoundStmt(loc);
+
+	// Local Declaration
+	const ast::ObjectDecl * local_except =
+		modded_handler->decl.strict_as<ast::ObjectDecl>();
+	block->push_back( new ast::DeclStmt( loc,  local_except ) );
+
+	// Check for type match.
+	ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc,
+		new ast::VariableExpr(loc, except_obj ),
+		local_except->get_type()
+		);
+	ast::Expr * cond = ast::UntypedExpr::createAssign(loc,
+		new ast::VariableExpr(loc, local_except ), vcex );
+
+	// Add the check on the conditional if it is provided.
+	if ( modded_handler->cond ) {
+		cond = new ast::LogicalExpr( loc, cond, modded_handler->cond, ast::LogicalFlag::AndExpr );
+	}
+	// Construct the match condition.
+	block->push_back( new ast::IfStmt(loc,
+		cond, modded_handler->body, nullptr ) );
+
+	return block;
+}
+
+ast::FunctionDecl * TryMutatorCore::create_terminate_match(
+		CatchList &handlers ) {
+	// int match(exception * except) {
+	//     HANDLER WRAPPERS { return `index`; }
+	// }
+
+	assert (!handlers.empty());
+	const CodeLocation loc = handlers.front()->location;
+
+	ast::CompoundStmt * body = new ast::CompoundStmt(loc);
+
+	ast::FunctionDecl * func_t = make_match_function( loc );
+	const ast::DeclWithType * except_obj = func_t->params.back();
+
+	// Index 1..{number of handlers}
+	int index = 0;
+	CatchList::iterator it;
+	for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
+		++index;
+		ast::CatchClause * handler = *it;
+
+		// Body should have been taken by create_terminate_catch.
+		// xxx - just ignore it?
+		// assert( nullptr == handler->get_body() );
+
+		// Create new body.
+		handler->body = new ast::ReturnStmt( handler->location,
+			ast::ConstantExpr::from_int( handler->location, index ) );
+
+		// Create the handler.
+		body->push_back( create_single_matcher( except_obj, handler ) );
+		*it = nullptr;
+	}
+
+	body->push_back( new ast::ReturnStmt(loc,
+		ast::ConstantExpr::from_int( loc, 0 ) ));
+
+	func_t->stmts = body;
+
+	return func_t;
+}
+
+ast::CompoundStmt * TryMutatorCore::create_terminate_caller(
+		CodeLocation loc,
+		ast::FunctionDecl * try_wrapper,
+		ast::FunctionDecl * terminate_catch,
+		ast::FunctionDecl * terminate_match ) {
+	// { __cfaehm_try_terminate(`try`, `catch`, `match`); }
+
+	ast::UntypedExpr * caller = new ast::UntypedExpr(loc, new ast::NameExpr(loc,
+		"__cfaehm_try_terminate" ) );
+	caller->args.push_back( new ast::VariableExpr(loc, try_wrapper ) );
+	caller->args.push_back( new ast::VariableExpr(loc, terminate_catch ) );
+	caller->args.push_back( new ast::VariableExpr(loc, terminate_match ) );
+
+	ast::CompoundStmt * callStmt = new ast::CompoundStmt(loc);
+	callStmt->push_back( new ast::ExprStmt( loc, caller ) );
+	return callStmt;
+}
+
+ast::FunctionDecl * TryMutatorCore::create_resume_handler(
+		CatchList &handlers ) {
+	// bool handle(exception * except) {
+	//     HANDLER WRAPPERS { `hander->body`; return true; }
+	// }
+	assert (!handlers.empty());
+	const CodeLocation loc = handlers.front()->location;
+	ast::CompoundStmt * body = new ast::CompoundStmt(loc);
+
+	ast::FunctionDecl * func_t = make_handle_function( loc );
+	const ast::DeclWithType * except_obj = func_t->params.back();
+
+	CatchList::iterator it;
+	for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
+		ast::CatchClause * handler = *it;
+		const CodeLocation loc = handler->location;
+		// Modifiy body.
+		ast::CompoundStmt * handling_code;
+		if (handler->body.as<ast::CompoundStmt>()) {
+			handling_code = strict_dynamic_cast<ast::CompoundStmt*>(
+				handler->body.get_and_mutate() );
+		} else {
+			handling_code = new ast::CompoundStmt(loc);
+			handling_code->push_back( handler->body );
+		}
+		handling_code->push_back( new ast::ReturnStmt(loc,
+			ast::ConstantExpr::from_bool(loc, true ) ) );
+		handler->body = handling_code;
+
+		// Create the handler.
+		body->push_back( create_single_matcher( except_obj, handler ) );
+		*it = nullptr;
+	}
+
+	body->push_back( new ast::ReturnStmt(loc,
+		ast::ConstantExpr::from_bool(loc, false ) ) );
+	func_t->stmts = body;
+
+	return func_t;
+}
+
+ast::CompoundStmt * TryMutatorCore::create_resume_wrapper(
+		const ast::Stmt * wraps,
+		const ast::FunctionDecl * resume_handler ) {
+	const CodeLocation loc = wraps->location;
+	ast::CompoundStmt * body = new ast::CompoundStmt(loc);
+
+	// struct __try_resume_node __resume_node
+	//  	__attribute__((cleanup( __cfaehm_try_resume_cleanup )));
+	// ** unwinding of the stack here could cause problems **
+	// ** however I don't think that can happen currently **
+	// __cfaehm_try_resume_setup( &__resume_node, resume_handler );
+
+	ast::ObjectDecl * obj = new ast::ObjectDecl(
+		loc,
+		"__resume_node",
+		new ast::StructInstType(
+			node_decl
+			),
+		nullptr,
+		ast::Storage::Classes{},
+		ast::Linkage::Cforall,
+		nullptr,
+		{new ast::Attribute("cleanup", {new ast::NameExpr(loc, "__cfaehm_try_resume_cleanup")})}
+		);
+	appendDeclStmt( body, obj );
+
+	ast::UntypedExpr *setup = new ast::UntypedExpr(loc, new ast::NameExpr(loc,
+		"__cfaehm_try_resume_setup" ) );
+	setup->args.push_back( new ast::AddressExpr( loc, new ast::VariableExpr(loc, obj ) ) );
+	setup->args.push_back( new ast::VariableExpr( loc, resume_handler ) );
+
+	body->push_back( new ast::ExprStmt(loc, setup ) );
+
+	body->push_back( wraps );
+	return body;
+}
+
+ast::FunctionDecl * TryMutatorCore::create_finally_wrapper(
+		ast::TryStmt * tryStmt ) {
+	// void finally() { `finally->block` }
+	const ast::FinallyClause * finally = tryStmt->finally;
+	const ast::CompoundStmt * body = finally->body;
+
+	ast::FunctionDecl * func_t = make_finally_function( tryStmt->location );
+	func_t->stmts = body;
+
+	tryStmt->finally = nullptr;
+
+	return func_t;
+}
+
+ast::ObjectDecl * TryMutatorCore::create_finally_hook(
+		ast::FunctionDecl * finally_wrapper ) {
+	// struct __cfaehm_cleanup_hook __finally_hook
+	//   	__attribute__((cleanup( `finally_wrapper` )));
+
+	const CodeLocation loc = finally_wrapper->location;
+	return new ast::ObjectDecl(
+		loc,
+		"__finally_hook",
+		new ast::StructInstType(
+			hook_decl
+			),
+		nullptr,
+		ast::Storage::Classes{},
+		ast::Linkage::Cforall,
+		nullptr,
+		{new ast::Attribute("cleanup", {new ast::VariableExpr{loc, finally_wrapper}})}
+		);
+}
+
+ast::Stmt * TryMutatorCore::create_resume_rethrow( const ast::ThrowStmt *throwStmt ) {
+	// return false;
+	const CodeLocation loc = throwStmt->location;
+	ast::Stmt * result = new ast::ReturnStmt(loc,
+		ast::ConstantExpr::from_bool( loc, false )
+		);
+	result->labels = throwStmt->labels;
+	return result;
+}
+
+// Visiting/Mutating Functions
+void TryMutatorCore::previsit( const ast::StructDecl *structDecl ) {
+	if ( !structDecl->body ) {
+		// Skip children?
+		return;
+	} else if ( structDecl->name == "__cfaehm_base_exception_t" ) {
+		assert( nullptr == except_decl );
+		except_decl = structDecl;
+	} else if ( structDecl->name == "__cfaehm_try_resume_node" ) {
+		assert( nullptr == node_decl );
+		node_decl = structDecl;
+	} else if ( structDecl->name == "__cfaehm_cleanup_hook" ) {
+		assert( nullptr == hook_decl );
+		hook_decl = structDecl;
+	}
+}
+
+ast::Stmt * TryMutatorCore::postvisit( const ast::TryStmt *tryStmt ) {
+	assert( except_decl );
+	assert( node_decl );
+	assert( hook_decl );
+
+	const CodeLocation loc = tryStmt->location;
+	ast::TryStmt * mutStmt = mutate(tryStmt);
+	// Generate a prefix for the function names?
+
+	ast::CompoundStmt * block = new ast::CompoundStmt( loc );
+	// ast::CompoundStmt * inner = take_try_block( mutStmt );
+	// this is never mutated so let node deletion do its job?
+	const ast::CompoundStmt * inner = mutStmt->body;
+
+	if ( mutStmt->finally ) {
+		// Define the helper function.
+		ast::FunctionDecl * finally_block =
+			create_finally_wrapper( mutStmt );
+		appendDeclStmt( block, finally_block );
+		// Create and add the finally cleanup hook.
+		appendDeclStmt( block, create_finally_hook( finally_block ) );
+	}
+
+	CatchList termination_handlers;
+	CatchList resumption_handlers;
+
+	for (auto & handler: mutStmt->handlers) {
+		// xxx - should always be unique? mutate as safe const-cast
+		assert(handler->unique());
+		if (handler->kind == ast::ExceptionKind::Resume) {
+			resumption_handlers.push_back(handler.get_and_mutate());
+		}
+		else {
+			termination_handlers.push_back(handler.get_and_mutate());
+		}
+	}
+
+	if ( resumption_handlers.size() ) {
+		// Define the helper function.
+		ast::FunctionDecl * resume_handler =
+			create_resume_handler( resumption_handlers );
+		appendDeclStmt( block, resume_handler );
+		// Prepare hooks
+		inner = create_resume_wrapper( inner, resume_handler );
+	}
+
+	if ( termination_handlers.size() ) {
+		// Define the three helper functions.
+		ast::FunctionDecl * try_wrapper = create_try_wrapper( inner );
+		appendDeclStmt( block, try_wrapper );
+		ast::FunctionDecl * terminate_catch =
+			create_terminate_catch( termination_handlers );
+		appendDeclStmt( block, terminate_catch );
+		ast::FunctionDecl * terminate_match =
+			create_terminate_match( termination_handlers );
+		appendDeclStmt( block, terminate_match );
+		// Build the call to the try wrapper.
+		inner = create_terminate_caller(inner->location,
+			try_wrapper, terminate_catch, terminate_match );
+	}
+
+	// Embed the try block.
+	block->push_back( inner );
+
+	return block;
+}
+
+ast::Stmt * TryMutatorCore::postvisit( const ast::ThrowStmt *throwStmt ) {
+	// Only valid `throwResume;` statements should remain. (2/3 checks)
+	assert( ast::ExceptionKind::Resume == throwStmt->kind && ! throwStmt->expr );
+	return create_resume_rethrow( throwStmt );
+}
+
+} // namespace
+
+void translateThrows( ast::TranslationUnit & transUnit ) {
+	ast::Pass<TranslateThrowsCore>::run( transUnit );
+}
+
+void translateTries( ast::TranslationUnit & transUnit ) {
+	ast::Pass<TryMutatorCore>::run(transUnit);
+}
+
+} // namespace ControlStruct
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/ControlStruct/ExceptTranslateNew.cpp
===================================================================
--- src/ControlStruct/ExceptTranslateNew.cpp	(revision 37273c8cb34ce14d7da1cb9d4d43491327ff6807)
+++ 	(revision )
@@ -1,725 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// ExceptTranslateNew.cpp -- Conversion of exception control flow structures.
-//
-// Author           : Andrew Beach
-// Created On       : Mon Nov  8 11:53:00 2021
-// Last Modified By : Andrew Beach
-// Last Modified On : Fri Mar 11 17:51:00 2022
-// Update Count     : 2
-//
-
-#include "ExceptTranslate.h"
-
-#include "AST/Expr.hpp"
-#include "AST/Pass.hpp"
-#include "AST/Stmt.hpp"
-#include "AST/TranslationUnit.hpp"
-#include "AST/DeclReplacer.hpp"
-
-namespace ControlStruct {
-
-namespace {
-
-	typedef std::list<ast::CatchClause*> CatchList;
-
-	void appendDeclStmt( ast::CompoundStmt * block, ast::DeclWithType * item ) {
-		block->push_back(new ast::DeclStmt(block->location, item));
-	}
-
-class TranslateThrowsCore final : public ast::WithGuards {
-	const ast::ObjectDecl * terminateHandlerExcept;
-	enum Context { NoHandler, TerHandler, ResHandler } currentContext;
-
-	const ast::Stmt * createEitherThrow(
-		const ast::ThrowStmt * throwStmt, const char * funcName );
-	const ast::Stmt * createTerminateRethrow( const ast::ThrowStmt * );
-
-public:
-	TranslateThrowsCore() :
-		terminateHandlerExcept( nullptr ), currentContext( NoHandler )
-	{}
-
-	void previsit( const ast::CatchClause * stmt );
-	const ast::Stmt * postvisit( const ast::ThrowStmt * stmt );
-};
-
-const ast::Stmt * TranslateThrowsCore::createEitherThrow(
-		const ast::ThrowStmt * throwStmt, const char * funcName ) {
-	// `throwFunc`( `throwStmt->name` );
-	ast::UntypedExpr * call = new ast::UntypedExpr( throwStmt->location,
-		new ast::NameExpr( throwStmt->location, funcName )
-	);
-	call->args.push_back( throwStmt->expr );
-	return new ast::ExprStmt( throwStmt->location, call );
-}
-
-ast::VariableExpr * varOf( const ast::DeclWithType * decl ) {
-	return new ast::VariableExpr( decl->location, decl );
-}
-
-const ast::Stmt * TranslateThrowsCore::createTerminateRethrow(
-		const ast::ThrowStmt * stmt ) {
-	// { `terminate_handler_except` = 0p; __rethrow_terminate(); }
-	assert( nullptr == stmt->expr );
-	assert( terminateHandlerExcept );
-
-	ast::CompoundStmt * result = new ast::CompoundStmt(
-		stmt->location, {}, std::vector<ast::Label>( stmt->labels ) );
-	result->push_back( new ast::ExprStmt( stmt->location,
-		ast::UntypedExpr::createAssign(
-			stmt->location,
-			varOf( terminateHandlerExcept ),
-			ast::ConstantExpr::null(
-				stmt->location,
-				terminateHandlerExcept->type
-			)
-		)
-	) );
-	result->push_back( new ast::ExprStmt( stmt->location, new ast::UntypedExpr(
-		stmt->location,
-		new ast::NameExpr( stmt->location, "__cfaehm_rethrow_terminate" )
-	) ) );
-	return result;
-}
-
-void TranslateThrowsCore::previsit( const ast::CatchClause * stmt ) {
-	// Validate the statement's form.
-	const ast::ObjectDecl * decl = stmt->decl.as<ast::ObjectDecl>();
-	// Also checking the type would be nice.
-	if ( !decl || !decl->type.as<ast::PointerType>() ) {
-		std::string kind = (ast::Terminate == stmt->kind) ? "catch" : "catchResume";
-		SemanticError( stmt->location, kind + " must have pointer to an exception type" );
-	}
-
-	// Track the handler context.
-	if ( ast::Terminate == stmt->kind ) {
-		GuardValue( currentContext ) = TerHandler;
-		GuardValue( terminateHandlerExcept ) = decl;
-	} else {
-		GuardValue( currentContext ) = ResHandler;
-	}
-}
-
-const ast::Stmt * TranslateThrowsCore::postvisit(
-		const ast::ThrowStmt * stmt ) {
-	// Ignoring ThrowStmt::target for now.
-	// Handle Termination (Raise, Reraise, Error):
-	if ( ast::Terminate == stmt->kind ) {
-		if ( stmt->expr ) {
-			return createEitherThrow( stmt, "$throw" );
-		} else if ( TerHandler == currentContext ) {
-			return createTerminateRethrow( stmt );
-		} else {
-			abort( "Invalid throw in %s at %i\n",
-				stmt->location.filename.c_str(),
-				stmt->location.first_line);
-		}
-	// Handle Resumption (Raise, Reraise, Error):
-	} else {
-		if ( stmt->expr ) {
-			return createEitherThrow( stmt, "$throwResume" );
-		} else if ( ResHandler == currentContext ) {
-			// This has to be handled later.
-			return stmt;
-		} else {
-			abort( "Invalid throwResume in %s at %i\n",
-				stmt->location.filename.c_str(),
-				stmt->location.first_line);
-		}
-	}
-}
-
-
-class TryMutatorCore final {
-	// The built in types used in translation.
-	const ast::StructDecl * except_decl;
-	const ast::StructDecl * node_decl;
-	const ast::StructDecl * hook_decl;
-
-	// The many helper functions for code/syntree generation.
-	ast::CompoundStmt * take_try_block( ast::TryStmt * tryStmt );
-	ast::FunctionDecl * create_try_wrapper( const ast::CompoundStmt * body );
-	ast::FunctionDecl * create_terminate_catch( CatchList &handlers );
-	ast::CompoundStmt * create_single_matcher(
-		const ast::DeclWithType * except_obj, ast::CatchClause * modded_handler );
-	ast::FunctionDecl * create_terminate_match( CatchList &handlers );
-	ast::CompoundStmt * create_terminate_caller( CodeLocation loc, ast::FunctionDecl * try_wrapper,
-		ast::FunctionDecl * terminate_catch, ast::FunctionDecl * terminate_match );
-	ast::FunctionDecl * create_resume_handler( CatchList &handlers );
-	ast::CompoundStmt * create_resume_wrapper(
-		const ast::Stmt * wraps, const ast::FunctionDecl * resume_handler );
-	ast::FunctionDecl * create_finally_wrapper( ast::TryStmt * tryStmt );
-	ast::ObjectDecl * create_finally_hook( ast::FunctionDecl * finally_wrapper );
-	ast::Stmt * create_resume_rethrow( const ast::ThrowStmt * throwStmt );
-
-	// Types used in translation, first group are internal.
-	ast::ObjectDecl * make_index_object( CodeLocation const & ) const;
-	ast::ObjectDecl * make_exception_object( CodeLocation const & ) const;
-	ast::ObjectDecl * make_bool_object( CodeLocation const & ) const;
-	ast::ObjectDecl * make_voidptr_object( CodeLocation const & ) const;
-	ast::ObjectDecl * make_unused_index_object( CodeLocation const & ) const;
-	// void (*function)();
-	ast::FunctionDecl * make_try_function( CodeLocation const & ) const;
-	// void (*function)(int, exception);
-	ast::FunctionDecl * make_catch_function( CodeLocation const & ) const;
-	// int (*function)(exception);
-	ast::FunctionDecl * make_match_function( CodeLocation const & ) const;
-	// bool (*function)(exception);
-	ast::FunctionDecl * make_handle_function( CodeLocation const & ) const;
-	// void (*function)(__attribute__((unused)) void *);
-	ast::FunctionDecl * make_finally_function( CodeLocation const & ) const;
-
-public:
-	TryMutatorCore() :
-		except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr )
-	{}
-
-	void previsit( const ast::StructDecl *structDecl );
-	ast::Stmt * postvisit( const ast::TryStmt *tryStmt );
-	ast::Stmt * postvisit( const ast::ThrowStmt *throwStmt );
-};
-
-ast::ObjectDecl * TryMutatorCore::make_index_object(
-		CodeLocation const & location ) const {
-	return new ast::ObjectDecl(
-		location,
-		"__handler_index",
-		new ast::BasicType( ast::BasicType::SignedInt )
-		);
-}
-
-ast::ObjectDecl * TryMutatorCore::make_exception_object(
-		CodeLocation const & location ) const {
-	assert( except_decl );
-	return new ast::ObjectDecl(
-		location,
-		"__exception_inst",
-		new ast::PointerType( new ast::StructInstType( except_decl ) )
-		);
-}
-
-ast::ObjectDecl * TryMutatorCore::make_bool_object(
-		CodeLocation const & location ) const {
-	return new ast::ObjectDecl(
-		location,
-		"__ret_bool",
-		new ast::BasicType( ast::BasicType::Bool ),
-		nullptr, //init
-		ast::Storage::Classes{},
-		ast::Linkage::Cforall,
-		nullptr, //width
-		std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
-		);
-}
-
-ast::ObjectDecl * TryMutatorCore::make_voidptr_object(
-		CodeLocation const & location ) const {
-	return new ast::ObjectDecl(
-		location,
-		"__hook",
-		new ast::PointerType(
-			new ast::VoidType()
-		),
-		nullptr, //init
-		ast::Storage::Classes{},
-		ast::Linkage::Cforall,
-		nullptr, //width
-		std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
-		);
-}
-
-ast::ObjectDecl * TryMutatorCore::make_unused_index_object(
-		CodeLocation const & location ) const {
-	return new ast::ObjectDecl(
-		location,
-		"__handler_index",
-		new ast::BasicType(ast::BasicType::SignedInt),
-		nullptr,
-		ast::Storage::Classes{},
-		ast::Linkage::Cforall,
-		nullptr, //width
-		std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
-	);
-}
-
-ast::FunctionDecl * TryMutatorCore::make_try_function(
-		CodeLocation const & location ) const {
-	return new ast::FunctionDecl(
-		location,
-		"try",
-		{}, //no param
-		{}, //no return
-		nullptr,
-		ast::Storage::Classes{},
-		ast::Linkage::Cforall
-	);
-}
-
-ast::FunctionDecl * TryMutatorCore::make_catch_function(
-		CodeLocation const & location ) const {
-	return new ast::FunctionDecl(
-		location,
-		"catch",
-		{ make_index_object( location ), make_exception_object( location ) },
-		{}, //return void
-		nullptr,
-		ast::Storage::Classes{},
-		ast::Linkage::Cforall
-	);
-}
-
-ast::FunctionDecl * TryMutatorCore::make_match_function(
-		CodeLocation const & location ) const {
-	return new ast::FunctionDecl(
-		location,
-		"match",
-		{ make_exception_object( location ) },
-		{ make_unused_index_object( location ) },
-		nullptr,
-		ast::Storage::Classes{},
-		ast::Linkage::Cforall
-	);
-}
-
-ast::FunctionDecl * TryMutatorCore::make_handle_function(
-		CodeLocation const & location ) const {
-	return new ast::FunctionDecl(
-		location,
-		"handle",
-		{ make_exception_object( location ) },
-		{ make_bool_object( location ) },
-		nullptr,
-		ast::Storage::Classes{},
-		ast::Linkage::Cforall
-	);
-}
-
-ast::FunctionDecl * TryMutatorCore::make_finally_function(
-		CodeLocation const & location ) const {
-	return new ast::FunctionDecl(
-		location,
-		"finally",
-		{ make_voidptr_object( location ) },
-		{}, //return void
-		nullptr,
-		ast::Storage::Classes{},
-		ast::Linkage::Cforall,
-		{},
-		{ ast::Function::Inline }
-	);
-}
-
-// TryStmt Mutation Helpers
-
-ast::FunctionDecl * TryMutatorCore::create_try_wrapper(
-		const ast::CompoundStmt *body ) {
-
-	ast::FunctionDecl * ret = make_try_function( body->location );
-	ret->stmts = body;
-	return ret;
-}
-
-ast::FunctionDecl * TryMutatorCore::create_terminate_catch(
-		CatchList &handlers ) {
-	std::vector<ast::ptr<ast::CaseClause>> handler_wrappers;
-
-	assert (!handlers.empty());
-	const CodeLocation loc = handlers.front()->location;
-
-	ast::FunctionDecl * func_t = make_catch_function( loc );
-	const ast::DeclWithType * index_obj = func_t->params.front();
-	const ast::DeclWithType * except_obj = func_t->params.back();
-
-	// Index 1..{number of handlers}
-	int index = 0;
-	CatchList::iterator it = handlers.begin();
-	for ( ; it != handlers.end() ; ++it ) {
-		++index;
-		ast::CatchClause * handler = *it;
-		const CodeLocation loc = handler->location;
-
-		// case `index`:
-		// {
-		//     `handler.decl` = { (virtual `decl.type`)`except` };
-		//     `handler.body`;
-		// }
-		// return;
-		ast::CompoundStmt * block = new ast::CompoundStmt(loc);
-
-		// Just copy the exception value. (Post Validation)
-		const ast::ObjectDecl * handler_decl =
-			handler->decl.strict_as<ast::ObjectDecl>();
-		ast::ObjectDecl * local_except = ast::deepCopy(handler_decl);
-		ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc,
-			new ast::VariableExpr( loc, except_obj ),
-			local_except->get_type()
-			);
-		vcex->location = handler->location;
-		local_except->init = new ast::ListInit(loc, { new ast::SingleInit( loc, vcex ) });
-		block->push_back( new ast::DeclStmt( loc, local_except ) );
-
-		// Add the cleanup attribute.
-		local_except->attributes.push_back( new ast::Attribute(
-			"cleanup",
-			{ new ast::NameExpr( loc, "__cfaehm_cleanup_terminate" ) }
-			) );
-
-		ast::DeclReplacer::DeclMap mapping;
-		mapping[handler_decl] = local_except;
-		const ast::Stmt * mutBody = strict_dynamic_cast<const ast::Stmt *>(
-			ast::DeclReplacer::replace(handler->body, mapping));
-
-
-		block->push_back( mutBody );
-		// handler->body = nullptr;
-
-		handler_wrappers.push_back( new ast::CaseClause(loc,
-			ast::ConstantExpr::from_int(loc, index) ,
-			{ block, new ast::ReturnStmt( loc, nullptr ) }
-			));
-	}
-	// TODO: Some sort of meaningful error on default perhaps?
-
-	ast::SwitchStmt * handler_lookup = new ast::SwitchStmt( loc,
-		new ast::VariableExpr( loc, index_obj ),
-		std::move(handler_wrappers)
-		);
-	ast::CompoundStmt * body = new ast::CompoundStmt( loc, {handler_lookup} );
-
-	func_t->stmts = body;
-	return func_t;
-}
-
-// Create a single check from a moddified handler.
-// except_obj is referenced, modded_handler will be freed.
-ast::CompoundStmt * TryMutatorCore::create_single_matcher(
-		const ast::DeclWithType * except_obj, ast::CatchClause * modded_handler ) {
-	// {
-	//     `modded_handler.decl`
-	//     if ( `decl.name = (virtual `decl.type`)`except`
-	//             [&& `modded_handler.cond`] ) {
-	//         `modded_handler.body`
-	//     }
-	// }
-
-	const CodeLocation loc = modded_handler->location;
-	ast::CompoundStmt * block = new ast::CompoundStmt(loc);
-
-	// Local Declaration
-	const ast::ObjectDecl * local_except =
-		modded_handler->decl.strict_as<ast::ObjectDecl>();
-	block->push_back( new ast::DeclStmt( loc,  local_except ) );
-
-	// Check for type match.
-	ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc,
-		new ast::VariableExpr(loc, except_obj ),
-		local_except->get_type()
-		);
-	ast::Expr * cond = ast::UntypedExpr::createAssign(loc,
-		new ast::VariableExpr(loc, local_except ), vcex );
-
-	// Add the check on the conditional if it is provided.
-	if ( modded_handler->cond ) {
-		cond = new ast::LogicalExpr( loc, cond, modded_handler->cond, ast::LogicalFlag::AndExpr );
-	}
-	// Construct the match condition.
-	block->push_back( new ast::IfStmt(loc,
-		cond, modded_handler->body, nullptr ) );
-
-	return block;
-}
-
-ast::FunctionDecl * TryMutatorCore::create_terminate_match(
-		CatchList &handlers ) {
-	// int match(exception * except) {
-	//     HANDLER WRAPPERS { return `index`; }
-	// }
-
-	assert (!handlers.empty());
-	const CodeLocation loc = handlers.front()->location;
-
-	ast::CompoundStmt * body = new ast::CompoundStmt(loc);
-
-	ast::FunctionDecl * func_t = make_match_function( loc );
-	const ast::DeclWithType * except_obj = func_t->params.back();
-
-	// Index 1..{number of handlers}
-	int index = 0;
-	CatchList::iterator it;
-	for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
-		++index;
-		ast::CatchClause * handler = *it;
-
-		// Body should have been taken by create_terminate_catch.
-		// xxx - just ignore it?
-		// assert( nullptr == handler->get_body() );
-
-		// Create new body.
-		handler->body = new ast::ReturnStmt( handler->location,
-			ast::ConstantExpr::from_int( handler->location, index ) );
-
-		// Create the handler.
-		body->push_back( create_single_matcher( except_obj, handler ) );
-		*it = nullptr;
-	}
-
-	body->push_back( new ast::ReturnStmt(loc,
-		ast::ConstantExpr::from_int( loc, 0 ) ));
-
-	func_t->stmts = body;
-
-	return func_t;
-}
-
-ast::CompoundStmt * TryMutatorCore::create_terminate_caller(
-		CodeLocation loc,
-		ast::FunctionDecl * try_wrapper,
-		ast::FunctionDecl * terminate_catch,
-		ast::FunctionDecl * terminate_match ) {
-	// { __cfaehm_try_terminate(`try`, `catch`, `match`); }
-
-	ast::UntypedExpr * caller = new ast::UntypedExpr(loc, new ast::NameExpr(loc,
-		"__cfaehm_try_terminate" ) );
-	caller->args.push_back( new ast::VariableExpr(loc, try_wrapper ) );
-	caller->args.push_back( new ast::VariableExpr(loc, terminate_catch ) );
-	caller->args.push_back( new ast::VariableExpr(loc, terminate_match ) );
-
-	ast::CompoundStmt * callStmt = new ast::CompoundStmt(loc);
-	callStmt->push_back( new ast::ExprStmt( loc, caller ) );
-	return callStmt;
-}
-
-ast::FunctionDecl * TryMutatorCore::create_resume_handler(
-		CatchList &handlers ) {
-	// bool handle(exception * except) {
-	//     HANDLER WRAPPERS { `hander->body`; return true; }
-	// }
-	assert (!handlers.empty());
-	const CodeLocation loc = handlers.front()->location;
-	ast::CompoundStmt * body = new ast::CompoundStmt(loc);
-
-	ast::FunctionDecl * func_t = make_handle_function( loc );
-	const ast::DeclWithType * except_obj = func_t->params.back();
-
-	CatchList::iterator it;
-	for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
-		ast::CatchClause * handler = *it;
-		const CodeLocation loc = handler->location;
-		// Modifiy body.
-		ast::CompoundStmt * handling_code;
-		if (handler->body.as<ast::CompoundStmt>()) {
-			handling_code = strict_dynamic_cast<ast::CompoundStmt*>(
-				handler->body.get_and_mutate() );
-		} else {
-			handling_code = new ast::CompoundStmt(loc);
-			handling_code->push_back( handler->body );
-		}
-		handling_code->push_back( new ast::ReturnStmt(loc,
-			ast::ConstantExpr::from_bool(loc, true ) ) );
-		handler->body = handling_code;
-
-		// Create the handler.
-		body->push_back( create_single_matcher( except_obj, handler ) );
-		*it = nullptr;
-	}
-
-	body->push_back( new ast::ReturnStmt(loc,
-		ast::ConstantExpr::from_bool(loc, false ) ) );
-	func_t->stmts = body;
-
-	return func_t;
-}
-
-ast::CompoundStmt * TryMutatorCore::create_resume_wrapper(
-		const ast::Stmt * wraps,
-		const ast::FunctionDecl * resume_handler ) {
-	const CodeLocation loc = wraps->location;
-	ast::CompoundStmt * body = new ast::CompoundStmt(loc);
-
-	// struct __try_resume_node __resume_node
-	//  	__attribute__((cleanup( __cfaehm_try_resume_cleanup )));
-	// ** unwinding of the stack here could cause problems **
-	// ** however I don't think that can happen currently **
-	// __cfaehm_try_resume_setup( &__resume_node, resume_handler );
-
-	ast::ObjectDecl * obj = new ast::ObjectDecl(
-		loc,
-		"__resume_node",
-		new ast::StructInstType(
-			node_decl
-			),
-		nullptr,
-		ast::Storage::Classes{},
-		ast::Linkage::Cforall,
-		nullptr,
-		{new ast::Attribute("cleanup", {new ast::NameExpr(loc, "__cfaehm_try_resume_cleanup")})}
-		);
-	appendDeclStmt( body, obj );
-
-	ast::UntypedExpr *setup = new ast::UntypedExpr(loc, new ast::NameExpr(loc,
-		"__cfaehm_try_resume_setup" ) );
-	setup->args.push_back( new ast::AddressExpr( loc, new ast::VariableExpr(loc, obj ) ) );
-	setup->args.push_back( new ast::VariableExpr( loc, resume_handler ) );
-
-	body->push_back( new ast::ExprStmt(loc, setup ) );
-
-	body->push_back( wraps );
-	return body;
-}
-
-ast::FunctionDecl * TryMutatorCore::create_finally_wrapper(
-		ast::TryStmt * tryStmt ) {
-	// void finally() { `finally->block` }
-	const ast::FinallyClause * finally = tryStmt->finally;
-	const ast::CompoundStmt * body = finally->body;
-
-	ast::FunctionDecl * func_t = make_finally_function( tryStmt->location );
-	func_t->stmts = body;
-
-	tryStmt->finally = nullptr;
-
-	return func_t;
-}
-
-ast::ObjectDecl * TryMutatorCore::create_finally_hook(
-		ast::FunctionDecl * finally_wrapper ) {
-	// struct __cfaehm_cleanup_hook __finally_hook
-	//   	__attribute__((cleanup( `finally_wrapper` )));
-
-	const CodeLocation loc = finally_wrapper->location;
-	return new ast::ObjectDecl(
-		loc,
-		"__finally_hook",
-		new ast::StructInstType(
-			hook_decl
-			),
-		nullptr,
-		ast::Storage::Classes{},
-		ast::Linkage::Cforall,
-		nullptr,
-		{new ast::Attribute("cleanup", {new ast::VariableExpr{loc, finally_wrapper}})}
-		);
-}
-
-ast::Stmt * TryMutatorCore::create_resume_rethrow( const ast::ThrowStmt *throwStmt ) {
-	// return false;
-	const CodeLocation loc = throwStmt->location;
-	ast::Stmt * result = new ast::ReturnStmt(loc,
-		ast::ConstantExpr::from_bool( loc, false )
-		);
-	result->labels = throwStmt->labels;
-	return result;
-}
-
-// Visiting/Mutating Functions
-void TryMutatorCore::previsit( const ast::StructDecl *structDecl ) {
-	if ( !structDecl->body ) {
-		// Skip children?
-		return;
-	} else if ( structDecl->name == "__cfaehm_base_exception_t" ) {
-		assert( nullptr == except_decl );
-		except_decl = structDecl;
-	} else if ( structDecl->name == "__cfaehm_try_resume_node" ) {
-		assert( nullptr == node_decl );
-		node_decl = structDecl;
-	} else if ( structDecl->name == "__cfaehm_cleanup_hook" ) {
-		assert( nullptr == hook_decl );
-		hook_decl = structDecl;
-	}
-}
-
-ast::Stmt * TryMutatorCore::postvisit( const ast::TryStmt *tryStmt ) {
-	assert( except_decl );
-	assert( node_decl );
-	assert( hook_decl );
-
-	const CodeLocation loc = tryStmt->location;
-	ast::TryStmt * mutStmt = mutate(tryStmt);
-	// Generate a prefix for the function names?
-
-	ast::CompoundStmt * block = new ast::CompoundStmt( loc );
-	// ast::CompoundStmt * inner = take_try_block( mutStmt );
-	// this is never mutated so let node deletion do its job?
-	const ast::CompoundStmt * inner = mutStmt->body;
-
-	if ( mutStmt->finally ) {
-		// Define the helper function.
-		ast::FunctionDecl * finally_block =
-			create_finally_wrapper( mutStmt );
-		appendDeclStmt( block, finally_block );
-		// Create and add the finally cleanup hook.
-		appendDeclStmt( block, create_finally_hook( finally_block ) );
-	}
-
-	CatchList termination_handlers;
-	CatchList resumption_handlers;
-
-	for (auto & handler: mutStmt->handlers) {
-		// xxx - should always be unique? mutate as safe const-cast
-		assert(handler->unique());
-		if (handler->kind == ast::ExceptionKind::Resume) {
-			resumption_handlers.push_back(handler.get_and_mutate());
-		}
-		else {
-			termination_handlers.push_back(handler.get_and_mutate());
-		}
-	}
-
-	if ( resumption_handlers.size() ) {
-		// Define the helper function.
-		ast::FunctionDecl * resume_handler =
-			create_resume_handler( resumption_handlers );
-		appendDeclStmt( block, resume_handler );
-		// Prepare hooks
-		inner = create_resume_wrapper( inner, resume_handler );
-	}
-
-	if ( termination_handlers.size() ) {
-		// Define the three helper functions.
-		ast::FunctionDecl * try_wrapper = create_try_wrapper( inner );
-		appendDeclStmt( block, try_wrapper );
-		ast::FunctionDecl * terminate_catch =
-			create_terminate_catch( termination_handlers );
-		appendDeclStmt( block, terminate_catch );
-		ast::FunctionDecl * terminate_match =
-			create_terminate_match( termination_handlers );
-		appendDeclStmt( block, terminate_match );
-		// Build the call to the try wrapper.
-		inner = create_terminate_caller(inner->location,
-			try_wrapper, terminate_catch, terminate_match );
-	}
-
-	// Embed the try block.
-	block->push_back( inner );
-
-	return block;
-}
-
-ast::Stmt * TryMutatorCore::postvisit( const ast::ThrowStmt *throwStmt ) {
-	// Only valid `throwResume;` statements should remain. (2/3 checks)
-	assert( ast::ExceptionKind::Resume == throwStmt->kind && ! throwStmt->expr );
-	return create_resume_rethrow( throwStmt );
-}
-
-} // namespace
-
-void translateThrows( ast::TranslationUnit & transUnit ) {
-	ast::Pass<TranslateThrowsCore>::run( transUnit );
-}
-
-void translateTries( ast::TranslationUnit & transUnit ) {
-	ast::Pass<TryMutatorCore>::run(transUnit);
-}
-
-} // namespace ControlStruct
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/ControlStruct/LabelGenerator.cpp
===================================================================
--- src/ControlStruct/LabelGenerator.cpp	(revision 4dc3b8c90f62876e9e5e2b84283aebb28622582a)
+++ src/ControlStruct/LabelGenerator.cpp	(revision 4dc3b8c90f62876e9e5e2b84283aebb28622582a)
@@ -0,0 +1,71 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// LabelGenerator.cpp --
+//
+// Author           : Peter A. Buhr
+// Created On       : Mon May 18 07:44:20 2015
+// Last Modified By : Andrew Beach
+// Last Modified On : Mon Mar 28 10:03:00 2022
+// Update Count     : 73
+//
+
+#include "LabelGenerator.hpp"
+
+#include "AST/Attribute.hpp"
+#include "AST/Label.hpp"
+#include "AST/Stmt.hpp"
+
+using namespace std;
+using namespace ast;
+
+namespace ControlStruct {
+
+enum { size = 128 };
+
+static int newLabelPre( char buf[size], const string & suffix ) {
+	static int current = 0;
+
+	int len = snprintf( buf, size, "__L%d__%s", current++, suffix.c_str() );
+	assertf( len < size, "CFA Internal error: buffer overflow creating label" );
+	return len;
+}
+
+static Label newLabelPost( char buf[size], const CodeLocation & location ) {
+	Label ret_label( location, buf );
+	ret_label.attributes.push_back( new Attribute( "unused" ) );
+	return ret_label;
+}
+
+Label newLabel( const string & suffix, const Stmt * stmt ) {
+	// Buffer for string manipulation.
+	char buf[size];
+
+	assertf( stmt, "CFA internal error: parameter statement cannot be null pointer" );
+	int len = newLabelPre( buf, suffix );
+
+	// What does this do?
+	if ( ! stmt->labels.empty() ) {
+		len = snprintf( buf + len, size - len, "_%s__", stmt->labels.front().name.c_str() );
+		assertf( len < size - len, "CFA Internal error: buffer overflow creating label" );
+	} // if
+
+	return newLabelPost( buf, stmt->location );
+}
+
+Label newLabel( const string & suffix, const CodeLocation & location ) {
+	// Buffer for string manipulation.
+	char buf[size];
+
+	newLabelPre( buf, suffix );
+	return newLabelPost( buf, location );
+}
+
+} // namespace ControlStruct
+
+// Local Variables: //
+// mode: c++ //
+// End: //
Index: src/ControlStruct/LabelGenerator.hpp
===================================================================
--- src/ControlStruct/LabelGenerator.hpp	(revision 4dc3b8c90f62876e9e5e2b84283aebb28622582a)
+++ src/ControlStruct/LabelGenerator.hpp	(revision 4dc3b8c90f62876e9e5e2b84283aebb28622582a)
@@ -0,0 +1,38 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// LabelGenerator.hpp --
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Mon May 18 07:44:20 2015
+// Last Modified By : Andrew Beach
+// Last Modified On : Fir Mar 25 15:40:00 2022
+// Update Count     : 28
+//
+
+#pragma once
+
+#include <string>										// for string
+
+struct CodeLocation;
+
+namespace ast {
+	class Label;
+	class Stmt;
+} // namespace ast
+
+namespace ControlStruct {
+
+ast::Label newLabel( const std::string &, const ast::Stmt * );
+ast::Label newLabel( const std::string &, const CodeLocation & );
+
+} // namespace ControlStruct
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/ControlStruct/LabelGeneratorNew.cpp
===================================================================
--- src/ControlStruct/LabelGeneratorNew.cpp	(revision 37273c8cb34ce14d7da1cb9d4d43491327ff6807)
+++ 	(revision )
@@ -1,71 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// LabelGeneratorNew.cpp --
-//
-// Author           : Peter A. Buhr
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Mar 28 10:03:00 2022
-// Update Count     : 73
-//
-
-#include "LabelGeneratorNew.hpp"
-
-#include "AST/Attribute.hpp"
-#include "AST/Label.hpp"
-#include "AST/Stmt.hpp"
-
-using namespace std;
-using namespace ast;
-
-namespace ControlStruct {
-
-enum { size = 128 };
-
-static int newLabelPre( char buf[size], const string & suffix ) {
-	static int current = 0;
-
-	int len = snprintf( buf, size, "__L%d__%s", current++, suffix.c_str() );
-	assertf( len < size, "CFA Internal error: buffer overflow creating label" );
-	return len;
-}
-
-static Label newLabelPost( char buf[size], const CodeLocation & location ) {
-	Label ret_label( location, buf );
-	ret_label.attributes.push_back( new Attribute( "unused" ) );
-	return ret_label;
-}
-
-Label newLabel( const string & suffix, const Stmt * stmt ) {
-	// Buffer for string manipulation.
-	char buf[size];
-
-	assertf( stmt, "CFA internal error: parameter statement cannot be null pointer" );
-	int len = newLabelPre( buf, suffix );
-
-	// What does this do?
-	if ( ! stmt->labels.empty() ) {
-		len = snprintf( buf + len, size - len, "_%s__", stmt->labels.front().name.c_str() );
-		assertf( len < size - len, "CFA Internal error: buffer overflow creating label" );
-	} // if
-
-	return newLabelPost( buf, stmt->location );
-}
-
-Label newLabel( const string & suffix, const CodeLocation & location ) {
-	// Buffer for string manipulation.
-	char buf[size];
-
-	newLabelPre( buf, suffix );
-	return newLabelPost( buf, location );
-}
-
-} // namespace ControlStruct
-
-// Local Variables: //
-// mode: c++ //
-// End: //
Index: src/ControlStruct/LabelGeneratorNew.hpp
===================================================================
--- src/ControlStruct/LabelGeneratorNew.hpp	(revision 37273c8cb34ce14d7da1cb9d4d43491327ff6807)
+++ 	(revision )
@@ -1,36 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// LabelGenerator.h --
-//
-// Author           : Rodolfo G. Esteves
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Fir Mar 25 15:40:00 2022
-// Update Count     : 28
-//
-
-#pragma once
-
-#include <string>										// for string
-
-struct CodeLocation;
-
-namespace ast {
-	class Label;
-	class Stmt;
-} // namespace ast
-
-namespace ControlStruct {
-	ast::Label newLabel( const std::string &, const ast::Stmt * );
-	ast::Label newLabel( const std::string &, const CodeLocation & );
-} // namespace ControlStruct
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/ControlStruct/MultiLevelExit.cpp
===================================================================
--- src/ControlStruct/MultiLevelExit.cpp	(revision 37273c8cb34ce14d7da1cb9d4d43491327ff6807)
+++ src/ControlStruct/MultiLevelExit.cpp	(revision 4dc3b8c90f62876e9e5e2b84283aebb28622582a)
@@ -16,9 +16,10 @@
 #include "MultiLevelExit.hpp"
 
+#include <set>
+
 #include "AST/Pass.hpp"
 #include "AST/Stmt.hpp"
-#include "LabelGeneratorNew.hpp"
-
-#include <set>
+#include "LabelGenerator.hpp"
+
 using namespace std;
 using namespace ast;
Index: src/ControlStruct/module.mk
===================================================================
--- src/ControlStruct/module.mk	(revision 37273c8cb34ce14d7da1cb9d4d43491327ff6807)
+++ src/ControlStruct/module.mk	(revision 4dc3b8c90f62876e9e5e2b84283aebb28622582a)
@@ -16,7 +16,7 @@
 
 SRC += \
-	ControlStruct/ExceptDeclNew.cpp \
+	ControlStruct/ExceptDecl.cpp \
 	ControlStruct/ExceptDecl.h \
-	ControlStruct/ExceptTranslateNew.cpp \
+	ControlStruct/ExceptTranslate.cpp \
 	ControlStruct/ExceptTranslate.h \
 	ControlStruct/FixLabels.cpp \
@@ -24,6 +24,6 @@
 	ControlStruct/HoistControlDecls.cpp \
 	ControlStruct/HoistControlDecls.hpp \
-	ControlStruct/LabelGeneratorNew.cpp \
-	ControlStruct/LabelGeneratorNew.hpp \
+	ControlStruct/LabelGenerator.cpp \
+	ControlStruct/LabelGenerator.hpp \
 	ControlStruct/MultiLevelExit.cpp \
 	ControlStruct/MultiLevelExit.hpp
