Index: src/ResolvExpr/Alternative.cc
===================================================================
--- src/ResolvExpr/Alternative.cc	(revision b46e3bd5b2d8744c0e03f9a699c26f6faa6d35bb)
+++ src/ResolvExpr/Alternative.cc	(revision 89be1c68ce6af5c822ac429caef167ce24a3cf97)
@@ -28,11 +28,14 @@
 		: cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {}
 
-	Alternative::Alternative( const Alternative &other ) {
-		initialize( other, *this );
+	Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) {
 	}
 
 	Alternative &Alternative::operator=( const Alternative &other ) {
 		if ( &other == this ) return *this;
-		initialize( other, *this );
+		delete expr;
+		cost = other.cost;
+		cvtCost = other.cvtCost;
+		expr = maybeClone( other.expr );
+		env = other.env;
 		return *this;
 	}
@@ -51,11 +54,4 @@
 		other.expr = nullptr;
 		return *this;
-	}
-
-	void Alternative::initialize( const Alternative &src, Alternative &dest ) {
-		dest.cost = src.cost;
-		dest.cvtCost = src.cvtCost;
-		dest.expr = maybeClone( src.expr );
-		dest.env = src.env;
 	}
 
Index: src/ResolvExpr/Alternative.h
===================================================================
--- src/ResolvExpr/Alternative.h	(revision b46e3bd5b2d8744c0e03f9a699c26f6faa6d35bb)
+++ src/ResolvExpr/Alternative.h	(revision 89be1c68ce6af5c822ac429caef167ce24a3cf97)
@@ -36,6 +36,4 @@
 		~Alternative();
 
-		void initialize( const Alternative &src, Alternative &dest );
-
 		void print( std::ostream &os, int indent = 0 ) const;
 
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision b46e3bd5b2d8744c0e03f9a699c26f6faa6d35bb)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 89be1c68ce6af5c822ac429caef167ce24a3cf97)
@@ -67,5 +67,5 @@
 
 	Cost sumCost( const AltList &in ) {
-		Cost total;
+		Cost total = Cost::zero;
 		for ( AltList::const_iterator i = in.begin(); i != in.end(); ++i ) {
 			total += i->cost;
@@ -218,8 +218,8 @@
 		if ( StructInstType *structInst = dynamic_cast< StructInstType* >( expr->get_result() ) ) {
 			NameExpr nameExpr( "" );
-			addAggMembers( structInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );
+			addAggMembers( structInst, expr, alt.cost+Cost::safe, alt.env, &nameExpr );
 		} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( expr->get_result() ) ) {
 			NameExpr nameExpr( "" );
-			addAggMembers( unionInst, expr, alt.cost+Cost( 0, 0, 1 ), alt.env, &nameExpr );
+			addAggMembers( unionInst, expr, alt.cost+Cost::safe, alt.env, &nameExpr );
 		} // if
 	}
@@ -277,5 +277,5 @@
 		FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() );
 
-		Cost convCost( 0, 0, 0 );
+		Cost convCost = Cost::zero;
 		std::list< DeclarationWithType* >& formals = function->get_parameters();
 		std::list< DeclarationWithType* >::iterator formal = formals.begin();
@@ -290,8 +290,8 @@
 				actualType->print( std::cerr, 8 );
 			)
-			Cost actualCost;
+			Cost actualCost = Cost::zero;
 			if ( formal == formals.end() ) {
 				if ( function->get_isVarArgs() ) {
-					convCost += Cost( 1, 0, 0 );
+					convCost.incUnsafe();
 					continue;
 				} else {
@@ -319,10 +319,10 @@
 			convCost += newCost;
 			actualCost += newCost;
-			if ( actualCost != Cost( 0, 0, 0 ) ) {
+			if ( actualCost != Cost::zero ) {
 				Type *newType = formalType->clone();
 				alt.env.apply( newType );
 				*actualExpr = new CastExpr( *actualExpr, newType );
 			}
-			convCost += Cost( 0, polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ), 0 );
+			convCost.incPoly( polyCost( formalType, alt.env, indexer ) + polyCost( actualType, alt.env, indexer ) );
 			++formal; // can't be in for-loop update because of the continue
 		}
@@ -346,5 +346,5 @@
 			}
 			convCost += newCost;
