Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/CodeGen/CodeGenerator.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -443,11 +443,11 @@
 	void CodeGenerator::postvisit( UntypedExpr * untypedExpr ) {
 		extension( untypedExpr );
-		if ( NameExpr * nameExpr = dynamic_cast< NameExpr* >( untypedExpr->get_function() ) ) {
+		if ( NameExpr * nameExpr = dynamic_cast< NameExpr* >( untypedExpr->function ) ) {
 			OperatorInfo opInfo;
-			if ( operatorLookup( nameExpr->get_name(), opInfo ) ) {
-				std::list< Expression* >::iterator arg = untypedExpr->get_args().begin();
+			if ( operatorLookup( nameExpr->name, opInfo ) ) {
+				std::list< Expression* >::iterator arg = untypedExpr->args.begin();
 				switch ( opInfo.type ) {
 				  case OT_INDEX:
-					assert( untypedExpr->get_args().size() == 2 );
+					assert( untypedExpr->args.size() == 2 );
 					(*arg++)->accept( *visitor );
 					output << "[";
@@ -461,5 +461,5 @@
 				  case OT_CTOR:
 				  case OT_DTOR:
-					if ( untypedExpr->get_args().size() == 1 ) {
+					if ( untypedExpr->args.size() == 1 ) {
 						// the expression fed into a single parameter constructor or destructor may contain side
 						// effects, so must still output this expression
@@ -480,5 +480,5 @@
 						(*arg++)->accept( *visitor );
 						output << opInfo.symbol << "{ ";
-						genCommaList( arg, untypedExpr->get_args().end() );
+						genCommaList( arg, untypedExpr->args.end() );
 						output << "}) /* " << opInfo.inputName << " */";
 					} // if
@@ -488,5 +488,5 @@
 				  case OT_PREFIXASSIGN:
 				  case OT_LABELADDRESS:
-					assert( untypedExpr->get_args().size() == 1 );
+					assert( untypedExpr->args.size() == 1 );
 					output << "(";
 					output << opInfo.symbol;
@@ -497,5 +497,5 @@
 				  case OT_POSTFIX:
 				  case OT_POSTFIXASSIGN:
-					assert( untypedExpr->get_args().size() == 1 );
+					assert( untypedExpr->args.size() == 1 );
 					(*arg)->accept( *visitor );
 					output << opInfo.symbol;
@@ -504,5 +504,5 @@
 				  case OT_INFIX:
 				  case OT_INFIXASSIGN:
-					assert( untypedExpr->get_args().size() == 2 );
+					assert( untypedExpr->args.size() == 2 );
 					output << "(";
 					(*arg++)->accept( *visitor );
@@ -517,20 +517,14 @@
 				} // switch
 			} else {
-				if ( nameExpr->get_name() == "..." ) { // case V1 ... V2 or case V1~V2
-					assert( untypedExpr->get_args().size() == 2 );
-					(*untypedExpr->get_args().begin())->accept( *visitor );
-					output << " ... ";
-					(*--untypedExpr->get_args().end())->accept( *visitor );
-				} else {								// builtin routines
-					nameExpr->accept( *visitor );
-					output << "(";
-					genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
-					output << ")";
-				} // if
+				// builtin routines
+				nameExpr->accept( *visitor );
+				output << "(";
+				genCommaList( untypedExpr->args.begin(), untypedExpr->args.end() );
+				output << ")";
 			} // if
 		} else {
-			untypedExpr->get_function()->accept( *visitor );
+			untypedExpr->function->accept( *visitor );
 			output << "(";
-			genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
+			genCommaList( untypedExpr->args.begin(), untypedExpr->args.end() );
 			output << ")";
 		} // if
@@ -538,7 +532,7 @@
 
 	void CodeGenerator::postvisit( RangeExpr * rangeExpr ) {
-		rangeExpr->get_low()->accept( *visitor );
+		rangeExpr->low->accept( *visitor );
 		output << " ... ";
-		rangeExpr->get_high()->accept( *visitor );
+		rangeExpr->high->accept( *visitor );
 	}
 
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/GenPoly/Box.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -32,5 +32,4 @@
 #include "Common/UniqueName.h"           // for UniqueName
 #include "Common/utility.h"              // for toString
-#include "DeclMutator.h"                 // for DeclMutator
 #include "FindFunction.h"                // for findFunction, findAndReplace...
 #include "GenPoly/ErasableScopedMap.h"   // for ErasableScopedMap<>::const_i...
@@ -39,5 +38,4 @@
 #include "Lvalue.h"                      // for generalizedLvalue
 #include "Parser/LinkageSpec.h"          // for C, Spec, Cforall, Intrinsic
-#include "PolyMutator.h"                 // for PolyMutator
 #include "ResolvExpr/TypeEnvironment.h"  // for EqvClass
 #include "ResolvExpr/typeops.h"          // for typesCompatible
@@ -62,35 +60,37 @@
 		FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars );
 
+		class BoxPass {
+		protected:
+			BoxPass() : scopeTyVars( TypeDecl::Data{} ) {}
+			TyVarMap scopeTyVars;
+		};
+
 		/// Adds layout-generation functions to polymorphic types
-		class LayoutFunctionBuilder final : public DeclMutator {
-			unsigned int functionNesting;  // current level of nested functions
+		class LayoutFunctionBuilder final : public WithDeclsToAdd, public WithVisitorRef<LayoutFunctionBuilder>, public WithShortCircuiting {
+			unsigned int functionNesting = 0;  // current level of nested functions
 		public:
-			LayoutFunctionBuilder() : functionNesting( 0 ) {}
-
-			using DeclMutator::mutate;
-			virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override;
-			virtual Declaration *mutate( StructDecl *structDecl ) override;
-			virtual Declaration *mutate( UnionDecl *unionDecl ) override;
+			void previsit( FunctionDecl *functionDecl );
+			void previsit( StructDecl *structDecl );
+			void previsit( UnionDecl *unionDecl );
 		};
 
 		/// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call
-		class Pass1 final : public PolyMutator {
+		class Pass1 final : public BoxPass, public WithTypeSubstitution, public WithStmtsToAdd, public WithGuards, public WithVisitorRef<Pass1>, public WithShortCircuiting {
 		  public:
 			Pass1();
 
-			using PolyMutator::mutate;
-			virtual Expression *mutate( ApplicationExpr *appExpr ) override;
-			virtual Expression *mutate( AddressExpr *addrExpr ) override;
-			virtual Expression *mutate( UntypedExpr *expr ) override;
-			virtual DeclarationWithType* mutate( FunctionDecl *functionDecl ) override;
-			virtual TypeDecl *mutate( TypeDecl *typeDecl ) override;
-			virtual Expression *mutate( CommaExpr *commaExpr ) override;
-			virtual Expression *mutate( ConditionalExpr *condExpr ) override;
-			virtual Statement * mutate( ReturnStmt *returnStmt ) override;
-			virtual Type *mutate( PointerType *pointerType ) override;
-			virtual Type * mutate( FunctionType *functionType ) override;
-
-			virtual void doBeginScope() override;
-			virtual void doEndScope() override;
+			void premutate( FunctionDecl * functionDecl );
+			void premutate( TypeDecl * typeDecl );
+			void premutate( CommaExpr * commaExpr );
+			Expression * postmutate( ApplicationExpr * appExpr );
+			Expression * postmutate( UntypedExpr *expr );
+			void premutate( AddressExpr * addrExpr );
+			Expression * postmutate( AddressExpr * addrExpr );
+			void premutate( ReturnStmt * returnStmt );
+			void premutate( PointerType * pointerType );
+			void premutate( FunctionType * functionType );
+
+			void beginScope();
+			void endScope();
 		  private:
 			/// Pass the extra type parameters from polymorphic generic arguments or return types into a function application
@@ -129,22 +129,14 @@
 		/// * Moves polymorphic returns in function types to pointer-type parameters
 		/// * adds type size and assertion parameters to parameter lists
-		class Pass2 final : public PolyMutator {
-		  public:
-			template< typename DeclClass >
-			DeclClass *handleDecl( DeclClass *decl );
-			template< typename AggDecl >
-			AggDecl * handleAggDecl( AggDecl * aggDecl );
-
-			typedef PolyMutator Parent;
-			using Parent::mutate;
-			virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override;
-			virtual ObjectDecl *mutate( ObjectDecl *objectDecl ) override;
-			virtual StructDecl *mutate( StructDecl *structDecl ) override;
-			virtual UnionDecl *mutate( UnionDecl *unionDecl ) override;
-			virtual TraitDecl *mutate( TraitDecl *unionDecl ) override;
-			virtual TypeDecl *mutate( TypeDecl *typeDecl ) override;
-			virtual TypedefDecl *mutate( TypedefDecl *typedefDecl ) override;
-			virtual Type *mutate( PointerType *pointerType ) override;
-			virtual Type *mutate( FunctionType *funcType ) override;
+		struct Pass2 final : public BoxPass, public WithGuards {
+			void handleAggDecl();
+
+			DeclarationWithType * postmutate( FunctionDecl *functionDecl );
+			void premutate( StructDecl *structDecl );
+			void premutate( UnionDecl *unionDecl );
+			void premutate( TraitDecl *unionDecl );
+			void premutate( TypeDecl *typeDecl );
+			void premutate( PointerType *pointerType );
+			void premutate( FunctionType *funcType );
 
 		  private:
@@ -158,5 +150,5 @@
 		/// * Calculates polymorphic offsetof expressions from offset array
 		/// * Inserts dynamic calculation of polymorphic type layouts where needed
-		class PolyGenericCalculator final : public WithGuards, public WithVisitorRef<PolyGenericCalculator>, public WithStmtsToAdd, public WithDeclsToAdd, public WithTypeSubstitution {
+		class PolyGenericCalculator final : public BoxPass, public WithGuards, public WithVisitorRef<PolyGenericCalculator>, public WithStmtsToAdd, public WithDeclsToAdd, public WithTypeSubstitution {
 		public:
 			PolyGenericCalculator();
@@ -197,23 +189,19 @@
 			ScopedSet< std::string > knownOffsets;          ///< Set of non-generic types for which the offset array exists in the current scope, indexed by offsetofName
 			UniqueName bufNamer;                           ///< Namer for VLA buffers
-			TyVarMap scopeTyVars;
 		};
 
 		/// Replaces initialization of polymorphic values with alloca, declaration of dtype/ftype with appropriate void expression, sizeof expressions of polymorphic types with the proper variable, and strips fields from generic struct declarations.
-		class Pass3 final : public PolyMutator {
-		  public:
+		struct Pass3 final : public BoxPass, public WithGuards {
 			template< typename DeclClass >
-			DeclClass *handleDecl( DeclClass *decl, Type *type );
-
-			using PolyMutator::mutate;
-			virtual DeclarationWithType *mutate( FunctionDecl *functionDecl ) override;
-			virtual Declaration *mutate( StructDecl *structDecl ) override;
-			virtual Declaration *mutate( UnionDecl *unionDecl ) override;
-			virtual ObjectDecl *mutate( ObjectDecl *objectDecl ) override;
-			virtual TypedefDecl *mutate( TypedefDecl *objectDecl ) override;
-			virtual TypeDecl *mutate( TypeDecl *objectDecl ) override;
-			virtual Type *mutate( PointerType *pointerType ) override;
-			virtual Type *mutate( FunctionType *funcType ) override;
-		  private:
+			void handleDecl( DeclClass * decl, Type * type );
+
+			void premutate( ObjectDecl * objectDecl );
+			void premutate( FunctionDecl * functionDecl );
+			void premutate( TypedefDecl * typedefDecl );
+			void premutate( StructDecl * structDecl );
+			void premutate( UnionDecl * unionDecl );
+			void premutate( TypeDecl * typeDecl );
+			void premutate( PointerType * pointerType );
+			void premutate( FunctionType * funcType );
 		};
 	} // anonymous namespace
@@ -247,25 +235,25 @@
 
 	void box( std::list< Declaration *>& translationUnit ) {
-		LayoutFunctionBuilder layoutBuilder;
-		Pass1 pass1;
-		Pass2 pass2;
+		PassVisitor<LayoutFunctionBuilder> layoutBuilder;
+		PassVisitor<Pass1> pass1;
+		PassVisitor<Pass2> pass2;
 		PassVisitor<PolyGenericCalculator> polyCalculator;
-		Pass3 pass3;
-
-		layoutBuilder.mutateDeclarationList( translationUnit );
-		mutateTranslationUnit/*All*/( translationUnit, pass1 );
-		mutateTranslationUnit/*All*/( translationUnit, pass2 );
+		PassVisitor<Pass3> pass3;
+
+		acceptAll( translationUnit, layoutBuilder );
+		mutateAll( translationUnit, pass1 );
+		mutateAll( translationUnit, pass2 );
 		mutateAll( translationUnit, polyCalculator );
-		mutateTranslationUnit/*All*/( translationUnit, pass3 );
+		mutateAll( translationUnit, pass3 );
 	}
 
 	////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////
 
-	DeclarationWithType *LayoutFunctionBuilder::mutate( FunctionDecl *functionDecl ) {
-		functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
+	void LayoutFunctionBuilder::previsit( FunctionDecl *functionDecl ) {
+		visit_children = false;
+		maybeAccept( functionDecl->get_functionType(), *visitor );
 		++functionNesting;
-		functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
+		maybeAccept( functionDecl->get_statements(), *visitor );
 		--functionNesting;
-		return functionDecl;
 	}
 
@@ -356,11 +344,12 @@
 	}
 
-	Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) {
+	void LayoutFunctionBuilder::previsit( StructDecl *structDecl ) {
 		// do not generate layout function for "empty" tag structs
-		if ( structDecl->get_members().empty() ) return structDecl;
+		visit_children = false;
+		if ( structDecl->get_members().empty() ) return;
 
 		// get parameters that can change layout, exiting early if none
 		std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() );
-		if ( otypeParams.empty() ) return structDecl;
+		if ( otypeParams.empty() ) return;
 
 		// build layout function signature
@@ -413,15 +402,15 @@
 		addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
 
-		addDeclarationAfter( layoutDecl );
-		return structDecl;
+		declsToAddAfter.push_back( layoutDecl );
 	}
 
-	Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) {
+	void LayoutFunctionBuilder::previsit( UnionDecl *unionDecl ) {
 		// do not generate layout function for "empty" tag unions
-		if ( unionDecl->get_members().empty() ) return unionDecl;
+		visit_children = false;
+		if ( unionDecl->get_members().empty() ) return;
 
 		// get parameters that can change layout, exiting early if none
 		std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );
-		if ( otypeParams.empty() ) return unionDecl;
+		if ( otypeParams.empty() ) return;
 
 		// build layout function signature
@@ -456,6 +445,5 @@
 		addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
 
-		addDeclarationAfter( layoutDecl );
-		return unionDecl;
+		declsToAddAfter.push_back( layoutDecl );
 	}
 
@@ -501,31 +489,29 @@
 		Pass1::Pass1() : tempNamer( "_temp" ) {}
 
-		DeclarationWithType *Pass1::mutate( FunctionDecl *functionDecl ) {
+		void Pass1::premutate( FunctionDecl *functionDecl ) {
 			if ( functionDecl->get_statements() ) {		// empty routine body ?
 				// std::cerr << "mutating function: " << functionDecl->get_mangleName() << std::endl;
-				doBeginScope();
-				scopeTyVars.beginScope();
-
-				DeclarationWithType *oldRetval = retval;
+				GuardScope( scopeTyVars );
+				GuardValue( retval );
 
 				// process polymorphic return value
 				retval = nullptr;
-				if ( isDynRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() != LinkageSpec::C ) {
-					retval = functionDecl->get_functionType()->get_returnVals().front();
+				FunctionType *functionType = functionDecl->type;
+				if ( isDynRet( functionType ) && functionDecl->linkage != LinkageSpec::C ) {
+					retval = functionType->returnVals.front();
 
 					// give names to unnamed return values
-					if ( retval->get_name() == "" ) {
-						retval->set_name( "_retparm" );
-						retval->set_linkage( LinkageSpec::C );
+					if ( retval->name == "" ) {
+						retval->name = "_retparm";
+						retval->linkage = LinkageSpec::C;
 					} // if
 				} // if
 
-				FunctionType *functionType = functionDecl->get_functionType();
-				makeTyVarMap( functionDecl->get_functionType(), scopeTyVars );
-
-				std::list< DeclarationWithType *> &paramList = functionType->get_parameters();
+				makeTyVarMap( functionType, scopeTyVars );
+
+				std::list< DeclarationWithType *> &paramList = functionType->parameters;
 				std::list< FunctionType *> functions;
-				for ( Type::ForallList::iterator tyVar = functionType->get_forall().begin(); tyVar != functionType->get_forall().end(); ++tyVar ) {
-					for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->get_assertions().begin(); assert != (*tyVar)->get_assertions().end(); ++assert ) {
+				for ( Type::ForallList::iterator tyVar = functionType->forall.begin(); tyVar != functionType->forall.end(); ++tyVar ) {
+					for ( std::list< DeclarationWithType *>::iterator assert = (*tyVar)->assertions.begin(); assert != (*tyVar)->assertions.end(); ++assert ) {
 						findFunction( (*assert)->get_type(), functions, scopeTyVars, needsAdapter );
 					} // for
@@ -542,21 +528,13 @@
 					} // if
 				} // for
-
-				functionDecl->set_statements( functionDecl->get_statements()->acceptMutator( *this ) );
-
-				scopeTyVars.endScope();
-				retval = oldRetval;
-				doEndScope();
 				// std::cerr << "end function: " << functionDecl->get_mangleName() << std::endl;
 			} // if
-			return functionDecl;
-		}
-
-		TypeDecl *Pass1::mutate( TypeDecl *typeDecl ) {
+		}
+
+		void Pass1::premutate( TypeDecl *typeDecl ) {
 			addToTyVarMap( typeDecl, scopeTyVars );
-			return dynamic_cast<TypeDecl*>( Mutator::mutate( typeDecl ) );
-		}
-
-		Expression *Pass1::mutate( CommaExpr *commaExpr ) {
+		}
+
+		void Pass1::premutate( CommaExpr *commaExpr ) {
 			// Attempting to find application expressions that were mutated by the copy constructor passes
 			// to use an explicit return variable, so that the variable can be reused as a parameter to the
@@ -574,16 +552,4 @@
 				}
 			}
-
-			commaExpr->set_arg1( maybeMutate( commaExpr->get_arg1(), *this ) );
-			commaExpr->set_arg2( maybeMutate( commaExpr->get_arg2(), *this ) );
-			return commaExpr;
-		}
-
-		Expression *Pass1::mutate( ConditionalExpr *condExpr ) {
-			condExpr->set_arg1( maybeMutate( condExpr->get_arg1(), *this ) );
-			condExpr->set_arg2( maybeMutate( condExpr->get_arg2(), *this ) );
-			condExpr->set_arg3( maybeMutate( condExpr->get_arg3(), *this ) );
-			return condExpr;
-
 		}
 
@@ -659,5 +625,5 @@
 		ObjectDecl *Pass1::makeTemporary( Type *type ) {
 			ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, type, 0 );
-			stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
+			stmtsToAddBefore.push_back( new DeclStmt( noLabels, newObj ) );
 			return newObj;
 		}
@@ -775,9 +741,9 @@
 					ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, newType, 0 );
 					newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
-					stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) );
+					stmtsToAddBefore.push_back( new DeclStmt( noLabels, newObj ) );
 					UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); // TODO: why doesn't this just use initialization syntax?
 					assign->get_args().push_back( new VariableExpr( newObj ) );
 					assign->get_args().push_back( arg );
-					stmtsToAdd.push_back( new ExprStmt( noLabels, assign ) );
+					stmtsToAddBefore.push_back( new ExprStmt( noLabels, assign ) );
 					arg = new AddressExpr( new VariableExpr( newObj ) );
 				} // if
@@ -961,5 +927,5 @@
 						std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
 						adapter = answer.first;
-						stmtsToAdd.push_back( new DeclStmt( noLabels, newAdapter ) );
+						stmtsToAddBefore.push_back( new DeclStmt( noLabels, newAdapter ) );
 					} // if
 					assert( adapter != adapters.end() );
@@ -1118,5 +1084,5 @@
 		}
 
