Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
+++ src/SymTab/Autogen.cc	(revision 8a919cfec5f277378c3bc7e5d16717f7d44058c6)
@@ -10,6 +10,6 @@
 // Created On       : Thu Mar 03 15:45:56 2016
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Apr 27 14:39:06 2018
-// Update Count     : 63
+// Last Modified On : Fri Apr 14 15:03:00 2023
+// Update Count     : 64
 //
 
@@ -211,8 +211,4 @@
 	}
 
-	bool isUnnamedBitfield( const ast::ObjectDecl * obj ) {
-		return obj && obj->name.empty() && obj->bitfieldWidth;
-	}
-
 	/// inserts a forward declaration for functionDecl into declsToAdd
 	void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) {
@@ -234,15 +230,4 @@
 	}
 
-	// shallow copy the pointer list for return
-	std::vector<ast::ptr<ast::TypeDecl>> getGenericParams (const ast::Type * t) {
-		if (auto structInst = dynamic_cast<const ast::StructInstType*>(t)) {
-			return structInst->base->params;
-		}
-		if (auto unionInst = dynamic_cast<const ast::UnionInstType*>(t)) {
-			return unionInst->base->params;
-		}
-		return {};
-	}
-
 	/// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
 	FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) {
@@ -256,12 +241,4 @@
 		ftype->parameters.push_back( dstParam );
 		return ftype;
-	}
-
-	/// Given type T, generate type of default ctor/dtor, i.e. function type void (*) (T &).
-	ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic) {
-		std::vector<ast::ptr<ast::TypeDecl>> typeParams;
-		if (maybePolymorphic) typeParams = getGenericParams(paramType);
-		auto dstParam = new ast::ObjectDecl(loc, "_dst", new ast::ReferenceType(paramType), nullptr, {}, ast::Linkage::Cforall);
-		return new ast::FunctionDecl(loc, fname, std::move(typeParams), {dstParam}, {}, new ast::CompoundStmt(loc), {}, ast::Linkage::Cforall);
 	}
 
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
+++ src/SymTab/Autogen.h	(revision 8a919cfec5f277378c3bc7e5d16717f7d44058c6)
@@ -9,7 +9,7 @@
 // Author           : Rob Schluntz
 // Created On       : Sun May 17 21:53:34 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Dec 13 16:38:06 2019
-// Update Count     : 16
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Apr 14 15:06:00 2023
+// Update Count     : 17
 //
 
@@ -45,5 +45,4 @@
 	/// returns true if obj's name is the empty string and it has a bitfield width
 	bool isUnnamedBitfield( ObjectDecl * obj );
-	bool isUnnamedBitfield( const ast::ObjectDecl * obj );
 
 	/// generate the type of an assignment function for paramType.
@@ -55,6 +54,4 @@
 	FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
 
-	ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic = true);
-
 	/// generate the type of a copy constructor for paramType.
 	/// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
@@ -67,10 +64,4 @@
 	template< typename OutputIterator >
 	Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
-
-	template< typename OutIter >
-	ast::ptr< ast::Stmt > genCall(
-		InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
-		const CodeLocation & loc, const std::string & fname, OutIter && out,
-		const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );
 
 	/// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
@@ -121,61 +112,4 @@
 
 		*out++ = new ExprStmt( fExpr );
-
-		srcParam.clearArrayIndices();
-
-		return listInit;
-	}
-
-	/// inserts into out a generated call expression to function fname with arguments dstParam and
-	/// srcParam. Should only be called with non-array types.
-	/// optionally returns a statement which must be inserted prior to the containing loop, if
-	/// there is one
-	template< typename OutIter >
-	ast::ptr< ast::Stmt > genScalarCall(
-		InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
-		const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,
-		const ast::Type * addCast = nullptr
-	) {
-		bool isReferenceCtorDtor = false;
-		if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
-			// reference constructors are essentially application of the rebind operator.
-			// apply & to both arguments, do not need a cast
-			fname = "?=?";
-			dstParam = new ast::AddressExpr{ dstParam };
-			addCast = nullptr;
-			isReferenceCtorDtor = true;
-		}
-
-		// want to be able to generate assignment, ctor, and dtor generically, so fname is one of
-		// "?=?", "?{}", or "^?{}"
-		ast::UntypedExpr * fExpr = new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, fname } };
-
-		if ( addCast ) {
-			// cast to T& with qualifiers removed, so that qualified objects can be constructed and
-			// destructed with the same functions as non-qualified objects. Unfortunately, lvalue
-			// is considered a qualifier - for AddressExpr to resolve, its argument must have an
-			// lvalue-qualified type, so remove all qualifiers except lvalue.
-			// xxx -- old code actually removed lvalue too...
-			ast::ptr< ast::Type > guard = addCast;  // prevent castType from mutating addCast
-			ast::ptr< ast::Type > castType = addCast;
-			ast::remove_qualifiers(
-				castType,
-				ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic );
-			dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } };
-		}
-		fExpr->args.emplace_back( dstParam );
-
-		ast::ptr<ast::Stmt> listInit = srcParam.buildListInit( fExpr );
-
-		// fetch next set of arguments
-		++srcParam;
-
-		// return if adding reference fails -- will happen on default ctor and dtor
-		if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit;
-
-		std::vector< ast::ptr< ast::Expr > > args = *srcParam;
-		splice( fExpr->args, args );
-
-		*out++ = new ast::ExprStmt{ loc, fExpr };
 
 		srcParam.clearArrayIndices();
