Index: src/GenPoly/InstantiateGeneric.cc
===================================================================
--- src/GenPoly/InstantiateGeneric.cc	(revision 6c2ba385b7573940622a91ec236a0a6de26c4300)
+++ src/GenPoly/InstantiateGeneric.cc	(revision 8d5b9cf388030c46b0f033a5e263141fc124d268)
@@ -21,4 +21,5 @@
 #include <vector>                      // for vector
 
+#include "CodeGen/OperatorTable.h"
 #include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
 #include "Common/ScopedMap.h"          // for ScopedMap
@@ -27,4 +28,5 @@
 #include "Common/utility.h"            // for deleteAll, cloneAll
 #include "GenPoly.h"                   // for isPolyType, typesPolyCompatible
+#include "InitTweak/InitTweak.h"
 #include "ResolvExpr/typeops.h"
 #include "ScopedSet.h"                 // for ScopedSet, ScopedSet<>::iterator
@@ -154,9 +156,14 @@
 
 	/// Add cast to dtype-static member expressions so that type information is not lost in GenericInstantiator
-	struct FixDtypeStatic final {
+	struct FixDtypeStatic final : public WithGuards, public WithVisitorRef<FixDtypeStatic>, public WithShortCircuiting, public WithStmtsToAdd {
 		Expression * postmutate( MemberExpr * memberExpr );
+
+		void premutate( ApplicationExpr * appExpr );
+		void premutate( AddressExpr * addrExpr );
 
 		template<typename AggrInst>
 		Expression * fixMemberExpr( AggrInst * inst, MemberExpr * memberExpr );
+
+		bool isLvalueArg = false;
 	};
 
@@ -210,5 +217,5 @@
 		PassVisitor<GenericInstantiator> instantiator;
 
-		// mutateAll( translationUnit, fixer );
+		mutateAll( translationUnit, fixer );
 		mutateAll( translationUnit, instantiator );
 	}
@@ -501,6 +508,28 @@
 		if ( isDtypeStatic( baseParams ) ) {
 			if ( ! ResolvExpr::typesCompatible( memberExpr->result, memberExpr->member->get_type(), SymTab::Indexer() ) ) {
-				// type of member and type of expression differ, so add cast to actual type
-				return new CastExpr( memberExpr, memberExpr->result->clone() );
+				// type of member and type of expression differ
+				Type * concType = memberExpr->result->clone();
+				if ( isLvalueArg ) {
+					// result must be C lvalue, so make a new reference variable with the correct actual type to replace the member expression
+					//   forall(dtype T)
+					//   struct Ptr {
+					//     T * x
+					//   };
+					//   Ptr(int) p;
+					//   int i;
+					//   p.x = &i;
+					// becomes
+					//   int *& _dtype_static_member_0 = (int **)&p.x;
+					//   _dtype_static_member_0 = &i;
+					// Note: this currently creates more temporaries than is strictly necessary, since it does not check for duplicate uses of the same member expression.
+					static UniqueName tmpNamer( "_dtype_static_member_" );
+					Expression * init = new CastExpr( new AddressExpr( memberExpr ), new PointerType( Type::Qualifiers(), concType->clone() ) );
+					ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), new ReferenceType( Type::Qualifiers(), concType ), new SingleInit( init ) );
+					stmtsToAddBefore.push_back( new DeclStmt( noLabels, tmp ) );
+					return new VariableExpr( tmp );
+				} else {
+					// can simply add a cast to actual type
+					return new CastExpr( memberExpr, concType );
+				}
 			}
 		}
@@ -520,4 +549,27 @@
 	}
 
+	void FixDtypeStatic::premutate( ApplicationExpr * appExpr ) {
+		GuardValue( isLvalueArg );
+		isLvalueArg = false;
+		DeclarationWithType * function = InitTweak::getFunction( appExpr );
+		if ( function->linkage == LinkageSpec::Intrinsic && CodeGen::isAssignment( function->name ) ) {
+			// explicitly visit children because only the first argument must be a C lvalue.
+			visit_children = false;
+			appExpr->env = maybeMutate( appExpr->env, *visitor );
+			appExpr->result = maybeMutate( appExpr->result, *visitor );
+			appExpr->function = maybeMutate( appExpr->function, *visitor );
+			isLvalueArg = true;
+			for ( Expression * arg : appExpr->args ) {
+				arg = maybeMutate( arg, *visitor );
+				isLvalueArg = false;
+			}
+		}
+	}
+
+	void FixDtypeStatic::premutate( AddressExpr * ) {
+		// argument of & must be C lvalue
+		GuardValue( isLvalueArg );
+		isLvalueArg = true;
+	}
 } // namespace GenPoly
 