-		Expression *Pass1::mutate( ApplicationExpr *appExpr ) {
+		Expression *Pass1::postmutate( ApplicationExpr *appExpr ) {
 			// std::cerr << "mutate appExpr: " << InitTweak::getFunctionName( appExpr ) << std::endl;
 			// for ( TyVarMap::iterator i = scopeTyVars.begin(); i != scopeTyVars.end(); ++i ) {
@@ -1124,10 +1090,8 @@
 			// }
 			// std::cerr << "\n";
-			appExpr->get_function()->acceptMutator( *this );
-			mutateAll( appExpr->get_args(), *this );
-
-			assert( appExpr->get_function()->has_result() );
-			FunctionType * function = getFunctionType( appExpr->get_function()->get_result() );
-			assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->get_function()->get_result() ).c_str() );
+
+			assert( appExpr->function->result );
+			FunctionType * function = getFunctionType( appExpr->function->result );
+			assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() );
 
 			if ( Expression *newExpr = handleIntrinsics( appExpr ) ) {
@@ -1182,19 +1146,20 @@
 		}
 
-		Expression *Pass1::mutate( UntypedExpr *expr ) {
-			if ( expr->has_result() && isPolyType( expr->get_result(), scopeTyVars, env ) ) {
-				if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->get_function() ) ) {
+		Expression * Pass1::postmutate( UntypedExpr *expr ) {
+			if ( expr->result && isPolyType( expr->result, scopeTyVars, env ) ) {
+				if ( NameExpr *name = dynamic_cast< NameExpr *>( expr->function ) ) {
 					if ( name->get_name() == "*?" ) {
-						Expression *ret = expr->get_args().front();
-						expr->get_args().clear();
+						Expression *ret = expr->args.front();
+						expr->args.clear();
 						delete expr;
-						return ret->acceptMutator( *this );
+						return ret;
 					} // if
 				} // if
 			} // if
-			return PolyMutator::mutate( expr );
-		}
-
-		Expression *Pass1::mutate( AddressExpr *addrExpr ) {
+			return expr;
+		}
+
+		void Pass1::premutate( AddressExpr * ) { visit_children = false; }
+		Expression * Pass1::postmutate( AddressExpr * addrExpr ) {
 			assert( addrExpr->get_arg()->has_result() && ! addrExpr->get_arg()->get_result()->isVoid() );
 
@@ -1216,5 +1181,5 @@
 			// isPolyType check needs to happen before mutating addrExpr arg, so pull it forward
 			// out of the if condition.
-			addrExpr->set_arg( mutateExpression( addrExpr->get_arg() ) );
+			addrExpr->arg = addrExpr->get_arg()->acceptMutator( *visitor );
 			// ... but must happen after mutate, since argument might change (e.g. intrinsic *?, ?[?]) - re-evaluate above comment
 			bool polytype = isPolyType( addrExpr->get_arg()->get_result(), scopeTyVars, env );
@@ -1231,40 +1196,27 @@
 		}
 
-		Statement * Pass1::mutate( ReturnStmt *returnStmt ) {
-			if ( retval && returnStmt->get_expr() ) {
-				assert( returnStmt->get_expr()->has_result() && ! returnStmt->get_expr()->get_result()->isVoid() );
-				delete returnStmt->get_expr();
-				returnStmt->set_expr( 0 );
-			} else {
-				returnStmt->set_expr( mutateExpression( returnStmt->get_expr() ) );
+		void Pass1::premutate( ReturnStmt *returnStmt ) {
+			if ( retval && returnStmt->expr ) {
+				assert( returnStmt->expr->result && ! returnStmt->expr->result->isVoid() );
+				delete returnStmt->expr;
+				returnStmt->expr = nullptr;
 			} // if
-			return returnStmt;
-		}
-
-		Type * Pass1::mutate( PointerType *pointerType ) {
-			scopeTyVars.beginScope();
+		}
+
+		void Pass1::premutate( PointerType *pointerType ) {
+			GuardScope( scopeTyVars );
 			makeTyVarMap( pointerType, scopeTyVars );
-
-			Type *ret = Mutator::mutate( pointerType );
-
-			scopeTyVars.endScope();
-			return ret;
-		}
-
-		Type * Pass1::mutate( FunctionType *functionType ) {
-			scopeTyVars.beginScope();
+		}
+
+		void Pass1::premutate( FunctionType *functionType ) {
+			GuardScope( scopeTyVars );
 			makeTyVarMap( functionType, scopeTyVars );
-
-			Type *ret = Mutator::mutate( functionType );
-
-			scopeTyVars.endScope();
-			return ret;
-		}
-
-		void Pass1::doBeginScope() {
+		}
+
+		void Pass1::beginScope() {
 			adapters.beginScope();
 		}
 
-		void Pass1::doEndScope() {
+		void Pass1::endScope() {
 			adapters.endScope();
 		}
@@ -1293,13 +1245,5 @@
 		}
 
-		template< typename DeclClass >
-		DeclClass * Pass2::handleDecl( DeclClass *decl ) {
-			DeclClass *ret = static_cast< DeclClass *>( Parent::mutate( decl ) );
-
-			return ret;
-		}
-
-		DeclarationWithType * Pass2::mutate( FunctionDecl *functionDecl ) {
-			functionDecl = strict_dynamic_cast< FunctionDecl * > ( handleDecl( functionDecl ) );
+		DeclarationWithType * Pass2::postmutate( FunctionDecl *functionDecl ) {
 			FunctionType * ftype = functionDecl->get_functionType();
 			if ( ! ftype->get_returnVals().empty() && functionDecl->get_statements() ) {
@@ -1325,55 +1269,30 @@
 		}
 
-		ObjectDecl * Pass2::mutate( ObjectDecl *objectDecl ) {
-			return handleDecl( objectDecl );
-		}
-
-		template< typename AggDecl >
-		AggDecl * Pass2::handleAggDecl( AggDecl * aggDecl ) {
+		void Pass2::premutate( StructDecl * ) {
 			// prevent tyVars from leaking into containing scope
-			scopeTyVars.beginScope();
-			Parent::mutate( aggDecl );
-			scopeTyVars.endScope();
-			return aggDecl;
-		}
-
-		StructDecl * Pass2::mutate( StructDecl *aggDecl ) {
-			return handleAggDecl( aggDecl );
-		}
-
-		UnionDecl * Pass2::mutate( UnionDecl *aggDecl ) {
-			return handleAggDecl( aggDecl );
-		}
-
-		TraitDecl * Pass2::mutate( TraitDecl *aggDecl ) {
-			return handleAggDecl( aggDecl );
-		}
-
-		TypeDecl * Pass2::mutate( TypeDecl *typeDecl ) {
+			GuardScope( scopeTyVars );
+		}
+
+		void Pass2::premutate( UnionDecl * ) {
+			// prevent tyVars from leaking into containing scope
+			GuardScope( scopeTyVars );
+		}
+
+		void Pass2::premutate( TraitDecl * ) {
+			// prevent tyVars from leaking into containing scope
+			GuardScope( scopeTyVars );
+		}
+
+		void Pass2::premutate( TypeDecl *typeDecl ) {
 			addToTyVarMap( typeDecl, scopeTyVars );
-			if ( typeDecl->get_base() ) {
-				return handleDecl( typeDecl );
-			} else {
-				return dynamic_cast<TypeDecl*>( Parent::mutate( typeDecl ) );
-			}
-		}
-
-		TypedefDecl * Pass2::mutate( TypedefDecl *typedefDecl ) {
-			return handleDecl( typedefDecl );
-		}
-
-		Type * Pass2::mutate( PointerType *pointerType ) {
-			scopeTyVars.beginScope();
+		}
+
+		void Pass2::premutate( PointerType *pointerType ) {
+			GuardScope( scopeTyVars );
 			makeTyVarMap( pointerType, scopeTyVars );
-
-			Type *ret = Parent::mutate( pointerType );
-
-			scopeTyVars.endScope();
-			return ret;
-		}
-
-		Type *Pass2::mutate( FunctionType *funcType ) {
-			scopeTyVars.beginScope();
-
+		}
+
+		void Pass2::premutate( FunctionType *funcType ) {
+			GuardScope( scopeTyVars );
 			makeTyVarMap( funcType, scopeTyVars );
 
@@ -1414,5 +1333,4 @@
 				// move all assertions into parameter list
 				for ( std::list< DeclarationWithType *>::iterator assert = (*tyParm)->get_assertions().begin(); assert != (*tyParm)->get_assertions().end(); ++assert ) {
-//      *assert = (*assert)->acceptMutator( *this );
 					// assertion parameters may not be used in body, pass along with unused attribute.
 					(*assert)->get_attributes().push_back( new Attribute( "unused" ) );
@@ -1450,5 +1368,4 @@
 						}
 					}
-
 					seenTypes.insert( typeName );
 				}
@@ -1458,9 +1375,4 @@
 			funcType->get_parameters().splice( last, inferredParams );
 			addAdapters( funcType );
-			mutateAll( funcType->get_returnVals(), *this );
-			mutateAll( funcType->get_parameters(), *this );
-
-			scopeTyVars.endScope();
-			return funcType;
 		}
 
@@ -1468,5 +1380,5 @@
 
 		PolyGenericCalculator::PolyGenericCalculator()
-			: knownLayouts(), knownOffsets(), bufNamer( "_buf" ), scopeTyVars( TypeDecl::Data{} ) {}
+			: knownLayouts(), knownOffsets(), bufNamer( "_buf" ) {}
 
 		void PolyGenericCalculator::beginTypeScope( Type *ty ) {
@@ -1829,74 +1741,47 @@
 
 		template< typename DeclClass >
-		DeclClass * Pass3::handleDecl( DeclClass *decl, Type *type ) {
-			scopeTyVars.beginScope();
+		void Pass3::handleDecl( DeclClass * decl, Type * type ) {
+			GuardScope( scopeTyVars );
 			makeTyVarMap( type, scopeTyVars );
-
-			DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
-			// ScrubTyVars::scrub( decl, scopeTyVars );
 			ScrubTyVars::scrubAll( decl );
-
-			scopeTyVars.endScope();
-			return ret;
-		}
-
-		ObjectDecl * Pass3::mutate( ObjectDecl *objectDecl ) {
-			return handleDecl( objectDecl, objectDecl->get_type() );
-		}
-
-		DeclarationWithType * Pass3::mutate( FunctionDecl *functionDecl ) {
-			return handleDecl( functionDecl, functionDecl->get_functionType() );
-		}
-
-		TypedefDecl * Pass3::mutate( TypedefDecl *typedefDecl ) {
-			return handleDecl( typedefDecl, typedefDecl->get_base() );
+		}
+
+		void Pass3::premutate( ObjectDecl * objectDecl ) {
+			handleDecl( objectDecl, objectDecl->type );
+		}
+
+		void Pass3::premutate( FunctionDecl * functionDecl ) {
+			handleDecl( functionDecl, functionDecl->type );
+		}
+
+		void Pass3::premutate( TypedefDecl * typedefDecl ) {
+			handleDecl( typedefDecl, typedefDecl->base );
 		}
 
 		/// Strips the members from a generic aggregate
-		void stripGenericMembers(AggregateDecl* decl) {
-			if ( ! decl->get_parameters().empty() ) decl->get_members().clear();
-		}
-
-		Declaration *Pass3::mutate( StructDecl *structDecl ) {
+		void stripGenericMembers(AggregateDecl * decl) {
+			if ( ! decl->parameters.empty() ) decl->members.clear();
+		}
+
+		void Pass3::premutate( StructDecl * structDecl ) {
 			stripGenericMembers( structDecl );
-			return structDecl;
-		}
-
-		Declaration *Pass3::mutate( UnionDecl *unionDecl ) {
+		}
+
+		void Pass3::premutate( UnionDecl * unionDecl ) {
 			stripGenericMembers( unionDecl );
-			return unionDecl;
-		}
-
-		TypeDecl * Pass3::mutate( TypeDecl *typeDecl ) {
-//   Initializer *init = 0;
-//   std::list< Expression *> designators;
-//   addToTyVarMap( typeDecl, scopeTyVars );
-//   if ( typeDecl->get_base() ) {
-//     init = new SimpleInit( new SizeofExpr( handleDecl( typeDecl, typeDecl->get_base() ) ), designators );
-//   }
-//   return new ObjectDecl( typeDecl->get_name(), Declaration::Extern, LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::UnsignedInt ), init );
-
+		}
+
+		void Pass3::premutate( TypeDecl * typeDecl ) {
 			addToTyVarMap( typeDecl, scopeTyVars );
-			return dynamic_cast<TypeDecl*>( Mutator::mutate( typeDecl ) );
-		}
-
-		Type * Pass3::mutate( PointerType *pointerType ) {
-			scopeTyVars.beginScope();
+		}
+
+		void Pass3::premutate( PointerType * pointerType ) {
+			GuardScope( scopeTyVars );
 			makeTyVarMap( pointerType, scopeTyVars );
-
-			Type *ret = Mutator::mutate( pointerType );
-
-			scopeTyVars.endScope();
-			return ret;
-		}
-
-		Type * Pass3::mutate( FunctionType *functionType ) {
-			scopeTyVars.beginScope();
+		}
+
+		void Pass3::premutate( FunctionType * functionType ) {
+			GuardScope( scopeTyVars );
 			makeTyVarMap( functionType, scopeTyVars );
-
-			Type *ret = Mutator::mutate( functionType );
-
-			scopeTyVars.endScope();
-			return ret;
 		}
 	} // anonymous namespace
Index: src/GenPoly/DeclMutator.cc
===================================================================
--- src/GenPoly/DeclMutator.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ 	(revision )
@@ -1,195 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// DeclMutator.cc --
-//
-// Author           : Aaron B. Moss
-// Created On       : Fri Nov 27 14:44:00 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Thu Jun 22 13:49:00 2017
-// Update Count     : 4
-//
-
-#include "DeclMutator.h"
-
-#include <memory>                  // for allocator_traits<>::value_type
-
-#include "Common/SemanticError.h"  // for SemanticError
-#include "SynTree/Declaration.h"   // for Declaration
-#include "SynTree/Expression.h"    // for Expression
-#include "SynTree/Label.h"         // for Label, noLabels
-#include "SynTree/Statement.h"     // for CatchStmt, Statement, CompoundStmt
-
-namespace GenPoly {
-	DeclMutator::DeclMutator() : Mutator(), declsToAdd(1), declsToAddAfter(1) {}
-
-	DeclMutator::~DeclMutator() {}
-
-	void DeclMutator::mutateDeclarationList( std::list< Declaration* > &decls ) {
-		for ( std::list< Declaration* >::iterator decl = decls.begin(); ; ++decl ) {
-			// splice in new declarations after previous decl
-			decls.splice( decl, declsToAddAfter.back() );
-
-			if ( decl == decls.end() ) break;
-
-			// run mutator on declaration
-			*decl = maybeMutate( *decl, *this );
-
-			// splice in new declarations before current decl
-			decls.splice( decl, declsToAdd.back() );
-		}
-	}
-
-	void DeclMutator::doBeginScope() {
-		// add new decl lists for inside of scope
-		declsToAdd.resize( declsToAdd.size()+1 );
-		declsToAddAfter.resize( declsToAddAfter.size()+1 );
-	}
-
-	void DeclMutator::doEndScope() {
-		// splice any leftover declarations from this scope onto the containing scope
-		std::vector< std::list< Declaration* > >::reverse_iterator back = declsToAdd.rbegin();
-		std::vector< std::list< Declaration* > >::reverse_iterator newBack = back + 1;
-		newBack->splice( newBack->end(), *back );
-		declsToAdd.pop_back();
-
-		back = declsToAddAfter.rbegin();
-		newBack = back + 1;
-		newBack->splice( newBack->end(), *back );
-		declsToAddAfter.pop_back();
-	}
-
-	Statement* DeclMutator::mutateStatement( Statement *stmt ) {
-		// shunt over to compound statement handling if applicable
-		CompoundStmt *compoundStmt = dynamic_cast< CompoundStmt* >(stmt);
-		if ( compoundStmt ) return mutate( compoundStmt );
-
-		doBeginScope();
-
-		// run mutator on statement
-		stmt = maybeMutate( stmt, *this );
-		// return if no declarations to add
-		if ( declsToAdd.back().empty() && declsToAddAfter.back().empty() ) {
-			doEndScope();
-			return stmt;
-		}
-
-		// otherwise add declarations to new compound statement
-		CompoundStmt *compound = new CompoundStmt( noLabels );
-		for ( std::list< Declaration* >::iterator decl = declsToAdd.back().begin(); decl != declsToAdd.back().end(); ++decl ) {
-			DeclStmt *declStmt = new DeclStmt( noLabels, *decl );
-			compound->get_kids().push_back( declStmt );
-		}
-		declsToAdd.back().clear();
-
-		// add mutated statement
-		compound->get_kids().push_back( stmt );
-
-		// add declarations after to new compound statement
-		for ( std::list< Declaration* >::iterator decl = declsToAddAfter.back().begin(); decl != declsToAddAfter.back().end(); ++decl ) {
-			DeclStmt *declStmt = new DeclStmt( noLabels, *decl );
-			compound->get_kids().push_back( declStmt );
-		}
-		declsToAddAfter.back().clear();
-
-		doEndScope();
-		return compound;
-	}
-
-	void DeclMutator::mutateStatementList( std::list< Statement* > &stmts ) {
-		doBeginScope();
-
-
-		for ( std::list< Statement* >::iterator stmt = stmts.begin(); ; ++stmt ) {
-			// add any new declarations after the previous statement
-			for ( std::list< Declaration* >::iterator decl = declsToAddAfter.back().begin(); decl != declsToAddAfter.back().end(); ++decl ) {
-				DeclStmt *declStmt = new DeclStmt( noLabels, *decl );
-				stmts.insert( stmt, declStmt );
-			}
-			declsToAddAfter.back().clear();
-
-			if ( stmt == stmts.end() ) break;
-
-			// run mutator on statement
-			*stmt = maybeMutate( *stmt, *this );
-
-			// add any new declarations before the statement
-			for ( std::list< Declaration* >::iterator decl = declsToAdd.back().begin(); decl != declsToAdd.back().end(); ++decl ) {
-				DeclStmt *declStmt = new DeclStmt( noLabels, *decl );
-				stmts.insert( stmt, declStmt );
-			}
-			declsToAdd.back().clear();
-		}
-
-		doEndScope();
-	}
-
-	void DeclMutator::addDeclaration( Declaration *decl ) {
-		declsToAdd.back().push_back( decl );
-	}
-
-	void DeclMutator::addDeclarationAfter( Declaration *decl ) {
-		declsToAddAfter.back().push_back( decl );
-	}
-
-	CompoundStmt* DeclMutator::mutate(CompoundStmt *compoundStmt) {
-		mutateStatementList( compoundStmt->get_kids() );
-		return compoundStmt;
-	}
-
-	Statement* DeclMutator::mutate(IfStmt *ifStmt) {
-		ifStmt->set_condition( maybeMutate( ifStmt->get_condition(), *this ) );
-		ifStmt->set_thenPart( mutateStatement( ifStmt->get_thenPart() ) );
-		ifStmt->set_elsePart( mutateStatement( ifStmt->get_elsePart() ) );
-		return ifStmt;
-	}
-
-	Statement* DeclMutator::mutate(WhileStmt *whileStmt) {
-		whileStmt->set_condition( maybeMutate( whileStmt->get_condition(), *this ) );
-		whileStmt->set_body(  mutateStatement( whileStmt->get_body() ) );
-		return whileStmt;
-	}
-
-	Statement* DeclMutator::mutate(ForStmt *forStmt) {
-		mutateAll( forStmt->get_initialization(), *this );
-		forStmt->set_condition(  maybeMutate( forStmt->get_condition(), *this ) );
-		forStmt->set_increment(  maybeMutate( forStmt->get_increment(), *this ) );
-		forStmt->set_body(  mutateStatement( forStmt->get_body() ) );
-		return forStmt;
-	}
-
-	Statement* DeclMutator::mutate(SwitchStmt *switchStmt) {
-		switchStmt->set_condition( maybeMutate( switchStmt->get_condition(), *this ) );
-		mutateAll( switchStmt->get_statements(), *this );
-		return switchStmt;
-	}
-
-	Statement* DeclMutator::mutate(CaseStmt *caseStmt) {
-		caseStmt->set_condition( maybeMutate( caseStmt->get_condition(), *this ) );
-		mutateAll( caseStmt->get_statements(), *this );
-		return caseStmt;
-	}
-
-	Statement* DeclMutator::mutate(TryStmt *tryStmt) {
-		tryStmt->set_block( maybeMutate( tryStmt->get_block(), *this ) );
-		mutateAll( tryStmt->get_catchers(), *this );
-		tryStmt->set_finally( maybeMutate( tryStmt->get_finally(), *this ) );
-		return tryStmt;
-	}
-
-	Statement* DeclMutator::mutate(CatchStmt *catchStmt) {
-		catchStmt->set_decl( maybeMutate( catchStmt->get_decl(), *this ) );
-		catchStmt->set_cond( maybeMutate( catchStmt->get_cond(), *this ) );
-		catchStmt->set_body( mutateStatement( catchStmt->get_body() ) );
-		return catchStmt;
-	}
-}  // namespace GenPoly
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/GenPoly/DeclMutator.h
===================================================================
--- src/GenPoly/DeclMutator.h	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ 	(revision )
@@ -1,71 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// DeclMutator.h --
-//
-// Author           : Aaron B. Moss
-// Created On       : Fri Nov 27 14:44:00 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul 22 09:21:12 2017
-// Update Count     : 4
-//
-
-#pragma once
-
-#include <list>               // for list
-#include <vector>             // for vector
-
-#include "SynTree/Mutator.h"  // for Mutator
-#include "SynTree/SynTree.h"  // for Visitor Nodes
-
-namespace GenPoly {
-	/// Mutates a list of declarations, providing a means of adding new declarations into the list
-	class DeclMutator : public Mutator {
-	  public:
-		typedef Mutator Parent;
-
-		DeclMutator();
-		virtual ~DeclMutator();
-
-		using Parent::mutate;
-		virtual CompoundStmt* mutate(CompoundStmt *compoundStmt);
-		virtual Statement* mutate(IfStmt *ifStmt);
-		virtual Statement* mutate(WhileStmt *whileStmt);
-		virtual Statement* mutate(ForStmt *forStmt);
-		virtual Statement* mutate(SwitchStmt *switchStmt);
-		virtual Statement* mutate(CaseStmt *caseStmt);
-		virtual Statement* mutate(TryStmt *tryStmt);
-		virtual Statement* mutate(CatchStmt *catchStmt);
-
-		/// Mutates a list of declarations with this visitor
-		void mutateDeclarationList(std::list< Declaration* >& decls);
-
-		/// Called on entry to a new scope; overriders should call this as a super-class call
-		virtual void doBeginScope();
-		/// Called on exit from a scope; overriders should call this as a super-class call
-		virtual void doEndScope();
-	  protected:
-		/// Mutate a statement that forms its own scope
-		Statement* mutateStatement( Statement *stmt );
-		/// Mutate a list of statements that form a scope
-		void mutateStatementList( std::list< Statement* > &stmts );
-		/// Add a declaration to the list to be added before the current position
-		void addDeclaration( Declaration* decl );
-		/// Add a declaration to the list to be added after the current position
-		void addDeclarationAfter( Declaration* decl );
-	  private:
-		/// A stack of declarations to add before the current declaration or statement
-		std::vector< std::list< Declaration* > > declsToAdd;
-		/// A stack of declarations to add after the current declaration or statement
-		std::vector< std::list< Declaration* > > declsToAddAfter;
-	};
-} // namespace
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/GenPoly/PolyMutator.cc
===================================================================
--- src/GenPoly/PolyMutator.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ 	(revision )
@@ -1,187 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// PolyMutator.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Thu Jun 22 13:47:00 2017
-// Update Count     : 17
-//
-
-#include "PolyMutator.h"
-
-#include "Common/SemanticError.h"  // for SemanticError
-#include "Common/utility.h"        // for ValueGuard
-#include "SynTree/Declaration.h"   // for Declaration, TypeDecl, TypeDecl::Data
-#include "SynTree/Expression.h"    // for Expression, UntypedExpr, StmtExpr ...
-#include "SynTree/Initializer.h"   // for SingleInit, Initializer (ptr only)
-#include "SynTree/Label.h"         // for Label, noLabels
-#include "SynTree/Mutator.h"       // for maybeMutate, mutateAll
-#include "SynTree/Statement.h"     // for CatchStmt, CompoundStmt, ForStmt
-
-class TypeSubstitution;
-
-namespace GenPoly {
-	PolyMutator::PolyMutator() : scopeTyVars( TypeDecl::Data{} ), env( 0 ) {}
-
-	void PolyMutator::mutateStatementList( std::list< Statement* > &statements ) {
-		SemanticError errors;
-
-		for ( std::list< Statement* >::iterator i = statements.begin(); i != statements.end(); ++i ) {
-			if ( ! stmtsToAddAfter.empty() ) {
-				statements.splice( i, stmtsToAddAfter );
-			} // if
-			try {
-				*i = (*i)->acceptMutator( *this );
-			} catch ( SemanticError &e ) {
-				errors.append( e );
-			} // try
-			if ( ! stmtsToAdd.empty() ) {
-				statements.splice( i, stmtsToAdd );
-			} // if
-		} // for
-		if ( ! stmtsToAddAfter.empty() ) {
-			statements.splice( statements.end(), stmtsToAddAfter );
-		} // if
-		if ( ! errors.isEmpty() ) {
-			throw errors;
-		}
-	}
-
-	Statement * PolyMutator::mutateStatement( Statement *stmt ) {
-		// don't want statements from outer CompoundStmts to be added to this CompoundStmt
-		ValueGuard< std::list< Statement* > > oldStmtsToAdd( stmtsToAdd );
-		ValueGuard< std::list< Statement* > > oldStmtsToAddAfter( stmtsToAddAfter );
-		ValueGuard< TypeSubstitution * > oldEnv( env );
-		stmtsToAdd.clear();
-		stmtsToAddAfter.clear();
-
-		Statement *newStmt = maybeMutate( stmt, *this );
-		if ( ! stmtsToAdd.empty() || ! stmtsToAddAfter.empty() ) {
-			CompoundStmt *compound = new CompoundStmt( noLabels );
-			compound->get_kids().splice( compound->get_kids().end(), stmtsToAdd );
-			compound->get_kids().push_back( newStmt );
-			compound->get_kids().splice( compound->get_kids().end(), stmtsToAddAfter );
-			// doEndScope();
-			return compound;
-		} else {
-			return newStmt;
-		}
-	}
-
-	Expression * PolyMutator::mutateExpression( Expression *expr ) {
-		if ( expr ) {
-			if ( expr->get_env() ) {
-				env = expr->get_env();
-			}
-			// xxx - should env be cloned (or moved) onto the result of the mutate?
-			return expr->acceptMutator( *this );
-		} else {
-			return expr;
-		}
-	}
-
-	CompoundStmt * PolyMutator::mutate(CompoundStmt *compoundStmt) {
-		doBeginScope();
-		mutateStatementList( compoundStmt->get_kids() );
-		doEndScope();
-		return compoundStmt;
-	}
-
-	Statement * PolyMutator::mutate(IfStmt *ifStmt) {
-		ifStmt->set_condition(  mutateExpression( ifStmt->get_condition() ) );
-		ifStmt->set_thenPart(  mutateStatement( ifStmt->get_thenPart() ) );
-		ifStmt->set_elsePart(  mutateStatement( ifStmt->get_elsePart() ) );
-		return ifStmt;
-	}
-
-	Statement * PolyMutator::mutate(WhileStmt *whileStmt) {
-		whileStmt->set_condition(  mutateExpression( whileStmt->get_condition() ) );
-		whileStmt->set_body(  mutateStatement( whileStmt->get_body() ) );
-		return whileStmt;
-	}
-
-	Statement * PolyMutator::mutate(ForStmt *forStmt) {
-		mutateAll( forStmt->get_initialization(), *this );
-		forStmt->set_condition(  mutateExpression( forStmt->get_condition() ) );
-		forStmt->set_increment(  mutateExpression( forStmt->get_increment() ) );
-		forStmt->set_body(  mutateStatement( forStmt->get_body() ) );
-		return forStmt;
-	}
-
-	Statement * PolyMutator::mutate(SwitchStmt *switchStmt) {
-		switchStmt->set_condition( mutateExpression( switchStmt->get_condition() ) );
-		mutateStatementList( switchStmt->get_statements() );
-		return switchStmt;
-	}
-
-	Statement * PolyMutator::mutate(CaseStmt *caseStmt) {
-		caseStmt->set_condition(  mutateExpression( caseStmt->get_condition() ) );
-		mutateStatementList( caseStmt->get_statements() );
-		return caseStmt;
-	}
-
-	Statement * PolyMutator::mutate(TryStmt *tryStmt) {
-		tryStmt->set_block( maybeMutate( tryStmt->get_block(), *this ) );
-		mutateAll( tryStmt->get_catchers(), *this );
-		tryStmt->set_finally( maybeMutate( tryStmt->get_finally(), *this ) );
-		return tryStmt;
-	}
-
-	Statement * PolyMutator::mutate(CatchStmt *cathStmt) {
-		cathStmt->set_body( mutateStatement( cathStmt->get_body() ) );
-		cathStmt->set_cond( maybeMutate( cathStmt->get_cond(), *this ) );
-		cathStmt->set_decl( maybeMutate( cathStmt->get_decl(), *this ) );
-		return cathStmt;
-	}
-
-	Statement * PolyMutator::mutate(ReturnStmt *retStmt) {
-		retStmt->set_expr( mutateExpression( retStmt->get_expr() ) );
-		return retStmt;
-	}
-
-	Statement * PolyMutator::mutate(ExprStmt *exprStmt) {
-		exprStmt->set_expr( mutateExpression( exprStmt->get_expr() ) );
-		return exprStmt;
-	}
-
-
-	Expression * PolyMutator::mutate(UntypedExpr *untypedExpr) {
-		for ( std::list< Expression* >::iterator i = untypedExpr->get_args().begin(); i != untypedExpr->get_args().end(); ++i ) {
-			*i = mutateExpression( *i );
-		} // for
-		return untypedExpr;
-	}
-
-	Expression *PolyMutator::mutate( StmtExpr * stmtExpr ) {
-		// don't want statements from outer CompoundStmts to be added to this StmtExpr
-		ValueGuard< std::list< Statement* > > oldStmtsToAdd( stmtsToAdd );
-		ValueGuard< std::list< Statement* > > oldStmtsToAddAfter( stmtsToAddAfter );
-		ValueGuard< TypeSubstitution * > oldEnv( env );
-
-		// xxx - not sure if this is needed, along with appropriate reset, but I don't think so...
-		// ValueGuard< TyVarMap > oldScopeTyVars( scopeTyVars );
-
-		stmtsToAdd.clear();
-		stmtsToAddAfter.clear();
-		// scopeTyVars.clear();
-
-		return Parent::mutate( stmtExpr );
-	}
-
-	Initializer *PolyMutator::mutate( SingleInit *singleInit ) {
-		singleInit->set_value( mutateExpression( singleInit->get_value() ) );
-		return singleInit;
-	}
-} // namespace GenPoly
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/GenPoly/PolyMutator.h
===================================================================
--- src/GenPoly/PolyMutator.h	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ 	(revision )
@@ -1,67 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// PolyMutator.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul 22 09:20:31 2017
-// Update Count     : 7
-//
-
-#pragma once
-
-#include <list>               // for list
-
-#include "GenPoly.h"          // for TyVarMap
-#include "SynTree/Mutator.h"  // for Mutator
-#include "SynTree/SynTree.h"  // for Visitor Nodes
-
-namespace GenPoly {
-	class PolyMutator : public Mutator {
-	  public:
-		typedef Mutator Parent;
-		using Parent::mutate;
-
-		PolyMutator();
-
-		virtual CompoundStmt* mutate(CompoundStmt *compoundStmt);
-		virtual Statement* mutate(IfStmt *ifStmt);
-		virtual Statement* mutate(WhileStmt *whileStmt);
-		virtual Statement* mutate(ForStmt *forStmt);
-		virtual Statement* mutate(SwitchStmt *switchStmt);
-		virtual Statement* mutate(CaseStmt *caseStmt);
-		virtual Statement* mutate(TryStmt *returnStmt);
-		virtual Statement* mutate(CatchStmt *catchStmt);
-		virtual Statement* mutate(ExprStmt *catchStmt);
-		virtual Statement* mutate(ReturnStmt *catchStmt);
-
-		virtual Expression* mutate(UntypedExpr *untypedExpr);
-		virtual Expression* mutate( StmtExpr *stmtExpr );
-
-		virtual Initializer* mutate(SingleInit *SingleInit);
-
-		// template method
-		virtual void doBeginScope() {}
-		virtual void doEndScope() {}
-	  protected:
-		void mutateStatementList( std::list< Statement* > &statements );
-		Statement* mutateStatement( Statement *stmt );
-		Expression* mutateExpression( Expression *expr );
-
-		TyVarMap scopeTyVars;
-		TypeSubstitution *env;
-		std::list< Statement* > stmtsToAdd;
-		std::list< Statement* > stmtsToAddAfter;
-	};
-} // namespace
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/GenPoly/Specialize.cc
===================================================================
--- src/GenPoly/Specialize.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/GenPoly/Specialize.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -22,4 +22,5 @@
 #include <utility>                       // for pair
 
+#include "Common/PassVisitor.h"
 #include "Common/SemanticError.h"        // for SemanticError
 #include "Common/UniqueName.h"           // for UniqueName
@@ -28,5 +29,4 @@
 #include "InitTweak/InitTweak.h"         // for isIntrinsicCallExpr
 #include "Parser/LinkageSpec.h"          // for C
-#include "PolyMutator.h"                 // for PolyMutator
 #include "ResolvExpr/FindOpenVars.h"     // for findOpenVars
 #include "ResolvExpr/TypeEnvironment.h"  // for OpenVarSet, AssertionSet
@@ -43,13 +43,8 @@
 
 namespace GenPoly {
-	class Specialize final : public PolyMutator {
-	  public:
-		using PolyMutator::mutate;
-		virtual Expression * mutate( ApplicationExpr *applicationExpr ) override;
-		virtual Expression * mutate( AddressExpr *castExpr ) override;
-		virtual Expression * mutate( CastExpr *castExpr ) override;
-		// virtual Expression * mutate( LogicalExpr *logicalExpr );
-		// virtual Expression * mutate( ConditionalExpr *conditionalExpr );
-		// virtual Expression * mutate( CommaExpr *commaExpr );
+	struct Specialize final : public WithTypeSubstitution, public WithStmtsToAdd, public WithVisitorRef<Specialize> {
+		Expression * postmutate( ApplicationExpr *applicationExpr );
+		Expression * postmutate( AddressExpr *castExpr );
+		Expression * postmutate( CastExpr *castExpr );
 
 		void handleExplicitParams( ApplicationExpr *appExpr );
@@ -204,11 +199,11 @@
 	}
 
-	struct EnvTrimmer : public Visitor {
+	struct EnvTrimmer {
 		TypeSubstitution * env, * newEnv;
 		EnvTrimmer( TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
-		virtual void visit( TypeDecl * tyDecl ) {
+		void previsit( TypeDecl * tyDecl ) {
 			// transfer known bindings for seen type variables
-			if ( Type * t = env->lookup( tyDecl->get_name() ) ) {
-				newEnv->add( tyDecl->get_name(), t );
+			if ( Type * t = env->lookup( tyDecl->name ) ) {
+				newEnv->add( tyDecl->name, t );
 			}
 		}
@@ -219,5 +214,5 @@
 		if ( env ) {
 			TypeSubstitution * newEnv = new TypeSubstitution();
-			EnvTrimmer trimmer( env, newEnv );
+			PassVisitor<EnvTrimmer> trimmer( env, newEnv );
 			expr->accept( trimmer );
 			return newEnv;
@@ -277,25 +272,25 @@
 		std::string oldParamPrefix = paramPrefix;
 		paramPrefix += "p";
-		// save stmtsToAdd in oldStmts
+		// save stmtsToAddBefore in oldStmts
 		std::list< Statement* > oldStmts;
-		oldStmts.splice( oldStmts.end(), stmtsToAdd );
-		mutate( appExpr );
+		oldStmts.splice( oldStmts.end(), stmtsToAddBefore );
+		appExpr->acceptMutator( *visitor );
 		paramPrefix = oldParamPrefix;
 		// write any statements added for recursive specializations into the thunk body
-		thunkFunc->get_statements()->get_kids().splice( thunkFunc->get_statements()->get_kids().end(), stmtsToAdd );
-		// restore oldStmts into stmtsToAdd
-		stmtsToAdd.splice( stmtsToAdd.end(), oldStmts );
+		thunkFunc->statements->kids.splice( thunkFunc->statements->kids.end(), stmtsToAddBefore );
+		// restore oldStmts into stmtsToAddBefore
+		stmtsToAddBefore.splice( stmtsToAddBefore.end(), oldStmts );
 
 		// add return (or valueless expression) to the thunk
 		Statement *appStmt;
-		if ( funType->get_returnVals().empty() ) {
+		if ( funType->returnVals.empty() ) {
 			appStmt = new ExprStmt( noLabels, appExpr );
 		} else {
 			appStmt = new ReturnStmt( noLabels, appExpr );
 		} // if
-		thunkFunc->get_statements()->get_kids().push_back( appStmt );
+		thunkFunc->statements->kids.push_back( appStmt );
 
 		// add thunk definition to queue of statements to add
-		stmtsToAdd.push_back( new DeclStmt( noLabels, thunkFunc ) );
+		stmtsToAddBefore.push_back( new DeclStmt( noLabels, thunkFunc ) );
 		// return address of thunk function as replacement expression
 		return new AddressExpr( new VariableExpr( thunkFunc ) );
@@ -304,18 +299,15 @@
 	void Specialize::handleExplicitParams( ApplicationExpr *appExpr ) {
 		// create thunks for the explicit parameters
-		assert( appExpr->get_function()->has_result() );
-		FunctionType *function = getFunctionType( appExpr->get_function()->get_result() );
+		assert( appExpr->function->result );
+		FunctionType *function = getFunctionType( appExpr->function->result );
 		assert( function );
 		std::list< DeclarationWithType* >::iterator formal;
 		std::list< Expression* >::iterator actual;
 		for ( formal = function->get_parameters().begin(), actual = appExpr->get_args().begin(); formal != function->get_parameters().end() && actual != appExpr->get_args().end(); ++formal, ++actual ) {
-			*actual = doSpecialization( (*formal )->get_type(), *actual, &appExpr->get_inferParams() );
-		}
-	}
-
-	Expression * Specialize::mutate( ApplicationExpr *appExpr ) {
-		appExpr->get_function()->acceptMutator( *this );
-		mutateAll( appExpr->get_args(), *this );
-
+			*actual = doSpecialization( (*formal)->get_type(), *actual, &appExpr->get_inferParams() );
+		}
+	}
+
+	Expression * Specialize::postmutate( ApplicationExpr *appExpr ) {
 		if ( ! InitTweak::isIntrinsicCallExpr( appExpr ) ) {
 			// create thunks for the inferred parameters
@@ -331,19 +323,17 @@
 	}
 
-	Expression * Specialize::mutate( AddressExpr *addrExpr ) {
-		addrExpr->get_arg()->acceptMutator( *this );
-		assert( addrExpr->has_result() );
-		addrExpr->set_arg( doSpecialization( addrExpr->get_result(), addrExpr->get_arg() ) );
+	Expression * Specialize::postmutate( AddressExpr *addrExpr ) {
+		assert( addrExpr->result );
+		addrExpr->set_arg( doSpecialization( addrExpr->result, addrExpr->arg ) );
 		return addrExpr;
 	}
 
-	Expression * Specialize::mutate( CastExpr *castExpr ) {
-		castExpr->get_arg()->acceptMutator( *this );
-		if ( castExpr->get_result()->isVoid() ) {
+	Expression * Specialize::postmutate( CastExpr *castExpr ) {
+		if ( castExpr->result->isVoid() ) {
 			// can't specialize if we don't have a return value
 			return castExpr;
 		}
-		Expression *specialized = doSpecialization( castExpr->get_result(), castExpr->get_arg() );
-		if ( specialized != castExpr->get_arg() ) {
+		Expression *specialized = doSpecialization( castExpr->result, castExpr->arg );
+		if ( specialized != castExpr->arg ) {
 			// assume here that the specialization incorporates the cast
 			return specialized;
@@ -353,22 +343,6 @@
 	}
 
-	// Removing these for now. Richard put these in for some reason, but it's not clear why.
-	// In particular, copy constructors produce a comma expression, and with this code the parts
-	// of that comma expression are not specialized, which causes problems.
-
-	// Expression * Specialize::mutate( LogicalExpr *logicalExpr ) {
-	// 	return logicalExpr;
-	// }
-
-	// Expression * Specialize::mutate( ConditionalExpr *condExpr ) {
-	// 	return condExpr;
-	// }
-
-	// Expression * Specialize::mutate( CommaExpr *commaExpr ) {
-	// 	return commaExpr;
-	// }
-
 	void convertSpecializations( std::list< Declaration* >& translationUnit ) {
-		Specialize spec;
+		PassVisitor<Specialize> spec;
 		mutateAll( translationUnit, spec );
 	}
Index: src/GenPoly/module.mk
===================================================================
--- src/GenPoly/module.mk	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/GenPoly/module.mk	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -6,5 +6,5 @@
 ## file "LICENCE" distributed with Cforall.
 ##
-## module.mk -- 
+## module.mk --
 ##
 ## Author           : Richard C. Bilson
@@ -17,5 +17,4 @@
 SRC += GenPoly/Box.cc \
        GenPoly/GenPoly.cc \
-       GenPoly/PolyMutator.cc \
        GenPoly/ScrubTyVars.cc \
        GenPoly/Lvalue.cc \
@@ -23,4 +22,3 @@
        GenPoly/CopyParams.cc \
        GenPoly/FindFunction.cc \
-       GenPoly/DeclMutator.cc \
        GenPoly/InstantiateGeneric.cc
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/InitTweak/FixInit.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -36,7 +36,5 @@
 #include "FixGlobalInit.h"             // for fixGlobalInit
 #include "GenInit.h"                   // for genCtorDtor
-#include "GenPoly/DeclMutator.h"       // for DeclMutator
 #include "GenPoly/GenPoly.h"           // for getFunctionType
-#include "GenPoly/PolyMutator.h"       // for PolyMutator
 #include "InitTweak.h"                 // for getFunctionName, getCallArg
 #include "Parser/LinkageSpec.h"        // for C, Spec, Cforall, isBuiltin
@@ -46,5 +44,4 @@
 #include "SymTab/Indexer.h"            // for Indexer
 #include "SymTab/Mangler.h"            // for Mangler
-#include "SynTree/AddStmtVisitor.h"    // for AddStmtVisitor
 #include "SynTree/Attribute.h"         // for Attribute
 #include "SynTree/Constant.h"          // for Constant
@@ -58,5 +55,4 @@
 #include "SynTree/TypeSubstitution.h"  // for TypeSubstitution, operator<<
 #include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
-#include "Tuples/Tuples.h"             // for isTtype
 
 bool ctordtorp = false; // print all debug
@@ -187,5 +183,5 @@
 		};
 
-		class FixCopyCtors final : public GenPoly::PolyMutator {
+		class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> {
 		  public:
 			FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){}
@@ -194,9 +190,7 @@
 			static void fixCopyCtors( std::list< Declaration * > &translationUnit, UnqCount & unqCount );
 
-			typedef GenPoly::PolyMutator Parent;
-			using Parent::mutate;
-			virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
-			virtual Expression * mutate( UniqueExpr * unqExpr ) override;
-			virtual Expression * mutate( StmtExpr * stmtExpr ) override;
+			Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr );
+			void premutate( StmtExpr * stmtExpr );
+			void premutate( UniqueExpr * unqExpr );
 
 			UnqCount & unqCount;
@@ -243,11 +237,9 @@
 		};
 
-		class FixCtorExprs final : public GenPoly::DeclMutator {
-		  public:
+		struct FixCtorExprs final : public WithDeclsToAdd, public WithIndexer {
 			/// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument
 			static void fix( std::list< Declaration * > & translationUnit );
 
-			using GenPoly::DeclMutator::mutate;
-			virtual Expression * mutate( ConstructorExpr * ctorExpr ) override;
+			Expression * postmutate( ConstructorExpr * ctorExpr );
 		};
 	} // namespace
@@ -316,5 +308,5 @@
 
 		void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
-			FixCopyCtors fixer( unqCount );
+			PassVisitor<FixCopyCtors> fixer( unqCount );
 			mutateAll( translationUnit, fixer );
 		}
@@ -326,6 +318,6 @@
 
 		void FixCtorExprs::fix( std::list< Declaration * > & translationUnit ) {
-			FixCtorExprs fixer;
-			fixer.mutateDeclarationList( translationUnit );
+			PassVisitor<FixCtorExprs> fixer;
+			mutateAll( translationUnit, fixer );
 		}
 
@@ -339,5 +331,5 @@
 				} else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) {
 					FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
-					assert( ftype );
+					assertf( ftype, "Function call without function type: %s", toString( funcDecl ).c_str() );
 					if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
 						Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
@@ -368,7 +360,5 @@
 		}
 
-		bool ResolveCopyCtors::skipCopyConstruct( Type * type ) {
-			return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
-		}
+		bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { return ! isConstructable( type ); }
 
 		Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
@@ -407,5 +397,5 @@
 			result = result->clone();
 			env->apply( result );
-			ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
+			ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr );
 			tmp->get_type()->set_const( false );
 
@@ -421,4 +411,7 @@
 				if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return;
 			}
+
+			// set a unique name for the temporary once it's certain the call is necessary
+			tmp->name = tempNamer.newName();
 
 			// replace argument to function call with temporary
@@ -450,10 +443,10 @@
 				result = result->clone();
 				env->apply( result );
-				ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
+				ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
 				ret->get_type()->set_const( false );
 				impCpCtorExpr->get_returnDecls().push_back( ret );
 				CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
 				if ( ! dynamic_cast< ReferenceType * >( result ) ) {
-					// destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
+					// destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
 					destructRet( ret, impCpCtorExpr );
 				}
@@ -472,5 +465,5 @@
 				result = result->clone();
 				env->apply( result );
-				ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 );
+				ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr );
 				ret->get_type()->set_const( false );
 				stmtExpr->get_returnDecls().push_front( ret );
@@ -509,5 +502,5 @@
 			} else {
 				// expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
-				unqExpr->set_object( new ObjectDecl( toString("_unq", unqExpr->get_id()), Type::StorageClasses(), LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) );
+				unqExpr->set_object( ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->get_result()->clone(), nullptr ) );
 				unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) );
 			}
@@ -515,8 +508,7 @@
 		}
 
-		Expression * FixCopyCtors::mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
+		Expression * FixCopyCtors::postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
 			CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; )
 
-			impCpCtorExpr = strict_dynamic_cast< ImplicitCopyCtorExpr * >( Parent::mutate( impCpCtorExpr ) );
 			std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls();
 			std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls();
@@ -525,8 +517,8 @@
 			// add all temporary declarations and their constructors
 			for ( ObjectDecl * obj : tempDecls ) {
-				stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
+				stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
 			} // for
 			for ( ObjectDecl * obj : returnDecls ) {
-				stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
+				stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
 			} // for
 
@@ -536,5 +528,4 @@
 			} // for
 
-			// xxx - update to work with multiple return values
 			ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front();
 			Expression * callExpr = impCpCtorExpr->get_callExpr();
@@ -569,21 +560,23 @@
 		}
 
-		Expression * FixCopyCtors::mutate( StmtExpr * stmtExpr ) {
+		void FixCopyCtors::premutate( StmtExpr * stmtExpr ) {
 			// function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression,
 			// since temporaries can be shared across sub-expressions, e.g.
 			//   [A, A] f();
 			//   g([A] x, [A] y);
-			//   f(g());
+			//   g(f());
 			// f is executed once, so the return temporary is shared across the tuple constructors for x and y.
+			// Explicitly mutating children instead of mutating the inner compound statment forces the temporaries to be added
+			// to the outer context, rather than inside of the statement expression.
+			visit_children = false;
 			std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
 			for ( Statement *& stmt : stmts ) {
-				stmt = stmt->acceptMutator( *this );
+				stmt = stmt->acceptMutator( *visitor );
 			} // for
-			// stmtExpr = strict_dynamic_cast< StmtExpr * >( Parent::mutate( stmtExpr ) );
 			assert( stmtExpr->get_result() );
 			Type * result = stmtExpr->get_result();
 			if ( ! result->isVoid() ) {
 				for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) {
-					stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) );
+					stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
 				} // for
 				// add destructors after current statement
@@ -592,8 +585,7 @@
 				} // for
 				// must have a non-empty body, otherwise it wouldn't have a result
-				CompoundStmt * body = stmtExpr->get_statements();
-				assert( ! body->get_kids().empty() );
+				assert( ! stmts.empty() );
 				assert( ! stmtExpr->get_returnDecls().empty() );
-				body->get_kids().push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
+				stmts.push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
 				stmtExpr->get_returnDecls().clear();
 				stmtExpr->get_dtors().clear();
@@ -601,12 +593,11 @@
 			assert( stmtExpr->get_returnDecls().empty() );
 			assert( stmtExpr->get_dtors().empty() );
-			return stmtExpr;
-		}
-
-		Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {
+		}
+
+		void FixCopyCtors::premutate( UniqueExpr * unqExpr ) {
+			visit_children = false;
 			unqCount[ unqExpr->get_id() ]--;
 			static std::unordered_map< int, std::list< Statement * > > dtors;
 			static std::unordered_map< int, UniqueExpr * > unqMap;
-			static std::unordered_set< int > addDeref;
 			// has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes
 			if ( unqMap.count( unqExpr->get_id() ) ) {
@@ -619,30 +610,16 @@
 					stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
 				}
-				if ( addDeref.count( unqExpr->get_id() ) ) {
-					// other UniqueExpr was dereferenced because it was an lvalue return, so this one should be too
-					return UntypedExpr::createDeref( unqExpr );
-				}
-				return unqExpr;
-			}
-			FixCopyCtors fixer( unqCount );
+				return;
+			}
+			PassVisitor<FixCopyCtors> fixer( unqCount );
 			unqExpr->set_expr( unqExpr->get_expr()->acceptMutator( fixer ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup
-			stmtsToAdd.splice( stmtsToAdd.end(), fixer.stmtsToAdd );
+			stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore );
 			unqMap[unqExpr->get_id()] = unqExpr;
 			if ( unqCount[ unqExpr->get_id() ] == 0 ) {  // insert destructor after the last use of the unique expression
 				stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
 			} else { // remember dtors for last instance of unique expr
-				dtors[ unqExpr->get_id() ] = fixer.stmtsToAddAfter;
-			}
-			if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) {
-				// unique expression is now a dereference, because the inner expression is an lvalue returning function call.
-				// Normalize the expression by dereferencing the unique expression, rather than the inner expression
-				// (i.e. move the dereference out a level)
-				assert( getFunctionName( deref ) == "*?" );
-				unqExpr->set_expr( getCallArg( deref, 0 ) );
-				getCallArg( deref, 0 ) = unqExpr;
-				addDeref.insert( unqExpr->get_id() );
-				return deref;
-			}
-			return unqExpr;
+				dtors[ unqExpr->get_id() ] = fixer.pass.stmtsToAddAfter;
+			}
+			return;
 		}
 