@@ -248,74 +182,4 @@
 	}
 
-	/// Store in out a loop which calls fname on each element of the array with srcParam and
-	/// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0
-	template< typename OutIter >
-	void genArrayCall(
-		InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
-		const CodeLocation & loc, const std::string & fname, OutIter && out,
-		const ast::ArrayType * array, const ast::Type * addCast = nullptr,
-		LoopDirection forward = LoopForward
-	) {
-		static UniqueName indexName( "_index" );
-
-		// for a flexible array member nothing is done -- user must define own assignment
-		if ( ! array->dimension ) return;
-
-		if ( addCast ) {
-			// peel off array layer from cast
-			addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base;
-		}
-
-		ast::ptr< ast::Expr > begin, end;
-		std::string cmp, update;
-
-		if ( forward ) {
-			// generate: for ( int i = 0; i < N; ++i )
-			begin = ast::ConstantExpr::from_int( loc, 0 );
-			end = array->dimension;
-			cmp = "?<?";
-			update = "++?";
-		} else {
-			// generate: for ( int i = N-1; i >= 0; --i )
-			begin = ast::UntypedExpr::createCall( loc, "?-?",
-				{ array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } );
-			end = ast::ConstantExpr::from_int( loc, 0 );
-			cmp = "?>=?";
-			update = "--?";
-		}
-
-		ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl{
-			loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },
-			new ast::SingleInit{ loc, begin } };
-		ast::ptr< ast::Expr > indexVar = new ast::VariableExpr{ loc, index };
-
-		ast::ptr< ast::Expr > cond = ast::UntypedExpr::createCall(
-			loc, cmp, { indexVar, end } );
-
-		ast::ptr< ast::Expr > inc = ast::UntypedExpr::createCall(
-			loc, update, { indexVar } );
-
-		ast::ptr< ast::Expr > dstIndex = ast::UntypedExpr::createCall(
-			loc, "?[?]", { dstParam, indexVar } );
-
-		// srcParam must keep track of the array indices to build the source parameter and/or
-		// array list initializer
-		srcParam.addArrayIndex( indexVar, array->dimension );
-
-		// for stmt's body, eventually containing call
-		ast::CompoundStmt * body = new ast::CompoundStmt{ loc };
-		ast::ptr< ast::Stmt > listInit = genCall(
-			srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast,
-			forward );
-
-		// block containing the stmt and index variable
-		ast::CompoundStmt * block = new ast::CompoundStmt{ loc };
-		block->push_back( new ast::DeclStmt{ loc, index } );
-		if ( listInit ) { block->push_back( listInit ); }
-		block->push_back( new ast::ForStmt{ loc, {}, cond, inc, body } );
-
-		*out++ = block;
-	}
-
 	template< typename OutputIterator >
 	Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
@@ -325,21 +189,4 @@
 		} else {
 			return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
-		}
-	}
-
-	template< typename OutIter >
-	ast::ptr< ast::Stmt > genCall(
-		InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
-		const CodeLocation & loc, const std::string & fname, OutIter && out,
-		const ast::Type * type, const ast::Type * addCast, LoopDirection forward
-	) {
-		if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
-			genArrayCall(
-				srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,
-				forward );
-			return {};
-		} else {
-			return genScalarCall(
-				srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast );
 		}
 	}
@@ -379,37 +226,4 @@
 	}
 
-	static inline ast::ptr< ast::Stmt > genImplicitCall(
-		InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
-		const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
-		LoopDirection forward = LoopForward
-	) {
-		// unnamed bit fields are not copied as they cannot be accessed
-		if ( isUnnamedBitfield( obj ) ) return {};
-
-		ast::ptr< ast::Type > addCast;
-		if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
-			assert( dstParam->result );
-			addCast = dstParam->result;
-		}
-
-		std::vector< ast::ptr< ast::Stmt > > stmts;
-		genCall(
-			srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );
-
-		if ( stmts.empty() ) {
-			return {};
-		} else if ( stmts.size() == 1 ) {
-			const ast::Stmt * callStmt = stmts.front();
-			if ( addCast ) {
-				// implicitly generated ctor/dtor calls should be wrapped so that later passes are
-				// aware they were generated.
-				callStmt = new ast::ImplicitCtorDtorStmt{ callStmt->location, callStmt };
-			}
-			return callStmt;
-		} else {
-			assert( false );
-			return {};
-		}
-	}
 } // namespace SymTab
 
