Index: src/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision fe5c01dc12bdff1880c53a48f4b74eb6262c2008)
+++ src/Common/PassVisitor.h	(revision 949934ef4a9c85ee6b2393cde997ad480d65a7af)
@@ -12,4 +12,5 @@
 #include "SynTree/Expression.h"
 #include "SynTree/Constant.h"
+#include "SynTree/TypeSubstitution.h"
 
 #include "PassVisitor.proto.h"
@@ -26,5 +27,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 +33,4 @@
 class PassVisitor final : public Visitor, public Mutator {
 public:
-	PassVisitor() = default;
 
 	template< typename... Args >
@@ -283,5 +283,5 @@
 
 public:
-	TypeSubstitution * env;
+	TypeSubstitution * env = nullptr;
 };
 
@@ -295,4 +295,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 +315,8 @@
 };
 
-class WithScopes {
-protected:
-	WithScopes() = default;
-	~WithScopes() = default;
+class WithGuards {
+protected:
+	WithGuards() = default;
+	~WithGuards() = default;
 
 public:
@@ -318,4 +329,17 @@
 		}, static_cast< void * >( & val ) );
 	}
+
+	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( [func](__attribute__((unused)) void *) { func(); }, nullptr );
+	}
 };
 
@@ -323,9 +347,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 fe5c01dc12bdff1880c53a48f4b74eb6262c2008)
+++ src/Common/PassVisitor.impl.h	(revision 949934ef4a9c85ee6b2393cde997ad480d65a7af)
@@ -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;
@@ -104,4 +104,10 @@
 void PassVisitor< pass_type >::handleStatementList( std::list< Statement * > & statements, func_t func ) {
 	SemanticError errors;
+
+	// don't want statements from outer CompoundStmts to be added to this CompoundStmt
+	ValueGuardPtr< StmtList_t > oldBeforeStmts( get_beforeStmts() );
+	ValueGuardPtr< StmtList_t > oldAfterStmts ( get_afterStmts () );
+	ValueGuardPtr< DeclList_t > oldBeforeDecls( get_beforeDecls() );
+	ValueGuardPtr< DeclList_t > oldAfterDecls ( get_afterDecls () );
 
 	StmtList_t* beforeStmts = get_beforeStmts();
@@ -181,5 +187,5 @@
 Statement * PassVisitor< pass_type >::visitStatement( Statement * stmt ) {
 	return handleStatement( stmt, [this]( Statement * stmt ) {
-		maybeAccept( stmt, *this ); 
+		maybeAccept( stmt, *this );
 		return stmt;
 	});
@@ -212,5 +218,5 @@
 		expr->accept( *this );
 		return expr;
-	});		
+	});
 }
 
@@ -565,4 +571,7 @@
 	VISIT_START( node );
 
