Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision b3b2077b1feda429f174cfb4f374cb1e00580630)
+++ src/InitTweak/FixInit.cc	(revision 141b7868c72c7947affae41e61e4bfcd7f9c6652)
@@ -65,5 +65,9 @@
 			static void resolveImplicitCalls( std::list< Declaration * > & translationUnit );
 
+			typedef SymTab::Indexer Parent;
+			using Parent::visit;
+
 			virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr );
+			virtual void visit( UniqueExpr * unqExpr );
 
 			/// create and resolve ctor/dtor expression: fname(var, [cpArg])
@@ -178,4 +182,5 @@
 
 			virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr );
+			virtual Expression * mutate( UniqueExpr * unqExpr );
 		};
 
@@ -421,5 +426,5 @@
 		void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) {
 			CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
-			Visitor::visit( impCpCtorExpr );
+			Parent::visit( impCpCtorExpr );
 			env = impCpCtorExpr->get_env(); // xxx - maybe we really should just have a PolyIndexer...
 
@@ -455,4 +460,26 @@
 		}
 
+		void ResolveCopyCtors::visit( UniqueExpr * unqExpr ) {
+			static std::unordered_set< int > vars;
+			if ( vars.count( unqExpr->get_id() ) ) {
+				// xxx - hack to prevent double-handling of unique exprs, otherwise too many temporary variables and destructors are generated
+				return;
+			}
+
+			Parent::visit( unqExpr );
+			// it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought
+			assert( unqExpr->get_result() );
+			if ( ImplicitCopyCtorExpr * impCpCtorExpr = dynamic_cast<ImplicitCopyCtorExpr*>( unqExpr->get_expr() ) ) {
+				// note the variable used as the result from the call
+				assert( impCpCtorExpr->get_result() && impCpCtorExpr->get_returnDecls().size() == 1 );
+				unqExpr->set_var( new VariableExpr( impCpCtorExpr->get_returnDecls().front() ) );
+			} 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_expr_", unqExpr->get_id()), DeclarationNode::NoStorageClass, LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) );
+				unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) );
+			}
+			vars.insert( unqExpr->get_id() );
+		}
+
 
 		Expression * FixCopyCtors::mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {
@@ -526,4 +553,35 @@
 				return callExpr;
 			} // if
+		}
+
+		Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {
+			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
+			unqExpr = safe_dynamic_cast< UniqueExpr * >( Parent::mutate( unqExpr ) );
+			if ( unqMap.count( unqExpr->get_id() ) ) {
+				// take data from other UniqueExpr to ensure consistency
+				delete unqExpr->get_expr();
+				unqExpr->set_expr( unqMap[unqExpr->get_id()]->get_expr()->clone() );
+				delete unqExpr->get_result();
+				unqExpr->set_result( maybeClone( unqExpr->get_expr()->get_result() ) );
+				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;
+			}
+			unqMap[unqExpr->get_id()] = unqExpr;
+			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;
 		}
 
