Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision c57ded701c64266f443f9f06e781a051aad5c287)
+++ src/Common/PassVisitor.impl.h	(revision 522363e8799469eb8e37c765e3c5d28f46066d9a)
@@ -66,4 +66,5 @@
 	DeclList_t* beforeDecls = visitor.get_beforeDecls();
 	DeclList_t* afterDecls  = visitor.get_afterDecls();
+	SemanticError errors;
 
 	for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
@@ -73,10 +74,18 @@
 		if ( i == decls.end() ) break;
 
-		// run mutator on declaration
-		maybeAccept( *i, visitor );
+		try {
+			// run visitor on declaration
+			maybeAccept( *i, visitor );
+		} catch( SemanticError &e ) {
+			e.set_location( (*i)->location );
+			errors.append( e );
+		}
 
 		// splice in new declarations before current decl
 		if ( !empty( beforeDecls ) ) { decls.splice( i, *beforeDecls ); }
 	}
+	if ( ! errors.isEmpty() ) {
+		throw errors;
+	}
 }
 
@@ -86,4 +95,5 @@
 	DeclList_t* beforeDecls = mutator.get_beforeDecls();
 	DeclList_t* afterDecls  = mutator.get_afterDecls();
+	SemanticError errors;
 
 	for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
@@ -92,10 +102,17 @@
 
 		if ( i == decls.end() ) break;
-
-		// run mutator on declaration
-		*i = maybeMutate( *i, mutator );
+		try {
+			// run mutator on declaration
+			*i = maybeMutate( *i, mutator );
+		} catch( SemanticError &e ) {
+			e.set_location( (*i)->location );
+			errors.append( e );
+		}
 
 		// splice in new declarations before current decl
 		if ( !empty( beforeDecls ) ) { decls.splice( i, *beforeDecls ); }
+	}
+	if ( ! errors.isEmpty() ) {
+		throw errors;
 	}
 }
@@ -445,5 +462,5 @@
 	indexerAddEnum( node );
 
-	// unlike structs, contexts, and unions, enums inject their members into the global scope
+	// unlike structs, traits, and unions, enums inject their members into the global scope
 	maybeMutateRef( node->parameters, *this );
 	maybeMutateRef( node->members   , *this );
Index: src/Common/PassVisitor.proto.h
===================================================================
--- src/Common/PassVisitor.proto.h	(revision c57ded701c64266f443f9f06e781a051aad5c287)
+++ src/Common/PassVisitor.proto.h	(revision 522363e8799469eb8e37c765e3c5d28f46066d9a)
@@ -179,5 +179,5 @@
 
 template<typename pass_type>
-static inline auto indexer_impl_enterScope( pass_type &, int ) {}
+static inline auto indexer_impl_enterScope( pass_type &, long ) {}
 
 template<typename pass_type>
@@ -187,5 +187,5 @@
 
 template<typename pass_type>
-static inline auto indexer_impl_leaveScope( pass_type &, int ) {}
+static inline auto indexer_impl_leaveScope( pass_type &, long ) {}
 
 
@@ -197,5 +197,5 @@
                                                                                                                                \
 template<typename pass_type>                                                                                                   \
-static inline void indexer_impl_##func ( pass_type &, long, type ) {}                                                          \
+static inline void indexer_impl_##func ( pass_type &, long, type ) { }                                                          \
 
 INDEXER_FUNC( addId     , DeclarationWithType * );
@@ -215,5 +215,5 @@
 
 template<typename pass_type>
-static inline auto indexer_impl_addStructFwd( pass_type &, int, StructDecl * ) {}
+static inline auto indexer_impl_addStructFwd( pass_type &, long, StructDecl * ) {}
 
 template<typename pass_type>
@@ -225,5 +225,5 @@
 
 template<typename pass_type>
-static inline auto indexer_impl_addUnionFwd( pass_type &, int, UnionDecl * ) {}
+static inline auto indexer_impl_addUnionFwd( pass_type &, long, UnionDecl * ) {}
 
 template<typename pass_type>
@@ -235,5 +235,5 @@
 
 template<typename pass_type>
-static inline auto indexer_impl_addStruct( pass_type &, int, const std::string & ) {}
+static inline auto indexer_impl_addStruct( pass_type &, long, const std::string & ) {}
 
 template<typename pass_type>
@@ -245,3 +245,3 @@
 
 template<typename pass_type>
-static inline auto indexer_impl_addUnion( pass_type &, int, const std::string & ) {}
+static inline auto indexer_impl_addUnion( pass_type &, long, const std::string & ) {}
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision c57ded701c64266f443f9f06e781a051aad5c287)
+++ src/SymTab/Indexer.cc	(revision 522363e8799469eb8e37c765e3c5d28f46066d9a)
@@ -37,5 +37,5 @@
 #include "SynTree/Type.h"          // for Type, StructInstType, UnionInstType
 