+	// maybeAccept( node->get_env(), *this );
+	maybeAccept( node->get_result(), *this );
+
 	for ( auto expr : node->get_args() ) {
 		visitExpression( expr );
@@ -575,4 +584,7 @@
 Expression * PassVisitor< pass_type >::mutate( UntypedExpr * node ) {
 	MUTATE_START( node );
+
+	node->set_env( maybeMutate( node->get_env(), *this ) );
+	node->set_result( maybeMutate( node->get_result(), *this ) );
 
 	for ( auto& expr : node->get_args() ) {
Index: src/Common/PassVisitor.proto.h
===================================================================
--- src/Common/PassVisitor.proto.h	(revision fe5c01dc12bdff1880c53a48f4b74eb6262c2008)
+++ src/Common/PassVisitor.proto.h	(revision 949934ef4a9c85ee6b2393cde997ad480d65a7af)
@@ -56,5 +56,5 @@
 // Deep magic (a.k.a template meta programming) to make the templated visitor work
 // Basically the goal is to make 2 previsit_impl
-// 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of 
+// 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of
 //     'pass.previsit( node )' that compiles will be used for that node for that type
 //     This requires that this option only compile for passes that actually define an appropriate visit.
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision fe5c01dc12bdff1880c53a48f4b74eb6262c2008)
+++ src/GenPoly/Box.cc	(revision 949934ef4a9c85ee6b2393cde997ad480d65a7af)
@@ -504,4 +504,5 @@
 		DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
 			if ( functionDecl->get_statements() ) {		// empty routine body ?
+				// std::cerr << "mutating function: " << functionDecl->get_mangleName() << std::endl;
 				doBeginScope();
 				scopeTyVars.beginScope();
@@ -548,4 +549,5 @@
 				retval = oldRetval;
 				doEndScope();
+				// std::cerr << "end function: " << functionDecl->get_mangleName() << std::endl;
 			} // if
 			return functionDecl;
@@ -1116,5 +1118,5 @@
 
 		Expression *Pass1::mutate( ApplicationExpr *appExpr ) {
-			// std::cerr << "mutate appExpr: ";
+			// std::cerr << "mutate appExpr: " << InitTweak::getFunctionName( appExpr ) << std::endl;
 			// for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
 			// 	std::cerr << i->first << " ";
@@ -1141,8 +1143,17 @@
 			ReferenceToType *dynRetType = isDynRet( function, exprTyVars );
 
+			// std::cerr << function << std::endl;
+			// std::cerr << "scopeTyVars: ";
+			// printTyVarMap( std::cerr, scopeTyVars );
+			// std::cerr << "exprTyVars: ";
+			// printTyVarMap( std::cerr, exprTyVars );
+			// std::cerr << "env: " << *env << std::endl;
+			// std::cerr << needsAdapter( function, scopeTyVars ) << ! needsAdapter( function, exprTyVars) << std::endl;
+
 			// NOTE: addDynRetParam needs to know the actual (generated) return type so it can make a temp variable, so pass the result type from the appExpr
 			// passTypeVars needs to know the program-text return type (i.e. the distinction between _conc_T30 and T3(int))
 			// concRetType may not be a good name in one or both of these places. A more appropriate name change is welcome.
 			if ( dynRetType ) {
+				// std::cerr << "dynRetType: " << dynRetType << std::endl;
 				Type *concRetType = appExpr->get_result()->isVoid() ? nullptr : appExpr->get_result();
 				ret = addDynRetParam( appExpr, concRetType, arg ); // xxx - used to use dynRetType instead of concRetType
Index: src/GenPoly/InstantiateGeneric.cc
===================================================================
--- src/GenPoly/InstantiateGeneric.cc	(revision fe5c01dc12bdff1880c53a48f4b74eb6262c2008)
+++ src/GenPoly/InstantiateGeneric.cc	(revision 949934ef4a9c85ee6b2393cde997ad480d65a7af)
@@ -22,9 +22,12 @@
 #include "InstantiateGeneric.h"
 
-#include "DeclMutator.h"
 #include "GenPoly.h"
 #include "ScopedSet.h"
 #include "ScrubTyVars.h"
-#include "PolyMutator.h"
+
+#include "Common/PassVisitor.h"
+#include "Common/ScopedMap.h"
+#include "Common/UniqueName.h"
+#include "Common/utility.h"
 
 #include "ResolvExpr/typeops.h"
@@ -34,7 +37,7 @@
 #include "SynTree/Type.h"
 
-#include "Common/ScopedMap.h"
-#include "Common/UniqueName.h"
-#include "Common/utility.h"
+
+#include "InitTweak/InitTweak.h"
+
 
 namespace GenPoly {
@@ -153,23 +156,6 @@
 	}
 
-	// collect the environments of each TypeInstType so that type variables can be replaced
-	// xxx - possibly temporary solution. Access to type environments is required in GenericInstantiator, but it needs to be a DeclMutator which does not provide easy access to the type environments.
-	class EnvFinder final : public GenPoly::PolyMutator {
-	public:
-		using GenPoly::PolyMutator::mutate;
-		virtual Type * mutate( TypeInstType * inst ) override {
-			if ( env ) envMap[inst] = env;
-			return inst;
-		}
-
-		// don't want to associate an environment with TypeInstTypes that occur in function types - this may actually only apply to function types belonging to DeclarationWithTypes (or even just FunctionDecl)?
-		virtual Type * mutate( FunctionType * ftype ) override {
-			return ftype;
-		}
-		std::unordered_map< ReferenceToType *, TypeSubstitution * > envMap;
-	};
-
 	/// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
-	class GenericInstantiator final : public DeclMutator {
+	struct GenericInstantiator final : public WithTypeSubstitution, public WithDeclsToAdd, public WithVisitorRef<GenericInstantiator>, public WithGuards {
 		/// Map of (generic type, parameter list) pairs to concrete type instantiations
 		InstantiationMap< AggregateDecl, AggregateDecl > instantiations;
@@ -178,15 +164,18 @@
 		/// Namer for concrete types
 		UniqueName typeNamer;
-		/// Reference to mapping of environments
-		const std::unordered_map< ReferenceToType *, TypeSubstitution * > & envMap;
-	public:
-		GenericInstantiator( const std::unordered_map< ReferenceToType *, TypeSubstitution * > & envMap ) : DeclMutator(), instantiations(), dtypeStatics(), typeNamer("_conc_"), envMap( envMap ) {}
-
-		using DeclMutator::mutate;
-		virtual Type* mutate( StructInstType *inst ) override;
-		virtual Type* mutate( UnionInstType *inst ) override;
-
-		virtual void doBeginScope() override;
-		virtual void doEndScope() override;
+		/// Should not make use of type environment to replace types of function parameter and return values.
+		bool inFunctionType = false;
+		GenericInstantiator() : instantiations(), dtypeStatics(), typeNamer("_conc_") {}
+
+		Type* postmutate( StructInstType *inst );
+		Type* postmutate( UnionInstType *inst );
+
+		void premutate( FunctionType * ftype ) {
+			GuardValue( inFunctionType );
+			inFunctionType = true;
+		}
+
+		void beginScope();
+		void endScope();
 	private:
 		/// Wrap instantiation lookup for structs
@@ -207,8 +196,6 @@
 
 	void instantiateGeneric( std::list< Declaration* > &translationUnit ) {
-		EnvFinder finder;
-		mutateAll( translationUnit, finder );
-		GenericInstantiator instantiator( finder.envMap );
-		instantiator.mutateDeclarationList( translationUnit );
+		PassVisitor<GenericInstantiator> instantiator;
+		mutateAll( translationUnit, instantiator );
 	}
 
@@ -306,6 +293,5 @@
 	Type *GenericInstantiator::replaceWithConcrete( Type *type, bool doClone ) {
 		if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
-			if ( envMap.count( typeInst ) ) {
-				TypeSubstitution * env = envMap.at( typeInst );
+			if ( env && ! inFunctionType ) {
 				Type *concrete = env->lookup( typeInst->get_name() );
 				if ( concrete ) {
@@ -331,10 +317,5 @@
 
 
-	Type* GenericInstantiator::mutate( StructInstType *inst ) {
-		// mutate subtypes
-		Type *mutated = Mutator::mutate( inst );
-		inst = dynamic_cast< StructInstType* >( mutated );
-		if ( ! inst ) return mutated;
-
+	Type* GenericInstantiator::postmutate( StructInstType *inst ) {
 		// exit early if no need for further mutation
 		if ( inst->get_parameters().empty() ) return inst;
@@ -368,6 +349,6 @@
 				substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
 				insert( inst, typeSubs, concDecl ); // must insert before recursion
-				concDecl->acceptMutator( *this ); // recursively instantiate members
-				DeclMutator::addDeclaration( concDecl ); // must occur before declaration is added so that member instantiations appear first
+				concDecl->acceptMutator( *visitor ); // recursively instantiate members
+				declsToAddBefore.push_back( concDecl ); // must occur before declaration is added so that member instantiations appear first
 			}
 			StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() );
@@ -388,10 +369,5 @@
 	}
 
-	Type* GenericInstantiator::mutate( UnionInstType *inst ) {
-		// mutate subtypes
-		Type *mutated = Mutator::mutate( inst );
-		inst = dynamic_cast< UnionInstType* >( mutated );
-		if ( ! inst ) return mutated;
-
+	Type* GenericInstantiator::postmutate( UnionInstType *inst ) {
 		// exit early if no need for further mutation
 		if ( inst->get_parameters().empty() ) return inst;
@@ -423,6 +399,6 @@
 				substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
 				insert( inst, typeSubs, concDecl ); // must insert before recursion
-				concDecl->acceptMutator( *this ); // recursively instantiate members
-				DeclMutator::addDeclaration( concDecl ); // must occur before declaration is added so that member instantiations appear first
+				concDecl->acceptMutator( *visitor ); // recursively instantiate members
+				declsToAddBefore.push_back( concDecl ); // must occur before declaration is added so that member instantiations appear first
 			}
 			UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() );
@@ -442,12 +418,10 @@
 	}
 
-	void GenericInstantiator::doBeginScope() {
-		DeclMutator::doBeginScope();
+	void GenericInstantiator::beginScope() {
 		instantiations.beginScope();
 		dtypeStatics.beginScope();
 	}
 
-	void GenericInstantiator::doEndScope() {
-		DeclMutator::doEndScope();
+	void GenericInstantiator::endScope() {
 		instantiations.endScope();
 		dtypeStatics.endScope();
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision fe5c01dc12bdff1880c53a48f4b74eb6262c2008)
+++ src/InitTweak/GenInit.cc	(revision 949934ef4a9c85ee6b2393cde997ad480d65a7af)
@@ -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 fe5c01dc12bdff1880c53a48f4b74eb6262c2008)
+++ src/SymTab/Validate.cc	(revision 949934ef4a9c85ee6b2393cde997ad480d65a7af)
@@ -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 );
 	}
 
