Index: src/ResolvExpr/CurrentObject.cc
===================================================================
--- src/ResolvExpr/CurrentObject.cc	(revision d3b2c32a655466c4084655c0fb259f5b8b1d0eb5)
+++ src/ResolvExpr/CurrentObject.cc	(revision b7d92b9615536fccd480694cbb6833bd89ffa8f3)
@@ -579,4 +579,26 @@
 } // namespace ResolvExpr
 
+namespace ast {
+
+	/// Iterates members of a type by initializer
+	class MemberIterator {
+	public:
+		virtual ~MemberIterator() {}
+	};
+
+	/// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry
+	class SimpleIterator final : public MemberIterator {
+		const Type * type = nullptr;
+	public:
+		SimpleIterator( const Type * t ) : type( t ) {}
+	};
+
+	CurrentObject::CurrentObject( const ast::Type * type ) : objStack() {
+		objStack.emplace_back( new SimpleIterator{ type } );
+	}
+
+	#warning ast::CurrentObject port incomplete
+}
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/ResolvExpr/CurrentObject.h
===================================================================
--- src/ResolvExpr/CurrentObject.h	(revision d3b2c32a655466c4084655c0fb259f5b8b1d0eb5)
+++ src/ResolvExpr/CurrentObject.h	(revision b7d92b9615536fccd480694cbb6833bd89ffa8f3)
@@ -17,5 +17,7 @@
 
 #include <list>   // for list
+#include <memory> // for unique_ptr
 #include <stack>  // for stack
+#include <vector>
 
 class Designation;
@@ -52,4 +54,23 @@
 } // namespace ResolvExpr
 
+namespace ast {
+	// AST class types
+	class Designation;
+	class InitAlternative;
+	class Type;
+
+	// forward declaration of internal detail
+	class MemberIterator;
+
+	/// Builds initializer lists in resolution
+	class CurrentObject final {
+		std::vector< std::shared_ptr<MemberIterator> > objStack;
+	
+	public:
+		CurrentObject() = default;
+		CurrentObject( const Type * type );
+	};
+} // namespace ast
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision d3b2c32a655466c4084655c0fb259f5b8b1d0eb5)
+++ src/ResolvExpr/Resolver.cc	(revision b7d92b9615536fccd480694cbb6833bd89ffa8f3)
@@ -165,5 +165,5 @@
 		void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
 			if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
-				if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
+				if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
 					// cast is to the same type as its argument, so it's unnecessary -- remove it
 					expr = castExpr->arg;
@@ -965,8 +965,11 @@
 		}
 
+		/// always-accept candidate filter
+		bool anyCandidate( const Candidate & ) { return true; }
+
 		/// Calls the CandidateFinder and finds the single best candidate
 		CandidateRef findUnfinishedKindExpression(
 			const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind, 
-			std::function<bool(const Candidate &)> pred, ResolvMode mode = {}
+			std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {}
 		) {
 			if ( ! untyped ) return nullptr;
@@ -1056,7 +1059,6 @@
 				) {
 					// generated cast is the same type as its argument, remove it after keeping env
-					ast::ptr<ast::Expr> arg = castExpr->arg;
-					arg.get_and_mutate()->env = castExpr->env;
-					return arg;
+					return ast::mutate_field( 
+						castExpr->arg.get(), &ast::Expr::env, castExpr->env );
 				}
 				return castExpr;
@@ -1068,4 +1070,15 @@
 			}
 		};
+
+		/// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts)
+		void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) {
+			if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) {
+				if ( typesCompatible( castExpr->arg->result, castExpr->result, symtab ) ) {
+					// cast is to the same type as its argument, remove it
+					ast::ptr< ast::TypeSubstitution > env = castExpr->env;
+					expr.set_and_mutate( castExpr->arg )->env = env;
+				}
+			}
+		}
 
 		/// Establish post-resolver invariants for expressions
@@ -1082,5 +1095,37 @@
 			StripCasts_new::strip( expr );
 		}