@@ -819,7 +796,9 @@
 					assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() );
 					Statement * dtor = ctorInit->get_dtor();
+					// don't need to call intrinsic dtor, because it does nothing, but
+					// non-intrinsic dtors must be called
 					if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
-						// don't need to call intrinsic dtor, because it does nothing, but
-						// non-intrinsic dtors must be called
+						// set dtor location to the object's location for error messages
+						ctorInit->dtor->location = objDecl->location;
 						reverseDeclOrder.front().push_front( objDecl );
 					} // if
@@ -1012,4 +991,6 @@
 					// skip non-DWT members
 					if ( ! field ) continue;
+					// skip non-constructable members
+					if ( ! tryConstruct( field ) ) continue;
 					// skip handled members
 					if ( ! unhandled.count( field ) ) continue;
@@ -1142,5 +1123,5 @@
 		}
 
-		Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) {
+		Expression * FixCtorExprs::postmutate( ConstructorExpr * ctorExpr ) {
 			static UniqueName tempNamer( "_tmp_ctor_expr" );
 			// xxx - is the size check necessary?
@@ -1148,6 +1129,6 @@
 
 			// xxx - ideally we would reuse the temporary generated from the copy constructor passes from within firstArg if it exists and not generate a temporary if it's unnecessary.
-			ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, nullptr, ctorExpr->get_result()->clone(), nullptr );
-			addDeclaration( tmp );
+			ObjectDecl * tmp = ObjectDecl::newObject( tempNamer.newName(), ctorExpr->get_result()->clone(), nullptr );
+			declsToAddBefore.push_back( tmp );
 
 			// xxx - this can be TupleAssignExpr now. Need to properly handle this case.
@@ -1158,26 +1139,14 @@
 			delete ctorExpr;
 
+			// build assignment and replace constructor's first argument with new temporary
 			Expression *& firstArg = callExpr->get_args().front();
-
-			// xxx - hack in 'fake' assignment operator until resolver can easily be called in this pass. Once the resolver can be used in PassVisitor, this hack goes away.
-
-			// generate the type of assignment operator using the type of tmp minus any reference types
-			Type * type = tmp->get_type()->stripReferences();
-			FunctionType * ftype = SymTab::genAssignType( type );
-
-			// generate fake assignment decl and call it using &tmp and &firstArg
-			// since tmp is guaranteed to be a reference and we want to assign pointers
-			FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr );
-			ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) );
-			assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) );
-			Expression * addrArg = new AddressExpr( firstArg );
-			// if firstArg has type T&&, then &firstArg has type T*&.
-			// Cast away the reference to a value type so that the argument
-			// matches the assignment's parameter types
-			if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) {
-				addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() );
-			}
-			assign->get_args().push_back( addrArg );
+			Expression * assign = new UntypedExpr( new NameExpr( "?=?" ), { new AddressExpr( new VariableExpr( tmp ) ), new AddressExpr( firstArg ) } );
 			firstArg = new VariableExpr( tmp );
