Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision 9504a8969e7d1bb7042a4cf7d786d6db2fbe2d39)
+++ src/AST/Stmt.hpp	(revision f2f22e34cda38ea572dae4fcf8ee19c16aa4160d)
@@ -143,5 +143,5 @@
 
 	IfStmt( const CodeLocation & loc, const Expr * cond, const Stmt * thenPart,
-		Stmt * const elsePart, std::vector<ptr<Stmt>> && inits,
+		const Stmt * elsePart = nullptr, std::vector<ptr<Stmt>> && inits = {},
 		std::vector<Label> && labels = {} )
 	: Stmt(loc, std::move(labels)), cond(cond), thenPart(thenPart), elsePart(elsePart),
Index: src/Common/utility.h
===================================================================
--- src/Common/utility.h	(revision 9504a8969e7d1bb7042a4cf7d786d6db2fbe2d39)
+++ src/Common/utility.h	(revision f2f22e34cda38ea572dae4fcf8ee19c16aa4160d)
@@ -34,4 +34,11 @@
 class Expression;
 
+/// bring std::move into global scope
+using std::move;
+
+/// partner to move that copies any copyable type
+template<typename T>
+T copy( const T & x ) { return x; }
+
 template< typename T >
 static inline T * maybeClone( const T *orig ) {
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 9504a8969e7d1bb7042a4cf7d786d6db2fbe2d39)
+++ src/InitTweak/InitTweak.cc	(revision f2f22e34cda38ea572dae4fcf8ee19c16aa4160d)
@@ -22,5 +22,7 @@
 
 #include "AST/Expr.hpp"
+#include "AST/Init.hpp"
 #include "AST/Node.hpp"
+#include "AST/Pass.hpp"
 #include "AST/Stmt.hpp"
 #include "AST/Type.hpp"
@@ -85,5 +87,5 @@
 		};
 
