Index: src/ResolvExpr/Alternative.cc
===================================================================
--- src/ResolvExpr/Alternative.cc	(revision b6fe7e6c491f467e31d7ef488c6c0c23df6534a8)
+++ src/ResolvExpr/Alternative.cc	(revision 906e24deeab82aafdd4cbb08fb896c8ffe5b99e0)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// Alternative.cc -- 
+// Alternative.cc --
 //
 // Author           : Richard C. Bilson
@@ -12,5 +12,5 @@
 // Last Modified On : Sat May 16 23:54:23 2015
 // Update Count     : 2
-// 
+//
 
 #include "Alternative.h"
@@ -54,6 +54,7 @@
 			expr->print( os, indent );
 			os << "(types:" << std::endl;
-			printAll( expr->get_results(), os, indent + 4 );
-			os << ")" << std::endl;
+			os << std::string( indent+4, ' ' );
+			expr->get_result()->print( os, indent + 4 );
+			os << std::endl << ")" << std::endl;
 		} else {
 			os << "Null expression!" << std::endl;
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision b6fe7e6c491f467e31d7ef488c6c0c23df6534a8)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 906e24deeab82aafdd4cbb08fb896c8ffe5b99e0)
@@ -101,8 +101,8 @@
 				PruneStruct current( candidate );
 				std::string mangleName;
-				for ( std::list< Type* >::const_iterator retType = candidate->expr->get_results().begin(); retType != candidate->expr->get_results().end(); ++retType ) {
-					Type *newType = (*retType)->clone();
+				{
+					Type * newType = candidate->expr->get_result()->clone();
 					candidate->env.apply( newType );
-					mangleName += SymTab::Mangler::mangle( newType );
+					mangleName = SymTab::Mangler::mangle( newType );
 					delete newType;
 				}
@@ -133,11 +133,8 @@
 				if ( ! target->second.isAmbiguous ) {
 					Alternative &alt = *target->second.candidate;
-					for ( std::list< Type* >::iterator result = alt.expr->get_results().begin(); result != alt.expr->get_results().end(); ++result ) {
-						alt.env.applyFree( *result );
-					}
+					alt.env.applyFree( alt.expr->get_result() );
 					*out++ = alt;
 				}
 			}
-
 		}
 
@@ -170,7 +167,5 @@
 
 		void renameTypes( Expression *expr ) {
-			for ( std::list< Type* >::iterator i = expr->get_results().begin(); i != expr->get_results().end(); ++i ) {
-				(*i)->accept( global_renamer );
-			}
+			expr->get_result()->accept( global_renamer );
 		}
 	}
@@ -204,5 +199,5 @@
 		for ( AltList::iterator i = alternatives.begin(); i != alternatives.end(); ++i ) {
 			if ( adjust ) {
-				adjustExprTypeList( i->expr->get_results().begin(), i->expr->get_results().end(), i->env, indexer );
+				adjustExprType( i->expr->get_result(), i->env, indexer );
 			}
 		}
@@ -259,10 +254,7 @@
 
 	Cost computeConversionCost( Alternative &alt, const SymTab::Indexer &indexer ) {
-		ApplicationExpr *appExpr = dynamic_cast< ApplicationExpr* >( alt.expr );
-		assert( appExpr );
-		PointerType *pointer = dynamic_cast< PointerType* >( appExpr->get_function()->get_results().front() );
-		assert( pointer );
-		FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
-		assert( function );
+		ApplicationExpr *appExpr = safe_dynamic_cast< ApplicationExpr* >( alt.expr );
+		PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
+		FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
 
 		Cost convCost( 0, 0, 0 );
@@ -275,9 +267,12 @@
 				(*actualExpr)->print( std::cerr, 8 );
 				std::cerr << "--- results are" << std::endl;
-				printAll( (*actualExpr)->get_results(), std::cerr, 8 );
+				(*actualExpr)->get_result()->print( std::cerr, 8 );
 			)
 			std::list< DeclarationWithType* >::iterator startFormal = formal;
 			Cost actualCost;
