Index: src/InitTweak/FixGlobalInit.cc
===================================================================
--- src/InitTweak/FixGlobalInit.cc	(revision 0bd3faf870391e5ed803287ec0b3c696cfde22b2)
+++ src/InitTweak/FixGlobalInit.cc	(revision 8984003da746813325cd05052fbcb1cb7bef8d62)
@@ -27,79 +27,81 @@
 
 namespace InitTweak {
-	class GlobalFixer : public ast::WithShortCircuiting {
-	public:
-		void previsit (const ast::ObjectDecl *);
-		void previsit (const ast::FunctionDecl *) { visit_children = false; }
-		void previsit (const ast::StructDecl *) { visit_children = false; }
-		void previsit (const ast::UnionDecl *) { visit_children = false; }
-		void previsit (const ast::EnumDecl *) { visit_children = false; }
-		void previsit (const ast::TraitDecl *) { visit_children = false; }
-		void previsit (const ast::TypeDecl *) { visit_children = false; }
 
-		std::list< ast::ptr<ast::Stmt> > initStmts;
-		std::list< ast::ptr<ast::Stmt> > destroyStmts;
-	};
+namespace {
 
-	void fixGlobalInit(ast::TranslationUnit & translationUnit, bool inLibrary) {
-		ast::Pass<GlobalFixer> fixer;
-		accept_all(translationUnit, fixer);
+class GlobalFixer : public ast::WithShortCircuiting {
+public:
+	void previsit(const ast::ObjectDecl *);
+	void previsit(const ast::FunctionDecl *) { visit_children = false; }
+	void previsit(const ast::StructDecl *) { visit_children = false; }
+	void previsit(const ast::UnionDecl *) { visit_children = false; }
+	void previsit(const ast::EnumDecl *) { visit_children = false; }
+	void previsit(const ast::TraitDecl *) { visit_children = false; }
+	void previsit(const ast::TypeDecl *) { visit_children = false; }
 
-		// Say these magic declarations come at the end of the file.
-		CodeLocation const & location = translationUnit.decls.back()->location;
+	std::list< ast::ptr<ast::Stmt> > initStmts;
+	std::list< ast::ptr<ast::Stmt> > destroyStmts;
+};
 
-		if ( !fixer.core.initStmts.empty() ) {
-			std::vector<ast::ptr<ast::Expr>> ctorParams;
-			if (inLibrary) ctorParams.emplace_back(ast::ConstantExpr::from_int(location, 200));
-			auto initFunction = new ast::FunctionDecl(location,
-				"__global_init__", {}, {}, {},
-				new ast::CompoundStmt(location, std::move(fixer.core.initStmts)),
-				ast::Storage::Static, ast::Linkage::C,
-				{new ast::Attribute("constructor", std::move(ctorParams))});
+void GlobalFixer::previsit(const ast::ObjectDecl * objDecl) {
+	auto mutDecl = mutate(objDecl);
+	assertf(mutDecl == objDecl, "Global object decl must be unique");
+	auto ctorInit = objDecl->init.as<ast::ConstructorInit>();
+	if ( nullptr == ctorInit ) return;
 
-			translationUnit.decls.emplace_back( initFunction );
-		} // if
+	// a decision should have been made by the resolver, so ctor and init are not both non-NULL
+	assert( !ctorInit->ctor || !ctorInit->init );
 
-		if ( !fixer.core.destroyStmts.empty() ) {
-			std::vector<ast::ptr<ast::Expr>> dtorParams;
-			if (inLibrary) dtorParams.emplace_back(ast::ConstantExpr::from_int(location, 200));
-			auto destroyFunction = new ast::FunctionDecl( location,
-				"__global_destroy__", {}, {}, {},
-				new ast::CompoundStmt(location, std::move(fixer.core.destroyStmts)),
-				ast::Storage::Static, ast::Linkage::C,
-				{new ast::Attribute("destructor", std::move(dtorParams))});
+	const ast::Stmt * dtor = ctorInit->dtor;
+	if ( dtor && !isIntrinsicSingleArgCallStmt( dtor ) ) {
+		// don't need to call intrinsic dtor, because it does nothing, but
+		// non-intrinsic dtors must be called
+		destroyStmts.push_front( dtor );
+	} // if
+	if ( const ast::Stmt * ctor = ctorInit->ctor ) {
+		addDataSectionAttribute(mutDecl);
+		initStmts.push_back( ctor );
+		mutDecl->init = nullptr;
+	} else if ( const ast::Init * init = ctorInit->init ) {
+		mutDecl->init = init;
+	} else {
+		// no constructor and no initializer, which is okay
+		mutDecl->init = nullptr;
+	}
+}
 
-			translationUnit.decls.emplace_back(destroyFunction);
-		} // if
-	}
+} // namespace
 
-	void GlobalFixer::previsit(const ast::ObjectDecl * objDecl) {
-		auto mutDecl = mutate(objDecl);
-		assertf(mutDecl == objDecl, "Global object decl must be unique");
-		if ( auto ctorInit = objDecl->init.as<ast::ConstructorInit>() ) {
-			// a decision should have been made by the resolver, so ctor and init are not both non-NULL
-			assert( ! ctorInit->ctor || ! ctorInit->init );
+void fixGlobalInit(ast::TranslationUnit & translationUnit, bool inLibrary) {
+	ast::Pass<GlobalFixer> fixer;
+	accept_all(translationUnit, fixer);
 
-			const ast::Stmt * dtor = ctorInit->dtor;
-			if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
-				// don't need to call intrinsic dtor, because it does nothing, but
-				// non-intrinsic dtors must be called
-				destroyStmts.push_front( dtor );
-				// ctorInit->dtor = nullptr;
-			} // if
-			if ( const ast::Stmt * ctor = ctorInit->ctor ) {
-				addDataSectionAttribute(mutDecl);
-				initStmts.push_back( ctor );
-				mutDecl->init = nullptr;
-				// ctorInit->ctor = nullptr;
-			} else if ( const ast::Init * init = ctorInit->init ) {
-				mutDecl->init = init;
-				// ctorInit->init = nullptr;
-			} else {
-				// no constructor and no initializer, which is okay
-				mutDecl->init = nullptr;
-			} // if
-			// delete ctorInit;
-		} // if
-	}
+	// Say these magic declarations come at the end of the file.
+	CodeLocation const & location = translationUnit.decls.back()->location;
+
+	if ( !fixer.core.initStmts.empty() ) {
+		std::vector<ast::ptr<ast::Expr>> ctorParams;
+		if (inLibrary) ctorParams.emplace_back(ast::ConstantExpr::from_int(location, 200));
+		auto initFunction = new ast::FunctionDecl(location,
+			"__global_init__", {}, {}, {},
+			new ast::CompoundStmt(location, std::move(fixer.core.initStmts)),
+			ast::Storage::Static, ast::Linkage::C,
+			{new ast::Attribute("constructor", std::move(ctorParams))});
+
+		translationUnit.decls.emplace_back( initFunction );
+	} // if
+
+	if ( !fixer.core.destroyStmts.empty() ) {
+		std::vector<ast::ptr<ast::Expr>> dtorParams;
+		if (inLibrary) dtorParams.emplace_back(ast::ConstantExpr::from_int(location, 200));
+		auto destroyFunction = new ast::FunctionDecl( location,
+			"__global_destroy__", {}, {}, {},
+			new ast::CompoundStmt(location, std::move(fixer.core.destroyStmts)),
+			ast::Storage::Static, ast::Linkage::C,
+			{new ast::Attribute("destructor", std::move(dtorParams))});
+
+		translationUnit.decls.emplace_back(destroyFunction);
+	} // if
+}
 
 } // namespace InitTweak
