Index: src/SymTab/AddVisit.h
===================================================================
--- src/SymTab/AddVisit.h	(revision 81644e025cbf854af3550d54b343f22ec9ec8f05)
+++ src/SymTab/AddVisit.h	(revision 3ca540ff8fca8be28ec085a72a11b96bf920dd76)
@@ -24,5 +24,5 @@
 			// add any new declarations after the previous statement
 			for ( std::list< Declaration* >::iterator decl = visitor.declsToAddAfter.begin(); decl != visitor.declsToAddAfter.end(); ++decl ) {
-				DeclStmt *declStmt = new DeclStmt( noLabels, *decl );
+				DeclStmt *declStmt = new DeclStmt( *decl );
 				stmts.insert( stmt, declStmt );
 			}
@@ -36,5 +36,5 @@
 			// add any new declarations before the statement
 			for ( std::list< Declaration* >::iterator decl = visitor.declsToAdd.begin(); decl != visitor.declsToAdd.end(); ++decl ) {
-				DeclStmt *declStmt = new DeclStmt( noLabels, *decl );
+				DeclStmt *declStmt = new DeclStmt( *decl );
 				stmts.insert( stmt, declStmt );
 			}
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision 81644e025cbf854af3550d54b343f22ec9ec8f05)
+++ src/SymTab/Autogen.cc	(revision 3ca540ff8fca8be28ec085a72a11b96bf920dd76)
@@ -264,5 +264,5 @@
 		Type::StorageClasses scs = functionNesting > 0 ? Type::StorageClasses() : Type::StorageClasses( Type::Static );
 		LinkageSpec::Spec spec = isIntrinsic ? LinkageSpec::Intrinsic : LinkageSpec::AutoGen;
-		FunctionDecl * decl = new FunctionDecl( fname, scs, spec, ftype, new CompoundStmt( noLabels ),
+		FunctionDecl * decl = new FunctionDecl( fname, scs, spec, ftype, new CompoundStmt(),
 												std::list< Attribute * >(), Type::FuncSpecifiers( Type::Inline ) );
 		decl->fixUniqueId();
@@ -299,5 +299,5 @@
 				assert( assignType->returnVals.size() == 1 );
 				ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( assignType->parameters.front() );
-				dcl->statements->push_back( new ReturnStmt( noLabels, new VariableExpr( dstParam ) ) );
+				dcl->statements->push_back( new ReturnStmt( new VariableExpr( dstParam ) ) );
 			}
 			resolve( dcl );
@@ -468,5 +468,5 @@
 		copy->args.push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
 		copy->args.push_back( new SizeofExpr( srcParam->get_type()->clone() ) );
-		*out++ = new ExprStmt( noLabels, copy );
+		*out++ = new ExprStmt( copy );
 	}
 
@@ -544,5 +544,5 @@
 			callExpr->get_args().push_back( new VariableExpr( dstParam ) );
 			callExpr->get_args().push_back( new VariableExpr( srcParam ) );
-			funcDecl->statements->push_back( new ExprStmt( noLabels, callExpr ) );
+			funcDecl->statements->push_back( new ExprStmt( callExpr ) );
 		} else {
 			// default ctor/dtor body is empty - add unused attribute to parameter to silence warnings
@@ -569,5 +569,5 @@
 		expr->args.push_back( new CastExpr( new VariableExpr( dst ), new ReferenceType( Type::Qualifiers(), typeDecl->base->clone() ) ) );
 		if ( src ) expr->args.push_back( new CastExpr( new VariableExpr( src ), typeDecl->base->clone() ) );
-		dcl->statements->kids.push_back( new ExprStmt( noLabels, expr ) );
+		dcl->statements->kids.push_back( new ExprStmt( expr ) );
 	};
 
@@ -664,6 +664,6 @@
 			untyped->get_args().push_back( new VariableExpr( ftype->get_parameters().back() ) );
 		}
