Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision d5556a3ceec1d963a2e9c0fccbfe2ff51b6eb263)
+++ src/SymTab/Validate.cc	(revision a64644c8182e47ed436d2d8d7dd8ea0e08ce8362)
@@ -86,4 +86,12 @@
 	};
 
+	/// Fix return types so that every function returns exactly one value
+	class ReturnTypeFixer : public Visitor {
+	  public:
+		static void fix( std::list< Declaration * > &translationUnit );
+
+		virtual void visit( FunctionType * ftype );
+	};
+
 	/// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers.
 	class EnumAndPointerDecayPass : public Visitor {
@@ -94,8 +102,8 @@
 
 	/// Associates forward declarations of aggregates with their definitions
-	class Pass2 final : public Indexer {
+	class LinkReferenceToTypes final : public Indexer {
 		typedef Indexer Parent;
 	  public:
-		Pass2( bool doDebug, const Indexer *indexer );
+		LinkReferenceToTypes( bool doDebug, const Indexer *indexer );
 	  private:
   		using Indexer::visit;
@@ -193,5 +201,5 @@
 	void validate( std::list< Declaration * > &translationUnit, bool doDebug ) {
 		EnumAndPointerDecayPass epc;
-		Pass2 pass2( doDebug, 0 );
+		LinkReferenceToTypes lrt( doDebug, 0 );
 		Pass3 pass3( 0 );
 		CompoundLiteral compoundliteral;
@@ -199,7 +207,8 @@
 		EliminateTypedef::eliminateTypedef( translationUnit );
 		HoistStruct::hoistStruct( translationUnit );
+		ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
 		autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecayPass
 		acceptAll( translationUnit, epc );
-		acceptAll( translationUnit, pass2 );
+		acceptAll( translationUnit, lrt );
 		ReturnChecker::checkFunctionReturns( translationUnit );
 		compoundliteral.mutateDeclarationList( translationUnit );
@@ -210,8 +219,8 @@
 	void validateType( Type *type, const Indexer *indexer ) {
 		EnumAndPointerDecayPass epc;
-		Pass2 pass2( false, indexer );
+		LinkReferenceToTypes lrt( false, indexer );
 		Pass3 pass3( indexer );
 		type->accept( epc );
-		type->accept( pass2 );
+		type->accept( lrt );
 		type->accept( pass3 );
 	}
@@ -324,5 +333,5 @@
 	}
 
-	Pass2::Pass2( bool doDebug, const Indexer *other_indexer ) : Indexer( doDebug ) {
+	LinkReferenceToTypes::LinkReferenceToTypes( bool doDebug, const Indexer *other_indexer ) : Indexer( doDebug ) {
 		if ( other_indexer ) {
 			indexer = other_indexer;
@@ -332,5 +341,5 @@
 	}
 
-	void Pass2::visit( StructInstType *structInst ) {
+	void LinkReferenceToTypes::visit( StructInstType *structInst ) {
 		Parent::visit( structInst );
 		StructDecl *st = indexer->lookupStruct( structInst->get_name() );
@@ -346,5 +355,5 @@
 	}
 
-	void Pass2::visit( UnionInstType *unionInst ) {
+	void LinkReferenceToTypes::visit( UnionInstType *unionInst ) {
 		Parent::visit( unionInst );
 		UnionDecl *un = indexer->lookupUnion( unionInst->get_name() );
@@ -359,5 +368,5 @@
 	}
 
-	void Pass2::visit( TraitInstType *contextInst ) {
+	void LinkReferenceToTypes::visit( TraitInstType *contextInst ) {
 		Parent::visit( contextInst );
 		if ( contextInst->get_name() == "sized" ) {
@@ -398,5 +407,5 @@
 	}
 
-	void Pass2::visit( StructDecl *structDecl ) {
+	void LinkReferenceToTypes::visit( StructDecl *structDecl ) {
 		// visit struct members first so that the types of self-referencing members are updated properly
 		Parent::visit( structDecl );
@@ -412,5 +421,5 @@
 	}
 
-	void Pass2::visit( UnionDecl *unionDecl ) {
+	void LinkReferenceToTypes::visit( UnionDecl *unionDecl ) {
 		Parent::visit( unionDecl );
 		if ( ! unionDecl->get_members().empty() ) {
@@ -425,5 +434,5 @@
 	}
 
-	void Pass2::visit( TypeInstType *typeInst ) {
+	void LinkReferenceToTypes::visit( TypeInstType *typeInst ) {
 		if ( NamedTypeDecl *namedTypeDecl = lookupType( typeInst->get_name() ) ) {
 			if ( TypeDecl *typeDecl = dynamic_cast< TypeDecl * >( namedTypeDecl ) ) {
@@ -747,4 +756,34 @@
 		return new VariableExpr( newtempvar );
 	}
+
+	void ReturnTypeFixer::fix( std::list< Declaration * > &translationUnit ) {
+		ReturnTypeFixer fixer;
+		acceptAll( translationUnit, fixer );
+	}
+
+	void ReturnTypeFixer::visit( FunctionType * ftype ) {
+		static UniqueName tempNamer( "_retval" );
+
+		// xxx - need to handle named return values - this information needs to be saved somehow
+		// so that resolution has access to the names.
+		// Note that this pass needs to happen early so that other passes which look for tuple types
+		// find them in all of the right places, including function return types.
+		std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
+		if ( retVals.size() > 1 ) {
+			// generate a single return parameter which is the tuple of all of the return values
+			TupleType * tupleType = safe_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) );
+			// ensure return value is not destructed by explicitly creating an empty ListInit node wherein maybeConstruct is false.
+			ObjectDecl * newRet = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, tupleType, new ListInit( std::list<Initializer*>(), noDesignators, false ) );
+			deleteAll( retVals );
+			retVals.clear();
+			retVals.push_back( newRet );
+		} else if ( retVals.size() == 1 ) {
+			// ensure other return values have a name
+			DeclarationWithType * ret = retVals.front();
+			if ( ret->get_name() == "" ) {
+				ret->set_name( tempNamer.newName() );
+			}
+		}
+	}
 } // namespace SymTab
 
