Index: src/SymTab/AddVisit.h
===================================================================
--- src/SymTab/AddVisit.h	(revision 5070fe4b9ad7bec2681f51b6b650a12237ceefc1)
+++ src/SymTab/AddVisit.h	(revision c3314061a7f72e82701eb3e9bdf37c2cd6d45268)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 16:14:32 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Jul 12 17:46:33 2016
-// Update Count     : 6
+// Last Modified On : Thu Aug  4 11:22:01 2016
+// Update Count     : 9
 //
 
@@ -33,5 +33,5 @@
 	template< typename Visitor >
 	inline void addVisit(SwitchStmt *switchStmt, Visitor &visitor) {
-		addVisitStatementList( switchStmt->get_branches(), visitor );
+		addVisitStatementList( switchStmt->get_statements(), visitor );
 		maybeAccept( switchStmt->get_condition(), visitor );
 	}
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision 5070fe4b9ad7bec2681f51b6b650a12237ceefc1)
+++ src/SymTab/Autogen.cc	(revision c3314061a7f72e82701eb3e9bdf37c2cd6d45268)
@@ -26,4 +26,6 @@
 
 namespace SymTab {
+	Type * SizeType = 0;
+
 	class AutogenerateRoutines : public Visitor {
 		public:
@@ -59,36 +61,4 @@
 	bool isUnnamedBitfield( ObjectDecl * obj ) {
 		return obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL;
-	}
-
-	template< typename OutputIterator >
-	void makeScalarFunction( Expression *src, ObjectDecl *dstParam, DeclarationWithType *member, std::string fname, OutputIterator out ) {
-		ObjectDecl *obj = dynamic_cast<ObjectDecl *>( member );
-		// unnamed bit fields are not copied as they cannot be accessed
-		if ( isUnnamedBitfield( obj ) ) return;
-
-		// want to be able to generate assignment, ctor, and dtor generically,
-		// so fname is either ?=?, ?{}, or ^?{}
-		UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
-
-		UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
-		derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
-
-		// do something special for unnamed members
-		Expression *dstselect = new AddressExpr( new MemberExpr( member, derefExpr ) );
-		fExpr->get_args().push_back( dstselect );
-
-		if ( src ) {
-			fExpr->get_args().push_back( src );
-		}
-
-		Statement * callStmt = new ExprStmt( noLabels, fExpr );
-		if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ) ) {
-			// implicitly generated ctor/dtor calls should be wrapped
-			// so that later passes are aware they were generated.
-			// xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
-			// because this causes the address to be taken at codegen, which is illegal in C.
-			callStmt = new ImplicitCtorDtorStmt( callStmt );
-		}
-		*out++ = callStmt;
 	}
 
@@ -219,21 +189,17 @@
 		}
 
+		InitTweak::InitExpander srcParam( src );
+
 		// assign to destination (and return value if generic)