Index: src/InitTweak/FixGlobalInit.h
===================================================================
--- src/InitTweak/FixGlobalInit.h	(revision 0bd3faf870391e5ed803287ec0b3c696cfde22b2)
+++ src/InitTweak/FixGlobalInit.h	(revision 8984003da746813325cd05052fbcb1cb7bef8d62)
@@ -16,18 +16,15 @@
 #pragma once
 
-#include <list>    // for list
-#include <string>  // for string
-
-#include <AST/Fwd.hpp>
-
-
-class Declaration;
+namespace ast {
+	class TranslationUnit;
+}
 
 namespace InitTweak {
-	/// Moves global initialization into an _init function that is unique to the translation unit.
-	/// Sets the priority of the initialization function depending on whether the initialization
-	/// function is for library code.
-	void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary );
-	void fixGlobalInit( ast::TranslationUnit & translationUnit, bool inLibrary );
+
+/// Moves global initialization into an _init function that is unique to the translation unit.
+/// Sets the priority of the initialization function depending on whether the initialization
+/// function is for library code.
+void fixGlobalInit( ast::TranslationUnit & translationUnit, bool inLibrary );
+
 } // namespace
 
Index: src/InitTweak/FixInit.h
===================================================================
--- src/InitTweak/FixInit.h	(revision 0bd3faf870391e5ed803287ec0b3c696cfde22b2)
+++ src/InitTweak/FixInit.h	(revision 8984003da746813325cd05052fbcb1cb7bef8d62)
@@ -16,8 +16,4 @@
 #pragma once
 
-#include <list>    // for list
-#include <string>  // for string
-
-class Declaration;
 namespace ast {
 	class TranslationUnit;
@@ -25,8 +21,8 @@
 
 namespace InitTweak {
-	/// replace constructor initializers with expression statements and unwrap basic C-style initializers
-	void fix( std::list< Declaration * > & translationUnit, bool inLibrary );
 
-	void fix( ast::TranslationUnit & translationUnit, bool inLibrary);
+/// Replace constructor initializers with expression statements and unwrap basic C-style initializers.
+void fix( ast::TranslationUnit & translationUnit, bool inLibrary);
+
 } // namespace
 
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision 0bd3faf870391e5ed803287ec0b3c696cfde22b2)
+++ src/InitTweak/GenInit.cc	(revision 8984003da746813325cd05052fbcb1cb7bef8d62)
@@ -206,7 +206,4 @@
 	};
 
-
-
-
 	struct ReturnFixer final :
 			public ast::WithStmtsToAdd<>, ast::WithGuards, ast::WithShortCircuiting {
@@ -262,77 +259,77 @@
 } // namespace
 
