Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision 39f84a4e271ab1b20b0bd4bae4f1ca69460c1dc7)
+++ src/InitTweak/GenInit.cc	(revision 4d2434a3b1b9692aecc5c41cc41df0d3c37fbefb)
@@ -154,4 +154,6 @@
 	}
 
+	// precompute array dimension expression, because constructor generation may duplicate it,
+	// which would be incorrect if it is a side-effecting computation.
 	void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
 		HoistArrayDimension hoister;
@@ -215,54 +217,31 @@
 		// hands off if designated, if @=, or if extern
 		if ( tryConstruct( objDecl ) ) {
-			if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
-				// call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array
-				// TODO: walk initializers and generate appropriate ctor if element has initializer.
-				// Initializer could be nested (depends on the depth of the array type on the object)
-
-				std::list< Expression * > args = makeInitList( objDecl->get_init() );
-				if ( args.empty() ) {
-					std::list< Statement * > ctor;
-					std::list< Statement * > dtor;
-
-					InitExpander srcParam( (Expression *)NULL );
-					SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
-					SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
-
-					// Currently genImplicitCall produces a single Statement - a CompoundStmt
-					// which  wraps everything that needs to happen. As such, it's technically
-					// possible to use a Statement ** in the above calls, but this is inherently
-					// unsafe, so instead we take the slightly less efficient route, but will be
-					// immediately informed if somehow the above assumption is broken. In this case,
-					// we could always wrap the list of statements at this point with a CompoundStmt,
-					// but it seems reasonable at the moment for this to be done by genImplicitCall
-					// itself. It is possible that genImplicitCall produces no statements (e.g. if
-					// an array type does not have a dimension). In this case, it's fine to ignore
-					// the object for the purposes of construction.
-					assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
-					if ( ctor.size() == 1 ) {
-						assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
-						objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
-					}
-				} else {
-					// array came with an initializer list: initialize each element
-					// may have more initializers than elements in the array - need to check at each index that
-					// we haven't exceeded size. This requires precomputing the size because it might be a side-effecting
-					// computation.
-					// may have fewer initializers than elements in the array - need to default construct
-					// remaining elements.
-					// might be able to merge this with the case above.
-
-				}
-			} else {
-				// it's sufficient to attempt to call the ctor/dtor for the given object and its initializer
-				Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) );
-				Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() );
-
+			// call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
+			// for each constructable object
+			std::list< Statement * > ctor;
+			std::list< Statement * > dtor;
+
+			InitExpander srcParam( objDecl->get_init() );
+			InitExpander nullParam( (Initializer *)NULL );
+			SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
+			SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
+
+			// Currently genImplicitCall produces a single Statement - a CompoundStmt
+			// which  wraps everything that needs to happen. As such, it's technically
+			// possible to use a Statement ** in the above calls, but this is inherently
+			// unsafe, so instead we take the slightly less efficient route, but will be
+			// immediately informed if somehow the above assumption is broken. In this case,
+			// we could always wrap the list of statements at this point with a CompoundStmt,
+			// but it seems reasonable at the moment for this to be done by genImplicitCall
+			// itself. It is possible that genImplicitCall produces no statements (e.g. if
+			// an array type does not have a dimension). In this case, it's fine to ignore
+			// the object for the purposes of construction.
+			assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
+			if ( ctor.size() == 1 ) {
 				// need to remember init expression, in case no ctors exist
 				// if ctor does exist, want to use ctor expression instead of init
 				// push this decision to the resolver
-				ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor );
-				ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor );
-				objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) );
+				assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
+				objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) );
 			}
 		}
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 39f84a4e271ab1b20b0bd4bae4f1ca69460c1dc7)
+++ src/InitTweak/InitTweak.cc	(revision 4d2434a3b1b9692aecc5c41cc41df0d3c37fbefb)
@@ -1,2 +1,3 @@
+#include <algorithm>
 #include "InitTweak.h"
 #include "SynTree/Visitor.h"
@@ -20,5 +21,5 @@
 		};
 
-		class InitExpander_OLD : public Visitor {
+		class InitFlattener : public Visitor {
 			public:
 			virtual void visit( SingleInit * singleInit );
@@ -27,12 +28,12 @@
 		};
 
-		void InitExpander_OLD::visit( SingleInit * singleInit ) {
+		void InitFlattener::visit( SingleInit * singleInit ) {
 			argList.push_back( singleInit->get_value()->clone() );
 		}
 
-		void InitExpander_OLD::visit( ListInit * listInit ) {
-			// xxx - for now, assume no nested list inits
-			std::list<Initializer*>::iterator it = listInit->begin_initializers();
-			for ( ; it != listInit->end_initializers(); ++it ) {
+		void InitFlattener::visit( ListInit * listInit ) {
+			// flatten nested list inits
+			std::list<Initializer*>::iterator it = listInit->begin();
+			for ( ; it != listInit->end(); ++it ) {
 				(*it)->accept( *this );
 			}
@@ -41,7 +42,7 @@
 
 	std::list< Expression * > makeInitList( Initializer * init ) {
-		InitExpander_OLD expander;
-		maybeAccept( init, expander );
-		return expander.argList;
+		InitFlattener flattener;
+		maybeAccept( init, flattener );
+		return flattener.argList;
 	}
 
@@ -55,18 +56,21 @@
 	public:
 		virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0;
+		virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0;
 	};
 
 	class InitImpl : public InitExpander::ExpanderImpl {
 	public:
-		InitImpl( Initializer * init ) {
-			if ( init ) inits.push_back( init );
-		}
+		InitImpl( Initializer * init ) : init( init ) {}
 
 		virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
 			// this is wrong, but just a placeholder for now
-			return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >();
-		}
+			// if ( ! flattened ) flatten( indices );
+			// return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >();
+			return makeInitList( init );
+		}
+
+		virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
 	private:
-		std::list< Initializer * > inits;
+		Initializer * init;
 	};
 
@@ -91,4 +95,6 @@
 			return ret;
 		}
+
+		virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
 	private:
 		Expression * arg;
@@ -114,44 +120,96 @@
 	}
 
