Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 1622af58aed4c83eebaa99e928f0b0358263b087)
+++ src/AST/Convert.cpp	(revision b7fd9daffd1af20c4c7cc80ac4660136917af20f)
@@ -1041,18 +1041,16 @@
 
 	const ast::Expr * visit( const ast::StmtExpr * node ) override final {
-		auto stmts = node->stmts;
-		// disable sharing between multiple StmtExprs explicitly.
-		// this should no longer be true.
-
 		auto rslt = new StmtExpr(
-			get<CompoundStmt>().accept1(stmts)
+			get<CompoundStmt>().accept1(node->stmts)
 		);
 
 		rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls);
 		rslt->dtors       = get<Expression>().acceptL(node->dtors);
-		if (node->resultExpr) {
-			// this MUST be found by children visit
-			rslt->resultExpr  = strict_dynamic_cast<ExprStmt *>(readonlyCache.at(node->resultExpr));
-		}
+
+		// is this even used after convert?
+		//if (tmp->resultExpr) {
+		//	// this MUST be found by children visit
+		//	rslt->resultExpr  = strict_dynamic_cast<ExprStmt *>(readonlyCache.at(tmp->resultExpr));
+		//}
 
 		auto expr = visitBaseExpr( node, rslt );
Index: src/AST/Copy.hpp
===================================================================
--- src/AST/Copy.hpp	(revision 1622af58aed4c83eebaa99e928f0b0358263b087)
+++ src/AST/Copy.hpp	(revision b7fd9daffd1af20c4c7cc80ac4660136917af20f)
@@ -88,4 +88,8 @@
 	}
 
+	void postvisit( const StmtExpr * node ) {
+		readonlyInsert( &node->resultExpr );
+	}
+
 	void postvisit( const MemberExpr * node ) {
 		readonlyInsert( &node->member );
@@ -122,5 +126,5 @@
 node_t * deepCopy( const node_t * localRoot ) {
 	Pass< DeepCopyCore > dc;
-	node_t const * newRoot = localRoot->accept( dc );
+	node_t const * newRoot = strict_dynamic_cast<node_t const*>(localRoot->accept( dc ));
 	dc.core.readonlyUpdates();
 	return const_cast< node_t * >( newRoot );
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 1622af58aed4c83eebaa99e928f0b0358263b087)
+++ src/AST/Expr.hpp	(revision b7fd9daffd1af20c4c7cc80ac4660136917af20f)
@@ -767,5 +767,6 @@
 
 /// An expression which must only be evaluated once
-class UniqueExpr final : public Expr {
+class 
+UniqueExpr final : public Expr {
 	static unsigned long long nextId;
 public:
Index: src/Tuples/TupleExpansionNew.cpp
===================================================================
--- src/Tuples/TupleExpansionNew.cpp	(revision 1622af58aed4c83eebaa99e928f0b0358263b087)
+++ src/Tuples/TupleExpansionNew.cpp	(revision b7fd9daffd1af20c4c7cc80ac4660136917af20f)
@@ -21,4 +21,8 @@
 		void previsit( const ast::UntypedMemberExpr * ) { visit_children = false; }
         const ast::Expr * postvisit( const ast::UntypedMemberExpr * memberExpr );
+	};
+	struct UniqueExprExpander final : public ast::WithDeclsToAdd<> {
+		const ast::Expr * postvisit( const ast::UniqueExpr * unqExpr );
+		std::map< int, ast::ptr<ast::Expr> > decls; // not vector, because order added may not be increasing order
 	};
 } // namespace
@@ -66,3 +70,44 @@
 	}
 } // namespace
