Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision 6d267ca6bdc59bcd82cb15c2629c927f34392457)
+++ src/GenPoly/Box.cc	(revision d3356273b5793b3e8f1af94e178f3f46c47bea72)
@@ -1027,5 +1027,7 @@
 						} // if
 						if ( baseType1 || baseType2 ) {
-							ret->set_result( appExpr->get_result()->clone() );
+							Type * baseType = InitTweak::getPointerBase( appExpr->get_result() );
+							assert( baseType );
+							ret->set_result( baseType->clone() );
 							if ( appExpr->get_env() ) {
 								ret->set_env( appExpr->get_env() );
@@ -1222,6 +1224,7 @@
 			// isPolyType check needs to happen before mutating addrExpr arg, so pull it forward
 			// out of the if condition.
+			addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
+			// ... but must happen after mutate, since argument might change (e.g. intrinsic *?, ?[?]) - re-evaluate above comment
 			bool polytype = isPolyType( addrExpr->get_arg()->get_result(), scopeTyVars, env );
-			addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
 			if ( polytype || needs ) {
 				Expression *ret = addrExpr->get_arg();
Index: src/GenPoly/Lvalue.cc
===================================================================
--- src/GenPoly/Lvalue.cc	(revision 6d267ca6bdc59bcd82cb15c2629c927f34392457)
+++ src/GenPoly/Lvalue.cc	(revision d3356273b5793b3e8f1af94e178f3f46c47bea72)
@@ -82,5 +82,5 @@
 		/// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues
 		/// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c)
-		struct GeneralizedLvalue final {
+		struct GeneralizedLvalue final : public WithVisitorRef<GeneralizedLvalue> {
 			Expression * postmutate( AddressExpr * addressExpr );
 		};
@@ -145,38 +145,40 @@
 		}
 
-		void fixArg( Expression *& arg, Type * formal ) {
-			if ( dynamic_cast<ReferenceType*>( formal ) ) {
-				// if the parameter is a reference, add a dereference to the reference-typed argument.
-				Type * baseType = InitTweak::getPointerBase( arg->get_result() );
-				assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ) );
-				PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() );
-				delete arg->get_result();
-				arg->set_result( ptrType );
-				arg = mkDeref( arg );
-			}
-		}
-
 		// xxx - might need to & every * (or every * that is an arg to non-intrinsic function??)
 		Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) {
 			// intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments.
 			if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
-				if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
-					FunctionType * ftype = GenPoly::getFunctionType( function->get_type() );
-					assertf( ftype, "Function declaration does not have function type." );
-					for ( auto p : group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) {
-						Expression *& arg = std::get<0>( p );
-						DeclarationWithType * formal = std::get<1>( p );
-						PRINT(
-							std::cerr << "pair<0>: " << arg << std::endl;
-							std::cerr << "pair<1>: " << formal->get_type() << std::endl;
-						)
-						if ( isIntrinsicReference( arg ) ) { // intrinsic functions that turn pointers into references
-							// if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument
-							PRINT( std::cerr << "skipping intrinsic reference" << std::endl; )
-							continue;
-						} else {
-							fixArg( arg, formal->get_type() );
+				FunctionType * ftype = GenPoly::getFunctionType( function->get_type() );
+				assertf( ftype, "Function declaration does not have function type." );
+				// can be of differing lengths only when function is variadic
+				assertf( ftype->get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." );
+				unsigned int i = 0;
+				const unsigned int end = ftype->get_parameters().size();
+				for ( auto p : unsafe_group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) {
+					if (i == end) break;
+					Expression *& arg = std::get<0>( p );
+					Type * formal = std::get<1>( p )->get_type();
+					PRINT(
+						std::cerr << "pair<0>: " << arg << std::endl;
+						std::cerr << "pair<1>: " << formal << std::endl;
+					)
+					if ( dynamic_cast<ReferenceType*>( formal ) ) {
+						if ( isIntrinsicReference( arg ) ) {
+							if ( function->get_linkage() != LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references
+								// if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument
+								PRINT( std::cerr << "is intrinsic arg in non-intrinsic call - adding address" << std::endl; )
+								arg = new AddressExpr( arg );
+							}
+						} else if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
+							// if the parameter is a reference, add a dereference to the reference-typed argument.
+							Type * baseType = InitTweak::getPointerBase( arg->get_result() );
+							assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ) );
+							PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() );
+							delete arg->get_result();
+							arg->set_result( ptrType );
+							arg = mkDeref( arg );
 						}
 					}
+					++i;
 				}
 			}
@@ -240,4 +242,5 @@
 				assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() );
 			} else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
+				(void)refType;
 				// conversion from reference to rvalue
 				PRINT( std::cerr << "convert reference to rvalue -- *" << std::endl; )
@@ -270,5 +273,5 @@
 				Expression * arg2 = commaExpr->get_arg2()->clone();
 				delete addrExpr;
-				return new CommaExpr( arg1, new AddressExpr( arg2 ) );
+				return new CommaExpr( arg1, (new AddressExpr( arg2 ))->acceptMutator( *visitor ) );
 			} else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( addrExpr->get_arg() ) ) {
 				Expression * arg1 = condExpr->get_arg1()->clone();
@@ -276,5 +279,5 @@
 				Expression * arg3 = condExpr->get_arg3()->clone();
 				delete addrExpr;
-				return new ConditionalExpr( arg1, new AddressExpr( arg2 ), new AddressExpr( arg3 ) );
+				return new ConditionalExpr( arg1, (new AddressExpr( arg2 ))->acceptMutator( *visitor ), (new AddressExpr( arg3 ))->acceptMutator( *visitor ) );
 			}
 			return addrExpr;