+
+			// resolve assignment and dispose of new env
+			Expression * resolvedAssign = ResolvExpr::findVoidExpression( assign, indexer );
+			delete resolvedAssign->env;
+			resolvedAssign->env = nullptr;
+			delete assign;
 
 			// for constructor expr:
@@ -1188,5 +1157,5 @@
 			//   T & tmp;
 			//   &tmp = &x, ?{}(tmp), tmp
-			CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
+			CommaExpr * commaExpr = new CommaExpr( resolvedAssign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
 			commaExpr->set_env( env );
 			return commaExpr;
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/InitTweak/GenInit.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -26,5 +26,4 @@
 #include "Common/UniqueName.h"     // for UniqueName
 #include "Common/utility.h"        // for ValueGuard, maybeClone
-#include "GenPoly/DeclMutator.h"   // for DeclMutator
 #include "GenPoly/GenPoly.h"       // for getFunctionType, isPolyType
 #include "GenPoly/ScopedSet.h"     // for ScopedSet, ScopedSet<>::const_iter...
@@ -62,5 +61,5 @@
 	};
 
-	struct CtorDtor : public WithGuards, public WithShortCircuiting  {
+	struct CtorDtor : public WithGuards, public WithShortCircuiting, public WithVisitorRef<CtorDtor>  {
 		/// create constructor and destructor statements for object declarations.
 		/// the actual call statements will be added in after the resolver has run
@@ -75,10 +74,7 @@
 		// that need to be constructed or destructed
 		void previsit( StructDecl *aggregateDecl );
-		void previsit( __attribute__((unused)) UnionDecl    * aggregateDecl ) { visit_children = false; }
-		void previsit( __attribute__((unused)) EnumDecl     * aggregateDecl ) { visit_children = false; }
-		void previsit( __attribute__((unused)) TraitDecl    * aggregateDecl ) { visit_children = false; }
-		void previsit( __attribute__((unused)) TypeDecl     * typeDecl )      { visit_children = false; }
-		void previsit( __attribute__((unused)) TypedefDecl  * typeDecl )      { visit_children = false; }
-		void previsit( __attribute__((unused)) FunctionType * funcType )      { visit_children = false; }
+		void previsit( AggregateDecl * ) { visit_children = false; }
+		void previsit( NamedTypeDecl * ) { visit_children = false; }
+		void previsit( FunctionType * ) { visit_children = false; }
 
 		void previsit( CompoundStmt * compoundStmt );
@@ -96,8 +92,5 @@
 	};
 
-	class HoistArrayDimension final : public GenPoly::DeclMutator {
-	  public:
-		typedef GenPoly::DeclMutator Parent;
-
+	struct HoistArrayDimension final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards {
 		/// hoist dimension from array types in object declaration so that it uses a single
 		/// const variable of type size_t, so that side effecting array dimensions are only
@@ -105,19 +98,12 @@
 		static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
 
-	  private:
-		using Parent::mutate;
-
-		virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override;
-		virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ) override;
+		void premutate( ObjectDecl * objectDecl );
+		DeclarationWithType * postmutate( ObjectDecl * objectDecl );
+		void premutate( 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 { return aggregateDecl; }
-		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; }
+		void premutate( AggregateDecl * ) { visit_children = false; }
+		void premutate( NamedTypeDecl * ) { visit_children = false; }
+		void premutate( FunctionType * ) { visit_children = false; }
 
 		void hoist( Type * type );
@@ -128,10 +114,10 @@
 
 	void genInit( std::list< Declaration * > & translationUnit ) {
-		ReturnFixer::makeReturnTemp( translationUnit );
+		fixReturnStatements( translationUnit );
 		HoistArrayDimension::hoistArrayDimension( translationUnit );
 		CtorDtor::generateCtorDtor( translationUnit );
 	}
 
-	void ReturnFixer::makeReturnTemp( std::list< Declaration * > & translationUnit ) {
+	void fixReturnStatements( std::list< Declaration * > & translationUnit ) {
 		PassVisitor<ReturnFixer> fixer;
 		mutateAll( translationUnit, fixer );
@@ -143,5 +129,5 @@
 		// hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address
 		// is being returned
-		if ( returnStmt->get_expr() && returnVals.size() == 1 && ! dynamic_cast< ReferenceType * >( returnVals.front()->get_type() ) ) {
+		if ( returnStmt->get_expr() && returnVals.size() == 1 && isConstructable( returnVals.front()->get_type() ) ) {
 			// explicitly construct the return value using the return expression and the retVal object
 			assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() );
@@ -158,6 +144,6 @@
 		GuardValue( funcName );
 
-		ftype = functionDecl->get_functionType();
-		funcName = functionDecl->get_name();
+		ftype = functionDecl->type;
+		funcName = functionDecl->name;
 	}
 
@@ -165,13 +151,16 @@
 	// which would be incorrect if it is a side-effecting computation.
 	void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
-		HoistArrayDimension hoister;
-		hoister.mutateDeclarationList( translationUnit );
-	}
-
-	DeclarationWithType * HoistArrayDimension::mutate( ObjectDecl * objectDecl ) {
+		PassVisitor<HoistArrayDimension> hoister;
+		mutateAll( translationUnit, hoister );
+	}
+
+	void HoistArrayDimension::premutate( ObjectDecl * objectDecl ) {
+		GuardValue( storageClasses );
 		storageClasses = objectDecl->get_storageClasses();
-		DeclarationWithType * temp = Parent::mutate( objectDecl );
+	}
+
+	DeclarationWithType * HoistArrayDimension::postmutate( ObjectDecl * objectDecl ) {
 		hoist( objectDecl->get_type() );
-		return temp;
+		return objectDecl;
 	}
 
@@ -194,5 +183,5 @@
 
 			arrayType->set_dimension( new VariableExpr( arrayDimension ) );
-			addDeclaration( arrayDimension );
+			declsToAddBefore.push_back( arrayDimension );
 
 			hoist( arrayType->get_base() );
@@ -201,9 +190,6 @@
 	}
 
-	DeclarationWithType * HoistArrayDimension::mutate( FunctionDecl *functionDecl ) {
-		ValueGuard< bool > oldInFunc( inFunction );
-		inFunction = true;
-		DeclarationWithType * decl = Parent::mutate( functionDecl );
-		return decl;
+	void HoistArrayDimension::premutate( FunctionDecl * ) {
+		GuardValue( inFunction );
 	}
 
@@ -214,5 +200,5 @@
 
 	bool CtorDtor::isManaged( Type * type ) const {
-		// at least for now, references are never constructed
+		// references are never constructed
 		if ( dynamic_cast< ReferenceType * >( type ) ) return false;
 		// need to clear and reset qualifiers when determining if a type is managed
@@ -221,5 +207,5 @@
 		if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
 			// tuple is also managed if any of its components are managed
-			if ( std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) {
+			if ( std::any_of( tupleType->types.begin(), tupleType->types.end(), [&](Type * type) { return isManaged( type ); }) ) {
 				return true;
 			}
@@ -305,4 +291,5 @@
 
 	void CtorDtor::previsit( FunctionDecl *functionDecl ) {
+		visit_children = false;  // do not try and construct parameters or forall parameters
 		GuardValue( inFunction );
 		inFunction = true;
@@ -318,8 +305,5 @@
 		}
 
-		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
+		maybeAccept( functionDecl->get_statements(), *visitor );
 	}
 
@@ -340,5 +324,5 @@
 	}
 
-	void CtorDtor::previsit( __attribute__((unused)) CompoundStmt * compoundStmt ) {
+	void CtorDtor::previsit( CompoundStmt * ) {
 		GuardScope( managedTypes );
 	}
Index: src/InitTweak/GenInit.h
===================================================================
--- src/InitTweak/GenInit.h	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/InitTweak/GenInit.h	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -25,6 +25,9 @@
 	void genInit( std::list< Declaration * > & translationUnit );
 
-  /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument
-  ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr );
+	/// Converts return statements into copy constructor calls on the hidden return variable
+	void fixReturnStatements( std::list< Declaration * > & translationUnit );
+
+	/// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument
+	ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr );
 
 	/// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/InitTweak/InitTweak.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -1,3 +1,2 @@
-#include <stddef.h>                // for NULL
 #include <algorithm>               // for find, all_of
 #include <cassert>                 // for assertf, assert, strict_dynamic_cast
@@ -23,4 +22,5 @@
 #include "SynTree/Type.h"          // for FunctionType, ArrayType, PointerType
 #include "SynTree/Visitor.h"       // for Visitor, maybeAccept
+#include "Tuples/Tuples.h"         // for Tuples::isTtype
 
 class UntypedValofExpr;
@@ -184,5 +184,5 @@
 			callExpr->get_args().splice( callExpr->get_args().end(), args );
 
-			*out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), NULL );
+			*out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), nullptr );
 
 			UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
