Index: src/AST/Copy.cpp
===================================================================
--- src/AST/Copy.cpp	(revision 3249dd8b090e8deb3ea0c7a3cc02a9fd797487de)
+++ src/AST/Copy.cpp	(revision 3249dd8b090e8deb3ea0c7a3cc02a9fd797487de)
@@ -0,0 +1,120 @@
+//
+// 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.
+//
+// Copy.cpp -- Provides functions to copy the AST.
+//
+// Author           : Andrew Beach
+// Created On       : Thr Nov 11  9:16:00 2019
+// Last Modified By : Andrew Beach
+// Last Modified On : Thr Nov 11  9:28:00 2021
+// Update Count     : 0
+//
+
+#include "Copy.hpp"
+
+#include "Decl.hpp"
+#include "Expr.hpp"
+#include "Pass.hpp"
+#include "Stmt.hpp"
+#include "Type.hpp"
+#include <unordered_set>
+#include <unordered_map>
+
+namespace ast {
+
+namespace {
+
+class DeepCopyCore {
+	std::unordered_map< const Node *, const Node * > nodeCache;
+	std::unordered_set< readonly<Node> * > readonlyCache;
+
+	template<typename node_t>
+	void readonlyInsert( const readonly<node_t> * ptrptr ) {
+		readonlyCache.insert( (readonly<Node> *) ptrptr );
+	}
+
+public:
+	template<typename node_t>
+	const node_t * previsit( const node_t * node ) {
+		const node_t * copy = shallowCopy( node );
+		nodeCache.insert( std::make_pair( node, copy ) );
+		return copy;
+	}
+
+	void postvisit( const AggregateDecl * node ) {
+		readonlyInsert( &node->parent );
+	}
+
+	void postvisit( const StructInstType * node ) {
+		readonlyInsert( &node->base );
+	}
+
+	void postvisit( const UnionInstType * node ) {
+		readonlyInsert( &node->base );
+	}
+
+	void postvisit( const EnumInstType * node ) {
+		readonlyInsert( &node->base );
+	}
+
+	void postvisit( const TraitInstType * node ) {
+		readonlyInsert( &node->base );
+	}
+
+	void postvisit( const TypeInstType * node ) {
+		readonlyInsert( &node->base );
+	}
+
+	void postvisit( const ImplicitCtorDtorStmt * node ) {
+		readonlyInsert( (const readonly<Stmt> *) &node->callStmt );
+	}
+
+	void postvisit( const StmtExpr * node ) {
+		readonlyInsert( &node->resultExpr );
+	}
+
+	void postvisit( const MemberExpr * node ) {
+		readonlyInsert( &node->member );
+	}
+
+	void postvisit( const VariableExpr * node ) {
+		readonlyInsert( &node->var );
+	}
+
+	void postvisit( const OffsetofExpr * node ) {
+		readonlyInsert( &node->member );
+	}
+
+	void postvisit( const DeletedExpr * node ) {
+		readonlyInsert( &node->deleteStmt );
+	}
+
+	void readonlyUpdates() {
+		for ( readonly<Node> * ptr : readonlyCache ) {
+			auto it = nodeCache.find( ptr->get() );
+			if ( nodeCache.end() != it ) {
+				*ptr = it->second;
+			}
+		}
+	}
+};
+
+}
+
+Node * deepCopyNode( const Node * localRoot ) {
+	Pass< DeepCopyCore > dc;
+	Node const * newRoot = localRoot->accept( dc );
+	dc.core.readonlyUpdates();
+	return const_cast< Node * >( newRoot );
+}
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/AST/Copy.hpp
===================================================================
--- src/AST/Copy.hpp	(revision b7fd9daffd1af20c4c7cc80ac4660136917af20f)
+++ src/AST/Copy.hpp	(revision 3249dd8b090e8deb3ea0c7a3cc02a9fd797487de)
@@ -10,17 +10,12 @@
 // Created On       : Wed Jul 10 16:13:00 2019
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri Jun 19 16:43:00 2020
-// Update Count     : 1
+// Last Modified On : Thr Nov 11  9:22:00 2021
+// Update Count     : 2
 //
 
 #pragma once
 
-#include "Decl.hpp"
-#include "Expr.hpp"
-#include "Pass.hpp"
-#include "Stmt.hpp"
-#include "Type.hpp"
-#include <unordered_set>
-#include <unordered_map>
+#include "Node.hpp"
+#include <cassert>
 
 namespace ast {
@@ -43,79 +38,5 @@
  */
 
-class DeepCopyCore {
-	std::unordered_map< const Node *, const Node * > nodeCache;
-	std::unordered_set< readonly<Node> * > readonlyCache;
-
-	template<typename node_t>
-	void readonlyInsert( const readonly<node_t> * ptrptr ) {
-		readonlyCache.insert( (readonly<Node> *) ptrptr );
-	}
-
-public:
-	template<typename node_t>
-	const node_t * previsit( const node_t * node ) {
-		const node_t * copy = shallowCopy( node );
-		nodeCache.insert( std::make_pair( node, copy ) );
-		return copy;
-	}
-
-	void postvisit( const AggregateDecl * node ) {
-		readonlyInsert( &node->parent );
-	}
-
-	void postvisit( const StructInstType * node ) {
-		readonlyInsert( &node->base );
-	}
-
-	void postvisit( const UnionInstType * node ) {
-		readonlyInsert( &node->base );
-	}
-
-	void postvisit( const EnumInstType * node ) {
-		readonlyInsert( &node->base );
-	}
-
-	void postvisit( const TraitInstType * node ) {
-		readonlyInsert( &node->base );
-	}
-
-	void postvisit( const TypeInstType * node ) {
-		readonlyInsert( &node->base );
-	}
-
-	void postvisit( const ImplicitCtorDtorStmt * node ) {
-		readonlyInsert( (const readonly<Stmt> *) &node->callStmt );
-	}
-
-	void postvisit( const StmtExpr * node ) {
-		readonlyInsert( &node->resultExpr );
-	}
-
-	void postvisit( const MemberExpr * node ) {
-		readonlyInsert( &node->member );
-	}
-
-	void postvisit( const VariableExpr * node ) {
-		readonlyInsert( &node->var );
-	}
-
-	void postvisit( const OffsetofExpr * node ) {
-		readonlyInsert( &node->member );
-	}
-
-	void postvisit( const DeletedExpr * node ) {
-		readonlyInsert( &node->deleteStmt );
-	}
-
-	void readonlyUpdates() {
-		for ( readonly<Node> * ptr : readonlyCache ) {
-			auto it = nodeCache.find( ptr->get() );
-			if ( nodeCache.end() != it ) {
-				*ptr = it->second;
-			}
-		}
-	}
-};
-
+// Implementations:
 template<typename node_t>
 node_t * shallowCopy( const node_t * localRoot ) {
@@ -123,10 +44,9 @@
 }
 
+Node * deepCopyNode( const Node * node );
+
 template<typename node_t>
 node_t * deepCopy( const node_t * localRoot ) {
-	Pass< DeepCopyCore > dc;
-	node_t const * newRoot = strict_dynamic_cast<node_t const*>(localRoot->accept( dc ));
-	dc.core.readonlyUpdates();
-	return const_cast< node_t * >( newRoot );
+	return strict_dynamic_cast<node_t *>( deepCopyNode( localRoot ) );
 }
 
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision b7fd9daffd1af20c4c7cc80ac4660136917af20f)
+++ src/AST/Expr.hpp	(revision 3249dd8b090e8deb3ea0c7a3cc02a9fd797487de)
@@ -767,6 +767,5 @@
 
 /// An expression which must only be evaluated once
-class 
-UniqueExpr final : public Expr {
+class UniqueExpr final : public Expr {
 	static unsigned long long nextId;
 public:
Index: src/AST/module.mk
===================================================================
--- src/AST/module.mk	(revision b7fd9daffd1af20c4c7cc80ac4660136917af20f)
+++ src/AST/module.mk	(revision 3249dd8b090e8deb3ea0c7a3cc02a9fd797487de)
@@ -24,4 +24,5 @@
 	AST/Convert.cpp \
 	AST/Convert.hpp \
+	AST/Copy.cpp \
 	AST/Copy.hpp \
 	AST/CVQualifiers.hpp \