-#define debugPrint(x) if ( doDebug ) { std::cout << x; }
+#define debugPrint(x) if ( doDebug ) { std::cerr << x; }
 
 namespace SymTab {
Index: src/SymTab/Indexer.h
===================================================================
--- src/SymTab/Indexer.h	(revision c57ded701c64266f443f9f06e781a051aad5c287)
+++ src/SymTab/Indexer.h	(revision 522363e8799469eb8e37c765e3c5d28f46066d9a)
@@ -104,5 +104,5 @@
 
 		void print( std::ostream &os, int indent = 0 ) const;
-	  private:
+
 		/// looks up a specific mangled ID at the given scope
 		DeclarationWithType *lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
@@ -127,4 +127,5 @@
 		void addTrait( TraitDecl *decl );
 
+	  private:
 		struct Impl;
 
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision c57ded701c64266f443f9f06e781a051aad5c287)
+++ src/SymTab/Validate.cc	(revision 522363e8799469eb8e37c765e3c5d28f46066d9a)
@@ -123,23 +123,20 @@
 
 	/// Associates forward declarations of aggregates with their definitions
-	class LinkReferenceToTypes final : public Indexer {
-		typedef Indexer Parent;
-	  public:
-		LinkReferenceToTypes( bool doDebug, const Indexer *indexer );
-		using Parent::visit;
-		void visit( TypeInstType *typeInst ) final;
-
-		void visit( EnumInstType *enumInst ) final;
-		void visit( StructInstType *structInst ) final;
-		void visit( UnionInstType *unionInst ) final;
-		void visit( TraitInstType *traitInst ) final;
-
-		void visit( EnumDecl *enumDecl ) final;
-		void visit( StructDecl *structDecl ) final;
-		void visit( UnionDecl *unionDecl ) final;
-		void visit( TraitDecl * traitDecl ) final;
+	struct LinkReferenceToTypes final : public WithIndexer {
+		LinkReferenceToTypes( const Indexer *indexer );
+		void postvisit( TypeInstType *typeInst );
+
+		void postvisit( EnumInstType *enumInst );
+		void postvisit( StructInstType *structInst );
+		void postvisit( UnionInstType *unionInst );
+		void postvisit( TraitInstType *traitInst );
+
+		void postvisit( EnumDecl *enumDecl );
+		void postvisit( StructDecl *structDecl );
+		void postvisit( UnionDecl *unionDecl );
+		void postvisit( TraitDecl * traitDecl );
 
 	  private:
-		const Indexer *indexer;
+		const Indexer *local_indexer;
 
 		typedef std::map< std::string, std::list< EnumInstType * > > ForwardEnumsType;
@@ -152,14 +149,7 @@
 
 	/// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID.
-	class ForallPointerDecay final : public Indexer {
-		typedef Indexer Parent;
-	  public:
-	  	using Parent::visit;
-		ForallPointerDecay( const Indexer *indexer );
-
-		virtual void visit( ObjectDecl *object ) override;
-		virtual void visit( FunctionDecl *func ) override;
-
-		const Indexer *indexer;
+	struct ForallPointerDecay final {
+		void previsit( ObjectDecl *object );
+		void previsit( FunctionDecl *func );
 	};
 
@@ -263,8 +253,8 @@
 	};
 
-	void validate( std::list< Declaration * > &translationUnit, bool doDebug ) {
+	void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) {
 		PassVisitor<EnumAndPointerDecay> epc;
-		LinkReferenceToTypes lrt( doDebug, 0 );
-		ForallPointerDecay fpd( 0 );
+		PassVisitor<LinkReferenceToTypes> lrt( nullptr );
+		PassVisitor<ForallPointerDecay> fpd;
 		PassVisitor<CompoundLiteral> compoundliteral;
 		PassVisitor<ValidateGenericParameters> genericParams;
@@ -293,6 +283,6 @@
 	void validateType( Type *type, const Indexer *indexer ) {
 		PassVisitor<EnumAndPointerDecay> epc;
-		LinkReferenceToTypes lrt( false, indexer );
-		ForallPointerDecay fpd( indexer );
+		PassVisitor<LinkReferenceToTypes> lrt( indexer );
+		PassVisitor<ForallPointerDecay> fpd;
 		type->accept( epc );
 		type->accept( lrt );
@@ -408,15 +398,14 @@
 	}
 
-	LinkReferenceToTypes::LinkReferenceToTypes( bool doDebug, const Indexer *other_indexer ) : Indexer( doDebug ) {
+	LinkReferenceToTypes::LinkReferenceToTypes( const Indexer *other_indexer ) {
 		if ( other_indexer ) {
-			indexer = other_indexer;
+			local_indexer = other_indexer;
 		} else {
-			indexer = this;
-		} // if
-	}
-
-	void LinkReferenceToTypes::visit( EnumInstType *enumInst ) {
-		Parent::visit( enumInst );
-		EnumDecl *st = indexer->lookupEnum( enumInst->get_name() );
+			local_indexer = &indexer;
+		} // if
+	}
+
+	void LinkReferenceToTypes::postvisit( EnumInstType *enumInst ) {
+		EnumDecl *st = local_indexer->lookupEnum( enumInst->get_name() );
 		// it's not a semantic error if the enum is not found, just an implicit forward declaration
 		if ( st ) {
@@ -430,7 +419,6 @@
 	}
 
-	void LinkReferenceToTypes::visit( StructInstType *structInst ) {
-		Parent::visit( structInst );
-		StructDecl *st = indexer->lookupStruct( structInst->get_name() );
+	void LinkReferenceToTypes::postvisit( StructInstType *structInst ) {
+		StructDecl *st = local_indexer->lookupStruct( structInst->get_name() );
 		// it's not a semantic error if the struct is not found, just an implicit forward declaration
 		if ( st ) {
@@ -444,7 +432,6 @@
 	}
 
-	void LinkReferenceToTypes::visit( UnionInstType *unionInst ) {
-		Parent::visit( unionInst );
-		UnionDecl *un = indexer->lookupUnion( unionInst->get_name() );
+	void LinkReferenceToTypes::postvisit( UnionInstType *unionInst ) {
+		UnionDecl *un = local_indexer->lookupUnion( unionInst->get_name() );
 		// it's not a semantic error if the union is not found, just an implicit forward declaration
 		if ( un ) {
@@ -499,7 +486,5 @@
 	}
 
-	void LinkReferenceToTypes::visit( TraitDecl * traitDecl ) {
-		Parent::visit( traitDecl );
-
+	void LinkReferenceToTypes::postvisit( TraitDecl * traitDecl ) {
 		if ( traitDecl->name == "sized" ) {
 			// "sized" is a special trait - flick the sized status on for the type variable
@@ -523,8 +508,7 @@
 	}
 
-	void LinkReferenceToTypes::visit( TraitInstType * traitInst ) {
-		Parent::visit( traitInst );
+	void LinkReferenceToTypes::postvisit( TraitInstType * traitInst ) {
 		// handle other traits
-		TraitDecl *traitDecl = indexer->lookupTrait( traitInst->name );
+		TraitDecl *traitDecl = local_indexer->lookupTrait( traitInst->name );
 		if ( ! traitDecl ) {
 			throw SemanticError( "use of undeclared trait " + traitInst->name );
@@ -547,7 +531,6 @@
 	}
 
-	void LinkReferenceToTypes::visit( EnumDecl *enumDecl ) {
+	void LinkReferenceToTypes::postvisit( EnumDecl *enumDecl ) {
 		// visit enum members first so that the types of self-referencing members are updated properly
-		Parent::visit( enumDecl );
 		if ( ! enumDecl->get_members().empty() ) {
 			ForwardEnumsType::iterator fwds = forwardEnums.find( enumDecl->get_name() );
@@ -561,8 +544,7 @@
 	}
 
-	void LinkReferenceToTypes::visit( StructDecl *structDecl ) {
+	void LinkReferenceToTypes::postvisit( StructDecl *structDecl ) {
 		// visit struct members first so that the types of self-referencing members are updated properly
-		// xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and and their defaults)
-		Parent::visit( structDecl );
+		// xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and their defaults)
 		if ( ! structDecl->get_members().empty() ) {
 			ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->get_name() );
@@ -576,6 +558,5 @@
 	}
 
-	void LinkReferenceToTypes::visit( UnionDecl *unionDecl ) {
-		Parent::visit( unionDecl );
+	void LinkReferenceToTypes::postvisit( UnionDecl *unionDecl ) {
 		if ( ! unionDecl->get_members().empty() ) {
 			ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->get_name() );
@@ -589,17 +570,9 @@
 	}
 
-	void LinkReferenceToTypes::visit( TypeInstType *typeInst ) {
-		if ( NamedTypeDecl *namedTypeDecl = lookupType( typeInst->get_name() ) ) {
+	void LinkReferenceToTypes::postvisit( TypeInstType *typeInst ) {
+		if ( NamedTypeDecl *namedTypeDecl = local_indexer->lookupType( typeInst->get_name() ) ) {
 			if ( TypeDecl *typeDecl = dynamic_cast< TypeDecl * >( namedTypeDecl ) ) {
 				typeInst->set_isFtype( typeDecl->get_kind() == TypeDecl::Ftype );
 			} // if
-		} // if
-	}
-
-	ForallPointerDecay::ForallPointerDecay( const Indexer *other_indexer ) :  Indexer( false ) {
-		if ( other_indexer ) {
-			indexer = other_indexer;
-		} else {
-			indexer = this;
 		} // if
 	}
@@ -633,16 +606,14 @@
 	}
 
-	void ForallPointerDecay::visit( ObjectDecl *object ) {
+	void ForallPointerDecay::previsit( ObjectDecl *object ) {
 		forallFixer( object->get_type() );
 		if ( PointerType *pointer = dynamic_cast< PointerType * >( object->get_type() ) ) {
 			forallFixer( pointer->get_base() );
 		} // if
-		Parent::visit( object );
 		object->fixUniqueId();
 	}
 
-	void ForallPointerDecay::visit( FunctionDecl *func ) {
+	void ForallPointerDecay::previsit( FunctionDecl *func ) {
 		forallFixer( func->get_type() );
-		Parent::visit( func );
 		func->fixUniqueId();
 	}