-			convCost += Cost( 0, polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ), 0 );
+			convCost.incPoly( polyCost( assert->second.formalType, alt.env, indexer ) + polyCost( assert->second.actualType, alt.env, indexer ) );
 		}
 
@@ -456,5 +456,5 @@
 			// match flattened actuals with formal parameters - actuals will be grouped to match
 			// with formals as appropriate
-			Cost cost;
+			Cost cost = Cost::zero;
 			std::list< Expression * > newExprs;
 			ObjectDecl * obj = safe_dynamic_cast< ObjectDecl * >( formal );
@@ -668,5 +668,5 @@
 				UntypedExpr *vexpr = untypedExpr->clone();
 				vexpr->set_result( pt.clone() );
-				alternatives.push_back( Alternative( vexpr, env, Cost()) );
+				alternatives.push_back( Alternative( vexpr, env, Cost::zero) );
 				return;
 			}
@@ -869,5 +869,5 @@
 			if ( thisCost != Cost::infinity ) {
 				// count one safe conversion for each value that is thrown away
-				thisCost += Cost( 0, 0, discardedValues );
+				thisCost.incSafe( discardedValues );
 
 				candidates.push_back( Alternative( restructureCast( i->expr->clone(), toType ), i->env, i->cost, thisCost ) );
@@ -916,5 +916,5 @@
 		for ( std::list< DeclarationWithType* >::iterator i = declList.begin(); i != declList.end(); ++i ) {
 			VariableExpr newExpr( *i, nameExpr->get_argName() );
-			alternatives.push_back( Alternative( newExpr.clone(), env, Cost() ) );
+			alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
 			PRINT(
 				std::cerr << "decl is ";
@@ -1060,5 +1060,5 @@
 			for ( std::list< DeclarationWithType* >::iterator i = attrList.begin(); i != attrList.end(); ++i ) {
 				VariableExpr newExpr( *i );
-				alternatives.push_back( Alternative( newExpr.clone(), env, Cost() ) );
+				alternatives.push_back( Alternative( newExpr.clone(), env, Cost::zero ) );
 				renameTypes( alternatives.back().expr );
 			} // for
@@ -1233,5 +1233,5 @@
 				if ( thisCost != Cost::infinity ) {
 					// count one safe conversion for each value that is thrown away
-					thisCost += Cost( 0, 0, discardedValues );
+					thisCost.incSafe( discardedValues );
 					candidates.push_back( Alternative( new InitExpr( restructureCast( alt.expr->clone(), toType ), initAlt.designation->clone() ), newEnv, alt.cost, thisCost ) );
 				}
Index: src/ResolvExpr/CastCost.cc
===================================================================
--- src/ResolvExpr/CastCost.cc	(revision b46e3bd5b2d8744c0e03f9a699c26f6faa6d35bb)
+++ src/ResolvExpr/CastCost.cc	(revision 89be1c68ce6af5c822ac429caef167ce24a3cf97)
@@ -46,12 +46,12 @@
 				assert( type );
 				if ( type->get_base() ) {
-					return castCost( src, type->get_base(), indexer, env ) + Cost( 0, 0, 1 );
+					return castCost( src, type->get_base(), indexer, env ) + Cost::safe;
 				} // if
 			} // if
 		} // if
 		if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
-			return Cost( 0, 0, 0 );
+			return Cost::zero;
 		} else if ( dynamic_cast< VoidType* >( dest ) ) {
-			return Cost( 0, 0, 1 );
+			return Cost::safe;
 		} else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
 			return convertToReferenceCost( src, refType, indexer, env );
@@ -63,5 +63,5 @@
 			} else {
 				// xxx - why are we adding cost 0 here?
-				return converter.get_cost() + Cost( 0, 0, 0 );
+				return converter.get_cost() + Cost::zero;
 			} // if
 		} // if
