Index: src/SymTab/FixFunction.cc
===================================================================
--- src/SymTab/FixFunction.cc	(revision 8404321b14af61fa51a2739f63bc8e76b6c4bed6)
+++ src/SymTab/FixFunction.cc	(revision 21b7161a88a09fe93c649966f0ea343f52a7bc56)
@@ -26,8 +26,9 @@
 	FixFunction::FixFunction() : isVoid( false ) {}
 
-	DeclarationWithType * FixFunction::mutate(FunctionDecl *functionDecl) {
+
+	DeclarationWithType * FixFunction::postmutate(FunctionDecl *functionDecl) {
 		// can't delete function type because it may contain assertions, so transfer ownership to new object
-		ObjectDecl *pointer = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClasses(), functionDecl->get_linkage(), 0, new PointerType( Type::Qualifiers(), functionDecl->get_type() ), 0, functionDecl->get_attributes() );
-		functionDecl->get_attributes().clear();
+		ObjectDecl *pointer = new ObjectDecl( functionDecl->name, functionDecl->get_storageClasses(), functionDecl->linkage, nullptr, new PointerType( Type::Qualifiers(), functionDecl->type ), nullptr, functionDecl->attributes );
+		functionDecl->attributes.clear();
 		functionDecl->type = nullptr;
 		delete functionDecl;
@@ -35,59 +36,29 @@
 	}
 
-	Type * FixFunction::mutate(VoidType *voidType) {
-		isVoid = true;
-		return voidType;
-	}
-
-	Type * FixFunction::mutate(BasicType *basicType) {
-		return basicType;
-	}
-
-	Type * FixFunction::mutate(PointerType *pointerType) {
-		return pointerType;
-	}
-
-	Type * FixFunction::mutate(ArrayType *arrayType) {
+	Type * FixFunction::postmutate(ArrayType *arrayType) {
 		// need to recursively mutate the base type in order for multi-dimensional arrays to work.
-		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->get_base()->clone()->acceptMutator( *this ), maybeClone( arrayType->get_dimension() ), arrayType->get_isVarLen(), arrayType->get_isStatic() );
+		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->isVarLen, arrayType->isStatic );
+		arrayType->base = nullptr;
+		arrayType->dimension = nullptr;
 		delete arrayType;
 		return pointerType;
 	}
 
-	Type * FixFunction::mutate(StructInstType *aggregateUseType) {
-		return aggregateUseType;
+	void FixFunction::premutate(VoidType *) {
+		isVoid = true;
 	}
 
-	Type * FixFunction::mutate(UnionInstType *aggregateUseType) {
-		return aggregateUseType;
-	}
-
-	Type * FixFunction::mutate(EnumInstType *aggregateUseType) {
-		return aggregateUseType;
-	}
-
-	Type * FixFunction::mutate(TraitInstType *aggregateUseType) {
-		return aggregateUseType;
-	}
-
-	Type * FixFunction::mutate(TypeInstType *aggregateUseType) {
-		return aggregateUseType;
-	}
-
-	Type * FixFunction::mutate(TupleType *tupleType) {
-		return tupleType;
-	}
-
-	Type * FixFunction::mutate(VarArgsType *varArgsType) {
-		return varArgsType;
-	}
-
-	Type * FixFunction::mutate(ZeroType *zeroType) {
-		return zeroType;
-	}
-
-	Type * FixFunction::mutate(OneType *oneType) {
-		return oneType;
-	}
+	void FixFunction::premutate(FunctionDecl *) { visit_children = false; }
+	void FixFunction::premutate(BasicType *) { visit_children = false; }
+	void FixFunction::premutate(PointerType *) { visit_children = false; }
+	void FixFunction::premutate(StructInstType *) { visit_children = false; }
+	void FixFunction::premutate(UnionInstType *) { visit_children = false; }
+	void FixFunction::premutate(EnumInstType *) { visit_children = false; }
+	void FixFunction::premutate(TraitInstType *) { visit_children = false; }
+	void FixFunction::premutate(TypeInstType *) { visit_children = false; }
+	void FixFunction::premutate(TupleType *) { visit_children = false; }
+	void FixFunction::premutate(VarArgsType *) { visit_children = false; }
+	void FixFunction::premutate(ZeroType *) { visit_children = false; }
+	void FixFunction::premutate(OneType *) { visit_children = false; }
 } // namespace SymTab
 
