Index: src/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision ba915fb57763ae661ddfbc000c81dde9a5ae0003)
+++ src/Common/PassVisitor.h	(revision d24d4e166c6a6516f309efbac59c59da18c7169f)
@@ -26,5 +26,5 @@
 //                          stmtsToAddBefore or stmtsToAddAfter respectively.
 // | WithShortCircuiting  - provides the ability to skip visiting child nodes; set visit_children to false in pre{visit,mutate} to skip visiting children
-// | WithScopes           - provides the ability to save/restore data like a LIFO stack; to save, call GuardValue with the variable to save, the variable
+// | WithGuards           - provides the ability to save/restore data like a LIFO stack; to save, call GuardValue with the variable to save, the variable
 //                          will automatically be restored to its previous value after the corresponding postvisit/postmutate teminates.
 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -32,5 +32,4 @@
 class PassVisitor final : public Visitor, public Mutator {
 public:
-	PassVisitor() = default;
 
 	template< typename... Args >
@@ -283,5 +282,5 @@
 
 public:
-	TypeSubstitution * env;
+	TypeSubstitution * env = nullptr;
 };
 
@@ -295,4 +294,15 @@
 	std::list< Statement* > stmtsToAddAfter;
 };
+
+class WithDeclsToAdd {
+protected:
+	WithDeclsToAdd() = default;
+	~WithDeclsToAdd() = default;
+
+public:
+	std::list< Declaration* > declsToAddBefore;
+	std::list< Declaration* > declsToAddAfter;
+};
+
 class WithShortCircuiting {
 protected:
@@ -304,8 +314,8 @@
 };
 
-class WithScopes {
-protected:
-	WithScopes() = default;
-	~WithScopes() = default;
+class WithGuards {
+protected:
+	WithGuards() = default;
+	~WithGuards() = default;
 
 public:
@@ -319,7 +329,15 @@
 	}
 
+	template< typename T >
+	void GuardScope( T& val ) {
+		val.beginScope();
+		at_cleanup( []( void * val ) {
+			static_cast< T * >( val )->endScope();
+		}, static_cast< void * >( & val ) );
+	}
+
 	template< typename Func >
-	void GuardAction( Func&& func ) {
-		at_cleanup( std::forward<Func>( func ) );
+	void GuardAction( Func func ) {
+		at_cleanup( [func](__attribute__((unused)) void *) { func(); }, nullptr );
 	}
 };
@@ -328,9 +346,9 @@
 class WithVisitorRef {
 protected:
-	WithVisitorRef() = default;
-	~WithVisitorRef() = default;
-
-public:
-	PassVisitor<pass_type> * const visitor;
+	WithVisitorRef() {}
+	~WithVisitorRef() {}
+
+public:
+	PassVisitor<pass_type> * const visitor = nullptr;
 };
 
Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision ba915fb57763ae661ddfbc000c81dde9a5ae0003)
+++ src/Common/PassVisitor.impl.h	(revision d24d4e166c6a6516f309efbac59c59da18c7169f)
@@ -68,5 +68,5 @@
 	for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
 		// splice in new declarations after previous decl
-		if ( !empty( afterDecls ) ) { decls.splice( i, *afterDecls ); }	
+		if ( !empty( afterDecls ) ) { decls.splice( i, *afterDecls ); }
 
 		if ( i == decls.end() ) break;
@@ -88,5 +88,5 @@
 	for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
 		// splice in new declarations after previous decl
-		if ( !empty( afterDecls ) ) { decls.splice( i, *afterDecls ); }	
+		if ( !empty( afterDecls ) ) { decls.splice( i, *afterDecls ); }
 
 		if ( i == decls.end() ) break;
@@ -181,5 +181,5 @@
 Statement * PassVisitor< pass_type >::visitStatement( Statement * stmt ) {
 	return handleStatement( stmt, [this]( Statement * stmt ) {
-		maybeAccept( stmt, *this ); 
+		maybeAccept( stmt, *this );
 		return stmt;
 	});
@@ -212,5 +212,5 @@
 		expr->accept( *this );
 		return expr;
-	});		
+	});
 }
 
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision ba915fb57763ae661ddfbc000c81dde9a5ae0003)
+++ src/InitTweak/GenInit.cc	(revision d24d4e166c6a6516f309efbac59c59da18c7169f)
@@ -44,6 +44,5 @@
 	}
 