@@ -76,5 +76,5 @@
 		if ( destAsPointer && basicType->isInteger() ) {
 			// necessary for, e.g. unsigned long => void*
-			cost = Cost( 1, 0, 0 );
+			cost = Cost::unsafe;
 		} else {
 			cost = conversionCost( basicType, dest, indexer, env );
@@ -85,5 +85,5 @@
 		if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
 			if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
-				cost = Cost( 0, 0, 1 );
+				cost = Cost::safe;
 			} else {
 				TypeEnvironment newEnv( env );
@@ -92,5 +92,5 @@
 				int castResult = ptrsCastable( pointerType->get_base(), destAsPtr->get_base(), newEnv, indexer );
 				if ( castResult > 0 ) {
-					cost = Cost( 0, 0, 1 );
+					cost = Cost::safe;
 				} else if ( castResult < 0 ) {
 					cost = Cost::infinity;
@@ -100,5 +100,5 @@
 			if ( destAsBasic->isInteger() ) {
 				// necessary for, e.g. void* => unsigned long
-				cost = Cost( 1, 0, 0 );
+				cost = Cost::unsafe;
 			} // if
 		}
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision b46e3bd5b2d8744c0e03f9a699c26f6faa6d35bb)
+++ src/ResolvExpr/ConversionCost.cc	(revision 89be1c68ce6af5c822ac429caef167ce24a3cf97)
@@ -45,5 +45,5 @@
 				assert( type );
 				if ( type->get_base() ) {
-					return conversionCost( src, type->get_base(), indexer, env ) + Cost( 0, 0, 1 );
+					return conversionCost( src, type->get_base(), indexer, env ) + Cost::safe;
 				} // if
 			} // if
@@ -58,7 +58,7 @@
 		if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
 ///     std::cout << "compatible!" << std::endl;
-			return Cost( 0, 0, 0 );
+			return Cost::zero;
 		} else if ( dynamic_cast< VoidType* >( dest ) ) {
-			return Cost( 0, 0, 1 );
+			return Cost::safe;
 		} else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
 			// std::cerr << "conversionCost: dest is reference" << std::endl;