Index: src/SymTab/GenImplicitCall.cpp
===================================================================
--- src/SymTab/GenImplicitCall.cpp	(revision 8a919cfec5f277378c3bc7e5d16717f7d44058c6)
+++ src/SymTab/GenImplicitCall.cpp	(revision 8a919cfec5f277378c3bc7e5d16717f7d44058c6)
@@ -0,0 +1,217 @@
+//
+// 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.
+//
+// GenImplicitCall.hpp --
+//
+// Author           : Andrew Beach
+// Created On       : Fri Apr 14 14:38:00 2023
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Apr 14 14:46:00 2023
+// Update Count     : 0
+//
+
+#include "GenImplicitCall.hpp"
+
+#include "AST/Inspect.hpp"               // for isUnnamedBitfield
+#include "CodeGen/OperatorTable.h"       // for isCtorDtor
+#include "Common/UniqueName.h"           // for UniqueName
+
+namespace SymTab {
+
+template< typename OutIter >
+ast::ptr< ast::Stmt > genCall(
+	InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
+	const CodeLocation & loc, const std::string & fname, OutIter && out,
+	const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );
+
+/// inserts into out a generated call expression to function fname with arguments dstParam and
+/// srcParam. Should only be called with non-array types.
+/// optionally returns a statement which must be inserted prior to the containing loop, if
+/// there is one
+template< typename OutIter >
+ast::ptr< ast::Stmt > genScalarCall(
+	InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
+	const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,
+	const ast::Type * addCast = nullptr
+) {
+	bool isReferenceCtorDtor = false;
+	if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
+		// reference constructors are essentially application of the rebind operator.
+		// apply & to both arguments, do not need a cast
+		fname = "?=?";
+		dstParam = new ast::AddressExpr( dstParam );
+		addCast = nullptr;
+		isReferenceCtorDtor = true;
+	}
+
+	// want to be able to generate assignment, ctor, and dtor generically, so fname is one of
+	// "?=?", "?{}", or "^?{}"
+	ast::UntypedExpr * fExpr = new ast::UntypedExpr( loc, new ast::NameExpr( loc, fname ) );
+
+	if ( addCast ) {
+		// cast to T& with qualifiers removed, so that qualified objects can be constructed and
+		// destructed with the same functions as non-qualified objects. Unfortunately, lvalue
+		// is considered a qualifier - for AddressExpr to resolve, its argument must have an
+		// lvalue-qualified type, so remove all qualifiers except lvalue.
+		// xxx -- old code actually removed lvalue too...
+		ast::ptr< ast::Type > guard = addCast;  // prevent castType from mutating addCast
+		ast::ptr< ast::Type > castType = addCast;
+		ast::remove_qualifiers(
+			castType,
+			ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic );
+			dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } };
+	}
+	fExpr->args.emplace_back( dstParam );
+
+	ast::ptr<ast::Stmt> listInit = srcParam.buildListInit( fExpr );
+
+	// fetch next set of arguments
+	++srcParam;
+
+	// return if adding reference fails -- will happen on default ctor and dtor
+	if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit;
+
+	std::vector< ast::ptr< ast::Expr > > args = *srcParam;
+	splice( fExpr->args, args );
+
+	*out++ = new ast::ExprStmt{ loc, fExpr };
+
+	srcParam.clearArrayIndices();
+
+	return listInit;
+}
+
+
+/// Store in out a loop which calls fname on each element of the array with srcParam and
+/// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0
+template< typename OutIter >
+void genArrayCall(
+	InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
+	const CodeLocation & loc, const std::string & fname, OutIter && out,
+	const ast::ArrayType * array, const ast::Type * addCast = nullptr,
+	LoopDirection forward = LoopForward
+) {
+	static UniqueName indexName( "_index" );
+
+	// for a flexible array member nothing is done -- user must define own assignment
+	if ( ! array->dimension ) return;
+
+	if ( addCast ) {
+		// peel off array layer from cast
+		addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base;
+	}
+
+	ast::ptr< ast::Expr > begin, end;
+	std::string cmp, update;
+
+	if ( forward ) {
+		// generate: for ( int i = 0; i < N; ++i )
+		begin = ast::ConstantExpr::from_int( loc, 0 );
+		end = array->dimension;
+		cmp = "?<?";
+		update = "++?";
+	} else {
+		// generate: for ( int i = N-1; i >= 0; --i )
+		begin = ast::UntypedExpr::createCall( loc, "?-?",
+			{ array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } );
+		end = ast::ConstantExpr::from_int( loc, 0 );
+		cmp = "?>=?";
+		update = "--?";
+	}
+
+	ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl(
+		loc, indexName.newName(), new ast::BasicType( ast::BasicType::SignedInt ),
+		new ast::SingleInit( loc, begin ) );
+	ast::ptr< ast::Expr > indexVar = new ast::VariableExpr( loc, index );
+
+	ast::ptr< ast::Expr > cond = ast::UntypedExpr::createCall(
+		loc, cmp, { indexVar, end } );
+
+	ast::ptr< ast::Expr > inc = ast::UntypedExpr::createCall(
+		loc, update, { indexVar } );
+
+	ast::ptr< ast::Expr > dstIndex = ast::UntypedExpr::createCall(
+		loc, "?[?]", { dstParam, indexVar } );
+
+	// srcParam must keep track of the array indices to build the source parameter and/or
+	// array list initializer
+	srcParam.addArrayIndex( indexVar, array->dimension );
+
+	// for stmt's body, eventually containing call
+	ast::CompoundStmt * body = new ast::CompoundStmt( loc );
+	ast::ptr< ast::Stmt > listInit = genCall(
+		srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast,
+		forward );
+
+	// block containing the stmt and index variable
+	ast::CompoundStmt * block = new ast::CompoundStmt( loc );
+	block->push_back( new ast::DeclStmt( loc, index ) );
+	if ( listInit ) { block->push_back( listInit ); }
+	block->push_back( new ast::ForStmt( loc, {}, cond, inc, body ) );
+
+	*out++ = block;
+}
+
+template< typename OutIter >
+ast::ptr< ast::Stmt > genCall(
+	InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
+	const CodeLocation & loc, const std::string & fname, OutIter && out,
+	const ast::Type * type, const ast::Type * addCast, LoopDirection forward
+) {
+	if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
+		genArrayCall(
+			srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,
+			forward );
+		return {};
+	} else {
+		return genScalarCall(
+			srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast );
+	}
+}
+
+ast::ptr< ast::Stmt > genImplicitCall(
+	InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
+	const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
+	LoopDirection forward
+) {
+	// unnamed bit fields are not copied as they cannot be accessed
+	if ( isUnnamedBitfield( obj ) ) return {};
+
+	ast::ptr< ast::Type > addCast;
+	if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
+		assert( dstParam->result );
+		addCast = dstParam->result;
+	}
+
+	std::vector< ast::ptr< ast::Stmt > > stmts;
+	genCall(
+		srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );
+
+	if ( stmts.empty() ) {
+		return {};
+	} else if ( stmts.size() == 1 ) {
+		const ast::Stmt * callStmt = stmts.front();
+		if ( addCast ) {
+			// implicitly generated ctor/dtor calls should be wrapped so that later passes are
+			// aware they were generated.
+			callStmt = new ast::ImplicitCtorDtorStmt( callStmt->location, callStmt );
+		}
+		return callStmt;
+	} else {
+		assert( false );
+		return {};
+	}
+}
+
+} // namespace SymTab
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
+
+
Index: src/SymTab/GenImplicitCall.hpp
===================================================================
--- src/SymTab/GenImplicitCall.hpp	(revision 8a919cfec5f277378c3bc7e5d16717f7d44058c6)
+++ src/SymTab/GenImplicitCall.hpp	(revision 8a919cfec5f277378c3bc7e5d16717f7d44058c6)
@@ -0,0 +1,36 @@
+//
+// 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.
+//
+// GenImplicitCall.hpp --
+//
+// Author           : Andrew Beach
+// Created On       : Fri Apr 14 14:29:00 2023
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Apr 14 14:29:00 2023
+// Update Count     : 0
+//
+
+#pragma once
+
+#include "InitTweak/InitTweak.h"  // for InitExpander
+#include "SymTab/Autogen.h"       // for LoopDirection
+
+namespace SymTab {
+
+ast::ptr<ast::Stmt> genImplicitCall(
+	InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
+	const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
+	LoopDirection forward = LoopForward
+);
+
+} // namespace SymTab
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
+
Index: src/SymTab/module.mk
===================================================================
--- src/SymTab/module.mk	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
+++ src/SymTab/module.mk	(revision 8a919cfec5f277378c3bc7e5d16717f7d44058c6)
@@ -20,4 +20,6 @@
 	SymTab/FixFunction.cc \
 	SymTab/FixFunction.h \
+	SymTab/GenImplicitCall.cpp \
+	SymTab/GenImplicitCall.hpp \
 	SymTab/Indexer.cc \
 	SymTab/Indexer.h \