-	void genInit( ast::TranslationUnit & transUnit ) {
-		ast::Pass<HoistArrayDimension_NoResolve>::run( transUnit );
-		ast::Pass<ReturnFixer>::run( transUnit );
-	}
-
-	void fixReturnStatements( ast::TranslationUnit & transUnit ) {
-		ast::Pass<ReturnFixer>::run( transUnit );
-	}
-
-	bool ManagedTypes::isManaged( const ast::Type * type ) const {
-		// references are never constructed
-		if ( dynamic_cast< const ast::ReferenceType * >( type ) ) return false;
-		if ( auto tupleType = dynamic_cast< const ast::TupleType * > ( type ) ) {
-			// tuple is also managed if any of its components are managed
-			for (auto & component : tupleType->types) {
-				if (isManaged(component)) return true;
-			}
-		}
-		// need to clear and reset qualifiers when determining if a type is managed
-		// ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );
-		auto tmp = shallowCopy(type);
-		tmp->qualifiers = {};
-		// delete tmp at return
-		ast::ptr<ast::Type> guard = tmp;
-		// a type is managed if it appears in the map of known managed types, or if it contains any polymorphism (is a type variable or generic type containing a type variable)
-		return managedTypes.find( Mangle::mangle( tmp, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ) != managedTypes.end() || GenPoly::isPolyType( tmp );
-	}
-
-	bool ManagedTypes::isManaged( const ast::ObjectDecl * objDecl ) const {
-		const ast::Type * type = objDecl->type;
-		while ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
-			// must always construct VLAs with an initializer, since this is an error in C
-			if ( at->isVarLen && objDecl->init ) return true;
-			type = at->base;
-		}
-		return isManaged( type );
-	}
-
-	void ManagedTypes::handleDWT( const ast::DeclWithType * dwt ) {
-		// if this function is a user-defined constructor or destructor, mark down the type as "managed"
-		if ( ! dwt->linkage.is_overrideable && CodeGen::isCtorDtor( dwt->name ) ) {
-			auto & params = GenPoly::getFunctionType( dwt->get_type())->params;
-			assert( ! params.empty() );
-			// Type * type = InitTweak::getPointerBase( params.front() );
-			// assert( type );
-			managedTypes.insert( Mangle::mangle( params.front(), {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) );
-		}
-	}
-
-	void ManagedTypes::handleStruct( const ast::StructDecl * aggregateDecl ) {
-		// don't construct members, but need to take note if there is a managed member,
-		// because that means that this type is also managed
-		for ( auto & member : aggregateDecl->members ) {
-			if ( auto field = member.as<ast::ObjectDecl>() ) {
-				if ( isManaged( field ) ) {
-					// generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that
-					// polymorphic constructors make generic types managed types
-					ast::StructInstType inst( aggregateDecl );
-					managedTypes.insert( Mangle::mangle( &inst, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) );
-					break;
-				}
-			}
-		}
-	}
-
-	void ManagedTypes::beginScope() { managedTypes.beginScope(); }
-	void ManagedTypes::endScope() { managedTypes.endScope(); }
-
-	ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg) {
-		assertf(objDecl, "genCtorDtor passed null objDecl");
-		InitExpander srcParam(arg);
-		return SymTab::genImplicitCall(srcParam, new ast::VariableExpr(loc, objDecl), loc, fname, objDecl);
-	}
+void genInit( ast::TranslationUnit & transUnit ) {
+	ast::Pass<HoistArrayDimension_NoResolve>::run( transUnit );
+	ast::Pass<ReturnFixer>::run( transUnit );
+}
+
+void fixReturnStatements( ast::TranslationUnit & transUnit ) {
+	ast::Pass<ReturnFixer>::run( transUnit );
+}
+
+bool ManagedTypes::isManaged( const ast::Type * type ) const {
+	// references are never constructed
+	if ( dynamic_cast< const ast::ReferenceType * >( type ) ) return false;
+	if ( auto tupleType = dynamic_cast< const ast::TupleType * > ( type ) ) {
+		// tuple is also managed if any of its components are managed
+		for (auto & component : tupleType->types) {
+			if (isManaged(component)) return true;
+		}
+	}
+	// need to clear and reset qualifiers when determining if a type is managed
+	// ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );
+	auto tmp = shallowCopy(type);
+	tmp->qualifiers = {};
+	// delete tmp at return
+	ast::ptr<ast::Type> guard = tmp;
+	// a type is managed if it appears in the map of known managed types, or if it contains any polymorphism (is a type variable or generic type containing a type variable)
+	return managedTypes.find( Mangle::mangle( tmp, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ) != managedTypes.end() || GenPoly::isPolyType( tmp );
+}
+
+bool ManagedTypes::isManaged( const ast::ObjectDecl * objDecl ) const {
+	const ast::Type * type = objDecl->type;
+	while ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
+		// must always construct VLAs with an initializer, since this is an error in C
+		if ( at->isVarLen && objDecl->init ) return true;
+		type = at->base;
+	}
+	return isManaged( type );
+}
+
+void ManagedTypes::handleDWT( const ast::DeclWithType * dwt ) {
+	// if this function is a user-defined constructor or destructor, mark down the type as "managed"
+	if ( ! dwt->linkage.is_overrideable && CodeGen::isCtorDtor( dwt->name ) ) {
+		auto & params = GenPoly::getFunctionType( dwt->get_type())->params;
+		assert( ! params.empty() );
+		// Type * type = InitTweak::getPointerBase( params.front() );
+		// assert( type );
+		managedTypes.insert( Mangle::mangle( params.front(), {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) );
+	}
+}
+
+void ManagedTypes::handleStruct( const ast::StructDecl * aggregateDecl ) {
+	// don't construct members, but need to take note if there is a managed member,
+	// because that means that this type is also managed
+	for ( auto & member : aggregateDecl->members ) {
+		if ( auto field = member.as<ast::ObjectDecl>() ) {
+			if ( isManaged( field ) ) {
+				// generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that
+				// polymorphic constructors make generic types managed types
+				ast::StructInstType inst( aggregateDecl );
+				managedTypes.insert( Mangle::mangle( &inst, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) );
+				break;
+			}
+		}
+	}
+}
+
+void ManagedTypes::beginScope() { managedTypes.beginScope(); }
+void ManagedTypes::endScope() { managedTypes.endScope(); }
+
+ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg) {
+	assertf(objDecl, "genCtorDtor passed null objDecl");
+	InitExpander srcParam(arg);
+	return SymTab::genImplicitCall(srcParam, new ast::VariableExpr(loc, objDecl), loc, fname, objDecl);
+}
 
 ast::ConstructorInit * genCtorInit( const CodeLocation & loc, const ast::ObjectDecl * objDecl ) {
Index: src/InitTweak/GenInit.h
===================================================================
--- src/InitTweak/GenInit.h	(revision 0bd3faf870391e5ed803287ec0b3c696cfde22b2)
+++ src/InitTweak/GenInit.h	(revision 8984003da746813325cd05052fbcb1cb7bef8d62)
@@ -24,30 +24,32 @@
 
 namespace InitTweak {
-	/// Adds return value temporaries and wraps Initializers in ConstructorInit nodes
-	void genInit( ast::TranslationUnit & translationUnit );
 
-	/// Converts return statements into copy constructor calls on the hidden return variable.
-	/// This pass must happen before auto-gen.
-	void fixReturnStatements( ast::TranslationUnit & translationUnit );
+/// Adds return value temporaries and wraps Initializers in ConstructorInit nodes
+void genInit( ast::TranslationUnit & translationUnit );
 
-	/// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument
-	ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg = nullptr);
+/// Converts return statements into copy constructor calls on the hidden return variable.
+/// This pass must happen before auto-gen.
+void fixReturnStatements( ast::TranslationUnit & translationUnit );
 
-	/// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
-	ast::ConstructorInit * genCtorInit( const CodeLocation & loc, const ast::ObjectDecl * objDecl );
+/// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument
+ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg = nullptr);
 