@@ -70,48 +70,77 @@
 				return Cost::infinity;
 			} else {
-				return converter.get_cost() + Cost( 0, 0, 0 );
-			} // if
-		} // if
-	}
-
-	Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
-		// std::cerr << "convert to reference cost..." << std::endl;
-		if ( ReferenceType *srcAsRef = dynamic_cast< ReferenceType * >( src ) ) { // pointer-like conversions between references
-			// std::cerr << "converting between references" << std::endl;
-			if ( srcAsRef->get_base()->get_qualifiers() <= dest->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), dest->get_base(), indexer, env ) ) {
-				return Cost( 0, 0, 1 );
-			} else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
-				int assignResult = ptrsAssignable( srcAsRef->get_base(), dest->get_base(), env );
-				if ( assignResult < 0 ) {
-					return Cost( 0, 0, 1 );
-				} else if ( assignResult > 0 ) {
-					return Cost( 1, 0, 0 );
-				} // if
-			} // if
-		} else if ( typesCompatibleIgnoreQualifiers( src, dest->get_base(), indexer, env ) ) {
-			// std::cerr << "converting compatible base type" << std::endl;
-			if ( src->get_lvalue() ) {
-				// std::cerr << "lvalue to reference conversion" << std::endl;
-				// lvalue-to-reference conversion:  cv lvalue T => cv T &
-				if ( src->get_qualifiers() == dest->get_base()->get_qualifiers() ) {
-					return Cost( 0, 0, 1 ); // cost needs to be non-zero to add cast
-				} if ( src->get_qualifiers() < dest->get_base()->get_qualifiers() ) {
-					return Cost( 0, 0, 2 ); // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
+				return converter.get_cost() + Cost::zero;
+			} // if
+		} // if
+	}
+
+	Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
+		std::cerr << "convert to reference cost..." << std::endl;
+		if ( diff > 0 ) {
+			// TODO: document this
+			Cost cost = convertToReferenceCost( safe_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env );
+			// TODO: increment reference cost
+			cost.incSafe();
+			return cost;
+		} else if ( diff < -1 ) {
+			// TODO: document this
+			Cost cost = convertToReferenceCost( src, safe_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env );
+			// TODO: increment reference cost
+			cost.incSafe();
+			return cost;
+		} else if ( diff == 0 ) {
+			ReferenceType * srcAsRef = dynamic_cast< ReferenceType * >( src );
+			ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
+			if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
+				std::cerr << "converting between references" << std::endl;
+				if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) {
+					return Cost::safe;
+				} else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
+					int assignResult = ptrsAssignable( srcAsRef->get_base(), destAsRef->get_base(), env );
+					if ( assignResult < 0 ) {
+						return Cost::safe;
+					} else if ( assignResult > 0 ) {
+						return Cost::unsafe;
+					} // if
+				} // if
+			} else {
+				std::cerr << "reference to rvalue conversion" << std::endl;
+				ConversionCost converter( dest, indexer, env );
+				src->accept( converter );
+				return converter.get_cost();
+			} // if
+		} else {
+			ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
+			assert( diff == -1 && destAsRef );
+			if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) {
+				std::cerr << "converting compatible base type" << std::endl;
+				if ( src->get_lvalue() ) {
+					std::cerr << "lvalue to reference conversion" << std::endl;
+					// lvalue-to-reference conversion:  cv lvalue T => cv T &
+					if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) {
+						return Cost::safe; // cost needs to be non-zero to add cast
+					} if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) {
+						return Cost::safe + Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
+					} else {
+						return Cost::unsafe;
+					} // if
+				} else if ( destAsRef->get_base()->get_const() ) {
+					std::cerr << "rvalue to const ref conversion" << std::endl;
+					// rvalue-to-const-reference conversion: T => const T &
+					return Cost::safe;
 				} else {
-					return Cost( 1, 0, 0 );
-				}
-			} else if ( dest->get_base()->get_const() ) {
-				// std::cerr << "rvalue to const ref conversion" << std::endl;
-				// rvalue-to-const-reference conversion: T => const T &
-				return Cost( 0, 0, 1 );
-			} else {
-				// std::cerr << "rvalue to non-const reference conversion" << std::endl;
-				// rvalue-to-reference conversion: T => T &
-				return Cost( 1, 0, 0 );
-			}
-		} else {
-			// std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl;
+					// std::cerr << "rvalue to non-const reference conversion" << std::endl;
+					// rvalue-to-reference conversion: T => T &
+					return Cost::unsafe;
+				} // if
+			} // if
+			std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl;
 		}
 		return Cost::infinity;
+	}
+
+	Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
+		int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
+		return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env );
 	}
 
@@ -205,13 +234,14 @@
 			int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
 			if ( tableResult == -1 ) {
-				cost = Cost( 1, 0, 0 );
-			} else {
-				cost = Cost( 0, 0, tableResult );
+				cost = Cost::unsafe;
+			} else {
+				cost = Cost::zero;
+				cost.incSafe( tableResult );
 			} // if
 		} else if ( dynamic_cast< EnumInstType *>( dest ) ) {
 			// xxx - not positive this is correct, but appears to allow casting int => enum
-			cost = Cost( 1, 0, 0 );
+			cost = Cost::unsafe;
 		} else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
-			cost = Cost( 1, 0, 0 );
+			cost = Cost::unsafe;
 		} // if
 	}
@@ -220,15 +250,15 @@
 		if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
 			if ( pointerType->get_base()->get_qualifiers() <= destAsPtr->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
-				cost = Cost( 0, 0, 1 );
+				cost = Cost::safe;
 			} else {  // xxx - this discards pointer qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
 				int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env );
 				if ( assignResult < 0 ) {
-					cost = Cost( 0, 0, 1 );
+					cost = Cost::safe;
 				} else if ( assignResult > 0 ) {
-					cost = Cost( 1, 0, 0 );
+					cost = Cost::unsafe;
 				} // if
 			} // if
 		} else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
