Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 698ec72fc748f1221cc0c8cf5d714510c3c4999e)
+++ src/InitTweak/FixInit.cc	(revision a6c5d7c3b627f0180da89e9ae78c01a821292827)
@@ -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 698ec72fc748f1221cc0c8cf5d714510c3c4999e)
+++ src/InitTweak/GenInit.cc	(revision a6c5d7c3b627f0180da89e9ae78c01a821292827)
@@ -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 698ec72fc748f1221cc0c8cf5d714510c3c4999e)
+++ src/InitTweak/GenInit.h	(revision a6c5d7c3b627f0180da89e9ae78c01a821292827)
@@ -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 698ec72fc748f1221cc0c8cf5d714510c3c4999e)
+++ src/InitTweak/InitTweak.cc	(revision a6c5d7c3b627f0180da89e9ae78c01a821292827)
@@ -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 698ec72fc748f1221cc0c8cf5d714510c3c4999e)
+++ src/InitTweak/InitTweak.h	(revision a6c5d7c3b627f0180da89e9ae78c01a821292827)
@@ -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