+
+void expandUniqueExpr( ast::TranslationUnit & translationUnit ) {
+	ast::Pass< UniqueExprExpander >::run( translationUnit );
+}
+
+namespace {
+	const ast::Expr * UniqueExprExpander::postvisit( const ast::UniqueExpr * unqExpr ) {
+		const CodeLocation loc = unqExpr->location;
+		const int id = unqExpr->id;
+
+		// on first time visiting a unique expr with a particular ID, generate the expression that replaces all UniqueExprs with that ID,
+		// and lookup on subsequent hits. This ensures that all unique exprs with the same ID reference the same variable.
+		if ( ! decls.count( id ) ) {
+			ast::ptr< ast::Expr > assignUnq;
+			const ast::VariableExpr * var = unqExpr->var;
+			if ( unqExpr->object ) {
+				// an object was generated to represent this unique expression -- it should be added to the list of declarations now
+				declsToAddBefore.push_back( unqExpr->object.as< ast::Decl >() );
+				// deep copy required due to unresolved issues with UniqueExpr
+				assignUnq = ast::UntypedExpr::createAssign( loc, var, unqExpr->expr );
+			} else {
+				const auto commaExpr = unqExpr->expr.strict_as< ast::CommaExpr >();
+				assignUnq = commaExpr->arg1;
+			}
+			auto finished = new ast::ObjectDecl( loc, toString( "_unq", id, "_finished_" ), new ast::BasicType( ast::BasicType::Kind::Bool ),
+				new ast::SingleInit( loc, ast::ConstantExpr::from_int( loc, 0 ) ), {}, ast::Linkage::Cforall );
+			declsToAddBefore.push_back( finished );
+			// (finished ? _unq_expr_N : (_unq_expr_N = <unqExpr->get_expr()>, finished = 1, _unq_expr_N))
+			// This pattern ensures that each unique expression is evaluated once, regardless of evaluation order of the generated C code.
+			auto assignFinished = ast::UntypedExpr::createAssign( loc, new ast::VariableExpr( loc, finished ),
+				ast::ConstantExpr::from_int( loc, 1 ) );
+			auto condExpr = new ast::ConditionalExpr( loc, new ast::VariableExpr( loc, finished ), var,
+				new ast::CommaExpr( loc, new ast::CommaExpr( loc, assignUnq, assignFinished ), var ) );
+			condExpr->result = var->result;
+			condExpr->env = unqExpr->env;
+			decls[id] = condExpr;
+		}
+		//delete unqExpr;
+		return ast::deepCopy(decls[id].get());
+	}
+} // namespace
 } // namespace Tuples
Index: src/Tuples/Tuples.h
===================================================================
--- src/Tuples/Tuples.h	(revision 1622af58aed4c83eebaa99e928f0b0358263b087)
+++ src/Tuples/Tuples.h	(revision b7fd9daffd1af20c4c7cc80ac4660136917af20f)
@@ -46,4 +46,5 @@
 	/// replaces UniqueExprs with a temporary variable and one call
 	void expandUniqueExpr( std::list< Declaration * > & translationUnit );
+	void expandUniqueExpr( ast::TranslationUnit & translationUnit );
 
 	/// returns VoidType if any of the expressions have Voidtype, otherwise TupleType of the Expression result types
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 1622af58aed4c83eebaa99e928f0b0358263b087)
+++ src/main.cc	(revision b7fd9daffd1af20c4c7cc80ac4660136917af20f)
@@ -381,4 +381,12 @@
 			PASS( "Fix Init", InitTweak::fix(transUnit, buildingLibrary()));
 
+			// fix ObjectDecl - replaces ConstructorInit nodes
+			if ( ctorinitp ) {
+				dump( move( transUnit ) );
+				return EXIT_SUCCESS;
+			} // if
+
+			// Currently not working due to unresolved issues with UniqueExpr
+			PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( transUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
 			translationUnit = convert( move( transUnit ) );
 		} else {
@@ -435,13 +443,13 @@
 
 			PASS( "Fix Init", InitTweak::fix( translationUnit, buildingLibrary() ) );
+
+			// fix ObjectDecl - replaces ConstructorInit nodes
+			if ( ctorinitp ) {
+				dump ( translationUnit );
+				return EXIT_SUCCESS;
+			} // if
+
+			PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
 		}
-
-		// fix ObjectDecl - replaces ConstructorInit nodes
-		if ( ctorinitp ) {
-			dump ( translationUnit );
-			return EXIT_SUCCESS;
-		} // if
-
-		PASS( "Expand Unique Expr", Tuples::expandUniqueExpr( translationUnit ) ); // xxx - is this the right place for this? want to expand ASAP so tha, sequent passes don't need to worry about double-visiting a unique expr - needs to go after InitTweak::fix so that copy constructed return declarations are reused
 
 		PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) );