-			cost = Cost( 1, 0, 0 );
+			cost = Cost::unsafe;
 		} // if
 	}
@@ -243,4 +273,6 @@
 		// cv can be safely dropped because of 'implicit dereference' behavior.
 		refType->get_base()->accept( *this );
+		// TODO: increment reference cost
+		cost.incSafe();
 	}
 
@@ -267,5 +299,5 @@
 		static BasicType integer( q, BasicType::SignedInt );
 		integer.accept( *this );  // safe if dest >= int
-		if ( cost < Cost( 1, 0, 0 ) ) {
+		if ( cost < Cost::unsafe ) {
 			cost.incSafe();
 		} // if
@@ -289,5 +321,5 @@
 			assert( type );
 			if ( type->get_base() ) {
-				cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost( 0, 0, 1 );
+				cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;
 			} // if
 		} // if
@@ -295,5 +327,5 @@
 
 	void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) {
-		Cost c;
+		Cost c = Cost::zero;
 		if ( TupleType *destAsTuple = dynamic_cast< TupleType* >( dest ) ) {
 			std::list< Type* >::const_iterator srcIt = tupleType->get_types().begin();
@@ -327,10 +359,11 @@
 			int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
 			if ( tableResult == -1 ) {
-				cost = Cost( 1, 0, 0 );
-			} else {
-				cost = Cost( 0, 0, tableResult + 1 );
+				cost = Cost::unsafe;
+			} else {
+				cost = Cost::zero;
+				cost.incSafe( tableResult + 1 );
 			}
 		} else if ( dynamic_cast< PointerType* >( dest ) ) {
-			cost = Cost( 0, 0, 1 );
+			cost = Cost::safe;
 		}
 	}
@@ -343,7 +376,8 @@
 			int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
 			if ( tableResult == -1 ) {
-				cost = Cost( 1, 0, 0 );
-			} else {
-				cost = Cost( 0, 0, tableResult + 1 );
+				cost = Cost::unsafe;
+			} else {
+				cost = Cost::zero;
+				cost.incSafe( tableResult + 1 );
 			}
 		}
Index: src/ResolvExpr/Cost.h
===================================================================
--- src/ResolvExpr/Cost.h	(revision b46e3bd5b2d8744c0e03f9a699c26f6faa6d35bb)
+++ src/ResolvExpr/Cost.h	(revision 89be1c68ce6af5c822ac429caef167ce24a3cf97)
@@ -21,11 +21,11 @@
 namespace ResolvExpr {
 	class Cost {
-	  public:
-		Cost();
+	  private:
 		Cost( int unsafeCost, int polyCost, int safeCost );
 
-		void incUnsafe( int inc = 1 );
-		void incPoly( int inc = 1 );
-		void incSafe( int inc = 1 );
+	  public:
+		Cost & incUnsafe( int inc = 1 );
+		Cost & incPoly( int inc = 1 );
+		Cost & incSafe( int inc = 1 );
 
 		Cost operator+( const Cost &other ) const;
@@ -50,18 +50,19 @@
 	};
 
-	inline Cost::Cost() : unsafeCost( 0 ), polyCost( 0 ), safeCost( 0 ) {}
-
 	inline Cost::Cost( int unsafeCost, int polyCost, int safeCost ) : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ) {}
 
-	inline void Cost::incUnsafe( int inc ) {
+	inline Cost & Cost::incUnsafe( int inc ) {
 		unsafeCost += inc;
+		return *this;
 	}
 
-	inline void Cost::incPoly( int inc ) {
+	inline Cost & Cost::incPoly( int inc ) {
 		polyCost += inc;
+		return *this;
 	}
 
-	inline void Cost::incSafe( int inc ) {
+	inline Cost & Cost::incSafe( int inc ) {
 		safeCost += inc;
+		return *this;
 	}
 
