Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 25a054f2026506f0b8d821cfc29790b22ca54608)
+++ src/SymTab/Validate.cc	(revision 32805dbb99ed120ef9921a7fe6fa64ce4be94a49)
@@ -585,4 +585,14 @@
 	}
 
+	template< typename OutputIterator >
+	void makeUnionFieldsAssignment( ObjectDecl *srcParam, ObjectDecl *dstParam, UnionInstType *unionType, OutputIterator out ) {
+		UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
+		copy->get_args().push_back( new VariableExpr( dstParam ) );
+		copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
+		copy->get_args().push_back( new SizeofExpr( unionType ) );
+
+		*out++ = new ExprStmt( noLabels, copy );
+	}
+
 	//E ?=?(E volatile*, int),
 	//  ?=?(E _Atomic volatile*, int);
@@ -653,7 +663,9 @@
 
 		// Make function polymorphic in same parameters as generic struct, if applicable
+		bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for union)
 		std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
 		std::list< Expression* > structParams;  // List of matching parameters to put on types
 		for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
+			isGeneric = true;
 			TypeDecl *typeParam = (*param)->clone();
 			assignType->get_forall().push_back( typeParam );
@@ -661,5 +673,5 @@
 		}
 
-		ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
+		ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, structParams ), 0 );
 		assignType->get_returnVals().push_back( returnVal );
 
@@ -691,10 +703,12 @@
 				if ( ArrayType *array = dynamic_cast< ArrayType * >( dwt->get_type() ) ) {
 					makeArrayAssignment( srcParam, dstParam, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
+					if ( isGeneric ) makeArrayAssignment( srcParam, returnVal, dwt, array, back_inserter( assignDecl->get_statements()->get_kids() ) );
 				} else {
 					makeScalarAssignment( srcParam, dstParam, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
+					if ( isGeneric ) makeScalarAssignment( srcParam, returnVal, dwt, back_inserter( assignDecl->get_statements()->get_kids() ) );
 				} // if
 			} // if
 		} // for
-		assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
+		if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
 
 		return assignDecl;
@@ -705,7 +719,9 @@
 
 		// Make function polymorphic in same parameters as generic union, if applicable
+		bool isGeneric = false;  // NOTE this flag is an incredibly ugly kludge; we should fix the assignment signature instead (ditto for struct)
 		std::list< TypeDecl* >& genericParams = aggregateDecl->get_parameters();
 		std::list< Expression* > unionParams;  // List of matching parameters to put on types
 		for ( std::list< TypeDecl* >::const_iterator param = genericParams.begin(); param != genericParams.end(); ++param ) {
+			isGeneric = true;
 			TypeDecl *typeParam = (*param)->clone();
 			assignType->get_forall().push_back( typeParam );
@@ -713,5 +729,5 @@
 		}
 
-		ObjectDecl *returnVal = new ObjectDecl( "", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
+		ObjectDecl *returnVal = new ObjectDecl( "_ret", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, cloneWithParams( refType, unionParams ), 0 );
 		assignType->get_returnVals().push_back( returnVal );
 
@@ -727,11 +743,8 @@
 		assignDecl->fixUniqueId();
 
-		UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
-		copy->get_args().push_back( new VariableExpr( dstParam ) );
-		copy->get_args().push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
-		copy->get_args().push_back( new SizeofExpr( cloneWithParams( refType, unionParams ) ) );
-
-		assignDecl->get_statements()->get_kids().push_back( new ExprStmt( noLabels, copy ) );
-		assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
+		makeUnionFieldsAssignment( srcParam, dstParam, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
+		if ( isGeneric ) makeUnionFieldsAssignment( srcParam, returnVal, cloneWithParams( refType, unionParams ), back_inserter( assignDecl->get_statements()->get_kids() ) );
+		
+		if ( ! isGeneric ) assignDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new VariableExpr( srcParam ) ) );
 
 		return assignDecl;