-		struct InitFlattener : public WithShortCircuiting {
+		struct InitFlattener_old : public WithShortCircuiting {
 			void previsit( SingleInit * singleInit ) {
 				visit_children = false;
@@ -93,8 +95,17 @@
 		};
 
-	}
+		struct InitFlattener_new : 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
 
 	std::list< Expression * > makeInitList( Initializer * init ) {
-		PassVisitor<InitFlattener> flattener;
+		PassVisitor<InitFlattener_old> flattener;
 		maybeAccept( init, flattener );
 		return flattener.pass.argList;
@@ -114,8 +125,7 @@
 
 std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init ) {
-	#warning unimplmented
-	(void)init;
-	assert(false);
-	return {};
+	ast::Pass< InitFlattener_new > flattener;
+	maybe_accept( init, flattener );
+	return std::move( flattener.pass.argList );
 }
 
@@ -309,8 +319,75 @@
 	virtual std::vector< ast::ptr< ast::Expr > > next( IndexList & indices ) = 0;
 	virtual ast::ptr< ast::Stmt > buildListInit( 
-		const ast::UntypedExpr * callExpr, IndexList & indices ) = 0;
+		ast::UntypedExpr * callExpr, IndexList & indices ) = 0;
 };
 
 namespace {
+	template< typename Out >
+	void buildCallExpr( 
+		ast::UntypedExpr * callExpr, const ast::Expr * index, const ast::Expr * dimension, 
+		const ast::Init * init, Out & out
+	) {
+		const CodeLocation & loc = init->location;
+
+		auto cond = new ast::UntypedExpr{ 
+			loc, new ast::NameExpr{ loc, "?<?" }, { index, dimension } };
+		
+		std::vector< ast::ptr< ast::Expr > > args = makeInitList( init );
+		splice( callExpr->args, args );
+
+		out.emplace_back( new ast::IfStmt{ loc, cond, new ast::ExprStmt{ loc, callExpr } } );
+
+		out.emplace_back( new ast::ExprStmt{ 
+			loc, new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, "++?" }, { index } } } );
+	}
+
+	template< typename Out >
+	void build(
+		ast::UntypedExpr * callExpr, const InitExpander_new::IndexList & indices, 
+		const ast::Init * init, Out & out
+	) {
+		if ( indices.empty() ) return;
+
+		unsigned idx = 0;
+
+		const ast::Expr * index = indices[idx++];
+		assert( idx != indices.size() );
+		const ast::Expr * dimension = indices[idx++];
+
+		if ( idx == indices.size() ) {
+			if ( auto listInit = dynamic_cast< const ast::ListInit * >( init ) ) {
+				for ( const ast::Init * init : *listInit ) {
+					buildCallExpr( callExpr, index, dimension, init, out );
+				}
+			} else {
+				buildCallExpr( callExpr, index, dimension, init, out );
+			}
+		} else {
+			const CodeLocation & loc = init->location;
+
+			unsigned long cond = 0;
+			auto listInit = dynamic_cast< const ast::ListInit * >( init );
+			if ( ! listInit ) { SemanticError( loc, "unbalanced list initializers" ); }
+
+			static UniqueName targetLabel( "L__autogen__" );
+			ast::Label switchLabel{ 
+				loc, targetLabel.newName(), { new ast::Attribute{ "unused" } } };
+			
+			std::vector< ast::ptr< ast::Stmt > > branches;
+			for ( const ast::Init * init : *listInit ) {
+				auto condition = ast::ConstantExpr::from_ulong( loc, cond );
+				++cond;
+
+				std::vector< ast::ptr< ast::Stmt > > stmts;
+				build( callExpr, indices, init, stmts );
+				stmts.emplace_back( 
+					new ast::BranchStmt{ loc, ast::BranchStmt::Break, switchLabel } );
+				branches.emplace_back( new ast::CaseStmt{ loc, condition, std::move( stmts ) } );
+			}
+			out.emplace_back( new ast::SwitchStmt{ loc, index, std::move( branches ) } );
+			out.emplace_back( new ast::NullStmt{ loc, { switchLabel } } );
+		}
+	}
+
 	class InitImpl_new final : public InitExpander_new::ExpanderImpl {
 		ast::ptr< ast::Init > init;
@@ -323,10 +400,23 @@
 		
 		ast::ptr< ast::Stmt > buildListInit( 
-			const ast::UntypedExpr * callExpr, InitExpander_new::IndexList & indices 
+			ast::UntypedExpr * callExpr, InitExpander_new::IndexList & indices 
 		) override {
-			#warning unimplemented
-			(void)callExpr; (void)indices;
-			assert(false);
-			return {};
+			// If array came with an initializer list, initialize each element. We may have more 
+			// initializers than elements of the array; need to check at each index that we have 
+			// not exceeded size. We 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
+
+			if ( ! init ) return {};
+
+			std::list< ast::ptr< ast::Stmt > > stmts;
+			build( callExpr, indices, init, stmts );
+			if ( stmts.empty() ) {
+				return {};
+			} else {
+				auto block = new ast::CompoundStmt{ init->location, std::move( stmts ) };
+				init = nullptr;  // consumed in creating the list init
+				return block;
+			}
 		}
 	};
@@ -340,12 +430,19 @@
 			InitExpander_new::IndexList & indices 
 		) override {
-			#warning unimplemented
-			(void)indices;
-			assert(false);
-			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 ?[?]
+				++it;
+				expr = new ast::UntypedExpr{ 
+					loc, new ast::NameExpr{ loc, "?[?]" }, { expr, *it } };
+			}
+			return { expr };
 		}
 		
 		ast::ptr< ast::Stmt > buildListInit( 
-			const ast::UntypedExpr *, InitExpander_new::IndexList & 
+			ast::UntypedExpr *, InitExpander_new::IndexList & 
 		) override { 
 			return {};
@@ -369,5 +466,5 @@
 /// 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_new::buildListInit( const ast::UntypedExpr * callExpr ) {
+ast::ptr< ast::Stmt > InitExpander_new::buildListInit( ast::UntypedExpr * callExpr ) {
 	return expander->buildListInit( callExpr, indices );
 }
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision 9504a8969e7d1bb7042a4cf7d786d6db2fbe2d39)
+++ src/InitTweak/InitTweak.h	(revision f2f22e34cda38ea572dae4fcf8ee19c16aa4160d)
@@ -154,6 +154,7 @@
 
 		/// 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 > buildListInit( const ast::UntypedExpr * callExpr );
