Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision b4cd03b740cf2cfe5905750f3587883e5a51a654)
+++ src/GenPoly/Box.cc	(revision 4789f44f209a3abbeda0761c6adc954c88a1bff8)
@@ -123,5 +123,6 @@
 		};
 
-		/// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference
+		/// Replaces member expressions for polymorphic types with calculated add-field-offset-and-dereference;
+		/// also fixes offsetof expressions.
 		class MemberExprFixer : public PolyMutator {
 		  public:
@@ -136,4 +137,5 @@
 			virtual Type *mutate( FunctionType *funcType );
 			virtual Expression *mutate( MemberExpr *memberExpr );
+			virtual Expression *mutate( OffsetofExpr *offsetofExpr );
 		};
 
@@ -1283,4 +1285,39 @@
 		}
 
+		/// Finds the member in the base list that matches the given declaration; returns its index, or -1 if not present
+		long findMember( DeclarationWithType *memberDecl, std::list< Declaration* > &baseDecls ) {
+			long i = 0;
+			for(std::list< Declaration* >::const_iterator decl = baseDecls.begin(); decl != baseDecls.end(); ++decl, ++i ) {
+				if ( memberDecl->get_name() != (*decl)->get_name() ) continue;
+
+				if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) {
+					if ( memberDecl->get_mangleName() == declWithType->get_mangleName() ) return i;
+					else continue;
+				} else return i;
+			}
+			return -1;
+		}
+
+		/// Returns an index expression into the offset array for a type
+		Expression *makeOffsetIndex( Type *objectType, long i ) {
+			std::stringstream offset_namer;
+			offset_namer << i;
+			ConstantExpr *fieldIndex = new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), offset_namer.str() ) );
+			UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) );
+			fieldOffset->get_args().push_back( new NameExpr( offsetofName( objectType ) ) );
+			fieldOffset->get_args().push_back( fieldIndex );
+			return fieldOffset;
+		}
+
+		/// Returns an expression dereferenced n times
+		Expression *makeDerefdVar( Expression *derefdVar, long n ) {
+			for ( int i = 1; i < n; ++i ) {
+				UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
+				derefExpr->get_args().push_back( derefdVar );
+				derefdVar = derefExpr;
+			}
+			return derefdVar;
+		}
+		
 		Expression *MemberExprFixer::mutate( MemberExpr *memberExpr ) {
 			// mutate, exiting early if no longer MemberExpr
@@ -1301,49 +1338,47 @@
 			if ( ! objectType ) return memberExpr;
 
-			// get base aggregate for type so members can be looked up
-			AggregateDecl *memberBase = 0;
 			if ( StructInstType *structType = dynamic_cast< StructInstType* >( objectType ) ) {
-				memberBase = structType->get_baseStruct();
+				// look up offset index
+				long i = findMember( memberExpr->get_member(), structType->get_baseStruct()->get_members() );
+				if ( i == -1 ) return memberExpr;
+
+				// replace member expression with pointer to base plus offset
+				UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );
+				fieldLoc->get_args().push_back( makeDerefdVar( varExpr->clone(), varDepth ) );
+				fieldLoc->get_args().push_back( makeOffsetIndex( objectType, i ) );
+
+				delete memberExpr;
+				return fieldLoc;
 			} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType ) ) {
-				memberBase = unionType->get_baseUnion();
+				// union members are all at offset zero, so build appropriately-dereferenced variable
+				Expression *derefdVar = makeDerefdVar( varExpr->clone(), varDepth );
+				delete memberExpr;
+				return derefdVar;
 			} else return memberExpr;
-
-			// look up numeric index of member in base aggregate
-			DeclarationWithType *memberDecl = memberExpr->get_member();
-			std::list< Declaration* > &baseDecls = memberBase->get_members();
-			std::list< Declaration* >::const_iterator decl = baseDecls.begin();
-			unsigned long i = 0;
-			for( ; decl != baseDecls.end(); ++decl, ++i ) {
-				if ( memberDecl->get_name() != (*decl)->get_name() ) continue;
-
-				if ( DeclarationWithType *declWithType = dynamic_cast< DeclarationWithType* >( *decl ) ) {
-					if ( memberDecl->get_mangleName() == declWithType->get_mangleName() ) break;
-					else continue;
-				} else break;
-			}
-			if ( decl == baseDecls.end() ) return memberExpr;
-
-			// replace member expression with pointer to base plus offset
-			// get offset for field
-			std::stringstream offset_namer;
-			offset_namer << i;
-			ConstantExpr *fieldIndex = new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), offset_namer.str() ) );
-			UntypedExpr *fieldOffset = new UntypedExpr( new NameExpr( "?[?]" ) );
-			fieldOffset->get_args().push_back( new NameExpr( offsetofName( objectType ) ) );
-			fieldOffset->get_args().push_back( fieldIndex );
-			// build appropriately-dereferenced variable
-			Expression *derefdVar = varExpr->clone();
-			for ( int i = 1; i < varDepth; ++i ) {
-				UntypedExpr *derefExpr = new UntypedExpr( new NameExpr( "*?" ) );
-				derefExpr->get_args().push_back( derefdVar );
-				derefdVar = derefExpr;
-			}
-			// add offset to deref'd variable
-			UntypedExpr *fieldLoc = new UntypedExpr( new NameExpr( "?+?" ) );
-			fieldLoc->get_args().push_back( derefdVar );
-			fieldLoc->get_args().push_back( fieldOffset );
-
-			delete memberExpr;
-			return fieldLoc;
+		}
+
+		Expression *MemberExprFixer::mutate( OffsetofExpr *offsetofExpr ) {
+			// mutate, exiting early if no longer OffsetofExpr
+			Expression *expr = Mutator::mutate( offsetofExpr );
+			offsetofExpr = dynamic_cast< OffsetofExpr* >( expr );
+			if ( ! offsetofExpr ) return expr;
+
+			// only mutate expressions for polymorphic structs/unions
+			Type *ty = isPolyType( offsetofExpr->get_type(), scopeTyVars );
+			if ( ! ty ) return offsetofExpr;
+
+			if ( StructInstType *structType = dynamic_cast< StructInstType* >( ty ) ) {
+				// replace offsetof expression by index into offset array
+				long i = findMember( offsetofExpr->get_member(), structType->get_baseStruct()->get_members() );
+				if ( i == -1 ) return offsetofExpr;
+
+				Expression *offsetInd = makeOffsetIndex( ty, i );
+				delete offsetofExpr;
+				return offsetInd;
+			} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( ty ) ) {
+				// all union members are at offset zero
+				delete offsetofExpr;
+				return new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), std::string("0") ) );
+			} else return offsetofExpr;
 		}
 