-		
+
+		/// Find the expression candidate that is the unique best match for `untyped` in a `void`
+		/// context.
+		ast::ptr< ast::Expr > resolveInVoidContext(
+			const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env
+		) {
+			assertf( expr, "expected a non-null expression" );
+			
+			// set up and resolve expression cast to void
+			ast::CastExpr * untyped = new ast::CastExpr{ expr->location, expr };
+			CandidateRef choice = findUnfinishedKindExpression( 
+				untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
+			
+			// a cast expression has either 0 or 1 interpretations (by language rules);
+			// if 0, an exception has already been thrown, and this code will not run
+			const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >();
+			env = std::move( choice->env );
+
+			return castExpr->arg;
+		}
+
+		/// Resolve `untyped` to the expression whose candidate is the best match for a `void` 
+		/// context.
+		ast::ptr< ast::Expr > findVoidExpression( 
+			const ast::Expr * untyped, const ast::SymbolTable & symtab
+		) {
+			resetTyVarRenaming();
+			ast::TypeEnvironment env;
+			ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env );
+			finishExpr( newExpr, env, untyped->env );
+			return newExpr;
+		}
+
 		/// resolve `untyped` to the expression whose candidate satisfies `pred` with the 
 		/// lowest cost, returning the resolved version
@@ -1094,4 +1139,17 @@
 			finishExpr( choice->expr, choice->env, untyped->env );
 			return std::move( choice->expr );
+		}
+
+		/// Resolve `untyped` to the single expression whose candidate is the best match for the 
+		/// given type.
+		ast::ptr< ast::Expr > findSingleExpression(
+			const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
+		) {
+			assert( untyped && type );
+			const ast::Expr * castExpr = new ast::CastExpr{ untyped->location, untyped, type };
+			ast::ptr< ast::Expr > newExpr = 
+				findKindExpression( castExpr, symtab, "", anyCandidate );
+			removeExtraneousCast( newExpr, symtab );
+			return newExpr;
 		}
 
@@ -1125,5 +1183,5 @@
 
 		ast::ptr< ast::Type > functionReturn = nullptr;
-		// ast::CurrentObject currentObject = nullptr;
+		ast::CurrentObject currentObject = nullptr;
 		bool inEnumDecl = false;
 
@@ -1141,13 +1199,13 @@
 		void previsit( const ast::PointerType * );
 
-		void previsit( const ast::ExprStmt * );
-		void previsit( const ast::AsmExpr * );
+		const ast::ExprStmt * previsit( const ast::ExprStmt * );
+		const ast::AsmExpr * previsit( const ast::AsmExpr * );
 		void previsit( const ast::AsmStmt * );
-		void previsit( const ast::IfStmt * );
-		void previsit( const ast::WhileStmt * );
-		void previsit( const ast::ForStmt * );
-		void previsit( const ast::SwitchStmt * );
-		void previsit( const ast::CaseStmt * );
-		void previsit( const ast::BranchStmt * );
+		const ast::IfStmt * previsit( const ast::IfStmt * );
+		const ast::WhileStmt * previsit( const ast::WhileStmt * );
+		const ast::ForStmt * previsit( const ast::ForStmt * );
+		const ast::SwitchStmt * previsit( const ast::SwitchStmt * );
+		const ast::CaseStmt * previsit( const ast::CaseStmt * );
+		const ast::BranchStmt * previsit( const ast::BranchStmt * );
 		void previsit( const ast::ReturnStmt * );
 		void previsit( const ast::ThrowStmt * );
@@ -1196,7 +1254,17 @@
 
 	void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
-		#warning unimplemented; Resolver port in progress
-		(void)objectDecl;
-		assert(false);
+		// To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()], 
+		// class-variable `initContext` is changed multiple times because the LHS is analyzed 
+		// twice. The second analysis changes `initContext` because a function type can contain 
+		// object declarations in the return and parameter types. Therefore each value of 
+		// `initContext` is retained so the type on the first analysis is preserved and used for 
+		// selecting the RHS.
+		GuardValue( currentObject );
+		currentObject = ast::CurrentObject{ objectDecl->get_type() };
+		if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) {
+			// enumerator initializers should not use the enum type to initialize, since the 
+			// enum type is still incomplete at this point. Use `int` instead.
+			currentObject = ast::CurrentObject{ new ast::BasicType{ ast::BasicType::SignedInt } };
+		}
 	}
 