+		/// initializers) using callExpr as the base expression to perform initialization. 
+		/// Mutates callExpr
+		ast::ptr< ast::Stmt > buildListInit( ast::UntypedExpr * callExpr );
 
 		void addArrayIndex( const ast::Expr * index, const ast::Expr * dimension );
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 9504a8969e7d1bb7042a4cf7d786d6db2fbe2d39)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision f2f22e34cda38ea572dae4fcf8ee19c16aa4160d)
@@ -56,10 +56,4 @@
 #define PRINT( text ) if ( resolvep ) { text }
 //#define DEBUG_COST
-
-using std::move;
-
-/// copies any copyable type
-template<typename T>
-T copy(const T& x) { return x; }
 
 namespace ResolvExpr {
Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision 9504a8969e7d1bb7042a4cf7d786d6db2fbe2d39)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision f2f22e34cda38ea572dae4fcf8ee19c16aa4160d)
@@ -39,4 +39,5 @@
 #include "AST/SymbolTable.hpp"
 #include "AST/Type.hpp"
+#include "Common/utility.h"       // for move, copy
 #include "SymTab/Mangler.h"
 #include "SymTab/Validate.h"      // for validateType
@@ -46,10 +47,4 @@
 
 namespace ResolvExpr {
-
-using std::move;
-
-/// partner to move that copies any copyable type
-template<typename T>
-T copy( const T & x ) { return x; }
 
 const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ) {
Index: src/SymTab/FixFunction.cc
===================================================================
--- src/SymTab/FixFunction.cc	(revision 9504a8969e7d1bb7042a4cf7d786d6db2fbe2d39)
+++ src/SymTab/FixFunction.cc	(revision f2f22e34cda38ea572dae4fcf8ee19c16aa4160d)
@@ -18,5 +18,8 @@
 #include <list>                   // for list
 
-#include "Common/utility.h"       // for maybeClone
+#include "AST/Decl.hpp"
+#include "AST/Pass.hpp"
+#include "AST/Type.hpp"
+#include "Common/utility.h"       // for maybeClone, copy
 #include "SynTree/Declaration.h"  // for FunctionDecl, ObjectDecl, Declarati...
 #include "SynTree/Expression.h"   // for Expression
@@ -24,8 +27,32 @@
 
 namespace SymTab {
-	FixFunction::FixFunction() : isVoid( false ) {}
+	class FixFunction_old : public WithShortCircuiting {
+		typedef Mutator Parent;
+	  public:
+		FixFunction_old() : isVoid( false ) {}
 
+		void premutate(FunctionDecl *functionDecl);
+		DeclarationWithType* postmutate(FunctionDecl *functionDecl);
 
-	DeclarationWithType * FixFunction::postmutate(FunctionDecl *functionDecl) {
+		Type * postmutate(ArrayType * arrayType);
+
+		void premutate(ArrayType * arrayType);
+		void premutate(VoidType * voidType);
+		void premutate(BasicType * basicType);
+		void premutate(PointerType * pointerType);
+		void premutate(StructInstType * aggregateUseType);
+		void premutate(UnionInstType * aggregateUseType);
+		void premutate(EnumInstType * aggregateUseType);
+		void premutate(TraitInstType * aggregateUseType);
+		void premutate(TypeInstType * aggregateUseType);
+		void premutate(TupleType * tupleType);
+		void premutate(VarArgsType * varArgsType);
+		void premutate(ZeroType * zeroType);
+		void premutate(OneType * oneType);
+
+		bool isVoid;
+	};
+
+	DeclarationWithType * FixFunction_old::postmutate(FunctionDecl *functionDecl) {
 		// can't delete function type because it may contain assertions, so transfer ownership to new object
 		ObjectDecl *pointer = new ObjectDecl( functionDecl->name, functionDecl->get_storageClasses(), functionDecl->linkage, nullptr, new PointerType( Type::Qualifiers(), functionDecl->type ), nullptr, functionDecl->attributes );
@@ -41,5 +68,5 @@
 	// does not cause an error
 
-	Type * FixFunction::postmutate(ArrayType *arrayType) {
+	Type * FixFunction_old::postmutate(ArrayType *arrayType) {
 		// need to recursively mutate the base type in order for multi-dimensional arrays to work.
 		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->isVarLen, arrayType->isStatic );
@@ -51,27 +78,71 @@
 	}
 
-	void FixFunction::premutate(VoidType *) {
+	void FixFunction_old::premutate(VoidType *) {
 		isVoid = true;
 	}
 
-	void FixFunction::premutate(FunctionDecl *) { visit_children = false; }
-	void FixFunction::premutate(ArrayType *) { visit_children = false; }
-	void FixFunction::premutate(BasicType *) { visit_children = false; }
-	void FixFunction::premutate(PointerType *) { visit_children = false; }
-	void FixFunction::premutate(StructInstType *) { visit_children = false; }
-	void FixFunction::premutate(UnionInstType *) { visit_children = false; }
-	void FixFunction::premutate(EnumInstType *) { visit_children = false; }
-	void FixFunction::premutate(TraitInstType *) { visit_children = false; }
-	void FixFunction::premutate(TypeInstType *) { visit_children = false; }
-	void FixFunction::premutate(TupleType *) { visit_children = false; }
-	void FixFunction::premutate(VarArgsType *) { visit_children = false; }
-	void FixFunction::premutate(ZeroType *) { visit_children = false; }
-	void FixFunction::premutate(OneType *) { visit_children = false; }
+	void FixFunction_old::premutate(FunctionDecl *) { visit_children = false; }
+	void FixFunction_old::premutate(ArrayType *) { visit_children = false; }
+	void FixFunction_old::premutate(BasicType *) { visit_children = false; }
+	void FixFunction_old::premutate(PointerType *) { visit_children = false; }
+	void FixFunction_old::premutate(StructInstType *) { visit_children = false; }
+	void FixFunction_old::premutate(UnionInstType *) { visit_children = false; }
+	void FixFunction_old::premutate(EnumInstType *) { visit_children = false; }
+	void FixFunction_old::premutate(TraitInstType *) { visit_children = false; }
+	void FixFunction_old::premutate(TypeInstType *) { visit_children = false; }
+	void FixFunction_old::premutate(TupleType *) { visit_children = false; }
+	void FixFunction_old::premutate(VarArgsType *) { visit_children = false; }
+	void FixFunction_old::premutate(ZeroType *) { visit_children = false; }
+	void FixFunction_old::premutate(OneType *) { visit_children = false; }
 
 	bool fixFunction( DeclarationWithType *& dwt ) {
-		PassVisitor<FixFunction> fixer;
+		PassVisitor<FixFunction_old> fixer;
 		dwt = dwt->acceptMutator( fixer );
 		return fixer.pass.isVoid;
 	}
+
+namespace {
+	struct FixFunction_new final : public ast::WithShortCircuiting {
+		bool isVoid = false;
+
+		void premutate( const ast::FunctionDecl * ) { visit_children = false; }
+
+		const ast::DeclWithType * postmutate( const ast::FunctionDecl * func ) {
+			return new ast::ObjectDecl{ 
+				func->location, func->name, new ast::PointerType{ func->type }, nullptr, 
+				func->storage, func->linkage, nullptr, copy( func->attributes ) };
+		}
+
+		void premutate( const ast::ArrayType * ) { visit_children = false; }
+
+		const ast::Type * postmutate( const ast::ArrayType * array ) {
+			return new ast::PointerType{ 
+				array->base, array->dimension, array->isVarLen, array->isStatic, 
+				array->qualifiers };
+		}
+
+		void premutate( const ast::VoidType * ) { isVoid = true; }
+
+		void premutate( const ast::BasicType * ) { visit_children = false; }
+		void premutate( const ast::PointerType * ) { visit_children = false; }
+		void premutate( const ast::StructInstType * ) { visit_children = false; }
+		void premutate( const ast::UnionInstType * ) { visit_children = false; }
+		void premutate( const ast::EnumInstType * ) { visit_children = false; }
+		void premutate( const ast::TraitInstType * ) { visit_children = false; }
+		void premutate( const ast::TypeInstType * ) { visit_children = false; }
+		void premutate( const ast::TupleType * ) { visit_children = false; }
+		void premutate( const ast::VarArgsType * ) { visit_children = false; }
+		void premutate( const ast::ZeroType * ) { visit_children = false; }
+		void premutate( const ast::OneType * ) { visit_children = false; }
+	};
+} // anonymous namespace
+
+const ast::DeclWithType * fixFunction( const ast::DeclWithType * dwt, bool & isVoid ) {
+	ast::Pass< FixFunction_new > fixer;
+	dwt = dwt->accept( fixer );
+	isVoid |= fixer.pass.isVoid;
+	return dwt;
+}
+
 } // namespace SymTab
 
Index: src/SymTab/FixFunction.h
===================================================================
--- src/SymTab/FixFunction.h	(revision 9504a8969e7d1bb7042a4cf7d786d6db2fbe2d39)
+++ src/SymTab/FixFunction.h	(revision f2f22e34cda38ea572dae4fcf8ee19c16aa4160d)
@@ -19,34 +19,16 @@
 #include "SynTree/SynTree.h"    // for Types
 
+namespace ast {
+	class DeclWithType;
+}
+
 namespace SymTab {
-	/// Replaces function and array types by equivalent pointer types.
-	class FixFunction : public WithShortCircuiting {
-		typedef Mutator Parent;
-	  public:
-		FixFunction();
+	/// Replaces function and array types by equivalent pointer types. Returns true if type is 
+	/// void
+	bool fixFunction( DeclarationWithType *& );
 
-		void premutate(FunctionDecl *functionDecl);
-		DeclarationWithType* postmutate(FunctionDecl *functionDecl);
-
-		Type * postmutate(ArrayType * arrayType);
-
-		void premutate(ArrayType * arrayType);
-		void premutate(VoidType * voidType);
-		void premutate(BasicType * basicType);
-		void premutate(PointerType * pointerType);
-		void premutate(StructInstType * aggregateUseType);
-		void premutate(UnionInstType * aggregateUseType);
-		void premutate(EnumInstType * aggregateUseType);
-		void premutate(TraitInstType * aggregateUseType);
-		void premutate(TypeInstType * aggregateUseType);
-		void premutate(TupleType * tupleType);
-		void premutate(VarArgsType * varArgsType);
-		void premutate(ZeroType * zeroType);
-		void premutate(OneType * oneType);
-
-		bool isVoid;
-	};
-
-	bool fixFunction( DeclarationWithType *& );
+	/// Returns declaration with function and array types replaced by equivalent pointer types.
+	/// Sets isVoid to true if type is void
+	const ast::DeclWithType * fixFunction( const ast::DeclWithType * dwt, bool & isVoid );
 } // namespace SymTab
 
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 9504a8969e7d1bb7042a4cf7d786d6db2fbe2d39)
+++ src/SymTab/Validate.cc	(revision f2f22e34cda38ea572dae4fcf8ee19c16aa4160d)
@@ -46,4 +46,9 @@
 #include <utility>                     // for pair
 
+#include "AST/Decl.hpp"
+#include "AST/Node.hpp"
+#include "AST/Pass.hpp"
+#include "AST/SymbolTable.hpp"
+#include "AST/Type.hpp"
 #include "CodeGen/CodeGenerator.h"     // for genName
 #include "CodeGen/OperatorTable.h"     // for isCtorDtor, isCtorDtorAssign
@@ -124,5 +129,5 @@
 
 	/// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers.
-	struct EnumAndPointerDecay {
+	struct EnumAndPointerDecay_old {
 		void previsit( EnumDecl *aggregateDecl );
 		void previsit( FunctionType *func );
@@ -130,6 +135,6 @@
 
 	/// Associates forward declarations of aggregates with their definitions
-	struct LinkReferenceToTypes final : public WithIndexer, public WithGuards, public WithVisitorRef<LinkReferenceToTypes>, public WithShortCircuiting {
-		LinkReferenceToTypes( const Indexer *indexer );
+	struct LinkReferenceToTypes_old final : public WithIndexer, public WithGuards, public WithVisitorRef<LinkReferenceToTypes_old>, public WithShortCircuiting {
+		LinkReferenceToTypes_old( const Indexer *indexer );
 		void postvisit( TypeInstType *typeInst );
 
@@ -165,5 +170,5 @@
 
 	/// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID.
-	struct ForallPointerDecay final {
+	struct ForallPointerDecay_old final {
 		void previsit( ObjectDecl * object );
 		void previsit( FunctionDecl * func );
@@ -290,7 +295,7 @@
 
 	void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) {
-		PassVisitor<EnumAndPointerDecay> epc;
-		PassVisitor<LinkReferenceToTypes> lrt( nullptr );
-		PassVisitor<ForallPointerDecay> fpd;
+		PassVisitor<EnumAndPointerDecay_old> epc;
+		PassVisitor<LinkReferenceToTypes_old> lrt( nullptr );
+		PassVisitor<ForallPointerDecay_old> fpd;
 		PassVisitor<CompoundLiteral> compoundliteral;
 		PassVisitor<ValidateGenericParameters> genericParams;
@@ -305,5 +310,5 @@
 			ReplaceTypedef::replaceTypedef( translationUnit );
 			ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
-			acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes because it is an indexer and needs correct types for mangling
+			acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes_old because it is an indexer and needs correct types for mangling
 		}
 		{
@@ -314,5 +319,5 @@
 			});
 			Stats::Time::TimeBlock("Fix Qualified Types", [&]() {
-				mutateAll( translationUnit, fixQual ); // must happen after LinkReferenceToTypes, because aggregate members are accessed
+				mutateAll( translationUnit, fixQual ); // must happen after LinkReferenceToTypes_old, because aggregate members are accessed
 			});
 			Stats::Time::TimeBlock("Hoist Structs", [&]() {
@@ -326,5 +331,5 @@
 			Stats::Heap::newPass("validate-C");
 			Stats::Time::BlockGuard guard("validate-C");
-			acceptAll( translationUnit, genericParams );  // check as early as possible - can't happen before LinkReferenceToTypes
+			acceptAll( translationUnit, genericParams );  // check as early as possible - can't happen before LinkReferenceToTypes_old
 			VerifyCtorDtorAssign::verify( translationUnit );  // must happen before autogen, because autogen examines existing ctor/dtors
 			ReturnChecker::checkFunctionReturns( translationUnit );
@@ -344,5 +349,5 @@
 			});
 			Stats::Time::TimeBlock("Generate Autogen routines", [&]() {
-				autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay
+				autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay_old
 			});
 		}
@@ -385,7 +390,7 @@
 
 	void validateType( Type *type, const Indexer *indexer ) {
-		PassVisitor<EnumAndPointerDecay> epc;
-		PassVisitor<LinkReferenceToTypes> lrt( indexer );
-		PassVisitor<ForallPointerDecay> fpd;
+		PassVisitor<EnumAndPointerDecay_old> epc;
+		PassVisitor<LinkReferenceToTypes_old> lrt( indexer );
+		PassVisitor<ForallPointerDecay_old> fpd;
 		type->accept( epc );
 		type->accept( lrt );
@@ -586,5 +591,5 @@
 	}
 
-	void EnumAndPointerDecay::previsit( EnumDecl *enumDecl ) {
+	void EnumAndPointerDecay_old::previsit( EnumDecl *enumDecl ) {
 		// Set the type of each member of the enumeration to be EnumConstant
 		for ( std::list< Declaration * >::iterator i = enumDecl->members.begin(); i != enumDecl->members.end(); ++i ) {
@@ -618,5 +623,5 @@
 	}
 
-	void EnumAndPointerDecay::previsit( FunctionType *func ) {
+	void EnumAndPointerDecay_old::previsit( FunctionType *func ) {
 		// Fix up parameters and return types
 		fixFunctionList( func->parameters, func->isVarArgs, func );
@@ -624,5 +629,5 @@
 	}
 
-	LinkReferenceToTypes::LinkReferenceToTypes( const Indexer *other_indexer ) {
+	LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer *other_indexer ) {
 		if ( other_indexer ) {
 			local_indexer = other_indexer;
@@ -632,5 +637,5 @@
 	}
 
-	void LinkReferenceToTypes::postvisit( EnumInstType *enumInst ) {
+	void LinkReferenceToTypes_old::postvisit( EnumInstType *enumInst ) {
 		EnumDecl *st = local_indexer->lookupEnum( enumInst->name );
 		// it's not a semantic error if the enum is not found, just an implicit forward declaration
@@ -652,5 +657,5 @@
 	}
 
-	void LinkReferenceToTypes::postvisit( StructInstType *structInst ) {
+	void LinkReferenceToTypes_old::postvisit( StructInstType *structInst ) {
 		StructDecl *st = local_indexer->lookupStruct( structInst->name );
 		// it's not a semantic error if the struct is not found, just an implicit forward declaration
@@ -665,5 +670,5 @@
 	}
 
-	void LinkReferenceToTypes::postvisit( UnionInstType *unionInst ) {
+	void LinkReferenceToTypes_old::postvisit( UnionInstType *unionInst ) {
 		UnionDecl *un = local_indexer->lookupUnion( unionInst->name );
 		// it's not a semantic error if the union is not found, just an implicit forward declaration
@@ -678,9 +683,9 @@
 	}
 
-	void LinkReferenceToTypes::previsit( QualifiedType * ) {
+	void LinkReferenceToTypes_old::previsit( QualifiedType * ) {
 		visit_children = false;
 	}
 
-	void LinkReferenceToTypes::postvisit( QualifiedType * qualType ) {
+	void LinkReferenceToTypes_old::postvisit( QualifiedType * qualType ) {
 		// linking only makes sense for the 'oldest ancestor' of the qualified type
 		qualType->parent->accept( *visitor );
@@ -729,5 +734,5 @@
 	}
 
-	void LinkReferenceToTypes::postvisit( TraitDecl * traitDecl ) {
+	void LinkReferenceToTypes_old::postvisit( TraitDecl * traitDecl ) {
 		if ( traitDecl->name == "sized" ) {
 			// "sized" is a special trait - flick the sized status on for the type variable
@@ -751,5 +756,5 @@
 	}
 
-	void LinkReferenceToTypes::postvisit( TraitInstType * traitInst ) {
+	void LinkReferenceToTypes_old::postvisit( TraitInstType * traitInst ) {
 		// handle other traits
 		TraitDecl *traitDecl = local_indexer->lookupTrait( traitInst->name );
@@ -777,5 +782,5 @@
 	}
 
-	void LinkReferenceToTypes::postvisit( EnumDecl *enumDecl ) {
+	void LinkReferenceToTypes_old::postvisit( EnumDecl *enumDecl ) {
 		// visit enum members first so that the types of self-referencing members are updated properly
 		if ( enumDecl->body ) {
@@ -799,5 +804,5 @@
 	}
 
-	void LinkReferenceToTypes::renameGenericParams( std::list< TypeDecl * > & params ) {
+	void LinkReferenceToTypes_old::renameGenericParams( std::list< TypeDecl * > & params ) {
 		// rename generic type parameters uniquely so that they do not conflict with user-defined function forall parameters, e.g.
 		//   forall(otype T)
@@ -817,13 +822,13 @@
 	}
 
-	void LinkReferenceToTypes::previsit( StructDecl * structDecl ) {
+	void LinkReferenceToTypes_old::previsit( StructDecl * structDecl ) {
 		renameGenericParams( structDecl->parameters );
 	}
 
-	void LinkReferenceToTypes::previsit( UnionDecl * unionDecl ) {
+	void LinkReferenceToTypes_old::previsit( UnionDecl * unionDecl ) {
 		renameGenericParams( unionDecl->parameters );
 	}
 
-	void LinkReferenceToTypes::postvisit( StructDecl *structDecl ) {
+	void LinkReferenceToTypes_old::postvisit( StructDecl *structDecl ) {
 		// visit struct members first so that the types of self-referencing members are updated properly
 		// xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and their defaults)
@@ -839,5 +844,5 @@
 	}
 
-	void LinkReferenceToTypes::postvisit( UnionDecl *unionDecl ) {
+	void LinkReferenceToTypes_old::postvisit( UnionDecl *unionDecl ) {
 		if ( unionDecl->body ) {
 			ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->name );
@@ -851,5 +856,5 @@
 	}
 
-	void LinkReferenceToTypes::postvisit( TypeInstType *typeInst ) {
+	void LinkReferenceToTypes_old::postvisit( TypeInstType *typeInst ) {
 		// ensure generic parameter instances are renamed like the base type
 		if ( inGeneric && typeInst->baseType ) typeInst->name = typeInst->baseType->name;
@@ -888,5 +893,5 @@
 	}
 
-	void ForallPointerDecay::previsit( ObjectDecl *object ) {
+	void ForallPointerDecay_old::previsit( ObjectDecl *object ) {
 		// ensure that operator names only apply to functions or function pointers
 		if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) {
@@ -896,17 +901,17 @@
 	}
 
-	void ForallPointerDecay::previsit( FunctionDecl *func ) {
+	void ForallPointerDecay_old::previsit( FunctionDecl *func ) {
 		func->fixUniqueId();
 	}
 
-	void ForallPointerDecay::previsit( FunctionType * ftype ) {
+	void ForallPointerDecay_old::previsit( FunctionType * ftype ) {
 		forallFixer( ftype->forall, ftype );
 	}
 
-	void ForallPointerDecay::previsit( StructDecl * aggrDecl ) {
+	void ForallPointerDecay_old::previsit( StructDecl * aggrDecl ) {
 		forallFixer( aggrDecl->parameters, aggrDecl );
 	}
 
-	void ForallPointerDecay::previsit( UnionDecl * aggrDecl ) {
+	void ForallPointerDecay_old::previsit( UnionDecl * aggrDecl ) {
 		forallFixer( aggrDecl->parameters, aggrDecl );
 	}
@@ -1368,10 +1373,85 @@
 	}
 
-	const ast::Type * validateType( const ast::Type * type, const ast::SymbolTable & symtab ) {
-		#warning unimplemented
-		(void)type; (void)symtab;
-		assert(false);
-		return nullptr;
-	}
+namespace {
+	/// Replaces enum types by int, and function/array types in function parameter and return 
+	/// lists by appropriate pointers
+	struct EnumAndPointerDecay_new {
+		const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) {
+			// set the type of each member of the enumeration to be EnumConstant
+			for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) {
+				// build new version of object with EnumConstant
+				ast::ptr< ast::ObjectDecl > obj = 
+					enumDecl->members[i].strict_as< ast::ObjectDecl >();
+				obj.get_and_mutate()->type = 
+					new ast::EnumInstType{ enumDecl->name, ast::CV::Const };
+				
+				// set into decl
+				ast::EnumDecl * mut = mutate( enumDecl );
+				mut->members[i] = obj.get();
+				enumDecl = mut;
+			}
+			return enumDecl;
+		}
+
+		static const ast::FunctionType * fixFunctionList(
+			const ast::FunctionType * func, 
+			std::vector< ast::ptr< ast::DeclWithType > > ast::FunctionType::* field,
+			ast::ArgumentFlag isVarArgs = ast::FixedArgs
+		) {
+			const auto & dwts = func->*field;
+			unsigned nvals = dwts.size();
+			bool hasVoid = false;
+			for ( unsigned i = 0; i < nvals; ++i ) {
+				func = ast::mutate_field_index( func, field, i, fixFunction( dwts[i], hasVoid ) );
+			}
+			
+			// the only case in which "void" is valid is where it is the only one in the list
+			if ( hasVoid && ( nvals > 1 || isVarArgs ) ) {
+				SemanticError( 
+					dwts.front()->location, func, "invalid type void in function type" );
+			}
+
+			// one void is the only thing in the list, remove it
+			if ( hasVoid ) {
+				func = ast::mutate_field( 
+					func, field, std::vector< ast::ptr< ast::DeclWithType > >{} );
+			}
+
+			return func;
+		}
+
+		const ast::FunctionType * previsit( const ast::FunctionType * func ) {
+			func = fixFunctionList( func, &ast::FunctionType::params, func->isVarArgs );
+			return fixFunctionList( func, &ast::FunctionType::returns );
+		}
+	};
+
+	/// Associates forward declarations of aggregates with their definitions
+	struct LinkReferenceToTypes_new final 
+	: public ast::WithSymbolTable, public ast::WithGuards, public 
+	  ast::WithVisitorRef<LinkReferenceToTypes_new>, public ast::WithShortCircuiting {
+		
+		const ast::SymbolTable * localSyms;
+
+		LinkReferenceToTypes_new( const ast::SymbolTable & syms ) : localSyms( &syms ) {}
+
+		#warning incomplete
+	};
+
+	/// Replaces array and function types in forall lists by appropriate pointer type and assigns 
+	/// each object and function declaration a unique ID
+	struct ForallPointerDecay_new {
+		#warning incomplete
+	};
+} // anonymous namespace
+
+const ast::Type * validateType( const ast::Type * type, const ast::SymbolTable & symtab ) {
+	ast::Pass< EnumAndPointerDecay_new > epc;
+	ast::Pass< LinkReferenceToTypes_new > lrt{ symtab };
+	ast::Pass< ForallPointerDecay_new > fpd;
+
+	return type->accept( epc )->accept( lrt )->accept( fpd );
+}
+
 } // namespace SymTab
 
