Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/AST/Expr.cpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -102,4 +102,29 @@
 	}
 	return ret;
+}
+
+// --- VariableExpr
+
+VariableExpr::VariableExpr( const CodeLocation & loc )
+: Expr( loc ), var( nullptr ) {}
+
+VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
+: Expr( loc ), var( v ) {
+	assert( var );
+	assert( var->get_type() );
+	result = shallowCopy( var->get_type() );
+}
+
+bool VariableExpr::get_lvalue() const {
+	// It isn't always an lvalue, but it is never an rvalue.
+	return true;
+}
+
+VariableExpr * VariableExpr::functionPointer(
+		const CodeLocation & loc, const FunctionDecl * decl ) {
+	// wrap usually-determined result type in a pointer
+	VariableExpr * funcExpr = new VariableExpr{ loc, decl };
+	funcExpr->result = new PointerType{ funcExpr->result };
+	return funcExpr;
 }
 
@@ -238,29 +263,4 @@
 }
 
-// --- VariableExpr
-
-VariableExpr::VariableExpr( const CodeLocation & loc )
-: Expr( loc ), var( nullptr ) {}
-
-VariableExpr::VariableExpr( const CodeLocation & loc, const DeclWithType * v )
-: Expr( loc ), var( v ) {
-	assert( var );
-	assert( var->get_type() );
-	result = shallowCopy( var->get_type() );
-}
-
-bool VariableExpr::get_lvalue() const {
-	// It isn't always an lvalue, but it is never an rvalue.
-	return true;
-}
-
-VariableExpr * VariableExpr::functionPointer(
-		const CodeLocation & loc, const FunctionDecl * decl ) {
-	// wrap usually-determined result type in a pointer
-	VariableExpr * funcExpr = new VariableExpr{ loc, decl };
-	funcExpr->result = new PointerType{ funcExpr->result };
-	return funcExpr;
-}
-
 // --- ConstantExpr
 
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/AST/Expr.hpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -250,4 +250,23 @@
 };
 
+/// A reference to a named variable.
+class VariableExpr final : public Expr {
+public:
+	readonly<DeclWithType> var;
+
+	VariableExpr( const CodeLocation & loc );
+	VariableExpr( const CodeLocation & loc, const DeclWithType * v );
+
+	bool get_lvalue() const final;
+
+	/// generates a function pointer for a given function
+	static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
+
+	const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
+private:
+	VariableExpr * clone() const override { return new VariableExpr{ *this }; }
+	MUTATE_FRIEND
+};
+
 /// Address-of expression `&e`
 class AddressExpr final : public Expr {
@@ -390,23 +409,4 @@
 	friend class ::ConverterOldToNew;
 	friend class ::ConverterNewToOld;
-};
-
-/// A reference to a named variable.
-class VariableExpr final : public Expr {
-public:
-	readonly<DeclWithType> var;
-
-	VariableExpr( const CodeLocation & loc );
-	VariableExpr( const CodeLocation & loc, const DeclWithType * v );
-
-	bool get_lvalue() const final;
-
-	/// generates a function pointer for a given function
-	static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
-
-	const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
-	VariableExpr * clone() const override { return new VariableExpr{ *this }; }
-	MUTATE_FRIEND
 };
 
Index: src/AST/Type.cpp
===================================================================
--- src/AST/Type.cpp	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/AST/Type.cpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -157,4 +157,10 @@
 
 template<typename decl_t>
