Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 33a25f904db2c5a826a55cdb66cfd7d4cc979de3)
+++ src/InitTweak/FixInit.cc	(revision d48e529cc868a651ee3760fbd3cf7b1570a205b4)
@@ -105,15 +105,12 @@
 
 		/// collects constructed object decls - used as a base class
-		class ObjDeclCollector : public AddStmtVisitor {
-		  public:
-			typedef AddStmtVisitor Parent;
-			using Parent::visit;
+		struct ObjDeclCollector : public WithGuards, public WithShortCircuiting {
 			// use ordered data structure to maintain ordering for set_difference and for consistent error messages
 			typedef std::list< ObjectDecl * > ObjectSet;
-			virtual void visit( CompoundStmt *compoundStmt ) override;
-			virtual void visit( DeclStmt *stmt ) override;
+			void previsit( CompoundStmt *compoundStmt );
+			void previsit( DeclStmt *stmt );
 
 			// don't go into other functions
-			virtual void visit( FunctionDecl * ) override {}
+			void previsit( FunctionDecl * ) { visit_children = false; }
 
 		  protected:
@@ -139,61 +136,41 @@
 		}
 
-		class LabelFinder final : public ObjDeclCollector {
-		  public:
-			typedef ObjDeclCollector Parent;
+		struct LabelFinder final : public ObjDeclCollector {
 			typedef std::map< Label, ObjectSet > LabelMap;
 			// map of Label -> live variables at that label
 			LabelMap vars;
 
-			void handleStmt( Statement * stmt );
-
-			// xxx - This needs to be done better.
-			// allow some generalization among different kinds of nodes with with similar parentage (e.g. all
-			// expressions, all statements, etc.)  important to have this to provide a single entry point so that as new
-			// subclasses are added, there is only one place that the code has to be updated, rather than ensure that
-			// every specialized class knows about every new kind of statement that might be added.
-			using Parent::visit;
-			virtual void visit( CompoundStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( ExprStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( AsmStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( IfStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( WhileStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( ForStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( SwitchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( CaseStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( BranchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( ReturnStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( TryStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( CatchStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( FinallyStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( NullStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( DeclStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
-			virtual void visit( ImplicitCtorDtorStmt *stmt ) override { handleStmt( stmt ); return Parent::visit( stmt ); }
+			typedef ObjDeclCollector Parent;
+			using Parent::previsit;
+			void previsit( Statement * stmt );
+
+			void previsit( CompoundStmt *compoundStmt );
+			void previsit( DeclStmt *stmt );
 		};
 
-		class InsertDtors final : public ObjDeclCollector {
-		public:
+		struct InsertDtors final : public ObjDeclCollector, public WithStmtsToAdd {
 			/// insert destructor calls at the appropriate places.  must happen before CtorInit nodes are removed
 			/// (currently by FixInit)
 			static void insert( std::list< Declaration * > & translationUnit );
 
-			typedef ObjDeclCollector Parent;
 			typedef std::list< ObjectDecl * > OrderedDecls;
 			typedef std::list< OrderedDecls > OrderedDeclsStack;
 
-			InsertDtors( LabelFinder & finder ) : finder( finder ), labelVars( finder.vars ) {}
-
-			using Parent::visit;
-
-			virtual void visit( ObjectDecl * objDecl ) override;
-			virtual void visit( FunctionDecl * funcDecl ) override;
-
-			virtual void visit( CompoundStmt * compoundStmt ) override;
-			virtual void visit( ReturnStmt * returnStmt ) override;
-			virtual void visit( BranchStmt * stmt ) override;
+			InsertDtors( PassVisitor<LabelFinder> & finder ) : finder( finder ), labelVars( finder.pass.vars ) {}
+
+			typedef ObjDeclCollector Parent;
+			using Parent::previsit;
+
+			void previsit( ObjectDecl * objDecl );
+			void previsit( FunctionDecl * funcDecl );
+
+			void previsit( CompoundStmt * compoundStmt );
+			void postvisit( CompoundStmt * compoundStmt );
+			void previsit( ReturnStmt * returnStmt );
+			void previsit( BranchStmt * stmt );
 		private:
 			void handleGoto( BranchStmt * stmt );
 
-			LabelFinder & finder;
+			PassVisitor<LabelFinder> & finder;
 			LabelFinder::LabelMap & labelVars;
 			OrderedDeclsStack reverseDeclOrder;
@@ -333,6 +310,6 @@
 
 		void InsertDtors::insert( std::list< Declaration * > & translationUnit ) {
-			LabelFinder finder;
-			InsertDtors inserter( finder );
+			PassVisitor<LabelFinder> finder;
+			PassVisitor<InsertDtors> inserter( finder );
 			acceptAll( translationUnit, inserter );
 		}
@@ -792,19 +769,16 @@
 		}
 
-		void ObjDeclCollector::visit( CompoundStmt * compoundStmt ) {
-			ObjectSet prevVars = curVars;
-			Parent::visit( compoundStmt );
-			curVars = prevVars;
-		}
-
-		void ObjDeclCollector::visit( DeclStmt * stmt ) {
+		void ObjDeclCollector::previsit( CompoundStmt * ) {
+			GuardValue( curVars );
+		}
+
+		void ObjDeclCollector::previsit( DeclStmt * stmt ) {
 			// keep track of all variables currently in scope
 			if ( ObjectDecl * objDecl = dynamic_cast< ObjectDecl * > ( stmt->get_decl() ) ) {
 				curVars.push_back( objDecl );
 			} // if
-			Parent::visit( stmt );
-		}
-
-		void LabelFinder::handleStmt( Statement * stmt ) {
+		}
+
+		void LabelFinder::previsit( Statement * stmt ) {
 			// for each label, remember the variables in scope at that label.
 			for ( Label l : stmt->get_labels() ) {
@@ -812,4 +786,15 @@
 			} // for
 		}
+
+		void LabelFinder::previsit( CompoundStmt * stmt ) {
+			previsit( (Statement *)stmt );
+			Parent::previsit( stmt );
+		}
+
+		void LabelFinder::previsit( DeclStmt * stmt ) {
+			previsit( (Statement *)stmt );
+			Parent::previsit( stmt );
+		}
+
 
 		template<typename Iterator, typename OutputIterator>
@@ -827,5 +812,5 @@
 		}
 
-		void InsertDtors::visit( ObjectDecl * objDecl ) {
+		void InsertDtors::previsit( ObjectDecl * objDecl ) {
 			// remember non-static destructed objects so that their destructors can be inserted later
 			if ( ! objDecl->get_storageClasses().is_static ) {
@@ -841,31 +826,25 @@
 				} // if
 			} // if
-			Parent::visit( objDecl );
-		}
-
-		template< typename Visitor >
-		void handleFuncDecl( FunctionDecl * funcDecl, Visitor & visitor ) {
-			maybeAccept( funcDecl->get_functionType(), visitor );
-			maybeAccept( funcDecl->get_statements(), visitor );
-		}
-
-		void InsertDtors::visit( FunctionDecl * funcDecl ) {
+		}
+
+		void InsertDtors::previsit( FunctionDecl * funcDecl ) {
 			// each function needs to have its own set of labels
-			ValueGuard< LabelFinder::LabelMap > oldLabels( labelVars );
+			GuardValue( labelVars );
 			labelVars.clear();
-			handleFuncDecl( funcDecl, finder );
-
-			// all labels for this function have been collected, insert destructors as appropriate.
-			// can't be Parent::mutate, because ObjDeclCollector bottoms out on FunctionDecl
-			handleFuncDecl( funcDecl, *this );
-		}
-
-		void InsertDtors::visit( CompoundStmt * compoundStmt ) {
+			maybeAccept( funcDecl->type, finder );
+			maybeAccept( funcDecl->statements, finder );
+
+			// all labels for this function have been collected, insert destructors as appropriate via implicit recursion.
+		}
+
+		void InsertDtors::previsit( CompoundStmt * compoundStmt ) {
 			// visit statements - this will also populate reverseDeclOrder list.  don't want to dump all destructors
 			// when block is left, just the destructors associated with variables defined in this block, so push a new
 			// list to the top of the stack so that we can differentiate scopes
 			reverseDeclOrder.push_front( OrderedDecls() );
-			Parent::visit( compoundStmt );
-
+			Parent::previsit( compoundStmt );
+		}
+
+		void InsertDtors::postvisit( CompoundStmt * compoundStmt ) {
 			// add destructors for the current scope that we're exiting, unless the last statement is a return, which
 			// causes unreachable code warnings
@@ -877,8 +856,8 @@
 		}
 
-		void InsertDtors::visit( __attribute((unused)) ReturnStmt * returnStmt ) {
+		void InsertDtors::previsit( ReturnStmt * ) {
 			// return exits all scopes, so dump destructors for all scopes
 			for ( OrderedDecls & od : reverseDeclOrder ) {
-				insertDtors( od.begin(), od.end(), back_inserter( stmtsToAdd ) );
+				insertDtors( od.begin(), od.end(), back_inserter( stmtsToAddBefore ) );
 			} // for
 		}
@@ -928,9 +907,9 @@
 					copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return needsDestructor.count( objDecl ); } );
 				} // for
-				insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAdd ) );
+				insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAddBefore ) );
 			} // if
 		}
 
-		void InsertDtors::visit( BranchStmt * stmt ) {
+		void InsertDtors::previsit( BranchStmt * stmt ) {
 			switch( stmt->get_type() ) {
 			  case BranchStmt::Continue:
