Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 1f37045134019dcc85ce9bbfe573c87275cfb714)
+++ src/SymTab/Validate.cc	(revision a09e45b1ba904ce92f02b3ad9409aa1c53244ed8)
@@ -81,30 +81,18 @@
 
 namespace SymTab {
-	class HoistStruct final : public Visitor {
-		template< typename Visitor >
-		friend void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor );
-	    template< typename Visitor >
-	    friend void addVisitStatementList( std::list< Statement* > &stmts, Visitor &visitor );
-	  public:
+	struct HoistStruct final : public WithDeclsToAdd, public WithGuards {
 		/// Flattens nested struct types
 		static void hoistStruct( std::list< Declaration * > &translationUnit );
 
-		std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
-
-		virtual void visit( EnumInstType *enumInstType );
-		virtual void visit( StructInstType *structInstType );
-		virtual void visit( UnionInstType *unionInstType );
-		virtual void visit( StructDecl *aggregateDecl );
-		virtual void visit( UnionDecl *aggregateDecl );
-
-		virtual void visit( CompoundStmt *compoundStmt );
-		virtual void visit( SwitchStmt *switchStmt );
+		void previsit( EnumInstType * enumInstType );
+		void previsit( StructInstType * structInstType );
+		void previsit( UnionInstType * unionInstType );
+		void previsit( StructDecl * aggregateDecl );
+		void previsit( UnionDecl * aggregateDecl );
+
 	  private:
-		HoistStruct();
-
 		template< typename AggDecl > void handleAggregate( AggDecl *aggregateDecl );
 
-		std::list< Declaration * > declsToAdd, declsToAddAfter;
-		bool inStruct;
+		bool inStruct = false;
 	};
 
@@ -305,9 +293,6 @@
 
 	void HoistStruct::hoistStruct( std::list< Declaration * > &translationUnit ) {
-		HoistStruct hoister;
-		acceptAndAdd( translationUnit, hoister );
-	}
-
-	HoistStruct::HoistStruct() : inStruct( false ) {
+		PassVisitor<HoistStruct> hoister;
+		acceptAll( translationUnit, hoister );
 	}
 
@@ -320,47 +305,37 @@
 		if ( inStruct ) {
 			// Add elements in stack order corresponding to nesting structure.
-			declsToAdd.push_front( aggregateDecl );
-			Visitor::visit( aggregateDecl );
+			declsToAddBefore.push_front( aggregateDecl );
 		} else {
+			GuardValue( inStruct );
 			inStruct = true;
-			Visitor::visit( aggregateDecl );
-			inStruct = false;
 		} // if
 		// Always remove the hoisted aggregate from the inner structure.
-		filter( aggregateDecl->get_members(), isStructOrUnion, false );
-	}
-
-	void HoistStruct::visit( EnumInstType *structInstType ) {
-		if ( structInstType->get_baseEnum() ) {
-			declsToAdd.push_front( structInstType->get_baseEnum() );
-		}
-	}
-
-	void HoistStruct::visit( StructInstType *structInstType ) {
-		if ( structInstType->get_baseStruct() ) {
-			declsToAdd.push_front( structInstType->get_baseStruct() );
-		}
-	}
-
-	void HoistStruct::visit( UnionInstType *structInstType ) {
-		if ( structInstType->get_baseUnion() ) {
-			declsToAdd.push_front( structInstType->get_baseUnion() );
-		}
-	}
-
-	void HoistStruct::visit( StructDecl *aggregateDecl ) {
+		GuardAction( [this, aggregateDecl]() { filter( aggregateDecl->members, isStructOrUnion, false ); } );
+	}
+
+	void HoistStruct::previsit( EnumInstType * inst ) {
+		if ( inst->baseEnum ) {
+			declsToAddBefore.push_front( inst->baseEnum );
+		}
+	}
+
+	void HoistStruct::previsit( StructInstType * inst ) {
+		if ( inst->baseStruct ) {
+			declsToAddBefore.push_front( inst->baseStruct );
+		}
+	}
+
+	void HoistStruct::previsit( UnionInstType * inst ) {
+		if ( inst->baseUnion ) {
+			declsToAddBefore.push_front( inst->baseUnion );
+		}
+	}
+
+	void HoistStruct::previsit( StructDecl * aggregateDecl ) {
 		handleAggregate( aggregateDecl );
 	}
 
-	void HoistStruct::visit( UnionDecl *aggregateDecl ) {
+	void HoistStruct::previsit( UnionDecl * aggregateDecl ) {
 		handleAggregate( aggregateDecl );
-	}
-
-	void HoistStruct::visit( CompoundStmt *compoundStmt ) {
-		addVisit( compoundStmt, *this );
-	}
-
-	void HoistStruct::visit( SwitchStmt *switchStmt ) {
-		addVisit( switchStmt, *this );
 	}
 
