Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision beefc34cfb147868f1ec6e2b7ac16aed470af054)
+++ src/CodeGen/CodeGenerator.cc	(revision 61accc5c6c10982782355b908a789b97fc95a130)
@@ -836,4 +836,9 @@
 		assertf( ! genC, "Deleted expressions should not reach code generation." );
 		expr->expr->accept( *visitor );
+	}
+
+	void CodeGenerator::postvisit( DefaultArgExpr * arg ) {
+		assertf( ! genC, "Default argument expressions should not reach code generation." );
+		arg->expr->accept( *visitor );
 	}
 
Index: src/CodeGen/CodeGenerator.h
===================================================================
--- src/CodeGen/CodeGenerator.h	(revision beefc34cfb147868f1ec6e2b7ac16aed470af054)
+++ src/CodeGen/CodeGenerator.h	(revision 61accc5c6c10982782355b908a789b97fc95a130)
@@ -94,4 +94,5 @@
 		void postvisit( ConstructorExpr * );
 		void postvisit( DeletedExpr * );
+		void postvisit( DefaultArgExpr * );
 		void postvisit( GenericExpr * );
 
Index: src/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision beefc34cfb147868f1ec6e2b7ac16aed470af054)
+++ src/Common/PassVisitor.h	(revision 61accc5c6c10982782355b908a789b97fc95a130)
@@ -125,4 +125,5 @@
 	virtual void visit( InitExpr *  initExpr ) override final;
 	virtual void visit( DeletedExpr *  delExpr ) override final;
+	virtual void visit( DefaultArgExpr * argExpr ) override final;
 	virtual void visit( GenericExpr * genExpr ) override final;
 
@@ -224,4 +225,5 @@
 	virtual Expression * mutate( InitExpr *  initExpr ) override final;
 	virtual Expression * mutate( DeletedExpr *  delExpr ) override final;
+	virtual Expression * mutate( DefaultArgExpr * argExpr ) override final;
 	virtual Expression * mutate( GenericExpr * genExpr ) override final;
 
@@ -258,4 +260,6 @@
 
 private:
+	bool inFunction = false;
+
 	template<typename pass_t> friend void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
 	template<typename pass_t> friend void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision beefc34cfb147868f1ec6e2b7ac16aed470af054)
+++ src/Common/PassVisitor.impl.h	(revision 61accc5c6c10982782355b908a789b97fc95a130)
@@ -404,4 +404,8 @@
 			indexerAddId( &func );
 			maybeAccept_impl( node->type, *this );
+			// function body needs to have the same scope as parameters - CompoundStmt will not enter
+			// a new scope if inFunction is true
+			ValueGuard< bool > oldInFunction( inFunction );
+			inFunction = true;
 			maybeAccept_impl( node->statements, *this );
 			maybeAccept_impl( node->attributes, *this );
@@ -434,4 +438,8 @@
 			indexerAddId( &func );
 			maybeMutate_impl( node->type, *this );
+			// function body needs to have the same scope as parameters - CompoundStmt will not enter
+			// a new scope if inFunction is true
+			ValueGuard< bool > oldInFunction( inFunction );
+			inFunction = true;
 			maybeMutate_impl( node->statements, *this );
 			maybeMutate_impl( node->attributes, *this );
@@ -712,6 +720,9 @@
 	VISIT_START( node );
 	{
-		auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		// do not enter a new scope if inFunction is true - needs to check old state before the assignment
+		ValueGuard< bool > oldInFunction( inFunction );
+		auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
 		auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
+		inFunction = false;
 		visitStatementList( node->kids );
 	}
@@ -723,6 +734,9 @@
 	MUTATE_START( node );
 	{
-		auto guard1 = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		// do not enter a new scope if inFunction is true - needs to check old state before the assignment
+		ValueGuard< bool > oldInFunction( inFunction );
+		auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
 		auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
+		inFunction = false;
 		mutateStatementList( node->kids );
 	}
@@ -2084,4 +2098,27 @@
 
 //--------------------------------------------------------------------------
