Index: src/AST/AssertAcyclic.cpp
===================================================================
--- src/AST/AssertAcyclic.cpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ 	(revision )
@@ -1,53 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// AssertAcyclic.cpp -- Check that ast::ptr does not form a cycle.
-//
-// Author           : Andrew Beach
-// Created On       : Thu Jun 06 15:00:00 2019
-// Last Modified By : Andrew Beach
-// Last Modified On : Fri Jun 07 14:32:00 2019
-// Update Count     : 1
-//
-
-#include "AssertAcyclic.hpp"
-
-#include "AST/Pass.hpp"
-
-namespace {
-
-class NoStrongCyclesCore {
-    std::vector<const ast::Node *> parents;
-public:
-	void previsit( const ast::Node * node ) {
-		for (auto & parent : parents) {
-			assert(parent != node);
-		}
-		parents.push_back(node);
-	}
-	void postvisit( const ast::Node * ) {
-		parents.pop_back();
-	}
-};
-
-}
-
-namespace ast {
-
-void assertAcyclic( const std::list< ast::ptr< ast::Decl > > & translationUnit ) {
-   	Pass<NoStrongCyclesCore> visitor;
-	for ( auto & decl : translationUnit ) {
-		decl->accept( visitor );
-	}
-}
-
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/AST/AssertAcyclic.hpp
===================================================================
--- src/AST/AssertAcyclic.hpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ 	(revision )
@@ -1,35 +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.
-//
-// AssertAcyclic.hpp -- Check that ast::ptr does not form a cycle.
-//
-// Author           : Andrew Beach
-// Created On       : Thr Jun  6 15:00:00 2019
-// Last Modified By : Andrew Beach
-// Last Modified On : Fri Jun  7 14:32:00 2019
-// Update Count     : 1
-//
-
-#pragma once
-
-#include <list>
-
-#include "Node.hpp"
-namespace ast {
-    class Decl;
-};
-
-namespace ast {
-
-void assertAcyclic( const std::list< ast::ptr< ast::Decl > > & translationUnit );
-
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/Convert.cpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -9,7 +9,7 @@
 // Author           : Thierry Delisle
 // Created On       : Thu May 09 15::37::05 2019
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  2 13:19:22 2022
-// Update Count     : 41
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Mar 16 15:01:00 2022
+// Update Count     : 42
 //
 
@@ -49,14 +49,11 @@
 //================================================================================================
 namespace ast {
-
-// This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not)
-// allow us to use the same stratagy in the new ast.
-// xxx - since convert back pass works, this concern seems to be unnecessary.
-
-// these need to be accessed in new FixInit now
-ast::ptr<ast::Type> sizeType = nullptr;
-const ast::FunctionDecl * dereferenceOperator = nullptr;
-const ast::StructDecl   * dtorStruct = nullptr;
-const ast::FunctionDecl * dtorStructDestroy = nullptr;
+// These are the shared local information used by ConverterNewToOld and
+// ConverterOldToNew to update the global information in the two versions.
+
+static ast::ptr<ast::Type> sizeType = nullptr;
+static const ast::FunctionDecl * dereferenceOperator = nullptr;
+static const ast::StructDecl   * dtorStruct = nullptr;
+static const ast::FunctionDecl * dtorStructDestroy = nullptr;
 
 }
@@ -357,4 +354,9 @@
 	}
 
+	void clausePostamble( Statement * stmt, const ast::StmtClause * node ) {
+		stmt->location = node->location;
+		this->node = stmt;
+	}
+
 	const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) override final {
 		if ( inCache( node ) ) return nullptr;
@@ -405,10 +407,10 @@
 		auto stmt = new SwitchStmt(
 			get<Expression>().accept1( node->cond ),
-			get<Statement>().acceptL( node->stmts )
+			get<Statement>().acceptL( node->cases )
 		);
 		return stmtPostamble( stmt, node );
 	}
 
-	const ast::Stmt * visit( const ast::CaseStmt * node ) override final {
+	const ast::CaseClause * visit( const ast::CaseClause * node ) override final {
 		if ( inCache( node ) ) return nullptr;
 		auto stmt = new CaseStmt(
@@ -417,5 +419,6 @@
 			node->isDefault()
 		);
-		return stmtPostamble( stmt, node );
+		clausePostamble( stmt, node );
+		return nullptr;
 	}
 
@@ -513,5 +516,5 @@
 	}
 
-	const ast::Stmt * visit( const ast::CatchStmt * node ) override final {
+	const ast::CatchClause * visit( const ast::CatchClause * node ) override final {
 		if ( inCache( node ) ) return nullptr;
 		CatchStmt::Kind kind;
@@ -524,5 +527,5 @@
 			break;
 		default:
-			assertf(false, "Invalid ast::CatchStmt::Kind: %d\n", node->kind);
+			assertf(false, "Invalid ast::ExceptionKind: %d\n", node->kind);
 		}
 		auto stmt = new CatchStmt(
@@ -532,11 +535,11 @@
 			get<Statement>().accept1( node->body )
 		);
-		return stmtPostamble( stmt, node );
-	}
-
-	const ast::Stmt * visit( const ast::FinallyStmt * node ) override final {
+		return clausePostamble( stmt, node ), nullptr;
+	}
+
+	const ast::FinallyClause * visit( const ast::FinallyClause * node ) override final {
 		if ( inCache( node ) ) return nullptr;
 		auto stmt = new FinallyStmt( get<CompoundStmt>().accept1( node->body ) );
-		return stmtPostamble( stmt, node );
+		return clausePostamble( stmt, node ), nullptr;
 	}
 
