Index: src/SynTree/CompoundStmt.cc
===================================================================
--- src/SynTree/CompoundStmt.cc	(revision b3b2077b1feda429f174cfb4f374cb1e00580630)
+++ src/SynTree/CompoundStmt.cc	(revision 23bb1b935afeee154439a3a5065ccd588e7c946e)
@@ -20,24 +20,8 @@
 #include "Expression.h"
 #include "Declaration.h"
+#include "SynTree/VarExprReplacer.h"
 
 using std::string;
 using std::endl;
-
-class VarExprReplacer : public Visitor {
-public:
-  typedef std::map< DeclarationWithType *, DeclarationWithType * > DeclMap;
-private:
-  const DeclMap & declMap;
-public:
-  VarExprReplacer( const DeclMap & declMap ) : declMap( declMap ) {}
-
-  // replace variable with new node from decl map
-  virtual void visit( VariableExpr * varExpr ) {
-    if ( declMap.count( varExpr->get_var() ) ) {
-      varExpr->set_var( declMap.at( varExpr->get_var() ) );
-    }
-  }
-};
-
 
 CompoundStmt::CompoundStmt( std::list<Label> labels ) : Statement( labels ) {
@@ -47,34 +31,36 @@
 	cloneAll( other.kids, kids );
 
-  // when cloning a compound statement, we may end up cloning declarations which
-  // are referred to by VariableExprs throughout the block. Cloning a VariableExpr
-  // does a shallow copy, so the VariableExpr will end up pointing to the original
-  // declaration. If the original declaration is deleted, e.g. because the original
-  // CompoundStmt is deleted, then we have a dangling pointer. To avoid this case,
-  // find all DeclarationWithType nodes (since a VariableExpr must point to a
-  // DeclarationWithType) in the original CompoundStmt and map them to the cloned
-  // node in the new CompoundStmt ('this'), then replace the Declarations referred to
-  // by each VariableExpr according to the constructed map. Note that only the declarations
-  // in the current level are collected into the map, because child CompoundStmts will
-  // recursively execute this routine. There may be more efficient ways of doing
-  // this.
-  VarExprReplacer::DeclMap declMap;
-  std::list< Statement * >::const_iterator origit = other.kids.begin();
-  for ( Statement * s : kids ) {
-    assert( origit != other.kids.end() );
-    if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( s ) ) {
-      DeclStmt * origDeclStmt = dynamic_cast< DeclStmt * >( *origit );
-      assert( origDeclStmt );
-      if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * > ( declStmt->get_decl() ) ) {
-        DeclarationWithType * origdwt = dynamic_cast< DeclarationWithType * > ( origDeclStmt->get_decl() );
-        assert( origdwt );
-        declMap[ origdwt ] = dwt;
-      }
-    }
-  }
-  if ( ! declMap.empty() ) {
-    VarExprReplacer replacer( declMap );
-    accept( replacer );
-  }
+	// when cloning a compound statement, we may end up cloning declarations which
+	// are referred to by VariableExprs throughout the block. Cloning a VariableExpr
+	// does a shallow copy, so the VariableExpr will end up pointing to the original
+	// declaration. If the original declaration is deleted, e.g. because the original
+	// CompoundStmt is deleted, then we have a dangling pointer. To avoid this case,
+	// find all DeclarationWithType nodes (since a VariableExpr must point to a
+	// DeclarationWithType) in the original CompoundStmt and map them to the cloned
+	// node in the new CompoundStmt ('this'), then replace the Declarations referred to
+	// by each VariableExpr according to the constructed map. Note that only the declarations
+	// in the current level are collected into the map, because child CompoundStmts will
+	// recursively execute this routine. There may be more efficient ways of doing
+	// this.
+	VarExprReplacer::DeclMap declMap;
+	std::list< Statement * >::const_iterator origit = other.kids.begin();
+	for ( Statement * s : kids ) {
+		assert( origit != other.kids.end() );
+		Statement * origStmt = *origit++;
+		if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( s ) ) {
+			DeclStmt * origDeclStmt = dynamic_cast< DeclStmt * >( origStmt );
+			assert( origDeclStmt );
+			if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * > ( declStmt->get_decl() ) ) {
+				DeclarationWithType * origdwt = dynamic_cast< DeclarationWithType * > ( origDeclStmt->get_decl() );
+				assert( origdwt );
+				assert( dwt->get_name() == origdwt->get_name() );
+				declMap[ origdwt ] = dwt;
+			}
+		}
+	}
+	if ( ! declMap.empty() ) {
+		VarExprReplacer replacer( declMap );
+		accept( replacer );
+	}
 }
 