+// DefaultArgExpr
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( DefaultArgExpr * node ) {
+	VISIT_START( node );
+
+	indexerScopedAccept( node->result, *this );
+	maybeAccept_impl( node->expr, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( DefaultArgExpr * node ) {
+	MUTATE_START( node );
+
+	indexerScopedMutate( node->env, *this );
+	indexerScopedMutate( node->result, *this );
+	maybeMutate_impl( node->expr, *this );
+
+	MUTATE_END( Expression, node );
+}
+
+//--------------------------------------------------------------------------
 // GenericExpr
 template< typename pass_type >
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision beefc34cfb147868f1ec6e2b7ac16aed470af054)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 61accc5c6c10982782355b908a789b97fc95a130)
@@ -176,8 +176,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(
@@ -335,22 +345,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->clone(), 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->clone(), val ), env, newCost ) );
-			}
 		} // if
 	}
@@ -439,4 +436,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();
@@ -611,6 +615,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 );
 			}
 		}
@@ -873,5 +879,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 );
 						}
@@ -1065,4 +1071,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;
 
Index: src/ResolvExpr/Resolver.h
===================================================================
--- src/ResolvExpr/Resolver.h	(revision beefc34cfb147868f1ec6e2b7ac16aed470af054)
+++ src/ResolvExpr/Resolver.h	(revision 61accc5c6c10982782355b908a789b97fc95a130)
@@ -36,4 +36,6 @@
 	void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer );
 	void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer );
+	/// Searches expr and returns the first DeletedExpr found, otherwise nullptr
+	DeletedExpr * findDeletedExpr( Expression * expr );
 } // namespace ResolvExpr
 
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision beefc34cfb147868f1ec6e2b7ac16aed470af054)
+++ src/SynTree/Expression.cc	(revision 61accc5c6c10982782355b908a789b97fc95a130)
@@ -746,4 +746,19 @@
 	os << std::endl << indent+1 << "... deleted by: ";
 	deleteStmt->print( os, indent+1 );
+}
+
+
+DefaultArgExpr::DefaultArgExpr( Expression * expr ) : expr( expr ) {
+	assert( expr->result );
+	result = expr->result->clone();
+}
+DefaultArgExpr::DefaultArgExpr( const DefaultArgExpr & other ) : Expression( other ), expr( maybeClone( other.expr ) ) {}
+DefaultArgExpr::~DefaultArgExpr() {
+	delete expr;
+}
+
+void DefaultArgExpr::print( std::ostream & os, Indenter indent ) const {
+	os << "Default Argument Expression" << std::endl << indent+1;
+	expr->print( os, indent+1 );
 }
 
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision beefc34cfb147868f1ec6e2b7ac16aed470af054)
+++ src/SynTree/Expression.h	(revision 61accc5c6c10982782355b908a789b97fc95a130)
@@ -865,4 +865,19 @@
 };
 
+/// expression wrapping the use of a default argument - should never make it past the resolver.
+class DefaultArgExpr : public Expression {
+public:
+	Expression * expr;
+
+	DefaultArgExpr( Expression * expr );
+	DefaultArgExpr( const DefaultArgExpr & other );
+	~DefaultArgExpr();
+
+	virtual DefaultArgExpr * clone() const { return new DefaultArgExpr( * this ); }
+	virtual void accept( Visitor & v ) { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+};
+
 /// C11 _Generic expression
 class GenericExpr : public Expression {
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision beefc34cfb147868f1ec6e2b7ac16aed470af054)
+++ src/SynTree/Mutator.h	(revision 61accc5c6c10982782355b908a789b97fc95a130)
@@ -93,4 +93,5 @@
 	virtual Expression * mutate( InitExpr  * initExpr ) = 0;
 	virtual Expression * mutate( DeletedExpr * delExpr ) = 0;
+	virtual Expression * mutate( DefaultArgExpr * argExpr ) = 0;
 	virtual Expression * mutate( GenericExpr * genExpr ) = 0;
 
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision beefc34cfb147868f1ec6e2b7ac16aed470af054)
+++ src/SynTree/SynTree.h	(revision 61accc5c6c10982782355b908a789b97fc95a130)
@@ -101,4 +101,5 @@
 class InitExpr;
 class DeletedExpr;
+class DefaultArgExpr;
 class GenericExpr;
 
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision beefc34cfb147868f1ec6e2b7ac16aed470af054)
+++ src/SynTree/Visitor.h	(revision 61accc5c6c10982782355b908a789b97fc95a130)
@@ -95,4 +95,5 @@
 	virtual void visit( InitExpr *  initExpr ) = 0;
 	virtual void visit( DeletedExpr * delExpr ) = 0;
+	virtual void visit( DefaultArgExpr * argExpr ) = 0;
 	virtual void visit( GenericExpr * genExpr ) = 0;
 