+SueInstType<decl_t>::SueInstType(
+	const base_type * b, std::vector<ptr<Expr>> && params,
+	CV::Qualifiers q, std::vector<ptr<Attribute>> && as )
+: BaseInstType( b->name, std::move(params), q, std::move(as) ), base( b ) {}
+
+template<typename decl_t>
 bool SueInstType<decl_t>::isComplete() const {
 	return base ? base->body : false;
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/AST/Type.hpp	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -302,7 +302,4 @@
 class FunctionType final : public ParameterizedType {
 public:
-//	std::vector<ptr<DeclWithType>> returns;
-//	std::vector<ptr<DeclWithType>> params;
-
 	std::vector<ptr<Type>> returns;
 	std::vector<ptr<Type>> params;
@@ -345,4 +342,9 @@
 	: ParameterizedType(q, std::move(as)), params(), name(n) {}
 
+	BaseInstType(
+		const std::string& n, std::vector<ptr<Expr>> && params,
+		CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} )
+	: ParameterizedType(q, std::move(as)), params(std::move(params)), name(n) {}
+
 	BaseInstType( const BaseInstType & o );
 
@@ -369,5 +371,9 @@
 
 	SueInstType(
-		const decl_t * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
+		const base_type * b, CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
+
+	SueInstType(
+		const base_type * b, std::vector<ptr<Expr>> && params,
+		CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
 
 	bool isComplete() const override;
Index: src/AST/porting.md
===================================================================
--- src/AST/porting.md	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/AST/porting.md	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -30,4 +30,8 @@
   * Base nodes now override `const Node * accept( Visitor & v ) const = 0` with, e.g. `const Stmt * accept( Visitor & v ) const override = 0`
 * `PassVisitor` is replaced with `ast::Pass`
+  * Most one shot uses can use `ast::Pass::run` and `ast::Pass::read`.
+
+`WithConstTypeSubstitution`
+* `env` => `typeSubs`
 
 ## Structural Changes ##
@@ -146,4 +150,9 @@
   * allows `newObject` as just default settings
 
+`FunctionDecl`
+* `params` and `returns` added.
+  * Contain the declarations of the parameters and return variables.
+  * Types should match (even be shared with) the fields of `type`.
+
 `NamedTypeDecl`
 * `parameters` => `params`
@@ -154,4 +163,7 @@
 `AggregateDecl`
 * `parameters` => `params`
+
+`StructDecl`
+* `makeInst` replaced by better constructor on `StructInstType`.
 
 `Expr`
@@ -245,5 +257,5 @@
 * **TODO** move `kind`, `typeNames` into code generator
 
-`ReferenceToType`
+`ReferenceToType` => `BaseInstType`
 * deleted `get_baseParameters()` from children
   * replace with `aggr() ? aggr()->params : nullptr`
@@ -261,5 +273,10 @@
 * `returnVals` => `returns`
 * `parameters` => `params`
+  * Both now just point at types.
 * `bool isVarArgs;` => `enum ArgumentFlag { FixedArgs, VariableArgs }; ArgumentFlag isVarArgs;`
+
+`SueInstType`
+* Template class, with specializations and using to implement some other types:
+  * `StructInstType`, `UnionInstType` & `EnumInstType`
 
 `TypeInstType`
Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/Concurrency/Keywords.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -66,5 +66,6 @@
 			bool needs_main, AggregateDecl::Aggregate cast_target ) :
 		  type_name( type_name ), field_name( field_name ), getter_name( getter_name ),
-		  context_error( context_error ), vtable_name( getVTableName( exception_name ) ),
+		  context_error( context_error ), exception_name( exception_name ),
+		  vtable_name( getVTableName( exception_name ) ),
 		  needs_main( needs_main ), cast_target( cast_target ) {}
 
@@ -89,4 +90,5 @@
 		const std::string getter_name;
 		const std::string context_error;
+		const std::string exception_name;
 		const std::string vtable_name;
 		bool needs_main;
@@ -95,4 +97,5 @@
 		StructDecl   * type_decl = nullptr;
 		FunctionDecl * dtor_decl = nullptr;
+		StructDecl * except_decl = nullptr;
 		StructDecl * vtable_decl = nullptr;
 	};
@@ -376,4 +379,7 @@
 		else if ( is_target(decl) ) {
 			handle( decl );
+		}
+		else if ( !except_decl && exception_name == decl->name && decl->body ) {
+			except_decl = decl;
 		}
 		else if ( !vtable_decl && vtable_name == decl->name && decl->body ) {
@@ -398,7 +404,11 @@
 			assert( struct_type );
 
-			declsToAddAfter.push_back( Virtual::makeVtableInstance( vtable_decl, {
-				new TypeExpr( struct_type->clone() ),
-			}, struct_type, nullptr ) );
+			std::list< Expression * > poly_args = { new TypeExpr( struct_type->clone() ) };
+			ObjectDecl * vtable_object = Virtual::makeVtableInstance(
+				vtable_decl->makeInst( poly_args ), struct_type, nullptr );
+			declsToAddAfter.push_back( vtable_object );
+			declsToAddAfter.push_back( Virtual::makeGetExceptionFunction(
+				vtable_object, except_decl->makeInst( std::move( poly_args ) )
+			) );
 		}
 
@@ -434,7 +444,13 @@
 	void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) {
 		if ( vtable_decl ) {
-			declsToAddBefore.push_back( Virtual::makeVtableForward( vtable_decl, {
+			std::list< Expression * > poly_args = {
 				new TypeExpr( new StructInstType( noQualifiers, decl ) ),
-			} ) );
+			};
+			declsToAddBefore.push_back( Virtual::makeGetExceptionForward(
+				vtable_decl->makeInst( poly_args ),
+				except_decl->makeInst( poly_args )
+			) );
+			declsToAddBefore.push_back( Virtual::makeVtableForward(
+				vtable_decl->makeInst( move( poly_args ) ) ) );
 		// Its only an error if we want a vtable and don't have one.
 		} else if ( ! vtable_name.empty() ) {
Index: src/InitTweak/FixGlobalInit.cc
===================================================================
--- src/InitTweak/FixGlobalInit.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/InitTweak/FixGlobalInit.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -153,4 +153,5 @@
 			} // if
 			if ( Statement * ctor = ctorInit->ctor ) {
+				addDataSectonAttribute( objDecl );
 				initStatements.push_back( ctor );
 				objDecl->init = nullptr;
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/InitTweak/FixInit.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -802,4 +802,10 @@
 				if ( Statement * ctor = ctorInit->get_ctor() ) {
 					if ( objDecl->get_storageClasses().is_static ) {
+
+						// The ojbect needs to go in the data section, regardless of dtor complexity below.
+						// The attribute works, and is meant to apply, both for leaving the static local alone,
+						// and for hoisting it out as a static global.
+						addDataSectonAttribute( objDecl );
+
 						// originally wanted to take advantage of gcc nested functions, but
 						// we get memory errors with this approach. To remedy this, the static
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/InitTweak/InitTweak.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -1103,3 +1103,13 @@
 		return isCopyFunction( decl, "?{}" );
 	}
+
+	void addDataSectonAttribute( ObjectDecl * objDecl ) {
+		Type *strLitT = new PointerType( Type::Qualifiers( ),
+			new BasicType( Type::Qualifiers( ), BasicType::Char ) );
+		std::list< Expression * > attr_params;
+		attr_params.push_back( 
+			new ConstantExpr( Constant( strLitT, "\".data#\"", std::nullopt ) ) );
+		objDecl->attributes.push_back(new Attribute("section", attr_params));
+	}
+
 }
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/InitTweak/InitTweak.h	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -108,4 +108,15 @@
 	bool isConstExpr( Initializer * init );
 
+	/// Modifies objDecl to have:
+	///    __attribute__((section (".data#")))
+	/// which makes gcc put the declared variable in the data section,
+	/// which is helpful for global constants on newer gcc versions,
+	/// so that CFA's generated initialization won't segfault when writing it via a const cast.
+	/// The trailing # is an injected assembly comment, to suppress the "a" in
+	///    .section .data,"a"
+	///    .section .data#,"a"
+	/// to avoid assembler warning "ignoring changed section attributes for .data"
+	void addDataSectonAttribute( ObjectDecl * objDecl );
+
 	class InitExpander_old {
 	public:
Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/Parser/DeclarationNode.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -10,6 +10,6 @@
 // Created On       : Sat May 16 12:34:05 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jun  9 20:26:55 2020
-// Update Count     : 1134
+// Last Modified On : Thu Oct  8 08:03:38 2020
+// Update Count     : 1135
 //
 
@@ -1016,5 +1016,5 @@
 			if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
 				dwt->location = cur->location;
-				* out++ = dwt;
+				*out++ = dwt;
 			} else if ( StructDecl * agg = dynamic_cast< StructDecl * >( decl ) ) {
 				// e.g., int foo(struct S) {}
@@ -1022,5 +1022,5 @@
 				auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
 				obj->location = cur->location;
-				* out++ = obj;
+				*out++ = obj;
 				delete agg;
 			} else if ( UnionDecl * agg = dynamic_cast< UnionDecl * >( decl ) ) {
@@ -1029,5 +1029,5 @@
 				auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
 				obj->location = cur->location;
-				* out++ = obj;
+				*out++ = obj;
 			} else if ( EnumDecl * agg = dynamic_cast< EnumDecl * >( decl ) ) {
 				// e.g., int foo(enum E) {}
@@ -1035,5 +1035,5 @@
 				auto obj = new ObjectDecl( "", Type::StorageClasses(), linkage, nullptr, inst, nullptr );
 				obj->location = cur->location;
-				* out++ = obj;
+				*out++ = obj;
 			} // if
 		} catch( SemanticErrorException & e ) {
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/Parser/parser.yy	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -10,6 +10,6 @@
 // Created On       : Sat Sep  1 20:22:55 2001
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Oct  6 18:24:18 2020
-// Update Count     : 4610
+// Last Modified On : Fri Oct  9 18:09:09 2020
+// Update Count     : 4614
 //
 
@@ -204,8 +204,8 @@
 			return forCtrl( type, new string( identifier->name ), start, compop, comp, inc );
 		} else {
-			SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed" ); return nullptr;
+			SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed." ); return nullptr;
 		} // if
 	} else {
-		SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed" ); return nullptr;
+		SemanticError( yylloc, "Expression disallowed. Only loop-index name allowed." ); return nullptr;
 	} // if
 } // forCtrl