-	class ManagedTypes final {
-	public:
-		bool isManaged( const ast::ObjectDecl * objDecl ) const ; // determine if object is managed
-		bool isManaged( const ast::Type * type ) const; // determine if type is managed
+/// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
+ast::ConstructorInit * genCtorInit( const CodeLocation & loc, const ast::ObjectDecl * objDecl );
 
-		void handleDWT( const ast::DeclWithType * dwt ); // add type to managed if ctor/dtor
-		void handleStruct( const ast::StructDecl * aggregateDecl ); // add type to managed if child is managed
+class ManagedTypes final {
+public:
+	bool isManaged( const ast::ObjectDecl * objDecl ) const ; // determine if object is managed
+	bool isManaged( const ast::Type * type ) const; // determine if type is managed
 
-		void beginScope();
-		void endScope();
-	private:
-		GenPoly::ScopedSet< std::string > managedTypes;
-	};
+	void handleDWT( const ast::DeclWithType * dwt ); // add type to managed if ctor/dtor
+	void handleStruct( const ast::StructDecl * aggregateDecl ); // add type to managed if child is managed
+
+	void beginScope();
+	void endScope();
+private:
+	GenPoly::ScopedSet< std::string > managedTypes;
+};
+
 } // namespace
 
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 0bd3faf870391e5ed803287ec0b3c696cfde22b2)
+++ src/InitTweak/InitTweak.cc	(revision 8984003da746813325cd05052fbcb1cb7bef8d62)
@@ -14,4 +14,6 @@
 //
 
+#include "InitTweak.h"
+
 #include <algorithm>               // for find, all_of
 #include <cassert>                 // for assertf, assert, strict_dynamic_cast
@@ -30,81 +32,13 @@
 #include "CodeGen/OperatorTable.h" // for isConstructor, isDestructor, isCto...
 #include "Common/SemanticError.h"  // for SemanticError
+#include "Common/ToString.hpp"     // for toCString
 #include "Common/UniqueName.h"     // for UniqueName
-#include "Common/utility.h"        // for toString, deleteAll, maybeClone
 #include "GenPoly/GenPoly.h"       // for getFunctionType
-#include "InitTweak.h"
 #include "ResolvExpr/Unify.h"      // for typesCompatibleIgnoreQualifiers
 #include "Tuples/Tuples.h"         // for Tuples::isTtype
 
 namespace InitTweak {
-	namespace {
-		struct HasDesignations : public ast::WithShortCircuiting {
-			bool result = false;
-
-			void previsit( const ast::Node * ) {
-				// short circuit if we already know there are designations
-				if ( result ) visit_children = false;
-			}
-
-			void previsit( const ast::Designation * des ) {
-				// short circuit if we already know there are designations
-				if ( result ) visit_children = false;
-				else if ( ! des->designators.empty() ) {
-					result = true;
-					visit_children = false;
-				}
-			}
-		};
-
-		struct InitDepthChecker {
-			bool result = true;
-			const ast::Type * type;
-			int curDepth = 0, maxDepth = 0;
-			InitDepthChecker( const ast::Type * type ) : type( type ) {
-				const ast::Type * t = type;
-				while ( auto at = dynamic_cast< const ast::ArrayType * >( t ) ) {
-					maxDepth++;
-					t = at->base;
-				}
-				maxDepth++;
-			}
-			void previsit( ast::ListInit const * ) {
-				curDepth++;
-				if ( curDepth > maxDepth ) result = false;
-			}
-			void postvisit( ast::ListInit const * ) {
-				curDepth--;
-			}
-		};
-
-		struct InitFlattener : public ast::WithShortCircuiting {
-			std::vector< ast::ptr< ast::Expr > > argList;
-
-			void previsit( const ast::SingleInit * singleInit ) {
-				visit_children = false;
-				argList.emplace_back( singleInit->value );
-			}
-		};
-
-	} // anonymous namespace
-
-	bool isDesignated( const ast::Init * init ) {
-		ast::Pass<HasDesignations> finder;
-		maybe_accept( init, finder );
-		return finder.core.result;
-	}
-
-	bool checkInitDepth( const ast::ObjectDecl * objDecl ) {
-		ast::Pass<InitDepthChecker> checker( objDecl->type );
-		maybe_accept( objDecl->init.get(), checker );
-		return checker.core.result;
-	}
-
-std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init ) {
-	ast::Pass< InitFlattener > flattener;
-	maybe_accept( init, flattener );
-	return std::move( flattener.core.argList );
-}
-
+
+// Forward declared, because it is used as a parent type.
 class InitExpander::ExpanderImpl {
 public:
@@ -116,4 +50,52 @@
 
 namespace {
+	struct HasDesignations : public ast::WithShortCircuiting {
+		bool result = false;
+
+		void previsit( const ast::Node * ) {
+			// Short circuit if we already know there are designations.
+			if ( result ) visit_children = false;
+		}
+
+		void previsit( const ast::Designation * des ) {
+			// Short circuit if we already know there are designations.
+			if ( result ) visit_children = false;
+			else if ( !des->designators.empty() ) {
+				result = true;
+				visit_children = false;
+			}
+		}
+	};
+
+	struct InitDepthChecker {
+		bool result = true;
+		const ast::Type * type;
+		int curDepth = 0, maxDepth = 0;
+		InitDepthChecker( const ast::Type * type ) : type( type ) {
+			const ast::Type * t = type;
+			while ( auto at = dynamic_cast< const ast::ArrayType * >( t ) ) {
+				maxDepth++;
+				t = at->base;
+			}
+			maxDepth++;
+		}
+		void previsit( ast::ListInit const * ) {
+			curDepth++;
+			if ( curDepth > maxDepth ) result = false;
+		}
+		void postvisit( ast::ListInit const * ) {
+			curDepth--;
+		}
+	};
+
+	struct InitFlattener : public ast::WithShortCircuiting {
+		std::vector< ast::ptr< ast::Expr > > argList;
+
+		void previsit( const ast::SingleInit * singleInit ) {
+			visit_children = false;
+			argList.emplace_back( singleInit->value );
+		}
+	};
+
 	template< typename Out >
 	void buildCallExpr(
@@ -223,10 +205,10 @@
 			InitExpander::IndexList & indices
 		) override {
-			if ( ! arg ) return {};
+			if ( !arg ) return {};
 
 			const CodeLocation & loc = arg->location;
 			const ast::Expr * expr = arg;
 			for ( auto it = indices.rbegin(); it != indices.rend(); ++it ) {
-				// go through indices and layer on subscript exprs ?[?]
+				// Go through indices and layer on subscript exprs ?[?].
 				++it;
 				expr = new ast::UntypedExpr{
@@ -242,69 +224,4 @@
 		}
 	};
-} // anonymous namespace
-
-InitExpander::InitExpander( const ast::Init * init )
-: expander( new InitImpl{ init } ), crnt(), indices() {}
-
-InitExpander::InitExpander( const ast::Expr * expr )
-: expander( new ExprImpl{ expr } ), crnt(), indices() {}
-
-std::vector< ast::ptr< ast::Expr > > InitExpander::operator* () { return crnt; }
-
-InitExpander & InitExpander::operator++ () {
-	crnt = expander->next( indices );
-	return *this;
-}
-
-/// builds statement which has the same semantics as a C-style list initializer (for array
-/// initializers) using callExpr as the base expression to perform initialization
-ast::ptr< ast::Stmt > InitExpander::buildListInit( ast::UntypedExpr * callExpr ) {
-	return expander->buildListInit( callExpr, indices );
-}
-
-void InitExpander::addArrayIndex( const ast::Expr * index, const ast::Expr * dimension ) {
-	indices.emplace_back( index );
-	indices.emplace_back( dimension );
-}
-
-void InitExpander::clearArrayIndices() { indices.clear(); }
-
-bool InitExpander::addReference() {
-	for ( ast::ptr< ast::Expr > & expr : crnt ) {
-		expr = new ast::AddressExpr{ expr };
-	}
-	return ! crnt.empty();
-}
-
-	const ast::Type * getTypeofThis( const ast::FunctionType * ftype ) {
-		assertf( ftype, "getTypeofThis: nullptr ftype" );
-		const std::vector<ast::ptr<ast::Type>> & params = ftype->params;
-		assertf( !params.empty(), "getTypeofThis: ftype with 0 parameters: %s",
-				toString( ftype ).c_str() );
-		const ast::ReferenceType * refType =
-			params.front().strict_as<ast::ReferenceType>();
-		return refType->base;
-	}
-
-	const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func) {
-		assertf( func, "getParamThis: nullptr ftype" );
-		auto & params = func->params;
-		assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( func ).c_str());
-		return params.front().strict_as<ast::ObjectDecl>();
-	}
-
-	bool tryConstruct( const ast::DeclWithType * dwt ) {
-		auto objDecl = dynamic_cast< const ast::ObjectDecl * >( dwt );
-		if ( ! objDecl ) return false;
-		return (objDecl->init == nullptr ||
-				( objDecl->init != nullptr && objDecl->init->maybeConstructed ))
-			&& ! objDecl->storage.is_extern
-			&& isConstructable( objDecl->type );
-	}
-
-	bool isConstructable( const ast::Type * type ) {
-		return ! dynamic_cast< const ast::VarArgsType * >( type ) && ! dynamic_cast< const ast::ReferenceType * >( type )
-		&& ! dynamic_cast< const ast::FunctionType * >( type ) && ! Tuples::isTtype( type );
-	}
 
 	struct CallFinder final {
@@ -325,62 +242,12 @@
 	};
 
