Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 67cf18c3e5b8ae6e923fa93e69357ba5e746bf57)
+++ src/SymTab/Validate.cc	(revision 7985fa5410478aa52d6410c814bd9432dab4d748)
@@ -38,29 +38,38 @@
 //   definition occurs later in the input.
 
+#include <algorithm>
+#include <iterator>
 #include <list>
-#include <iterator>
+
+#include "CodeGen/CodeGenerator.h"
+
+#include "Common/PassVisitor.h"
 #include "Common/ScopedMap.h"
+#include "Common/UniqueName.h"
 #include "Common/utility.h"
-#include "Common/UniqueName.h"
+
 #include "Concurrency/Keywords.h"
-#include "Validate.h"
-#include "SynTree/Visitor.h"
-#include "SynTree/Mutator.h"
-#include "SynTree/Type.h"
-#include "SynTree/Expression.h"
-#include "SynTree/Statement.h"
-#include "SynTree/TypeSubstitution.h"
-#include "Indexer.h"
+
+#include "GenPoly/DeclMutator.h"
+
+#include "InitTweak/InitTweak.h"
+
+#include "AddVisit.h"
+#include "Autogen.h"
 #include "FixFunction.h"
 // #include "ImplementationType.h"
-#include "GenPoly/DeclMutator.h"
-#include "AddVisit.h"
+#include "Indexer.h"
 #include "MakeLibCfa.h"
 #include "TypeEquality.h"
-#include "Autogen.h"
+#include "Validate.h"
+
 #include "ResolvExpr/typeops.h"
-#include <algorithm>
-#include "InitTweak/InitTweak.h"
-#include "CodeGen/CodeGenerator.h"
+
+#include "SynTree/Expression.h"
+#include "SynTree/Mutator.h"
+#include "SynTree/Statement.h"
+#include "SynTree/Type.h"
+#include "SynTree/TypeSubstitution.h"
+#include "SynTree/Visitor.h"
 
 #define debugPrint( x ) if ( doDebug ) { std::cout << x; }
@@ -96,13 +105,10 @@
 
 	/// Fix return types so that every function returns exactly one value
-	class ReturnTypeFixer final : public Visitor {
+	class ReturnTypeFixer {
 	  public:
-		typedef Visitor Parent;
-		using Parent::visit;
-
 		static void fix( std::list< Declaration * > &translationUnit );
 
-		virtual void visit( FunctionDecl * functionDecl );
-		virtual void visit( FunctionType * ftype );
+		void postvisit( FunctionDecl * functionDecl );
+		void postvisit( FunctionType * ftype );
 	};
 
@@ -153,5 +159,5 @@
 	};
 
-	class ReturnChecker : public Visitor {
+	class ReturnChecker {
 	  public:
 		/// Checks that return statements return nothing if their return type is void
@@ -159,8 +165,11 @@
 		static void checkFunctionReturns( std::list< Declaration * > & translationUnit );
 	  private:
-		virtual void visit( FunctionDecl * functionDecl );
-		virtual void visit( ReturnStmt * returnStmt );
-
-		std::list< DeclarationWithType * > returnVals;
+		void previsit( FunctionDecl * functionDecl );
+		void postvisit( FunctionDecl * functionDecl );
+		void previsit( ReturnStmt * returnStmt );
+
+		typedef std::list< DeclarationWithType * > ReturnVals;
+		ReturnVals returnVals;
+		std::stack< ReturnVals > returnValsStack;
 	};
 
@@ -198,5 +207,5 @@
 	};
 