@@ -250,18 +250,18 @@
 	// To accomplish this, generate switch statement, consuming all of expander's elements
 	Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
-		if ( ! init ) return NULL;
+		if ( ! init ) return nullptr;
 		CompoundStmt * block = new CompoundStmt( noLabels );
 		build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );
 		if ( block->get_kids().empty() ) {
 			delete block;
-			return NULL;
+			return nullptr;
 		} else {
-			init = NULL; // init was consumed in creating the list init
+			init = nullptr; // init was consumed in creating the list init
 			return block;
 		}
 	}
 
-	Statement * ExprImpl::buildListInit( __attribute((unused)) UntypedExpr * dst, __attribute((unused)) std::list< Expression * > & indices ) {
-		return NULL;
+	Statement * ExprImpl::buildListInit( UntypedExpr *, std::list< Expression * > & ) {
+		return nullptr;
 	}
 
@@ -270,9 +270,16 @@
 	}
 
-	bool tryConstruct( ObjectDecl * objDecl ) {
+	bool tryConstruct( DeclarationWithType * dwt ) {
+		ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt );
+		if ( ! objDecl ) return false;
 		return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) &&
-			(objDecl->get_init() == NULL ||
-				( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() ))
-			&& ! objDecl->get_storageClasses().is_extern;
+			(objDecl->get_init() == nullptr ||
+				( objDecl->get_init() != nullptr && objDecl->get_init()->get_maybeConstructed() ))
+			&& ! objDecl->get_storageClasses().is_extern
+			&& isConstructable( objDecl->type );
+	}
+
+	bool isConstructable( Type * type ) {
+		return ! dynamic_cast< VarArgsType * >( type ) && ! dynamic_cast< ReferenceType * >( type ) && ! dynamic_cast< FunctionType * >( type ) && ! Tuples::isTtype( type );
 	}
 
