Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 233e4d9b6c11222533f75c7e90ac84e0e527d6b9)
+++ src/InitTweak/FixInit.cc	(revision 1674ff8d97df610098c5e0ed4230d5f2691eff36)
@@ -52,4 +52,5 @@
 	namespace {
 		typedef std::unordered_map< Expression *, TypeSubstitution * > EnvMap;
+		typedef std::unordered_map< int, int > UnqCount;
 
 		class InsertImplicitCalls final : public GenPoly::PolyMutator {
@@ -74,10 +75,10 @@
 			/// generate/resolve copy construction expressions for each, and generate/resolve destructors for both
 			/// arguments and return value temporaries
-			static void resolveImplicitCalls( std::list< Declaration * > & translationUnit, const EnvMap & envMap );
+			static void resolveImplicitCalls( std::list< Declaration * > & translationUnit, const EnvMap & envMap, UnqCount & unqCount );
 
 			typedef SymTab::Indexer Parent;
 			using Parent::visit;
 
-			ResolveCopyCtors( const EnvMap & envMap ) : envMap( envMap ) {}
+			ResolveCopyCtors( const EnvMap & envMap, UnqCount & unqCount ) : envMap( envMap ), unqCount( unqCount ) {}
 
 			virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override;
@@ -94,4 +95,5 @@
 			TypeSubstitution * env;
 			const EnvMap & envMap;
+			UnqCount & unqCount; // count the number of times each unique expr ID appears
 		};
 
@@ -202,7 +204,8 @@
 		class FixCopyCtors final : public GenPoly::PolyMutator {
 		  public:
+			FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){}
 			/// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors, call expression,
 			/// and destructors
-			static void fixCopyCtors( std::list< Declaration * > &translationUnit );
+			static void fixCopyCtors( std::list< Declaration * > &translationUnit, UnqCount & unqCount );
 
 			typedef GenPoly::PolyMutator Parent;
@@ -211,4 +214,6 @@
 			virtual Expression * mutate( UniqueExpr * unqExpr ) override;
 			virtual Expression * mutate( StmtExpr * stmtExpr ) override;
+
+			UnqCount & unqCount;
 		};
 
@@ -272,12 +277,13 @@
 
 		EnvMap envMap;
+		UnqCount unqCount;
 
 		InsertImplicitCalls::insert( translationUnit, envMap );
-		ResolveCopyCtors::resolveImplicitCalls( translationUnit, envMap );
+		ResolveCopyCtors::resolveImplicitCalls( translationUnit, envMap, unqCount );
 		InsertDtors::insert( translationUnit );
 		FixInit::fixInitializers( translationUnit );
 
 		// FixCopyCtors must happen after FixInit, so that destructors are placed correctly
-		FixCopyCtors::fixCopyCtors( translationUnit );
+		FixCopyCtors::fixCopyCtors( translationUnit, unqCount );
 
 		GenStructMemberCalls::generate( translationUnit );
@@ -298,6 +304,6 @@
 		}
 
-		void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit, const EnvMap & envMap ) {
-			ResolveCopyCtors resolver( envMap );
+		void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit, const EnvMap & envMap, UnqCount & unqCount ) {
+			ResolveCopyCtors resolver( envMap, unqCount );
 			acceptAll( translationUnit, resolver );
 		}
@@ -329,6 +335,6 @@
 		}
 
-		void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit ) {
-			FixCopyCtors fixer;
+		void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) {
+			FixCopyCtors fixer( unqCount );
 			mutateAll( translationUnit, fixer );
 		}
@@ -520,4 +526,5 @@
 		void ResolveCopyCtors::visit( UniqueExpr * unqExpr ) {
 			static std::unordered_set< int > vars;
+			unqCount[ unqExpr->get_id() ]++;  // count the number of unique expressions for each ID
 			if ( vars.count( unqExpr->get_id() ) ) {
 				// xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
@@ -636,4 +643,6 @@
 
 		Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {
+			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;
@@ -645,4 +654,7 @@
 				delete unqExpr->get_result();
 				unqExpr->set_result( maybeClone( unqExpr->get_expr()->get_result() ) );
+				if ( unqCount[ unqExpr->get_id() ] == 0 ) {  // insert destructor after the last use of the unique expression
+					stmtsToAdd.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
@@ -651,5 +663,7 @@
 				return unqExpr;
 			}
-			unqExpr = safe_dynamic_cast< UniqueExpr * >( Parent::mutate( unqExpr ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup
+			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 );
 			unqMap[unqExpr->get_id()] = unqExpr;
 			if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) {
@@ -661,4 +675,9 @@
 				getCallArg( deref, 0 ) = unqExpr;
 				addDeref.insert( unqExpr->get_id() );
+				if ( unqCount[ unqExpr->get_id() ] == 0 ) {  // insert destructor after the last use of the unique expression
+					stmtsToAdd.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] );
+				} else { // remember dtors for last instance of unique expr
+					dtors[ unqExpr->get_id() ] = fixer.stmtsToAddAfter;
+				}
 				return deref;
 			}