Index: src/SynTree/TupleExpr.cc
===================================================================
--- src/SynTree/TupleExpr.cc	(revision b3b2077b1feda429f174cfb4f374cb1e00580630)
+++ src/SynTree/TupleExpr.cc	(revision 23bb1b935afeee154439a3a5065ccd588e7c946e)
@@ -19,4 +19,5 @@
 #include "Declaration.h"
 #include "Tuples/Tuples.h"
+#include "VarExprReplacer.h"
 
 TupleExpr::TupleExpr( const std::list< Expression * > & exprs, Expression *_aname ) : Expression( _aname ), exprs( exprs ) {
@@ -91,7 +92,24 @@
 }
 
-TupleAssignExpr::TupleAssignExpr( const TupleAssignExpr &other ) : Expression( other ), tempDecls( other.tempDecls ) /* temporary */ {
+TupleAssignExpr::TupleAssignExpr( const TupleAssignExpr &other ) : Expression( other ) {
 	cloneAll( other.assigns, assigns );
-	// xxx - clone needs to go into assigns and replace tempDecls
+	cloneAll( other.tempDecls, tempDecls );
+
+	// clone needs to go into assigns and replace tempDecls
+	VarExprReplacer::DeclMap declMap;
+	std::list< ObjectDecl * >::const_iterator origit = other.tempDecls.begin();
+	for ( ObjectDecl * temp : tempDecls ) {
+		assert( origit != other.tempDecls.end() );
+		ObjectDecl * origTemp = *origit++;
+		assert( origTemp );
+		assert( temp->get_name() == origTemp->get_name() );
+		declMap[ origTemp ] = temp;
+	}
+	if ( ! declMap.empty() ) {
+		VarExprReplacer replacer( declMap );
+		for ( Expression * assn : assigns ) {
+			assn->accept( replacer );
+		}
+	}
 }
 
Index: src/SynTree/VarExprReplacer.cc
===================================================================
--- src/SynTree/VarExprReplacer.cc	(revision 23bb1b935afeee154439a3a5065ccd588e7c946e)
+++ src/SynTree/VarExprReplacer.cc	(revision 23bb1b935afeee154439a3a5065ccd588e7c946e)
@@ -0,0 +1,26 @@
+//
+// 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.
+//
+// VarExprReplacer.h --
+//
+// Author           : Rob Schluntz
+// Created On       : Wed Jan 13 16:29:30 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 13 11:27:52 2016
+// Update Count     : 5
+//
+
+#include "Expression.h"
+#include "VarExprReplacer.h"
+
+VarExprReplacer::VarExprReplacer( const DeclMap & declMap ) : declMap( declMap ) {}
+
+// replace variable with new node from decl map
+void VarExprReplacer::visit( VariableExpr * varExpr ) {
+  if ( declMap.count( varExpr->get_var() ) ) {
+    varExpr->set_var( declMap.at( varExpr->get_var() ) );
+  }
+}
Index: src/SynTree/VarExprReplacer.h
===================================================================
--- src/SynTree/VarExprReplacer.h	(revision 23bb1b935afeee154439a3a5065ccd588e7c946e)
+++ src/SynTree/VarExprReplacer.h	(revision 23bb1b935afeee154439a3a5065ccd588e7c946e)
@@ -0,0 +1,42 @@
+//
+// 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.
+//
+// VarExprReplacer.h --
+//
+// Author           : Rob Schluntz
+// Created On       : Wed Jan 13 16:29:30 2016
+// Last Modified By : Rob Schluntz
+// Last Modified On : Fri May 13 11:27:52 2016
+// Update Count     : 5
+//
+
+#ifndef VAR_EXPR_REPLACER_H
+#define VAR_EXPR_REPLACER_H
+
+#include <map>
+
+#include "SynTree/SynTree.h"
+
+/// Visitor that replaces the declarations that VariableExprs refer to, according to the supplied mapping
+class VarExprReplacer : public Visitor {
+public:
+	typedef std::map< DeclarationWithType *, DeclarationWithType * > DeclMap;
+private:
+	const DeclMap & declMap;
+public:
+	VarExprReplacer( const DeclMap & declMap );
+
+	// replace variable with new node from decl map
+	virtual void visit( VariableExpr * varExpr );
+};
+
+#endif // VAR_EXPR_REPLACER_H
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/SynTree/module.mk
===================================================================
--- src/SynTree/module.mk	(revision b3b2077b1feda429f174cfb4f374cb1e00580630)
+++ src/SynTree/module.mk	(revision 23bb1b935afeee154439a3a5065ccd588e7c946e)
@@ -49,4 +49,5 @@
        SynTree/AddStmtVisitor.cc \
        SynTree/TypeSubstitution.cc \
-       SynTree/Attribute.cc
+       SynTree/Attribute.cc \
+       SynTree/VarExprReplacer.cc
 
