Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision 5aa46564b0d1f7306f95e372cde97db89d81bfa1)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision 17a0ede27bb20911a3aba83aed2737c64852721d)
@@ -559,5 +559,5 @@
 	/// Generate a cast expression from `arg` to `toType`
 	const ast::Expr * restructureCast( 
-		ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated 
+		ast::ptr< ast::Expr > & arg, const ast::Type * toType, ast::GeneratedFlag isGenerated = ast::GeneratedCast
 	) {
 		if ( 
@@ -1404,13 +1404,61 @@
 
 		void postvisit( const ast::StmtExpr * stmtExpr ) {
-			#warning unimplemented
-			(void)stmtExpr;
-			assert(false);
+			addCandidate( resolveStmtExpr( stmtExpr, symtab ), tenv );
 		}
 
 		void postvisit( const ast::UntypedInitExpr * initExpr ) {
-			#warning unimplemented
-			(void)initExpr;
-			assert(false);
+			// handle each option like a cast
+			CandidateList matches;
+			PRINT(
+				std::cerr << "untyped init expr: " << initExpr << std::endl;
+			)
+			// O(n^2) checks of d-types with e-types
+			for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) {
+				// calculate target type
+				const ast::Type * toType = resolveTypeof( initAlt.type, symtab );
+				toType = SymTab::validateType( toType, symtab );
+				toType = adjustExprType( toType, tenv, symtab );
+				// The call to find must occur inside this loop, otherwise polymorphic return 
+				// types are not bound to the initialization type, since return type variables are 
+				// only open for the duration of resolving the UntypedExpr. 
+				CandidateFinder finder{ symtab, tenv, toType };
+				finder.find( initExpr->expr, ResolvMode::withAdjustment() );
+				for ( CandidateRef & cand : finder.candidates ) {
+					ast::TypeEnvironment env{ cand->env };
+					ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have;
+					ast::OpenVarSet open{ cand->open };
+
+					PRINT(
+						std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
+					)
+
+					// It is possible that a cast can throw away some values in a multiply-valued 
+					// expression, e.g. cast-to-void, one value to zero. Figure out the prefix of 
+					// the subexpression results that are cast directly. The candidate is invalid 
+					// if it has fewer results than there are types to cast to.
+					int discardedValues = cand->expr->result->size() - toType->size();
+					if ( discardedValues < 0 ) continue;
+
+					// unification run for side-effects
+					unify( toType, cand->expr->result, env, need, have, open, symtab );
+					Cost thisCost = castCost( cand->expr->result, toType, symtab, env );
+					
+					if ( thisCost != Cost::infinity ) {
+						// count one safe conversion for each value that is thrown away
+						thisCost.incSafe( discardedValues );
+						CandidateRef newCand = std::make_shared<Candidate>( 
+							new ast::InitExpr{ 
+								initExpr->location, restructureCast( cand->expr, toType ), 
+								initAlt.designation }, 
+							copy( cand->env ), move( open ), move( need ), cand->cost, thisCost );
+						inferParameters( newCand, matches );
+					}
+				}
+			}
+
+			// select first on argument cost, then conversion cost
+			CandidateList minArgCost = findMinCost( matches );
+			promoteCvtCost( minArgCost );
+			candidates = findMinCost( minArgCost );
 		}
 
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 5aa46564b0d1f7306f95e372cde97db89d81bfa1)
+++ src/ResolvExpr/Resolver.cc	(revision 17a0ede27bb20911a3aba83aed2737c64852721d)
@@ -1249,6 +1249,17 @@
 
 	void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {
-		ast::Pass<Resolver_new> resolver;
+		ast::Pass< Resolver_new > resolver;
 		accept_all( translationUnit, resolver );
+	}
+
+	ast::ptr< ast::Expr > resolveStmtExpr( 
+		const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab 
+	) {
+		assert( stmtExpr );
+		ast::Pass< Resolver_new > resolver{ symtab };
+		ast::ptr< ast::Expr > ret = stmtExpr;
+		ret = ret->accept( resolver );
+		strict_dynamic_cast< ast::StmtExpr * >( ret.get_and_mutate() )->computeResult();
+		return ret;
 	}
 
Index: src/ResolvExpr/Resolver.h
===================================================================
--- src/ResolvExpr/Resolver.h	(revision 5aa46564b0d1f7306f95e372cde97db89d81bfa1)
+++ src/ResolvExpr/Resolver.h	(revision 17a0ede27bb20911a3aba83aed2737c64852721d)
@@ -31,4 +31,5 @@
 	class Decl;
 	class DeletedExpr;
+	class StmtExpr;
 	class SymbolTable;
 	class TypeEnvironment;
@@ -58,4 +59,7 @@
 	ast::ptr< ast::Expr > resolveInVoidContext(
 		const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env );
+	/// Resolves a statement expression
+	ast::ptr< ast::Expr > resolveStmtExpr( 
+		const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab );
 } // namespace ResolvExpr
 