@@ -1210,34 +1278,44 @@
 		const ast::StaticAssertDecl * assertDecl 
 	) {
-		ast::ptr< ast::Expr > cond = findIntegralExpression( assertDecl->cond, symtab );
-		if ( cond == assertDecl->cond ) return assertDecl;
+		return ast::mutate_field( 
+			assertDecl, &ast::StaticAssertDecl::cond, 
+			findIntegralExpression( assertDecl->cond, symtab ) );
+	}
+
+	template< typename PtrType >
+	void handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {
+		#warning unimplemented; needs support for new Validate::SizeType global
+		(void)type; (void)symtab;
+		assert( false );
+	}
+
+	void Resolver_new::previsit( const ast::ArrayType * at ) {
+		handlePtrType( at, symtab );
+	}
+
+	void Resolver_new::previsit( const ast::PointerType * pt ) {
+		handlePtrType( pt, symtab );
+	}
+
+	const ast::ExprStmt * Resolver_new::previsit( const ast::ExprStmt * exprStmt ) {
+		visit_children = false;
+		assertf( exprStmt->expr, "ExprStmt has null expression in resolver" );
 		
-		ast::StaticAssertDecl * ret = mutate( assertDecl );
-		ret->cond = cond;
-		return ret;
-	}
-
-	void Resolver_new::previsit( const ast::ArrayType * at ) {
-		#warning unimplemented; Resolver port in progress
-		(void)at;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::PointerType * pt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)pt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::ExprStmt * exprStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)exprStmt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::AsmExpr * asmExpr ) {
-		#warning unimplemented; Resolver port in progress
-		(void)asmExpr;
-		assert(false);
+		return ast::mutate_field( 
+			exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab ) );
+	}
+
+	const ast::AsmExpr * Resolver_new::previsit( const ast::AsmExpr * asmExpr ) {
+		visit_children = false;
+
+		asmExpr = ast::mutate_field( 
+			asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab ) );
+		
+		if ( asmExpr->inout ) {
+			asmExpr = ast::mutate_field(
+				asmExpr, &ast::AsmExpr::inout, findVoidExpression( asmExpr->inout, symtab ) );
+		}
+		
+		return asmExpr;
 	}
 
@@ -1248,38 +1326,57 @@
 	}
 
-	void Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)ifStmt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::WhileStmt * whileStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)whileStmt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::ForStmt * forStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)forStmt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)switchStmt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::CaseStmt * caseStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)caseStmt;
-		assert(false);
-	}
-
-	void Resolver_new::previsit( const ast::BranchStmt * branchStmt ) {
-		#warning unimplemented; Resolver port in progress
-		(void)branchStmt;
-		assert(false);
+	const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
+		return ast::mutate_field(
+			ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab ) );
+	}
+
+	const ast::WhileStmt * Resolver_new::previsit( const ast::WhileStmt * whileStmt ) {
+		return ast::mutate_field( 
+			whileStmt, &ast::WhileStmt::cond, findIntegralExpression( whileStmt->cond, symtab ) );
+	}
+
+	const ast::ForStmt * Resolver_new::previsit( const ast::ForStmt * forStmt ) {
+		if ( forStmt->cond ) {
+			forStmt = ast::mutate_field(
+				forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab ) );
+		}
+
+		if ( forStmt->inc ) {
+			forStmt = ast::mutate_field(
+				forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab ) );
+		}
+
+		return forStmt;
+	}
+
+	const ast::SwitchStmt * Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) {
+		GuardValue( currentObject );
+		switchStmt = ast::mutate_field(
+			switchStmt, &ast::SwitchStmt::cond, 
+			findIntegralExpression( switchStmt->cond, symtab ) );
+		currentObject = ast::CurrentObject{ switchStmt->cond->result };
+		return switchStmt;
+	}
+
+	const ast::CaseStmt * Resolver_new::previsit( const ast::CaseStmt * caseStmt ) {
+		if ( caseStmt->cond ) {
+			#warning unimplemented, depends on currentObject implementation
+			assert(false);
+		}
+		return caseStmt;
+	}
+
+	const ast::BranchStmt * Resolver_new::previsit( const ast::BranchStmt * branchStmt ) {
+		visit_children = false;
+		// must resolve the argument of a computed goto
+		if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) {
+			// computed goto argument is void*
+			branchStmt = ast::mutate_field(
+				branchStmt, &ast::BranchStmt::computedTarget, 
+				findSingleExpression( 
+					branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} }, 
+					symtab ) );
+		}
+		return branchStmt;
 	}
 