-	class VerifyCtorDtorAssign : public Visitor {
+	class VerifyCtorDtorAssign {
 	public:
 		/// ensure that constructors, destructors, and assignment have at least one
@@ -205,16 +214,15 @@
 		static void verify( std::list< Declaration * > &translationUnit );
 
-		virtual void visit( FunctionDecl *funcDecl );
+		void previsit( FunctionDecl *funcDecl );
 	};
 
 	/// ensure that generic types have the correct number of type arguments
-	class ValidateGenericParameters : public Visitor {
+	class ValidateGenericParameters {
 	public:
-		typedef Visitor Parent;
-		virtual void visit( StructInstType * inst ) final override;
-		virtual void visit( UnionInstType * inst ) final override;
-	};
-
-	class ArrayLength : public Visitor {
+		void previsit( StructInstType * inst );
+		void previsit( UnionInstType * inst );
+	};
+
+	class ArrayLength {
 	public:
 		/// for array types without an explicit length, compute the length and store it so that it
@@ -227,5 +235,5 @@
 		static void computeLength( std::list< Declaration * > & translationUnit );
 
-		virtual void visit( ObjectDecl * objDecl );
+		void previsit( ObjectDecl * objDecl );
 	};
 
@@ -243,5 +251,5 @@
 		Pass3 pass3( 0 );
 		CompoundLiteral compoundliteral;
-		ValidateGenericParameters genericParams;
+		PassVisitor<ValidateGenericParameters> genericParams;
 
 		EliminateTypedef::eliminateTypedef( translationUnit );
@@ -594,16 +602,18 @@
 
 	void ReturnChecker::checkFunctionReturns( std::list< Declaration * > & translationUnit ) {
-		ReturnChecker checker;
+		PassVisitor<ReturnChecker> checker;
 		acceptAll( translationUnit, checker );
 	}
 
-	void ReturnChecker::visit( FunctionDecl * functionDecl ) {
-		std::list< DeclarationWithType * > oldReturnVals = returnVals;
+	void ReturnChecker::previsit( FunctionDecl * functionDecl ) {
+		returnValsStack.push( returnVals );
 		returnVals = functionDecl->get_functionType()->get_returnVals();
-		Visitor::visit( functionDecl );
-		returnVals = oldReturnVals;
-	}
-
-	void ReturnChecker::visit( ReturnStmt * returnStmt ) {
+	}
+	void ReturnChecker::postvisit( FunctionDecl * functionDecl ) {
+		returnVals = returnValsStack.top();
+		returnValsStack.pop();
+	}
+
+	void ReturnChecker::previsit( ReturnStmt * returnStmt ) {
 		// Previously this also checked for the existence of an expr paired with no return values on
 		// the  function return type. This is incorrect, since you can have an expression attached to
@@ -815,9 +825,9 @@
 
 	void VerifyCtorDtorAssign::verify( std::list< Declaration * > & translationUnit ) {
-		VerifyCtorDtorAssign verifier;
+		PassVisitor<VerifyCtorDtorAssign> verifier;
 		acceptAll( translationUnit, verifier );
 	}
 
-	void VerifyCtorDtorAssign::visit( FunctionDecl * funcDecl ) {
+	void VerifyCtorDtorAssign::previsit( FunctionDecl * funcDecl ) {
 		FunctionType * funcType = funcDecl->get_functionType();
 		std::list< DeclarationWithType * > &returnVals = funcType->get_returnVals();
@@ -836,6 +846,4 @@
 			}
 		}
-
-		Visitor::visit( funcDecl );
 	}
 
@@ -875,12 +883,10 @@
 	}
 
-	void ValidateGenericParameters::visit( StructInstType * inst ) {
+	void ValidateGenericParameters::previsit( StructInstType * inst ) {
 		validateGeneric( inst );
-		Parent::visit( inst );
-	}
-
-	void ValidateGenericParameters::visit( UnionInstType * inst ) {
+	}
+
+	void ValidateGenericParameters::previsit( UnionInstType * inst ) {
 		validateGeneric( inst );
-		Parent::visit( inst );
 	}
 
@@ -906,10 +912,9 @@
 
 	void ReturnTypeFixer::fix( std::list< Declaration * > &translationUnit ) {
-		ReturnTypeFixer fixer;
+		PassVisitor<ReturnTypeFixer> fixer;
 		acceptAll( translationUnit, fixer );
 	}
 
-	void ReturnTypeFixer::visit( FunctionDecl * functionDecl ) {
-		Parent::visit( functionDecl );
+	void ReturnTypeFixer::postvisit( FunctionDecl * functionDecl ) {
 		FunctionType * ftype = functionDecl->get_functionType();
 		std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
@@ -925,5 +930,5 @@
 	}
 
-	void ReturnTypeFixer::visit( FunctionType * ftype ) {
+	void ReturnTypeFixer::postvisit( FunctionType * ftype ) {
 		// xxx - need to handle named return values - this information needs to be saved somehow
 		// so that resolution has access to the names.
@@ -943,9 +948,9 @@
 
 	void ArrayLength::computeLength( std::list< Declaration * > & translationUnit ) {
-		ArrayLength len;
+		PassVisitor<ArrayLength> len;
 		acceptAll( translationUnit, len );
 	}
 
-	void ArrayLength::visit( ObjectDecl * objDecl ) {
+	void ArrayLength::previsit( ObjectDecl * objDecl ) {
 		if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) {
 			if ( at->get_dimension() != nullptr ) return;
