Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision 31f379c6412cdf1bd9e7efed78d6788bbf58ed10)
+++ src/InitTweak/GenInit.cc	(revision a64644c8182e47ed436d2d8d7dd8ea0e08ce8362)
@@ -46,5 +46,6 @@
 		ReturnFixer();
 
-		using GenPoly::PolyMutator::mutate;
+		typedef GenPoly::PolyMutator Parent;
+		using Parent::mutate;
 		virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override;
 		virtual Statement * mutate( ReturnStmt * returnStmt ) override;
@@ -142,17 +143,15 @@
 		// hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
 		// is being returned
+		// Note: under the assumption that assignments return *this, checking for ?=? here is an optimization, since it shouldn't be necessary to copy construct `this`. This is a temporary optimization until reference types are added, at which point this should be removed, along with the analogous optimization in copy constructor generation.
 		if ( returnStmt->get_expr() && returnVals.size() == 1 && funcName != "?=?" && ! returnVals.front()->get_type()->get_isLvalue() ) {
-			// ensure return value is not destructed by explicitly creating
-			// an empty SingleInit node wherein maybeConstruct is false
-			ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, returnVals.front()->get_type()->clone(), new ListInit( std::list<Initializer*>(), noDesignators, false ) );
-			stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
-
-			// and explicitly create the constructor expression separately
+			// explicitly construct the return value using the return expression and the retVal object
+			assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() );
 			UntypedExpr *construct = new UntypedExpr( new NameExpr( "?{}" ) );
-			construct->get_args().push_back( new AddressExpr( new VariableExpr( newObj ) ) );
+			construct->get_args().push_back( new AddressExpr( new VariableExpr( returnVals.front() ) ) );
 			construct->get_args().push_back( returnStmt->get_expr() );
 			stmtsToAdd.push_back(new ExprStmt(noLabels, construct));
 
-			returnStmt->set_expr( new VariableExpr( newObj ) );
+			// return the retVal object
+			returnStmt->set_expr( new VariableExpr( returnVals.front() ) );
 		} // if
 		return returnStmt;
@@ -160,27 +159,10 @@
 
 	DeclarationWithType* ReturnFixer::mutate( FunctionDecl *functionDecl ) {
-		// xxx - need to handle named return values - this pass may need to happen
-		// after resolution? the ordering is tricky because return statements must be
-		// constructed - the simplest way to do that (while also handling multiple
-		// returns) is to structure the returnVals into a tuple, as done here.
-		// however, if the tuple return value is structured before resolution,
-		// it's difficult to resolve named return values, since the name is lost
-		// in conversion to a tuple. this might be easiest to deal with
-		// after reference types are added, as it may then be possible to
-		// uniformly move named return values to the parameter list directly
 		ValueGuard< FunctionType * > oldFtype( ftype );
 		ValueGuard< std::string > oldFuncName( funcName );
 
 		ftype = functionDecl->get_functionType();
-		std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
-		if ( retVals.size() > 1 ) {
-			TupleType * tupleType = safe_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) );
-			ObjectDecl * newRet = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) );
-			retVals.clear();
-			retVals.push_back( newRet );
-		}
 		funcName = functionDecl->get_name();
-		DeclarationWithType * decl = Mutator::mutate( functionDecl );
-		return decl;
+		return Parent::mutate( functionDecl );
 	}
 