-	std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt ) {
-		ast::Pass< CallFinder > finder{ std::vector< std::string >{ "?{}", "^?{}" } };
-		maybe_accept( stmt, finder );
-		return std::move( finder.core.matches );
-	}
-
-	namespace {
-		template <typename Predicate>
-		bool allofCtorDtor( const ast::Stmt * stmt, const Predicate & pred ) {
-			std::vector< const ast::Expr * > callExprs = collectCtorDtorCalls( stmt );
-			return std::all_of( callExprs.begin(), callExprs.end(), pred );
-		}
-	}
-
-	bool isIntrinsicSingleArgCallStmt( const ast::Stmt * stmt ) {
-		return allofCtorDtor( stmt, []( const ast::Expr * callExpr ){
-			if ( const ast::ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
-				const ast::FunctionType * funcType =
-					GenPoly::getFunctionType( appExpr->func->result );
-				assert( funcType );
-				return funcType->params.size() == 1;
-			}
-			return false;
-		});
-	}
-
-	// looks like some other such codegen uses UntypedExpr and does not create fake function. should revisit afterwards
-	// following passes may accidentally resolve this expression if returned as untyped...
-	ast::Expr * createBitwiseAssignment (const ast::Expr * dst, const ast::Expr * src) {
-		static ast::ptr<ast::FunctionDecl> assign = nullptr;
-		if (!assign) {
-			auto td = new ast::TypeDecl(CodeLocation(), "T", {}, nullptr, ast::TypeDecl::Dtype, true);
-			assign = new ast::FunctionDecl(CodeLocation(), "?=?", {td},
-			{ new ast::ObjectDecl(CodeLocation(), "_dst", new ast::ReferenceType(new ast::TypeInstType("T", td))),
-			  new ast::ObjectDecl(CodeLocation(), "_src", new ast::TypeInstType("T", td))},
-			{ new ast::ObjectDecl(CodeLocation(), "_ret", new ast::TypeInstType("T", td))}, nullptr, {}, ast::Linkage::Intrinsic);
-		}
-		if (dst->result.as<ast::ReferenceType>()) {
-			for (int depth = dst->result->referenceDepth(); depth > 0; depth--) {
-				dst = new ast::AddressExpr(dst);
-			}
-		} else {
-			dst = new ast::CastExpr(dst, new ast::ReferenceType(dst->result, {}));
-		}
-		if (src->result.as<ast::ReferenceType>()) {
-			for (int depth = src->result->referenceDepth(); depth > 0; depth--) {
-				src = new ast::AddressExpr(src);
-			}
-		}
-		auto var = ast::VariableExpr::functionPointer(dst->location, assign);
-		auto app = new ast::ApplicationExpr(dst->location, var, {dst, src});
-		// Skip the resolver, just set the result to the correct type.
-		app->result = ast::deepCopy( src->result );
-		return app;
+	template <typename Predicate>
+	bool allofCtorDtor( const ast::Stmt * stmt, const Predicate & pred ) {
+		std::vector< const ast::Expr * > callExprs = collectCtorDtorCalls( stmt );
+		return std::all_of( callExprs.begin(), callExprs.end(), pred );
 	}
 
 	struct ConstExprChecker : public ast::WithShortCircuiting {
-		// most expressions are not const expr
+		// Most expressions are not const-expr.
 		void previsit( const ast::Expr * ) { result = false; visit_children = false; }
 
@@ -389,12 +256,12 @@
 			const ast::Expr * arg = addressExpr->arg;
 
-			// address of a variable or member expression is constexpr
-			if ( ! dynamic_cast< const ast::NameExpr * >( arg )
-			&& ! dynamic_cast< const ast::VariableExpr * >( arg )
-			&& ! dynamic_cast< const ast::MemberExpr * >( arg )
-			&& ! dynamic_cast< const ast::UntypedMemberExpr * >( arg ) ) result = false;
-		}
-
-		// these expressions may be const expr, depending on their children
+			// Address of a variable or member expression is const-expr.
+			if ( !dynamic_cast< const ast::NameExpr * >( arg )
+				&& !dynamic_cast< const ast::VariableExpr * >( arg )
+				&& !dynamic_cast< const ast::MemberExpr * >( arg )
+				&& !dynamic_cast< const ast::UntypedMemberExpr * >( arg ) ) result = false;
+		}
+
+		// These expressions may be const expr, depending on their children.
 		void previsit( const ast::SizeofExpr * ) {}
 		void previsit( const ast::AlignofExpr * ) {}