@@ -314,5 +321,5 @@
 		collectCtorDtorCalls( stmt, matches );
 		assert( matches.size() <= 1 );
-		return matches.size() == 1 ? matches.front() : NULL;
+		return matches.size() == 1 ? matches.front() : nullptr;
 	}
 
@@ -359,10 +366,10 @@
 	ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) {
 		ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr );
-		if ( ! appExpr ) return NULL;
+		if ( ! appExpr ) return nullptr;
 		DeclarationWithType * function = getCalledFunction( appExpr->get_function() );
 		assertf( function, "getCalledFunction returned nullptr: %s", toString( appExpr->get_function() ).c_str() );
 		// check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
 		// will call all member dtors, and some members may have a user defined dtor.
-		return function->get_linkage() == LinkageSpec::Intrinsic ? appExpr : NULL;
+		return function->get_linkage() == LinkageSpec::Intrinsic ? appExpr : nullptr;
 	}
 
@@ -482,5 +489,5 @@
 			return refType->get_base();
 		} else {
-			return NULL;
+			return nullptr;
 		}
 	}
@@ -488,5 +495,5 @@
 	Type * isPointerType( Type * type ) {
 		if ( getPointerBase( type ) ) return type;
-		else return NULL;
+		else return nullptr;
 	}
 
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/InitTweak/InitTweak.h	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -33,6 +33,9 @@
 	std::list< Expression * > makeInitList( Initializer * init );
 
-	/// True if the resolver should try to construct objDecl
-	bool tryConstruct( ObjectDecl * objDecl );
+	/// True if the resolver should try to construct dwt
+	bool tryConstruct( DeclarationWithType * dwt );
+
+	/// True if the type can have a user-defined constructor
+	bool isConstructable( Type * t );
 
 	/// True if the Initializer contains designations
Index: src/Makefile.in
===================================================================
--- src/Makefile.in	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/Makefile.in	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -172,5 +172,4 @@
 	GenPoly/driver_cfa_cpp-Box.$(OBJEXT) \
 	GenPoly/driver_cfa_cpp-GenPoly.$(OBJEXT) \
-	GenPoly/driver_cfa_cpp-PolyMutator.$(OBJEXT) \
 	GenPoly/driver_cfa_cpp-ScrubTyVars.$(OBJEXT) \
 	GenPoly/driver_cfa_cpp-Lvalue.$(OBJEXT) \
@@ -178,5 +177,4 @@
 	GenPoly/driver_cfa_cpp-CopyParams.$(OBJEXT) \
 	GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT) \
-	GenPoly/driver_cfa_cpp-DeclMutator.$(OBJEXT) \
 	GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT) \
 	InitTweak/driver_cfa_cpp-GenInit.$(OBJEXT) \
@@ -253,5 +251,4 @@
 	SynTree/driver_cfa_cpp-Visitor.$(OBJEXT) \
 	SynTree/driver_cfa_cpp-Mutator.$(OBJEXT) \
-	SynTree/driver_cfa_cpp-AddStmtVisitor.$(OBJEXT) \
 	SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT) \
 	SynTree/driver_cfa_cpp-Attribute.$(OBJEXT) \
@@ -497,8 +494,7 @@
 	ControlStruct/ForExprMutator.cc \
 	ControlStruct/ExceptTranslate.cc GenPoly/Box.cc \
-	GenPoly/GenPoly.cc GenPoly/PolyMutator.cc \
-	GenPoly/ScrubTyVars.cc GenPoly/Lvalue.cc GenPoly/Specialize.cc \
-	GenPoly/CopyParams.cc GenPoly/FindFunction.cc \
-	GenPoly/DeclMutator.cc GenPoly/InstantiateGeneric.cc \
+	GenPoly/GenPoly.cc GenPoly/ScrubTyVars.cc GenPoly/Lvalue.cc \
+	GenPoly/Specialize.cc GenPoly/CopyParams.cc \
+	GenPoly/FindFunction.cc GenPoly/InstantiateGeneric.cc \
 	InitTweak/GenInit.cc InitTweak/FixInit.cc \
 	InitTweak/FixGlobalInit.cc InitTweak/InitTweak.cc \
@@ -535,8 +531,8 @@
 	SynTree/NamedTypeDecl.cc SynTree/TypeDecl.cc \
 	SynTree/Initializer.cc SynTree/Visitor.cc SynTree/Mutator.cc \
-	SynTree/AddStmtVisitor.cc SynTree/TypeSubstitution.cc \
-	SynTree/Attribute.cc SynTree/VarExprReplacer.cc \
-	Tuples/TupleAssignment.cc Tuples/TupleExpansion.cc \
-	Tuples/Explode.cc Virtual/ExpandCasts.cc
+	SynTree/TypeSubstitution.cc SynTree/Attribute.cc \
+	SynTree/VarExprReplacer.cc Tuples/TupleAssignment.cc \
+	Tuples/TupleExpansion.cc Tuples/Explode.cc \
+	Virtual/ExpandCasts.cc
 MAINTAINERCLEANFILES = Parser/parser.output ${libdir}/${notdir \
 	${cfa_cpplib_PROGRAMS}}
@@ -717,6 +713,4 @@
 GenPoly/driver_cfa_cpp-GenPoly.$(OBJEXT): GenPoly/$(am__dirstamp) \
 	GenPoly/$(DEPDIR)/$(am__dirstamp)
-GenPoly/driver_cfa_cpp-PolyMutator.$(OBJEXT): GenPoly/$(am__dirstamp) \
-	GenPoly/$(DEPDIR)/$(am__dirstamp)
 GenPoly/driver_cfa_cpp-ScrubTyVars.$(OBJEXT): GenPoly/$(am__dirstamp) \
 	GenPoly/$(DEPDIR)/$(am__dirstamp)
@@ -729,6 +723,4 @@
 GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT):  \
 	GenPoly/$(am__dirstamp) GenPoly/$(DEPDIR)/$(am__dirstamp)
-GenPoly/driver_cfa_cpp-DeclMutator.$(OBJEXT): GenPoly/$(am__dirstamp) \
-	GenPoly/$(DEPDIR)/$(am__dirstamp)
 GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT):  \
 	GenPoly/$(am__dirstamp) GenPoly/$(DEPDIR)/$(am__dirstamp)
@@ -929,6 +921,4 @@
 SynTree/driver_cfa_cpp-Mutator.$(OBJEXT): SynTree/$(am__dirstamp) \
 	SynTree/$(DEPDIR)/$(am__dirstamp)
-SynTree/driver_cfa_cpp-AddStmtVisitor.$(OBJEXT):  \
-	SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
 SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT):  \
 	SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp)
@@ -1008,10 +998,8 @@
 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Box.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-CopyParams.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-FindFunction.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-GenPoly.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Lvalue.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-ScrubTyVars.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Specialize.Po@am__quote@
@@ -1056,5 +1044,4 @@
 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-TypeEquality.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Validate.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AddressExpr.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AggregateDecl.Po@am__quote@
@@ -1450,18 +1437,4 @@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-GenPoly.obj `if test -f 'GenPoly/GenPoly.cc'; then $(CYGPATH_W) 'GenPoly/GenPoly.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/GenPoly.cc'; fi`
 
-GenPoly/driver_cfa_cpp-PolyMutator.o: GenPoly/PolyMutator.cc
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-PolyMutator.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Tpo -c -o GenPoly/driver_cfa_cpp-PolyMutator.o `test -f 'GenPoly/PolyMutator.cc' || echo '$(srcdir)/'`GenPoly/PolyMutator.cc
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='GenPoly/PolyMutator.cc' object='GenPoly/driver_cfa_cpp-PolyMutator.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-PolyMutator.o `test -f 'GenPoly/PolyMutator.cc' || echo '$(srcdir)/'`GenPoly/PolyMutator.cc
-
-GenPoly/driver_cfa_cpp-PolyMutator.obj: GenPoly/PolyMutator.cc
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-PolyMutator.obj -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Tpo -c -o GenPoly/driver_cfa_cpp-PolyMutator.obj `if test -f 'GenPoly/PolyMutator.cc'; then $(CYGPATH_W) 'GenPoly/PolyMutator.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/PolyMutator.cc'; fi`
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='GenPoly/PolyMutator.cc' object='GenPoly/driver_cfa_cpp-PolyMutator.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-PolyMutator.obj `if test -f 'GenPoly/PolyMutator.cc'; then $(CYGPATH_W) 'GenPoly/PolyMutator.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/PolyMutator.cc'; fi`
-
 GenPoly/driver_cfa_cpp-ScrubTyVars.o: GenPoly/ScrubTyVars.cc
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-ScrubTyVars.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-ScrubTyVars.Tpo -c -o GenPoly/driver_cfa_cpp-ScrubTyVars.o `test -f 'GenPoly/ScrubTyVars.cc' || echo '$(srcdir)/'`GenPoly/ScrubTyVars.cc
@@ -1534,18 +1507,4 @@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-FindFunction.obj `if test -f 'GenPoly/FindFunction.cc'; then $(CYGPATH_W) 'GenPoly/FindFunction.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/FindFunction.cc'; fi`
 
-GenPoly/driver_cfa_cpp-DeclMutator.o: GenPoly/DeclMutator.cc
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-DeclMutator.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Tpo -c -o GenPoly/driver_cfa_cpp-DeclMutator.o `test -f 'GenPoly/DeclMutator.cc' || echo '$(srcdir)/'`GenPoly/DeclMutator.cc
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='GenPoly/DeclMutator.cc' object='GenPoly/driver_cfa_cpp-DeclMutator.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-DeclMutator.o `test -f 'GenPoly/DeclMutator.cc' || echo '$(srcdir)/'`GenPoly/DeclMutator.cc
-
-GenPoly/driver_cfa_cpp-DeclMutator.obj: GenPoly/DeclMutator.cc
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-DeclMutator.obj -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Tpo -c -o GenPoly/driver_cfa_cpp-DeclMutator.obj `if test -f 'GenPoly/DeclMutator.cc'; then $(CYGPATH_W) 'GenPoly/DeclMutator.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/DeclMutator.cc'; fi`
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='GenPoly/DeclMutator.cc' object='GenPoly/driver_cfa_cpp-DeclMutator.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-DeclMutator.obj `if test -f 'GenPoly/DeclMutator.cc'; then $(CYGPATH_W) 'GenPoly/DeclMutator.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/DeclMutator.cc'; fi`
-
 GenPoly/driver_cfa_cpp-InstantiateGeneric.o: GenPoly/InstantiateGeneric.cc
 @am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-InstantiateGeneric.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Tpo -c -o GenPoly/driver_cfa_cpp-InstantiateGeneric.o `test -f 'GenPoly/InstantiateGeneric.cc' || echo '$(srcdir)/'`GenPoly/InstantiateGeneric.cc
@@ -2583,18 +2542,4 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Mutator.obj `if test -f 'SynTree/Mutator.cc'; then $(CYGPATH_W) 'SynTree/Mutator.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Mutator.cc'; fi`
-
-SynTree/driver_cfa_cpp-AddStmtVisitor.o: SynTree/AddStmtVisitor.cc
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-AddStmtVisitor.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Tpo -c -o SynTree/driver_cfa_cpp-AddStmtVisitor.o `test -f 'SynTree/AddStmtVisitor.cc' || echo '$(srcdir)/'`SynTree/AddStmtVisitor.cc
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='SynTree/AddStmtVisitor.cc' object='SynTree/driver_cfa_cpp-AddStmtVisitor.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-AddStmtVisitor.o `test -f 'SynTree/AddStmtVisitor.cc' || echo '$(srcdir)/'`SynTree/AddStmtVisitor.cc
-
-SynTree/driver_cfa_cpp-AddStmtVisitor.obj: SynTree/AddStmtVisitor.cc
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-AddStmtVisitor.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Tpo -c -o SynTree/driver_cfa_cpp-AddStmtVisitor.obj `if test -f 'SynTree/AddStmtVisitor.cc'; then $(CYGPATH_W) 'SynTree/AddStmtVisitor.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/AddStmtVisitor.cc'; fi`
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='SynTree/AddStmtVisitor.cc' object='SynTree/driver_cfa_cpp-AddStmtVisitor.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-AddStmtVisitor.obj `if test -f 'SynTree/AddStmtVisitor.cc'; then $(CYGPATH_W) 'SynTree/AddStmtVisitor.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/AddStmtVisitor.cc'; fi`
 
 SynTree/driver_cfa_cpp-TypeSubstitution.o: SynTree/TypeSubstitution.cc
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/ResolvExpr/Resolver.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -95,4 +95,9 @@
 		PassVisitor<Resolver> resolver;
 		acceptAll( translationUnit, resolver );
+	}
+
+	void resolveDecl( Declaration * decl, const SymTab::Indexer &indexer ) {
+		PassVisitor<Resolver> resolver( indexer );
+		maybeAccept( decl, resolver );
 	}
 
Index: src/ResolvExpr/Resolver.h
===================================================================
--- src/ResolvExpr/Resolver.h	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/ResolvExpr/Resolver.h	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -29,6 +29,7 @@
 	/// Checks types and binds syntactic constructs to typed representations
 	void resolve( std::list< Declaration * > translationUnit );