-	template< typename OutIterator >
-	void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator end, OutIterator out ) {
-		if ( idx == end ) return;
-		Expression * index = *idx++;
-		assert( idx != end );
-		Expression * dimension = *idx++;
-
-		// if ( idx == end ) {
-		// 	// loop through list of expressions belonging to the current initializer
-		// 	UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );
-		// 	cond->get_args().push_back( index->clone() );
-		// 	cond->get_args().push_back( dimension->clone() );
-
-		// 	UntypedExpr * call = callExpr->clone();
-		// 	std::list< Expression * > args = *++expander; // xxx - need a way to indentify the end of an init list
-		// 	call->get_args().splice( args );
-
-		// 	*out++ = new IfStmt( noLabels, cond, new ExprStmt( call ), NULL );
-
-		// 	UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
-		// 	increment->get_args().push_back( index->clone() );
-		// 	*out++ = new ExprStmt( increment );
-		// } else {
-		// 	std::list< Statement * > branches;
-		// 	for (...) { // loop over conditions?
-		// 		std::list< Statement * > stmts;
-		// 		build( idx, end, back_inserter( stmts ) );
-		// 		CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
-		// 		branches.push_back( caseStmt );
-		// 	}
-		// 	*out++ = new SwitchStmt( noLabels, index->clone(), branches );
-		// }
-	}
-
-	// generate switch statement, consuming all of expander's elements
+	void InitExpander::clearArrayIndices() {
+		indices.clear();
+	}
+
+	namespace {
+		template< typename OutIterator >
+		void dothething( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {
+			UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );
+			cond->get_args().push_back( index->clone() );
+			cond->get_args().push_back( dimension->clone() );
+
+			std::list< Expression * > args = makeInitList( init );
+			callExpr->get_args().splice( callExpr->get_args().end(), args );
+
+			*out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL );
+
+			UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
+			increment->get_args().push_back( new AddressExpr( index->clone() ) );
+			*out++ = new ExprStmt( noLabels, increment );
+		}
+
+		template< typename OutIterator >
+		void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
+			if ( idx == idxEnd ) return;
+			Expression * index = *idx++;
+			assert( idx != idxEnd );
+			Expression * dimension = *idx++;
+
+			if ( idx == idxEnd ) {
+				if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) {
+					for ( Initializer * init : *listInit ) {
+						dothething( callExpr->clone(), index, dimension, init, out );
+					}
+				} else {
+					dothething( callExpr->clone(), index, dimension, init, out );
+				}
+			} else {
+				std::list< Statement * > branches;
+
+				unsigned long cond = 0;
+				ListInit * listInit = dynamic_cast< ListInit * >( init );
+				if ( ! listInit ) {
+					// xxx - this shouldn't be an error, but need a way to
+					// terminate without creating output, so should catch this error
+					throw SemanticError( "unbalanced list initializers" );
+				}
+				for ( Initializer * init : *listInit ) {
+					Expression * condition;
+					// check for designations
+					// if ( init-> ) {
+						condition = new ConstantExpr( Constant::from_ulong( cond ) );
+						++cond;
+					// } else {
+					// 	condition = // ... take designation
+					// 	cond = // ... take designation+1
+					// }
+					std::list< Statement * > stmts;
+					build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );
+					CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
+					branches.push_back( caseStmt );
+				}
+				*out++ = new SwitchStmt( noLabels, index->clone(), branches );
+			}
+		}
+	}
+
+	// if array came with an initializer list: initialize each element
+	// may have more initializers than elements in the array - need to check at each index that
+	// we haven't exceeded size.
+	// may have fewer initializers than elements in the array - need to default construct
+	// remaining elements.
+	// To accomplish this, generate switch statement, consuming all of expander's elements
+	Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
+		if ( ! init ) return NULL;
+		std::list< Statement * > results;
+		build( dst, indices.begin(), indices.end(), init, back_inserter( results ) );
+		assert( results.size() <= 1 );
+		if ( results.empty() ) {
+			return NULL;
+		} else {
+			init = NULL; // init was consumed in creating the list init
+			return results.front();
+		}
+		return ! results.empty() ? results.front() : NULL;
+	}
+
+	Statement * ExprImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
+		return NULL;
+	}
+
 	Statement * InitExpander::buildListInit( UntypedExpr * dst ) {
-		std::list< Statement * > results;
-		build( dst, indices.begin(), indices.end(), back_inserter( results ) );
-		assert( results.size() <= 1 );
-		return ! results.empty() ? results.front() : NULL;
+		return expander->buildListInit( dst, indices );
 	}
 