@@ -423,23 +290,5 @@
 		bool result = true;
 	};
-
-	bool isConstExpr( const ast::Expr * expr ) {
-		if ( expr ) {
-			ast::Pass<ConstExprChecker> checker;
-			expr->accept( checker );
-			return checker.core.result;
-		}
-		return true;
-	}
-
-	bool isConstExpr( const ast::Init * init ) {
-		if ( init ) {
-			ast::Pass<ConstExprChecker> checker;
-			init->accept( checker );
-			return checker.core.result;
-		} // if
-		// for all intents and purposes, no initializer means const expr
-		return true;
-	}
+} // namespace
 
 bool isAssignment( const ast::FunctionDecl * decl ) {
@@ -470,19 +319,160 @@
 }
 
-	#if defined( __x86_64 ) || defined( __i386 ) // assembler comment to prevent assembler warning message
-		#define ASM_COMMENT "#"
-	#else // defined( __ARM_ARCH )
-		#define ASM_COMMENT "//"
-	#endif
-	static const char * const data_section =  ".data" ASM_COMMENT;
-	static const char * const tlsd_section = ".tdata" ASM_COMMENT;
-
-	void addDataSectionAttribute( ast::ObjectDecl * objDecl ) {
-		const bool is_tls = objDecl->storage.is_threadlocal_any();
-		const char * section = is_tls ? tlsd_section : data_section;
-		objDecl->attributes.push_back(new ast::Attribute("section", {
-			ast::ConstantExpr::from_string(objDecl->location, section)
-		}));
-	}
+const ast::Type * getTypeofThis( const ast::FunctionType * ftype ) {
+	assertf( ftype, "getTypeofThis: nullptr ftype" );
+	const std::vector<ast::ptr<ast::Type>> & params = ftype->params;
+	assertf( !params.empty(), "getTypeofThis: ftype with 0 parameters: %s",
+			toCString( ftype ) );
+	const ast::ReferenceType * refType =
+		params.front().strict_as<ast::ReferenceType>();
+	return refType->base;
+}
+
+const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func) {
+	assertf( func, "getParamThis: nullptr ftype" );
+	auto & params = func->params;
+	assertf( !params.empty(), "getParamThis: ftype with 0 parameters: %s", toCString( func ));
+	return params.front().strict_as<ast::ObjectDecl>();
+}
+
+// looks like some other such codegen uses UntypedExpr and does not create fake function. should revisit afterwards
+// following passes may accidentally resolve this expression if returned as untyped...
+ast::Expr * createBitwiseAssignment(const ast::Expr * dst, const ast::Expr * src) {
+	static ast::ptr<ast::FunctionDecl> assign = nullptr;
+	if (!assign) {
+		auto td = new ast::TypeDecl(CodeLocation(), "T", {}, nullptr, ast::TypeDecl::Dtype, true);
+		assign = new ast::FunctionDecl(CodeLocation(), "?=?", {td},
+		{ new ast::ObjectDecl(CodeLocation(), "_dst", new ast::ReferenceType(new ast::TypeInstType("T", td))),
+		  new ast::ObjectDecl(CodeLocation(), "_src", new ast::TypeInstType("T", td))},
+		{ new ast::ObjectDecl(CodeLocation(), "_ret", new ast::TypeInstType("T", td))}, nullptr, {}, ast::Linkage::Intrinsic);
+	}
+	if (dst->result.as<ast::ReferenceType>()) {
+		for (int depth = dst->result->referenceDepth(); depth > 0; depth--) {
+			dst = new ast::AddressExpr(dst);
+		}
+	} else {
+		dst = new ast::CastExpr(dst, new ast::ReferenceType(dst->result, {}));
+	}
+	if (src->result.as<ast::ReferenceType>()) {
+		for (int depth = src->result->referenceDepth(); depth > 0; depth--) {
+			src = new ast::AddressExpr(src);
+		}
+	}
+	auto var = ast::VariableExpr::functionPointer(dst->location, assign);
+	auto app = new ast::ApplicationExpr(dst->location, var, {dst, src});
+	// Skip the resolver, just set the result to the correct type.
+	app->result = ast::deepCopy( src->result );
+	return app;
+}
+
+std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init ) {
+	ast::Pass< InitFlattener > flattener;
+	maybe_accept( init, flattener );
+	return std::move( flattener.core.argList );
+}
+
+bool tryConstruct( const ast::DeclWithType * dwt ) {
+	auto objDecl = dynamic_cast< const ast::ObjectDecl * >( dwt );
+	if ( !objDecl ) return false;
+	return (objDecl->init == nullptr ||
+			( objDecl->init != nullptr && objDecl->init->maybeConstructed ))
+		&& !objDecl->storage.is_extern
+		&& isConstructable( objDecl->type );
+}
+
+bool isConstructable( const ast::Type * type ) {
+	return !dynamic_cast< const ast::VarArgsType * >( type ) && !dynamic_cast< const ast::ReferenceType * >( type )
+		&& !dynamic_cast< const ast::FunctionType * >( type ) && !Tuples::isTtype( type );
+}
+
+bool isDesignated( const ast::Init * init ) {
+//	return ( init ) ? ast::Pass<HasDesignations>::read( init ) : false;
+	ast::Pass<HasDesignations> finder;
+	maybe_accept( init, finder );
+	return finder.core.result;
+}
+
+bool checkInitDepth( const ast::ObjectDecl * objDecl ) {
+//	return ( objDecl->init ) ? ast::Pass<InitDepthChecker::read( objDecl->init, objDecl->type ) : true;
+	ast::Pass<InitDepthChecker> checker( objDecl->type );
+	maybe_accept( objDecl->init.get(), checker );
+	return checker.core.result;
+}
+
+bool isIntrinsicSingleArgCallStmt( const ast::Stmt * stmt ) {
+	return allofCtorDtor( stmt, []( const ast::Expr * callExpr ){
+		if ( const ast::ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
+			const ast::FunctionType * funcType =
+				GenPoly::getFunctionType( appExpr->func->result );
+			assert( funcType );
+			return funcType->params.size() == 1;
+		}
+		return false;
+	});
+}
+
+std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt ) {
+	ast::Pass< CallFinder > finder{ std::vector< std::string >{ "?{}", "^?{}" } };
+	maybe_accept( stmt, finder );
+	return std::move( finder.core.matches );
+}
+
+bool isConstExpr( const ast::Expr * expr ) {
+	return ( expr ) ? ast::Pass<ConstExprChecker>::read( expr ) : true;
+}
+
+bool isConstExpr( const ast::Init * init ) {
+	// for all intents and purposes, no initializer means const expr
+	return ( init ) ? ast::Pass<ConstExprChecker>::read( init ) : true;
+}
+
+#if defined( __x86_64 ) || defined( __i386 ) // assembler comment to prevent assembler warning message
+	#define ASM_COMMENT "#"
+#else // defined( __ARM_ARCH )
+	#define ASM_COMMENT "//"
+#endif
+static const char * const data_section =  ".data" ASM_COMMENT;
+static const char * const tlsd_section = ".tdata" ASM_COMMENT;
+
+void addDataSectionAttribute( ast::ObjectDecl * objDecl ) {
+	const bool is_tls = objDecl->storage.is_threadlocal_any();
+	const char * section = is_tls ? tlsd_section : data_section;
+	objDecl->attributes.push_back(new ast::Attribute("section", {
+		ast::ConstantExpr::from_string(objDecl->location, section)
+	}));
+}
+
+InitExpander::InitExpander( const ast::Init * init )
+: expander( new InitImpl{ init } ), crnt(), indices() {}
+
+InitExpander::InitExpander( const ast::Expr * expr )
+: expander( new ExprImpl{ expr } ), crnt(), indices() {}
+
+std::vector< ast::ptr< ast::Expr > > InitExpander::operator* () { return crnt; }
+
+InitExpander & InitExpander::operator++ () {
+	crnt = expander->next( indices );
+	return *this;
+}
+
+/// builds statement which has the same semantics as a C-style list initializer (for array
+/// initializers) using callExpr as the base expression to perform initialization
+ast::ptr< ast::Stmt > InitExpander::buildListInit( ast::UntypedExpr * callExpr ) {
+	return expander->buildListInit( callExpr, indices );
+}
+
+void InitExpander::addArrayIndex( const ast::Expr * index, const ast::Expr * dimension ) {
+	indices.emplace_back( index );
+	indices.emplace_back( dimension );
+}
+
+void InitExpander::clearArrayIndices() { indices.clear(); }
+
+bool InitExpander::addReference() {
+	for ( ast::ptr< ast::Expr > & expr : crnt ) {
+		expr = new ast::AddressExpr{ expr };
+	}
+	return !crnt.empty();
+}
 
 } // namespace InitTweak
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision 0bd3faf870391e5ed803287ec0b3c696cfde22b2)
+++ src/InitTweak/InitTweak.h	(revision 8984003da746813325cd05052fbcb1cb7bef8d62)
@@ -25,90 +25,92 @@
 // helper functions for initialization
 namespace InitTweak {
-	bool isAssignment( const ast::FunctionDecl * decl );
-	bool isDestructor( const ast::FunctionDecl * decl );
-	bool isDefaultConstructor( const ast::FunctionDecl * decl );
-	bool isCopyConstructor( const ast::FunctionDecl * decl );
-	bool isCopyFunction( const ast::FunctionDecl * decl );
 
-	/// returns the base type of the first parameter to a constructor/destructor/assignment function
-	const ast::Type * getTypeofThis( const ast::FunctionType * ftype );
+bool isAssignment( const ast::FunctionDecl * decl );
+bool isDestructor( const ast::FunctionDecl * decl );
+bool isDefaultConstructor( const ast::FunctionDecl * decl );
+bool isCopyConstructor( const ast::FunctionDecl * decl );
+bool isCopyFunction( const ast::FunctionDecl * decl );
 
-	/// returns the first parameter of a constructor/destructor/assignment function
-	const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func);
+/// returns the base type of the first parameter to a constructor/destructor/assignment function
+const ast::Type * getTypeofThis( const ast::FunctionType * ftype );
 