-	Expression * resolveInVoidContext( Expression *expr   , const SymTab::Indexer &indexer );
-	Expression * findVoidExpression  ( Expression *untyped, const SymTab::Indexer &indexer );
+	void resolveDecl( Declaration *, const SymTab::Indexer &indexer );
+	Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer );
+	Expression *findVoidExpression( Expression *untyped, const SymTab::Indexer &indexer );
 	Expression * findSingleExpression( Expression *untyped, const SymTab::Indexer &indexer );
 	void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer );
Index: src/ResolvExpr/TypeEnvironment.cc
===================================================================
--- src/ResolvExpr/TypeEnvironment.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/ResolvExpr/TypeEnvironment.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -123,13 +123,13 @@
 		for ( std::list< EqvClass >::const_iterator theClass = env.begin(); theClass != env.end(); ++theClass ) {
 			for ( std::set< std::string >::const_iterator theVar = theClass->vars.begin(); theVar != theClass->vars.end(); ++theVar ) {
-///       std::cout << "adding " << *theVar;
+///       std::cerr << "adding " << *theVar;
 				if ( theClass->type ) {
-///         std::cout << " bound to ";
-///         theClass->type->print( std::cout );
-///         std::cout << std::endl;
+///         std::cerr << " bound to ";
+///         theClass->type->print( std::cerr );
+///         std::cerr << std::endl;
 					sub.add( *theVar, theClass->type );
 				} else if ( theVar != theClass->vars.begin() ) {
 					TypeInstType *newTypeInst = new TypeInstType( Type::Qualifiers(), *theClass->vars.begin(), theClass->data.kind == TypeDecl::Ftype );
-///         std::cout << " bound to variable " << *theClass->vars.begin() << std::endl;
+///         std::cerr << " bound to variable " << *theClass->vars.begin() << std::endl;
 					sub.add( *theVar, newTypeInst );
 					delete newTypeInst;
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/SymTab/Autogen.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -16,5 +16,4 @@
 #include "Autogen.h"
 
-#include <cstddef>                 // for NULL
 #include <algorithm>               // for count_if
 #include <cassert>                 // for strict_dynamic_cast, assert, assertf
@@ -27,8 +26,10 @@
 #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+
-#include "GenPoly/DeclMutator.h"   // for DeclMutator
 #include "GenPoly/ScopedSet.h"     // for ScopedSet, ScopedSet<>::iterator
+#include "InitTweak/GenInit.h"     // for fixReturnStatements
+#include "ResolvExpr/Resolver.h"   // for resolveDecl
 #include "SymTab/Mangler.h"        // for Mangler
 #include "SynTree/Attribute.h"     // For Attribute
@@ -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
@@ -93,16 +80,10 @@
 
 	/// generates routines for tuple types.
-	/// Doesn't really need to be a mutator, but it's easier to reuse DeclMutator than it is to use AddVisit
-	/// or anything we currently have that supports adding new declarations for visitors
-	class AutogenTupleRoutines : public GenPoly::DeclMutator {
-	  public:
-		typedef GenPoly::DeclMutator Parent;
-		using Parent::mutate;
-
-		virtual DeclarationWithType * mutate( FunctionDecl *functionDecl );
-
-		virtual Type * mutate( TupleType *tupleType );
-
-		virtual CompoundStmt * mutate( CompoundStmt *compoundStmt );
+	struct AutogenTupleRoutines : public WithDeclsToAdd, public WithVisitorRef<AutogenTupleRoutines>, public WithGuards, public WithShortCircuiting {
+		void previsit( FunctionDecl *functionDecl );
+
+		void postvisit( TupleType *tupleType );
+
+		void previsit( CompoundStmt *compoundStmt );
 
 	  private:
@@ -112,14 +93,14 @@
 
 	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.
 		// AutogenTupleRoutines tupleGenerator;
-		// tupleGenerator.mutateDeclarationList( translationUnit );
+		// acceptAll( translationUnit, tupleGenerator );
 	}
 
 	bool isUnnamedBitfield( ObjectDecl * obj ) {
-		return obj != NULL && obj->get_name() == "" && obj->get_bitfieldWidth() != NULL;
+		return obj != nullptr && obj->get_name() == "" && obj->get_bitfieldWidth() != nullptr;
 	}
 
@@ -128,5 +109,5 @@
 		FunctionDecl * decl = functionDecl->clone();
 		delete decl->get_statements();
-		decl->set_statements( NULL );
+		decl->set_statements( nullptr );
 		declsToAdd.push_back( decl );
 		decl->fixUniqueId();
@@ -339,5 +320,5 @@
 				assert( ! func->get_functionType()->get_parameters().empty() );
 				ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().front() );
-				ObjectDecl * srcParam = NULL;
+				ObjectDecl * srcParam = nullptr;
 				if ( func->get_functionType()->get_parameters().size() == 2 ) {
 					srcParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().back() );
@@ -346,5 +327,5 @@
 				assert( dstParam );
 
-				Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : NULL;
+				Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : nullptr;
 				makeStructMemberOp( dstParam, srcselect, field, func, forward );
 			} // if
@@ -385,5 +366,5 @@
 				} else {
 					// no matching parameter, initialize field with default ctor
-					makeStructMemberOp( dstParam, NULL, field, func );
+					makeStructMemberOp( dstParam, nullptr, field, func );
 				}
 			}
@@ -401,11 +382,10 @@
 	void makeStructFunctions( StructDecl *aggregateDecl, StructInstType *refType, unsigned int functionNesting, std::list< Declaration * > & declsToAdd, const std::vector< FuncData > & data ) {
 		// Builtins do not use autogeneration.
-		if ( aggregateDecl->get_linkage() == LinkageSpec::BuiltinCFA ||
-			 aggregateDecl->get_linkage() == LinkageSpec::BuiltinC ) {
+		if ( LinkageSpec::isBuiltin( aggregateDecl->get_linkage() ) ) {
 			return;
 		}
 
 		// Make function polymorphic in same parameters as generic struct, if applicable
-		const std::list< TypeDecl* > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
+		const std::list< TypeDecl * > & typeParams = aggregateDecl->get_parameters(); // List of type variables to be placed on the generated functions
 
 		// generate each of the functions based on the supplied FuncData objects
@@ -572,11 +552,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,19 +567,21 @@
 	}
 
-	void AutogenerateRoutines::visit( StructDecl *structDecl ) {
-		if ( structDecl->has_body() && structsDone.find( structDecl->get_name() ) == structsDone.end() ) {
-			StructInstType structInst( Type::Qualifiers(), structDecl->get_name() );
-			for ( TypeDecl * typeDecl : structDecl->get_parameters() ) {
+	void AutogenerateRoutines::previsit( StructDecl * structDecl ) {
+		visit_children = false;
+		if ( structDecl->has_body() && structsDone.find( structDecl->name ) == structsDone.end() ) {
+			StructInstType structInst( Type::Qualifiers(), structDecl->name );
+			for ( TypeDecl * typeDecl : structDecl->parameters ) {
 				// need to visit assertions so that they are added to the appropriate maps
-				acceptAll( typeDecl->get_assertions(), *this );
-				structInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );
+				acceptAll( typeDecl->assertions, *visitor );
+				structInst.parameters.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->name, typeDecl ) ) );
 			}
 			structInst.set_baseStruct( structDecl );
 			makeStructFunctions( structDecl, &structInst, functionNesting, declsToAddAfter, data );
-			structsDone.insert( structDecl->get_name() );
+			structsDone.insert( structDecl->name );
 		} // if
 	}
 
-	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 +602,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 +648,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 +671,16 @@
 		insert( functionDecl, destructable, InitTweak::isDestructor );
 
-		maybeAccept( functionDecl->get_functionType(), *this );
+		maybeAccept( functionDecl->type, *visitor );
 		functionNesting += 1;
-		maybeAccept( functionDecl->get_statements(), *this );
+		maybeAccept( functionDecl->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 );
 	}
 
@@ -734,8 +700,7 @@
 	}
 
-	Type * AutogenTupleRoutines::mutate( TupleType * tupleType ) {
-		tupleType = strict_dynamic_cast< TupleType * >( Parent::mutate( tupleType ) );
+	void AutogenTupleRoutines::postvisit( TupleType * tupleType ) {
 		std::string mangleName = SymTab::Mangler::mangleType( tupleType );
-		if ( seenTuples.find( mangleName ) != seenTuples.end() ) return tupleType;
+		if ( seenTuples.find( mangleName ) != seenTuples.end() ) return;
 		seenTuples.insert( mangleName );
 
@@ -785,25 +750,20 @@
 		makeTupleFunctionBody( dtorDecl );
 
-		addDeclaration( ctorDecl );
-		addDeclaration( copyCtorDecl );
-		addDeclaration( dtorDecl );
-		addDeclaration( assignDecl ); // assignment should come last since it uses copy constructor in return
-
-		return tupleType;
-	}
-
-	DeclarationWithType * AutogenTupleRoutines::mutate( FunctionDecl *functionDecl ) {
-		functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
+		declsToAddBefore.push_back( ctorDecl );
+		declsToAddBefore.push_back( copyCtorDecl );
+		declsToAddBefore.push_back( dtorDecl );
+		declsToAddBefore.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return
+	}
+
+	void AutogenTupleRoutines::previsit( FunctionDecl *functionDecl ) {
+		visit_children = false;
+		maybeAccept( functionDecl->type, *visitor );
 		functionNesting += 1;
-		functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
+		maybeAccept( functionDecl->statements, *visitor );
 		functionNesting -= 1;
-		return functionDecl;
-	}
-
-	CompoundStmt * AutogenTupleRoutines::mutate( CompoundStmt *compoundStmt ) {
-		seenTuples.beginScope();
-		compoundStmt = strict_dynamic_cast< CompoundStmt * >( Parent::mutate( compoundStmt ) );
-		seenTuples.endScope();
-		return compoundStmt;
+	}
+
+	void AutogenTupleRoutines::previsit( CompoundStmt * ) {
+		GuardScope( seenTuples );
 	}
 } // SymTab