@@ -2412,5 +2412,5 @@
 // Overloading: function, data, and operator identifiers may be overloaded.
 //
-// Type declarations: "type" is used to generate new types for declaring objects. Similarly, "dtype" is used for object
+// Type declarations: "otype" is used to generate new types for declaring objects. Similarly, "dtype" is used for object
 //     and incomplete types, and "ftype" is used for function types. Type declarations with initializers provide
 //     definitions of new types. Type declarations with storage class "extern" provide opaque types.
@@ -2441,5 +2441,5 @@
 	type_class identifier_or_type_name
 		{ typedefTable.addToScope( *$2, TYPEDEFname, "9" ); }
-	  type_initializer_opt assertion_list_opt
+	type_initializer_opt assertion_list_opt
 		{ $$ = DeclarationNode::newTypeParam( $1, $2 )->addTypeInitializer( $4 )->addAssertions( $5 ); }
 	| type_specifier identifier_parameter_declarator
@@ -2468,5 +2468,5 @@
 	assertion
 	| assertion_list assertion
-		{ $$ = $1 ? $1->appendList( $2 ) : $2; }
+		{ $$ = $1->appendList( $2 ); }
 	;
 
Index: src/SynTree/AggregateDecl.cc
===================================================================
--- src/SynTree/AggregateDecl.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/SynTree/AggregateDecl.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -21,4 +21,5 @@
 #include "Common/utility.h"      // for printAll, cloneAll, deleteAll
 #include "Declaration.h"         // for AggregateDecl, TypeDecl, Declaration