-			for ( std::list< Type* >::iterator actual = (*actualExpr)->get_results().begin(); actual != (*actualExpr)->get_results().end(); ++actual ) {
+			// xxx - tuple type matching
+			std::list< Type * > flatActualTypes;
+			flatten( (*actualExpr)->get_result(), back_inserter( flatActualTypes ) );
+			for ( std::list< Type* >::iterator actual = flatActualTypes.begin(); actual != flatActualTypes.end(); ++actual ) {
 				if ( formal == formals.end() ) {
 					if ( function->get_isVarArgs() ) {
@@ -383,5 +378,7 @@
 		std::list< DeclarationWithType* >::iterator formal = formals.begin();
 		for ( AltList::const_iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
-			for ( std::list< Type* >::iterator actual = actualExpr->expr->get_results().begin(); actual != actualExpr->expr->get_results().end(); ++actual ) {
+			std::list< Type * > flatActualTypes;
+			flatten( actualExpr->expr->get_result(), back_inserter( flatActualTypes ) );
+			for ( std::list< Type* >::iterator actual = flatActualTypes.begin(); actual != flatActualTypes.end(); ++actual ) {
 				if ( formal == formals.end() ) {
 					return isVarArgs;
@@ -500,7 +497,6 @@
 				//if ( newNeedParents[ curDecl->get_uniqueId() ][ candDecl->get_uniqueId() ]++ > recursionParentLimit ) continue;
 				Expression *varExpr = new VariableExpr( candDecl );
-				deleteAll( varExpr->get_results() );
-				varExpr->get_results().clear();
-				varExpr->get_results().push_front( adjType->clone() );
+				delete varExpr->get_result();
+				varExpr->set_result( adjType->clone() );
 				PRINT(
 					std::cerr << "satisfying assertion " << curDecl->get_uniqueId() << " ";
@@ -574,5 +570,5 @@
 				PointerType pt( Type::Qualifiers(), v.clone() );
 				UntypedExpr *vexpr = untypedExpr->clone();
-				vexpr->get_results().push_front( pt.clone() );
+				vexpr->set_result( pt.clone() );
 				alternatives.push_back( Alternative( vexpr, env, Cost()) );
 				return;
@@ -604,5 +600,5 @@
 				// check if the type is pointer to function
 				PointerType *pointer;
-				if ( func->expr->get_results().size() == 1 && ( pointer = dynamic_cast< PointerType* >( func->expr->get_results().front() ) ) ) {
+				if ( ( pointer = dynamic_cast< PointerType* >( func->expr->get_result() ) ) ) {
 					if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
 						for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
@@ -640,6 +636,5 @@
 						// check if the type is pointer to function
 						PointerType *pointer;
-						if ( funcOp->expr->get_results().size() == 1
-							&& ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_results().front() ) ) ) {
+						if ( ( pointer = dynamic_cast< PointerType* >( funcOp->expr->get_result() ) ) ) {
 							if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
 								for ( std::list< AltList >::iterator actualAlt = possibilities.begin(); actualAlt != possibilities.end(); ++actualAlt ) {
@@ -665,10 +660,7 @@
 
 			PRINT(
-				ApplicationExpr *appExpr = dynamic_cast< ApplicationExpr* >( withFunc->expr );
-				assert( appExpr );
-				PointerType *pointer = dynamic_cast< PointerType* >( appExpr->get_function()->get_results().front() );
-				assert( pointer );
-				FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() );
-				assert( function );
+				ApplicationExpr *appExpr = safe_dynamic_cast< ApplicationExpr* >( withFunc->expr );
+				PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
+				FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
 				std::cerr << "Case +++++++++++++" << std::endl;
 				std::cerr << "formals are:" << std::endl;
@@ -692,8 +684,6 @@
 
 	bool isLvalue( Expression *expr ) {
-		for ( std::list< Type* >::const_iterator i = expr->get_results().begin(); i != expr->get_results().end(); ++i ) {
-			if ( !(*i)->get_isLvalue() ) return false;
-		} // for
-		return true;
+		// xxx - recurse into tuples?
+		return expr->has_result() && expr->get_result()->get_isLvalue();
 	}
 
@@ -709,9 +699,8 @@
 
 	void AlternativeFinder::visit( CastExpr *castExpr ) {
-		for ( std::list< Type* >::iterator i = castExpr->get_results().begin(); i != castExpr->get_results().end(); ++i ) {
-			*i = resolveTypeof( *i, indexer );
-			SymTab::validateType( *i, &indexer );
-			adjustExprType( *i, env, indexer );
-		} // for
+		Type *& toType = castExpr->get_result();
+		toType = resolveTypeof( toType, indexer );
+		SymTab::validateType( toType, &indexer );
+		adjustExprType( toType, env, indexer );
 
 		AlternativeFinder finder( indexer, env );
@@ -727,15 +716,10 @@
 			// that are cast directly.  The candidate is invalid if it has fewer results than there are types to cast
 			// to.
-			int discardedValues = (*i).expr->get_results().size() - castExpr->get_results().size();
+			int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();
 			if ( discardedValues < 0 ) continue;
-			std::list< Type* >::iterator candidate_end = (*i).expr->get_results().begin();
-			std::advance( candidate_end, castExpr->get_results().size() );
+			// xxx - may need to go into tuple types and extract relavent types and use unifyList
 			// unification run for side-effects
-			unifyList( castExpr->get_results().begin(), castExpr->get_results().end(),
-					   (*i).expr->get_results().begin(), candidate_end,
-			           i->env, needAssertions, haveAssertions, openVars, indexer );
-			Cost thisCost = castCostList( (*i).expr->get_results().begin(), candidate_end,
-										  castExpr->get_results().begin(), castExpr->get_results().end(),
-										  indexer, i->env );
+			unify( castExpr->get_result(), (*i).expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );
+			Cost thisCost = castCost( (*i).expr->get_result(), castExpr->get_result(), indexer, i->env );
 			if ( thisCost != Cost::infinity ) {
 				// count one safe conversion for each value that is thrown away
@@ -760,10 +744,8 @@
 
 		for ( AltList::const_iterator agg = funcFinder.alternatives.begin(); agg != funcFinder.alternatives.end(); ++agg ) {
-			if ( agg->expr->get_results().size() == 1 ) {
-				if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_results().front() ) ) {
-					addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
-				} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_results().front() ) ) {
-					addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
-				} // if
+			if ( StructInstType *structInst = dynamic_cast< StructInstType* >( agg->expr->get_result() ) ) {
+				addAggMembers( structInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
+			} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( agg->expr->get_result() ) ) {
+				addAggMembers( unionInst, agg->expr, agg->cost, agg->env, memberExpr->get_member() );
 			} // if
 		} // for
@@ -894,5 +876,5 @@
 			alternatives.push_back( Alternative( new AttrExpr( new VariableExpr( funcDecl ), argType->clone() ), env, Cost::zero ) );
 			for ( std::list< DeclarationWithType* >::iterator i = function->get_returnVals().begin(); i != function->get_returnVals().end(); ++i ) {
-				alternatives.back().expr->get_results().push_back( (*i)->get_type()->clone() );
+				alternatives.back().expr->set_result( (*i)->get_type()->clone() );
 			} // for
 		} // if
@@ -917,6 +899,6 @@
 							finder.find( attrExpr->get_expr() );
 							for ( AltList::iterator choice = finder.alternatives.begin(); choice != finder.alternatives.end(); ++choice ) {
-								if ( choice->expr->get_results().size() == 1 ) {
-									resolveAttr(*i, function, choice->expr->get_results().front(), choice->env );
+								if ( choice->expr->get_result()->size() == 1 ) {
+									resolveAttr(*i, function, choice->expr->get_result(), choice->env );
 								} // fi
 							} // for
@@ -960,16 +942,8 @@
 					AssertionSet needAssertions, haveAssertions;
 					Alternative newAlt( 0, third->env, first->cost + second->cost + third->cost );
-					std::list< Type* > commonTypes;
-					if ( unifyList( second->expr->get_results().begin(), second->expr->get_results().end(), third->expr->get_results().begin(), third->expr->get_results().end(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonTypes ) ) {
+					Type* commonType;
+					if ( unify( second->expr->get_result(), third->expr->get_result(), newAlt.env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
 						ConditionalExpr *newExpr = new ConditionalExpr( first->expr->clone(), second->expr->clone(), third->expr->clone() );
-						std::list< Type* >::const_iterator original = second->expr->get_results().begin();
-						std::list< Type* >::const_iterator commonType = commonTypes.begin();
-						for ( ; original != second->expr->get_results().end() && commonType != commonTypes.end(); ++original, ++commonType ) {
-							if ( *commonType ) {
-								newExpr->get_results().push_back( *commonType );
-							} else {
-								newExpr->get_results().push_back( (*original)->clone() );
-							} // if
-						} // for
+						newExpr->set_result( commonType ? commonType : second->expr->get_result()->clone() );
 						newAlt.expr = newExpr;
 						inferParameters( needAssertions, haveAssertions, newAlt, openVars, back_inserter( alternatives ) );
@@ -999,8 +973,6 @@
 			TupleExpr *newExpr = new TupleExpr;
 			makeExprList( *i, newExpr->get_exprs() );
-			for ( std::list< Expression* >::const_iterator resultExpr = newExpr->get_exprs().begin(); resultExpr != newExpr->get_exprs().end(); ++resultExpr ) {
-				for ( std::list< Type* >::const_iterator resultType = (*resultExpr)->get_results().begin(); resultType != (*resultExpr)->get_results().end(); ++resultType ) {
-					newExpr->get_results().push_back( (*resultType)->clone() );
-				} // for
+			for ( Expression * resultExpr : newExpr->get_exprs() ) {
+				newExpr->set_result( resultExpr->get_result()->clone() );
 			} // for
 
Index: src/ResolvExpr/AlternativePrinter.cc
===================================================================
--- src/ResolvExpr/AlternativePrinter.cc	(revision b6fe7e6c491f467e31d7ef488c6c0c23df6534a8)
+++ src/ResolvExpr/AlternativePrinter.cc	(revision 906e24deeab82aafdd4cbb08fb896c8ffe5b99e0)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// AlternativePrinter.cc -- 
+// AlternativePrinter.cc --
 //
 // Author           : Richard C. Bilson
@@ -33,5 +33,5 @@
 		for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
 			os << "Alternative " << count++ << " ==============" << std::endl;
-			printAll( i->expr->get_results(), os );
+			i->expr->get_result()->print( os );
 			//    i->print( os );
 			os << std::endl;
Index: src/ResolvExpr/ResolveTypeof.cc
===================================================================
--- src/ResolvExpr/ResolveTypeof.cc	(revision b6fe7e6c491f467e31d7ef488c6c0c23df6534a8)
+++ src/ResolvExpr/ResolveTypeof.cc	(revision 906e24deeab82aafdd4cbb08fb896c8ffe5b99e0)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// ResolveTypeof.cc -- 
+// ResolveTypeof.cc --
 //
 // Author           : Richard C. Bilson
@@ -58,13 +58,6 @@
 		if ( typeofType->get_expr() ) {
 			Expression *newExpr = resolveInVoidContext( typeofType->get_expr(), indexer );
-			assert( newExpr->get_results().size() > 0 );
-			Type *newType;
-			if ( newExpr->get_results().size() > 1 ) {
-				TupleType *tupleType = new TupleType( Type::Qualifiers() );
-				cloneAll( newExpr->get_results(), tupleType->get_types() );
-				newType = tupleType;
-			} else {
-				newType = newExpr->get_results().front()->clone();
-			} // if
+			assert( newExpr->has_result() && ! newExpr->get_result()->isVoid() );
+			Type *newType = newExpr->get_result();
 			delete typeofType;
 			return newType;
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision b6fe7e6c491f467e31d7ef488c6c0c23df6534a8)
+++ src/ResolvExpr/Resolver.cc	(revision 906e24deeab82aafdd4cbb08fb896c8ffe5b99e0)
@@ -19,4 +19,5 @@
 #include "RenameVars.h"
 #include "ResolveTypeof.h"
+#include "typeops.h"
 #include "SynTree/Statement.h"
 #include "SynTree/Type.h"
@@ -67,5 +68,5 @@
 	  void resolveSingleAggrInit( Declaration *, InitIterator &, InitIterator & );
 	  void fallbackInit( ConstructorInit * ctorInit );
-		std::list< Type * > functionReturn;
+		Type * functionReturn;
 		Type *initContext;
 		Type *switchType;
@@ -155,5 +156,5 @@
 			const TypeEnvironment *newEnv = 0;
 			for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) {
-				if ( i->expr->get_results().size() == 1 && isIntegralType( i->expr->get_results().front() ) ) {
+				if ( i->expr->get_result()->size() == 1 && isIntegralType( i->expr->get_result() ) ) {
 					if ( newExpr ) {
 						throw SemanticError( "Too many interpretations for case control expression", untyped );
@@ -232,11 +233,7 @@
 		Type *new_type = resolveTypeof( functionDecl->get_type(), *this );
 		functionDecl->set_type( new_type );
-		std::list< Type * > oldFunctionReturn = functionReturn;
-		functionReturn.clear();
-		for ( std::list< DeclarationWithType * >::const_iterator i = functionDecl->get_functionType()->get_returnVals().begin(); i != functionDecl->get_functionType()->get_returnVals().end(); ++i ) {
-			functionReturn.push_back( (*i)->get_type() );
-		} // for
+		ValueGuard< Type * > oldFunctionReturn( functionReturn );
+		functionReturn = ResolvExpr::extractResultType( functionDecl->get_functionType() );
 		SymTab::Indexer::visit( functionDecl );
-		functionReturn = oldFunctionReturn;
 	}
 
@@ -336,6 +333,5 @@
 	void Resolver::visit( ReturnStmt *returnStmt ) {
 		if ( returnStmt->get_expr() ) {
-			CastExpr *castExpr = new CastExpr( returnStmt->get_expr() );
-			cloneAll( functionReturn, castExpr->get_results() );
+			CastExpr *castExpr = new CastExpr( returnStmt->get_expr(), functionReturn->clone() );
 			Expression *newExpr = findSingleExpression( castExpr, *this );
 			delete castExpr;
@@ -382,5 +378,5 @@
 				if ( isCharType( at->get_base() ) ) {
 					// check if the resolved type is char *
-					if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_results().front() ) ) {
+					if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) {
 						if ( isCharType( pt->get_base() ) ) {
 							// strip cast if we're initializing a char[] with a char *, e.g.  char x[] = "hello";
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision b6fe7e6c491f467e31d7ef488c6c0c23df6534a8)
+++ src/ResolvExpr/Unify.cc	(revision 906e24deeab82aafdd4cbb08fb896c8ffe5b99e0)
@@ -588,4 +588,19 @@
 	}
 
+	// xxx - compute once and store in the FunctionType?
+	Type * extractResultType( FunctionType * function ) {
+		if ( function->get_returnVals().size() == 0 ) {
+			return new VoidType( Type::Qualifiers() );
+		} else if ( function->get_returnVals().size() == 1 ) {
+			return function->get_returnVals().front()->get_type()->clone();
+		} else {
+			TupleType * tupleType = new TupleType( Type::Qualifiers() );
+			for ( DeclarationWithType * decl : function->get_returnVals() ) {
+				tupleType->get_types().push_back( decl->get_type()->clone() );
+			} // for
+			return tupleType;
+		}
+	}
+
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/typeops.h
===================================================================
--- src/ResolvExpr/typeops.h	(revision b6fe7e6c491f467e31d7ef488c6c0c23df6534a8)
+++ src/ResolvExpr/typeops.h	(revision 906e24deeab82aafdd4cbb08fb896c8ffe5b99e0)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// typeops.h -- 
+// typeops.h --
 //
 // Author           : Richard C. Bilson
@@ -30,10 +30,10 @@
 		typedef typename InputIterator::value_type SetType;
 		typedef typename std::list< typename SetType::value_type > ListType;
-  
+
 		if ( begin == end )	{
 			*out++ = ListType();
 			return;
 		} // if
-  
+
 		InputIterator current = begin;
 		begin++;
@@ -41,5 +41,5 @@
 		std::list< ListType > recursiveResult;
 		combos( begin, end, back_inserter( recursiveResult ) );
-  
+
 		for ( typename std::list< ListType >::const_iterator i = recursiveResult.begin(); i != recursiveResult.end(); ++i ) {
 			for ( typename ListType::const_iterator j = current->begin(); j != current->end(); ++j ) {
@@ -52,5 +52,5 @@
 		} // for
 	}
-  
+
 	// in AdjustExprType.cc
 	/// Replaces array types with the equivalent pointer, and function types with a pointer-to-function
@@ -144,4 +144,7 @@
 	}
 
+	/// creates the type represented by the list of returnVals in a FunctionType. The caller owns the return value.
+	Type * extractResultType( FunctionType * functionType );
+
 	// in CommonType.cc
 	Type *commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
@@ -152,4 +155,16 @@
 	// in Occurs.cc
 	bool occurs( Type *type, std::string varName, const TypeEnvironment &env );
+
+	// flatten tuple type into list of types
+	template< typename OutputIterator >
+	void flatten( Type * type, OutputIterator out ) {
+		if ( TupleType * tupleType = dynamic_cast< TupleType * >( type ) ) {
+			for ( Type * t : tupleType->get_types() ) {
+				flatten( t, out );
+			}
+		} else {
+			*out++ = type;
+		}
+	}
 } // namespace ResolvExpr
 