@@ -1894,5 +1897,5 @@
 			old->location,
 			GET_ACCEPT_1(condition, Expr),
-			GET_ACCEPT_V(statements, Stmt),
+			GET_ACCEPT_V(statements, CaseClause),
 			GET_LABELS_V(old->labels)
 		);
@@ -1902,10 +1905,11 @@
 	virtual void visit( const CaseStmt * old ) override final {
 		if ( inCache( old ) ) return;
-		this->node = new ast::CaseStmt(
+		this->node = new ast::CaseClause(
 			old->location,
 			GET_ACCEPT_1(condition, Expr),
-			GET_ACCEPT_V(stmts, Stmt),
-			GET_LABELS_V(old->labels)
-		);
+			GET_ACCEPT_V(stmts, Stmt)
+		);
+		auto labels = GET_LABELS_V(old->labels);
+		assertf(labels.empty(), "Labels found on CaseStmt.");
 		cache.emplace( old, this->node );
 	}
@@ -2015,6 +2019,6 @@
 			old->location,
 			GET_ACCEPT_1(block, CompoundStmt),
-			GET_ACCEPT_V(handlers, CatchStmt),
-			GET_ACCEPT_1(finallyBlock, FinallyStmt),
+			GET_ACCEPT_V(handlers, CatchClause),
+			GET_ACCEPT_1(finallyBlock, FinallyClause),
 			GET_LABELS_V(old->labels)
 		);
@@ -2036,12 +2040,13 @@
 		}
 
-		this->node = new ast::CatchStmt(
+		this->node = new ast::CatchClause(
 			old->location,
 			kind,
 			GET_ACCEPT_1(decl, Decl),
 			GET_ACCEPT_1(cond, Expr),
-			GET_ACCEPT_1(body, Stmt),
-			GET_LABELS_V(old->labels)
-		);
+			GET_ACCEPT_1(body, Stmt)
+		);
+		auto labels = GET_LABELS_V(old->labels);
+		assertf(labels.empty(), "Labels found on CatchStmt.");
 		cache.emplace( old, this->node );
 	}
@@ -2049,9 +2054,10 @@
 	virtual void visit( const FinallyStmt * old ) override final {
 		if ( inCache( old ) ) return;
-		this->node = new ast::FinallyStmt(
-			old->location,
-			GET_ACCEPT_1(block, CompoundStmt),
-			GET_LABELS_V(old->labels)
-		);
+		this->node = new ast::FinallyClause(
+			old->location,
+			GET_ACCEPT_1(block, CompoundStmt)
+		);
+		auto labels = GET_LABELS_V(old->labels);
+		assertf(labels.empty(), "Labels found on FinallyStmt.");
 		cache.emplace( old, this->node );
 	}
