Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision 1ba5803c90674cf77489dd4409a2afd3b782551e)
+++ src/GenPoly/Box.cc	(revision 8dceeb78ad2ff73a75b2a0589e7539e4da01800f)
@@ -167,4 +167,6 @@
 			Expression *postmutate( OffsetofExpr *offsetofExpr );
 			Expression *postmutate( OffsetPackExpr *offsetPackExpr );
+			void premutate( StructDecl * );
+			void premutate( UnionDecl * );
 
 			void beginScope();
@@ -178,4 +180,6 @@
 			/// adds type parameters to the layout call; will generate the appropriate parameters if needed
 			void addOtypeParamsToLayoutCall( UntypedExpr *layoutCall, const std::list< Type* > &otypeParams );
+			/// change the type of generic aggregate members to char[]
+			void mutateMembers( AggregateDecl * aggrDecl );
 
 			/// Enters a new scope for type-variables, adding the type variables from ty
@@ -1414,4 +1418,5 @@
 
 		void PolyGenericCalculator::premutate( TypedefDecl *typedefDecl ) {
+			assert(false);
 			beginTypeScope( typedefDecl->get_base() );
 		}
@@ -1460,4 +1465,43 @@
 		}
 
+		/// converts polymorphic type T into a suitable monomorphic representation, currently: __attribute__((aligned(8)) char[size_T]
+		Type * polyToMonoType( Type * declType ) {
+			Type * charType = new BasicType( Type::Qualifiers(), BasicType::Kind::Char);
+			Expression * size = new NameExpr( sizeofName( mangleType(declType) ) );
+			Attribute * aligned = new Attribute( "aligned", std::list<Expression*>{ new ConstantExpr( Constant::from_int(8) ) } );
+			return new ArrayType( Type::Qualifiers(), charType, size,
+				true, false, std::list<Attribute *>{ aligned } );
+		}
+
+		void PolyGenericCalculator::mutateMembers( AggregateDecl * aggrDecl ) {
+			std::set< std::string > genericParams;
+			for ( TypeDecl * td : aggrDecl->parameters ) {
+				genericParams.insert( td->name );
+			}
+			for ( Declaration * decl : aggrDecl->members ) {
+				if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( decl ) ) {
+					Type * ty = replaceTypeInst( field->type, env );
+					if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
+						// do not try to monomorphize generic parameters
+						if ( scopeTyVars.find( typeInst->get_name() ) != scopeTyVars.end() && ! genericParams.count( typeInst->name ) ) {
+							// polymorphic aggregate members should be converted into monomorphic members.
+							// Using char[size_T] here respects the expected sizing rules of an aggregate type.
+							Type * newType = polyToMonoType( field->type );
+							delete field->type;
+							field->type = newType;
+						}
+					}
+				}
+			}
+		}
+
+		void PolyGenericCalculator::premutate( StructDecl * structDecl ) {
+			mutateMembers( structDecl );
+		}
+
+		void PolyGenericCalculator::premutate( UnionDecl * unionDecl ) {
+			mutateMembers( unionDecl );
+		}
+
 		void PolyGenericCalculator::premutate( DeclStmt *declStmt ) {
 			if ( ObjectDecl *objectDecl = dynamic_cast< ObjectDecl *>( declStmt->get_decl() ) ) {
@@ -1465,8 +1509,5 @@
 					// change initialization of a polymorphic value object to allocate via a VLA
 					// (alloca was previously used, but can't be safely used in loops)
-					Type *declType = objectDecl->get_type();
-					ObjectDecl *newBuf = new ObjectDecl( bufNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0,
-						new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers(), BasicType::Kind::Char), new NameExpr( sizeofName( mangleType(declType) ) ),
-						true, false, std::list<Attribute*>{ new Attribute( "aligned", std::list<Expression*>{ new ConstantExpr( Constant::from_int(8) ) } ) } ), 0 );
+					ObjectDecl *newBuf = ObjectDecl::newObject( bufNamer.newName(), polyToMonoType( objectDecl->type ), nullptr );
 					stmtsToAddBefore.push_back( new DeclStmt( noLabels, newBuf ) );
 