-	/// generate a bitwise assignment operation.
-	ast::Expr * createBitwiseAssignment( const ast::Expr * dst, const ast::Expr * src);
+/// returns the first parameter of a constructor/destructor/assignment function
+const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func);
 
-	/// transform Initializer into an argument list that can be passed to a call expression
-	std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init );
+/// generate a bitwise assignment operation.
+ast::Expr * createBitwiseAssignment( const ast::Expr * dst, const ast::Expr * src);
 
-	/// True if the resolver should try to construct dwt
-	bool tryConstruct( const ast::DeclWithType * dwt );
+/// transform Initializer into an argument list that can be passed to a call expression
+std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init );
 
-	/// True if the type can have a user-defined constructor
-	bool isConstructable( const ast::Type * t );
+/// True if the resolver should try to construct dwt
+bool tryConstruct( const ast::DeclWithType * dwt );
 
-	/// True if the Initializer contains designations
-	bool isDesignated( const ast::Init * init );
+/// True if the type can have a user-defined constructor
+bool isConstructable( const ast::Type * t );
 
-	/// True if the ObjectDecl's Initializer nesting level is not deeper than the depth of its
-	/// type, where the depth of its type is the number of nested ArrayTypes + 1
-	bool checkInitDepth( const ast::ObjectDecl * objDecl );
+/// True if the Initializer contains designations
+bool isDesignated( const ast::Init * init );
 
