Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 70d826cd91250522cc2c47b0fdb237bd3ca2fde5)
+++ src/SymTab/Validate.cc	(revision a506df4491ac8c4833409d2d89a5029078041055)
@@ -176,23 +176,30 @@
 	};
 
-	class EliminateTypedef : public Mutator {
-	  public:
+	struct EliminateTypedef final : public WithVisitorRef<EliminateTypedef>, public WithGuards {
 		EliminateTypedef() : scopeLevel( 0 ) {}
 		/// Replaces typedefs by forward declarations
 		static void eliminateTypedef( std::list< Declaration * > &translationUnit );
+
+		Type * postmutate( TypeInstType * aggregateUseType );
+		Declaration * postmutate( TypedefDecl * typeDecl );
+		void premutate( TypeDecl * typeDecl );
+		void premutate( FunctionDecl * funcDecl );
+		void premutate( ObjectDecl * objDecl );
+		DeclarationWithType * postmutate( ObjectDecl * objDecl );
+
+		void premutate( CastExpr * castExpr );
+
+		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 );
+
 	  private:
-		virtual Declaration *mutate( TypedefDecl *typeDecl );
-		virtual TypeDecl *mutate( TypeDecl *typeDecl );
-		virtual DeclarationWithType *mutate( FunctionDecl *funcDecl );
-		virtual DeclarationWithType *mutate( ObjectDecl *objDecl );
-		virtual CompoundStmt *mutate( CompoundStmt *compoundStmt );
-		virtual Type *mutate( TypeInstType *aggregateUseType );
-		virtual Expression *mutate( CastExpr *castExpr );
-
-		virtual Declaration *mutate( StructDecl * structDecl );
-		virtual Declaration *mutate( UnionDecl * unionDecl );
-		virtual Declaration *mutate( EnumDecl * enumDecl );
-		virtual Declaration *mutate( TraitDecl * contextDecl );
-
 		template<typename AggDecl>
 		AggDecl *handleAggregate( AggDecl * aggDecl );
@@ -667,9 +674,9 @@
 
 	void EliminateTypedef::eliminateTypedef( std::list< Declaration * > &translationUnit ) {
-		EliminateTypedef eliminator;
+		PassVisitor<EliminateTypedef> eliminator;
 		mutateAll( translationUnit, eliminator );
-		if ( eliminator.typedefNames.count( "size_t" ) ) {
+		if ( eliminator.pass.typedefNames.count( "size_t" ) ) {
 			// grab and remember declaration of size_t
-			SizeType = eliminator.typedefNames["size_t"].first->get_base()->clone();
+			SizeType = eliminator.pass.typedefNames["size_t"].first->get_base()->clone();
 		} else {
 			// xxx - missing global typedef for size_t - default to long unsigned int, even though that may be wrong
@@ -681,5 +688,5 @@
 	}
 
-	Type *EliminateTypedef::mutate( TypeInstType * typeInst ) {
+	Type * EliminateTypedef::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.
@@ -696,5 +703,5 @@
 				rtt->get_parameters().clear();
 				cloneAll( typeInst->get_parameters(), rtt->get_parameters() );
-				mutateAll( rtt->get_parameters(), *this );  // recursively fix typedefs on parameters
+				mutateAll( rtt->get_parameters(), *visitor );  // recursively fix typedefs on parameters
 			} // if
 			delete typeInst;
@@ -708,7 +715,5 @@
 	}
 
-	Declaration *EliminateTypedef::mutate( TypedefDecl * tyDecl ) {
-		Declaration *ret = Mutator::mutate( tyDecl );
-
+	Declaration *EliminateTypedef::postmutate( TypedefDecl * tyDecl ) {
 		if ( typedefNames.count( tyDecl->get_name() ) == 1 && typedefNames[ tyDecl->get_name() ].second == scopeLevel ) {
 			// typedef to the same name from the same scope
@@ -741,9 +746,9 @@
 			return new EnumDecl( enumDecl->get_name(), noAttributes, tyDecl->get_linkage() );
 		} else {
-			return ret->clone();
-		} // if
-	}
-
-	TypeDecl *EliminateTypedef::mutate( TypeDecl * typeDecl ) {
+			return tyDecl->clone();
+		} // if
+	}
+
+	void EliminateTypedef::premutate( TypeDecl * typeDecl ) {
 		TypedefMap::iterator i = typedefNames.find( typeDecl->get_name() );
 		if ( i != typedefNames.end() ) {
@@ -752,22 +757,18 @@
 
 		typedeclNames[ typeDecl->get_name() ] = typeDecl;
-		return dynamic_cast<TypeDecl *>( Mutator::mutate( typeDecl ) );
-	}
-
-	DeclarationWithType *EliminateTypedef::mutate( FunctionDecl * funcDecl ) {
-		typedefNames.beginScope();
-		DeclarationWithType *ret = Mutator::mutate( funcDecl );
-		typedefNames.endScope();
-		return ret;
-	}
-
-	DeclarationWithType *EliminateTypedef::mutate( ObjectDecl * objDecl ) {
-		typedefNames.beginScope();
-		DeclarationWithType *ret = Mutator::mutate( objDecl );
-		typedefNames.endScope();
-
-		if ( FunctionType *funtype = dynamic_cast<FunctionType *>( ret->get_type() ) ) { // function type?
+	}
+
+	void EliminateTypedef::premutate( FunctionDecl * ) {
+		GuardScope( typedefNames );
+	}
+
+	void EliminateTypedef::premutate( ObjectDecl * ) {
+		GuardScope( typedefNames );
+	}
+
+	DeclarationWithType *EliminateTypedef::postmutate( ObjectDecl * objDecl ) {
+		if ( FunctionType *funtype = dynamic_cast<FunctionType *>( objDecl->get_type() ) ) { // function type?
 			// replace the current object declaration with a function declaration
-			FunctionDecl * newDecl = new FunctionDecl( ret->get_name(), ret->get_storageClasses(), ret->get_linkage(), funtype, 0, objDecl->get_attributes(), ret->get_funcSpec() );
+			FunctionDecl * newDecl = new FunctionDecl( objDecl->get_name(), objDecl->get_storageClasses(), objDecl->get_linkage(), funtype, 0, objDecl->get_attributes(), objDecl->get_funcSpec() );
 			objDecl->get_attributes().clear();
 			objDecl->set_type( nullptr );
@@ -775,19 +776,18 @@
 			return newDecl;
 		} // if
-		return ret;
-	}
-
-	Expression *EliminateTypedef::mutate( CastExpr * castExpr ) {
-		typedefNames.beginScope();
-		Expression *ret = Mutator::mutate( castExpr );
-		typedefNames.endScope();
-		return ret;
-	}
-
-	CompoundStmt *EliminateTypedef::mutate( CompoundStmt * compoundStmt ) {
-		typedefNames.beginScope();
+		return objDecl;
+	}
+
+	void EliminateTypedef::premutate( CastExpr * ) {
+		GuardScope( typedefNames );
+	}
+
+	void EliminateTypedef::premutate( CompoundStmt * ) {
+		GuardScope( typedefNames );
 		scopeLevel += 1;
-		CompoundStmt *ret = Mutator::mutate( compoundStmt );
-		scopeLevel -= 1;
+		GuardAction( [this](){ scopeLevel -= 1; } );
+	}
+
+	CompoundStmt *EliminateTypedef::postmutate( CompoundStmt * compoundStmt ) {
 		// remove and delete decl stmts
 		filter( compoundStmt->kids, [](Statement * stmt) {
@@ -799,6 +799,5 @@
 			return false;
 		}, true);
-		typedefNames.endScope();
-		return ret;
+		return compoundStmt;
 	}
 
@@ -827,25 +826,31 @@
 	}
 
-	Declaration *EliminateTypedef::mutate( StructDecl * structDecl ) {
+	void EliminateTypedef::premutate( StructDecl * structDecl ) {
 		addImplicitTypedef( structDecl );
-		Mutator::mutate( structDecl );
+	}
+
+
+	Declaration *EliminateTypedef::postmutate( StructDecl * structDecl ) {
 		return handleAggregate( structDecl );
 	}
 
-	Declaration *EliminateTypedef::mutate( UnionDecl * unionDecl ) {
+	void EliminateTypedef::premutate( UnionDecl * unionDecl ) {
 		addImplicitTypedef( unionDecl );
-		Mutator::mutate( unionDecl );
+	}
+
+	Declaration *EliminateTypedef::postmutate( UnionDecl * unionDecl ) {
 		return handleAggregate( unionDecl );
 	}
 
-	Declaration *EliminateTypedef::mutate( EnumDecl * enumDecl ) {
+	void EliminateTypedef::premutate( EnumDecl * enumDecl ) {
 		addImplicitTypedef( enumDecl );
-		Mutator::mutate( enumDecl );
+	}
+
+	Declaration *EliminateTypedef::postmutate( EnumDecl * enumDecl ) {
 		return handleAggregate( enumDecl );
 	}
 
-	Declaration *EliminateTypedef::mutate( TraitDecl * contextDecl ) {
-		Mutator::mutate( contextDecl );
-		return handleAggregate( contextDecl );
+	Declaration *EliminateTypedef::postmutate( TraitDecl * traitDecl ) {
+		return handleAggregate( traitDecl );
 	}
 
