Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision 4e8949f3e86a781045a82d44c0fd4e0469048937)
+++ src/SymTab/Autogen.cc	(revision 22bc27633b10d98030a7959b4671f00d9985c61a)
@@ -27,4 +27,5 @@
 #include "AddVisit.h"              // for addVisit
 #include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
+#include "Common/PassVisitor.h"    // for PassVisitor
 #include "Common/ScopedMap.h"      // for ScopedMap<>::const_iterator, Scope...
 #include "Common/utility.h"        // for cloneAll, operator+
@@ -53,35 +54,21 @@
 	};
 
-	class AutogenerateRoutines 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:
-		std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
-
-		typedef Visitor Parent;
-		using Parent::visit;
-
+	struct AutogenerateRoutines final : public WithDeclsToAdd, public WithVisitorRef<AutogenerateRoutines>, public WithGuards, public WithShortCircuiting {
 		AutogenerateRoutines();
 
-		virtual void visit( EnumDecl *enumDecl );
-		virtual void visit( StructDecl *structDecl );
-		virtual void visit( UnionDecl *structDecl );
-		virtual void visit( TypeDecl *typeDecl );
-		virtual void visit( TraitDecl *ctxDecl );
-		virtual void visit( FunctionDecl *functionDecl );
-
-		virtual void visit( FunctionType *ftype );
-		virtual void visit( PointerType *ftype );
-
-		virtual void visit( CompoundStmt *compoundStmt );
-		virtual void visit( SwitchStmt *switchStmt );
+		void previsit( EnumDecl * enumDecl );
+		void previsit( StructDecl * structDecl );
+		void previsit( UnionDecl * structDecl );
+		void previsit( TypeDecl * typeDecl );
+		void previsit( TraitDecl * traitDecl );
+		void previsit( FunctionDecl * functionDecl );
+
+		void previsit( FunctionType * ftype );
+		void previsit( PointerType * ptype );
+
+		void previsit( CompoundStmt * compoundStmt );
 
 	  private:
-		template< typename StmtClass > void visitStatement( StmtClass *stmt );
-
-		std::list< Declaration * > declsToAdd, declsToAddAfter;
-		std::set< std::string > structsDone;
+		GenPoly::ScopedSet< std::string > structsDone;
 		unsigned int functionNesting = 0;     // current level of nested functions
 		/// Note: the following maps could be ScopedSets, but it should be easier to work
@@ -112,6 +99,6 @@
 
 	void autogenerateRoutines( std::list< Declaration * > &translationUnit ) {
-		AutogenerateRoutines generator;
-		acceptAndAdd( translationUnit, generator );
+		PassVisitor<AutogenerateRoutines> generator;
+		acceptAll( translationUnit, generator );
 
 		// needs to be done separately because AutogenerateRoutines skips types that appear as function arguments, etc.
@@ -572,11 +559,12 @@
 		// the order here determines the order that these functions are generated.
 		// assignment should come last since it uses copy constructor in return.
-		data.push_back( FuncData( "?{}", genDefaultType, constructable ) );
-		data.push_back( FuncData( "?{}", genCopyType, copyable ) );
-		data.push_back( FuncData( "^?{}", genDefaultType, destructable ) );
-		data.push_back( FuncData( "?=?", genAssignType, assignable ) );
-	}
-
-	void AutogenerateRoutines::visit( EnumDecl *enumDecl ) {
+		data.emplace_back( "?{}", genDefaultType, constructable );
+		data.emplace_back( "?{}", genCopyType, copyable );
+		data.emplace_back( "^?{}", genDefaultType, destructable );
+		data.emplace_back( "?=?", genAssignType, assignable );
+	}
+
+	void AutogenerateRoutines::previsit( EnumDecl *enumDecl ) {
+		visit_children = false;
 		if ( ! enumDecl->get_members().empty() ) {
 			EnumInstType *enumInst = new EnumInstType( Type::Qualifiers(), enumDecl->get_name() );
@@ -586,10 +574,11 @@
 	}
 
-	void AutogenerateRoutines::visit( StructDecl *structDecl ) {
+	void AutogenerateRoutines::previsit( StructDecl *structDecl ) {
+		visit_children = false;
 		if ( structDecl->has_body() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
 			StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
 			for ( TypeDecl * typeDecl : structDecl->get_parameters() ) {
 				// need to visit assertions so that they are added to the appropriate maps
-				acceptAll( typeDecl->get_assertions(), *this );
+				acceptAll( typeDecl->get_assertions(), *visitor );
 				structInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );
 			}
@@ -600,5 +589,6 @@
 	}
 
-	void AutogenerateRoutines::visit( UnionDecl *unionDecl ) {
+	void AutogenerateRoutines::previsit( UnionDecl *unionDecl ) {
+		visit_children = false;
 		if ( ! unionDecl->get_members().empty() ) {
 			UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
@@ -619,5 +609,6 @@
 
 	// generate ctor/dtors/assign for typedecls, e.g., otype T = int *;
-	void AutogenerateRoutines::visit( TypeDecl *typeDecl ) {
+	void AutogenerateRoutines::previsit( TypeDecl *typeDecl ) {
+		visit_children = false;
 		if ( ! typeDecl->base ) return;
 
@@ -664,31 +655,21 @@
 	}
 
-	void addDecls( std::list< Declaration * > &declsToAdd, std::list< Statement * > &statements, std::list< Statement * >::iterator i ) {
-		for ( std::list< Declaration * >::iterator decl = declsToAdd.begin(); decl != declsToAdd.end(); ++decl ) {
-			statements.insert( i, new DeclStmt( noLabels, *decl ) );
-		} // for
-		declsToAdd.clear();
-	}
-
-	void AutogenerateRoutines::visit( FunctionType *) {
+	void AutogenerateRoutines::previsit( FunctionType *) {
 		// ensure that we don't add assignment ops for types defined as part of the function
-	}
-
-	void AutogenerateRoutines::visit( PointerType *) {
+		visit_children = false;
+	}
+
+	void AutogenerateRoutines::previsit( PointerType *) {
 		// ensure that we don't add assignment ops for types defined as part of the pointer
-	}
-
-	void AutogenerateRoutines::visit( TraitDecl *) {
+		visit_children = false;
+	}
+
+	void AutogenerateRoutines::previsit( TraitDecl * ) {
 		// ensure that we don't add assignment ops for types defined as part of the trait
-	}
-
-	template< typename StmtClass >
-	inline void AutogenerateRoutines::visitStatement( StmtClass *stmt ) {
-		std::set< std::string > oldStructs = structsDone;
-		addVisit( stmt, *this );
-		structsDone = oldStructs;
-	}
-
-	void AutogenerateRoutines::visit( FunctionDecl *functionDecl ) {
+		visit_children = false;
+	}
+
+	void AutogenerateRoutines::previsit( FunctionDecl * functionDecl ) {
+		visit_children = false;
 		// record the existence of this function as appropriate
 		insert( functionDecl, constructable, InitTweak::isDefaultConstructor );
@@ -697,24 +678,16 @@
 		insert( functionDecl, destructable, InitTweak::isDestructor );
 
-		maybeAccept( functionDecl->get_functionType(), *this );
+		maybeAccept( functionDecl->get_functionType(), *visitor );
 		functionNesting += 1;
-		maybeAccept( functionDecl->get_statements(), *this );
+		maybeAccept( functionDecl->get_statements(), *visitor );
 		functionNesting -= 1;
 	}
 
-	void AutogenerateRoutines::visit( CompoundStmt *compoundStmt ) {
-		constructable.beginScope();
-		assignable.beginScope();
-		copyable.beginScope();
-		destructable.beginScope();
-		visitStatement( compoundStmt );
-		constructable.endScope();
-		assignable.endScope();
-		copyable.endScope();
-		destructable.endScope();
-	}
-
-	void AutogenerateRoutines::visit( SwitchStmt *switchStmt ) {
-		visitStatement( switchStmt );
+	void AutogenerateRoutines::previsit( CompoundStmt * ) {
+		GuardScope( constructable );
+		GuardScope( assignable );
+		GuardScope( copyable );
+		GuardScope( destructable );
+		GuardScope( structsDone );
 	}
 
