Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 15f5c5e6f56393ba5dce4777919465f0b132b585)
+++ src/SymTab/Validate.cc	(revision d419d8ed95449490f82bfab16ccd804501a01278)
@@ -95,4 +95,7 @@
 		void previsit( UnionDecl * aggregateDecl );
 		void previsit( StaticAssertDecl * assertDecl );
+		void previsit( StructInstType * type );
+		void previsit( UnionInstType * type );
+		void previsit( EnumInstType * type );
 
 	  private:
@@ -339,7 +342,23 @@
 	}
 
+	namespace {
+		void qualifiedName( AggregateDecl * aggr, std::ostringstream & ss ) {
+			if ( aggr->parent ) qualifiedName( aggr->parent, ss );
+			ss << "__" << aggr->name;
+		}
+
+		// mangle nested type names using entire parent chain
+		std::string qualifiedName( AggregateDecl * aggr ) {
+			std::ostringstream ss;
+			qualifiedName( aggr, ss );
+			return ss.str();
+		}
+	}
+
 	template< typename AggDecl >
 	void HoistStruct::handleAggregate( AggDecl *aggregateDecl ) {
 		if ( parentAggr ) {
+			aggregateDecl->parent = parentAggr;
+			aggregateDecl->name = qualifiedName( aggregateDecl );
 			// Add elements in stack order corresponding to nesting structure.
 			declsToAddBefore.push_front( aggregateDecl );
@@ -365,4 +384,21 @@
 		handleAggregate( aggregateDecl );
 	}
+
+	void HoistStruct::previsit( StructInstType * type ) {
+		// need to reset type name after expanding to qualified name
+		assert( type->baseStruct );
+		type->name = type->baseStruct->name;
+	}
+
+	void HoistStruct::previsit( UnionInstType * type ) {
+		assert( type->baseUnion );
+		type->name = type->baseUnion->name;
+	}
+
+	void HoistStruct::previsit( EnumInstType * type ) {
+		assert( type->baseEnum );
+		type->name = type->baseEnum->name;
+	}
+
 
 	void EnumAndPointerDecay::previsit( EnumDecl *enumDecl ) {