-	/// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
-	/// Intended to be used for default ctor/dtor calls, but might have use elsewhere.
-	/// Currently has assertions that make it less than fully general.
-	bool isIntrinsicSingleArgCallStmt( const ast::Stmt * stmt );
+/// True if the ObjectDecl's Initializer nesting level is not deeper than the depth of its
+/// type, where the depth of its type is the number of nested ArrayTypes + 1
+bool checkInitDepth( const ast::ObjectDecl * objDecl );
 
-	/// get all Ctor/Dtor call expressions from a Statement
-	std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt );
+/// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
+/// Intended to be used for default ctor/dtor calls, but might have use elsewhere.
+/// Currently has assertions that make it less than fully general.
+bool isIntrinsicSingleArgCallStmt( const ast::Stmt * stmt );
 
-	/// returns true if expr is trivially a compile-time constant
-	bool isConstExpr( const ast::Expr * expr );
-	bool isConstExpr( const ast::Init * init );
+/// get all Ctor/Dtor call expressions from a Statement
+std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt );
 
-	/// Modifies objDecl to have:
-	///    __attribute__((section (".data#")))
-	/// which makes gcc put the declared variable in the data section,
-	/// which is helpful for global constants on newer gcc versions,
-	/// so that CFA's generated initialization won't segfault when writing it via a const cast.
-	/// The trailing # is an injected assembly comment, to suppress the "a" in
-	///    .section .data,"a"
-	///    .section .data#,"a"
-	/// to avoid assembler warning "ignoring changed section attributes for .data"
-	void addDataSectionAttribute( ast::ObjectDecl * objDecl );
+/// returns true if expr is trivially a compile-time constant
+bool isConstExpr( const ast::Expr * expr );
+bool isConstExpr( const ast::Init * init );
 
-	class InitExpander final {
-	public:
-		using IndexList = std::vector< ast::ptr< ast::Expr > >;
-		class ExpanderImpl;
+/// Modifies objDecl to have:
+///    __attribute__((section (".data#")))
+/// which makes gcc put the declared variable in the data section,
+/// which is helpful for global constants on newer gcc versions,
+/// so that CFA's generated initialization won't segfault when writing it via a const cast.
+/// The trailing # is an injected assembly comment, to suppress the "a" in
+///    .section .data,"a"
+///    .section .data#,"a"
+/// to avoid assembler warning "ignoring changed section attributes for .data"
+void addDataSectionAttribute( ast::ObjectDecl * objDecl );
 
-	private:
-		std::shared_ptr< ExpanderImpl > expander;
-		std::vector< ast::ptr< ast::Expr > > crnt;
-		// invariant: list of size 2N (elements come in pairs [index, dimension])
-		IndexList indices;
+class InitExpander final {
+public:
+	using IndexList = std::vector< ast::ptr< ast::Expr > >;
+	class ExpanderImpl;
 
-	public:
-		/// Expand by stepping through init to get each list of arguments
-		InitExpander( const ast::Init * init );
+private:
+	std::shared_ptr< ExpanderImpl > expander;
+	std::vector< ast::ptr< ast::Expr > > crnt;
+	// invariant: list of size 2N (elements come in pairs [index, dimension])
+	IndexList indices;
 
-		/// Always expand to expression
-		InitExpander( const ast::Expr * expr );
+public:
+	/// Expand by stepping through init to get each list of arguments
+	InitExpander( const ast::Init * init );
 
-		std::vector< ast::ptr< ast::Expr > > operator* ();
-		InitExpander & operator++ ();
+	/// Always expand to expression
+	InitExpander( const ast::Expr * expr );
 
-		/// builds statement which has the same semantics as a C-style list initializer (for array
-		/// initializers) using callExpr as the base expression to perform initialization.
-		/// Mutates callExpr
-		ast::ptr< ast::Stmt > buildListInit( ast::UntypedExpr * callExpr );
+	std::vector< ast::ptr< ast::Expr > > operator* ();
+	InitExpander & operator++ ();
 
-		void addArrayIndex( const ast::Expr * index, const ast::Expr * dimension );
+	/// builds statement which has the same semantics as a C-style list initializer (for array
+	/// initializers) using callExpr as the base expression to perform initialization.
+	/// Mutates callExpr
+	ast::ptr< ast::Stmt > buildListInit( ast::UntypedExpr * callExpr );
 
-		void clearArrayIndices();
+	void addArrayIndex( const ast::Expr * index, const ast::Expr * dimension );
 
-		bool addReference();
-	};
+	void clearArrayIndices();
+
+	bool addReference();
+};
+
 } // namespace InitTweak
 
