Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision b69233aced1c8e524868a8ea35b14931e9676cf1)
+++ src/SymTab/Autogen.cc	(revision b8524ca1420ff28d69347f46888a20baa805f797)
@@ -24,4 +24,5 @@
 #include <vector>                  // for vector
 
+#include "AST/Decl.hpp"
 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
 #include "Common/PassVisitor.h"    // for PassVisitor
@@ -209,4 +210,8 @@
 	}
 
+	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 ) {
@@ -388,5 +393,5 @@
 
 	void StructFuncGenerator::makeMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward ) {
-		InitTweak::InitExpander srcParam( src );
+		InitTweak::InitExpander_old srcParam( src );
 
 		// assign to destination
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision b69233aced1c8e524868a8ea35b14931e9676cf1)
+++ src/SymTab/Autogen.h	(revision b8524ca1420ff28d69347f46888a20baa805f797)
@@ -17,8 +17,16 @@
 
 #include <cassert>                // for assert
+#include <iterator>               // for back_inserter
 #include <string>                 // for string
 
+#include "AST/Decl.hpp"
+#include "AST/Expr.hpp"
+#include "AST/Init.hpp"
+#include "AST/Node.hpp"
+#include "AST/Stmt.hpp"
+#include "AST/Type.hpp"
 #include "CodeGen/OperatorTable.h"
 #include "Common/UniqueName.h"    // for UniqueName
+#include "Common/utility.h"       // for splice
 #include "InitTweak/InitTweak.h"  // for InitExpander
 #include "SynTree/Constant.h"     // for Constant
@@ -36,4 +44,5 @@
 	/// 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.
@@ -49,12 +58,21 @@
 	FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true );
 
+	/// Enum for loop direction
+	enum LoopDirection { LoopBackward, LoopForward };
+
 	/// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
 	template< typename OutputIterator >
-	Statement * genCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
+	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.
 	/// optionally returns a statement which must be inserted prior to the containing loop, if there is one
 	template< typename OutputIterator >
-	Statement * genScalarCall( InitTweak::InitExpander & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {
+	Statement * genScalarCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {
 		bool isReferenceCtorDtor = false;
 		if ( dynamic_cast< ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
@@ -106,8 +124,65 @@
 	}
 
+	/// 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 );
+
+		const 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 OutputIterator >
-	void genArrayCall( InitTweak::InitExpander & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {
+	void genArrayCall( InitTweak::InitExpander_old & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {
 		static UniqueName indexName( "_index" );
 
@@ -170,6 +245,76 @@
 	}
 
+	/// 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, cmp, update;
+
+		if ( forward ) {
+			// generate: for ( int i = 0; i < N; ++i )
+			begin = ast::ConstantExpr::from_int( loc, 0 );
+			end = array->dimension;
+			cmp = new ast::NameExpr{ loc, "?<?" };
+			update = new ast::NameExpr{ loc, "++?" };
+		} else {
+			// generate: for ( int i = N-1; i >= 0; --i )
+			begin = new ast::UntypedExpr{ 
+				loc, new ast::NameExpr{ loc, "?-?" }, 
+				{ array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } };
+			end = ast::ConstantExpr::from_int( loc, 0 );
+			cmp = new ast::NameExpr{ loc, "?>=?" };
+			update = new ast::NameExpr{ loc, "--?" };
+		}
+
+		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 > cond = new ast::UntypedExpr{
+			loc, cmp, { new ast::VariableExpr{ loc, index }, end } };
+		
+		ast::ptr< ast::Expr > inc = new ast::UntypedExpr{
+			loc, update, { new ast::VariableExpr{ loc, index } } };
+		
+		ast::ptr< ast::Expr > dstIndex = new ast::UntypedExpr{
+			loc, new ast::NameExpr{ loc, "?[?]" }, 
+			{ dstParam, new ast::VariableExpr{ loc, index } } };
+		
+		// srcParam must keep track of the array indices to build the source parameter and/or 
+		// array list initializer
+		srcParam.addArrayIndex( new ast::VariableExpr{ loc, index }, 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 & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
+	Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
 		if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
 			genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
@@ -180,4 +325,21 @@
 	}
 
+	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 );
+		}
+	}
+
 	/// inserts into out a generated call expression to function fname with arguments dstParam
 	/// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
@@ -185,5 +347,5 @@
 	/// ImplicitCtorDtorStmt node.
 	template< typename OutputIterator >
-	void genImplicitCall( InitTweak::InitExpander & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
+	void genImplicitCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
 		ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
 		assert( obj );
@@ -213,4 +375,38 @@
 		}
 	}
+
+	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 = nullptr;
+		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
 