-		function->get_statements()->get_kids().push_back( new ExprStmt( noLabels, untyped ) );
-		function->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, UntypedExpr::createDeref( new VariableExpr( ftype->get_parameters().front() ) ) ) );
+		function->get_statements()->get_kids().push_back( new ExprStmt( untyped ) );
+		function->get_statements()->get_kids().push_back( new ReturnStmt( UntypedExpr::createDeref( new VariableExpr( ftype->get_parameters().front() ) ) ) );
 	}
 
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision 81644e025cbf854af3550d54b343f22ec9ec8f05)
+++ src/SymTab/Autogen.h	(revision 3ca540ff8fca8be28ec085a72a11b96bf920dd76)
@@ -104,5 +104,5 @@
 		fExpr->args.splice( fExpr->args.end(), args );
 
-		*out++ = new ExprStmt( noLabels, fExpr );
+		*out++ = new ExprStmt( fExpr );
 
 		srcParam.clearArrayIndices();
@@ -162,13 +162,13 @@
 
 		// for stmt's body, eventually containing call
-		CompoundStmt * body = new CompoundStmt( noLabels );
+		CompoundStmt * body = new CompoundStmt();
 		Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->kids ), array->base, addCast, forward );
 
 		// block containing for stmt and index variable
 		std::list<Statement *> initList;
-		CompoundStmt * block = new CompoundStmt( noLabels );
-		block->push_back( new DeclStmt( noLabels, index ) );
+		CompoundStmt * block = new CompoundStmt();
+		block->push_back( new DeclStmt( index ) );
 		if ( listInit ) block->get_kids().push_back( listInit );
-		block->push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
+		block->push_back( new ForStmt( initList, cond, inc, body ) );
 
 		*out++ = block;