-	class ReturnFixer : public WithStmtsToAdd, public WithScopes {
-	  public:
+	struct ReturnFixer : public WithStmtsToAdd, public WithGuards {
 		/// consistently allocates a temporary variable for the return value
 		/// of a function so that anything which the resolver decides can be constructed
@@ -59,8 +58,5 @@
 	};
 
-	class CtorDtor final : public GenPoly::PolyMutator {
-	  public:
-		typedef GenPoly::PolyMutator Parent;
-		using Parent::mutate;
+	struct CtorDtor : public WithGuards, public WithShortCircuiting  {
 		/// create constructor and destructor statements for object declarations.
 		/// the actual call statements will be added in after the resolver has run
@@ -69,18 +65,19 @@
 		static void generateCtorDtor( std::list< Declaration * > &translationUnit );
 
-		virtual DeclarationWithType * mutate( ObjectDecl * ) override;
-		virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override;
+		void previsit( ObjectDecl * );
+		void previsit( FunctionDecl *functionDecl );
+
 		// should not traverse into any of these declarations to find objects
 		// that need to be constructed or destructed
-		virtual Declaration* mutate( StructDecl *aggregateDecl ) override;
-		virtual Declaration* mutate( UnionDecl *aggregateDecl ) override { return aggregateDecl; }
-		virtual Declaration* mutate( EnumDecl *aggregateDecl ) override { return aggregateDecl; }
-		virtual Declaration* mutate( TraitDecl *aggregateDecl ) override { return aggregateDecl; }
-		virtual TypeDecl* mutate( TypeDecl *typeDecl ) override { return typeDecl; }
-		virtual Declaration* mutate( TypedefDecl *typeDecl ) override { return typeDecl; }
-
-		virtual Type * mutate( FunctionType *funcType ) override { return funcType; }
-
-		virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ) override;
+		void previsit( StructDecl *aggregateDecl );
+		void previsit( UnionDecl *aggregateDecl ) { visit_children = false; }
+		void previsit( EnumDecl *aggregateDecl ) { visit_children = false; }
+		void previsit( TraitDecl *aggregateDecl ) { visit_children = false; }
+		void previsit( TypeDecl *typeDecl ) { visit_children = false; }
+		void previsit( TypedefDecl *typeDecl ) { visit_children = false; }
+
+		void previsit( FunctionType *funcType ) { visit_children = false; }
+
+		void previsit( CompoundStmt * compoundStmt );
 
 	  private:
@@ -211,6 +208,6 @@
 
 	void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
-		CtorDtor ctordtor;
-		mutateAll( translationUnit, ctordtor );
+		PassVisitor<CtorDtor> ctordtor;
+		acceptAll( translationUnit, ctordtor );
 	}
 
@@ -289,5 +286,5 @@
 	}
 
-	DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) {
+	void CtorDtor::previsit( ObjectDecl * objDecl ) {
 		handleDWT( objDecl );
 		// hands off if @=, extern, builtin, etc.
@@ -301,14 +298,13 @@
 			objDecl->set_init( genCtorInit( objDecl ) );
 		}
-		return Parent::mutate( objDecl );
-	}
-
-	DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) {
-		ValueGuard< bool > oldInFunc = inFunction;
+	}
+
+	void CtorDtor::previsit( FunctionDecl *functionDecl ) {
+		GuardValue( inFunction );
 		inFunction = true;
 
 		handleDWT( functionDecl );
 
-		managedTypes.beginScope();
+		GuardScope( managedTypes );
 		// go through assertions and recursively add seen ctor/dtors
 		for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) {
@@ -317,12 +313,14 @@
 			}
 		}
-		// parameters should not be constructed and destructed, so don't mutate FunctionType
-		functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
-
-		managedTypes.endScope();
-		return functionDecl;
-	}
-
-	Declaration* CtorDtor::mutate( StructDecl *aggregateDecl ) {
+
+		PassVisitor<CtorDtor> newCtorDtor;
+		newCtorDtor.pass = *this;
+		maybeAccept( functionDecl->get_statements(), newCtorDtor );
+		visit_children = false;  // do not try and construct parameters or forall parameters - must happen after maybeAccept
+	}
+
+	void CtorDtor::previsit( StructDecl *aggregateDecl ) {
+		visit_children = false; // do not try to construct and destruct aggregate members
+
 		// don't construct members, but need to take note if there is a managed member,
 		// because that means that this type is also managed
@@ -336,14 +334,9 @@
 			}
 		}
-		return aggregateDecl;
-	}
-
-	CompoundStmt * CtorDtor::mutate( CompoundStmt * compoundStmt ) {
-		managedTypes.beginScope();
-		CompoundStmt * stmt = Parent::mutate( compoundStmt );
-		managedTypes.endScope();
-		return stmt;
-	}
-
+	}
+
+	void CtorDtor::previsit( CompoundStmt * compoundStmt ) {
+		GuardScope( managedTypes );
+	}
 } // namespace InitTweak
 
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision ba915fb57763ae661ddfbc000c81dde9a5ae0003)
+++ src/SymTab/Validate.cc	(revision d24d4e166c6a6516f309efbac59c59da18c7169f)
@@ -106,6 +106,5 @@
 
 	/// Fix return types so that every function returns exactly one value
