Index: src/SymTab/FixFunction.cc
===================================================================
--- src/SymTab/FixFunction.cc	(revision d53772d7bd7857cdbf9f250299a94b43ffd99f62)
+++ src/SymTab/FixFunction.cc	(revision c1ed2eed49812bcfa4987e47ccc9eda7d2fbf8c0)
@@ -18,5 +18,8 @@
 #include <list>                   // for list
 
-#include "Common/utility.h"       // for maybeClone
+#include "AST/Decl.hpp"
+#include "AST/Pass.hpp"
+#include "AST/Type.hpp"
+#include "Common/utility.h"       // for maybeClone, copy
 #include "SynTree/Declaration.h"  // for FunctionDecl, ObjectDecl, Declarati...
 #include "SynTree/Expression.h"   // for Expression
@@ -24,8 +27,32 @@
 
 namespace SymTab {
-	FixFunction::FixFunction() : isVoid( false ) {}
+	class FixFunction_old : public WithShortCircuiting {
+		typedef Mutator Parent;
+	  public:
+		FixFunction_old() : isVoid( false ) {}
 
+		void premutate(FunctionDecl *functionDecl);
+		DeclarationWithType* postmutate(FunctionDecl *functionDecl);
 
-	DeclarationWithType * FixFunction::postmutate(FunctionDecl *functionDecl) {
+		Type * postmutate(ArrayType * arrayType);
+
+		void premutate(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;
+	};
+
+	DeclarationWithType * FixFunction_old::postmutate(FunctionDecl *functionDecl) {
 		// can't delete function type because it may contain assertions, so transfer ownership to new object
 		ObjectDecl *pointer = new ObjectDecl( functionDecl->name, functionDecl->get_storageClasses(), functionDecl->linkage, nullptr, new PointerType( Type::Qualifiers(), functionDecl->type ), nullptr, functionDecl->attributes );
@@ -41,5 +68,5 @@
 	// does not cause an error
 
-	Type * FixFunction::postmutate(ArrayType *arrayType) {
+	Type * FixFunction_old::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->base, arrayType->dimension, arrayType->isVarLen, arrayType->isStatic );
@@ -51,27 +78,71 @@
 	}
 
-	void FixFunction::premutate(VoidType *) {
+	void FixFunction_old::premutate(VoidType *) {
 		isVoid = true;
 	}
 
-	void FixFunction::premutate(FunctionDecl *) { visit_children = false; }
-	void FixFunction::premutate(ArrayType *) { 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; }
+	void FixFunction_old::premutate(FunctionDecl *) { visit_children = false; }
+	void FixFunction_old::premutate(ArrayType *) { visit_children = false; }
+	void FixFunction_old::premutate(BasicType *) { visit_children = false; }
+	void FixFunction_old::premutate(PointerType *) { visit_children = false; }
+	void FixFunction_old::premutate(StructInstType *) { visit_children = false; }
+	void FixFunction_old::premutate(UnionInstType *) { visit_children = false; }
+	void FixFunction_old::premutate(EnumInstType *) { visit_children = false; }
+	void FixFunction_old::premutate(TraitInstType *) { visit_children = false; }
+	void FixFunction_old::premutate(TypeInstType *) { visit_children = false; }
+	void FixFunction_old::premutate(TupleType *) { visit_children = false; }
+	void FixFunction_old::premutate(VarArgsType *) { visit_children = false; }
+	void FixFunction_old::premutate(ZeroType *) { visit_children = false; }
+	void FixFunction_old::premutate(OneType *) { visit_children = false; }
 
 	bool fixFunction( DeclarationWithType *& dwt ) {
-		PassVisitor<FixFunction> fixer;
+		PassVisitor<FixFunction_old> fixer;
 		dwt = dwt->acceptMutator( fixer );
 		return fixer.pass.isVoid;
 	}
+
+namespace {
+	struct FixFunction_new final : public ast::WithShortCircuiting {
+		bool isVoid = false;
+
+		void premutate( const ast::FunctionDecl * ) { visit_children = false; }
+
+		const ast::DeclWithType * postmutate( const ast::FunctionDecl * func ) {
+			return new ast::ObjectDecl{ 
+				func->location, func->name, new ast::PointerType{ func->type }, nullptr, 
+				func->storage, func->linkage, nullptr, copy( func->attributes ) };
+		}
+
+		void premutate( const ast::ArrayType * ) { visit_children = false; }
+
+		const ast::Type * postmutate( const ast::ArrayType * array ) {
+			return new ast::PointerType{ 
+				array->base, array->dimension, array->isVarLen, array->isStatic, 
+				array->qualifiers };
+		}
+
+		void premutate( const ast::VoidType * ) { isVoid = true; }
+
+		void premutate( const ast::BasicType * ) { visit_children = false; }
+		void premutate( const ast::PointerType * ) { visit_children = false; }
+		void premutate( const ast::StructInstType * ) { visit_children = false; }
+		void premutate( const ast::UnionInstType * ) { visit_children = false; }
+		void premutate( const ast::EnumInstType * ) { visit_children = false; }
+		void premutate( const ast::TraitInstType * ) { visit_children = false; }
+		void premutate( const ast::TypeInstType * ) { visit_children = false; }
+		void premutate( const ast::TupleType * ) { visit_children = false; }
+		void premutate( const ast::VarArgsType * ) { visit_children = false; }
+		void premutate( const ast::ZeroType * ) { visit_children = false; }
+		void premutate( const ast::OneType * ) { visit_children = false; }
+	};
+} // anonymous namespace
+
+const ast::DeclWithType * fixFunction( const ast::DeclWithType * dwt, bool & isVoid ) {
+	ast::Pass< FixFunction_new > fixer;
+	dwt = dwt->accept( fixer );
+	isVoid |= fixer.pass.isVoid;
+	return dwt;
+}
+
 } // namespace SymTab
 