Index: src/SymTab/ImplementationType.cc
===================================================================
--- src/SymTab/ImplementationType.cc	(revision 81644e025cbf854af3550d54b343f22ec9ec8f05)
+++ 	(revision )
@@ -1,114 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// ImplementationType.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 21:32:01 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 16 15:54:08 2017
-// Update Count     : 4
-//
-
-#include "ImplementationType.h"
-
-#include <list>                   // for list, _List_iterator, list<>::iterator
-
-#include "SymTab/Indexer.h"       // for Indexer
-#include "SynTree/Declaration.h"  // for NamedTypeDecl
-#include "SynTree/Type.h"         // for TupleType, Type, ArrayType, Pointer...
-#include "SynTree/Visitor.h"      // for Visitor
-
-
-namespace SymTab {
-	class ImplementationType : public Visitor {
-	  public:
-		ImplementationType( const SymTab::Indexer &indexer );
-
-		Type *get_result() { return result; }
-	  private:
-		virtual void visit(VoidType *voidType);
-		virtual void visit(BasicType *basicType);
-		virtual void visit(PointerType *pointerType);
-		virtual void visit(ArrayType *arrayType);
-		virtual void visit(FunctionType *functionType);
-		virtual void visit(StructInstType *aggregateUseType);
-		virtual void visit(UnionInstType *aggregateUseType);
-		virtual void visit(EnumInstType *aggregateUseType);
-		virtual void visit(TraitInstType *aggregateUseType);
-		virtual void visit(TypeInstType *aggregateUseType);
-		virtual void visit(TupleType *tupleType);
-		virtual void visit(VarArgsType *varArgsType);
-		virtual void visit(ZeroType *zeroType);
-		virtual void visit(OneType *oneType);
-
-		Type *result;			// synthesized
-		const SymTab::Indexer &indexer;
-	};
-
-	Type * implementationType( Type *type, const SymTab::Indexer& indexer ) {
-		ImplementationType implementor( indexer );
-		type->accept( implementor );
-		if ( implementor.get_result() == 0 ) {
-			return type->clone();
-		} else {
-			return implementor.get_result();
-		} // if
-	}
-
-	ImplementationType::ImplementationType( const SymTab::Indexer &indexer ) : result( 0 ), indexer( indexer ) {
-	}
-
-	void ImplementationType::visit( __attribute__((unused)) VoidType *voidType ) {}
-	void ImplementationType::visit( __attribute__((unused)) BasicType *basicType ) {}
-
-	void ImplementationType::visit(PointerType *pointerType) {
-		PointerType *newType = pointerType->clone();
-		newType->set_base( implementationType( pointerType->get_base(), indexer ) );
-		result = newType;
-	}
-
-	void ImplementationType::visit(ArrayType *arrayType) {
-		ArrayType *newType = arrayType->clone();
-		newType->set_base( implementationType( arrayType->get_base(), indexer ) );
-		result = newType;
-	}
-
-	void ImplementationType::visit( __attribute__((unused)) FunctionType *functionType ) {}
-	void ImplementationType::visit( __attribute__((unused)) StructInstType * aggregateUseType ) {}
-	void ImplementationType::visit( __attribute__((unused)) UnionInstType * aggregateUseType ) {}
-	void ImplementationType::visit( __attribute__((unused)) EnumInstType * aggregateUseType ) {}
-	void ImplementationType::visit( __attribute__((unused)) TraitInstType * aggregateUseType ) {}
-
-	void ImplementationType::visit(TypeInstType *inst) {
-		NamedTypeDecl *typeDecl = indexer.lookupType( inst->get_name() );
-		if ( typeDecl && typeDecl->get_base() ) {
-			Type *base = implementationType( typeDecl->get_base(), indexer );
-			base->get_qualifiers() |= inst->get_qualifiers();
-			result = base;
-		} // if
-	}
-
-	void ImplementationType::visit(TupleType *tupleType) {
-		std::list< Type * > types;
-		for ( std::list< Type* >::iterator i = tupleType->get_types().begin(); i != tupleType->get_types().end(); ++i ) {
-			Type *implType = implementationType( *i, indexer );
-			implType->get_qualifiers() |= tupleType->get_qualifiers();
-			types.push_back( implType );
-		} // for
-		result = new TupleType( Type::Qualifiers(), types );
-	}
-
-	void ImplementationType::visit( __attribute__((unused)) VarArgsType *varArgsType ) {}
-	void ImplementationType::visit( __attribute__((unused)) ZeroType *zeroType ) {}
-	void ImplementationType::visit( __attribute__((unused)) OneType *oneType ) {}
-} // namespace SymTab
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/SymTab/ImplementationType.h
===================================================================
--- src/SymTab/ImplementationType.h	(revision 81644e025cbf854af3550d54b343f22ec9ec8f05)
+++ 	(revision )
@@ -1,37 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// ImplementationType.h -- 
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 21:35:41 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul 22 09:46:19 2017
-// Update Count     : 3
-//
-
-#pragma once
-
-class Type;
-
-namespace SymTab {
-class Indexer;
-
-	Type *implementationType( Type *, const SymTab::Indexer &indexer );
-
-	template< typename InputIterator, typename OutputIterator >
-	void implementationTypeList( InputIterator begin, InputIterator end, OutputIterator out, const SymTab::Indexer &indexer ) {
-		while ( begin != end ) {
-			*out++ = implementationType( *begin++, indexer );
-		} // while
-	}
-} // namespace SymTab
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/SymTab/TypeEquality.cc
===================================================================
--- src/SymTab/TypeEquality.cc	(revision 81644e025cbf854af3550d54b343f22ec9ec8f05)
+++ 	(revision )
@@ -1,218 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// TypeEquality.cc --
-//
-// Author           : Rob Schluntz
-// Created On       : Tue Jul 07 16:28:29 2015
-// Last Modified By : Rob Schluntz
-// Last Modified On : Mon Jul 20 14:16:11 2015
-// Update Count     : 37
-//
-#include "TypeEquality.h"
-
-#include <cassert>                // for assert
-#include <list>                   // for list, list<>::iterator, _List_iterator
-#include <string>                 // for operator==, string, basic_string
-
-#include "SynTree/Constant.h"     // for Constant
-#include "SynTree/Declaration.h"  // for DeclarationWithType
-#include "SynTree/Expression.h"   // for ConstantExpr, Expression
-#include "SynTree/Type.h"         // for Type, ArrayType, FunctionType, Enum...
-#include "SynTree/Visitor.h"      // for Visitor
-
-namespace SymTab {
-	class TypeEquality : public Visitor {
-  public:
-		TypeEquality( Type * other, bool vlaErr ) : result( true ), other( other ),
-			vlaErr( vlaErr ) {}
-		bool result;
-
-  private:
-		virtual void visit( FunctionType *funcType );
-		virtual void visit( VoidType *voidType );
-		virtual void visit( BasicType *basicType );
-		virtual void visit( PointerType *pointerType );
-		virtual void visit( ArrayType *arrayType );
-		virtual void visit( StructInstType *structInst );
-		virtual void visit( UnionInstType *unionInst );
-		virtual void visit( EnumInstType *enumInst );
-		virtual void visit( TypeInstType *typeInst );
-		virtual void visit( VarArgsType *varArgsType );
-		virtual void visit( ZeroType *zeroType );
-		virtual void visit( OneType *oneType );
-
-		void handleQualifiers( Type * t );
-
-		Type * other;
-		bool vlaErr;
-	};
-
-	bool typeEquals( Type * t1, Type * t2, bool vlaErr ) {
-		TypeEquality teq( t2, vlaErr );
-		t1->accept( teq );
-		return teq.result;
-	}
-
-	void TypeEquality::handleQualifiers( Type * t ) {
-		result = result && t->get_qualifiers() == other->get_qualifiers();
-	}
-
-	void TypeEquality::visit( VoidType *voidType ) {
-		handleQualifiers( voidType );
-		if ( ! dynamic_cast< VoidType * >( other ) ) {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( BasicType *basicType ) {
-		handleQualifiers( basicType );
-		if ( BasicType * bt = dynamic_cast< BasicType * >( other ) ) {
-			result = result && basicType->get_kind() == bt->get_kind();
-		} else {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( PointerType *pointerType ) {
-		handleQualifiers( pointerType );
-		if ( PointerType * pt = dynamic_cast< PointerType * >( other ) ) {
-			other = pt->get_base();
-			pointerType->get_base()->accept( *this );
-		} else {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( ArrayType *arrayType ) {
-		handleQualifiers( arrayType );
-
-		if ( ArrayType * at = dynamic_cast< ArrayType * >( other ) ) {
-			// to be equal, array types must both be VLA or both not VLA
-			// and must both have a dimension expression or not have a dimension
-			result = result	&& arrayType->get_isVarLen() == at->get_isVarLen()
-				&& ((arrayType->get_dimension() != 0 && at->get_dimension() != 0)
-					|| (arrayType->get_dimension() == 0 && at->get_dimension() == 0));
-
-			if ( vlaErr ) {
-				// useful for comparing typedef types - in this case, we
-				// want types to appear distinct if either is a VLA type
-				if ( arrayType->get_isVarLen() || at->get_isVarLen() ) {
-					result = false;
-				}
-			}
-
-			if ( ! arrayType->get_isVarLen() && ! at->get_isVarLen() &&
-				arrayType->get_dimension() != 0 && at->get_dimension() != 0 ) {
-				ConstantExpr * ce1 = dynamic_cast< ConstantExpr * >( arrayType->get_dimension() );
-				ConstantExpr * ce2 = dynamic_cast< ConstantExpr * >( at->get_dimension() );
-				assert(ce1 && ce2);
-
-				Constant * c1 = ce1->get_constant();
-				Constant * c2 = ce2->get_constant();
-
-				result = result && c1->get_value() == c2->get_value();
-			}
-
-			other = at->get_base();
-			arrayType->get_base()->accept( *this );
-		} else {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( FunctionType *funcType ) {
-		handleQualifiers( funcType );
-
-		if ( FunctionType * ft = dynamic_cast< FunctionType * >( other ) ) {
-			// function types must have the same number of return types
-			// and parameters to be equivalent
-			result = result && funcType->get_returnVals().size() == ft->get_returnVals().size()
-				&& funcType->get_parameters().size() == ft->get_parameters().size()
-				&& funcType->get_isVarArgs() == ft->get_isVarArgs();
-
-			std::list< DeclarationWithType * >::iterator it1, it2;
-
-			// return types must be equivalent
-			it1 = funcType->get_returnVals().begin();
-			it2 = ft->get_returnVals().begin();
-			for ( ; it1 != funcType->get_returnVals().end(); ++it1, ++it2 ) {
-				if ( ! result ) return;
-				other = (*it2)->get_type();
-				(*it1)->get_type()->accept( *this );
-			}
-
-			// parameter types must be equivalent
-			it1 = funcType->get_parameters().begin();
-			it2 = ft->get_parameters().begin();
-			for ( ; it1 != funcType->get_parameters().end(); ++it1, ++it2 ) {
-				if ( ! result ) return;
-				other = (*it2)->get_type();
-				(*it1)->get_type()->accept( *this );
-			}
-		} else {
-			result = false;
-		}
-	}
-
-	// aggregate types only need to have the same name
-	void TypeEquality::visit( StructInstType *structInst )  {
-		handleQualifiers( structInst );
-		if ( StructInstType * st = dynamic_cast< StructInstType * >( other ) ) {
-			result = result && structInst->get_name() == st->get_name();
-		} else {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( UnionInstType *unionInst ) {
-		handleQualifiers( unionInst );
-		if ( UnionInstType * ut = dynamic_cast< UnionInstType * >( other ) ) {
-			result = result && unionInst->get_name() == ut->get_name();
-		} else {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( EnumInstType *enumInst ) {
-		handleQualifiers( enumInst );
-		if ( EnumInstType * et = dynamic_cast< EnumInstType * >( other ) ) {
-			result = result && enumInst->get_name() == et->get_name();
-		} else {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( TypeInstType *typeInst ) {
-		handleQualifiers( typeInst );
-		if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( other ) ) {
-			result = result && typeInst->get_name() == tt->get_name();
-		} else {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( VarArgsType *varArgsType ) {
-		handleQualifiers( varArgsType );
-		if ( ! dynamic_cast< VarArgsType * >( other ) ) {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( ZeroType *zeroType ) {
-		handleQualifiers( zeroType );
-		if ( ! dynamic_cast< ZeroType * >( other ) ) {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( OneType *oneType ) {
-		handleQualifiers( oneType );
-		if ( ! dynamic_cast< OneType * >( other ) ) {
-			result = false;
-		}
-	}
-} // namespace SymTab
Index: src/SymTab/TypeEquality.h
===================================================================
--- src/SymTab/TypeEquality.h	(revision 81644e025cbf854af3550d54b343f22ec9ec8f05)
+++ 	(revision )
@@ -1,23 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// TypeEquality.h --
-//
-// Author           : Rob Schluntz
-// Created On       : Tue Jul 07 16:30:07 2015
-// Last Modified By : Rob Schluntz
-// Last Modified On : Wed Jul 08 12:41:15 2015
-// Update Count     : 6
-//
-
-class Type;
-
-namespace SymTab {
-  // compare types t1 and t2 for equality
-  // if vlaErr is true, then if at least one of the types is a
-  // variable-length array type, then the result will be false
-  bool typeEquals( Type * t1, Type * t2, bool vlaErr = false );
-} // namespace SymTab
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 81644e025cbf854af3550d54b343f22ec9ec8f05)
+++ src/SymTab/Validate.cc	(revision 3ca540ff8fca8be28ec085a72a11b96bf920dd76)
@@ -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 );
 	}
 
Index: src/SymTab/module.mk
===================================================================
--- src/SymTab/module.mk	(revision 81644e025cbf854af3550d54b343f22ec9ec8f05)
+++ src/SymTab/module.mk	(revision 3ca540ff8fca8be28ec085a72a11b96bf920dd76)
@@ -19,5 +19,3 @@
        SymTab/Validate.cc \
        SymTab/FixFunction.cc \
-       SymTab/ImplementationType.cc \
-       SymTab/TypeEquality.cc \
        SymTab/Autogen.cc