Index: src/SymTab/FixFunction.h
===================================================================
--- src/SymTab/FixFunction.h	(revision 8404321b14af61fa51a2739f63bc8e76b6c4bed6)
+++ src/SymTab/FixFunction.h	(revision 21b7161a88a09fe93c649966f0ea343f52a7bc56)
@@ -16,32 +16,31 @@
 #pragma once
 
-#include "SynTree/Mutator.h"  // for Mutator
-#include "SynTree/SynTree.h"  // for Types
+#include "Common/PassVisitor.h" // for PassVisitor
+#include "SynTree/SynTree.h"    // for Types
 
 namespace SymTab {
 	/// Replaces function and array types by equivalent pointer types.
-	class FixFunction : public Mutator {
+	class FixFunction : public WithShortCircuiting {
 		typedef Mutator Parent;
 	  public:
 		FixFunction();
 
-		bool get_isVoid() const { return isVoid; }
-		void set_isVoid( bool newValue ) { isVoid = newValue; }
-	  private:
-		virtual DeclarationWithType* mutate(FunctionDecl *functionDecl);
+		void premutate(FunctionDecl *functionDecl);
+		DeclarationWithType* postmutate(FunctionDecl *functionDecl);
 
-		virtual Type* mutate(VoidType *voidType);
-		virtual Type* mutate(BasicType *basicType);
-		virtual Type* mutate(PointerType *pointerType);
-		virtual Type* mutate(ArrayType *arrayType);
-		virtual Type* mutate(StructInstType *aggregateUseType);
-		virtual Type* mutate(UnionInstType *aggregateUseType);
-		virtual Type* mutate(EnumInstType *aggregateUseType);
-		virtual Type* mutate(TraitInstType *aggregateUseType);
-		virtual Type* mutate(TypeInstType *aggregateUseType);
-		virtual Type* mutate(TupleType *tupleType);
-		virtual Type* mutate(VarArgsType *varArgsType);
-		virtual Type* mutate(ZeroType *zeroType);
-		virtual Type* mutate(OneType *oneType);
+		Type * postmutate(ArrayType * arrayType);
+
+		void premutate(VoidType * voidType);
+		void premutate(BasicType * basicType);
+		void premutate(PointerType * pointerType);
+		void premutate(StructInstType * aggregateUseType);
+		void premutate(UnionInstType * aggregateUseType);
+		void premutate(EnumInstType * aggregateUseType);
+		void premutate(TraitInstType * aggregateUseType);
+		void premutate(TypeInstType * aggregateUseType);
+		void premutate(TupleType * tupleType);
+		void premutate(VarArgsType * varArgsType);
+		void premutate(ZeroType * zeroType);
+		void premutate(OneType * oneType);
 
 		bool isVoid;
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 8404321b14af61fa51a2739f63bc8e76b6c4bed6)
+++ src/SymTab/Validate.cc	(revision 21b7161a88a09fe93c649966f0ea343f52a7bc56)
@@ -369,8 +369,8 @@
 			DWTIterator begin( dwts.begin() ), end( dwts.end() );
 			if ( begin == end ) return;
-			FixFunction fixer;
+			PassVisitor<FixFunction> fixer;
 			DWTIterator i = begin;
 			*i = (*i)->acceptMutator( fixer );
-			if ( fixer.get_isVoid() ) {
+			if ( fixer.pass.isVoid ) {
 				DWTIterator j = i;
 				++i;
@@ -383,7 +383,7 @@
 				++i;
 				for ( ; i != end; ++i ) {
-					FixFunction fixer;
+					PassVisitor<FixFunction> fixer;
 					*i = (*i)->acceptMutator( fixer );
-					if ( fixer.get_isVoid() ) {
+					if ( fixer.pass.isVoid ) {
 						throw SemanticError( "invalid type void in function type ", func );
 					} // if
@@ -597,7 +597,7 @@
 			// apply FixFunction to every assertion to check for invalid void type
 			for ( DeclarationWithType *& assertion : type->assertions ) {
-				FixFunction fixer;
+				PassVisitor<FixFunction> fixer;
 				assertion = assertion->acceptMutator( fixer );
-				if ( fixer.get_isVoid() ) {
+				if ( fixer.pass.isVoid ) {
 					throw SemanticError( "invalid type void in assertion of function ", node );
 				} // if