@@ -2718,5 +2724,5 @@
 
 		for (auto & param : foralls) {
-			ty->forall.emplace_back(new ast::TypeInstType(param->name, param));
+			ty->forall.emplace_back(new ast::TypeInstType(param));
 			for (auto asst : param->assertions) {
 				ty->assertions.emplace_back(new ast::VariableExpr({}, asst));
Index: src/AST/Decl.cpp
===================================================================
--- src/AST/Decl.cpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/Decl.cpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -39,8 +39,11 @@
 	if ( uniqueId ) return;  // ensure only set once
 	uniqueId = ++lastUniqueId;
-	idMap[ uniqueId ] = this;
+	// The extra readonly pointer is causing some reference counting issues.
+	// idMap[ uniqueId ] = this;
 }
 
 readonly<Decl> Decl::fromId( UniqueId id ) {
+	// Right now this map is always empty, so don't use it.
+	assert( false );
 	IdMapType::const_iterator i = idMap.find( id );
 	if ( i != idMap.end() ) return i->second;
@@ -65,5 +68,5 @@
 	}
 	for (auto & tp : this->type_params) {
-		ftype->forall.emplace_back(new TypeInstType(tp->name, tp));
+		ftype->forall.emplace_back(new TypeInstType(tp));
 		for (auto & ap: tp->assertions) {
 			ftype->assertions.emplace_back(new VariableExpr(loc, ap));
Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/Fwd.hpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -47,11 +47,11 @@
 class ForStmt;
 class SwitchStmt;
-class CaseStmt;
+class CaseClause;
 class BranchStmt;
 class ReturnStmt;
 class ThrowStmt;
 class TryStmt;
-class CatchStmt;
-class FinallyStmt;
+class CatchClause;
+class FinallyClause;
 class SuspendStmt;
 class WaitForStmt;
@@ -141,9 +141,5 @@
 
 class TranslationUnit;
-// TODO: Get from the TranslationUnit:
-extern ptr<Type> sizeType;
-extern const FunctionDecl * dereferenceOperator;
-extern const StructDecl   * dtorStruct;
-extern const FunctionDecl * dtorStructDestroy;
+class TranslationGlobal;
 
 }
Index: src/AST/GenericSubstitution.cpp
===================================================================
--- src/AST/GenericSubstitution.cpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/GenericSubstitution.cpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -45,5 +45,5 @@
 			visit_children = false;
 			const AggregateDecl * aggr = ty->aggr();
-			sub = TypeSubstitution{ aggr->params.begin(), aggr->params.end(), ty->params.begin() };
+			sub = TypeSubstitution( aggr->params, ty->params );
 		}
 
Index: src/AST/Node.cpp
===================================================================
--- src/AST/Node.cpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/Node.cpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -9,7 +9,7 @@
 // Author           : Thierry Delisle
 // Created On       : Thu May 16 14:16:00 2019
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Feb  1 09:09:39 2022
-// Update Count     : 3
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Mar 25 10:30:00 2022
+// Update Count     : 4
 //
 
@@ -19,4 +19,5 @@
 #include <csignal>  // MEMORY DEBUG -- for raise
 #include <iostream>
+#include <utility>
 
 #include "Attribute.hpp"
@@ -76,4 +77,11 @@
 void ast::ptr_base<node_t, ref_t>::_check() const {
 	// if(node) assert(node->was_ever_strong == false || node->strong_count > 0);
+}
+
+template< typename node_t, enum ast::Node::ref_type ref_t >
+void ast::ptr_base<node_t, ref_t>::swap( ptr_base & other ) noexcept {
+	std::swap( this->node, other.node );
+	_trap( this->node );
+	_trap( other.node );
 }
 
@@ -152,6 +160,6 @@
 template class ast::ptr_base< ast::SwitchStmt, ast::Node::ref_type::weak >;
 template class ast::ptr_base< ast::SwitchStmt, ast::Node::ref_type::strong >;
-template class ast::ptr_base< ast::CaseStmt, ast::Node::ref_type::weak >;
-template class ast::ptr_base< ast::CaseStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::CaseClause, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::CaseClause, ast::Node::ref_type::strong >;
 template class ast::ptr_base< ast::BranchStmt, ast::Node::ref_type::weak >;
 template class ast::ptr_base< ast::BranchStmt, ast::Node::ref_type::strong >;
@@ -162,8 +170,8 @@
 template class ast::ptr_base< ast::TryStmt, ast::Node::ref_type::weak >;
 template class ast::ptr_base< ast::TryStmt, ast::Node::ref_type::strong >;
-template class ast::ptr_base< ast::CatchStmt, ast::Node::ref_type::weak >;
-template class ast::ptr_base< ast::CatchStmt, ast::Node::ref_type::strong >;
-template class ast::ptr_base< ast::FinallyStmt, ast::Node::ref_type::weak >;
-template class ast::ptr_base< ast::FinallyStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::CatchClause, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::CatchClause, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::FinallyClause, ast::Node::ref_type::strong >;
 template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::weak >;
 template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::strong >;
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/Node.hpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -10,6 +10,6 @@
 // Created On       : Wed May 8 10:27:04 2019
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri Jun 5 9:47:00 2020
-// Update Count     : 6
+// Last Modified On : Fri Mar 25 10:33:00 2022
+// Update Count     : 7
 //
 
@@ -103,6 +103,6 @@
 
 /// Mutate a node field (only clones if not equal to existing value)
-template<typename node_t, typename parent_t, typename field_t, typename assn_t>
-const node_t * mutate_field( const node_t * node, field_t parent_t::* field, assn_t && val ) {
+template<typename node_t, typename super_t, typename field_t, typename assn_t>
+const node_t * mutate_field( const node_t * node, field_t super_t::* field, assn_t && val ) {
 	// skip mutate if equivalent
 	if ( node->*field == val ) return node;
@@ -115,7 +115,7 @@
 
 /// Mutate a single index of a node field (only clones if not equal to existing value)
-template<typename node_t, typename parent_t, typename coll_t, typename ind_t, typename field_t>
+template<typename node_t, typename super_t, typename coll_t, typename ind_t, typename field_t>
 const node_t * mutate_field_index(
-	const node_t * node, coll_t parent_t::* field, ind_t i, field_t && val
+	const node_t * node, coll_t super_t::* field, ind_t i, field_t && val
 ) {
 	// skip mutate if equivalent
@@ -129,6 +129,6 @@
 
 /// Mutate an entire indexed collection by cloning to accepted value
-template<typename node_t, typename parent_t, typename coll_t>
-const node_t * mutate_each( const node_t * node, coll_t parent_t::* field, Visitor & v ) {
+template<typename node_t, typename super_t, typename coll_t>
+const node_t * mutate_each( const node_t * node, coll_t super_t::* field, Visitor & v ) {
 	for ( unsigned i = 0; i < (node->*field).size(); ++i ) {
 		node = mutate_field_index( node, field, i, (node->*field)[i]->accept( v ) );
@@ -230,4 +230,7 @@
 	}
 
+	/// Swaps the nodes contained within two pointers.
+	void swap( ptr_base & other ) noexcept;
+
 	const node_t * get() const { _check(); return  node; }
 	const node_t * operator->() const { _check(); return  node; }
@@ -292,4 +295,11 @@
 template< typename node_t >
 using readonly = ptr_base< node_t, Node::ref_type::weak >;
+
+/// Non-member swap that an participate in overload resolution.
+template< typename node_t, enum Node::ref_type ref_t >
+void swap( ptr_base< node_t, ref_t > & l, ptr_base< node_t, ref_t > & r ) {
+	l.swap( r );
+}
+
 }
 
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/Pass.hpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -149,11 +149,11 @@
 	const ast::Stmt *             visit( const ast::ForStmt              * ) override final;
 	const ast::Stmt *             visit( const ast::SwitchStmt           * ) override final;
-	const ast::Stmt *             visit( const ast::CaseStmt             * ) override final;
+	const ast::CaseClause *       visit( const ast::CaseClause           * ) override final;
 	const ast::Stmt *             visit( const ast::BranchStmt           * ) override final;
 	const ast::Stmt *             visit( const ast::ReturnStmt           * ) override final;
 	const ast::Stmt *             visit( const ast::ThrowStmt            * ) override final;
 	const ast::Stmt *             visit( const ast::TryStmt              * ) override final;
-	const ast::Stmt *             visit( const ast::CatchStmt            * ) override final;
-	const ast::Stmt *             visit( const ast::FinallyStmt          * ) override final;
+	const ast::CatchClause *      visit( const ast::CatchClause          * ) override final;
+	const ast::FinallyClause *    visit( const ast::FinallyClause        * ) override final;
 	const ast::Stmt *             visit( const ast::SuspendStmt          * ) override final;
 	const ast::Stmt *             visit( const ast::WaitForStmt          * ) override final;
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/Pass.impl.hpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -354,5 +354,5 @@
 			// Take all the elements that are different in 'values'
 			// and swap them into 'container'
-			if( values[i] != nullptr ) std::swap(container[i], values[i]);
+			if( values[i] != nullptr ) swap(container[i], values[i]);
 		}
 
@@ -399,13 +399,13 @@
 
 	template< typename core_t >
-	template<typename node_t, typename parent_t, typename child_t>
+	template<typename node_t, typename super_t, typename field_t>
 	void ast::Pass< core_t >::maybe_accept(
 		const node_t * & parent,
-		child_t parent_t::*child
+		field_t super_t::*field
 	) {
-		static_assert( std::is_base_of<parent_t, node_t>::value, "Error deducing member object" );
-
-		if(__pass::skip(parent->*child)) return;
-		const auto & old_val = __pass::get(parent->*child, 0);
+		static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
+
+		if(__pass::skip(parent->*field)) return;
+		const auto & old_val = __pass::get(parent->*field, 0);
 
 		static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR");
@@ -417,5 +417,5 @@
 		if( new_val.differs ) {
 			auto new_parent = __pass::mutate<core_t>(parent);
-			new_val.apply(new_parent, child);
+			new_val.apply(new_parent, field);
 			parent = new_parent;
 		}
@@ -423,10 +423,10 @@
 
 	template< typename core_t >
-	template<typename node_t, typename parent_t, typename child_t>
+	template<typename node_t, typename super_t, typename field_t>
 	void ast::Pass< core_t >::maybe_accept_as_compound(
 		const node_t * & parent,
-		child_t parent_t::*child
+		field_t super_t::*child
 	) {
-		static_assert( std::is_base_of<parent_t, node_t>::value, "Error deducing member object" );
+		static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" );
 
 		if(__pass::skip(parent->*child)) return;
@@ -893,5 +893,5 @@
 	if ( __visit_children() ) {
 		maybe_accept( node, &SwitchStmt::cond  );
-		maybe_accept( node, &SwitchStmt::stmts );
+		maybe_accept( node, &SwitchStmt::cases );
 	}
 
@@ -900,15 +900,15 @@
 
 //--------------------------------------------------------------------------
-// CaseStmt
-template< typename core_t >
-const ast::Stmt * ast::Pass< core_t >::visit( const ast::CaseStmt * node ) {
-	VISIT_START( node );
-
-	if ( __visit_children() ) {
-		maybe_accept( node, &CaseStmt::cond  );
-		maybe_accept( node, &CaseStmt::stmts );
-	}
-
-	VISIT_END( Stmt, node );
+// CaseClause
+template< typename core_t >
+const ast::CaseClause * ast::Pass< core_t >::visit( const ast::CaseClause * node ) {
+	VISIT_START( node );
+
+	if ( __visit_children() ) {
+		maybe_accept( node, &CaseClause::cond  );
+		maybe_accept( node, &CaseClause::stmts );
+	}
+
+	VISIT_END( CaseClause, node );
 }
 
@@ -964,7 +964,7 @@
 
 //--------------------------------------------------------------------------
-// CatchStmt
-template< typename core_t >
-const ast::Stmt * ast::Pass< core_t >::visit( const ast::CatchStmt * node ) {
+// CatchClause
+template< typename core_t >
+const ast::CatchClause * ast::Pass< core_t >::visit( const ast::CatchClause * node ) {
 	VISIT_START( node );
 
@@ -972,23 +972,23 @@
 		// catch statements introduce a level of scope (for the caught exception)
 		guard_symtab guard { *this };
-		maybe_accept( node, &CatchStmt::decl );
-		maybe_accept( node, &CatchStmt::cond );
-		maybe_accept_as_compound( node, &CatchStmt::body );
-	}
-
-	VISIT_END( Stmt, node );
-}
-
-//--------------------------------------------------------------------------
-// FinallyStmt
-template< typename core_t >
-const ast::Stmt * ast::Pass< core_t >::visit( const ast::FinallyStmt * node ) {
-	VISIT_START( node );
-
-	if ( __visit_children() ) {
-		maybe_accept( node, &FinallyStmt::body );
-	}
-
-	VISIT_END( Stmt, node );
+		maybe_accept( node, &CatchClause::decl );
+		maybe_accept( node, &CatchClause::cond );
+		maybe_accept_as_compound( node, &CatchClause::body );
+	}
+
+	VISIT_END( CatchClause, node );
+}
+
+//--------------------------------------------------------------------------
+// FinallyClause
+template< typename core_t >
+const ast::FinallyClause * ast::Pass< core_t >::visit( const ast::FinallyClause * node ) {
+	VISIT_START( node );
+
+	if ( __visit_children() ) {
+		maybe_accept( node, &FinallyClause::body );
+	}
+
+	VISIT_END( FinallyClause, node );
 }
 
@@ -1054,12 +1054,12 @@
 			auto n = __pass::mutate<core_t>(node);
 			for(size_t i = 0; i < new_clauses.size(); i++) {
-				if(new_clauses.at(i).target.func != nullptr) std::swap(n->clauses.at(i).target.func, new_clauses.at(i).target.func);
+				if(new_clauses.at(i).target.func != nullptr) swap(n->clauses.at(i).target.func, new_clauses.at(i).target.func);
 
 				for(size_t j = 0; j < new_clauses.at(i).target.args.size(); j++) {
-					if(new_clauses.at(i).target.args.at(j) != nullptr) std::swap(n->clauses.at(i).target.args.at(j), new_clauses.at(i).target.args.at(j));
+					if(new_clauses.at(i).target.args.at(j) != nullptr) swap(n->clauses.at(i).target.args.at(j), new_clauses.at(i).target.args.at(j));
 				}
 
-				if(new_clauses.at(i).stmt != nullptr) std::swap(n->clauses.at(i).stmt, new_clauses.at(i).stmt);
-				if(new_clauses.at(i).cond != nullptr) std::swap(n->clauses.at(i).cond, new_clauses.at(i).cond);
+				if(new_clauses.at(i).stmt != nullptr) swap(n->clauses.at(i).stmt, new_clauses.at(i).stmt);
+				if(new_clauses.at(i).cond != nullptr) swap(n->clauses.at(i).cond, new_clauses.at(i).cond);
 			}
 			node = n;
@@ -2151,18 +2151,16 @@
 
 	if ( __visit_children() ) {
-		{
-			bool mutated = false;
-			std::unordered_map< ast::TypeInstType::TypeEnvKey, ast::ptr< ast::Type > > new_map;
-			for ( const auto & p : node->typeEnv ) {
-				guard_symtab guard { *this };
-				auto new_node = p.second->accept( *this );
-				if (new_node != p.second) mutated = true;
-				new_map.insert({ p.first, new_node });
-			}
-			if (mutated) {
-				auto new_node = __pass::mutate<core_t>( node );
-				new_node->typeEnv.swap( new_map );
-				node = new_node;
-			}
+		bool mutated = false;
+		std::unordered_map< ast::TypeInstType::TypeEnvKey, ast::ptr< ast::Type > > new_map;
+		for ( const auto & p : node->typeEnv ) {
+			guard_symtab guard { *this };
+			auto new_node = p.second->accept( *this );
+			if (new_node != p.second) mutated = true;
+			new_map.insert({ p.first, new_node });
+		}
+		if (mutated) {
+			auto new_node = __pass::mutate<core_t>( node );
+			new_node->typeEnv.swap( new_map );
+			node = new_node;
 		}
 	}
Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/Print.cpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -597,5 +597,5 @@
 
 		++indent;
-		for ( const ast::Stmt * stmt : node->stmts ) {
+		for ( const ast::CaseClause * stmt : node->cases ) {
 			stmt->accept( *this );
 		}
@@ -605,5 +605,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::CaseStmt * node ) override final {
+	virtual const ast::CaseClause * visit( const ast::CaseClause * node ) override final {
 		if ( node->isDefault() ) {
 			os << indent << "Default ";
@@ -687,5 +687,5 @@
 
 		os << indent-1 << "... and handlers:" << endl;
-		for ( const ast::CatchStmt * stmt : node->handlers ) {
+		for ( const ast::CatchClause * stmt : node->handlers ) {
 			os << indent;
 			stmt->accept( *this );
@@ -701,5 +701,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::CatchStmt * node ) override final {
+	virtual const ast::CatchClause * visit( const ast::CatchClause * node ) override final {
 		os << "Catch ";
 		switch ( node->kind ) {
@@ -726,5 +726,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::FinallyStmt * node ) override final {
+	virtual const ast::FinallyClause * visit( const ast::FinallyClause * node ) override final {
 		os << "Finally Statement" << endl;
 		os << indent << "... with block:" << endl;
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/Stmt.hpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -9,7 +9,7 @@
 // Author           : Aaron B. Moss
 // Created On       : Wed May  8 13:00:00 2019
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  2 20:06:41 2022
-// Update Count     : 34
+// Last Modified By : Andrew Beach
+// Last Modified On : Mon Mar 28  9:50:00 2022
+// Update Count     : 35
 //
 
@@ -47,4 +47,20 @@
   private:
 	Stmt * clone() const override = 0;
+	MUTATE_FRIEND
+};
+
+// Base statement component node (only serves to group them).
+class StmtClause : public ParseNode {
+  public:
+	// This is for non-statements that still belong with the statements,
+	// but are not statements, usually some sort of clause. Often these can
+	// (and should) be folded into the approprate parent node, but if they
+	// cannot be, they are sub-types of this type, for organization.
+
+    StmtClause( const CodeLocation & loc )
+		: ParseNode(loc) {}
+
+  private:
+	StmtClause * clone() const override = 0;
 	MUTATE_FRIEND
 };
@@ -158,32 +174,32 @@
   public:
 	ptr<Expr> cond;
+	std::vector<ptr<CaseClause>> cases;
+
+	SwitchStmt( const CodeLocation & loc, const Expr * cond,
+				const std::vector<ptr<CaseClause>> && cases,
+				const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), cond(cond), cases(std::move(cases)) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
+	SwitchStmt * clone() const override { return new SwitchStmt{ *this }; }
+	MUTATE_FRIEND
+};
+
+// Case label: case ...: or default:
+class CaseClause final : public StmtClause {
+  public:
+	// Null for the default label.
+	ptr<Expr> cond;
 	std::vector<ptr<Stmt>> stmts;
 
-	SwitchStmt( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts,
-				const std::vector<Label> && labels = {} )
-		: Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-  private:
-	SwitchStmt * clone() const override { return new SwitchStmt{ *this }; }
-	MUTATE_FRIEND
-};
-
-// Case label: case ...: or default:
-class CaseStmt final : public Stmt {
-  public:
-	// Null for the default label.
-	ptr<Expr> cond;
-	std::vector<ptr<Stmt>> stmts;
-
-	CaseStmt( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts,
-			  const std::vector<Label> && labels = {} )
-		: Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
+	CaseClause( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts )
+		: StmtClause(loc), cond(cond), stmts(std::move(stmts)) {}
 
 	bool isDefault() const { return !cond; }
 
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-  private:
-	CaseStmt * clone() const override { return new CaseStmt{ *this }; }
+	const CaseClause * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
+	CaseClause * clone() const override { return new CaseClause{ *this }; }
 	MUTATE_FRIEND
 };
@@ -298,9 +314,9 @@
   public:
 	ptr<CompoundStmt> body;
-	std::vector<ptr<CatchStmt>> handlers;
-	ptr<FinallyStmt> finally;
+	std::vector<ptr<CatchClause>> handlers;
+	ptr<FinallyClause> finally;
 
 	TryStmt( const CodeLocation & loc, const CompoundStmt * body,
-			 const std::vector<ptr<CatchStmt>> && handlers, const FinallyStmt * finally,
+			 const std::vector<ptr<CatchClause>> && handlers, const FinallyClause * finally,
 			 const std::vector<Label> && labels = {} )
 		: Stmt(loc, std::move(labels)), body(body), handlers(std::move(handlers)), finally(finally) {}
@@ -313,5 +329,5 @@
 
 // Catch clause of try statement
-class CatchStmt final : public Stmt {
+class CatchClause final : public StmtClause {
   public:
 	ptr<Decl> decl;
@@ -320,26 +336,25 @@
 	ExceptionKind kind;
 
-	CatchStmt( const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond,
-			   const Stmt * body, const std::vector<Label> && labels = {} )
-		: Stmt(loc, std::move(labels)), decl(decl), cond(cond), body(body), kind(kind) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-  private:
-	CatchStmt * clone() const override { return new CatchStmt{ *this }; }
+	CatchClause( const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond,
+			   const Stmt * body )
+		: StmtClause(loc), decl(decl), cond(cond), body(body), kind(kind) {}
+
+	const CatchClause * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
+	CatchClause * clone() const override { return new CatchClause{ *this }; }
 	MUTATE_FRIEND
 };
 
 // Finally clause of try statement
-class FinallyStmt final : public Stmt {
+class FinallyClause final : public StmtClause {
   public:
 	ptr<CompoundStmt> body;
 
-	FinallyStmt( const CodeLocation & loc, const CompoundStmt * body,
-				 std::vector<Label> && labels = {} )
-		: Stmt(loc, std::move(labels)), body(body) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-  private:
-	FinallyStmt * clone() const override { return new FinallyStmt{ *this }; }
+	FinallyClause( const CodeLocation & loc, const CompoundStmt * body )
+		: StmtClause(loc), body(body) {}
+
+	const FinallyClause * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
+	FinallyClause * clone() const override { return new FinallyClause{ *this }; }
 	MUTATE_FRIEND
 };
Index: src/AST/TranslationUnit.hpp
===================================================================
--- src/AST/TranslationUnit.hpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/TranslationUnit.hpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -10,6 +10,6 @@
 // Created On       : Tue Jun 11 15:30:00 2019
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue Jun 11 15:42:00 2019
-// Update Count     : 0
+// Last Modified On : Tue Mar 11 11:19:00 2022
+// Update Count     : 1
 //
 
@@ -23,16 +23,18 @@
 namespace ast {
 
+class TranslationGlobal {
+public:
+	std::map< UniqueId, Decl * > idMap;
+
+	ptr<Type> sizeType;
+	const FunctionDecl * dereference;
+	const StructDecl * dtorStruct;
+	const FunctionDecl * dtorDestroy;
+};
+
 class TranslationUnit {
 public:
 	std::list< ptr< Decl > > decls;
-
-	struct Global {
-		std::map< UniqueId, Decl * > idMap;
-
-		ptr<Type> sizeType;
-		const FunctionDecl * dereference;
-		const StructDecl * dtorStruct;
-		const FunctionDecl * dtorDestroy;
-	} global;
+	TranslationGlobal global;
 };
 
Index: src/AST/Type.cpp
===================================================================
--- src/AST/Type.cpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/Type.cpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -147,4 +147,8 @@
 // --- TypeInstType
 
+TypeInstType::TypeInstType( const TypeDecl * b,
+	CV::Qualifiers q, std::vector<ptr<Attribute>> && as )
+: BaseInstType( b->name, q, move(as) ), base( b ), kind( b->kind ) {}
+
 void TypeInstType::set_base( const TypeDecl * b ) {
 	base = b;
Index: src/AST/Type.hpp
===================================================================
--- src/AST/Type.hpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/Type.hpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -421,4 +421,8 @@
 		std::vector<ptr<Attribute>> && as = {} )
 	: BaseInstType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
+
+	TypeInstType( const TypeDecl * b,
+		CV::Qualifiers q = {}, std::vector<ptr<Attribute>> && as = {} );
+
 	TypeInstType( const std::string& n, TypeDecl::Kind k, CV::Qualifiers q = {},
 		std::vector<ptr<Attribute>> && as = {} )
Index: src/AST/TypeSubstitution.hpp
===================================================================
--- src/AST/TypeSubstitution.hpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/TypeSubstitution.hpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -37,4 +37,6 @@
   public:
 	TypeSubstitution();
+	template< typename FormalContainer, typename ActualContainer >
+	TypeSubstitution( FormalContainer formals, ActualContainer actuals );
 	template< typename FormalIterator, typename ActualIterator >
 	TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
@@ -76,6 +78,8 @@
 	bool empty() const;
 
+	template< typename FormalContainer, typename ActualContainer >
+	void addAll( FormalContainer formals, ActualContainer actuals );
 	template< typename FormalIterator, typename ActualIterator >
-	void add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
+	void addAll( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
 
 	/// create a new TypeSubstitution using bindings from env containing all of the type variables in expr
@@ -112,7 +116,24 @@
 };
 
+template< typename FormalContainer, typename ActualContainer >
+TypeSubstitution::TypeSubstitution( FormalContainer formals, ActualContainer actuals ) {
+	assert( formals.size() == actuals.size() );
+	addAll( formals.begin(), formals.end(), actuals.begin() );
+}
+
+template< typename FormalIterator, typename ActualIterator >
+TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
+	addAll( formalBegin, formalEnd, actualBegin );
+}
+
+template< typename FormalContainer, typename ActualContainer >
+void TypeSubstitution::addAll( FormalContainer formals, ActualContainer actuals ) {
+	assert( formals.size() == actuals.size() );
+	addAll( formals.begin(), formals.end(), actuals.begin() );
+}
+
 // this is the only place where type parameters outside a function formal may be substituted.
 template< typename FormalIterator, typename ActualIterator >
-void TypeSubstitution::add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
+void TypeSubstitution::addAll( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
 	// FormalIterator points to a TypeDecl
 	// ActualIterator points to a Type
@@ -129,16 +150,8 @@
 			} // if
 		} else {
-			
+			// Is this an error?
 		} // if
 	} // for
 }
-
-
-
-template< typename FormalIterator, typename ActualIterator >
-TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
-	add( formalBegin, formalEnd, actualBegin );
-}
-
 
 } // namespace ast
Index: src/AST/Util.cpp
===================================================================
--- src/AST/Util.cpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
+++ src/AST/Util.cpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -0,0 +1,80 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Util.hpp -- General utilities for working with the AST.
+//
+// Author           : Andrew Beach
+// Created On       : Wed Jan 19  9:46:00 2022
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Mar 11 18:07:00 2022
+// Update Count     : 1
+//
+
+#include "Util.hpp"
+
+#include "Node.hpp"
+#include "ParseNode.hpp"
+#include "Pass.hpp"
+#include "TranslationUnit.hpp"
+
+#include <vector>
+
+namespace ast {
+
+namespace {
+
+/// Check that ast::ptr/strong references do not form a cycle.
+struct NoStrongCyclesCore {
+	std::vector<const Node *> parents;
+
+	void previsit( const Node * node ) {
+		for ( auto & parent : parents ) {
+			assert( parent != node );
+		}
+		parents.push_back( node );
+	}
+
+	void postvisit( const Node * node ) {
+		assert( !parents.empty() );
+		assert( parents.back() == node );
+		parents.pop_back();
+	}
+};
+
+/// Check that every note that can has a set CodeLocation.
+struct SetCodeLocationsCore {
+	void previsit( const ParseNode * node ) {
+		assert( node->location.isSet() );
+	}
+};
+
+struct InvariantCore {
+	// To save on the number of visits: this is a kind of composed core.
+	// None of the passes should make changes so ordering doesn't matter.
+	NoStrongCyclesCore no_strong_cycles;
+	SetCodeLocationsCore set_code_locations;
+
+	void previsit( const Node * node ) {
+		no_strong_cycles.previsit( node );
+	}
+
+	void previsit( const ParseNode * node ) {
+		no_strong_cycles.previsit( node );
+		set_code_locations.previsit( node );
+	}
+
+	void postvisit( const Node * node ) {
+		no_strong_cycles.postvisit( node );
+	}
+};
+
+} // namespace
+
+void checkInvariants( TranslationUnit & transUnit ) {
+	ast::Pass<InvariantCore>::run( transUnit );
+}
+
+} // namespace ast
Index: src/AST/Util.hpp
===================================================================
--- src/AST/Util.hpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
+++ src/AST/Util.hpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -0,0 +1,26 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Util.hpp -- General utilities for working with the AST.
+//
+// Author           : Andrew Beach
+// Created On       : Wed Jan 19  9:37:00 2022
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Feb 18  9:43:00 2022
+// Update Count     : 0
+//
+
+#pragma once
+
+namespace ast {
+
+class TranslationUnit;
+
+/// Check anything that should always be true of the AST between passes.
+/// Insert this whenever you want additional debugging checks.
+void checkInvariants( TranslationUnit & transUnit );
+
+}
Index: src/AST/Visitor.hpp
===================================================================
--- src/AST/Visitor.hpp	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/Visitor.hpp	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -41,11 +41,11 @@
     virtual const ast::Stmt *             visit( const ast::ForStmt              * ) = 0;
     virtual const ast::Stmt *             visit( const ast::SwitchStmt           * ) = 0;
-    virtual const ast::Stmt *             visit( const ast::CaseStmt             * ) = 0;
+    virtual const ast::CaseClause *       visit( const ast::CaseClause           * ) = 0;
     virtual const ast::Stmt *             visit( const ast::BranchStmt           * ) = 0;
     virtual const ast::Stmt *             visit( const ast::ReturnStmt           * ) = 0;
     virtual const ast::Stmt *             visit( const ast::ThrowStmt            * ) = 0;
     virtual const ast::Stmt *             visit( const ast::TryStmt              * ) = 0;
-    virtual const ast::Stmt *             visit( const ast::CatchStmt            * ) = 0;
-    virtual const ast::Stmt *             visit( const ast::FinallyStmt          * ) = 0;
+    virtual const ast::CatchClause *      visit( const ast::CatchClause          * ) = 0;
+    virtual const ast::FinallyClause *    visit( const ast::FinallyClause        * ) = 0;
     virtual const ast::Stmt *             visit( const ast::SuspendStmt          * ) = 0;
     virtual const ast::Stmt *             visit( const ast::WaitForStmt          * ) = 0;
Index: src/AST/module.mk
===================================================================
--- src/AST/module.mk	(revision 4559b34425030aa5ff5e6be7a0d6e46d70ae6fec)
+++ src/AST/module.mk	(revision d8e2a09543f35ee50941fc5ef2b7d98498ebe3b7)
@@ -16,6 +16,4 @@
 
 SRC_AST = \
-	AST/AssertAcyclic.cpp \
-	AST/AssertAcyclic.hpp \
 	AST/Attribute.cpp \
 	AST/Attribute.hpp \
@@ -64,4 +62,6 @@
 	AST/TypeSubstitution.cpp \
 	AST/TypeSubstitution.hpp \
+	AST/Util.cpp \
+	AST/Util.hpp \
 	AST/Visitor.hpp
 
