Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision d419d8ed95449490f82bfab16ccd804501a01278)
+++ src/SymTab/Validate.cc	(revision 48ed81cd8c41ddaf7edb958ec253a29ad6be20b8)
@@ -173,9 +173,11 @@
 	};
 
-	struct EliminateTypedef final : public WithVisitorRef<EliminateTypedef>, public WithGuards {
-		EliminateTypedef() : scopeLevel( 0 ) {}
+	struct ReplaceTypedef final : public WithVisitorRef<ReplaceTypedef>, public WithGuards, public WithShortCircuiting, public WithDeclsToAdd {
+		ReplaceTypedef() : scopeLevel( 0 ) {}
 		/// Replaces typedefs by forward declarations
-		static void eliminateTypedef( std::list< Declaration * > &translationUnit );
-
+		static void replaceTypedef( std::list< Declaration * > &translationUnit );
+
+		void premutate( QualifiedType * );
+		Type * postmutate( QualifiedType * qualType );
 		Type * postmutate( TypeInstType * aggregateUseType );
 		Declaration * postmutate( TypedefDecl * typeDecl );
@@ -188,13 +190,8 @@
 
 		void premutate( CompoundStmt * compoundStmt );
-		CompoundStmt * postmutate( CompoundStmt * compoundStmt );
 
 		void premutate( StructDecl * structDecl );
-		Declaration * postmutate( StructDecl * structDecl );
 		void premutate( UnionDecl * unionDecl );
-		Declaration * postmutate( UnionDecl * unionDecl );
 		void premutate( EnumDecl * enumDecl );
-		Declaration * postmutate( EnumDecl * enumDecl );
-		Declaration * postmutate( TraitDecl * contextDecl );
 
 		void premutate( FunctionType * ftype );
@@ -202,8 +199,7 @@
 	  private:
 		template<typename AggDecl>
-		AggDecl *handleAggregate( AggDecl * aggDecl );
-
-		template<typename AggDecl>
 		void addImplicitTypedef( AggDecl * aggDecl );
+		template< typename AggDecl >
+		void handleAggregate( AggDecl * aggr );
 
 		typedef std::unique_ptr<TypedefDecl> TypedefDeclPtr;
@@ -274,5 +270,5 @@
 
 		acceptAll( translationUnit, hoistDecls );
-		EliminateTypedef::eliminateTypedef( translationUnit );
+		ReplaceTypedef::replaceTypedef( translationUnit );
 		ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
 		acceptAll( translationUnit, epc ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes because it is an indexer and needs correct types for mangling
@@ -731,10 +727,6 @@
 
 
-	bool isTypedef( Declaration *decl ) {
-		return dynamic_cast< TypedefDecl * >( decl );
-	}
-
-	void EliminateTypedef::eliminateTypedef( std::list< Declaration * > &translationUnit ) {
-		PassVisitor<EliminateTypedef> eliminator;
+	void ReplaceTypedef::replaceTypedef( std::list< Declaration * > &translationUnit ) {
+		PassVisitor<ReplaceTypedef> eliminator;
 		mutateAll( translationUnit, eliminator );
 		if ( eliminator.pass.typedefNames.count( "size_t" ) ) {
@@ -746,8 +738,17 @@
 			SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
 		}
-		filter( translationUnit, isTypedef, true );
-	}
-
-	Type * EliminateTypedef::postmutate( TypeInstType * typeInst ) {
+	}
+
+	void ReplaceTypedef::premutate( QualifiedType * ) {
+		visit_children = false;
+	}
+
+	Type * ReplaceTypedef::postmutate( QualifiedType * qualType ) {
+		// replacing typedefs only makes sense for the 'oldest ancestor' of the qualified type
+		qualType->parent = qualType->parent->acceptMutator( *visitor );
+		return qualType;
+	}
+
+	Type * ReplaceTypedef::postmutate( TypeInstType * typeInst ) {
 		// instances of typedef types will come here. If it is an instance
 		// of a typdef type, link the instance to its actual type.
@@ -797,5 +798,5 @@
 	}
 
-	Declaration *EliminateTypedef::postmutate( TypedefDecl * tyDecl ) {
+	Declaration * ReplaceTypedef::postmutate( TypedefDecl * tyDecl ) {
 		if ( typedefNames.count( tyDecl->name ) == 1 && typedefNames[ tyDecl->name ].second == scopeLevel ) {
 			// typedef to the same name from the same scope
@@ -829,15 +830,14 @@
 		Type *designatorType = tyDecl->base->stripDeclarator();
 		if ( StructInstType *aggDecl = dynamic_cast< StructInstType * >( designatorType ) ) {
-			return new StructDecl( aggDecl->name, DeclarationNode::Struct, noAttributes, tyDecl->linkage );
+			declsToAddBefore.push_back( new StructDecl( aggDecl->name, DeclarationNode::Struct, noAttributes, tyDecl->linkage ) );
 		} else if ( UnionInstType *aggDecl = dynamic_cast< UnionInstType * >( designatorType ) ) {
-			return new UnionDecl( aggDecl->name, noAttributes, tyDecl->linkage );
+			declsToAddBefore.push_back( new UnionDecl( aggDecl->name, noAttributes, tyDecl->linkage ) );
 		} else if ( EnumInstType *enumDecl = dynamic_cast< EnumInstType * >( designatorType ) ) {
-			return new EnumDecl( enumDecl->name, noAttributes, tyDecl->linkage );
-		} else {
-			return tyDecl->clone();
-		} // if
-	}
-
-	void EliminateTypedef::premutate( TypeDecl * typeDecl ) {
+			declsToAddBefore.push_back( new EnumDecl( enumDecl->name, noAttributes, tyDecl->linkage ) );
+		} // if
+		return tyDecl->clone();
+	}
+
+	void ReplaceTypedef::premutate( TypeDecl * typeDecl ) {
 		TypedefMap::iterator i = typedefNames.find( typeDecl->name );
 		if ( i != typedefNames.end() ) {
@@ -848,13 +848,13 @@
 	}
 
-	void EliminateTypedef::premutate( FunctionDecl * ) {
+	void ReplaceTypedef::premutate( FunctionDecl * ) {
 		GuardScope( typedefNames );
 	}
 
-	void EliminateTypedef::premutate( ObjectDecl * ) {
+	void ReplaceTypedef::premutate( ObjectDecl * ) {
 		GuardScope( typedefNames );
 	}
 
-	DeclarationWithType *EliminateTypedef::postmutate( ObjectDecl * objDecl ) {
+	DeclarationWithType * ReplaceTypedef::postmutate( ObjectDecl * objDecl ) {
 		if ( FunctionType *funtype = dynamic_cast<FunctionType *>( objDecl->type ) ) { // function type?
 			// replace the current object declaration with a function declaration
@@ -868,9 +868,9 @@
 	}
 
-	void EliminateTypedef::premutate( CastExpr * ) {
+	void ReplaceTypedef::premutate( CastExpr * ) {
 		GuardScope( typedefNames );
 	}
 
-	void EliminateTypedef::premutate( CompoundStmt * ) {
+	void ReplaceTypedef::premutate( CompoundStmt * ) {
 		GuardScope( typedefNames );
 		scopeLevel += 1;
@@ -878,27 +878,6 @@
 	}
 
-	CompoundStmt *EliminateTypedef::postmutate( CompoundStmt * compoundStmt ) {
-		// remove and delete decl stmts
-		filter( compoundStmt->kids, [](Statement * stmt) {
-			if ( DeclStmt *declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
-				if ( dynamic_cast< TypedefDecl * >( declStmt->decl ) ) {
-					return true;
-				} // if
-			} // if
-			return false;
-		}, true);
-		return compoundStmt;
-	}
-
-	// there may be typedefs nested within aggregates. in order for everything to work properly, these should be removed
-	// as well
 	template<typename AggDecl>
-	AggDecl *EliminateTypedef::handleAggregate( AggDecl * aggDecl ) {
-		filter( aggDecl->members, isTypedef, true );
-		return aggDecl;
-	}
-
-	template<typename AggDecl>
-	void EliminateTypedef::addImplicitTypedef( AggDecl * aggDecl ) {
+	void ReplaceTypedef::addImplicitTypedef( AggDecl * aggDecl ) {
 		if ( typedefNames.count( aggDecl->get_name() ) == 0 ) {
 			Type *type = nullptr;
@@ -912,37 +891,55 @@
 			TypedefDeclPtr tyDecl( new TypedefDecl( aggDecl->get_name(), aggDecl->location, Type::StorageClasses(), type, aggDecl->get_linkage() ) );
 			typedefNames[ aggDecl->get_name() ] = std::make_pair( std::move( tyDecl ), scopeLevel );
-		} // if
-	}
-
-	void EliminateTypedef::premutate( StructDecl * structDecl ) {
+			// add the implicit typedef to the AST
+			declsToAddBefore.push_back( new TypedefDecl( aggDecl->get_name(), aggDecl->location, Type::StorageClasses(), type->clone(), aggDecl->get_linkage() ) );
+		} // if
+	}
+
+	template< typename AggDecl >
+	void ReplaceTypedef::handleAggregate( AggDecl * aggr ) {
+		SemanticErrorException errors;
+
+		ValueGuard< std::list<Declaration * > > oldBeforeDecls( declsToAddBefore );
+		ValueGuard< std::list<Declaration * > > oldAfterDecls ( declsToAddAfter  );
+		declsToAddBefore.clear();
+		declsToAddAfter.clear();
+
+		GuardScope( typedefNames );
+		mutateAll( aggr->parameters, *visitor );
+
+		// unroll mutateAll for aggr->members so that implicit typedefs for nested types are added to the aggregate body.
+		for ( std::list< Declaration * >::iterator i = aggr->members.begin(); i != aggr->members.end(); ++i ) {
+			if ( !declsToAddAfter.empty() ) { aggr->members.splice( i, declsToAddAfter ); }
+
+			try {
+				*i = maybeMutate( *i, *visitor );
+			} catch ( SemanticErrorException &e ) {
+				errors.append( e );
+			}
+
+			if ( !declsToAddBefore.empty() ) { aggr->members.splice( i, declsToAddBefore ); }
+		}
+
+		if ( !declsToAddAfter.empty() ) { aggr->members.splice( aggr->members.end(), declsToAddAfter ); }
+		if ( !errors.isEmpty() ) { throw errors; }
+	}
+
+	void ReplaceTypedef::premutate( StructDecl * structDecl ) {
+		visit_children = false;
 		addImplicitTypedef( structDecl );
-	}
-
-
-	Declaration *EliminateTypedef::postmutate( StructDecl * structDecl ) {
-		return handleAggregate( structDecl );
-	}
-
-	void EliminateTypedef::premutate( UnionDecl * unionDecl ) {
+		handleAggregate( structDecl );
+	}
+
+	void ReplaceTypedef::premutate( UnionDecl * unionDecl ) {
+		visit_children = false;
 		addImplicitTypedef( unionDecl );
-	}
-
-	Declaration *EliminateTypedef::postmutate( UnionDecl * unionDecl ) {
-		return handleAggregate( unionDecl );
-	}
-
-	void EliminateTypedef::premutate( EnumDecl * enumDecl ) {
+		handleAggregate( unionDecl );
+	}
+
+	void ReplaceTypedef::premutate( EnumDecl * enumDecl ) {
 		addImplicitTypedef( enumDecl );
 	}
 
-	Declaration *EliminateTypedef::postmutate( EnumDecl * enumDecl ) {
-		return handleAggregate( enumDecl );
-	}
-
-	Declaration *EliminateTypedef::postmutate( TraitDecl * traitDecl ) {
-		return handleAggregate( traitDecl );
-	}
-
-	void EliminateTypedef::premutate( FunctionType * ) {
+	void ReplaceTypedef::premutate( FunctionType * ) {
 		GuardValue( inFunctionType );
 		inFunctionType = true;