-	class ReturnTypeFixer {
-	  public:
+	struct ReturnTypeFixer {
 		static void fix( std::list< Declaration * > &translationUnit );
 
@@ -115,6 +114,5 @@
 
 	/// Replaces enum types by int, and function or array types in function parameter and return lists by appropriate pointers.
-	class EnumAndPointerDecay {
-	public:
+	struct EnumAndPointerDecay {
 		void previsit( EnumDecl *aggregateDecl );
 		void previsit( FunctionType *func );
@@ -159,10 +157,9 @@
 	};
 
-	class ReturnChecker : public WithScopes {
-	  public:
+	struct ReturnChecker : public WithGuards {
 		/// Checks that return statements return nothing if their return type is void
 		/// and return something if the return type is non-void.
 		static void checkFunctionReturns( std::list< Declaration * > & translationUnit );
-	  private:
+
 		void previsit( FunctionDecl * functionDecl );
 		void previsit( ReturnStmt * returnStmt );
@@ -205,6 +202,5 @@
 	};
 
-	class VerifyCtorDtorAssign {
-	public:
+	struct VerifyCtorDtorAssign {
 		/// ensure that constructors, destructors, and assignment have at least one
 		/// parameter, the first of which must be a pointer, and that ctor/dtors have no
@@ -216,12 +212,10 @@
 
 	/// ensure that generic types have the correct number of type arguments
-	class ValidateGenericParameters {
-	public:
+	struct ValidateGenericParameters {
 		void previsit( StructInstType * inst );
 		void previsit( UnionInstType * inst );
 	};
 
-	class ArrayLength {
-	public:
+	struct ArrayLength {
 		/// for array types without an explicit length, compute the length and store it so that it
 		/// is known to the rest of the phases. For example,
@@ -236,10 +230,9 @@
 	};
 
-	class CompoundLiteral final : public GenPoly::DeclMutator {
+	struct CompoundLiteral final : public WithDeclsToAdd, public WithVisitorRef<CompoundLiteral> {
 		Type::StorageClasses storageClasses;
 
-		using GenPoly::DeclMutator::mutate;
-		DeclarationWithType * mutate( ObjectDecl *objectDecl ) final;
-		Expression *mutate( CompoundLiteralExpr *compLitExpr ) final;
+		void premutate( ObjectDecl *objectDecl );
+		Expression * postmutate( CompoundLiteralExpr *compLitExpr );
 	};
 
@@ -248,5 +241,5 @@
 		LinkReferenceToTypes lrt( doDebug, 0 );
 		ForallPointerDecay fpd( 0 );
-		CompoundLiteral compoundliteral;
+		PassVisitor<CompoundLiteral> compoundliteral;
 		PassVisitor<ValidateGenericParameters> genericParams;
 
@@ -263,5 +256,5 @@
 		Concurrency::implementThreadStarter( translationUnit );
 		ReturnChecker::checkFunctionReturns( translationUnit );
-		compoundliteral.mutateDeclarationList( translationUnit );
+		mutateAll( translationUnit, compoundliteral );
 		acceptAll( translationUnit, fpd );
 		ArrayLength::computeLength( translationUnit );
@@ -883,22 +876,19 @@
 	}
 
-	DeclarationWithType * CompoundLiteral::mutate( ObjectDecl *objectDecl ) {
+	void CompoundLiteral::premutate( ObjectDecl *objectDecl ) {
 		storageClasses = objectDecl->get_storageClasses();
-		DeclarationWithType * temp = Mutator::mutate( objectDecl );
-		return temp;
-	}
-
-	Expression *CompoundLiteral::mutate( CompoundLiteralExpr *compLitExpr ) {
+	}
+
+	Expression *CompoundLiteral::postmutate( CompoundLiteralExpr *compLitExpr ) {
 		// transform [storage_class] ... (struct S){ 3, ... };
 		// into [storage_class] struct S temp =  { 3, ... };
 		static UniqueName indexName( "_compLit" );
 
-		ObjectDecl *tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, 0, compLitExpr->get_result(), compLitExpr->get_initializer() );
-		compLitExpr->set_result( 0 );
-		compLitExpr->set_initializer( 0 );
+		ObjectDecl *tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() );
+		compLitExpr->set_result( nullptr );
+		compLitExpr->set_initializer( nullptr );
 		delete compLitExpr;
-		DeclarationWithType * newtempvar = mutate( tempvar );
-		addDeclaration( newtempvar );					// add modified temporary to current block
-		return new VariableExpr( newtempvar );
+		declsToAddBefore.push_back( tempvar );					// add modified temporary to current block
+		return new VariableExpr( tempvar );
 	}
 