@@ -164,31 +222,48 @@
 	}
 
+	class CallFinder : public Visitor {
+	public:
+		typedef Visitor Parent;
+		CallFinder( const std::list< std::string > & names ) : names( names ) {}
+
+		virtual void visit( ApplicationExpr * appExpr ) {
+			handleCallExpr( appExpr );
+		}
+
+		virtual void visit( UntypedExpr * untypedExpr ) {
+			handleCallExpr( untypedExpr );
+		}
+
+		std::list< Expression * > * matches;
+	private:
+		const std::list< std::string > names;
+
+		template< typename CallExpr >
+		void handleCallExpr( CallExpr * expr ) {
+			Parent::visit( expr );
+			std::string fname = getFunctionName( expr );
+			if ( std::find( names.begin(), names.end(), fname ) != names.end() ) {
+				matches->push_back( expr );
+			}
+		}
+	};
+
+	void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) {
+		static CallFinder finder( std::list< std::string >{ "?{}", "^?{}" } );
+		finder.matches = &matches;
+		maybeAccept( stmt, finder );
+	}
+
 	Expression * getCtorDtorCall( Statement * stmt ) {
-		if ( stmt == NULL ) return NULL;
-		if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
-			return exprStmt->get_expr();
-		} else if ( CompoundStmt * compoundStmt = dynamic_cast< CompoundStmt * >( stmt ) ) {
-			// could also be a compound statement with a loop, in the case of an array
-			if( compoundStmt->get_kids().size() == 2 ) {
-				// loop variable and loop
-				ForStmt * forStmt = dynamic_cast< ForStmt * >( compoundStmt->get_kids().back() );
-				assert( forStmt && forStmt->get_body() );
-				return getCtorDtorCall( forStmt->get_body() );
-			} else if ( compoundStmt->get_kids().size() == 1 ) {
-				// should be the call statement, but in any case there's only one option
-				return getCtorDtorCall( compoundStmt->get_kids().front() );
-			} else {
-				assert( false && "too many statements in compoundStmt for getCtorDtorCall" );
-			}
-		} if ( ImplicitCtorDtorStmt * impCtorDtorStmt = dynamic_cast< ImplicitCtorDtorStmt * > ( stmt ) ) {
-			return getCtorDtorCall( impCtorDtorStmt->get_callStmt() );
-		} else {
-			// should never get here
-			assert( false && "encountered unknown call statement" );
-		}
-	}
+		std::list< Expression * > matches;
+		collectCtorDtorCalls( stmt, matches );
+		assert( matches.size() <= 1 );
+		return matches.size() == 1 ? matches.front() : NULL;
+	}
+
 	namespace {
 		VariableExpr * getCalledFunction( ApplicationExpr * appExpr ) {
 			assert( appExpr );
+			// xxx - it's possible this can be other things, e.g. MemberExpr, so this is insufficient
 			return dynamic_cast< VariableExpr * >( appExpr->get_function() );
 		}
@@ -206,13 +281,16 @@
 
 	bool isInstrinsicSingleArgCallStmt( Statement * stmt ) {
-		Expression * callExpr = getCtorDtorCall( stmt );
-		if ( ! callExpr ) return false;
-		if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
-			assert( ! appExpr->get_function()->get_results().empty() );
-			FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() );
-			assert( funcType );
-			return funcType->get_parameters().size() == 1;
-		}
-		return false;
+		std::list< Expression * > callExprs;
+		collectCtorDtorCalls( stmt, callExprs );
+		// if ( callExprs.empty() ) return false; // xxx - do I still need this check?
+		return std::all_of( callExprs.begin(), callExprs.end(), []( Expression * callExpr ){
+			if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
+				assert( ! appExpr->get_function()->get_results().empty() );
+				FunctionType *funcType = GenPoly::getFunctionType( appExpr->get_function()->get_results().front() );
+				assert( funcType );
+				return funcType->get_parameters().size() == 1;
+			}
+			return false;
+		});
 	}
 
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision 39f84a4e271ab1b20b0bd4bae4f1ca69460c1dc7)
+++ src/InitTweak/InitTweak.h	(revision 4d2434a3b1b9692aecc5c41cc41df0d3c37fbefb)
@@ -43,4 +43,7 @@
 	bool isInstrinsicSingleArgCallStmt( Statement * expr );
 
+	/// get all Ctor/Dtor call expressions from a Statement
+	void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
+
 	/// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
 	Expression * getCtorDtorCall( Statement * stmt );
@@ -78,4 +81,5 @@
 		Statement * buildListInit( UntypedExpr * callExpr );
 		void addArrayIndex( Expression * index, Expression * dimension );
+		void clearArrayIndices();
 
 		class ExpanderImpl;