+#include "Expression.h"
 #include "Initializer.h"
 #include "LinkageSpec.h"         // for Spec, linkageName, Cforall
@@ -88,4 +89,17 @@
 const char * StructDecl::typeString() const { return aggrString( kind ); }
 
+StructInstType * StructDecl::makeInst( std::list< Expression * > const & new_parameters ) {
+	std::list< Expression * > copy_parameters;
+	cloneAll( new_parameters, copy_parameters );
+	return makeInst( move( copy( copy_parameters ) ) );
+}
+
+StructInstType * StructDecl::makeInst( std::list< Expression * > && new_parameters ) {
+	assert( parameters.size() == new_parameters.size() );
+	StructInstType * type = new StructInstType( noQualifiers, this );
+	type->parameters = std::move( new_parameters );
+	return type;
+}
+
 const char * UnionDecl::typeString() const { return aggrString( Union ); }
 
Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/SynTree/Declaration.h	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -306,4 +306,8 @@
 	bool is_thread   () { return kind == Thread   ; }
 
+	// Make a type instance of this declaration.
+	StructInstType * makeInst( std::list< Expression * > const & parameters );
+	StructInstType * makeInst( std::list< Expression * > && parameters );
+
 	virtual StructDecl * clone() const override { return new StructDecl( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/SynTree/Expression.h	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -163,4 +163,29 @@
 };
 
+/// VariableExpr represents an expression that simply refers to the value of a named variable.
+/// Does not take ownership of var.
+class VariableExpr : public Expression {
+  public:
+	DeclarationWithType * var;
+
+	VariableExpr();
+	VariableExpr( DeclarationWithType * var );
+	VariableExpr( const VariableExpr & other );
+	virtual ~VariableExpr();
+
+	bool get_lvalue() const final;
+
+	DeclarationWithType * get_var() const { return var; }
+	void set_var( DeclarationWithType * newValue ) { var = newValue; }
+
+	static VariableExpr * functionPointer( FunctionDecl * decl );
+
+	virtual VariableExpr * clone() const override { return new VariableExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
+};
+
 // The following classes are used to represent expression types that cannot be converted into
 // function-call format.
@@ -329,29 +354,4 @@
 };
 
-/// VariableExpr represents an expression that simply refers to the value of a named variable.
-/// Does not take ownership of var.
-class VariableExpr : public Expression {
-  public:
-	DeclarationWithType * var;
-
-	VariableExpr();
-	VariableExpr( DeclarationWithType * var );
-	VariableExpr( const VariableExpr & other );
-	virtual ~VariableExpr();
-
-	bool get_lvalue() const final;
-
-	DeclarationWithType * get_var() const { return var; }
-	void set_var( DeclarationWithType * newValue ) { var = newValue; }
-
-	static VariableExpr * functionPointer( FunctionDecl * decl );
-
-	virtual VariableExpr * clone() const override { return new VariableExpr( * this ); }
-	virtual void accept( Visitor & v ) override { v.visit( this ); }
-	virtual void accept( Visitor & v ) const override { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
-};
-
 /// ConstantExpr represents an expression that simply refers to the value of a constant
 class ConstantExpr : public Expression {
Index: src/SynTree/TypeDecl.cc
===================================================================
--- src/SynTree/TypeDecl.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/SynTree/TypeDecl.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Dec 13 15:26:14 2019
-// Update Count     : 21
+// Last Modified On : Thu Oct  8 18:18:55 2020
+// Update Count     : 22
 //
 
@@ -21,5 +21,6 @@
 #include "Type.h"            // for Type, Type::StorageClasses
 
-TypeDecl::TypeDecl( const std::string & name, Type::StorageClasses scs, Type * type, Kind kind, bool sized, Type * init ) : Parent( name, scs, type ), kind( kind ), sized( kind == Ttype || sized ), init( init ) {
+TypeDecl::TypeDecl( const std::string & name, Type::StorageClasses scs, Type * type, Kind kind, bool sized, Type * init ) :
+	Parent( name, scs, type ), kind( kind ), sized( kind == Ttype || sized ), init( init ) {
 }
 
Index: src/Virtual/Tables.cc
===================================================================
--- src/Virtual/Tables.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/Virtual/Tables.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -14,6 +14,8 @@
 //
 
+#include <SynTree/Attribute.h>
 #include <SynTree/Declaration.h>
 #include <SynTree/Expression.h>
+#include <SynTree/Statement.h>
 #include <SynTree/Type.h>
 
@@ -38,14 +40,4 @@
 }
 
-// Fuse base polymorphic declaration and forall arguments into a new type.
-static StructInstType * vtableInstType(
-		StructDecl * polyDecl, std::list< Expression * > && parameters ) {
-	assert( parameters.size() == polyDecl->parameters.size() );
-	StructInstType * type = new StructInstType(
-			Type::Qualifiers( /* Type::Const */ ), polyDecl );
-	type->parameters = std::move( parameters );
-	return type;
-}
-
 static ObjectDecl * makeVtableDeclaration(
 		StructInstType * type, Initializer * init ) {
@@ -66,14 +58,12 @@
 
 ObjectDecl * makeVtableForward( StructInstType * type ) {
+	assert( type );
 	return makeVtableDeclaration( type, nullptr );
 }
 
-ObjectDecl * makeVtableForward(
-		StructDecl * polyDecl, std::list< Expression * > && parameters ) {
-	return makeVtableForward( vtableInstType( polyDecl, std::move( parameters ) ) );
-}
-
 ObjectDecl * makeVtableInstance(
-		StructInstType * vtableType, Type * vobject_type, Initializer * init ) {
+		StructInstType * vtableType, Type * objectType, Initializer * init ) {
+	assert( vtableType );
+	assert( objectType );
 	StructDecl * vtableStruct = vtableType->baseStruct;
 	// Build the initialization
@@ -92,7 +82,7 @@
 						new SingleInit( new AddressExpr( new NameExpr( parentInstance ) ) ) );
 			} else if ( std::string( "size" ) == field->name ) {
-				inits.push_back( new SingleInit( new SizeofExpr( vobject_type->clone() ) ) );
+				inits.push_back( new SingleInit( new SizeofExpr( objectType->clone() ) ) );
 			} else if ( std::string( "align" ) == field->name ) {
-				inits.push_back( new SingleInit( new AlignofExpr( vobject_type->clone() ) ) );
+				inits.push_back( new SingleInit( new AlignofExpr( objectType->clone() ) ) );
 			} else {
 				inits.push_back( new SingleInit( new NameExpr( field->name ) ) );
@@ -108,9 +98,51 @@
 }
 
-ObjectDecl * makeVtableInstance(
-		StructDecl * polyDecl, std::list< Expression * > && parameters,
-		Type * vobject, Initializer * init ) {
-	return makeVtableInstance(
-		vtableInstType( polyDecl, std::move( parameters ) ), vobject, init );
+namespace {
+	std::string const functionName = "get_exception_vtable";
+}
+
+FunctionDecl * makeGetExceptionForward(
+		Type * vtableType, Type * exceptType ) {
+	assert( vtableType );
+	assert( exceptType );
+	FunctionType * type = new FunctionType( noQualifiers, false );
+	vtableType->tq.is_const = true;
+	type->returnVals.push_back( new ObjectDecl(
+		"_retvalue",
+		noStorageClasses,
+		LinkageSpec::Cforall,
+		nullptr,
+		new ReferenceType( noQualifiers, vtableType ),
+		nullptr,
+        { new Attribute("unused") }
+	) );
+	type->parameters.push_back( new ObjectDecl(
+		"__unused",
+		noStorageClasses,
+		LinkageSpec::Cforall,
+		nullptr,
+		new PointerType( noQualifiers, exceptType ),
+		nullptr,
+		{ new Attribute("unused") }
+	) );
+	return new FunctionDecl(
+		functionName,
+		noStorageClasses,
+		LinkageSpec::Cforall,
+		type,
+		nullptr
+	);
+}
+
+FunctionDecl * makeGetExceptionFunction(
+		ObjectDecl * vtableInstance, Type * exceptType ) {
+	assert( vtableInstance );
+	assert( exceptType );
+	FunctionDecl * func = makeGetExceptionForward(
+		vtableInstance->type->clone(), exceptType );
+	func->statements = new CompoundStmt( {
+		new ReturnStmt( new VariableExpr( vtableInstance ) ),
+	} );
+	return func;
 }
 
Index: src/Virtual/Tables.h
===================================================================
--- src/Virtual/Tables.h	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/Virtual/Tables.h	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -27,25 +27,25 @@
 bool isVTableInstanceName( std::string const & name );
 
-/// Converts exceptions into regular structures.
-//void ( std::list< Declaration * > & translationUnit );
-
-ObjectDecl * makeVtableForward( StructInstType * );
-ObjectDecl * makeVtableForward( StructDecl *, std::list< Expression * > && );
-/* Create a forward definition of a vtable of the given type.
- *
- * Instead of the virtual table type you may provide the declaration and all
- * the forall parameters.
+ObjectDecl * makeVtableForward( StructInstType * vtableType );
+/* Create a forward declaration of a vtable of the given type.
+ * vtableType node is consumed.
  */
 
-ObjectDecl * makeVtableInstance( StructInstType *, Type *, Initializer * );
-ObjectDecl * makeVtableInstance(
-	StructDecl *, std::list< Expression * > &&, Type *, Initializer * );
+ObjectDecl * makeVtableInstance( StructInstType * vtableType, Type * objectType,
+	Initializer * init = nullptr );
 /* Create an initialized definition of a vtable.
- *
- * The parameters are the virtual table type (or the base declaration and the
- * forall parameters), the object type and optionally an initializer.
- *
- * Instead of the virtual table type you may provide the declaration and all
- * the forall parameters.
+ * vtableType and init (if provided) nodes are consumed.
+ */
+
+// Some special code for how exceptions interact with virtual tables.
+FunctionDecl * makeGetExceptionForward( Type * vtableType, Type * exceptType );
+/* Create a forward declaration of the exception virtual function
+ * linking the vtableType to the exceptType. Both nodes are consumed.
+ */
+
+FunctionDecl * makeGetExceptionFunction(
+	ObjectDecl * vtableInstance, Type * exceptType );
+/* Create the definition of the exception virtual function.
+ * exceptType node is consumed.
  */
 
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 37b7d951459a8cb66e00d62c29da49e8423128ed)
+++ src/main.cc	(revision e7d6968ca3b4455b39947466f58154fce3451c5c)
@@ -9,7 +9,7 @@
 // Author           : Peter Buhr and Rob Schluntz
 // Created On       : Fri May 15 23:12:02 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Tue May 19 12:03:00 2020
-// Update Count     : 634
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Thu Oct  8 18:17:46 2020
+// Update Count     : 637
 //
 
@@ -458,5 +458,5 @@
 
 
-static const char optstring[] = ":c:ghlLmNnpdP:S:twW:D:";
+static const char optstring[] = ":c:ghlLmNnpdOAP:S:twW:D:";
 
 enum { PreludeDir = 128 };
@@ -485,23 +485,23 @@
 
 static const char * description[] = {
-	"diagnostic color: never, always, or auto.",          // -c
-	"wait for gdb to attach",                             // -g
-	"print help message",                                 // -h
-	"generate libcfa.c",                                  // -l
-	"generate line marks",                                // -L
-	"do not replace main",                                // -m
-	"do not generate line marks",                         // -N
-	"do not read prelude",                                // -n
+	"diagnostic color: never, always, or auto.",		// -c
+	"wait for gdb to attach",							// -g
+	"print help message",								// -h
+	"generate libcfa.c",								// -l
+	"generate line marks",								// -L
+	"do not replace main",								// -m
+	"do not generate line marks",						// -N
+	"do not read prelude",								// -n
 	"generate prototypes for prelude functions",		// -p
-	"don't print output that isn't deterministic",        // -d
-	"Use the old-ast",                                    // -O
-	"Use the new-ast",                                    // -A
-	"print",                                              // -P
+	"only print deterministic output",                  // -d
+	"Use the old-ast",									// -O
+	"Use the new-ast",									// -A
+	"print",											// -P
 	"<directory> prelude directory for debug/nodebug",	// no flag
 	"<option-list> enable profiling information:\n          counters,heap,time,all,none", // -S
-	"building cfa standard lib",                          // -t
-	"",                                                   // -w
-	"",                                                   // -W
-	"",                                                   // -D
+	"building cfa standard lib",						// -t
+	"",													// -w
+	"",													// -W
+	"",													// -D
 }; // description
 