Index: src/SymTab/FixFunction.cc
===================================================================
--- src/SymTab/FixFunction.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/SymTab/FixFunction.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -27,8 +27,8 @@
 
 	DeclarationWithType * FixFunction::mutate(FunctionDecl *functionDecl) {
+		// can't delete function type because it may contain assertions, so transfer ownership to new object
 		ObjectDecl *pointer = new ObjectDecl( functionDecl->get_name(), functionDecl->get_storageClasses(), functionDecl->get_linkage(), 0, new PointerType( Type::Qualifiers(), functionDecl->get_type() ), 0, functionDecl->get_attributes() );
 		functionDecl->get_attributes().clear();
-		// can't delete function type because it may contain assertions, but can't transfer ownership without a clone since set_type checks for nullptr
-		functionDecl->set_type( functionDecl->get_type()->clone() );
+		functionDecl->type = nullptr;
 		delete functionDecl;
 		return pointer;
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/SymTab/Indexer.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -40,17 +40,4 @@
 
 namespace SymTab {
-	struct NewScope {
-		NewScope( SymTab::Indexer & indexer ) : indexer( indexer ) { indexer.enterScope(); }
-		~NewScope() { indexer.leaveScope(); }
-		SymTab::Indexer & indexer;
-	};
-
-	template< typename TreeType, typename VisitorType >
-	inline void acceptNewScope( TreeType *tree, VisitorType &visitor ) {
-		visitor.enterScope();
-		maybeAccept( tree, visitor );
-		visitor.leaveScope();
-	}
-
 	typedef std::unordered_map< std::string, DeclarationWithType* > MangleTable;
 	typedef std::unordered_map< std::string, MangleTable > IdTable;
@@ -198,9 +185,9 @@
 	}
 
-	Indexer::Indexer( bool _doDebug ) : tables( 0 ), scope( 0 ), doDebug( _doDebug ) {}
-
-	Indexer::Indexer( const Indexer &that ) : tables( newRef( that.tables ) ), scope( that.scope ), doDebug( that.doDebug ) {}
-
-	Indexer::Indexer( Indexer &&that ) : tables( that.tables ), scope( that.scope ), doDebug( that.doDebug ) {
+	Indexer::Indexer() : tables( 0 ), scope( 0 ) {}
+
+	Indexer::Indexer( const Indexer &that ) : doDebug( that.doDebug ), tables( newRef( that.tables ) ), scope( that.scope ) {}
+
+	Indexer::Indexer( Indexer &&that ) : doDebug( that.doDebug ), tables( that.tables ), scope( that.scope ) {
 		that.tables = 0;
 	}
Index: src/SymTab/Indexer.h
===================================================================
--- src/SymTab/Indexer.h	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/SymTab/Indexer.h	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -26,5 +26,5 @@
 	class Indexer {
 	  public:
-		explicit Indexer( bool useDebug = false );
+		explicit Indexer();
 
 		Indexer( const Indexer &that );
@@ -76,4 +76,5 @@
 		void addTrait( TraitDecl *decl );
 
+		bool doDebug = false; ///< Display debugging trace?
 	  private:
 		struct Impl;
@@ -81,5 +82,4 @@
 		Impl *tables;         ///< Copy-on-write instance of table data structure
 		unsigned long scope;  ///< Scope index of this pointer
-		bool doDebug;         ///< Display debugging trace?
 
 		/// Takes a new ref to a table (returns null if null)
Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/SymTab/Mangler.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -31,5 +31,5 @@
 
 namespace SymTab {
-	std::string Mangler::mangleType( Type *ty ) {
+	std::string Mangler::mangleType( Type * ty ) {
 		Mangler mangler( false, true );
 		maybeAccept( ty, mangler );
@@ -48,5 +48,5 @@
 	}
 
-	void Mangler::mangleDecl( DeclarationWithType *declaration ) {
+	void Mangler::mangleDecl( DeclarationWithType * declaration ) {
 		bool wasTopLevel = isTopLevel;
 		if ( isTopLevel ) {
@@ -79,18 +79,18 @@
 	}
 
-	void Mangler::visit( ObjectDecl *declaration ) {
+	void Mangler::visit( ObjectDecl * declaration ) {
 		mangleDecl( declaration );
 	}
 
-	void Mangler::visit( FunctionDecl *declaration ) {
+	void Mangler::visit( FunctionDecl * declaration ) {
 		mangleDecl( declaration );
 	}
 
-	void Mangler::visit( VoidType *voidType ) {
+	void Mangler::visit( VoidType * voidType ) {
 		printQualifiers( voidType );
 		mangleName << "v";
 	}
 
-	void Mangler::visit( BasicType *basicType ) {
+	void Mangler::visit( BasicType * basicType ) {
 		static const char *btLetter[] = {
 			"b",	// Bool
@@ -121,5 +121,5 @@
 	}
 
-	void Mangler::visit( PointerType *pointerType ) {
+	void Mangler::visit( PointerType * pointerType ) {
 		printQualifiers( pointerType );
 		mangleName << "P";
@@ -127,5 +127,5 @@
 	}
 
-	void Mangler::visit( ArrayType *arrayType ) {
+	void Mangler::visit( ArrayType * arrayType ) {
 		// TODO: encode dimension
 		printQualifiers( arrayType );
@@ -134,5 +134,5 @@
 	}
 
-	void Mangler::visit( ReferenceType *refType ) {
+	void Mangler::visit( ReferenceType * refType ) {
 		printQualifiers( refType );
 		mangleName << "R";
@@ -149,5 +149,5 @@
 	}
 
-	void Mangler::visit( FunctionType *functionType ) {
+	void Mangler::visit( FunctionType * functionType ) {
 		printQualifiers( functionType );
 		mangleName << "F";
@@ -160,5 +160,5 @@
 	}
 
-	void Mangler::mangleRef( ReferenceToType *refType, std::string prefix ) {
+	void Mangler::mangleRef( ReferenceToType * refType, std::string prefix ) {
 		printQualifiers( refType );
 
@@ -166,5 +166,5 @@
 	}
 
-	void Mangler::mangleGenericRef( ReferenceToType *refType, std::string prefix ) {
+	void Mangler::mangleGenericRef( ReferenceToType * refType, std::string prefix ) {
 		printQualifiers( refType );
 
@@ -189,19 +189,19 @@
 	}
 
-	void Mangler::visit( StructInstType *aggregateUseType ) {
+	void Mangler::visit( StructInstType * aggregateUseType ) {
 		if ( typeMode ) mangleGenericRef( aggregateUseType, "s" );
 		else mangleRef( aggregateUseType, "s" );
 	}
 
-	void Mangler::visit( UnionInstType *aggregateUseType ) {
+	void Mangler::visit( UnionInstType * aggregateUseType ) {
 		if ( typeMode ) mangleGenericRef( aggregateUseType, "u" );
 		else mangleRef( aggregateUseType, "u" );
 	}
 
-	void Mangler::visit( EnumInstType *aggregateUseType ) {
+	void Mangler::visit( EnumInstType * aggregateUseType ) {
 		mangleRef( aggregateUseType, "e" );
 	}
 
-	void Mangler::visit( TypeInstType *typeInst ) {
+	void Mangler::visit( TypeInstType * typeInst ) {
 		VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
 		if ( varNum == varNums.end() ) {
@@ -231,27 +231,27 @@
 	}
 
-	void Mangler::visit( TupleType *tupleType ) {
+	void Mangler::visit( TupleType * tupleType ) {
 		printQualifiers( tupleType );
 		mangleName << "T";
-		acceptAll( tupleType->get_types(), *this );
+		acceptAll( tupleType->types, *this );
 		mangleName << "_";
 	}
 
-	void Mangler::visit( VarArgsType *varArgsType ) {
+	void Mangler::visit( VarArgsType * varArgsType ) {
 		printQualifiers( varArgsType );
 		mangleName << "VARGS";
 	}
 
-	void Mangler::visit( __attribute__((unused)) ZeroType *zeroType ) {
+	void Mangler::visit( ZeroType * ) {
 		mangleName << "Z";
 	}
 
-	void Mangler::visit( __attribute__((unused)) OneType *oneType ) {
+	void Mangler::visit( OneType * ) {
 		mangleName << "O";
 	}
 
-	void Mangler::visit( TypeDecl *decl ) {
+	void Mangler::visit( TypeDecl * decl ) {
 		static const char *typePrefix[] = { "BT", "BD", "BF" };
-		mangleName << typePrefix[ decl->get_kind() ] << ( decl->get_name().length() + 1 ) << decl->get_name();
+		mangleName << typePrefix[ decl->get_kind() ] << ( decl->name.length() + 1 ) << decl->name;
 	}
 
@@ -262,5 +262,5 @@
 	}
 
-	void Mangler::printQualifiers( Type *type ) {
+	void Mangler::printQualifiers( Type * type ) {
 		// skip if not including qualifiers
 		if ( typeMode ) return;
@@ -270,5 +270,5 @@
 			int tcount = 0, dcount = 0, fcount = 0, vcount = 0;
 			mangleName << "A";
-			for ( Type::ForallList::iterator i = type->get_forall().begin(); i != type->get_forall().end(); ++i ) {
+			for ( Type::ForallList::iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
 				switch ( (*i)->get_kind() ) {
 				  case TypeDecl::Any:
@@ -287,6 +287,6 @@
 					assert( false );
 				} // switch
-				varNums[ (*i )->get_name() ] = std::pair< int, int >( nextVarNum++, (int )(*i )->get_kind() );
-				for ( std::list< DeclarationWithType* >::iterator assert = (*i )->get_assertions().begin(); assert != (*i )->get_assertions().end(); ++assert ) {
+				varNums[ (*i)->name ] = std::pair< int, int >( nextVarNum++, (int)(*i)->get_kind() );
+				for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) {
 					Mangler sub_mangler( mangleOverridable, typeMode );
 					sub_mangler.nextVarNum = nextVarNum;
@@ -315,6 +315,7 @@
 //		} // if
 		if ( type->get_lvalue() ) {
+			// mangle based on whether the type is lvalue, so that the resolver can differentiate lvalues and rvalues
 			mangleName << "L";
-		} // if
+		}
 		if ( type->get_atomic() ) {
 			mangleName << "A";
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/SymTab/Validate.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -56,4 +56,5 @@
 #include "FixFunction.h"               // for FixFunction
 #include "Indexer.h"                   // for Indexer
+#include "InitTweak/GenInit.h"         // for fixReturnStatements
 #include "InitTweak/InitTweak.h"       // for isCtorDtorAssign
 #include "Parser/LinkageSpec.h"        // for C
@@ -150,6 +151,6 @@
 	/// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID.
 	struct ForallPointerDecay final {
-		void previsit( ObjectDecl *object );
-		void previsit( FunctionDecl *func );
+		void previsit( ObjectDecl * object );
+		void previsit( FunctionDecl * func );
 	};
 
@@ -579,6 +580,6 @@
 
 	/// Fix up assertions - flattens assertion lists, removing all trait instances
-	void forallFixer( Type * func ) {
-		for ( TypeDecl * type : func->get_forall() ) {
+	void forallFixer( std::list< TypeDecl * > & forall, BaseSyntaxNode * node ) {
+		for ( TypeDecl * type : forall ) {
 			std::list< DeclarationWithType * > asserts;
 			asserts.splice( asserts.end(), type->assertions );
@@ -599,5 +600,5 @@
 				assertion = assertion->acceptMutator( fixer );
 				if ( fixer.get_isVoid() ) {
-					throw SemanticError( "invalid type void in assertion of function ", func );
+					throw SemanticError( "invalid type void in assertion of function ", node );
 				} // if
 			} // for
@@ -607,7 +608,7 @@
 
 	void ForallPointerDecay::previsit( ObjectDecl *object ) {
-		forallFixer( object->get_type() );
-		if ( PointerType *pointer = dynamic_cast< PointerType * >( object->get_type() ) ) {
-			forallFixer( pointer->get_base() );
+		forallFixer( object->type->forall, object );
+		if ( PointerType *pointer = dynamic_cast< PointerType * >( object->type ) ) {
+			forallFixer( pointer->base->forall, object );
 		} // if
 		object->fixUniqueId();
@@ -615,5 +616,5 @@
 
 	void ForallPointerDecay::previsit( FunctionDecl *func ) {
-		forallFixer( func->get_type() );
+		forallFixer( func->type->forall, func );
 		func->fixUniqueId();
 	}
Index: src/SynTree/AddStmtVisitor.cc
===================================================================
--- src/SynTree/AddStmtVisitor.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ 	(revision )
@@ -1,93 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// AddStmtVisitor.cc --
-//
-// Author           : Rob Schluntz
-// Created On       : Wed Jun 22 12:11:17 2016
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Aug  4 11:23:47 2016
-// Update Count     : 16
-//
-
-#include "AddStmtVisitor.h"
-
-#include "Common/SemanticError.h"  // for SemanticError
-#include "Declaration.h"           // for Declaration
-#include "Expression.h"            // for Expression
-#include "Statement.h"             // for CompoundStmt, ForStmt, IfStmt, Sta...
-#include "SynTree/Label.h"         // for Label, noLabels
-
-void AddStmtVisitor::visitStatementList( std::list< Statement* > &statements ) {
-	for ( std::list< Statement* >::iterator i = statements.begin(); i != statements.end(); ++i ) {
-		if ( ! stmtsToAddAfter.empty() ) {
-			statements.splice( i, stmtsToAddAfter );
-		} // if
-		(*i)->accept( *this );
-		if ( ! stmtsToAdd.empty() ) {
-			statements.splice( i, stmtsToAdd );
-		} // if
-	} // for
-	if ( ! stmtsToAddAfter.empty() ) {
-		statements.splice( statements.end(), stmtsToAddAfter );
-	} // if
-}
-
-Statement * AddStmtVisitor::visitStatement( Statement *stmt ) {
-	maybeAccept( stmt, *this );
-	if ( ! stmtsToAdd.empty() || ! stmtsToAddAfter.empty() ) {
-		CompoundStmt *compound = new CompoundStmt( noLabels );
-		compound->get_kids().splice( compound->get_kids().end(), stmtsToAdd );
-		compound->get_kids().push_back( stmt );
-		compound->get_kids().splice( compound->get_kids().end(), stmtsToAddAfter );
-		return compound;
-	} else {
-		return stmt;
-	}
-}
-
-void AddStmtVisitor::visit(CompoundStmt *compoundStmt) {
-	visitStatementList( compoundStmt->get_kids() );
-}
-
-void AddStmtVisitor::visit(IfStmt *ifStmt) {
-	ifStmt->set_thenPart( visitStatement( ifStmt->get_thenPart() ) );
-	ifStmt->set_elsePart( visitStatement( ifStmt->get_elsePart() ) );
-	maybeAccept( ifStmt->get_condition(), *this );
-}
-
-void AddStmtVisitor::visit(WhileStmt *whileStmt) {
-	whileStmt->set_body( visitStatement( whileStmt->get_body() ) );
-	maybeAccept( whileStmt->get_condition(), *this );
-}
-
-void AddStmtVisitor::visit(ForStmt *forStmt) {
-	forStmt->set_body( visitStatement( forStmt->get_body() ) );
-	acceptAll( forStmt->get_initialization(), *this );
-	maybeAccept( forStmt->get_condition(), *this );
-	maybeAccept( forStmt->get_increment(), *this );
-}
-
-void AddStmtVisitor::visit(SwitchStmt *switchStmt) {
-	visitStatementList( switchStmt->get_statements() );
-	maybeAccept( switchStmt->get_condition(), *this );
-}
-
-void AddStmtVisitor::visit(CaseStmt *caseStmt) {
-	visitStatementList( caseStmt->get_statements() );
-	maybeAccept( caseStmt->get_condition(), *this );
-}
-
-void AddStmtVisitor::visit(CatchStmt *catchStmt) {
-	catchStmt->set_body( visitStatement( catchStmt->get_body() ) );
-	maybeAccept( catchStmt->get_decl(), *this );
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/SynTree/AddStmtVisitor.h
===================================================================
--- src/SynTree/AddStmtVisitor.h	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ 	(revision )
@@ -1,47 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// AddStmtVisitor.h --
-//
-// Author           : Rob Schluntz
-// Created On       : Wed Jun 22 12:05:48 2016
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul 22 09:51:08 2017
-// Update Count     : 9
-//
-
-#pragma once
-
-#include <list>               // for list
-
-#include "SynTree/SynTree.h"  // for Visitor Nodes
-#include "SynTree/Visitor.h"  // for Visitor
-
-class AddStmtVisitor : public Visitor {
-  public:
-	typedef Visitor Parent;
-
-	using Parent::visit;
-	virtual void visit(CompoundStmt *compoundStmt);
-	virtual void visit(IfStmt *ifStmt);
-	virtual void visit(WhileStmt *whileStmt);
-	virtual void visit(ForStmt *forStmt);
-	virtual void visit(SwitchStmt *switchStmt);
-	virtual void visit(CaseStmt *caseStmt);
-	virtual void visit(CatchStmt *catchStmt);
-
-  protected:
-	void visitStatementList( std::list< Statement * > & );
-	Statement * visitStatement( Statement * );
-	std::list< Statement* > stmtsToAdd;
-	std::list< Statement* > stmtsToAddAfter;
-};
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/SynTree/Visitor.h	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -25,5 +25,5 @@
   public:
 	// visit: Default implementation of all functions visits the children
-    // of the given syntax node, but performs no other action.
+	// of the given syntax node, but performs no other action.
 
 	virtual void visit( ObjectDecl *objectDecl );
Index: src/SynTree/module.mk
===================================================================
--- src/SynTree/module.mk	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/SynTree/module.mk	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -48,5 +48,4 @@
        SynTree/Visitor.cc \
        SynTree/Mutator.cc \
-       SynTree/AddStmtVisitor.cc \
        SynTree/TypeSubstitution.cc \
        SynTree/Attribute.cc \
Index: src/Tuples/TupleExpansion.cc
===================================================================
--- src/Tuples/TupleExpansion.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/Tuples/TupleExpansion.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -21,5 +21,4 @@
 #include "Common/ScopedMap.h"     // for ScopedMap
 #include "Common/utility.h"       // for CodeLocation
-#include "GenPoly/DeclMutator.h"  // for DeclMutator
 #include "InitTweak/InitTweak.h"  // for getFunction
 #include "Parser/LinkageSpec.h"   // for Spec, C, Intrinsic
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/main.cc	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -239,7 +239,4 @@
 		} // if
 
-		// OPTPRINT( "Concurrency" )
-		// Concurrency::applyKeywords( translationUnit );
-
 		// add the assignment statement after the initialization of a type parameter
 		OPTPRINT( "validate" )
Index: src/tests/.expect/64/sched-ext-parse.txt
===================================================================
--- src/tests/.expect/64/sched-ext-parse.txt	(revision 4dfa56274012793a0b58553f6bb4c21708ba0a1d)
+++ src/tests/.expect/64/sched-ext-parse.txt	(revision a2d4d1c02d4227d2418326811c264dc1355f54d8)
@@ -1055,9 +1055,9 @@
 static inline struct condition ___operator_assign__F10scondition_R10scondition10scondition_autogen___1(struct condition *___dst__R10scondition_1, struct condition ___src__10scondition_1){
     struct condition ___ret__10scondition_1;
-    struct __condition_blocked_queue_t _tmp_cp56;
+    struct __condition_blocked_queue_t _tmp_cp4;
     struct __condition_blocked_queue_t _tmp_cp_ret29;
-    ((void)(((void)(_tmp_cp_ret29=___operator_assign__F28s__condition_blocked_queue_t_R28s__condition_blocked_queue_t28s__condition_blocked_queue_t_autogen___1((&(*___dst__R10scondition_1).__blocked__28s__condition_blocked_queue_t_1), (((void)___constructor__F_R28s__condition_blocked_queue_t28s__condition_blocked_queue_t_autogen___1((&_tmp_cp56), ___src__10scondition_1.__blocked__28s__condition_blocked_queue_t_1)) , _tmp_cp56)))) , _tmp_cp_ret29));
+    ((void)(((void)(_tmp_cp_ret29=___operator_assign__F28s__condition_blocked_queue_t_R28s__condition_blocked_queue_t28s__condition_blocked_queue_t_autogen___1((&(*___dst__R10scondition_1).__blocked__28s__condition_blocked_queue_t_1), (((void)___constructor__F_R28s__condition_blocked_queue_t28s__condition_blocked_queue_t_autogen___1((&_tmp_cp4), ___src__10scondition_1.__blocked__28s__condition_blocked_queue_t_1)) , _tmp_cp4)))) , _tmp_cp_ret29));
     ((void)___destructor__F_R28s__condition_blocked_queue_t_autogen___1((&_tmp_cp_ret29)));
-    ((void)___destructor__F_R28s__condition_blocked_queue_t_autogen___1((&_tmp_cp56)));
+    ((void)___destructor__F_R28s__condition_blocked_queue_t_autogen___1((&_tmp_cp4)));
     ((void)((*___dst__R10scondition_1).__monitors__PP13smonitor_desc_1=___src__10scondition_1.__monitors__PP13smonitor_desc_1));
     ((void)((*___dst__R10scondition_1).__monitor_count__Us_1=___src__10scondition_1.__monitor_count__Us_1));
@@ -1155,9 +1155,9 @@
 static inline struct M ___operator_assign__F2sM_R2sM2sM_autogen___1(struct M *___dst__R2sM_1, struct M ___src__2sM_1){
     struct M ___ret__2sM_1;
-    struct monitor_desc _tmp_cp60;
+    struct monitor_desc _tmp_cp5;
     struct monitor_desc _tmp_cp_ret31;
-    ((void)(((void)(_tmp_cp_ret31=___operator_assign__F13smonitor_desc_R13smonitor_desc13smonitor_desc_autogen___1((&(*___dst__R2sM_1).____mon__13smonitor_desc_1), (((void)___constructor__F_R13smonitor_desc13smonitor_desc_autogen___1((&_tmp_cp60), ___src__2sM_1.____mon__13smonitor_desc_1)) , _tmp_cp60)))) , _tmp_cp_ret31));
+    ((void)(((void)(_tmp_cp_ret31=___operator_assign__F13smonitor_desc_R13smonitor_desc13smonitor_desc_autogen___1((&(*___dst__R2sM_1).____mon__13smonitor_desc_1), (((void)___constructor__F_R13smonitor_desc13smonitor_desc_autogen___1((&_tmp_cp5), ___src__2sM_1.____mon__13smonitor_desc_1)) , _tmp_cp5)))) , _tmp_cp_ret31));
     ((void)___destructor__F_R13smonitor_desc_autogen___1((&_tmp_cp_ret31)));
-    ((void)___destructor__F_R13smonitor_desc_autogen___1((&_tmp_cp60)));
+    ((void)___destructor__F_R13smonitor_desc_autogen___1((&_tmp_cp5)));
     ((void)___constructor__F_R2sM2sM_autogen___1((&___ret__2sM_1), ___src__2sM_1));
     return ((struct M )___ret__2sM_1);
