Index: src/GenPoly/Lvalue.cc
===================================================================
--- src/GenPoly/Lvalue.cc	(revision b9f383f02133e2fd12cbee9fc0753d823a608d5e)
+++ src/GenPoly/Lvalue.cc	(revision 552775975b142e0bb26e33a21d776351992df048)
@@ -211,5 +211,7 @@
 						)
 						// TODO: it's likely that the second condition should be ... && ! isIntrinsicReference( arg ), but this requires investigation.
+
 						if ( function->get_linkage() != LinkageSpec::Intrinsic && isIntrinsicReference( arg ) ) {
+							// needed for definition of prelude functions, etc.
 							// if argument is dereference or array subscript, the result isn't REALLY a reference, but non-intrinsic functions expect a reference: take address
 
@@ -225,4 +227,5 @@
 							)
 							arg = new AddressExpr( arg );
+						// } else if ( function->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getPointerBase( arg->result ) ) {
 						} else if ( function->get_linkage() == LinkageSpec::Intrinsic && arg->result->referenceDepth() != 0 ) {
 							// argument is a 'real' reference, but function expects a C lvalue: add a dereference to the reference-typed argument
@@ -234,7 +237,7 @@
 							PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() );
 							delete arg->result;
-							arg->set_result( ptrType );
+							arg->result = ptrType;
 							arg = mkDeref( arg );
-							assertf( arg->result->referenceDepth() == 0, "Reference types should have been eliminated from intrinsic function calls, but weren't: %s", toCString( arg->result ) );
+							// assertf( arg->result->referenceDepth() == 0, "Reference types should have been eliminated from intrinsic function calls, but weren't: %s", toCString( arg->result ) );
 						}
 					}
@@ -298,6 +301,12 @@
 				}
 
-				if ( addCast ) {
-					PRINT( std::cerr << "adding cast..." << std::endl; )
+				// if addrExpr depth is 0, then the result is a pointer because the arg was depth 1 and not lvalue.
+				// This means the dereference result is not a reference, is lvalue, and one less pointer depth than
+				// the addrExpr. Thus the cast is meaningless.
+				// TODO: One thing to double check is whether it is possible for the types to differ outside of the single
+				// pointer level (i.e. can the base type of addrExpr differ from the type of addrExpr-arg?).
+				// If so then the cast might need to be added, conditional on a more sophisticated check.
+				if ( addCast && addrExpr->result->referenceDepth() != 0 ) {
+					PRINT( std::cerr << "adding cast to " << addrExpr->result << std::endl; )
 					return new CastExpr( ret, addrExpr->result->clone() );
 				}
@@ -413,4 +422,5 @@
 				for ( int i = 0; i < diff; ++i ) {
 					ret = mkDeref( ret );
+					// xxx - try removing one reference here? actually, looks like mkDeref already does this, so more closely look at the types generated.
 				}
 				if ( ! ResolvExpr::typesCompatibleIgnoreQualifiers( destType->stripReferences(), srcType->stripReferences(), SymTab::Indexer() ) ) {
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision b9f383f02133e2fd12cbee9fc0753d823a608d5e)
+++ src/InitTweak/InitTweak.cc	(revision 552775975b142e0bb26e33a21d776351992df048)
@@ -528,10 +528,15 @@
 		}
 		if ( dynamic_cast< ReferenceType * >( dst->result ) ) {
-			dst = new AddressExpr( dst );
+			for (int depth = dst->result->referenceDepth(); depth > 0; depth--) {
+				dst = new AddressExpr( dst );
+			}
 		} else {
 			dst = new CastExpr( dst, new ReferenceType( noQualifiers, dst->result->clone() ) );
 		}
 		if ( dynamic_cast< ReferenceType * >( src->result ) ) {
-			src = new CastExpr( src, new ReferenceType( noQualifiers, src->result->stripReferences()->clone() ) );
+			for (int depth = src->result->referenceDepth(); depth > 0; depth--) {
+				src = new AddressExpr( src );
+			}
+			// src = new CastExpr( src, new ReferenceType( noQualifiers, src->result->stripReferences()->clone() ) );
 		}
 		return new ApplicationExpr( VariableExpr::functionPointer( assign ), { dst, src } );
Index: src/ResolvExpr/CommonType.cc
===================================================================
--- src/ResolvExpr/CommonType.cc	(revision b9f383f02133e2fd12cbee9fc0753d823a608d5e)
+++ src/ResolvExpr/CommonType.cc	(revision 552775975b142e0bb26e33a21d776351992df048)
@@ -101,5 +101,5 @@
 			int diff = depth1-depth2;
 			// TODO: should it be possible for commonType to generate complicated conversions? I would argue no, only conversions that involve types of the same reference level or a difference of 1 should be allowed.
-			if ( diff > 1 || diff < -1 ) return nullptr;
+			// if ( diff > 1 || diff < -1 ) return nullptr;
 
 			// special case where one type has a reference depth of 1 larger than the other
Index: src/tests/references.c
===================================================================
--- src/tests/references.c	(revision b9f383f02133e2fd12cbee9fc0753d823a608d5e)
+++ src/tests/references.c	(revision 552775975b142e0bb26e33a21d776351992df048)
@@ -75,14 +75,14 @@
 	printf("%d %d\n", r1, x);
 
-	((int&)r3) = 6;                       // change x, ***r3
+	r3 = 6;                               // change x, ***r3
 	printf("x = %d ; x2 = %d\n", x, x2);  // check that x was changed
-	((int*&)&r3) = &x2;                   // change r1 to refer to x2, (&*)**r3
-	((int&)r3) = 999;                     // modify x2
+	&r3 = &x2;                            // change r1 to refer to x2, (&*)**r3
+	r3 = 999;                             // modify x2
 	printf("x = %d ; x2 = %d\n", x, x2);  // check that x2 was changed
-	((int**&)&&r3) = p2;                  // change r2, (&(&*)*)*r3
-	((int&)r3) = 12345;                   // modify x
+	((int**&)&&r3) = p2;                  // change r2, (&(&*)*)*r3, ensure explicit cast to reference works
+	r3 = 12345;                           // modify x
 	printf("x = %d ; x2 = %d\n", x, x2);  // check that x was changed
-	((int***&)&&&r3) = p3;                // change r3 to p3, (&(&(&*)*)*)r3
-	((int&)r3) = 22222;                   // modify x
+	&&&r3 = p3;                           // change r3 to p3, (&(&(&*)*)*)r3
+	((int&)r3) = 22222;                   // modify x, ensure explicit cast to reference works
 	printf("x = %d ; x2 = %d\n", x, x2);  // check that x was changed
 