-		if ( ArrayType *array = dynamic_cast< ArrayType * >( field->get_type() ) ) {
-			UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
-			derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
-			Expression *dstselect = new MemberExpr( field, derefExpr );
-
-			makeArrayFunction( src, dstselect, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ), forward );
-			if ( isDynamicLayout && returnVal ) {
-				UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
-				derefRet->get_args().push_back( new VariableExpr( returnVal ) );
-				Expression *retselect = new MemberExpr( field, derefRet );
-
-				makeArrayFunction( src, retselect, array, func->get_name(), back_inserter( func->get_statements()->get_kids() ), forward );
-			}
-		} else {
-			makeScalarFunction( src, dstParam, field, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
-			if ( isDynamicLayout && returnVal ) makeScalarFunction( src, returnVal, field, func->get_name(), back_inserter( func->get_statements()->get_kids() ) );
+		UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
+		derefExpr->get_args().push_back( new VariableExpr( dstParam ) );
+		Expression *dstselect = new MemberExpr( field, derefExpr );
+		genImplicitCall( srcParam, dstselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
+
+		if ( isDynamicLayout && returnVal ) {
+			UntypedExpr *derefRet = new UntypedExpr( new NameExpr( "*?" ) );
+			derefRet->get_args().push_back( new VariableExpr( returnVal ) );
+			Expression *retselect = new MemberExpr( field, derefRet );
+			genImplicitCall( srcParam, retselect, func->get_name(), back_inserter( func->get_statements()->get_kids() ), field, forward );
 		} // if
 	}
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision 5070fe4b9ad7bec2681f51b6b650a12237ceefc1)
+++ src/SymTab/Autogen.h	(revision c3314061a7f72e82701eb3e9bdf37c2cd6d45268)
@@ -22,82 +22,160 @@
 #include "SynTree/Declaration.h"
 #include "SynTree/Initializer.h"
+#include "InitTweak/InitTweak.h"
 
 namespace SymTab {
-  /// Generates assignment operators, constructors, and destructor for aggregate types as required
-  void autogenerateRoutines( std::list< Declaration * > &translationUnit );
+	/// Generates assignment operators, constructors, and destructor for aggregate types as required
+	void autogenerateRoutines( std::list< Declaration * > &translationUnit );
 
-  // originally makeArrayAssignment - changed to Function because it is now used for ctors and dtors as well
-  // admittedly not a great name change. This used to live in Validate.cc, but has been moved so it can be reused elsewhere
+	/// returns true if obj's name is the empty string and it has a bitfield width
+	bool isUnnamedBitfield( ObjectDecl * obj );
 
-  /// 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 makeArrayFunction( Expression *srcParam, Expression *dstParam, ArrayType *array, std::string fname, OutputIterator out, bool forward = true ) {
-    static UniqueName indexName( "_index" );
+	/// size_t type - set when size_t typedef is seen. Useful in a few places,
+	/// such as in determining array dimension type
+	extern Type * SizeType;
 
-    // for a flexible array member nothing is done -- user must define own assignment
-    if ( ! array->get_dimension() ) return;
+	/// 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, bool addCast = false, bool forward = true );
 
-    Expression * begin, * end, * update, * cmp;
-    if ( forward ) {
-      // generate: for ( int i = 0; i < 0; ++i )
-      begin = new NameExpr( "0" );
-      end = array->get_dimension()->clone();
-      cmp = new NameExpr( "?<?" );
-      update = new NameExpr( "++?" );
-    } else {
-      // generate: for ( int i = N-1; i >= 0; --i )
-      begin = new UntypedExpr( new NameExpr( "?-?" ) );
-      ((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
-      ((UntypedExpr*)begin)->get_args().push_back( new NameExpr( "1" ) );
-      end = new NameExpr( "0" );
-      cmp = new NameExpr( "?>=?" );
-      update = new NameExpr( "--?" );
-    }
+	/// 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, const std::string & fname, OutputIterator out, Type * type, bool addCast = false ) {
+		// want to be able to generate assignment, ctor, and dtor generically,
+		// so fname is either ?=?, ?{}, or ^?{}
+		UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
 
-    ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
+		// do something special for unnamed members
+		dstParam = new AddressExpr( dstParam );
+		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. If we ever
+			// remove lvalue as a qualifier, this can change to
+			//   type->get_qualifiers() = Type::Qualifiers();
+			assert( type );
+			Type * castType = type->clone();
+			castType->get_qualifiers() -= Type::Qualifiers(true, true, true, false, true, true);
+			castType->set_isLvalue( true ); // xxx - might not need this
+			dstParam = new CastExpr( dstParam, new PointerType( Type::Qualifiers(), castType ) );
+		}
+		fExpr->get_args().push_back( dstParam );
 
-    UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
-    init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
-    init->get_args().push_back( begin );
-    index->set_init( new SingleInit( init, std::list<Expression*>() ) );
+		Statement * listInit = srcParam.buildListInit( fExpr );
 
-    UntypedExpr *cond = new UntypedExpr( cmp );
-    cond->get_args().push_back( new VariableExpr( index ) );
-    cond->get_args().push_back( end );
+		std::list< Expression * > args = *++srcParam;
+		fExpr->get_args().splice( fExpr->get_args().end(), args );
 
-    UntypedExpr *inc = new UntypedExpr( update );
-    inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
+		*out++ = new ExprStmt( noLabels, fExpr );
 
-    // want to be able to generate assignment, ctor, and dtor generically,
-    // so fname is either ?=?, ?{}, or ^?{}
-    UntypedExpr *fExpr = new UntypedExpr( new NameExpr( fname ) );
+		srcParam.clearArrayIndices();
 
-    UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?+?" ) );
-    dstIndex->get_args().push_back( dstParam );
-    dstIndex->get_args().push_back( new VariableExpr( index ) );
-    fExpr->get_args().push_back( dstIndex );
+		return listInit;
+	}
 
-    // srcParam is NULL for default ctor/dtor
-    if ( srcParam ) {
-      UntypedExpr *srcIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
-      srcIndex->get_args().push_back( srcParam );
-      srcIndex->get_args().push_back( new VariableExpr( index ) );
-      fExpr->get_args().push_back( srcIndex );
-    }
+	/// 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, bool addCast = false, bool forward = true ) {
+		static UniqueName indexName( "_index" );
 
-    std::list<Statement *> initList;
-    CompoundStmt * block = new CompoundStmt( noLabels );
-    block->get_kids().push_back( new DeclStmt( noLabels, index ) );
-    block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, new ExprStmt( noLabels, fExpr ) ) );
+		// for a flexible array member nothing is done -- user must define own assignment
+		if ( ! array->get_dimension() ) return ;
 
