Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 97397a26b44bae1c0120193fd3d160297ec1db7a)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision b21c77a0e211d9361763565a2eb5ef4330f2957b)
@@ -100,4 +100,5 @@
 		void postvisit( InitExpr * initExpr );
 		void postvisit( DeletedExpr * delExpr );
+		void postvisit( GenericExpr * genExpr );
 
 		/// Adds alternatives for anonymous members
@@ -177,8 +178,18 @@
 						selected[ mangleName ] = current;
 					} else if ( candidate->cost == mapPlace->second.candidate->cost ) {
-						PRINT(
-							std::cerr << "marking ambiguous" << std::endl;
-						)
-						mapPlace->second.isAmbiguous = true;
+						// if one of the candidates contains a deleted identifier, can pick the other, since
+						// deleted expressions should not be ambiguous if there is another option that is at least as good
+						if ( findDeletedExpr( candidate->expr ) ) {
+							// do nothing
+							PRINT( std::cerr << "candidate is deleted" << std::endl; )
+						} else if ( findDeletedExpr( mapPlace->second.candidate->expr ) ) {
+							PRINT( std::cerr << "current is deleted" << std::endl; )
+							selected[ mangleName ] = current;
+						} else {
+							PRINT(
+								std::cerr << "marking ambiguous" << std::endl;
+							)
+							mapPlace->second.isAmbiguous = true;
+						}
 					} else {
 						PRINT(
@@ -300,6 +311,6 @@
 		// it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
 		Expression* aggrExpr = alt.expr->clone();
-		alt.env.apply( aggrExpr->get_result() );
-		Type * aggrType = aggrExpr->get_result();
+		alt.env.apply( aggrExpr->result );
+		Type * aggrType = aggrExpr->result;
 		if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
 			aggrType = aggrType->stripReferences();
@@ -307,7 +318,7 @@
 		}
 
-		if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
+		if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
 			addAggMembers( structInst, aggrExpr, alt.cost+Cost::safe, alt.env, "" );
-		} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
+		} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
 			addAggMembers( unionInst, aggrExpr, alt.cost+Cost::safe, alt.env, "" );
 		} // if
@@ -319,9 +330,12 @@
 		aggInst->lookup( name, members );
 
-		for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
-			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
-				alternatives.push_back( Alternative( new MemberExpr( dwt, expr->clone() ), env, newCost ) );
-				renameTypes( alternatives.back().expr );
-				addAnonConversions( alternatives.back() ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
+		for ( Declaration * decl : members ) {
+			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
+				// addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
+				// can't construct in place and use vector::back
+				Alternative newAlt( new MemberExpr( dwt, expr->clone() ), env, newCost );
+				renameTypes( newAlt.expr );
+				addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a member expression.
+				alternatives.push_back( std::move(newAlt) );
 			} else {
 				assert( false );
@@ -333,22 +347,9 @@
 		if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
 			// get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
-			// xxx - this should be improved by memoizing the value of constant exprs
-			// during parsing and reusing that information here.
-			std::stringstream ss( constantExpr->get_constant()->get_value() );
-			int val = 0;
+			auto val = constantExpr->intValue();
 			std::string tmp;
-			if ( ss >> val && ! (ss >> tmp) ) {
-				if ( val >= 0 && (unsigned int)val < tupleType->size() ) {
-					alternatives.push_back( Alternative( new TupleIndexExpr( expr, val ), env, newCost ) );
-				} // if
+			if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
+				alternatives.push_back( Alternative( new TupleIndexExpr( expr->clone(), val ), env, newCost ) );
 			} // if
-		} else if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {
-			// xxx - temporary hack until 0/1 are int constants
-			if ( nameExpr->get_name() == "0" || nameExpr->get_name() == "1" ) {
-				std::stringstream ss( nameExpr->get_name() );
-				int val;
-				ss >> val;
-				alternatives.push_back( Alternative( new TupleIndexExpr( expr, val ), env, newCost ) );
-			}
 		} // if
 	}
@@ -437,4 +438,11 @@
 					return Cost::infinity;
 				}
+			}
+			if ( DefaultArgExpr * def = dynamic_cast< DefaultArgExpr * >( *actualExpr ) ) {
+				// default arguments should be free - don't include conversion cost.
+				// Unwrap them here because they are not relevant to the rest of the system.
+				*actualExpr = def->expr;
+				++formal;
+				continue;
 			}
 			Type * formalType = (*formal)->get_type();
@@ -764,6 +772,8 @@
 	ConstantExpr* getDefaultValue( Initializer* init ) {
 		if ( SingleInit* si = dynamic_cast<SingleInit*>( init ) ) {
-			if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->get_value() ) ) {
-				return dynamic_cast<ConstantExpr*>( ce->get_arg() );
+			if ( CastExpr* ce = dynamic_cast<CastExpr*>( si->value ) ) {
+				return dynamic_cast<ConstantExpr*>( ce->arg );
+			} else {
+				return dynamic_cast<ConstantExpr*>( si->value );
 			}
 		}
@@ -1026,5 +1036,5 @@
 								indexer ) ) {
 							results.emplace_back(
-								i, cnstExpr, move(env), move(need), move(have),
+								i, new DefaultArgExpr( cnstExpr ), move(env), move(need), move(have),
 								move(openVars), nextArg, nTuples );
 						}
@@ -1359,4 +1369,5 @@
 		funcFinder.findWithAdjustment( untypedExpr->function );
 		// if there are no function alternatives, then proceeding is a waste of time.
+		// xxx - findWithAdjustment throws, so this check and others like it shouldn't be necessary.
 		if ( funcFinder.alternatives.empty() ) return;
 
@@ -1386,5 +1397,5 @@
 			argExpansions.emplace_back();
 			auto& argE = argExpansions.back();
-			argE.reserve( arg.alternatives.size() );
+			// argE.reserve( arg.alternatives.size() );
 
 			for ( const Alternative& actual : arg ) {
@@ -1409,6 +1420,6 @@
 							std::back_inserter( candidates ) );
 					}
-				} else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
-					if ( ClassRef eqvClass = func->env.lookup( typeInst->get_name() ) ) {
+				} else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->result->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
+					if ( ClassRef eqvClass = func->env.lookup( typeInst->name ) ) {
 						if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.get_bound().type ) ) {
 							Alternative newFunc( *func );
@@ -1665,5 +1676,8 @@
 			Cost cost = Cost::zero;
 			Expression * newExpr = data.combine( cost );
-			alternatives.push_back( Alternative( newExpr, env, Cost::zero, cost ) );
+
+			// addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
+			// can't construct in place and use vector::back
+			Alternative newAlt( newExpr, env, Cost::zero, cost );
 			PRINT(
 				std::cerr << "decl is ";
@@ -1674,6 +1688,7 @@
 				std::cerr << std::endl;
 			)
-			renameTypes( alternatives.back().expr );
-			addAnonConversions( alternatives.back() ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression.
+			renameTypes( newAlt.expr );
+			addAnonConversions( newAlt ); // add anonymous member interpretations whenever an aggregate value type is seen as a name expression.
+			alternatives.push_back( std::move(newAlt) );
 		} // for
 	}
@@ -2042,4 +2057,8 @@
 		assertf( false, "AlternativeFinder should never see a DeletedExpr." );
 	}
+
+	void AlternativeFinder::Finder::postvisit( GenericExpr * ) {
+		assertf( false, "_Generic is not yet supported." );
+	}
 } // namespace ResolvExpr
 