-    Statement * stmt = block;
-    if ( fname == "?{}" || fname == "^?{}" ) {
-      // implicitly generated ctor/dtor calls should be wrapped
-      // so that later passes are aware they were generated
-      stmt = new ImplicitCtorDtorStmt( stmt );
-    }
-    *out++ = stmt;
-  }
+		Expression * begin, * end, * update, * cmp;
+		if ( forward ) {
+			// generate: for ( int i = 0; i < 0; ++i )
+			begin = new NameExpr( "0" );
+			end = array->get_dimension()->clone();
+			cmp = new NameExpr( "?<?" );
+			update = new NameExpr( "++?" );
+		} else {
+			// generate: for ( int i = N-1; i >= 0; --i )
+			begin = new UntypedExpr( new NameExpr( "?-?" ) );
+			((UntypedExpr*)begin)->get_args().push_back( array->get_dimension()->clone() );
+			((UntypedExpr*)begin)->get_args().push_back( new NameExpr( "1" ) );
+			end = new NameExpr( "0" );
+			cmp = new NameExpr( "?>=?" );
+			update = new NameExpr( "--?" );
+		}
+
+		ObjectDecl *index = new ObjectDecl( indexName.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), NULL );
+
+		UntypedExpr *init = new UntypedExpr( new NameExpr( "?=?" ) );
+		init->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
+		init->get_args().push_back( begin );
+		index->set_init( new SingleInit( init, std::list<Expression*>() ) );
+
+		UntypedExpr *cond = new UntypedExpr( cmp );
+		cond->get_args().push_back( new VariableExpr( index ) );
+		cond->get_args().push_back( end );
+
+		UntypedExpr *inc = new UntypedExpr( update );
+		inc->get_args().push_back( new AddressExpr( new VariableExpr( index ) ) );
+
+		UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
+		dstIndex->get_args().push_back( dstParam );
+		dstIndex->get_args().push_back( new VariableExpr( index ) );
+		dstParam = dstIndex;
+
+		// srcParam must keep track of the array indices to build the
+		// source parameter and/or array list initializer
+		srcParam.addArrayIndex( new VariableExpr( index ), array->get_dimension()->clone() );
+
+		// for stmt's body, eventually containing call
+		CompoundStmt * body = new CompoundStmt( noLabels );
+		Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->get_kids() ), array->get_base(), addCast, forward );
+
+		// block containing for stmt and index variable
+		std::list<Statement *> initList;
+		CompoundStmt * block = new CompoundStmt( noLabels );
+		block->get_kids().push_back( new DeclStmt( noLabels, index ) );
+		if ( listInit ) block->get_kids().push_back( listInit );
+		block->get_kids().push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
+
+		*out++ = block;
+	}
+
+	template< typename OutputIterator >
+	Statement * genCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, bool addCast, bool forward ) {
+		if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
+			genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
+			return 0;
+		} else {
+			return genScalarCall( srcParam, dstParam, fname, 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
+	/// object being constructed. The function wraps constructor and destructor calls in an
+	/// ImplicitCtorDtorStmt node.
+	template< typename OutputIterator >
+	void genImplicitCall( InitTweak::InitExpander &  srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
+		ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
+		assert( obj );
+		// unnamed bit fields are not copied as they cannot be accessed
+		if ( isUnnamedBitfield( obj ) ) return;
+
+		bool addCast = (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) );
+		std::list< Statement * > stmts;
+		genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), addCast, forward );
+
+		// currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call
+		assert( stmts.size() <= 1 );
+		if ( stmts.size() == 1 ) {
+			Statement * callStmt = stmts.front();
+			if ( addCast ) {
+				// implicitly generated ctor/dtor calls should be wrapped
+				// so that later passes are aware they were generated.
+				// xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
+				// because this causes the address to be taken at codegen, which is illegal in C.
+				callStmt = new ImplicitCtorDtorStmt( callStmt );
+			}
+			*out++ = callStmt;
+		}
+	}
 } // namespace SymTab
 #endif // AUTOGEN_H
Index: src/SymTab/FixFunction.cc
===================================================================
--- src/SymTab/FixFunction.cc	(revision 5070fe4b9ad7bec2681f51b6b650a12237ceefc1)
+++ src/SymTab/FixFunction.cc	(revision c3314061a7f72e82701eb3e9bdf37c2cd6d45268)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// FixFunction.cc -- 
+// FixFunction.cc --
 //
 // Author           : Richard C. Bilson
@@ -44,5 +44,6 @@
 
 	Type * FixFunction::mutate(ArrayType *arrayType) {
-		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), maybeClone( arrayType->get_base()->clone() ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() );
+		// need to recursively mutate the base type in order for multi-dimensional arrays to work.
+		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->get_base()->clone()->acceptMutator( *this ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() );
 		delete arrayType;
 		return pointerType;
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 5070fe4b9ad7bec2681f51b6b650a12237ceefc1)
+++ src/SymTab/Validate.cc	(revision c3314061a7f72e82701eb3e9bdf37c2cd6d45268)
@@ -174,5 +174,5 @@
 
 		virtual void visit( FunctionDecl *funcDecl );
-};
+	};
 
 	class CompoundLiteral : public GenPoly::DeclMutator {
@@ -191,9 +191,9 @@
 		EliminateTypedef::eliminateTypedef( translationUnit );
 		HoistStruct::hoistStruct( translationUnit );
+		autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs Pass1
 		acceptAll( translationUnit, pass1 );
 		acceptAll( translationUnit, pass2 );
 		ReturnChecker::checkFunctionReturns( translationUnit );
-		mutateAll( translationUnit, compoundliteral );
-		autogenerateRoutines( translationUnit );
+		compoundliteral.mutateDeclarationList( translationUnit );
 		acceptAll( translationUnit, pass3 );
 		VerifyCtorDtor::verify( translationUnit );
@@ -490,5 +490,14 @@
 		EliminateTypedef eliminator;
 		mutateAll( translationUnit, eliminator );
+		if ( eliminator.typedefNames.count( "size_t" ) ) {
+			// grab and remember declaration of size_t
+			SizeType = eliminator.typedefNames["size_t"].first->get_base()->clone();
+		} else {
+			// xxx - missing global typedef for size_t - default to long unsigned int, even though that may be wrong
+			// eventually should have a warning for this case.
+			SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
+		}
 		filter( translationUnit, isTypedef, true );
+
 	}
 
@@ -518,4 +527,5 @@
 	Declaration *EliminateTypedef::mutate( TypedefDecl * tyDecl ) {
 		Declaration *ret = Mutator::mutate( tyDecl );
+
 		if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
 			// typedef to the same name from the same scope
