Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/AST/Convert.cpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Thierry Delisle
 // Created On       : Thu May 09 15::37::05 2019
-// Last Modified By : Andrew Beach
-// Last Modified On : Wed Jul 14 16:15:00 2021
-// Update Count     : 37
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Wed Feb  2 13:19:22 2022
+// Update Count     : 41
 //
 
@@ -393,6 +393,6 @@
 		auto stmt = new IfStmt(
 			get<Expression>().accept1( node->cond ),
-			get<Statement>().accept1( node->thenPart ),
-			get<Statement>().accept1( node->elsePart ),
+			get<Statement>().accept1( node->then ),
+			get<Statement>().accept1( node->else_ ),
 			get<Statement>().acceptL( node->inits )
 		);
@@ -419,10 +419,11 @@
 	}
 
-	const ast::Stmt * visit( const ast::WhileStmt * node ) override final {
+	const ast::Stmt * visit( const ast::WhileDoStmt * node ) override final {
 		if ( inCache( node ) ) return nullptr;
 		auto inits = get<Statement>().acceptL( node->inits );
-		auto stmt = new WhileStmt(
+		auto stmt = new WhileDoStmt(
 			get<Expression>().accept1( node->cond ),
 			get<Statement>().accept1( node->body ),
+			get<Statement>().accept1( node->else_ ),
 			inits,
 			node->isDoWhile
@@ -437,5 +438,6 @@
 			get<Expression>().accept1( node->cond ),
 			get<Expression>().accept1( node->inc ),
-			get<Statement>().accept1( node->body )
+			get<Statement>().accept1( node->body ),
+			get<Statement>().accept1( node->else_ )
 		);
 		return stmtPostamble( stmt, node );
@@ -1872,6 +1874,6 @@
 			old->location,
 			GET_ACCEPT_1(condition, Expr),
-			GET_ACCEPT_1(thenPart, Stmt),
-			GET_ACCEPT_1(elsePart, Stmt),
+			GET_ACCEPT_1(then, Stmt),
+			GET_ACCEPT_1(else_, Stmt),
 			GET_ACCEPT_V(initialization, Stmt),
 			GET_LABELS_V(old->labels)
@@ -1902,10 +1904,11 @@
 	}
 
-	virtual void visit( const WhileStmt * old ) override final {
+	virtual void visit( const WhileDoStmt * old ) override final {
 		if ( inCache( old ) ) return;
-		this->node = new ast::WhileStmt(
+		this->node = new ast::WhileDoStmt(
 			old->location,
 			GET_ACCEPT_1(condition, Expr),
 			GET_ACCEPT_1(body, Stmt),
+			GET_ACCEPT_1(else_, Stmt),
 			GET_ACCEPT_V(initialization, Stmt),
 			old->isDoWhile,
@@ -1923,4 +1926,5 @@
 			GET_ACCEPT_1(increment, Expr),
 			GET_ACCEPT_1(body, Stmt),
+			GET_ACCEPT_1(else_, Stmt),
 			GET_LABELS_V(old->labels)
 		);
Index: src/AST/Copy.hpp
===================================================================
--- src/AST/Copy.hpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/AST/Copy.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Wed Jul 10 16:13:00 2019
 // Last Modified By : Andrew Beach
-// Last Modified On : Thr Nov 11  9:22:00 2021
-// Update Count     : 2
+// Last Modified On : Wed Dec 15 11:07:00 2021
+// Update Count     : 3
 //
 
@@ -52,4 +52,14 @@
 Node * deepCopy<Node>( const Node * localRoot );
 
+template<typename node_t, enum Node::ref_type ref_t>
+node_t * shallowCopy( const ptr_base<node_t, ref_t> & localRoot ) {
+	return shallowCopy( localRoot.get() );
+}
+
+template<typename node_t, enum Node::ref_type ref_t>
+node_t * deepCopy( const ptr_base<node_t, ref_t> & localRoot ) {
+	return deepCopy( localRoot.get() );
+}
+
 }
 
Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/AST/Fwd.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Wed May  8 16:05:00 2019
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Mar 12 18:37:39 2021
-// Update Count     : 4
+// Last Modified On : Tue Feb  1 09:08:33 2022
+// Update Count     : 5
 //
 
@@ -44,5 +44,5 @@
 class DirectiveStmt;
 class IfStmt;
-class WhileStmt;
+class WhileDoStmt;
 class ForStmt;
 class SwitchStmt;
Index: src/AST/Node.cpp
===================================================================
--- src/AST/Node.cpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/AST/Node.cpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Thu May 16 14:16:00 2019
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Mar 12 18:25:06 2021
-// Update Count     : 2
+// Last Modified On : Tue Feb  1 09:09:39 2022
+// Update Count     : 3
 //
 
@@ -146,6 +146,6 @@
 template class ast::ptr_base< ast::IfStmt, ast::Node::ref_type::weak >;
 template class ast::ptr_base< ast::IfStmt, ast::Node::ref_type::strong >;
-template class ast::ptr_base< ast::WhileStmt, ast::Node::ref_type::weak >;
-template class ast::ptr_base< ast::WhileStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::WhileDoStmt, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::WhileDoStmt, ast::Node::ref_type::strong >;
 template class ast::ptr_base< ast::ForStmt, ast::Node::ref_type::weak >;
 template class ast::ptr_base< ast::ForStmt, ast::Node::ref_type::strong >;
Index: src/AST/Node.hpp
===================================================================
--- src/AST/Node.hpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/AST/Node.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -188,4 +188,9 @@
 	}
 
+	ptr_base & operator=( const node_t * node ) {
+		assign( node );
+		return *this;
+	}
+
 	template<typename o_node_t>
 	ptr_base & operator=( const o_node_t * node ) {
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/AST/Pass.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -146,5 +146,5 @@
 	const ast::Stmt *             visit( const ast::DirectiveStmt        * ) override final;
 	const ast::Stmt *             visit( const ast::IfStmt               * ) override final;
-	const ast::Stmt *             visit( const ast::WhileStmt            * ) override final;
+	const ast::Stmt *             visit( const ast::WhileDoStmt          * ) override final;
 	const ast::Stmt *             visit( const ast::ForStmt              * ) override final;
 	const ast::Stmt *             visit( const ast::SwitchStmt           * ) override final;
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/AST/Pass.impl.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -33,11 +33,4 @@
 	/* call the implementation of the previsit of this pass */ \
 	__pass::previsit( core, node, 0 );
-
-#define VISIT( code... ) \
-	/* if this node should visit its children */ \
-	if ( __visit_children() ) { \
-		/* visit the children */ \
-		code \
-	}
 
 #define VISIT_END( type, node ) \
@@ -452,5 +445,5 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		{
 			guard_symtab guard { *this };
@@ -460,5 +453,5 @@
 		maybe_accept( node, &ObjectDecl::bitfieldWidth );
 		maybe_accept( node, &ObjectDecl::attributes    );
-	)
+	}
 
 	__pass::symtab::addId( core, 0, node );
@@ -475,5 +468,7 @@
 	__pass::symtab::addId( core, 0, node );
 
-	VISIT(maybe_accept( node, &FunctionDecl::withExprs );)
+	if ( __visit_children() ) {
+		maybe_accept( node, &FunctionDecl::withExprs );
+	}
 	{
 		// with clause introduces a level of scope (for the with expression members).
@@ -493,5 +488,5 @@
 			} };
 			__pass::symtab::addId( core, 0, func );
-			VISIT(
+			if ( __visit_children() ) {
 				// parameter declarations
 				maybe_accept( node, &FunctionDecl::params );
@@ -509,5 +504,5 @@
 				maybe_accept( node, &FunctionDecl::stmts );
 				maybe_accept( node, &FunctionDecl::attributes );
-			)
+			}
 		}
 	}
@@ -526,10 +521,10 @@
 	__pass::symtab::addStructFwd( core, 0, node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		guard_symtab guard { * this };
 		maybe_accept( node, &StructDecl::params     );
 		maybe_accept( node, &StructDecl::members    );
 		maybe_accept( node, &StructDecl::attributes );
-	})
+	}
 
 	// this addition replaces the forward declaration
@@ -548,10 +543,10 @@
 	__pass::symtab::addUnionFwd( core, 0, node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		guard_symtab guard { * this };
 		maybe_accept( node, &UnionDecl::params     );
 		maybe_accept( node, &UnionDecl::members    );
 		maybe_accept( node, &UnionDecl::attributes );
-	})
+	}
 
 	__pass::symtab::addUnion( core, 0, node );
@@ -568,10 +563,10 @@
 	__pass::symtab::addEnum( core, 0, node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		// unlike structs, traits, and unions, enums inject their members into the global scope
 		maybe_accept( node, &EnumDecl::params     );
 		maybe_accept( node, &EnumDecl::members    );
 		maybe_accept( node, &EnumDecl::attributes );
-	)
+	}
 
 	VISIT_END( Decl, node );
@@ -584,10 +579,10 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		guard_symtab guard { *this };
 		maybe_accept( node, &TraitDecl::params     );
 		maybe_accept( node, &TraitDecl::members    );
 		maybe_accept( node, &TraitDecl::attributes );
-	})
+	}
 
 	__pass::symtab::addTrait( core, 0, node );
@@ -602,8 +597,8 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		guard_symtab guard { *this };
 		maybe_accept( node, &TypeDecl::base   );
-	})
+	}
 
 	// see A NOTE ON THE ORDER OF TRAVERSAL, above
@@ -612,5 +607,5 @@
 	__pass::symtab::addType( core, 0, node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &TypeDecl::assertions );
 
@@ -619,5 +614,5 @@
 			maybe_accept( node, &TypeDecl::init );
 		}
-	)
+	}
 
 	VISIT_END( Decl, node );
@@ -630,12 +625,14 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		guard_symtab guard { *this };
 		maybe_accept( node, &TypedefDecl::base   );
-	})
+	}
 
 	__pass::symtab::addType( core, 0, node );
 
-	VISIT( maybe_accept( node, &TypedefDecl::assertions ); )
+	if ( __visit_children() ) {
+		maybe_accept( node, &TypedefDecl::assertions );
+	}
 
 	VISIT_END( Decl, node );
@@ -648,7 +645,7 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &AsmDecl::stmt );
-	)
+	}
 
 	VISIT_END( AsmDecl, node );
@@ -661,7 +658,7 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &DirectiveDecl::stmt );
-	)
+	}
 
 	VISIT_END( DirectiveDecl, node );
@@ -674,8 +671,8 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &StaticAssertDecl::cond );
 		maybe_accept( node, &StaticAssertDecl::msg  );
-	)
+	}
 
 	VISIT_END( StaticAssertDecl, node );
@@ -687,5 +684,6 @@
 const ast::CompoundStmt * ast::Pass< core_t >::visit( const ast::CompoundStmt * node ) {
 	VISIT_START( node );
-	VISIT(
+
+	if ( __visit_children() ) {
 		// Do not enter (or leave) a new scope if atFunctionTop. Remember to save the result.
 		auto guard1 = makeFuncGuard( [this, enterScope = !this->atFunctionTop]() {
@@ -704,5 +702,6 @@
 		guard_scope guard3 { *this };
 		maybe_accept( node, &CompoundStmt::kids );
-	)
+	}
+
 	VISIT_END( CompoundStmt, node );
 }
@@ -714,7 +713,7 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &ExprStmt::expr );
-	)
+	}
 
 	VISIT_END( Stmt, node );
@@ -727,10 +726,10 @@
 	VISIT_START( node )
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &AsmStmt::instruction );
 		maybe_accept( node, &AsmStmt::output      );
 		maybe_accept( node, &AsmStmt::input       );
 		maybe_accept( node, &AsmStmt::clobber     );
-	)
+	}
 
 	VISIT_END( Stmt, node );
@@ -752,12 +751,12 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		// if statements introduce a level of scope (for the initialization)
 		guard_symtab guard { *this };
 		maybe_accept( node, &IfStmt::inits    );
 		maybe_accept( node, &IfStmt::cond     );
-		maybe_accept_as_compound( node, &IfStmt::thenPart );
-		maybe_accept_as_compound( node, &IfStmt::elsePart );
-	})
+		maybe_accept_as_compound( node, &IfStmt::then );
+		maybe_accept_as_compound( node, &IfStmt::else_ );
+	}
 
 	VISIT_END( Stmt, node );
@@ -765,16 +764,16 @@
 
 //--------------------------------------------------------------------------
-// WhileStmt
-template< typename core_t >
-const ast::Stmt * ast::Pass< core_t >::visit( const ast::WhileStmt * node ) {
-	VISIT_START( node );
-
-	VISIT({
+// WhileDoStmt
+template< typename core_t >
+const ast::Stmt * ast::Pass< core_t >::visit( const ast::WhileDoStmt * node ) {
+	VISIT_START( node );
+
+	if ( __visit_children() ) {
 		// while statements introduce a level of scope (for the initialization)
 		guard_symtab guard { *this };
-		maybe_accept( node, &WhileStmt::inits );
-		maybe_accept( node, &WhileStmt::cond  );
-		maybe_accept_as_compound( node, &WhileStmt::body  );
-	})
+		maybe_accept( node, &WhileDoStmt::inits );
+		maybe_accept( node, &WhileDoStmt::cond  );
+		maybe_accept_as_compound( node, &WhileDoStmt::body  );
+	}
 
 	VISIT_END( Stmt, node );
@@ -787,5 +786,5 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		// for statements introduce a level of scope (for the initialization)
 		guard_symtab guard { *this };
@@ -795,5 +794,5 @@
 		maybe_accept( node, &ForStmt::inc   );
 		maybe_accept_as_compound( node, &ForStmt::body  );
-	})
+	}
 
 	VISIT_END( Stmt, node );
@@ -806,8 +805,8 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &SwitchStmt::cond  );
 		maybe_accept( node, &SwitchStmt::stmts );
-	)
+	}
 
 	VISIT_END( Stmt, node );
@@ -820,8 +819,8 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &CaseStmt::cond  );
 		maybe_accept( node, &CaseStmt::stmts );
-	)
+	}
 
 	VISIT_END( Stmt, node );
@@ -842,7 +841,7 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &ReturnStmt::expr );
-	)
+	}
 
 	VISIT_END( Stmt, node );
@@ -855,8 +854,8 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &ThrowStmt::expr   );
 		maybe_accept( node, &ThrowStmt::target );
-	)
+	}
 
 	VISIT_END( Stmt, node );
@@ -869,9 +868,9 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &TryStmt::body     );
 		maybe_accept( node, &TryStmt::handlers );
 		maybe_accept( node, &TryStmt::finally  );
-	)
+	}
 
 	VISIT_END( Stmt, node );
@@ -884,5 +883,5 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		// catch statements introduce a level of scope (for the caught exception)
 		guard_symtab guard { *this };
@@ -890,5 +889,5 @@
 		maybe_accept( node, &CatchStmt::cond );
 		maybe_accept_as_compound( node, &CatchStmt::body );
-	})
+	}
 
 	VISIT_END( Stmt, node );
@@ -901,7 +900,7 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &FinallyStmt::body );
-	)
+	}
 
 	VISIT_END( Stmt, node );
@@ -914,7 +913,7 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &SuspendStmt::then   );
-	)
+	}
 
 	VISIT_END( Stmt, node );
@@ -934,5 +933,5 @@
 		// }
 
-	VISIT({
+	if ( __visit_children() ) {
 		std::vector<WaitForStmt::Clause> new_clauses;
 		new_clauses.reserve( node->clauses.size() );
@@ -965,5 +964,5 @@
 			node = n;
 		}
-	})
+	}
 
 	#define maybe_accept(field) \
@@ -977,5 +976,5 @@
 		}
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( timeout.time );
 		maybe_accept( timeout.stmt );
@@ -983,5 +982,5 @@
 		maybe_accept( orElse.stmt  );
 		maybe_accept( orElse.cond  );
-	)
+	}
 
 	#undef maybe_accept
@@ -996,5 +995,5 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &WithStmt::exprs );
 		{
@@ -1004,5 +1003,6 @@
 			maybe_accept( node, &WithStmt::stmt );
 		}
-	)
+	}
+
 	VISIT_END( Stmt, node );
 }
@@ -1022,7 +1022,7 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &DeclStmt::decl );
-	)
+	}
 
 	VISIT_END( Stmt, node );
@@ -1037,7 +1037,7 @@
 	// For now this isn't visited, it is unclear if this causes problem
 	// if all tests are known to pass, remove this code
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &ImplicitCtorDtorStmt::callStmt );
-	)
+	}
 
 	VISIT_END( Stmt, node );
@@ -1050,10 +1050,10 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		// mutex statements introduce a level of scope (for the initialization)
 		guard_symtab guard { *this };
 		maybe_accept( node, &MutexStmt::stmt );
 		maybe_accept( node, &MutexStmt::mutexObjs );
-	})
+	}
 
 	VISIT_END( Stmt, node );
@@ -1066,5 +1066,5 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		{
 			guard_symtab guard { *this };
@@ -1073,5 +1073,5 @@
 		maybe_accept( node, &ApplicationExpr::func );
 		maybe_accept( node, &ApplicationExpr::args );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1084,5 +1084,5 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		{
 			guard_symtab guard { *this };
@@ -1091,5 +1091,5 @@
 
 		maybe_accept( node, &UntypedExpr::args );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1102,8 +1102,8 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		guard_symtab guard { *this };
 		maybe_accept( node, &NameExpr::result );
-	})
+	}
 
 	VISIT_END( Expr, node );
@@ -1116,10 +1116,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &CastExpr::result );
 		}
 		maybe_accept( node, &CastExpr::arg );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1132,10 +1133,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &KeywordCastExpr::result );
 		}
 		maybe_accept( node, &KeywordCastExpr::arg );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1148,10 +1150,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &VirtualCastExpr::result );
 		}
 		maybe_accept( node, &VirtualCastExpr::arg );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1164,10 +1167,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &AddressExpr::result );
 		}
 		maybe_accept( node, &AddressExpr::arg );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1180,8 +1184,8 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		guard_symtab guard { *this };
 		maybe_accept( node, &LabelAddressExpr::result );
-	})
+	}
 
 	VISIT_END( Expr, node );
@@ -1194,5 +1198,6 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &UntypedMemberExpr::result );
@@ -1200,5 +1205,5 @@
 		maybe_accept( node, &UntypedMemberExpr::aggregate );
 		maybe_accept( node, &UntypedMemberExpr::member    );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1211,10 +1216,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &MemberExpr::result );
 		}
 		maybe_accept( node, &MemberExpr::aggregate );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1227,8 +1233,8 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		guard_symtab guard { *this };
 		maybe_accept( node, &VariableExpr::result );
-	})
+	}
 
 	VISIT_END( Expr, node );
@@ -1241,8 +1247,8 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		guard_symtab guard { *this };
 		maybe_accept( node, &ConstantExpr::result );
-	})
+	}
 
 	VISIT_END( Expr, node );
@@ -1255,5 +1261,6 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &SizeofExpr::result );
@@ -1264,5 +1271,5 @@
 			maybe_accept( node, &SizeofExpr::expr );
 		}
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1275,5 +1282,6 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &AlignofExpr::result );
@@ -1284,5 +1292,5 @@
 			maybe_accept( node, &AlignofExpr::expr );
 		}
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1295,10 +1303,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &UntypedOffsetofExpr::result );
 		}
 		maybe_accept( node, &UntypedOffsetofExpr::type   );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1311,10 +1320,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &OffsetofExpr::result );
 		}
 		maybe_accept( node, &OffsetofExpr::type   );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1327,10 +1337,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &OffsetPackExpr::result );
 		}
 		maybe_accept( node, &OffsetPackExpr::type   );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1343,5 +1354,6 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &LogicalExpr::result );
@@ -1349,5 +1361,5 @@
 		maybe_accept( node, &LogicalExpr::arg1 );
 		maybe_accept( node, &LogicalExpr::arg2 );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1360,5 +1372,6 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &ConditionalExpr::result );
@@ -1367,5 +1380,5 @@
 		maybe_accept( node, &ConditionalExpr::arg2 );
 		maybe_accept( node, &ConditionalExpr::arg3 );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1378,5 +1391,6 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &CommaExpr::result );
@@ -1384,5 +1398,5 @@
 		maybe_accept( node, &CommaExpr::arg1 );
 		maybe_accept( node, &CommaExpr::arg2 );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1395,10 +1409,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &TypeExpr::result );
 		}
 		maybe_accept( node, &TypeExpr::type );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1411,5 +1426,6 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &AsmExpr::result );
@@ -1417,5 +1433,5 @@
 		maybe_accept( node, &AsmExpr::constraint );
 		maybe_accept( node, &AsmExpr::operand    );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1428,10 +1444,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &ImplicitCopyCtorExpr::result );
 		}
 		maybe_accept( node, &ImplicitCopyCtorExpr::callExpr    );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1444,10 +1461,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &ConstructorExpr::result );
 		}
 		maybe_accept( node, &ConstructorExpr::callExpr );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1460,10 +1478,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &CompoundLiteralExpr::result );
 		}
 		maybe_accept( node, &CompoundLiteralExpr::init );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1476,5 +1495,6 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &RangeExpr::result );
@@ -1482,5 +1502,5 @@
 		maybe_accept( node, &RangeExpr::low    );
 		maybe_accept( node, &RangeExpr::high   );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1493,10 +1513,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &UntypedTupleExpr::result );
 		}
 		maybe_accept( node, &UntypedTupleExpr::exprs  );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1509,10 +1530,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &TupleExpr::result );
 		}
 		maybe_accept( node, &TupleExpr::exprs  );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1525,10 +1547,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &TupleIndexExpr::result );
 		}
 		maybe_accept( node, &TupleIndexExpr::tuple  );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1541,10 +1564,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &TupleAssignExpr::result );
 		}
 		maybe_accept( node, &TupleAssignExpr::stmtExpr );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1557,5 +1581,6 @@
 	VISIT_START( node );
 
-	VISIT(// don't want statements from outer CompoundStmts to be added to this StmtExpr
+	if ( __visit_children() ) {
+		// don't want statements from outer CompoundStmts to be added to this StmtExpr
 		// get the stmts that will need to be spliced in
 		auto stmts_before = __pass::stmtsToAddBefore( core, 0);
@@ -1574,5 +1599,5 @@
 		maybe_accept( node, &StmtExpr::returnDecls );
 		maybe_accept( node, &StmtExpr::dtors       );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1585,10 +1610,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &UniqueExpr::result );
 		}
 		maybe_accept( node, &UniqueExpr::expr   );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1601,5 +1627,6 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &UntypedInitExpr::result );
@@ -1607,5 +1634,5 @@
 		maybe_accept( node, &UntypedInitExpr::expr   );
 		// not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1618,5 +1645,6 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &InitExpr::result );
@@ -1624,5 +1652,5 @@
 		maybe_accept( node, &InitExpr::expr   );
 		maybe_accept( node, &InitExpr::designation );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1635,5 +1663,6 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &DeletedExpr::result );
@@ -1641,5 +1670,5 @@
 		maybe_accept( node, &DeletedExpr::expr );
 		// don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1652,10 +1681,11 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &DefaultArgExpr::result );
 		}
 		maybe_accept( node, &DefaultArgExpr::expr );
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1668,5 +1698,6 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
+		{
 			guard_symtab guard { *this };
 			maybe_accept( node, &GenericExpr::result );
@@ -1697,5 +1728,5 @@
 			node = n;
 		}
-	)
+	}
 
 	VISIT_END( Expr, node );
@@ -1726,8 +1757,8 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		// xxx - should PointerType visit/mutate dimension?
 		maybe_accept( node, &PointerType::base );
-	)
+	}
 
 	VISIT_END( Type, node );
@@ -1740,8 +1771,8 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &ArrayType::dimension );
 		maybe_accept( node, &ArrayType::base );
-	)
+	}
 
 	VISIT_END( Type, node );
@@ -1754,7 +1785,7 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &ReferenceType::base );
-	)
+	}
 
 	VISIT_END( Type, node );
@@ -1767,8 +1798,8 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &QualifiedType::parent );
 		maybe_accept( node, &QualifiedType::child );
-	)
+	}
 
 	VISIT_END( Type, node );
@@ -1781,5 +1812,5 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		// guard_forall_subs forall_guard { *this, node };
 		// mutate_forall( node );
@@ -1787,5 +1818,5 @@
 		maybe_accept( node, &FunctionType::returns );
 		maybe_accept( node, &FunctionType::params  );
-	})
+	}
 
 	VISIT_END( Type, node );
@@ -1800,8 +1831,8 @@
 	__pass::symtab::addStruct( core, 0, node->name );
 
-	VISIT({
+	if ( __visit_children() ) {
 		guard_symtab guard { *this };
 		maybe_accept( node, &StructInstType::params );
-	})
+	}
 
 	VISIT_END( Type, node );
@@ -1816,8 +1847,8 @@
 	__pass::symtab::addUnion( core, 0, node->name );
 
-	VISIT({
+	if ( __visit_children() ) {
 		guard_symtab guard { *this };
 		maybe_accept( node, &UnionInstType::params );
-	})
+	}
 
 	VISIT_END( Type, node );
@@ -1830,7 +1861,7 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		maybe_accept( node, &EnumInstType::params );
-	})
+	}
 
 	VISIT_END( Type, node );
@@ -1843,7 +1874,7 @@
 	VISIT_START( node );
 
-	VISIT({
+	if ( __visit_children() ) {
 		maybe_accept( node, &TraitInstType::params );
-	})
+	}
 
 	VISIT_END( Type, node );
@@ -1856,5 +1887,5 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		{
 			maybe_accept( node, &TypeInstType::params );
@@ -1862,5 +1893,5 @@
 		// ensure that base re-bound if doing substitution
 		__pass::forall::replace( core, 0, node );
-	)
+	}
 
 	VISIT_END( Type, node );
@@ -1873,8 +1904,8 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &TupleType::types );
 		maybe_accept( node, &TupleType::members );
-	)
+	}
 
 	VISIT_END( Type, node );
@@ -1887,7 +1918,7 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &TypeofType::expr );
-	)
+	}
 
 	VISIT_END( Type, node );
@@ -1900,7 +1931,7 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &VTableType::base );
-	)
+	}
 
 	VISIT_END( Type, node );
@@ -1950,5 +1981,7 @@
 	VISIT_START( node );
 
-	VISIT( maybe_accept( node, &Designation::designators ); )
+	if ( __visit_children() ) {
+		maybe_accept( node, &Designation::designators );
+	}
 
 	VISIT_END( Designation, node );
@@ -1961,7 +1994,7 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &SingleInit::value );
-	)
+	}
 
 	VISIT_END( Init, node );
@@ -1974,8 +2007,8 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &ListInit::designations );
 		maybe_accept( node, &ListInit::initializers );
-	)
+	}
 
 	VISIT_END( Init, node );
@@ -1988,9 +2021,9 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &ConstructorInit::ctor );
 		maybe_accept( node, &ConstructorInit::dtor );
 		maybe_accept( node, &ConstructorInit::init );
-	)
+	}
 
 	VISIT_END( Init, node );
@@ -2003,7 +2036,7 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		maybe_accept( node, &Attribute::params );
-	)
+	}
 
 	VISIT_END( Attribute, node );
@@ -2016,5 +2049,5 @@
 	VISIT_START( node );
 
-	VISIT(
+	if ( __visit_children() ) {
 		{
 			bool mutated = false;
@@ -2032,5 +2065,5 @@
 			}
 		}
-	)
+	}
 
 	VISIT_END( TypeSubstitution, node );
@@ -2038,4 +2071,3 @@
 
 #undef VISIT_START
-#undef VISIT
 #undef VISIT_END
Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/AST/Print.cpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -511,12 +511,12 @@
 		++indent;
 		os << indent;
-		safe_print( node->thenPart );
-		--indent;
-
-		if ( node->elsePart != 0 ) {
+		safe_print( node->then );
+		--indent;
+
+		if ( node->else_ != 0 ) {
 			os << indent << "... else:" << endl;
 			++indent;
 			os << indent;
-			node->elsePart->accept( *this );
+			node->else_->accept( *this );
 			--indent;
 		} // if
@@ -524,5 +524,5 @@
 	}
 
-	virtual const ast::Stmt * visit( const ast::WhileStmt * node ) override final {
+	virtual const ast::Stmt * visit( const ast::WhileDoStmt * node ) override final {
 		if ( node->isDoWhile ) { os << "Do-"; }
 		os << "While on condition:" << endl;
Index: src/AST/Stmt.cpp
===================================================================
--- src/AST/Stmt.cpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/AST/Stmt.cpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Aaron B. Moss
 // Created On       : Wed May  8 13:00:00 2019
-// Last Modified By : Andrew Beach
-// Last Modified On : Wed May 15 15:53:00 2019
-// Update Count     : 2
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Wed Feb  2 19:01:20 2022
+// Update Count     : 3
 //
 
@@ -56,6 +56,6 @@
 
 // --- BranchStmt
-BranchStmt::BranchStmt( const CodeLocation& loc, Kind kind, Label target, std::vector<Label>&& labels )
-: Stmt(loc, std::move(labels)), originalTarget(target), target(target), kind(kind) {
+BranchStmt::BranchStmt( const CodeLocation& loc, Kind kind, Label target, const std::vector<Label>&& labels )
+		: Stmt(loc, std::move(labels)), originalTarget(target), target(target), kind(kind) {
 	// Make sure a syntax error hasn't slipped through.
 	assert( Goto != kind || !target.empty() );
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/AST/Stmt.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Aaron B. Moss
 // Created On       : Wed May  8 13:00:00 2019
-// Last Modified By : Andrew Beach
-// Last Modified On : Fri May 17 12:45:00 2019
-// Update Count     : 5
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Wed Feb  2 20:06:41 2022
+// Update Count     : 34
 //
 
@@ -17,9 +17,9 @@
 
 #include <list>
-#include <utility>                // for move
+#include <utility>										// for move
 #include <vector>
 
 #include "Label.hpp"
-#include "Node.hpp"               // for node, ptr
+#include "Node.hpp"										// for node, ptr
 #include "ParseNode.hpp"
 #include "Visitor.hpp"
@@ -27,39 +27,37 @@
 
 // Must be included in *all* AST classes; should be #undef'd at the end of the file
-#define MUTATE_FRIEND \
+#define MUTATE_FRIEND													\
     template<typename node_t> friend node_t * mutate(const node_t * node); \
 	template<typename node_t> friend node_t * shallowCopy(const node_t * node);
 
 namespace ast {
-
 class Expr;
 
-/// Base statement node
+// Base statement node
 class Stmt : public ParseNode {
-public:
+  public:
 	std::vector<Label> labels;
 
-	Stmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
-	: ParseNode(loc), labels(std::move(labels)) {}
-
-	Stmt(const Stmt& o) : ParseNode(o), labels(o.labels) {}
+	Stmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
+		: ParseNode(loc), labels(std::move(labels)) {}
+
+	Stmt(const Stmt & o) : ParseNode(o), labels(o.labels) {}
 
 	const Stmt * accept( Visitor & v ) const override = 0;
-private:
+  private:
 	Stmt * clone() const override = 0;
 	MUTATE_FRIEND
 };
 
-/// Compound statement `{ ... }`
+// Compound statement: { ... }
 class CompoundStmt final : public Stmt {
-public:
+  public:
 	std::list<ptr<Stmt>> kids;
 
-	CompoundStmt(const CodeLocation & loc, std::list<ptr<Stmt>> && ks = {},
-		std::vector<Label>&& labels = {} )
-	: Stmt(loc, std::move(labels)), kids(std::move(ks)) {}
-
-	CompoundStmt( const CompoundStmt& o );
-	CompoundStmt( CompoundStmt&& o ) = default;
+	CompoundStmt(const CodeLocation & loc, const std::list<ptr<Stmt>> && ks = {}, const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), kids(std::move(ks)) {}
+
+	CompoundStmt( const CompoundStmt & o );
+	CompoundStmt( CompoundStmt && o ) = default;
 
 	void push_back( const Stmt * s ) { kids.emplace_back( s ); }
@@ -67,38 +65,38 @@
 
 	const CompoundStmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+  private:
 	CompoundStmt * clone() const override { return new CompoundStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Empty statment `;`
+// Empty statment: ;
 class NullStmt final : public Stmt {
-public:
-	NullStmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)) {}
+  public:
+	NullStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)) {}
 
 	const NullStmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+  private:
 	NullStmt * clone() const override { return new NullStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Expression wrapped by statement
+// Expression wrapped by statement
 class ExprStmt final : public Stmt {
-public:
+  public:
 	ptr<Expr> expr;
 
-	ExprStmt( const CodeLocation& loc, const Expr* e, std::vector<Label>&& labels = {} )
-	: Stmt(loc, std::move(labels)), expr(e) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+	ExprStmt( const CodeLocation & loc, const Expr* e, const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), expr(e) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	ExprStmt * clone() const override { return new ExprStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Assembly statement `asm ... ( "..." : ... )`
+// Assembly statement: asm ... ( "..." : ... )
 class AsmStmt final : public Stmt {
-public:
+  public:
 	bool isVolatile;
 	ptr<Expr> instruction;
@@ -108,128 +106,136 @@
 
 	AsmStmt( const CodeLocation & loc, bool isVolatile, const Expr * instruction,
-		std::vector<ptr<Expr>> && output, std::vector<ptr<Expr>> && input,
-		std::vector<ptr<ConstantExpr>> && clobber, std::vector<Label> && gotoLabels,
-		std::vector<Label> && labels = {})
-	: Stmt(loc, std::move(labels)), isVolatile(isVolatile), instruction(instruction),
-	  output(std::move(output)), input(std::move(input)), clobber(std::move(clobber)),
-	  gotoLabels(std::move(gotoLabels)) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+			 const std::vector<ptr<Expr>> && output, const std::vector<ptr<Expr>> && input,
+			 const std::vector<ptr<ConstantExpr>> && clobber, const std::vector<Label> && gotoLabels,
+			 const std::vector<Label> && labels = {})
+		: Stmt(loc, std::move(labels)), isVolatile(isVolatile), instruction(instruction),
+		  output(std::move(output)), input(std::move(input)), clobber(std::move(clobber)),
+		  gotoLabels(std::move(gotoLabels)) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	AsmStmt * clone() const override { return new AsmStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// C-preprocessor directive `#...`
+// C-preprocessor directive: #...
 class DirectiveStmt final : public Stmt {
-public:
+  public:
 	std::string directive;
 
 	DirectiveStmt( const CodeLocation & loc, const std::string & directive,
-		std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), directive(directive) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+				   std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), directive(directive) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	DirectiveStmt * clone() const override { return new DirectiveStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// If conditional statement `if (...) ... else ...`
+// If statement: if (...) ... else ...
 class IfStmt final : public Stmt {
-public:
-	ptr<Expr> cond;
-	ptr<Stmt> thenPart;
-	ptr<Stmt> elsePart;
+  public:
+	ptr<Expr> cond;
+	ptr<Stmt> then;
+	ptr<Stmt> else_;
 	std::vector<ptr<Stmt>> inits;
 
-	IfStmt( const CodeLocation & loc, const Expr * cond, const Stmt * thenPart,
-		const Stmt * elsePart = nullptr, std::vector<ptr<Stmt>> && inits = {},
-		std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), cond(cond), thenPart(thenPart), elsePart(elsePart),
-	  inits(std::move(inits)) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+	IfStmt( const CodeLocation & loc, const Expr * cond, const Stmt * then,
+			const Stmt * else_ = nullptr, const std::vector<ptr<Stmt>> && inits = {},
+			const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), cond(cond), then(then), else_(else_),
+		  inits(std::move(inits)) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	IfStmt * clone() const override { return new IfStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Switch or choose conditional statement `switch (...) { ... }`
+// Switch or choose statement: switch (...) { ... }
 class SwitchStmt final : public Stmt {
-public:
+  public:
 	ptr<Expr> cond;
 	std::vector<ptr<Stmt>> stmts;
 
-	SwitchStmt( const CodeLocation & loc, const Expr * cond, std::vector<ptr<Stmt>> && stmts,
-		std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+	SwitchStmt( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts,
+				const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	SwitchStmt * clone() const override { return new SwitchStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Case label `case ...:` `default:`
+// Case label: case ...: or default:
 class CaseStmt final : public Stmt {
-public:
-	/// Null for the default label.
+  public:
+	// Null for the default label.
 	ptr<Expr> cond;
 	std::vector<ptr<Stmt>> stmts;
 
-	CaseStmt( const CodeLocation & loc, const Expr * cond, std::vector<ptr<Stmt>> && stmts,
-		std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
+	CaseStmt( const CodeLocation & loc, const Expr * cond, const std::vector<ptr<Stmt>> && stmts,
+			  const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), cond(cond), stmts(std::move(stmts)) {}
 
 	bool isDefault() const { return !cond; }
 
 	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+  private:
 	CaseStmt * clone() const override { return new CaseStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// While loop `while (...) ...` `do ... while (...);
-class WhileStmt final : public Stmt {
-public:
+// While loop: while (...) ... else ... or do ... while (...) else ...;
+class WhileDoStmt final : public Stmt {
+  public:
 	ptr<Expr> cond;
 	ptr<Stmt> body;
+	ptr<Stmt> else_;
 	std::vector<ptr<Stmt>> inits;
 	bool isDoWhile;
 
-	WhileStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body,
-		std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), cond(cond), body(body), inits(std::move(inits)),
-	  isDoWhile(isDoWhile) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
-	WhileStmt * clone() const override { return new WhileStmt{ *this }; }
-	MUTATE_FRIEND
-};
-
-/// For loop `for (... ; ... ; ...) ...`
+	WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body,
+				 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), cond(cond), body(body), else_(nullptr), inits(std::move(inits)), isDoWhile(isDoWhile) {}
+
+	WhileDoStmt( const CodeLocation & loc, const Expr * cond, const Stmt * body, const Stmt * else_,
+				 const std::vector<ptr<Stmt>> && inits, bool isDoWhile = false, const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), cond(cond), body(body), else_(else_), inits(std::move(inits)), isDoWhile(isDoWhile) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
+	WhileDoStmt * clone() const override { return new WhileDoStmt{ *this }; }
+	MUTATE_FRIEND
+};
+
+// For loop: for (... ; ... ; ...) ... else ...
 class ForStmt final : public Stmt {
-public:
+  public:
 	std::vector<ptr<Stmt>> inits;
 	ptr<Expr> cond;
 	ptr<Expr> inc;
 	ptr<Stmt> body;
-
-	ForStmt( const CodeLocation & loc, std::vector<ptr<Stmt>> && inits, const Expr * cond,
-		const Expr * inc, const Stmt * body, std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), inits(std::move(inits)), cond(cond), inc(inc),
-	  body(body) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+	ptr<Stmt> else_;
+
+	ForStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * cond,
+			 const Expr * inc, const Stmt * body, const std::vector<Label> && label = {} )
+		: Stmt(loc, std::move(label)), inits(std::move(inits)), cond(cond), inc(inc), body(body), else_(nullptr) {}
+
+	ForStmt( const CodeLocation & loc, const std::vector<ptr<Stmt>> && inits, const Expr * cond,
+			 const Expr * inc, const Stmt * body, const Stmt * else_, const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), inits(std::move(inits)), cond(cond), inc(inc), body(body), else_(else_) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	ForStmt * clone() const override { return new ForStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Branch control flow statement `goto ...` `break` `continue` `fallthru`
+// Branch control flow statement: goto ... or break or continue or fallthru
 class BranchStmt final : public Stmt {
-public:
+  public:
 	enum Kind { Goto, Break, Continue, FallThrough, FallThroughDefault };
 	static constexpr size_t kindEnd = 1 + (size_t)FallThroughDefault;
@@ -240,15 +246,12 @@
 	Kind kind;
 
-	BranchStmt( const CodeLocation & loc, Kind kind, Label target,
-		std::vector<Label> && labels = {} );
-	BranchStmt( const CodeLocation & loc, const Expr * computedTarget,
-		std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), originalTarget(loc), target(loc),
-	  computedTarget(computedTarget), kind(Goto) {}
+	BranchStmt( const CodeLocation & loc, Kind kind, Label target, const std::vector<Label> && labels = {} );
+	BranchStmt( const CodeLocation & loc, const Expr * computedTarget, const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), originalTarget(loc), target(loc), computedTarget(computedTarget), kind(Goto) {}
 
 	const char * kindName() const { return kindNames[kind]; }
 
 	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+  private:
 	BranchStmt * clone() const override { return new BranchStmt{ *this }; }
 	MUTATE_FRIEND
@@ -257,61 +260,59 @@
 };
 
-/// Return statement `return ...`
+// Return statement: return ...
 class ReturnStmt final : public Stmt {
-public:
+  public:
 	ptr<Expr> expr;
 
-	ReturnStmt( const CodeLocation & loc, const Expr * expr, std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), expr(expr) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+	ReturnStmt( const CodeLocation & loc, const Expr * expr, const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), expr(expr) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	ReturnStmt * clone() const override { return new ReturnStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Kind of exception
+// Kind of exception
 enum ExceptionKind { Terminate, Resume };
 
-/// Throw statement `throw ...`
+// Throw statement: throw ...
 class ThrowStmt final : public Stmt {
-public:
+  public:
 	ptr<Expr> expr;
 	ptr<Expr> target;
 	ExceptionKind kind;
 
-	ThrowStmt(
-		const CodeLocation & loc, ExceptionKind kind, const Expr * expr, const Expr * target,
-		std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), expr(expr), target(target), kind(kind) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+	ThrowStmt( const CodeLocation & loc, ExceptionKind kind, const Expr * expr,
+			   const Expr * target, const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), expr(expr), target(target), kind(kind) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	ThrowStmt * clone() const override { return new ThrowStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Try statement `try { ... } ...`
+// Try statement: try { ... } ...
 class TryStmt final : public Stmt {
-public:
+  public:
 	ptr<CompoundStmt> body;
 	std::vector<ptr<CatchStmt>> handlers;
 	ptr<FinallyStmt> finally;
 
-	TryStmt(
-		const CodeLocation & loc, const CompoundStmt * body,
-		std::vector<ptr<CatchStmt>> && handlers, const FinallyStmt * finally,
-		std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), body(body), handlers(std::move(handlers)), finally(finally) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+	TryStmt( const CodeLocation & loc, const CompoundStmt * body,
+			 const std::vector<ptr<CatchStmt>> && handlers, const FinallyStmt * finally,
+			 const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), body(body), handlers(std::move(handlers)), finally(finally) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	TryStmt * clone() const override { return new TryStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Catch clause of try statement
+// Catch clause of try statement
 class CatchStmt final : public Stmt {
-public:
+  public:
 	ptr<Decl> decl;
 	ptr<Expr> cond;
@@ -319,48 +320,47 @@
 	ExceptionKind kind;
 
-	CatchStmt(
-		const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond,
-		const Stmt * body, std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), decl(decl), cond(cond), body(body), kind(kind) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+	CatchStmt( const CodeLocation & loc, ExceptionKind kind, const Decl * decl, const Expr * cond,
+			   const Stmt * body, const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), decl(decl), cond(cond), body(body), kind(kind) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	CatchStmt * clone() const override { return new CatchStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Finally clause of try statement
+// Finally clause of try statement
 class FinallyStmt final : public Stmt {
-public:
+  public:
 	ptr<CompoundStmt> body;
 
 	FinallyStmt( const CodeLocation & loc, const CompoundStmt * body,
-		std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), body(body) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+				 std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), body(body) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	FinallyStmt * clone() const override { return new FinallyStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Suspend statement
+// Suspend statement
 class SuspendStmt final : public Stmt {
-public:
+  public:
 	ptr<CompoundStmt> then;
 	enum Type { None, Coroutine, Generator } type = None;
 
-	SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), then(then), type(type) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+	SuspendStmt( const CodeLocation & loc, const CompoundStmt * then, Type type, const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), then(then), type(type) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	SuspendStmt * clone() const override { return new SuspendStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Wait for concurrency statement `when (...) waitfor (... , ...) ... timeout(...) ... else ...`
+// Waitfor statement: when (...) waitfor (... , ...) ... timeout(...) ... else ...
 class WaitForStmt final : public Stmt {
-public:
+  public:
 	struct Target {
 		ptr<Expr> func;
@@ -389,65 +389,62 @@
 	OrElse orElse;
 
-	WaitForStmt( const CodeLocation & loc, std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+	WaitForStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	WaitForStmt * clone() const override { return new WaitForStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Any declaration in a (compound) statement.
+// Any declaration in a (compound) statement.
 class DeclStmt final : public Stmt {
-public:
+  public:
 	ptr<Decl> decl;
 
-	DeclStmt( const CodeLocation & loc, const Decl * decl, std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), decl(decl) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+	DeclStmt( const CodeLocation & loc, const Decl * decl, const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), decl(decl) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	DeclStmt * clone() const override { return new DeclStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Represents an implicit application of a constructor or destructor.
+// Represents an implicit application of a constructor or destructor.
 class ImplicitCtorDtorStmt final : public Stmt {
-public:
+  public:
 	ptr<Stmt> callStmt;
 
 	ImplicitCtorDtorStmt( const CodeLocation & loc, const Stmt * callStmt,
-		std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), callStmt(callStmt) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+						  std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), callStmt(callStmt) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	ImplicitCtorDtorStmt * clone() const override { return new ImplicitCtorDtorStmt{ *this }; }
 	MUTATE_FRIEND
 };
 
-/// Mutex Statement
+// Mutex Statement
 class MutexStmt final : public Stmt {
-public:
+  public:
 	ptr<Stmt> stmt;
 	std::vector<ptr<Expr>> mutexObjs;
 
 	MutexStmt( const CodeLocation & loc, const Stmt * stmt, 
-		std::vector<ptr<Expr>> && mutexes, std::vector<Label> && labels = {} )
-	: Stmt(loc, std::move(labels)), stmt(stmt), mutexObjs(std::move(mutexes)) {}
-
-	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
-private:
+			   const std::vector<ptr<Expr>> && mutexes, const std::vector<Label> && labels = {} )
+		: Stmt(loc, std::move(labels)), stmt(stmt), mutexObjs(std::move(mutexes)) {}
+
+	const Stmt * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
 	MutexStmt * clone() const override { return new MutexStmt{ *this }; }
 	MUTATE_FRIEND
 };
-
-}
+} // namespace ast
 
 #undef MUTATE_FRIEND
 
 // Local Variables: //
-// tab-width: 4 //
 // mode: c++ //
-// compile-command: "make install" //
 // End: //
Index: src/AST/Visitor.hpp
===================================================================
--- src/AST/Visitor.hpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/AST/Visitor.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Thr May 9 15:28:00 2019
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Mar 12 18:25:07 2021
-// Update Count     : 1
+// Last Modified On : Tue Feb  1 09:09:34 2022
+// Update Count     : 2
 //
 
@@ -38,5 +38,5 @@
     virtual const ast::Stmt *             visit( const ast::DirectiveStmt        * ) = 0;
     virtual const ast::Stmt *             visit( const ast::IfStmt               * ) = 0;
-    virtual const ast::Stmt *             visit( const ast::WhileStmt            * ) = 0;
+    virtual const ast::Stmt *             visit( const ast::WhileDoStmt          * ) = 0;
     virtual const ast::Stmt *             visit( const ast::ForStmt              * ) = 0;
     virtual const ast::Stmt *             visit( const ast::SwitchStmt           * ) = 0;
Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/CodeGen/CodeGenerator.cc	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Mar 12 19:00:42 2021
-// Update Count     : 536
+// Last Modified On : Wed Feb  2 20:30:30 2022
+// Update Count     : 541
 //
 #include "CodeGenerator.h"
@@ -42,5 +42,5 @@
 	bool wantSpacing( Statement * stmt) {
 		return dynamic_cast< IfStmt * >( stmt ) || dynamic_cast< CompoundStmt * >( stmt ) ||
-			dynamic_cast< WhileStmt * >( stmt ) || dynamic_cast< ForStmt * >( stmt ) || dynamic_cast< SwitchStmt *>( stmt );
+			dynamic_cast< WhileDoStmt * >( stmt ) || dynamic_cast< ForStmt * >( stmt ) || dynamic_cast< SwitchStmt *>( stmt );
 	}
 
@@ -955,9 +955,9 @@
 		output << " ) ";
 
-		ifStmt->get_thenPart()->accept( *visitor );
-
-		if ( ifStmt->get_elsePart() != 0) {
+		ifStmt->get_then()->accept( *visitor );
+
+		if ( ifStmt->get_else() != 0) {
 			output << " else ";
-			ifStmt->get_elsePart()->accept( *visitor );
+			ifStmt->get_else()->accept( *visitor );
 		} // if
 	}
@@ -1020,4 +1020,5 @@
 			output << "fallthru";
 			break;
+		  default: ;									// prevent warning
 		} // switch
 		// print branch target for labelled break/continue/fallthru in debug mode
@@ -1125,22 +1126,22 @@
 	}
 
-	void CodeGenerator::postvisit( WhileStmt * whileStmt ) {
-		if ( whileStmt->get_isDoWhile() ) {
+	void CodeGenerator::postvisit( WhileDoStmt * whileDoStmt ) {
+		if ( whileDoStmt->get_isDoWhile() ) {
 			output << "do";
 		} else {
 			output << "while (";
-			whileStmt->get_condition()->accept( *visitor );
+			whileDoStmt->get_condition()->accept( *visitor );
 			output << ")";
 		} // if
 		output << " ";
 
-		output << CodeGenerator::printLabels( whileStmt->get_body()->get_labels() );
-		whileStmt->get_body()->accept( *visitor );
+		output << CodeGenerator::printLabels( whileDoStmt->get_body()->get_labels() );
+		whileDoStmt->get_body()->accept( *visitor );
 
 		output << indent;
 
-		if ( whileStmt->get_isDoWhile() ) {
+		if ( whileDoStmt->get_isDoWhile() ) {
 			output << " while (";
-			whileStmt->get_condition()->accept( *visitor );
+			whileDoStmt->get_condition()->accept( *visitor );
 			output << ");";
 		} // if
Index: src/CodeGen/CodeGenerator.h
===================================================================
--- src/CodeGen/CodeGenerator.h	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/CodeGen/CodeGenerator.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Mar 12 18:35:38 2021
-// Update Count     : 63
+// Last Modified On : Tue Feb  1 09:23:21 2022
+// Update Count     : 64
 //
 
@@ -116,5 +116,5 @@
 		void postvisit( WaitForStmt * );
 		void postvisit( WithStmt * );
-		void postvisit( WhileStmt * );
+		void postvisit( WhileDoStmt * );
 		void postvisit( ForStmt * );
 		void postvisit( NullStmt * );
Index: src/Common/CodeLocationTools.cpp
===================================================================
--- src/Common/CodeLocationTools.cpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/Common/CodeLocationTools.cpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Fri Dec  4 15:42:00 2020
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Mar 12 18:35:37 2021
-// Update Count     : 2
+// Last Modified On : Tue Feb  1 09:14:39 2022
+// Update Count     : 3
 //
 
@@ -109,5 +109,5 @@
     macro(DirectiveStmt, Stmt) \
     macro(IfStmt, Stmt) \
-    macro(WhileStmt, Stmt) \
+    macro(WhileDoStmt, Stmt) \
     macro(ForStmt, Stmt) \
     macro(SwitchStmt, Stmt) \
Index: src/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/Common/PassVisitor.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -92,6 +92,6 @@
 	virtual void visit( IfStmt * ifStmt ) override final;
 	virtual void visit( const IfStmt * ifStmt ) override final;
-	virtual void visit( WhileStmt * whileStmt ) override final;
-	virtual void visit( const WhileStmt * whileStmt ) override final;
+	virtual void visit( WhileDoStmt * whileDoStmt ) override final;
+	virtual void visit( const WhileDoStmt * whileDoStmt ) override final;
 	virtual void visit( ForStmt * forStmt ) override final;
 	virtual void visit( const ForStmt * forStmt ) override final;
@@ -277,5 +277,5 @@
 	virtual Statement * mutate( DirectiveStmt * dirStmt ) override final;
 	virtual Statement * mutate( IfStmt * ifStmt ) override final;
-	virtual Statement * mutate( WhileStmt * whileStmt ) override final;
+	virtual Statement * mutate( WhileDoStmt * whileDoStmt ) override final;
 	virtual Statement * mutate( ForStmt * forStmt ) override final;
 	virtual Statement * mutate( SwitchStmt * switchStmt ) override final;
Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/Common/PassVisitor.impl.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -1189,6 +1189,6 @@
 		maybeAccept_impl( node->initialization, *this );
 		visitExpression ( node->condition );
-		node->thenPart = visitStatement( node->thenPart );
-		node->elsePart = visitStatement( node->elsePart );
+		node->then = visitStatement( node->then );
+		node->else_ = visitStatement( node->else_ );
 	}
 	VISIT_END( node );
@@ -1203,6 +1203,6 @@
 		maybeAccept_impl( node->initialization, *this );
 		visitExpression ( node->condition );
-		visitStatement  ( node->thenPart );
-		visitStatement  ( node->elsePart );
+		visitStatement  ( node->then );
+		visitStatement  ( node->else_ );
 	}
 	VISIT_END( node );
@@ -1217,6 +1217,6 @@
 		maybeMutate_impl( node->initialization, *this );
 		node->condition = mutateExpression( node->condition );
-		node->thenPart  = mutateStatement ( node->thenPart  );
-		node->elsePart  = mutateStatement ( node->elsePart  );
+		node->then  = mutateStatement ( node->then  );
+		node->else_  = mutateStatement ( node->else_  );
 	}
 	MUTATE_END( Statement, node );
@@ -1224,7 +1224,7 @@
 
 //--------------------------------------------------------------------------
-// WhileStmt
-template< typename pass_type >
-void PassVisitor< pass_type >::visit( WhileStmt * node ) {
+// WhileDoStmt
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( WhileDoStmt * node ) {
 	VISIT_START( node );
 
@@ -1241,5 +1241,5 @@
 
 template< typename pass_type >
-void PassVisitor< pass_type >::visit( const WhileStmt * node ) {
+void PassVisitor< pass_type >::visit( const WhileDoStmt * node ) {
 	VISIT_START( node );
 
@@ -1256,5 +1256,5 @@
 
 template< typename pass_type >
-Statement * PassVisitor< pass_type >::mutate( WhileStmt * node ) {
+Statement * PassVisitor< pass_type >::mutate( WhileDoStmt * node ) {
 	MUTATE_START( node );
 
Index: src/ControlStruct/ExceptTranslateNew.cpp
===================================================================
--- src/ControlStruct/ExceptTranslateNew.cpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ControlStruct/ExceptTranslateNew.cpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Andrew Beach
 // Created On       : Mon Nov  8 11:53:00 2021
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Nov  8 16:50:00 2021
-// Update Count     : 0
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon Jan 31 18:49:58 2022
+// Update Count     : 1
 //
 
Index: src/ControlStruct/FixLabels.cpp
===================================================================
--- src/ControlStruct/FixLabels.cpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ControlStruct/FixLabels.cpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Andrew Beach
 // Created On       : Mon Nov  1 09:39:00 2021
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Nov  8 10:53:00 2021
-// Update Count     : 3
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon Jan 31 22:19:17 2022
+// Update Count     : 9
 //
 
@@ -20,42 +20,40 @@
 #include "AST/Stmt.hpp"
 #include "ControlStruct/MultiLevelExit.hpp"
+using namespace ast;
 
 namespace ControlStruct {
-
-namespace {
-
-class FixLabelsCore final : public ast::WithGuards {
+class FixLabelsCore final : public WithGuards {
 	LabelToStmt labelTable;
-public:
+  public:
 	FixLabelsCore() : labelTable() {}
 
-	void previsit( const ast::FunctionDecl * );
-	const ast::FunctionDecl * postvisit( const ast::FunctionDecl * );
-	void previsit( const ast::Stmt * );
-	void previsit( const ast::BranchStmt * );
-	void previsit( const ast::LabelAddressExpr * );
+	void previsit( const FunctionDecl * );
+	const FunctionDecl * postvisit( const FunctionDecl * );
+	void previsit( const Stmt * );
+	void previsit( const BranchStmt * );
+	void previsit( const LabelAddressExpr * );
 
-	void setLabelsDef( const std::vector<ast::Label> &, const ast::Stmt * );
-	void setLabelsUsage( const ast::Label & );
+	void setLabelsDef( const std::vector<Label> &, const Stmt * );
+	void setLabelsUsage( const Label & );
 };
 
-void FixLabelsCore::previsit( const ast::FunctionDecl * ) {
+void FixLabelsCore::previsit( const FunctionDecl * ) {
 	GuardValue( labelTable ).clear();
 }
 
-const ast::FunctionDecl * FixLabelsCore::postvisit(
-		const ast::FunctionDecl * decl ) {
+const FunctionDecl * FixLabelsCore::postvisit(
+	const FunctionDecl * decl ) {
 	if ( nullptr == decl->stmts ) return decl;
 	for ( auto kvp : labelTable ) {
 		if ( nullptr == kvp.second ) {
 			SemanticError( kvp.first.location,
-				"Use of undefined label: " + kvp.first.name );
+						   "Use of undefined label: " + kvp.first.name );
 		}
 	}
-	return ast::mutate_field( decl, &ast::FunctionDecl::stmts,
-		multiLevelExitUpdate( decl->stmts.get(), labelTable ) );
+	return mutate_field( decl, &FunctionDecl::stmts,
+						 multiLevelExitUpdate( decl->stmts.get(), labelTable ) );
 }
 
-void FixLabelsCore::previsit( const ast::Stmt * stmt ) {
+void FixLabelsCore::previsit( const Stmt * stmt ) {
 	if ( !stmt->labels.empty() ) {
 		setLabelsDef( stmt->labels, stmt );
@@ -63,5 +61,5 @@
 }
 
-void FixLabelsCore::previsit( const ast::BranchStmt * stmt ) {
+void FixLabelsCore::previsit( const BranchStmt * stmt ) {
 	if ( !stmt->labels.empty() ) {
 		setLabelsDef( stmt->labels, stmt );
@@ -72,5 +70,5 @@
 }
 
-void FixLabelsCore::previsit( const ast::LabelAddressExpr * expr ) {
+void FixLabelsCore::previsit( const LabelAddressExpr * expr ) {
 	assert( !expr->arg.empty() );
 	setLabelsUsage( expr->arg );
@@ -78,5 +76,5 @@
 
 void FixLabelsCore::setLabelsDef(
-		const std::vector<ast::Label> & labels, const ast::Stmt * stmt ) {
+	const std::vector<Label> & labels, const Stmt * stmt ) {
 	assert( !labels.empty() );
 	assert( stmt );
@@ -89,5 +87,5 @@
 			// Duplicate definition, this is an error.
 			SemanticError( label.location,
-				"Duplicate definition of label: " + label.name );
+						   "Duplicate definition of label: " + label.name );
 		} else {
 			// Perviously used, but not defined until now.
@@ -98,5 +96,5 @@
 
 // Label was used, if it is new add it to the table.
-void FixLabelsCore::setLabelsUsage( const ast::Label & label ) {
+void FixLabelsCore::setLabelsUsage( const Label & label ) {
 	if ( labelTable.find( label ) == labelTable.end() ) {
 		labelTable[ label ] = nullptr;
@@ -104,10 +102,7 @@
 }
 
-} // namespace
-
-void fixLabels( ast::TranslationUnit & translationUnit ) {
-	ast::Pass<FixLabelsCore>::run( translationUnit );
+void fixLabels( TranslationUnit & translationUnit ) {
+	Pass<FixLabelsCore>::run( translationUnit );
 }
-
 } // namespace ControlStruct
 
Index: src/ControlStruct/FixLabels.hpp
===================================================================
--- src/ControlStruct/FixLabels.hpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ControlStruct/FixLabels.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Andrew Beach
 // Created On       : Mon Nov  1 09:36:00 2021
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Nov  1 09:40:00 2021
-// Update Count     : 0
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon Jan 31 22:18:43 2022
+// Update Count     : 2
 //
 
@@ -17,12 +17,10 @@
 
 namespace ast {
-	class TranslationUnit;
+class TranslationUnit;
 }
 
 namespace ControlStruct {
-
-/// normalizes label definitions and generates multi-level exit labels
+// normalizes label definitions and generates multi-level exit labels
 void fixLabels( ast::TranslationUnit & translationUnit );
-
 }
 
Index: src/ControlStruct/ForExprMutator.cc
===================================================================
--- src/ControlStruct/ForExprMutator.cc	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ControlStruct/ForExprMutator.cc	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Mar 11 22:26:52 2019
-// Update Count     : 14
+// Last Modified On : Tue Feb  1 09:26:12 2022
+// Update Count     : 16
 //
 
@@ -45,6 +45,6 @@
 		return hoist( forStmt, forStmt->initialization );
 	}
-	Statement * ForExprMutator::postmutate( WhileStmt * whileStmt ) {
-		return hoist( whileStmt, whileStmt->initialization );
+	Statement * ForExprMutator::postmutate( WhileDoStmt * whileDoStmt ) {
+		return hoist( whileDoStmt, whileDoStmt->initialization );
 	}
 } // namespace ControlStruct
Index: src/ControlStruct/ForExprMutator.h
===================================================================
--- src/ControlStruct/ForExprMutator.h	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ControlStruct/ForExprMutator.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Aug 17 15:32:48 2017
-// Update Count     : 5
+// Last Modified On : Tue Feb  1 09:18:50 2022
+// Update Count     : 7
 //
 
@@ -18,5 +18,5 @@
 class IfStmt;
 class ForStmt;
-class WhileStmt;
+class WhileDoStmt;
 class Statement;
 
@@ -24,7 +24,7 @@
 	class ForExprMutator {
 	  public:
-		Statement *postmutate( IfStmt * );
-		Statement *postmutate( ForStmt * );
-		Statement *postmutate( WhileStmt * );
+		Statement * postmutate( IfStmt * );
+		Statement * postmutate( ForStmt * );
+		Statement * postmutate( WhileDoStmt * );
 	};
 } // namespace ControlStruct
Index: src/ControlStruct/HoistControlDecls.cpp
===================================================================
--- src/ControlStruct/HoistControlDecls.cpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
+++ src/ControlStruct/HoistControlDecls.cpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -0,0 +1,86 @@
+//
+// 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.
+//
+// HoistControlDecls.cpp -- Desugar Cforall control structures.
+//
+// Author           : Andrew Beach
+// Created On       : Fri Dec  3 15:34:00 2021
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue Feb  1 18:59:47 2022
+// Update Count     : 25
+//
+
+#include "HoistControlDecls.hpp"
+
+#include "AST/Decl.hpp"
+#include "AST/Pass.hpp"
+#include "AST/TranslationUnit.hpp"
+using namespace ast;
+
+namespace ControlStruct {
+
+template<typename StmtT>
+const Stmt * hoist( const StmtT * stmt ) {
+	// If no hoisting is needed, then make no changes.
+
+	if ( stmt->inits.size() == 0 ) {					// no declarations ?
+		// if ( /* no conditional declarations */ ...  ) ...
+		return stmt;
+	} // if
+
+	// Put hoist declarations and modified statement in a compound statement.
+
+	CompoundStmt * block = new CompoundStmt( stmt->location ); // create empty compound statement
+	//    {}
+
+	for ( const Stmt * next : stmt->inits ) {			// link conditional declarations into compound
+		block->kids.push_back( next );
+	}
+	//    if ( int x = f(), y = g(); ... ) ...
+	// link declarations into compound statement
+	//    {
+	//         int x = f();
+	//         int y = g();
+	//    }
+
+	StmtT * mutStmt = mutate( stmt );					// create mutate handle to change statement
+	mutStmt->inits.clear();								// remove declarations
+	//    if ( ... ) ...
+
+	block->kids.push_back( mutStmt );					// link modified statement into compound
+	//    {
+	//        int x = f();
+	//        int y = g();
+	//        if ( ... ) ...
+	//    }
+	return block;
+}
+
+struct hoistControlDeclsCore {
+	// Statements with declarations in conditional.
+	const Stmt * postvisit( const IfStmt * stmt ) {
+		return hoist<IfStmt>( stmt );
+	}
+	const Stmt * postvisit( const ForStmt * stmt ) {
+		return hoist<ForStmt>( stmt );
+	}
+	const Stmt * postvisit( const WhileDoStmt * stmt ) {
+		return hoist<WhileDoStmt>( stmt );
+	}
+};
+
+// Hoist initialization out of for statements.
+void hoistControlDecls( TranslationUnit & translationUnit ) {
+	Pass<hoistControlDeclsCore>::run( translationUnit );
+}
+
+} // namespace ControlStruct
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/ControlStruct/HoistControlDecls.hpp
===================================================================
--- src/ControlStruct/HoistControlDecls.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
+++ src/ControlStruct/HoistControlDecls.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -0,0 +1,31 @@
+//
+// 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.
+//
+// HoistControlDecls.hpp -- Desugar Cforall control structures.
+//
+// Author           : Andrew Beach
+// Created On       : Fri Dec  3 15:31:00 2021
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon Jan 31 22:25:07 2022
+// Update Count     : 3
+//
+
+#pragma once
+
+namespace ast {
+class TranslationUnit;
+}
+
+namespace ControlStruct {
+// Hoist declarations out of control flow statements into compound statement.
+void hoistControlDecls( ast::TranslationUnit & translationUnit );
+} // namespace ControlStruct
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/ControlStruct/LabelFixer.cc
===================================================================
--- src/ControlStruct/LabelFixer.cc	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ControlStruct/LabelFixer.cc	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Rodolfo G. Esteves
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Tue Jan 21 10:32:00 2020
-// Update Count     : 160
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue Feb  1 09:12:09 2022
+// Update Count     : 162
 //
 
@@ -27,107 +27,107 @@
 
 namespace ControlStruct {
-	bool LabelFixer::Entry::insideLoop() {
-		return ( dynamic_cast< ForStmt * > ( definition ) ||
-			dynamic_cast< WhileStmt * > ( definition )  );
+bool LabelFixer::Entry::insideLoop() {
+	return ( dynamic_cast< ForStmt * > ( definition ) ||
+		dynamic_cast< WhileDoStmt * > ( definition )  );
+}
+
+LabelFixer::LabelFixer( LabelGenerator * gen ) : generator ( gen ) {
+	if ( generator == 0 )
+		generator = LabelGenerator::getGenerator();
+}
+
+void LabelFixer::previsit( FunctionDecl * ) {
+	// need to go into a nested function in a fresh state
+	GuardValue( labelTable );
+	labelTable.clear();
+}
+
+void LabelFixer::postvisit( FunctionDecl * functionDecl ) {
+	PassVisitor<MultiLevelExitMutator> mlem( resolveJumps(), generator );
+	// We start in the body so we can stop when we hit another FunctionDecl.
+	maybeMutate( functionDecl->statements, mlem );
+}
+
+// prune to at most one label definition for each statement
+void LabelFixer::previsit( Statement * stmt ) {
+	std::list< Label > &labels = stmt->get_labels();
+
+	if ( ! labels.empty() ) {
+		// only remember one label for each statement
+		Label current = setLabelsDef( labels, stmt );
+	} // if
+}
+
+void LabelFixer::previsit( BranchStmt * branchStmt ) {
+	previsit( ( Statement *)branchStmt );
+
+	// for labeled branches, add an entry to the label table
+	Label target = branchStmt->get_target();
+	if ( target != "" ) {
+		setLabelsUsg( target, branchStmt );
+	}
+}
+
+void LabelFixer::previsit( LabelAddressExpr * addrExpr ) {
+	Label & target = addrExpr->arg;
+	assert( target != "" );
+	setLabelsUsg( target, addrExpr );
+}
+
+
+// Sets the definition of the labelTable entry to be the provided statement for every label in
+// the list parameter. Happens for every kind of statement.
+Label LabelFixer::setLabelsDef( std::list< Label > & llabel, Statement * definition ) {
+	assert( definition != 0 );
+	assert( llabel.size() > 0 );
+
+	for ( std::list< Label >::iterator i = llabel.begin(); i != llabel.end(); i++ ) {
+		Label & l = *i;
+		l.set_statement( definition ); // attach statement to the label to be used later
+		if ( labelTable.find( l ) == labelTable.end() ) {
+			// All labels on this statement need to use the same entry,
+			// so this should only be created once.
+			// undefined and unused until now, add an entry
+			labelTable[ l ] = new Entry( definition );
+		} else if ( labelTable[ l ]->defined() ) {
+			// defined twice, error
+			SemanticError( l.get_statement()->location,
+				"Duplicate definition of label: " + l.get_name() );
+		} else {
+			// used previously, but undefined until now -> link with this entry
+			// Question: Is changing objects important?
+			delete labelTable[ l ];
+			labelTable[ l ] = new Entry( definition );
+		} // if
+	} // for
+
+	// Produce one of the labels attached to this statement to be temporarily used as the
+	// canonical label.
+	return labelTable[ llabel.front() ]->get_label();
+}
+
+// A label was used, add it to the table if it isn't already there
+template< typename UsageNode >
+void LabelFixer::setLabelsUsg( Label orgValue, UsageNode *use ) {
+	assert( use != 0 );
+
+	// add label with an unknown origin
+	if ( labelTable.find( orgValue ) == labelTable.end() ) {
+		labelTable[ orgValue ] = new Entry( 0 );
+	}
+}
+
+// Builds a table that maps a label to its defining statement.
+std::map<Label, Statement * > * LabelFixer::resolveJumps() throw ( SemanticErrorException ) {
+	std::map< Label, Statement * > *ret = new std::map< Label, Statement * >();
+	for ( std::map< Label, Entry * >::iterator i = labelTable.begin(); i != labelTable.end(); ++i ) {
+		if ( ! i->second->defined() ) {
+			SemanticError( i->first.get_statement()->location, "Use of undefined label: " + i->first.get_name() );
+		}
+		(*ret)[ i->first ] = i->second->get_definition();
 	}
 
-	LabelFixer::LabelFixer( LabelGenerator * gen ) : generator ( gen ) {
-		if ( generator == 0 )
-			generator = LabelGenerator::getGenerator();
-	}
-
-	void LabelFixer::previsit( FunctionDecl * ) {
-		// need to go into a nested function in a fresh state
-		GuardValue( labelTable );
-		labelTable.clear();
-	}
-
-	void LabelFixer::postvisit( FunctionDecl * functionDecl ) {
-		PassVisitor<MultiLevelExitMutator> mlem( resolveJumps(), generator );
-		// We start in the body so we can stop when we hit another FunctionDecl.
-		maybeMutate( functionDecl->statements, mlem );
-	}
-
-	// prune to at most one label definition for each statement
-	void LabelFixer::previsit( Statement * stmt ) {
-		std::list< Label > &labels = stmt->get_labels();
-
-		if ( ! labels.empty() ) {
-			// only remember one label for each statement
-			Label current = setLabelsDef( labels, stmt );
-		} // if
-	}
-
-	void LabelFixer::previsit( BranchStmt * branchStmt ) {
-		previsit( ( Statement *)branchStmt );
-
-		// for labeled branches, add an entry to the label table
-		Label target = branchStmt->get_target();
-		if ( target != "" ) {
-			setLabelsUsg( target, branchStmt );
-		}
-	}
-
-	void LabelFixer::previsit( LabelAddressExpr * addrExpr ) {
-		Label & target = addrExpr->arg;
-		assert( target != "" );
-		setLabelsUsg( target, addrExpr );
-	}
-
-
-	// Sets the definition of the labelTable entry to be the provided statement for every label in
-	// the list parameter. Happens for every kind of statement.
-	Label LabelFixer::setLabelsDef( std::list< Label > & llabel, Statement * definition ) {
-		assert( definition != 0 );
-		assert( llabel.size() > 0 );
-
-		for ( std::list< Label >::iterator i = llabel.begin(); i != llabel.end(); i++ ) {
-			Label & l = *i;
-			l.set_statement( definition ); // attach statement to the label to be used later
-			if ( labelTable.find( l ) == labelTable.end() ) {
-				// All labels on this statement need to use the same entry,
-				// so this should only be created once.
-				// undefined and unused until now, add an entry
-				labelTable[ l ] = new Entry( definition );
-			} else if ( labelTable[ l ]->defined() ) {
-				// defined twice, error
-				SemanticError( l.get_statement()->location,
-					"Duplicate definition of label: " + l.get_name() );
-			} else {
-				// used previously, but undefined until now -> link with this entry
-				// Question: Is changing objects important?
-				delete labelTable[ l ];
-				labelTable[ l ] = new Entry( definition );
-			} // if
-		} // for
-
-		// Produce one of the labels attached to this statement to be temporarily used as the
-		// canonical label.
-		return labelTable[ llabel.front() ]->get_label();
-	}
-
-	// A label was used, add it to the table if it isn't already there
-	template< typename UsageNode >
-	void LabelFixer::setLabelsUsg( Label orgValue, UsageNode *use ) {
-		assert( use != 0 );
-
-		// add label with an unknown origin
-		if ( labelTable.find( orgValue ) == labelTable.end() ) {
-			labelTable[ orgValue ] = new Entry( 0 );
-		}
-	}
-
-	// Builds a table that maps a label to its defining statement.
-	std::map<Label, Statement * > * LabelFixer::resolveJumps() throw ( SemanticErrorException ) {
-		std::map< Label, Statement * > *ret = new std::map< Label, Statement * >();
-		for ( std::map< Label, Entry * >::iterator i = labelTable.begin(); i != labelTable.end(); ++i ) {
-			if ( ! i->second->defined() ) {
-				SemanticError( i->first.get_statement()->location, "Use of undefined label: " + i->first.get_name() );
-			}
-			(*ret)[ i->first ] = i->second->get_definition();
-		}
-
-		return ret;
-	}
+	return ret;
+}
 }  // namespace ControlStruct
 
Index: src/ControlStruct/LabelFixer.h
===================================================================
--- src/ControlStruct/LabelFixer.h	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ControlStruct/LabelFixer.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul 22 09:17:24 2017
-// Update Count     : 34
+// Last Modified On : Mon Jan 31 22:28:04 2022
+// Update Count     : 35
 //
 
@@ -26,49 +26,49 @@
 
 namespace ControlStruct {
-	/// normalizes label definitions and generates multi-level exit labels
-	class LabelGenerator;
+// normalizes label definitions and generates multi-level exit labels
+class LabelGenerator;
 
-	class LabelFixer final : public WithGuards {
-	  public:
-		LabelFixer( LabelGenerator *gen = 0 );
+class LabelFixer final : public WithGuards {
+  public:
+	LabelFixer( LabelGenerator *gen = 0 );
 
-		std::map < Label, Statement * > *resolveJumps() throw ( SemanticErrorException );
+	std::map < Label, Statement * > *resolveJumps() throw ( SemanticErrorException );
 
-		// Declarations
-		void previsit( FunctionDecl *functionDecl );
-		void postvisit( FunctionDecl *functionDecl );
+	// Declarations
+	void previsit( FunctionDecl *functionDecl );
+	void postvisit( FunctionDecl *functionDecl );
 
-		// Statements
-		void previsit( Statement *stmt );
-		void previsit( BranchStmt *branchStmt );
+	// Statements
+	void previsit( Statement *stmt );
+	void previsit( BranchStmt *branchStmt );
 
-		// Expressions
-		void previsit( LabelAddressExpr *addrExpr );
+	// Expressions
+	void previsit( LabelAddressExpr *addrExpr );
 
-		Label setLabelsDef( std::list< Label > &, Statement *definition );
-		template< typename UsageNode >
-		void setLabelsUsg( Label, UsageNode *usage = 0 );
+	Label setLabelsDef( std::list< Label > &, Statement *definition );
+	template< typename UsageNode >
+	void setLabelsUsg( Label, UsageNode *usage = 0 );
+
+  private:
+	class Entry {
+		public:
+		Entry( Statement *to ) : definition( to ) {}
+		bool defined() { return ( definition != 0 ); }
+		bool insideLoop();
+
+		Label get_label() const { return label; }
+		void set_label( Label lab ) { label = lab; }
+
+		Statement *get_definition() const { return definition; }
+		void set_definition( Statement *def ) { definition = def; }
 
 	  private:
-		class Entry {
-			public:
-			Entry( Statement *to ) : definition( to ) {}
-			bool defined() { return ( definition != 0 ); }
-			bool insideLoop();
+		Label label;
+		Statement *definition;
+	};
 
-			Label get_label() const { return label; }
-			void set_label( Label lab ) { label = lab; }
-
-			Statement *get_definition() const { return definition; }
-			void set_definition( Statement *def ) { definition = def; }
-
-		  private:
-			Label label;
-			Statement *definition;
-		};
-
-		std::map < Label, Entry *> labelTable;
-		LabelGenerator *generator;
-	};
+	std::map < Label, Entry *> labelTable;
+	LabelGenerator *generator;
+};
 } // namespace ControlStruct
 
Index: src/ControlStruct/LabelGenerator.cc
===================================================================
--- src/ControlStruct/LabelGenerator.cc	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ControlStruct/LabelGenerator.cc	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Rodolfo G. Esteves
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Nov  8 10:18:00 2021
-// Update Count     : 17
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon Jan 31 22:30:26 2022
+// Update Count     : 28
 //
 
@@ -17,10 +17,8 @@
 #include <sstream>              // for ostringstream
 #include <list>                 // for list
+using namespace std;
 
 #include "LabelGenerator.h"
 
-#include "AST/Attribute.hpp"
-#include "AST/Label.hpp"
-#include "AST/Stmt.hpp"
 #include "SynTree/Attribute.h"  // for Attribute
 #include "SynTree/Label.h"      // for Label, operator<<
@@ -28,45 +26,27 @@
 
 namespace ControlStruct {
-
 int LabelGenerator::current = 0;
 LabelGenerator * LabelGenerator::labelGenerator = nullptr;
 
-	LabelGenerator * LabelGenerator::getGenerator() {
-		if ( LabelGenerator::labelGenerator == 0 )
-			LabelGenerator::labelGenerator = new LabelGenerator();
-		return labelGenerator;
-	}
-
-	Label LabelGenerator::newLabel( std::string suffix, Statement * stmt ) {
-		std::ostringstream os;
-		os << "__L" << current++ << "__" << suffix;
-		if ( stmt && ! stmt->get_labels().empty() ) {
-			os << "_" << stmt->get_labels().front() << "__";
-		} // if
-		std::string ret = os.str();
-		Label l( ret );
-		l.get_attributes().push_back( new Attribute("unused") );
-		return l;
-	}
-
-ast::Label LabelGenerator::newLabel(
-		const std::string & suffix, const ast::Stmt * stmt ) {
-	assert( stmt );
-
-	std::ostringstream os;
-	os << "__L" << current++ << "__" << suffix;
-	if ( stmt && !stmt->labels.empty() ) {
-		os << "_" << stmt->labels.front() << "__";
-	}
-	ast::Label ret_label( stmt->location, os.str() );
-	ret_label.attributes.push_back( new ast::Attribute( "unused" ) );
-	return ret_label;
+LabelGenerator * LabelGenerator::getGenerator() {
+	if ( LabelGenerator::labelGenerator == 0 )
+		LabelGenerator::labelGenerator = new LabelGenerator();
+	return labelGenerator;
 }
 
+Label LabelGenerator::newLabel( string suffix, Statement * stmt ) {
+	ostringstream os;
+	os << "__L_OLD" << current++ << "__" << suffix;
+	if ( stmt && ! stmt->get_labels().empty() ) {
+		os << "_" << stmt->get_labels().front() << "__";
+	} // if
+	string ret = os.str();
+	Label l( ret );
+	l.get_attributes().push_back( new Attribute( "unused" ) );
+	return l;
+}
 } // namespace ControlStruct
 
 // Local Variables: //
-// tab-width: 4 //
 // mode: c++ //
-// compile-command: "make install" //
 // End: //
Index: src/ControlStruct/LabelGenerator.h
===================================================================
--- src/ControlStruct/LabelGenerator.h	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ControlStruct/LabelGenerator.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Rodolfo G. Esteves
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Nov  8 10:16:00 2021
-// Update Count     : 8
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon Jan 31 22:30:10 2022
+// Update Count     : 16
 //
 
@@ -21,24 +21,20 @@
 
 class Statement;
+
 namespace ast {
-	class Stmt;
-	class Label;
+class Stmt;
+class Label;
 }
 
 namespace ControlStruct {
-
 class LabelGenerator {
 	static int current;
 	static LabelGenerator *labelGenerator;
-protected:
+  protected:
 	LabelGenerator() {}
-public:
+  public:
 	static LabelGenerator *getGenerator();
 	static Label newLabel(std::string suffix, Statement * stmt = nullptr);
-	static ast::Label newLabel( const std::string&, const ast::Stmt * );
-	static void reset() { current = 0; }
-	static void rewind() { current--; }
 };
-
 } // namespace ControlStruct
 
Index: src/ControlStruct/LabelGeneratorNew.cpp
===================================================================
--- src/ControlStruct/LabelGeneratorNew.cpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
+++ src/ControlStruct/LabelGeneratorNew.cpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -0,0 +1,52 @@
+//
+// 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.
+//
+// LabelGenerator.cc --
+//
+// Author           : Peter A. Buhr
+// Created On       : Mon May 18 07:44:20 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Wed Feb  2 09:11:17 2022
+// Update Count     : 72
+//
+
+using namespace std;
+
+#include "LabelGeneratorNew.hpp"
+
+#include "AST/Attribute.hpp"
+#include "AST/Label.hpp"
+#include "AST/Stmt.hpp"
+using namespace ast;
+
+namespace ControlStruct {
+
+Label newLabel( const string & suffix, const Stmt * stmt ) {
+	static int current = 0;
+
+	assertf( stmt, "CFA internal error: parameter statement cannot be null pointer" );
+
+	enum { size = 128 };
+	char buf[size];										// space to build label
+	int len = snprintf( buf, size, "__L%d__%s", current++, suffix.c_str() );
+	assertf( len < size, "CFA Internal error: buffer overflow creating label" );
+
+	// What does this do?
+	if ( ! stmt->labels.empty() ) {
+		len = snprintf( buf + len, size - len, "_%s__", stmt->labels.front().name.c_str() );
+		assertf( len < size - len, "CFA Internal error: buffer overflow creating label" );
+	} // if
+
+	Label ret_label( stmt->location, buf );
+	ret_label.attributes.push_back( new Attribute( "unused" ) );
+	return ret_label;
+}
+
+} // namespace ControlStruct
+
+// Local Variables: //
+// mode: c++ //
+// End: //
Index: src/ControlStruct/LabelGeneratorNew.hpp
===================================================================
--- src/ControlStruct/LabelGeneratorNew.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
+++ src/ControlStruct/LabelGeneratorNew.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -0,0 +1,35 @@
+//
+// 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.
+//
+// LabelGenerator.h --
+//
+// Author           : Rodolfo G. Esteves
+// Created On       : Mon May 18 07:44:20 2015
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon Jan 31 18:03:09 2022
+// Update Count     : 27
+//
+
+#pragma once
+
+#include <string>										// for string
+
+class Statement;
+
+namespace ast {
+	class Stmt;
+	class Label;
+} // namespace ast
+
+namespace ControlStruct {
+	ast::Label newLabel( const std::string &, const ast::Stmt * );
+} // namespace ControlStruct
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/ControlStruct/MLEMutator.cc
===================================================================
--- src/ControlStruct/MLEMutator.cc	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ControlStruct/MLEMutator.cc	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Rodolfo G. Esteves
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Wed Jan 22 11:50:00 2020
-// Update Count     : 223
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Wed Feb  2 20:18:57 2022
+// Update Count     : 227
 //
 
@@ -39,5 +39,5 @@
 	namespace {
 		bool isLoop( const MultiLevelExitMutator::Entry & e ) {
-			return dynamic_cast< WhileStmt * >( e.get_controlStructure() )
+			return dynamic_cast< WhileDoStmt * >( e.get_controlStructure() )
 				|| dynamic_cast< ForStmt * >( e.get_controlStructure() );
 		}
@@ -136,5 +136,5 @@
 			}
 		}
-		assertf( false, "Could not find label '%s' on statement %s",
+		assertf( false, "CFA internal error: could not find label '%s' on statement %s",
 			originalTarget.get_name().c_str(), toString( stmt ).c_str() );
 	}
@@ -295,6 +295,6 @@
 	}
 
-	void MultiLevelExitMutator::premutate( WhileStmt * whileStmt ) {
-		return prehandleLoopStmt( whileStmt );
+	void MultiLevelExitMutator::premutate( WhileDoStmt * whileDoStmt ) {
+		return prehandleLoopStmt( whileDoStmt );
 	}
 
@@ -303,6 +303,6 @@
 	}
 
-	Statement * MultiLevelExitMutator::postmutate( WhileStmt * whileStmt ) {
-		return posthandleLoopStmt( whileStmt );
+	Statement * MultiLevelExitMutator::postmutate( WhileDoStmt * whileDoStmt ) {
+		return posthandleLoopStmt( whileDoStmt );
 	}
 
@@ -395,5 +395,7 @@
 		}
 		assert( ! enclosingControlStructures.empty() );
-		assertf( dynamic_cast<SwitchStmt *>( enclosingControlStructures.back().get_controlStructure() ), "Control structure enclosing a case clause must be a switch, but is: %s", toCString( enclosingControlStructures.back().get_controlStructure() ) );
+		assertf( dynamic_cast<SwitchStmt *>( enclosingControlStructures.back().get_controlStructure() ),
+				 "CFA internal error: control structure enclosing a case clause must be a switch, but is: %s",
+				 toCString( enclosingControlStructures.back().get_controlStructure() ) );
 		if ( caseStmt->isDefault() ) {
 			if ( enclosingControlStructures.back().isFallDefaultUsed() ) {
Index: src/ControlStruct/MLEMutator.h
===================================================================
--- src/ControlStruct/MLEMutator.h	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ControlStruct/MLEMutator.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Rodolfo G. Esteves
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Wed Jan 22 11:50:00 2020
-// Update Count     : 48
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue Feb  1 09:27:24 2022
+// Update Count     : 50
 //
 
@@ -42,6 +42,6 @@
 		void premutate( CompoundStmt *cmpndStmt );
 		Statement * postmutate( BranchStmt *branchStmt ) throw ( SemanticErrorException );
-		void premutate( WhileStmt *whileStmt );
-		Statement * postmutate( WhileStmt *whileStmt );
+		void premutate( WhileDoStmt *whileDoStmt );
+		Statement * postmutate( WhileDoStmt *whileDoStmt );
 		void premutate( ForStmt *forStmt );
 		Statement * postmutate( ForStmt *forStmt );
@@ -67,5 +67,5 @@
 				stmt( stmt ), breakExit( breakExit ), contExit( contExit ) {}
 
-			explicit Entry( WhileStmt *stmt, Label breakExit, Label contExit ) :
+			explicit Entry( WhileDoStmt *stmt, Label breakExit, Label contExit ) :
 				stmt( stmt ), breakExit( breakExit ), contExit( contExit ) {}
 
Index: src/ControlStruct/MultiLevelExit.cpp
===================================================================
--- src/ControlStruct/MultiLevelExit.cpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ControlStruct/MultiLevelExit.cpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Andrew Beach
 // Created On       : Mon Nov  1 13:48:00 2021
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Nov  8 10:56:00 2021
-// Update Count     : 2
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Wed Feb  2 23:07:54 2022
+// Update Count     : 33
 //
 
@@ -18,21 +18,20 @@
 #include "AST/Pass.hpp"
 #include "AST/Stmt.hpp"
-#include "ControlStruct/LabelGenerator.h"
+#include "LabelGeneratorNew.hpp"
 
 #include <set>
+using namespace std;
+using namespace ast;
 
 namespace ControlStruct {
-
-namespace {
-
 class Entry {
-public:
-	const ast::Stmt * stmt;
-private:
+  public:
+	const Stmt * stmt;
+  private:
 	// Organized like a manual ADT. Avoids creating a bunch of dead data.
 	struct Target {
-		ast::Label label;
+		Label label;
 		bool used = false;
-		Target( const ast::Label & label ) : label( label ) {}
+		Target( const Label & label ) : label( label ) {}
 		Target() : label( CodeLocation() ) {}
 	};
@@ -41,49 +40,50 @@
 
 	enum Kind {
-		ForStmt, WhileStmt, CompoundStmt, IfStmt, CaseStmt, SwitchStmt, TryStmt
+		ForStmtK, WhileDoStmtK, CompoundStmtK, IfStmtK, CaseStmtK, SwitchStmtK, TryStmtK
 	} kind;
 
 	bool fallDefaultValid = true;
 
-	static ast::Label & useTarget( Target & target ) {
+	static Label & useTarget( Target & target ) {
 		target.used = true;
 		return target.label;
 	}
-
-public:
-	Entry( const ast::ForStmt * stmt, ast::Label breakExit, ast::Label contExit ) :
-		stmt( stmt ), firstTarget( breakExit ), secondTarget( contExit ), kind( ForStmt ) {}
-	Entry( const ast::WhileStmt * stmt, ast::Label breakExit, ast::Label contExit ) :
-		stmt( stmt ), firstTarget( breakExit ), secondTarget( contExit ), kind( WhileStmt ) {}
-	Entry( const ast::CompoundStmt *stmt, ast::Label breakExit ) :
-		stmt( stmt ), firstTarget( breakExit ), secondTarget(), kind( CompoundStmt ) {}
-	Entry( const ast::IfStmt *stmt, ast::Label breakExit ) :
-		stmt( stmt ), firstTarget( breakExit ), secondTarget(), kind( IfStmt ) {}
-	Entry( const ast::CaseStmt *stmt, ast::Label fallExit ) :
-		stmt( stmt ), firstTarget( fallExit ), secondTarget(), kind( CaseStmt ) {}
-	Entry( const ast::SwitchStmt *stmt, ast::Label breakExit, ast::Label fallDefaultExit ) :
-		stmt( stmt ), firstTarget( breakExit ), secondTarget( fallDefaultExit ), kind( SwitchStmt ) {}
-	Entry( const ast::TryStmt *stmt, ast::Label breakExit ) :
-		stmt( stmt ), firstTarget( breakExit ), secondTarget(), kind( TryStmt ) {}
-
-	bool isContTarget() const { return kind <= WhileStmt; }
-	bool isBreakTarget() const { return CaseStmt != kind; }
-	bool isFallTarget() const { return CaseStmt == kind; }
-	bool isFallDefaultTarget() const { return SwitchStmt == kind; }
-
-	ast::Label useContExit() { assert( kind <= WhileStmt ); return useTarget(secondTarget); }
-	ast::Label useBreakExit() { assert( CaseStmt != kind ); return useTarget(firstTarget); }
-	ast::Label useFallExit() { assert( CaseStmt == kind );  return useTarget(firstTarget); }
-	ast::Label useFallDefaultExit() { assert( SwitchStmt == kind ); return useTarget(secondTarget); }
-
-	bool isContUsed() const { assert( kind <= WhileStmt ); return secondTarget.used; }
-	bool isBreakUsed() const { assert( CaseStmt != kind ); return firstTarget.used; }
-	bool isFallUsed() const { assert( CaseStmt == kind ); return firstTarget.used; }
-	bool isFallDefaultUsed() const { assert( SwitchStmt == kind ); return secondTarget.used; }
+  public:
+	Entry( const ForStmt * stmt, Label breakExit, Label contExit ) :
+		stmt( stmt ), firstTarget( breakExit ), secondTarget( contExit ), kind( ForStmtK ) {}
+	Entry( const WhileDoStmt * stmt, Label breakExit, Label contExit ) :
+		stmt( stmt ), firstTarget( breakExit ), secondTarget( contExit ), kind( WhileDoStmtK ) {}
+	Entry( const CompoundStmt *stmt, Label breakExit ) :
+		stmt( stmt ), firstTarget( breakExit ), secondTarget(), kind( CompoundStmtK ) {}
+	Entry( const IfStmt *stmt, Label breakExit ) :
+		stmt( stmt ), firstTarget( breakExit ), secondTarget(), kind( IfStmtK ) {}
+	Entry( const CaseStmt *stmt, Label fallExit ) :
+		stmt( stmt ), firstTarget( fallExit ), secondTarget(), kind( CaseStmtK ) {}
+	Entry( const SwitchStmt *stmt, Label breakExit, Label fallDefaultExit ) :
+		stmt( stmt ), firstTarget( breakExit ), secondTarget( fallDefaultExit ), kind( SwitchStmtK ) {}
+	Entry( const TryStmt *stmt, Label breakExit ) :
+		stmt( stmt ), firstTarget( breakExit ), secondTarget(), kind( TryStmtK ) {}
+
+	bool isContTarget() const { return kind <= WhileDoStmtK; }
+	bool isBreakTarget() const { return kind != CaseStmtK; }
+	bool isFallTarget() const { return kind == CaseStmtK; }
+	bool isFallDefaultTarget() const { return kind == SwitchStmtK; }
+
+	// These routines set a target as being "used" by a BranchStmt
+	Label useContExit() { assert( kind <= WhileDoStmtK ); return useTarget(secondTarget); }
+	Label useBreakExit() { assert( kind != CaseStmtK ); return useTarget(firstTarget); }
+	Label useFallExit() { assert( kind == CaseStmtK );  return useTarget(firstTarget); }
+	Label useFallDefaultExit() { assert( kind == SwitchStmtK ); return useTarget(secondTarget); }
+
+	// These routines check if a specific label for a statement is used by a BranchStmt
+	bool isContUsed() const { assert( kind <= WhileDoStmtK ); return secondTarget.used; }
+	bool isBreakUsed() const { assert( kind != CaseStmtK ); return firstTarget.used; }
+	bool isFallUsed() const { assert( kind == CaseStmtK ); return firstTarget.used; }
+	bool isFallDefaultUsed() const { assert( kind == SwitchStmtK ); return secondTarget.used; }
 	void seenDefault() { fallDefaultValid = false; }
 	bool isFallDefaultValid() const { return fallDefaultValid; }
 };
 
-// Helper predicates used in std::find_if calls (it doesn't take methods):
+// Helper predicates used in find_if calls (it doesn't take methods):
 bool isBreakTarget( const Entry & entry ) {
 	return entry.isBreakTarget();
@@ -103,32 +103,32 @@
 
 struct MultiLevelExitCore final :
-		public ast::WithVisitorRef<MultiLevelExitCore>,
-		public ast::WithShortCircuiting, public ast::WithGuards {
+	public WithVisitorRef<MultiLevelExitCore>,
+	public WithShortCircuiting, public WithGuards {
 	MultiLevelExitCore( const LabelToStmt & lt );
 
-	void previsit( const ast::FunctionDecl * );
-
-	const ast::CompoundStmt * previsit( const ast::CompoundStmt * );
-	const ast::BranchStmt * postvisit( const ast::BranchStmt * );
-	void previsit( const ast::WhileStmt * );
-	const ast::WhileStmt * postvisit( const ast::WhileStmt * );
-	void previsit( const ast::ForStmt * );
-	const ast::ForStmt * postvisit( const ast::ForStmt * );
-	const ast::CaseStmt * previsit( const ast::CaseStmt * );
-	void previsit( const ast::IfStmt * );
-	const ast::IfStmt * postvisit( const ast::IfStmt * );
-	void previsit( const ast::SwitchStmt * );
-	const ast::SwitchStmt * postvisit( const ast::SwitchStmt * );
-	void previsit( const ast::ReturnStmt * );
-	void previsit( const ast::TryStmt * );
-	void postvisit( const ast::TryStmt * );
-	void previsit( const ast::FinallyStmt * );
-
-	const ast::Stmt * mutateLoop( const ast::Stmt * body, Entry& );
+	void previsit( const FunctionDecl * );
+
+	const CompoundStmt * previsit( const CompoundStmt * );
+	const BranchStmt * postvisit( const BranchStmt * );
+	void previsit( const WhileDoStmt * );
+	const WhileDoStmt * postvisit( const WhileDoStmt * );
+	void previsit( const ForStmt * );
+	const ForStmt * postvisit( const ForStmt * );
+	const CaseStmt * previsit( const CaseStmt * );
+	void previsit( const IfStmt * );
+	const IfStmt * postvisit( const IfStmt * );
+	void previsit( const SwitchStmt * );
+	const SwitchStmt * postvisit( const SwitchStmt * );
+	void previsit( const ReturnStmt * );
+	void previsit( const TryStmt * );
+	void postvisit( const TryStmt * );
+	void previsit( const FinallyStmt * );
+
+	const Stmt * mutateLoop( const Stmt * body, Entry& );
 
 	const LabelToStmt & target_table;
-	std::set<ast::Label> fallthrough_labels;
-	std::vector<Entry> enclosing_control_structures;
-	ast::Label break_label;
+	set<Label> fallthrough_labels;
+	vector<Entry> enclosing_control_structures;
+	Label break_label;
 	bool inFinally;
 
@@ -138,17 +138,17 @@
 	const LoopNode * posthandleLoopStmt( const LoopNode * loopStmt );
 
-	std::list<ast::ptr<ast::Stmt>> fixBlock(
-		const std::list<ast::ptr<ast::Stmt>> & kids, bool caseClause );
+	list<ptr<Stmt>> fixBlock(
+		const list<ptr<Stmt>> & kids, bool caseClause );
 
 	template<typename UnaryPredicate>
 	auto findEnclosingControlStructure( UnaryPredicate pred ) {
-		return std::find_if( enclosing_control_structures.rbegin(),
-			enclosing_control_structures.rend(), pred );
+		return find_if( enclosing_control_structures.rbegin(),
+						enclosing_control_structures.rend(), pred );
 	}
 };
 
-ast::NullStmt * labelledNullStmt(
-		const CodeLocation & cl, const ast::Label & label ) {
-	return new ast::NullStmt( cl, std::vector<ast::Label>{ label } );
+NullStmt * labelledNullStmt(
+	const CodeLocation & cl, const Label & label ) {
+	return new NullStmt( cl, vector<Label>{ label } );
 }
 
@@ -158,26 +158,28 @@
 {}
 
-void MultiLevelExitCore::previsit( const ast::FunctionDecl * ) {
+void MultiLevelExitCore::previsit( const FunctionDecl * ) {
 	visit_children = false;
 }
 
-const ast::CompoundStmt * MultiLevelExitCore::previsit(
-		const ast::CompoundStmt * stmt ) {
+const CompoundStmt * MultiLevelExitCore::previsit(
+	const CompoundStmt * stmt ) {
 	visit_children = false;
-	bool isLabeled = !stmt->labels.empty();
+
+	// if the stmt is labelled then generate a label to check in postvisit if the label is used
+	bool isLabeled = ! stmt->labels.empty();
 	if ( isLabeled ) {
-		ast::Label breakLabel = LabelGenerator::newLabel( "blockBreak", stmt );
+		Label breakLabel = newLabel( "blockBreak", stmt );
 		enclosing_control_structures.emplace_back( stmt, breakLabel );
 		GuardAction( [this]() { enclosing_control_structures.pop_back(); } );
 	}
 
-	auto mutStmt = ast::mutate( stmt );
+	auto mutStmt = mutate( stmt );
 	// A child statement may set the break label.
-	mutStmt->kids = std::move( fixBlock( stmt->kids, false ) );
+	mutStmt->kids = move( fixBlock( stmt->kids, false ) );
 
 	if ( isLabeled ) {
-		assert( !enclosing_control_structures.empty() );
+		assert( ! enclosing_control_structures.empty() );
 		Entry & entry = enclosing_control_structures.back();
-		if ( !entry.useBreakExit().empty() ) {
+		if ( ! entry.useBreakExit().empty() ) {
 			break_label = entry.useBreakExit();
 		}
@@ -187,15 +189,15 @@
 
 size_t getUnusedIndex(
-		const ast::Stmt * stmt, const ast::Label & originalTarget ) {
+	const Stmt * stmt, const Label & originalTarget ) {
 	const size_t size = stmt->labels.size();
 
-	// If the label is empty, we can skip adding the unused attribute:
-	if ( originalTarget.empty() ) return size;
+	// If the label is empty, do not add unused attribute.
+  if ( originalTarget.empty() ) return size;
 
 	// Search for a label that matches the originalTarget.
 	for ( size_t i = 0 ; i < size ; ++i ) {
-		const ast::Label & label = stmt->labels[i];
+		const Label & label = stmt->labels[i];
 		if ( label == originalTarget ) {
-			for ( const ast::Attribute * attr : label.attributes ) {
+			for ( const Attribute * attr : label.attributes ) {
 				if ( attr->name == "unused" ) return size;
 			}
@@ -203,128 +205,128 @@
 		}
 	}
-	assertf( false, "Could not find label '%s' on statement %s",
-		originalTarget.name.c_str(), toString( stmt ).c_str() );
-}
-
-const ast::Stmt * addUnused(
-		const ast::Stmt * stmt, const ast::Label & originalTarget ) {
+	assertf( false, "CFA internal error: could not find label '%s' on statement %s",
+			 originalTarget.name.c_str(), toString( stmt ).c_str() );
+}
+
+const Stmt * addUnused(
+	const Stmt * stmt, const Label & originalTarget ) {
 	size_t i = getUnusedIndex( stmt, originalTarget );
 	if ( i == stmt->labels.size() ) {
 		return stmt;
 	}
-	ast::Stmt * mutStmt = ast::mutate( stmt );
-	mutStmt->labels[i].attributes.push_back( new ast::Attribute( "unused" ) );
+	Stmt * mutStmt = mutate( stmt );
+	mutStmt->labels[i].attributes.push_back( new Attribute( "unused" ) );
 	return mutStmt;
 }
 
-const ast::BranchStmt * MultiLevelExitCore::postvisit( const ast::BranchStmt * stmt ) {
-	std::vector<Entry>::reverse_iterator targetEntry =
+// This routine updates targets on enclosing control structures to indicate which
+//     label is used by the BranchStmt that is passed
+const BranchStmt * MultiLevelExitCore::postvisit( const BranchStmt * stmt ) {
+	vector<Entry>::reverse_iterator targetEntry =
 		enclosing_control_structures.rend();
+
+	// Labels on different stmts require different approaches to access
 	switch ( stmt->kind ) {
-	case ast::BranchStmt::Goto:
+	  case BranchStmt::Goto:
 		return stmt;
-	case ast::BranchStmt::Continue:
-	case ast::BranchStmt::Break: {
-		bool isContinue = stmt->kind == ast::BranchStmt::Continue;
-		// Handle unlabeled break and continue.
-		if ( stmt->target.empty() ) {
-			if ( isContinue ) {
-				targetEntry = findEnclosingControlStructure( isContinueTarget );
-			} else {
-				if ( enclosing_control_structures.empty() ) {
-					SemanticError( stmt->location,
-						"'break' outside a loop, 'switch', or labelled block" );
-				}
-				targetEntry = findEnclosingControlStructure( isBreakTarget );
-			}
-		// Handle labeled break and continue.
-		} else {
-			// Lookup label in table to find attached control structure.
-			targetEntry = findEnclosingControlStructure(
-				[ targetStmt = target_table.at(stmt->target) ](auto entry){
-					return entry.stmt == targetStmt;
-				} );
-		}
-		// Ensure that selected target is valid.
-		if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && !isContinueTarget( *targetEntry ) ) ) {
-			SemanticError(
-				stmt->location,
-				toString( (isContinue ? "'continue'" : "'break'"),
-					" target must be an enclosing ",
-					(isContinue ? "loop: " : "control structure: "),
-					stmt->originalTarget ) );
-		}
-		break;
-	}
-	case ast::BranchStmt::FallThrough: {
-		targetEntry = findEnclosingControlStructure( isFallthroughTarget );
-		// Check that target is valid.
-		if ( targetEntry == enclosing_control_structures.rend() ) {
-			SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
-		}
-		if ( !stmt->target.empty() ) {
-			// Labelled fallthrough: target must be a valid fallthough label.
-			if ( !fallthrough_labels.count( stmt->target ) ) {
-				SemanticError( stmt->location, toString( "'fallthrough' target must be a later case statement: ", stmt->originalTarget ) );
-			}
-			return new ast::BranchStmt(
-				stmt->location, ast::BranchStmt::Goto, stmt->originalTarget );
-		}
-		break;
-	}
-	case ast::BranchStmt::FallThroughDefault: {
-		targetEntry = findEnclosingControlStructure( isFallthroughDefaultTarget );
-
-		// Check that this is in a switch or choose statement.
-		if ( targetEntry == enclosing_control_structures.rend() ) {
-			SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
-		}
-
-		// Check that the switch or choose has a default clause.
-		auto switchStmt = strict_dynamic_cast< const ast::SwitchStmt * >(
-			targetEntry->stmt );
-		bool foundDefault = false;
-		for ( auto subStmt : switchStmt->stmts ) {
-			const ast::CaseStmt * caseStmt = subStmt.strict_as<ast::CaseStmt>();
-			if ( caseStmt->isDefault() ) {
-				foundDefault = true;
-				break;
-			}
-		}
-		if ( !foundDefault ) {
-			SemanticError( stmt->location, "'fallthrough default' must be enclosed in a 'switch' or 'choose' control structure with a 'default' clause" );
-		}
-		break;
-	}
-	default:
+	  case BranchStmt::Continue:
+	  case BranchStmt::Break: {
+		  bool isContinue = stmt->kind == BranchStmt::Continue;
+		  // Handle unlabeled break and continue.
+		  if ( stmt->target.empty() ) {
+			  if ( isContinue ) {
+				  targetEntry = findEnclosingControlStructure( isContinueTarget );
+			  } else {
+				  if ( enclosing_control_structures.empty() ) {
+					  SemanticError( stmt->location,
+									 "'break' outside a loop, 'switch', or labelled block" );
+				  }
+				  targetEntry = findEnclosingControlStructure( isBreakTarget );
+			  }
+			  // Handle labeled break and continue.
+		  } else {
+			  // Lookup label in table to find attached control structure.
+			  targetEntry = findEnclosingControlStructure(
+				  [ targetStmt = target_table.at(stmt->target) ](auto entry){
+					  return entry.stmt == targetStmt;
+				  } );
+		  }
+		  // Ensure that selected target is valid.
+		  if ( targetEntry == enclosing_control_structures.rend() || ( isContinue && ! isContinueTarget( *targetEntry ) ) ) {
+			  SemanticError( stmt->location, toString( (isContinue ? "'continue'" : "'break'"),
+							" target must be an enclosing ", (isContinue ? "loop: " : "control structure: "),
+							stmt->originalTarget ) );
+		  }
+		  break;
+	  }
+	  // handle fallthrough in case/switch stmts
+	  case BranchStmt::FallThrough: {
+		  targetEntry = findEnclosingControlStructure( isFallthroughTarget );
+		  // Check that target is valid.
+		  if ( targetEntry == enclosing_control_structures.rend() ) {
+			  SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
+		  }
+		  if ( ! stmt->target.empty() ) {
+			  // Labelled fallthrough: target must be a valid fallthough label.
+			  if ( ! fallthrough_labels.count( stmt->target ) ) {
+				  SemanticError( stmt->location, toString( "'fallthrough' target must be a later case statement: ",
+														   stmt->originalTarget ) );
+			  }
+			  return new BranchStmt( stmt->location, BranchStmt::Goto, stmt->originalTarget );
+		  }
+		  break;
+	  }
+	  case BranchStmt::FallThroughDefault: {
+		  targetEntry = findEnclosingControlStructure( isFallthroughDefaultTarget );
+
+		  // Check if in switch or choose statement.
+		  if ( targetEntry == enclosing_control_structures.rend() ) {
+			  SemanticError( stmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" );
+		  }
+
+		  // Check if switch or choose has default clause.
+		  auto switchStmt = strict_dynamic_cast< const SwitchStmt * >( targetEntry->stmt );
+		  bool foundDefault = false;
+		  for ( auto subStmt : switchStmt->stmts ) {
+			  const CaseStmt * caseStmt = subStmt.strict_as<CaseStmt>();
+			  if ( caseStmt->isDefault() ) {
+				  foundDefault = true;
+				  break;
+			  }
+		  }
+		  if ( ! foundDefault ) {
+			  SemanticError( stmt->location, "'fallthrough default' must be enclosed in a 'switch' or 'choose'"
+							 "control structure with a 'default' clause" );
+		  }
+		  break;
+	  }
+	  default:
 		assert( false );
 	}
 
-	// Branch error checks: get the appropriate label name:
-	// (This label will always be replaced.)
-	ast::Label exitLabel( CodeLocation(), "" );
+	// Branch error checks: get the appropriate label name, which is always replaced.
+	Label exitLabel( CodeLocation(), "" );
 	switch ( stmt->kind ) {
-	case ast::BranchStmt::Break:
-		assert( !targetEntry->useBreakExit().empty() );
+	  case BranchStmt::Break:
+		assert( ! targetEntry->useBreakExit().empty() );
 		exitLabel = targetEntry->useBreakExit();
 		break;
-	case ast::BranchStmt::Continue:
-		assert( !targetEntry->useContExit().empty() );
+	  case BranchStmt::Continue:
+		assert( ! targetEntry->useContExit().empty() );
 		exitLabel = targetEntry->useContExit();
 		break;
-	case ast::BranchStmt::FallThrough:
-		assert( !targetEntry->useFallExit().empty() );
+	  case BranchStmt::FallThrough:
+		assert( ! targetEntry->useFallExit().empty() );
 		exitLabel = targetEntry->useFallExit();
 		break;
-	case ast::BranchStmt::FallThroughDefault:
-		assert( !targetEntry->useFallDefaultExit().empty() );
+	  case BranchStmt::FallThroughDefault:
+		assert( ! targetEntry->useFallDefaultExit().empty() );
 		exitLabel = targetEntry->useFallDefaultExit();
 		// Check that fallthrough default comes before the default clause.
-		if ( !targetEntry->isFallDefaultValid() ) {
-			SemanticError( stmt->location,
-				"'fallthrough default' must precede the 'default' clause" );
+		if ( ! targetEntry->isFallDefaultValid() ) {
+			SemanticError( stmt->location, "'fallthrough default' must precede the 'default' clause" );
 		}
 		break;
-	default:
+	  default:
 		assert(0);
 	}
@@ -333,21 +335,21 @@
 	targetEntry->stmt = addUnused( targetEntry->stmt, stmt->originalTarget );
 
-	// Replace this with a goto to make later passes more uniform.
-	return new ast::BranchStmt( stmt->location, ast::BranchStmt::Goto, exitLabel );
-}
-
-void MultiLevelExitCore::previsit( const ast::WhileStmt * stmt ) {
+	// Replace with goto to make later passes more uniform.
+	return new BranchStmt( stmt->location, BranchStmt::Goto, exitLabel );
+}
+
+void MultiLevelExitCore::previsit( const WhileDoStmt * stmt ) {
 	return prehandleLoopStmt( stmt );
 }
 
-const ast::WhileStmt * MultiLevelExitCore::postvisit( const ast::WhileStmt * stmt ) {
+const WhileDoStmt * MultiLevelExitCore::postvisit( const WhileDoStmt * stmt ) {
 	return posthandleLoopStmt( stmt );
 }
 
-void MultiLevelExitCore::previsit( const ast::ForStmt * stmt ) {
+void MultiLevelExitCore::previsit( const ForStmt * stmt ) {
 	return prehandleLoopStmt( stmt );
 }
 
-const ast::ForStmt * MultiLevelExitCore::postvisit( const ast::ForStmt * stmt ) {
+const ForStmt * MultiLevelExitCore::postvisit( const ForStmt * stmt ) {
 	return posthandleLoopStmt( stmt );
 }
@@ -355,58 +357,55 @@
 // Mimic what the built-in push_front would do anyways. It is O(n).
 void push_front(
-		std::vector<ast::ptr<ast::Stmt>> & vec, const ast::Stmt * element ) {
+	vector<ptr<Stmt>> & vec, const Stmt * element ) {
 	vec.emplace_back( nullptr );
 	for ( size_t i = vec.size() - 1 ; 0 < i ; --i ) {
-		vec[ i ] = std::move( vec[ i - 1 ] );
+		vec[ i ] = move( vec[ i - 1 ] );
 	}
 	vec[ 0 ] = element;
 }
 
-const ast::CaseStmt * MultiLevelExitCore::previsit( const ast::CaseStmt * stmt ) {
+const CaseStmt * MultiLevelExitCore::previsit( const CaseStmt * stmt ) {
 	visit_children = false;
 
-	// If it is the default, mark the default as seen.
+	// If default, mark seen.
 	if ( stmt->isDefault() ) {
-		assert( !enclosing_control_structures.empty() );
+		assert( ! enclosing_control_structures.empty() );
 		enclosing_control_structures.back().seenDefault();
 	}
 
 	// The cond may not exist, but if it does update it now.
-	visitor->maybe_accept( stmt, &ast::CaseStmt::cond );
+	visitor->maybe_accept( stmt, &CaseStmt::cond );
 
 	// Just save the mutated node for simplicity.
-	ast::CaseStmt * mutStmt = ast::mutate( stmt );
-
-	ast::Label fallLabel = LabelGenerator::newLabel( "fallThrough", stmt );
-	if ( !mutStmt->stmts.empty() ) {
+	CaseStmt * mutStmt = mutate( stmt );
+
+	Label fallLabel = newLabel( "fallThrough", stmt );
+	if ( ! mutStmt->stmts.empty() ) {
 		// Ensure that the stack isn't corrupted by exceptions in fixBlock.
 		auto guard = makeFuncGuard(
 			[&](){ enclosing_control_structures.emplace_back( mutStmt, fallLabel ); },
 			[this](){ enclosing_control_structures.pop_back(); }
-		);
+			);
 
 		// These should already be in a block.
-		auto block = ast::mutate( mutStmt->stmts.front().strict_as<ast::CompoundStmt>() );
+		auto block = mutate( mutStmt->stmts.front().strict_as<CompoundStmt>() );
 		block->kids = fixBlock( block->kids, true );
 
 		// Add fallthrough label if necessary.
-		assert( !enclosing_control_structures.empty() );
+		assert( ! enclosing_control_structures.empty() );
 		Entry & entry = enclosing_control_structures.back();
 		if ( entry.isFallUsed() ) {
-			mutStmt->stmts.push_back(
-				labelledNullStmt( mutStmt->location, entry.useFallExit() ) );
-		}
-	}
-	assert( !enclosing_control_structures.empty() );
+			mutStmt->stmts.push_back( labelledNullStmt( mutStmt->location, entry.useFallExit() ) );
+		}
+	}
+	assert( ! enclosing_control_structures.empty() );
 	Entry & entry = enclosing_control_structures.back();
-	assertf( dynamic_cast< const ast::SwitchStmt * >( entry.stmt ),
-		"Control structure enclosing a case clause must be a switch, but is: %s",
-		toString( entry.stmt ).c_str() );
+	assertf( dynamic_cast< const SwitchStmt * >( entry.stmt ),
+			 "CFA internal error: control structure enclosing a case clause must be a switch, but is: %s",
+			 toString( entry.stmt ).c_str() );
 	if ( mutStmt->isDefault() ) {
 		if ( entry.isFallDefaultUsed() ) {
 			// Add fallthrough default label if necessary.
-			push_front( mutStmt->stmts, labelledNullStmt(
-				stmt->location, entry.useFallDefaultExit()
-			) );
+			push_front( mutStmt->stmts, labelledNullStmt( stmt->location, entry.useFallDefaultExit() ) );
 		}
 	}
@@ -414,8 +413,8 @@
 }
 
-void MultiLevelExitCore::previsit( const ast::IfStmt * stmt ) {
-	bool labeledBlock = !stmt->labels.empty();
+void MultiLevelExitCore::previsit( const IfStmt * stmt ) {
+	bool labeledBlock = ! stmt->labels.empty();
 	if ( labeledBlock ) {
-		ast::Label breakLabel = LabelGenerator::newLabel( "blockBreak", stmt );
+		Label breakLabel = newLabel( "blockBreak", stmt );
 		enclosing_control_structures.emplace_back( stmt, breakLabel );
 		GuardAction( [this](){ enclosing_control_structures.pop_back(); } );
@@ -423,9 +422,9 @@
 }
 
-const ast::IfStmt * MultiLevelExitCore::postvisit( const ast::IfStmt * stmt ) {
-	bool labeledBlock = !stmt->labels.empty();
+const IfStmt * MultiLevelExitCore::postvisit( const IfStmt * stmt ) {
+	bool labeledBlock = ! stmt->labels.empty();
 	if ( labeledBlock ) {
 		auto this_label = enclosing_control_structures.back().useBreakExit();
-		if ( !this_label.empty() ) {
+		if ( ! this_label.empty() ) {
 			break_label = this_label;
 		}
@@ -434,29 +433,26 @@
 }
 
-bool isDefaultCase( const ast::ptr<ast::Stmt> & stmt ) {
-	const ast::CaseStmt * caseStmt = stmt.strict_as<ast::CaseStmt>();
+bool isDefaultCase( const ptr<Stmt> & stmt ) {
+	const CaseStmt * caseStmt = stmt.strict_as<CaseStmt>();
 	return caseStmt->isDefault();
 }
 
-void MultiLevelExitCore::previsit( const ast::SwitchStmt * stmt ) {
-	ast::Label label = LabelGenerator::newLabel( "switchBreak", stmt );
-	auto it = std::find_if( stmt->stmts.rbegin(), stmt->stmts.rend(), isDefaultCase );
-
-	const ast::CaseStmt * defaultCase = it != stmt->stmts.rend()
-		? (it)->strict_as<ast::CaseStmt>() : nullptr;
-	ast::Label defaultLabel = defaultCase
-		? LabelGenerator::newLabel( "fallThroughDefault", defaultCase )
-		: ast::Label( stmt->location, "" );
+void MultiLevelExitCore::previsit( const SwitchStmt * stmt ) {
+	Label label = newLabel( "switchBreak", stmt );
+	auto it = find_if( stmt->stmts.rbegin(), stmt->stmts.rend(), isDefaultCase );
+
+	const CaseStmt * defaultCase = it != stmt->stmts.rend() ? (it)->strict_as<CaseStmt>() : nullptr;
+	Label defaultLabel = defaultCase ? newLabel( "fallThroughDefault", defaultCase ) : Label( stmt->location, "" );
 	enclosing_control_structures.emplace_back( stmt, label, defaultLabel );
 	GuardAction( [this]() { enclosing_control_structures.pop_back(); } );
 
-	// Collect valid labels for fallthrough. It starts with all labels at
-	// this level, then removed as we see them in traversal.
-	for ( const ast::Stmt * stmt : stmt->stmts ) {
-		auto * caseStmt = strict_dynamic_cast< const ast::CaseStmt * >( stmt );
+	// Collect valid labels for fallthrough. It starts with all labels at this level, then remove as each is seen during
+	// traversal.
+	for ( const Stmt * stmt : stmt->stmts ) {
+		auto * caseStmt = strict_dynamic_cast< const CaseStmt * >( stmt );
 		if ( caseStmt->stmts.empty() ) continue;
-		auto block = caseStmt->stmts.front().strict_as<ast::CompoundStmt>();
-		for ( const ast::Stmt * stmt : block->kids ) {
-			for ( const ast::Label & l : stmt->labels ) {
+		auto block = caseStmt->stmts.front().strict_as<CompoundStmt>();
+		for ( const Stmt * stmt : block->kids ) {
+			for ( const Label & l : stmt->labels ) {
 				fallthrough_labels.insert( l );
 			}
@@ -465,26 +461,24 @@
 }
 
-const ast::SwitchStmt * MultiLevelExitCore::postvisit( const ast::SwitchStmt * stmt ) {
-	assert( !enclosing_control_structures.empty() );
+const SwitchStmt * MultiLevelExitCore::postvisit( const SwitchStmt * stmt ) {
+	assert( ! enclosing_control_structures.empty() );
 	Entry & entry = enclosing_control_structures.back();
 	assert( entry.stmt == stmt );
 
-	// Only run if we need to generate the break label.
+	// Only run to generate the break label.
 	if ( entry.isBreakUsed() ) {
-		// To keep the switch statements uniform (all direct children of a
-		// SwitchStmt should be CastStmts), append the exit label and break
-		// to the last case, create a default case is there are no cases.
-		ast::SwitchStmt * mutStmt = ast::mutate( stmt );
+		// To keep the switch statements uniform (all direct children of a SwitchStmt should be CastStmts), append the
+		// exit label and break to the last case, create a default case if no cases.
+		SwitchStmt * mutStmt = mutate( stmt );
 		if ( mutStmt->stmts.empty() ) {
-			mutStmt->stmts.push_back( new ast::CaseStmt(
-				mutStmt->location, nullptr, {} ));
-		}
-
-		auto caseStmt = mutStmt->stmts.back().strict_as<ast::CaseStmt>();
-		auto mutCase = ast::mutate( caseStmt );
+			mutStmt->stmts.push_back( new CaseStmt( mutStmt->location, nullptr, {} ) );
+		}
+
+		auto caseStmt = mutStmt->stmts.back().strict_as<CaseStmt>();
+		auto mutCase = mutate( caseStmt );
 		mutStmt->stmts.back() = mutCase;
 
-		ast::Label label( mutCase->location, "breakLabel" );
-		auto branch = new ast::BranchStmt( mutCase->location, ast::BranchStmt::Break, label );
+		Label label( mutCase->location, "breakLabel" );
+		auto branch = new BranchStmt( mutCase->location, BranchStmt::Break, label );
 		branch->labels.push_back( entry.useBreakExit() );
 		mutCase->stmts.push_back( branch );
@@ -495,5 +489,5 @@
 }
 
-void MultiLevelExitCore::previsit( const ast::ReturnStmt * stmt ) {
+void MultiLevelExitCore::previsit( const ReturnStmt * stmt ) {
 	if ( inFinally ) {
 		SemanticError( stmt->location, "'return' may not appear in a finally clause" );
@@ -501,8 +495,8 @@
 }
 
-void MultiLevelExitCore::previsit( const ast::TryStmt * stmt ) {
-	bool isLabeled = !stmt->labels.empty();
+void MultiLevelExitCore::previsit( const TryStmt * stmt ) {
+	bool isLabeled = ! stmt->labels.empty();
 	if ( isLabeled ) {
-		ast::Label breakLabel = LabelGenerator::newLabel( "blockBreak", stmt );
+		Label breakLabel = newLabel( "blockBreak", stmt );
 		enclosing_control_structures.emplace_back( stmt, breakLabel );
 		GuardAction([this](){ enclosing_control_structures.pop_back(); } );
@@ -510,9 +504,9 @@
 }
 
-void MultiLevelExitCore::postvisit( const ast::TryStmt * stmt ) {
-	bool isLabeled = !stmt->labels.empty();
+void MultiLevelExitCore::postvisit( const TryStmt * stmt ) {
+	bool isLabeled = ! stmt->labels.empty();
 	if ( isLabeled ) {
 		auto this_label = enclosing_control_structures.back().useBreakExit();
-		if ( !this_label.empty() ) {
+		if ( ! this_label.empty() ) {
 			break_label = this_label;
 		}
@@ -520,23 +514,30 @@
 }
 
-void MultiLevelExitCore::previsit( const ast::FinallyStmt * ) {
-	GuardAction([this, old = std::move(enclosing_control_structures)](){
-		enclosing_control_structures = std::move(old);
-	});
-	enclosing_control_structures = std::vector<Entry>();
+void MultiLevelExitCore::previsit( const FinallyStmt * ) {
+	GuardAction([this, old = move( enclosing_control_structures)](){ enclosing_control_structures = move(old); });
+	enclosing_control_structures = vector<Entry>();
 	GuardValue( inFinally ) = true;
 }
 
-const ast::Stmt * MultiLevelExitCore::mutateLoop(
-		const ast::Stmt * body, Entry & entry ) {
+const Stmt * MultiLevelExitCore::mutateLoop(
+	const Stmt * body, Entry & entry ) {
 	if ( entry.isBreakUsed() ) {
 		break_label = entry.useBreakExit();
 	}
 
+	// if continue is used insert a continue label into the back of the body of the loop
 	if ( entry.isContUsed() ) {
-		ast::CompoundStmt * new_body = new ast::CompoundStmt( body->location );
+		CompoundStmt * new_body = new CompoundStmt( body->location );
+		// {}
 		new_body->kids.push_back( body );
+		// {
+		//  body
+		// }
 		new_body->kids.push_back(
 			labelledNullStmt( body->location, entry.useContExit() ) );
+		// {
+		//  body
+		//  ContinueLabel: {}
+		// }
 		return new_body;
 	}
@@ -549,7 +550,11 @@
 	// Remember is loop before going onto mutate the body.
 	// The labels will be folded in if they are used.
-	ast::Label breakLabel = LabelGenerator::newLabel( "loopBreak", loopStmt );
-	ast::Label contLabel = LabelGenerator::newLabel( "loopContinue", loopStmt );
+	Label breakLabel = newLabel( "loopBreak", loopStmt );
+	Label contLabel = newLabel( "loopContinue", loopStmt );
 	enclosing_control_structures.emplace_back( loopStmt, breakLabel, contLabel );
+	// labels are added temporarily to see if they are used and then added permanently in postvisit if ther are used
+	// children will tag labels as being used during their traversal which occurs before postvisit
+
+	// GuardAction calls the lambda after the node is done being visited
 	GuardAction( [this](){ enclosing_control_structures.pop_back(); } );
 }
@@ -557,25 +562,27 @@
 template<typename LoopNode>
 const LoopNode * MultiLevelExitCore::posthandleLoopStmt( const LoopNode * loopStmt ) {
-	assert( !enclosing_control_structures.empty() );
+	assert( ! enclosing_control_structures.empty() );
 	Entry & entry = enclosing_control_structures.back();
 	assert( entry.stmt == loopStmt );
 
-	// Now we check if the labels are used and add them if so.
-	return ast::mutate_field(
-		loopStmt, &LoopNode::body, mutateLoop( loopStmt->body, entry ) );
-}
-
-std::list<ast::ptr<ast::Stmt>> MultiLevelExitCore::fixBlock(
-		const std::list<ast::ptr<ast::Stmt>> & kids, bool is_case_clause ) {
-	// Unfortunately we can't use the automatic error collection.
+	// Now check if the labels are used and add them if so.
+	return mutate_field( loopStmt, &LoopNode::body, mutateLoop( loopStmt->body, entry ) );
+	// this call to mutate_field compares loopStmt->body and the result of mutateLoop
+	// 		if they are the same the node isn't mutated, if they differ then the new mutated node is returned
+	// 		the stmts will only differ if a label is used
+}
+
+list<ptr<Stmt>> MultiLevelExitCore::fixBlock(
+	const list<ptr<Stmt>> & kids, bool is_case_clause ) {
+	// Unfortunately cannot use automatic error collection.
 	SemanticErrorException errors;
 
-	std::list<ast::ptr<ast::Stmt>> ret;
+	list<ptr<Stmt>> ret;
 
 	// Manually visit each child.
-	for ( const ast::ptr<ast::Stmt> & kid : kids ) {
+	for ( const ptr<Stmt> & kid : kids ) {
 		if ( is_case_clause ) {
 			// Once a label is seen, it's no longer a valid for fallthrough.
-			for ( const ast::Label & l : kid->labels ) {
+			for ( const Label & l : kid->labels ) {
 				fallthrough_labels.erase( l );
 			}
@@ -588,12 +595,11 @@
 		}
 
-		if ( !break_label.empty() ) {
-			ret.push_back(
-				labelledNullStmt( ret.back()->location, break_label ) );
-			break_label = ast::Label( CodeLocation(), "" );
-		}
-	}
-
-	if ( !errors.isEmpty() ) {
+		if ( ! break_label.empty() ) {
+			ret.push_back( labelledNullStmt( ret.back()->location, break_label ) );
+			break_label = Label( CodeLocation(), "" );
+		}
+	}
+
+	if ( ! errors.isEmpty() ) {
 		throw errors;
 	}
@@ -601,15 +607,12 @@
 }
 
-} // namespace
-
-const ast::CompoundStmt * multiLevelExitUpdate(
-    	const ast::CompoundStmt * stmt,
-		const LabelToStmt & labelTable ) {
+const CompoundStmt * multiLevelExitUpdate(
+	const CompoundStmt * stmt,
+	const LabelToStmt & labelTable ) {
 	// Must start in the body, so FunctionDecls can be a stopping point.
-	ast::Pass<MultiLevelExitCore> visitor( labelTable );
-	const ast::CompoundStmt * ret = stmt->accept( visitor );
+	Pass<MultiLevelExitCore> visitor( labelTable );
+	const CompoundStmt * ret = stmt->accept( visitor );
 	return ret;
 }
-
 } // namespace ControlStruct
 
Index: src/ControlStruct/MultiLevelExit.hpp
===================================================================
--- src/ControlStruct/MultiLevelExit.hpp	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ControlStruct/MultiLevelExit.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Andrew Beach
 // Created On       : Mon Nov  1 13:49:00 2021
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Nov  8 10:53:00 2021
-// Update Count     : 3
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon Jan 31 22:34:06 2022
+// Update Count     : 6
 //
 
@@ -19,17 +19,14 @@
 
 namespace ast {
-	class CompoundStmt;
-	class Label;
-	class Stmt;
+class CompoundStmt;
+class Label;
+class Stmt;
 }
 
 namespace ControlStruct {
-
 using LabelToStmt = std::map<ast::Label, const ast::Stmt *>;
 
-/// Mutate a function body to handle multi-level exits.
-const ast::CompoundStmt * multiLevelExitUpdate(
-	const ast::CompoundStmt *, const LabelToStmt & );
-
+// Mutate a function body to handle multi-level exits.
+const ast::CompoundStmt * multiLevelExitUpdate(	const ast::CompoundStmt *, const LabelToStmt & );
 }
 
Index: src/ControlStruct/module.mk
===================================================================
--- src/ControlStruct/module.mk	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ControlStruct/module.mk	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,7 +10,7 @@
 ## Author           : Richard C. Bilson
 ## Created On       : Mon Jun  1 17:49:17 2015
-## Last Modified By : Henry Xue
-## Last Modified On : Tue Jul 20 04:10:50 2021
-## Update Count     : 5
+## Last Modified By : Peter A. Buhr
+## Last Modified On : Sat Jan 29 12:04:19 2022
+## Update Count     : 7
 ###############################################################################
 
@@ -22,8 +22,12 @@
 	ControlStruct/ForExprMutator.cc \
 	ControlStruct/ForExprMutator.h \
+	ControlStruct/HoistControlDecls.cpp \
+	ControlStruct/HoistControlDecls.hpp \
 	ControlStruct/LabelFixer.cc \
 	ControlStruct/LabelFixer.h \
 	ControlStruct/LabelGenerator.cc \
 	ControlStruct/LabelGenerator.h \
+	ControlStruct/LabelGeneratorNew.cpp \
+	ControlStruct/LabelGeneratorNew.hpp \
 	ControlStruct/MLEMutator.cc \
 	ControlStruct/MLEMutator.h \
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/InitTweak/InitTweak.cc	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Fri May 13 11:26:36 2016
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri Nov 19 19:22:00 2021
-// Update Count     : 19
+// Last Modified On : Mon Dec  6 13:21:00 2021
+// Update Count     : 20
 //
 
@@ -1191,14 +1191,30 @@
 	}
 
-	bool isCopyFunction( const ast::FunctionDecl * decl ) {
-		const ast::FunctionType * ftype = decl->type;
-		if ( ftype->params.size() != 2 ) return false;
-
-		const ast::Type * t1 = getPointerBase( ftype->params.front() );
-		if ( ! t1 ) return false;
-		const ast::Type * t2 = ftype->params.back();
-
-		return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable{} );
-	}
+bool isAssignment( const ast::FunctionDecl * decl ) {
+	return isAssignment( decl->name ) && isCopyFunction( decl );
+}
+
+bool isDestructor( const ast::FunctionDecl * decl ) {
+	return isDestructor( decl->name );
+}
+
+bool isDefaultConstructor( const ast::FunctionDecl * decl ) {
+	return isConstructor( decl->name ) && 1 == decl->params.size();
+}
+
+bool isCopyConstructor( const ast::FunctionDecl * decl ) {
+	return isConstructor( decl->name ) && 2 == decl->params.size();
+}
+
+bool isCopyFunction( const ast::FunctionDecl * decl ) {
+	const ast::FunctionType * ftype = decl->type;
+	if ( ftype->params.size() != 2 ) return false;
+
+	const ast::Type * t1 = getPointerBase( ftype->params.front() );
+	if ( ! t1 ) return false;
+	const ast::Type * t2 = ftype->params.back();
+
+	return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable{} );
+}
 
 	const FunctionDecl * isAssignment( const Declaration * decl ) {
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/InitTweak/InitTweak.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Fri May 13 11:26:36 2016
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri Nov 19 14:18:00 2021
-// Update Count     : 7
+// Last Modified On : Mon Dec  6 13:20:00 2021
+// Update Count     : 8
 //
 
@@ -31,4 +31,8 @@
 	const FunctionDecl * isCopyConstructor( const Declaration * decl );
 	const FunctionDecl * isCopyFunction( const Declaration * decl, const std::string & fname );
+	bool isAssignment( const ast::FunctionDecl * decl );
+	bool isDestructor( const ast::FunctionDecl * decl );
+	bool isDefaultConstructor( const ast::FunctionDecl * decl );
+	bool isCopyConstructor( const ast::FunctionDecl * decl );
 	bool isCopyFunction( const ast::FunctionDecl * decl );
 
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/Parser/ParseNode.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Sat May 16 13:28:16 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Jul 14 17:28:53 2021
-// Update Count     : 900
+// Last Modified On : Wed Feb  2 09:15:49 2022
+// Update Count     : 905
 //
 
@@ -390,6 +390,6 @@
 Statement * build_expr( ExpressionNode * ctl );
 
-struct IfCtrl {
-	IfCtrl( DeclarationNode * decl, ExpressionNode * condition ) :
+struct CondCtl {
+	CondCtl( DeclarationNode * decl, ExpressionNode * condition ) :
 		init( decl ? new StatementNode( decl ) : nullptr ), condition( condition ) {}
 
@@ -409,12 +409,12 @@
 };
 
-Expression * build_if_control( IfCtrl * ctl, std::list< Statement * > & init );
-Statement * build_if( IfCtrl * ctl, StatementNode * then_stmt, StatementNode * else_stmt );
+Expression * build_if_control( CondCtl * ctl, std::list< Statement * > & init );
+Statement * build_if( CondCtl * ctl, StatementNode * then, StatementNode * else_ );
 Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt );
 Statement * build_case( ExpressionNode * ctl );
 Statement * build_default();
-Statement * build_while( IfCtrl * ctl, StatementNode * stmt );
-Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt );
-Statement * build_for( ForCtrl * forctl, StatementNode * stmt );
+Statement * build_while( CondCtl * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );
+Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ = nullptr );
+Statement * build_for( ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ = nullptr );
 Statement * build_branch( BranchStmt::Type kind );
 Statement * build_branch( std::string * identifier, BranchStmt::Type kind );
@@ -424,6 +424,6 @@
 Statement * build_resume( ExpressionNode * ctl );
 Statement * build_resume_at( ExpressionNode * ctl , ExpressionNode * target );
-Statement * build_try( StatementNode * try_stmt, StatementNode * catch_stmt, StatementNode * finally_stmt );
-Statement * build_catch( CatchStmt::Kind kind, DeclarationNode *decl, ExpressionNode *cond, StatementNode *body );
+Statement * build_try( StatementNode * try_, StatementNode * catch_, StatementNode * finally_ );
+Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body );
 Statement * build_finally( StatementNode * stmt );
 Statement * build_compound( StatementNode * first );
Index: src/Parser/StatementNode.cc
===================================================================
--- src/Parser/StatementNode.cc	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/Parser/StatementNode.cc	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -5,11 +5,12 @@
 // file "LICENCE" distributed with Cforall.
 //
-// StatementNode.cc --
+// StatementNode.cc -- Transform from parse data-structures to AST data-structures, usually deleting the parse
+//     data-structure after the transformation.
 //
 // Author           : Rodolfo G. Esteves
 // Created On       : Sat May 16 14:59:41 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Oct 24 04:20:55 2020
-// Update Count     : 383
+// Last Modified On : Wed Feb  2 20:29:30 2022
+// Update Count     : 425
 //
 
@@ -63,5 +64,5 @@
 	// convert from StatementNode list to Statement list
 	StatementNode * node = dynamic_cast< StatementNode * >(prev);
-	std::list< Statement * > stmts;
+	list< Statement * > stmts;
 	buildMoveList( stmt, stmts );
 	// splice any new Statements to end of current Statements
@@ -78,5 +79,5 @@
 } // build_expr
 
-Expression * build_if_control( IfCtrl * ctl, std::list< Statement * > & init ) {
+Expression * build_if_control( CondCtl * ctl, list< Statement * > & init ) {
 	if ( ctl->init != 0 ) {
 		buildMoveList( ctl->init, init );
@@ -100,28 +101,29 @@
 } // build_if_control
 
-Statement * build_if( IfCtrl * ctl, StatementNode * then_stmt, StatementNode * else_stmt ) {
-	Statement * thenb, * elseb = nullptr;
-	std::list< Statement * > branches;
-	buildMoveList< Statement, StatementNode >( then_stmt, branches );
-	assert( branches.size() == 1 );
-	thenb = branches.front();
-
-	if ( else_stmt ) {
-		std::list< Statement * > branches;
-		buildMoveList< Statement, StatementNode >( else_stmt, branches );
-		assert( branches.size() == 1 );
-		elseb = branches.front();
-	} // if
-
-	std::list< Statement * > init;
-	Expression * cond = build_if_control( ctl, init );
-	return new IfStmt( cond, thenb, elseb, init );
+Statement * build_if( CondCtl * ctl, StatementNode * then, StatementNode * else_ ) {
+	list< Statement * > astinit;						// maybe empty
+	Expression * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
+
+	Statement * astthen, * astelse = nullptr;
+	list< Statement * > aststmt;
+	buildMoveList< Statement, StatementNode >( then, aststmt );
+	assert( aststmt.size() == 1 );
+	astthen = aststmt.front();
+
+	if ( else_ ) {
+		list< Statement * > aststmt;
+		buildMoveList< Statement, StatementNode >( else_, aststmt );
+		assert( aststmt.size() == 1 );
+		astelse = aststmt.front();
+	} // if
+
+	return new IfStmt( astcond, astthen, astelse, astinit );
 } // build_if
 
 Statement * build_switch( bool isSwitch, ExpressionNode * ctl, StatementNode * stmt ) {
-	std::list< Statement * > branches;
-	buildMoveList< Statement, StatementNode >( stmt, branches );
-	if ( ! isSwitch ) {										// choose statement
-		for ( Statement * stmt : branches ) {
+	list< Statement * > aststmt;
+	buildMoveList< Statement, StatementNode >( stmt, aststmt );
+	if ( ! isSwitch ) {									// choose statement
+		for ( Statement * stmt : aststmt ) {
 			CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt );
 			if ( ! caseStmt->stmts.empty() ) {			// code after "case" => end of case list
@@ -131,57 +133,61 @@
 		} // for
 	} // if
-	// branches.size() == 0 for switch (...) {}, i.e., no declaration or statements
-	return new SwitchStmt( maybeMoveBuild< Expression >(ctl), branches );
+	// aststmt.size() == 0 for switch (...) {}, i.e., no declaration or statements
+	return new SwitchStmt( maybeMoveBuild< Expression >(ctl), aststmt );
 } // build_switch
 
 Statement * build_case( ExpressionNode * ctl ) {
-	std::list< Statement * > branches;
-	return new CaseStmt( maybeMoveBuild< Expression >(ctl), branches );
+	return new CaseStmt( maybeMoveBuild< Expression >(ctl), {} ); // stmt starts empty and then added to
 } // build_case
 
 Statement * build_default() {
-	std::list< Statement * > branches;
-	return new CaseStmt( nullptr, branches, true );
+	return new CaseStmt( nullptr, {}, true );			// stmt starts empty and then added to
 } // build_default
 
-Statement * build_while( IfCtrl * ctl, StatementNode * stmt ) {
-	std::list< Statement * > branches;
-	buildMoveList< Statement, StatementNode >( stmt, branches );
-	assert( branches.size() == 1 );
-
-	std::list< Statement * > init;
-	Expression * cond = build_if_control( ctl, init );
-	return new WhileStmt( cond, branches.front(), init, false );
+Statement * build_while( CondCtl * ctl, StatementNode * stmt, StatementNode * else_ ) {
+	list< Statement * > astinit;						// maybe empty
+	Expression * astcond = build_if_control( ctl, astinit ); // ctl deleted, cond/init set
+
+	list< Statement * > aststmt;						// loop body, compound created if empty
+	buildMoveList< Statement, StatementNode >( stmt, aststmt );
+	assert( aststmt.size() == 1 );
+
+	list< Statement * > astelse;						// else clause, maybe empty
+	buildMoveList< Statement, StatementNode >( else_, astelse );
+
+	return new WhileDoStmt( astcond, aststmt.front(), astelse.front(), astinit, false );
 } // build_while
 
-Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt ) {
-	std::list< Statement * > branches;
-	buildMoveList< Statement, StatementNode >( stmt, branches );
-	assert( branches.size() == 1 );
-
-	std::list< Statement * > init;
-	return new WhileStmt( notZeroExpr( maybeMoveBuild< Expression >(ctl) ), branches.front(), init, true );
+Statement * build_do_while( ExpressionNode * ctl, StatementNode * stmt, StatementNode * else_ ) {
+	list< Statement * > aststmt;						// loop body, compound created if empty
+	buildMoveList< Statement, StatementNode >( stmt, aststmt );
+	assert( aststmt.size() == 1 );						// compound created if empty
+
+	list< Statement * > astelse;						// else clause, maybe empty
+	buildMoveList< Statement, StatementNode >( else_, astelse );
+
+	// do-while cannot have declarations in the contitional, so init is always empty
+	return new WhileDoStmt( notZeroExpr( maybeMoveBuild< Expression >(ctl) ), aststmt.front(), astelse.front(), {}, true );
 } // build_do_while
 
-Statement * build_for( ForCtrl * forctl, StatementNode * stmt ) {
-	std::list< Statement * > branches;
-	buildMoveList< Statement, StatementNode >( stmt, branches );
-	assert( branches.size() == 1 );
-
-	std::list< Statement * > init;
-	if ( forctl->init != 0 ) {
-		buildMoveList( forctl->init, init );
-	} // if
-
-	Expression * cond = 0;
-	if ( forctl->condition != 0 )
-		cond = notZeroExpr( maybeMoveBuild< Expression >(forctl->condition) );
-
-	Expression * incr = 0;
-	if ( forctl->change != 0 )
-		incr = maybeMoveBuild< Expression >(forctl->change);
-
+Statement * build_for( ForCtrl * forctl, StatementNode * stmt, StatementNode * else_ ) {
+	list< Statement * > astinit;						// maybe empty
+	buildMoveList( forctl->init, astinit );
+
+	Expression * astcond = nullptr;						// maybe empty
+	astcond = notZeroExpr( maybeMoveBuild< Expression >(forctl->condition) );
+
+	Expression * astincr = nullptr;						// maybe empty
+	astincr = maybeMoveBuild< Expression >(forctl->change);
 	delete forctl;
-	return new ForStmt( init, cond, incr, branches.front() );
+
+	list< Statement * > aststmt;						// loop body, compound created if empty
+	buildMoveList< Statement, StatementNode >( stmt, aststmt );
+	assert( aststmt.size() == 1 );
+
+	list< Statement * > astelse;						// else clause, maybe empty
+	buildMoveList< Statement, StatementNode >( else_, astelse );
+
+	return new ForStmt( astinit, astcond, astincr, aststmt.front(), astelse.front() );
 } // build_for
 
@@ -191,5 +197,5 @@
 } // build_branch
 
-Statement * build_branch( std::string * identifier, BranchStmt::Type kind ) {
+Statement * build_branch( string * identifier, BranchStmt::Type kind ) {
 	Statement * ret = new BranchStmt( * identifier, kind );
 	delete identifier; 									// allocated by lexer
@@ -202,5 +208,5 @@
 
 Statement * build_return( ExpressionNode * ctl ) {
-	std::list< Expression * > exps;
+	list< Expression * > exps;
 	buildMoveList( ctl, exps );
 	return new ReturnStmt( exps.size() > 0 ? exps.back() : nullptr );
@@ -208,14 +214,14 @@
 
 Statement * build_throw( ExpressionNode * ctl ) {
-	std::list< Expression * > exps;
+	list< Expression * > exps;
 	buildMoveList( ctl, exps );
-	assertf( exps.size() < 2, "This means we are leaking memory");
+	assertf( exps.size() < 2, "CFA internal error: leaking memory" );
 	return new ThrowStmt( ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr );
 } // build_throw
 
 Statement * build_resume( ExpressionNode * ctl ) {
-	std::list< Expression * > exps;
+	list< Expression * > exps;
 	buildMoveList( ctl, exps );
-	assertf( exps.size() < 2, "This means we are leaking memory");
+	assertf( exps.size() < 2, "CFA internal error: leaking memory" );
 	return new ThrowStmt( ThrowStmt::Resume, !exps.empty() ? exps.back() : nullptr );
 } // build_resume
@@ -227,24 +233,24 @@
 } // build_resume_at
 
-Statement * build_try( StatementNode * try_stmt, StatementNode * catch_stmt, StatementNode * finally_stmt ) {
-	std::list< CatchStmt * > branches;
-	buildMoveList< CatchStmt, StatementNode >( catch_stmt, branches );
-	CompoundStmt * tryBlock = strict_dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >(try_stmt));
-	FinallyStmt * finallyBlock = dynamic_cast< FinallyStmt * >(maybeMoveBuild< Statement >(finally_stmt) );
-	return new TryStmt( tryBlock, branches, finallyBlock );
+Statement * build_try( StatementNode * try_, StatementNode * catch_, StatementNode * finally_ ) {
+	list< CatchStmt * > aststmt;
+	buildMoveList< CatchStmt, StatementNode >( catch_, aststmt );
+	CompoundStmt * tryBlock = strict_dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >(try_));
+	FinallyStmt * finallyBlock = dynamic_cast< FinallyStmt * >(maybeMoveBuild< Statement >(finally_) );
+	return new TryStmt( tryBlock, aststmt, finallyBlock );
 } // build_try
 
 Statement * build_catch( CatchStmt::Kind kind, DeclarationNode * decl, ExpressionNode * cond, StatementNode * body ) {
-	std::list< Statement * > branches;
-	buildMoveList< Statement, StatementNode >( body, branches );
-	assert( branches.size() == 1 );
-	return new CatchStmt( kind, maybeMoveBuild< Declaration >(decl), maybeMoveBuild< Expression >(cond), branches.front() );
+	list< Statement * > aststmt;
+	buildMoveList< Statement, StatementNode >( body, aststmt );
+	assert( aststmt.size() == 1 );
+	return new CatchStmt( kind, maybeMoveBuild< Declaration >(decl), maybeMoveBuild< Expression >(cond), aststmt.front() );
 } // build_catch
 
 Statement * build_finally( StatementNode * stmt ) {
-	std::list< Statement * > branches;
-	buildMoveList< Statement, StatementNode >( stmt, branches );
-	assert( branches.size() == 1 );
-	return new FinallyStmt( dynamic_cast< CompoundStmt * >( branches.front() ) );
+	list< Statement * > aststmt;
+	buildMoveList< Statement, StatementNode >( stmt, aststmt );
+	assert( aststmt.size() == 1 );
+	return new FinallyStmt( dynamic_cast< CompoundStmt * >( aststmt.front() ) );
 } // build_finally
 
@@ -254,5 +260,5 @@
 	node->type = type;
 
-	std::list< Statement * > stmts;
+	list< Statement * > stmts;
 	buildMoveList< Statement, StatementNode >( then, stmts );
 	if(!stmts.empty()) {
@@ -319,5 +325,5 @@
 } // build_waitfor_timeout
 
-WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when,  StatementNode * else_stmt, ExpressionNode * else_when ) {
+WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when,  StatementNode * else_, ExpressionNode * else_when ) {
 	auto node = new WaitForStmt();
 
@@ -326,5 +332,5 @@
 	node->timeout.condition = notZeroExpr( maybeMoveBuild<Expression>( when ) );
 
-	node->orelse.statement  = maybeMoveBuild<Statement >( else_stmt );
+	node->orelse.statement  = maybeMoveBuild<Statement >( else_ );
 	node->orelse.condition  = notZeroExpr( maybeMoveBuild<Expression>( else_when ) );
 
@@ -333,5 +339,5 @@
 
 Statement * build_with( ExpressionNode * exprs, StatementNode * stmt ) {
-	std::list< Expression * > e;
+	list< Expression * > e;
 	buildMoveList( exprs, e );
 	Statement * s = maybeMoveBuild<Statement>( stmt );
@@ -361,6 +367,6 @@
 
 Statement * build_asm( bool voltile, Expression * instruction, ExpressionNode * output, ExpressionNode * input, ExpressionNode * clobber, LabelNode * gotolabels ) {
-	std::list< Expression * > out, in;
-	std::list< ConstantExpr * > clob;
+	list< Expression * > out, in;
+	list< ConstantExpr * > clob;
 
 	buildMoveList( output, out );
@@ -375,5 +381,5 @@
 
 Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt ) {
-	std::list< Expression * > expList;
+	list< Expression * > expList;
 	buildMoveList( exprs, expList );
 	Statement * body = maybeMoveBuild<Statement>( stmt );
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/Parser/parser.yy	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Sat Sep  1 20:22:55 2001
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Oct 15 09:20:17 2021
-// Update Count     : 5163
+// Last Modified On : Tue Feb  1 11:06:13 2022
+// Update Count     : 5167
 //
 
@@ -238,5 +238,5 @@
 	WaitForStmt * wfs;
 	Expression * constant;
-	IfCtrl * ifctl;
+	CondCtl * ifctl;
 	ForCtrl * fctl;
 	enum OperKinds compop;
@@ -327,5 +327,5 @@
 %type<en> comma_expression				comma_expression_opt
 %type<en> argument_expression_list_opt	argument_expression_list	argument_expression			default_initializer_opt
-%type<ifctl> if_control_expression
+%type<ifctl> conditional_declaration
 %type<fctl> for_control_expression		for_control_expression_list
 %type<compop> inclexcl
@@ -1123,20 +1123,20 @@
 
 if_statement:
-	IF '(' if_control_expression ')' statement			%prec THEN
+	IF '(' conditional_declaration ')' statement		%prec THEN
 		// explicitly deal with the shift/reduce conflict on if/else
 		{ $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), nullptr ) ); }
-	| IF '(' if_control_expression ')' statement ELSE statement
+	| IF '(' conditional_declaration ')' statement ELSE statement
 		{ $$ = new StatementNode( build_if( $3, maybe_build_compound( $5 ), maybe_build_compound( $7 ) ) ); }
 	;
 
-if_control_expression:
+conditional_declaration:
 	comma_expression
-		{ $$ = new IfCtrl( nullptr, $1 ); }
+		{ $$ = new CondCtl( nullptr, $1 ); }
 	| c_declaration										// no semi-colon
-		{ $$ = new IfCtrl( $1, nullptr ); }
+		{ $$ = new CondCtl( $1, nullptr ); }
 	| cfa_declaration									// no semi-colon
-		{ $$ = new IfCtrl( $1, nullptr ); }
+		{ $$ = new CondCtl( $1, nullptr ); }
 	| declaration comma_expression						// semi-colon separated
-		{ $$ = new IfCtrl( $1, $2 ); }
+		{ $$ = new CondCtl( $1, $2 ); }
  	;
 
@@ -1193,9 +1193,10 @@
 iteration_statement:
 	WHILE '(' ')' statement								// CFA => while ( 1 )
-		{ $$ = new StatementNode( build_while( new IfCtrl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) ); }
-	| WHILE '(' if_control_expression ')' statement		%prec THEN
+		{ $$ = new StatementNode( build_while( new CondCtl( nullptr, new ExpressionNode( build_constantInteger( *new string( "1" ) ) ) ), maybe_build_compound( $4 ) ) ); }
+	| WHILE '(' conditional_declaration ')' statement	%prec THEN
 		{ $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ) ) ); }
-	| WHILE '(' if_control_expression ')' statement ELSE statement // CFA
-		{ SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
+	| WHILE '(' conditional_declaration ')' statement ELSE statement // CFA
+		// { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
+		{ $$ = new StatementNode( build_while( $3, maybe_build_compound( $5 ), $7 ) ); }
 	| DO statement WHILE '(' ')' ';'					// CFA => do while( 1 )
 		{ $$ = new StatementNode( build_do_while( new ExpressionNode( build_constantInteger( *new string( "1" ) ) ), maybe_build_compound( $2 ) ) ); }
@@ -1203,5 +1204,6 @@
 		{ $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ) ) ); }
 	| DO statement WHILE '(' comma_expression ')' ELSE statement // CFA
-		{ SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
+		// { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
+		{ $$ = new StatementNode( build_do_while( $5, maybe_build_compound( $2 ), $8 ) ); }
 	| FOR '(' ')' statement								// CFA => for ( ;; )
 		{ $$ = new StatementNode( build_for( new ForCtrl( (ExpressionNode * )nullptr, (ExpressionNode * )nullptr, (ExpressionNode * )nullptr ), maybe_build_compound( $4 ) ) ); }
@@ -1209,5 +1211,6 @@
 	  	{ $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
 	| FOR '(' for_control_expression_list ')' statement ELSE statement // CFA
-		{ SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
+		// { SemanticError( yylloc, "Loop default block is currently unimplemented." ); $$ = nullptr; }
+		{ $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ), $7 ) ); }
 	;
 
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/ResolvExpr/Resolver.cc	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Aaron B. Moss
 // Created On       : Sun May 17 12:17:01 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Fri Mar 27 11:58:00 2020
-// Update Count     : 242
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Tue Feb  1 16:27:14 2022
+// Update Count     : 245
 //
 
@@ -80,5 +80,5 @@
 		void previsit( AsmStmt * asmStmt );
 		void previsit( IfStmt * ifStmt );
-		void previsit( WhileStmt * whileStmt );
+		void previsit( WhileDoStmt * whileDoStmt );
 		void previsit( ForStmt * forStmt );
 		void previsit( SwitchStmt * switchStmt );
@@ -502,6 +502,6 @@
 	}
 
-	void Resolver_old::previsit( WhileStmt * whileStmt ) {
-		findIntegralExpression( whileStmt->condition, indexer );
+	void Resolver_old::previsit( WhileDoStmt * whileDoStmt ) {
+		findIntegralExpression( whileDoStmt->condition, indexer );
 	}
 
@@ -572,8 +572,8 @@
 
 	void Resolver_old::previsit( CatchStmt * catchStmt ) {
-		// Until we are very sure this invarent (ifs that move between passes have thenPart)
+		// Until we are very sure this invarent (ifs that move between passes have then)
 		// holds, check it. This allows a check for when to decode the mangling.
 		if ( IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body ) ) {
-			assert( ifStmt->thenPart );
+			assert( ifStmt->then );
 		}
 		// Encode the catchStmt so the condition can see the declaration.
@@ -588,11 +588,11 @@
 		// Decode the catchStmt so everything is stored properly.
 		IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body );
-		if ( nullptr != ifStmt && nullptr == ifStmt->thenPart ) {
+		if ( nullptr != ifStmt && nullptr == ifStmt->then ) {
 			assert( ifStmt->condition );
-			assert( ifStmt->elsePart );
+			assert( ifStmt->else_ );
 			catchStmt->cond = ifStmt->condition;
-			catchStmt->body = ifStmt->elsePart;
+			catchStmt->body = ifStmt->else_;
 			ifStmt->condition = nullptr;
-			ifStmt->elsePart = nullptr;
+			ifStmt->else_ = nullptr;
 			delete ifStmt;
 		}
@@ -1272,5 +1272,5 @@
 		const ast::AsmStmt *         previsit( const ast::AsmStmt * );
 		const ast::IfStmt *          previsit( const ast::IfStmt * );
-		const ast::WhileStmt *       previsit( const ast::WhileStmt * );
+		const ast::WhileDoStmt *       previsit( const ast::WhileDoStmt * );
 		const ast::ForStmt *         previsit( const ast::ForStmt * );
 		const ast::SwitchStmt *      previsit( const ast::SwitchStmt * );
@@ -1581,7 +1581,7 @@
 	}
 
-	const ast::WhileStmt * Resolver_new::previsit( const ast::WhileStmt * whileStmt ) {
+	const ast::WhileDoStmt * Resolver_new::previsit( const ast::WhileDoStmt * whileDoStmt ) {
 		return ast::mutate_field(
-			whileStmt, &ast::WhileStmt::cond, findIntegralExpression( whileStmt->cond, symtab ) );
+			whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, symtab ) );
 	}
 
@@ -1669,8 +1669,8 @@
 
 	const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) {
-		// Until we are very sure this invarent (ifs that move between passes have thenPart)
+		// Until we are very sure this invarent (ifs that move between passes have then)
 		// holds, check it. This allows a check for when to decode the mangling.
 		if ( auto ifStmt = catchStmt->body.as<ast::IfStmt>() ) {
-			assert( ifStmt->thenPart );
+			assert( ifStmt->then );
 		}
 		// Encode the catchStmt so the condition can see the declaration.
@@ -1687,10 +1687,10 @@
 		// Decode the catchStmt so everything is stored properly.
 		const ast::IfStmt * ifStmt = catchStmt->body.as<ast::IfStmt>();
-		if ( nullptr != ifStmt && nullptr == ifStmt->thenPart ) {
+		if ( nullptr != ifStmt && nullptr == ifStmt->then ) {
 			assert( ifStmt->cond );
-			assert( ifStmt->elsePart );
+			assert( ifStmt->else_ );
 			ast::CatchStmt * stmt = ast::mutate( catchStmt );
 			stmt->cond = ifStmt->cond;
-			stmt->body = ifStmt->elsePart;
+			stmt->body = ifStmt->else_;
 			// ifStmt should be implicately deleted here.
 			return stmt;
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/SymTab/Validate.cc	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -453,4 +453,9 @@
 	}
 
+	void decayForallPointers( std::list< Declaration * > & translationUnit ) {
+		PassVisitor<ForallPointerDecay_old> fpd;
+		acceptAll( translationUnit, fpd );
+	}
+
 	void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) {
 		validate_A( translationUnit );
@@ -470,5 +475,4 @@
 		type->accept( fpd );
 	}
-
 
 	void HoistTypeDecls::handleType( Type * type ) {
Index: src/SymTab/Validate.h
===================================================================
--- src/SymTab/Validate.h	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/SymTab/Validate.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -42,4 +42,5 @@
 	void validate_E( std::list< Declaration * > &translationUnit );
 	void validate_F( std::list< Declaration * > &translationUnit );
+	void decayForallPointers( std::list< Declaration * > & translationUnit );
 
 	const ast::Type * validateType(
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/SynTree/Mutator.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Mar 12 18:35:36 2021
-// Update Count     : 18
+// Last Modified On : Tue Feb  1 09:26:49 2022
+// Update Count     : 20
 //
 #pragma once
@@ -42,5 +42,5 @@
 	virtual Statement * mutate( DirectiveStmt * dirStmt ) = 0;
 	virtual Statement * mutate( IfStmt * ifStmt ) = 0;
-	virtual Statement * mutate( WhileStmt * whileStmt ) = 0;
+	virtual Statement * mutate( WhileDoStmt * whileDoStmt ) = 0;
 	virtual Statement * mutate( ForStmt * forStmt ) = 0;
 	virtual Statement * mutate( SwitchStmt * switchStmt ) = 0;
Index: src/SynTree/Statement.cc
===================================================================
--- src/SynTree/Statement.cc	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/SynTree/Statement.cc	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Jan 20 16:03:00 2020
-// Update Count     : 71
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Wed Feb  2 20:19:33 2022
+// Update Count     : 90
 //
 
@@ -29,10 +29,10 @@
 #include "SynTree/Label.h"         // for Label, operator<<
 
-using std::string;
-using std::endl;
-
-Statement::Statement( const std::list<Label> & labels ) : labels( labels ) {}
-
-void Statement::print( std::ostream & os, Indenter indent ) const {
+using namespace std;
+
+
+Statement::Statement( const list<Label> & labels ) : labels( labels ) {}
+
+void Statement::print( ostream & os, Indenter indent ) const {
 	if ( ! labels.empty() ) {
 		os << indent << "... Labels: {";
@@ -54,11 +54,11 @@
 }
 
-void ExprStmt::print( std::ostream & os, Indenter indent ) const {
-	os << "Expression Statement:" << endl << indent+1;
-	expr->print( os, indent+1 );
-}
-
-
-AsmStmt::AsmStmt( bool voltile, Expression * instruction, std::list<Expression *> output, std::list<Expression *> input, std::list<ConstantExpr *> clobber, std::list<Label> gotolabels ) : Statement(), voltile( voltile ), instruction( instruction ), output( output ), input( input ), clobber( clobber ), gotolabels( gotolabels ) {}
+void ExprStmt::print( ostream & os, Indenter indent ) const {
+	os << "Expression Statement:" << endl << indent + 1;
+	expr->print( os, indent + 1 );
+}
+
+
+AsmStmt::AsmStmt( bool voltile, Expression * instruction, const list<Expression *> output, const list<Expression *> input, const list<ConstantExpr *> clobber, const list<Label> gotolabels ) : Statement(), voltile( voltile ), instruction( instruction ), output( output ), input( input ), clobber( clobber ), gotolabels( gotolabels ) {}
 
 AsmStmt::AsmStmt( const AsmStmt & other ) : Statement( other ), voltile( other.voltile ), instruction( maybeClone( other.instruction ) ), gotolabels( other.gotolabels ) {
@@ -75,26 +75,26 @@
 }
 
-void AsmStmt::print( std::ostream & os, Indenter indent ) const {
+void AsmStmt::print( ostream & os, Indenter indent ) const {
 	os << "Assembler Statement:" << endl;
-	os << indent+1 << "instruction: " << endl << indent;
-	instruction->print( os, indent+1 );
+	os << indent + 1 << "instruction: " << endl << indent;
+	instruction->print( os, indent + 1 );
 	if ( ! output.empty() ) {
-		os << endl << indent+1 << "output: " << endl;
-		printAll( output, os, indent+1 );
+		os << endl << indent + 1 << "output: " << endl;
+		printAll( output, os, indent + 1 );
 	} // if
 	if ( ! input.empty() ) {
-		os << indent+1 << "input: " << endl;
-		printAll( input, os, indent+1 );
+		os << indent + 1 << "input: " << endl;
+		printAll( input, os, indent + 1 );
 	} // if
 	if ( ! clobber.empty() ) {
-		os << indent+1 << "clobber: " << endl;
-		printAll( clobber, os, indent+1 );
+		os << indent + 1 << "clobber: " << endl;
+		printAll( clobber, os, indent + 1 );
 	} // if
 }
 
 
-DirectiveStmt::DirectiveStmt( const std::string & directive ) : Statement(), directive( directive ) {}
-
-void DirectiveStmt::print( std::ostream & os, Indenter ) const {
+DirectiveStmt::DirectiveStmt( const string & directive ) : Statement(), directive( directive ) {}
+
+void DirectiveStmt::print( ostream & os, Indenter ) const {
 	os << "GCC Directive:" << directive << endl;
 }
@@ -120,10 +120,10 @@
 }
 
-void BranchStmt::print( std::ostream & os, Indenter indent ) const {
-	assert(type < 5);
+void BranchStmt::print( ostream & os, Indenter indent ) const {
+	assertf(type < BranchStmts, "CFA internal error: invalid branch statement" );
 	os << "Branch (" << brType[type] << ")" << endl ;
-	if ( target != "" ) os << indent+1 << "with target: " << target << endl;
-	if ( originalTarget != "" ) os << indent+1 << "with original target: " << originalTarget << endl;
-	if ( computedTarget != nullptr ) os << indent+1 << "with computed target: " << computedTarget << endl;
+	if ( target != "" ) os << indent + 1 << "with target: " << target << endl;
+	if ( originalTarget != "" ) os << indent + 1 << "with original target: " << originalTarget << endl;
+	if ( computedTarget != nullptr ) os << indent + 1 << "with computed target: " << computedTarget << endl;
 }
 
@@ -136,18 +136,18 @@
 }
 
-void ReturnStmt::print( std::ostream & os, Indenter indent ) const {
+void ReturnStmt::print( ostream & os, Indenter indent ) const {
 	os << "Return Statement, returning: ";
 	if ( expr != nullptr ) {
-		os << endl << indent+1;
-		expr->print( os, indent+1 );
+		os << endl << indent + 1;
+		expr->print( os, indent + 1 );
 	}
 	os << endl;
 }
 
-IfStmt::IfStmt( Expression * condition, Statement * thenPart, Statement * elsePart, std::list<Statement *> initialization ):
-	Statement(), condition( condition ), thenPart( thenPart ), elsePart( elsePart ), initialization( initialization ) {}
+IfStmt::IfStmt( Expression * condition, Statement * then, Statement * else_, const list<Statement *> initialization ):
+	Statement(), condition( condition ), then( then ), else_( else_ ), initialization( initialization ) {}
 
 IfStmt::IfStmt( const IfStmt & other ) :
-	Statement( other ), condition( maybeClone( other.condition ) ), thenPart( maybeClone( other.thenPart ) ), elsePart( maybeClone( other.elsePart ) ) {
+	Statement( other ), condition( maybeClone( other.condition ) ), then( maybeClone( other.then ) ), else_( maybeClone( other.else_ ) ) {
 	cloneAll( other.initialization, initialization );
 }
@@ -156,18 +156,18 @@
 	deleteAll( initialization );
 	delete condition;
-	delete thenPart;
-	delete elsePart;
-}
-
-void IfStmt::print( std::ostream & os, Indenter indent ) const {
+	delete then;
+	delete else_;
+}
+
+void IfStmt::print( ostream & os, Indenter indent ) const {
 	os << "If on condition: " << endl;
-	os << indent+1;
-	condition->print( os, indent+1 );
+	os << indent + 1;
+	condition->print( os, indent + 1 );
 
 	if ( !initialization.empty() ) {
 		os << indent << "... with initialization: \n";
 		for ( const Statement * stmt : initialization ) {
-			os << indent+1;
-			stmt->print( os, indent+1 );
+			os << indent + 1;
+			stmt->print( os, indent + 1 );
 		}
 		os << endl;
@@ -176,15 +176,15 @@
 	os << indent << "... then: " << endl;
 
-	os << indent+1;
-	thenPart->print( os, indent+1 );
-
-	if ( elsePart != nullptr ) {
+	os << indent + 1;
+	then->print( os, indent + 1 );
+
+	if ( else_ != nullptr ) {
 		os << indent << "... else: " << endl;
-		os << indent+1;
-		elsePart->print( os, indent+1 );
+		os << indent + 1;
+		else_->print( os, indent + 1 );
 	} // if
 }
 
-SwitchStmt::SwitchStmt( Expression * condition, const std::list<Statement *> & statements ):
+SwitchStmt::SwitchStmt( Expression * condition, const list<Statement *> & statements ):
 	Statement(), condition( condition ), statements( statements ) {
 }
@@ -201,5 +201,5 @@
 }
 
-void SwitchStmt::print( std::ostream & os, Indenter indent ) const {
+void SwitchStmt::print( ostream & os, Indenter indent ) const {
 	os << "Switch on condition: ";
 	condition->print( os );
@@ -207,15 +207,15 @@
 
 	for ( const Statement * stmt : statements ) {
-		stmt->print( os, indent+1 );
-	}
-}
-
-CaseStmt::CaseStmt( Expression * condition, const std::list<Statement *> & statements, bool deflt ) throw ( SemanticErrorException ) :
-	Statement(), condition( condition ), stmts( statements ), _isDefault( deflt ) {
+		stmt->print( os, indent + 1 );
+	}
+}
+
+CaseStmt::CaseStmt( Expression * condition, const list<Statement *> & statements, bool deflt ) throw ( SemanticErrorException ) :
+		Statement(), condition( condition ), stmts( statements ), _isDefault( deflt ) {
 	if ( isDefault() && condition != nullptr ) SemanticError( condition, "default case with condition: " );
 }
 
 CaseStmt::CaseStmt( const CaseStmt & other ) :
-	Statement( other ), condition( maybeClone(other.condition ) ), _isDefault( other._isDefault ) {
+		Statement( other ), condition( maybeClone(other.condition ) ), _isDefault( other._isDefault ) {
 	cloneAll( other.stmts, stmts );
 }
@@ -226,5 +226,5 @@
 }
 
-CaseStmt * CaseStmt::makeDefault( const std::list<Label> & labels, std::list<Statement *> stmts ) {
+CaseStmt * CaseStmt::makeDefault( const list<Label> & labels, list<Statement *> stmts ) {
 	CaseStmt * stmt = new CaseStmt( nullptr, stmts, true );
 	stmt->labels = labels;
@@ -232,5 +232,5 @@
 }
 
-void CaseStmt::print( std::ostream & os, Indenter indent ) const {
+void CaseStmt::print( ostream & os, Indenter indent ) const {
 	if ( isDefault() ) os << indent << "Default ";
 	else {
@@ -241,37 +241,41 @@
 
 	for ( Statement * stmt : stmts ) {
-		os << indent+1;
-		stmt->print( os, indent+1 );
-	}
-}
-
-WhileStmt::WhileStmt( Expression * condition, Statement * body, std::list< Statement * > & initialization, bool isDoWhile ):
-	Statement(), condition( condition), body( body), initialization( initialization ), isDoWhile( isDoWhile) {
-}
-
-WhileStmt::WhileStmt( const WhileStmt & other ):
+		os << indent + 1;
+		stmt->print( os, indent + 1 );
+	}
+}
+
+WhileDoStmt::WhileDoStmt( Expression * condition, Statement * body, const list< Statement * > & initialization, bool isDoWhile ):
+	Statement(), condition( condition ), body( body ), else_( nullptr ), initialization( initialization ), isDoWhile( isDoWhile) {
+}
+
+WhileDoStmt::WhileDoStmt( Expression * condition, Statement * body, Statement * else_, const list< Statement * > & initialization, bool isDoWhile ):
+	Statement(), condition( condition), body( body ), else_( else_ ), initialization( initialization ), isDoWhile( isDoWhile) {
+}
+
+WhileDoStmt::WhileDoStmt( const WhileDoStmt & other ):
 	Statement( other ), condition( maybeClone( other.condition ) ), body( maybeClone( other.body ) ), isDoWhile( other.isDoWhile ) {
 }
 
-WhileStmt::~WhileStmt() {
+WhileDoStmt::~WhileDoStmt() {
 	delete body;
 	delete condition;
 }
 
-void WhileStmt::print( std::ostream & os, Indenter indent ) const {
+void WhileDoStmt::print( ostream & os, Indenter indent ) const {
 	os << "While on condition: " << endl ;
-	condition->print( os, indent+1 );
+	condition->print( os, indent + 1 );
 
 	os << indent << "... with body: " << endl;
 
-	if ( body != nullptr ) body->print( os, indent+1 );
-}
-
-ForStmt::ForStmt( std::list<Statement *> initialization, Expression * condition, Expression * increment, Statement * body ):
-	Statement(), initialization( initialization ), condition( condition ), increment( increment ), body( body ) {
+	if ( body != nullptr ) body->print( os, indent + 1 );
+}
+
+ForStmt::ForStmt( const list<Statement *> initialization, Expression * condition, Expression * increment, Statement * body, Statement * else_ ):
+	Statement(), initialization( initialization ), condition( condition ), increment( increment ), body( body ), else_( else_ ) {
 }
 
 ForStmt::ForStmt( const ForStmt & other ):
-	Statement( other ), condition( maybeClone( other.condition ) ), increment( maybeClone( other.increment ) ), body( maybeClone( other.body ) ) {
+	Statement( other ), condition( maybeClone( other.condition ) ), increment( maybeClone( other.increment ) ), body( maybeClone( other.body ) ), else_( maybeClone( other.else_ ) ) {
 		cloneAll( other.initialization, initialization );
 
@@ -283,7 +287,8 @@
 	delete increment;
 	delete body;
-}
-
-void ForStmt::print( std::ostream & os, Indenter indent ) const {
+	delete else_;
+}
+
+void ForStmt::print( ostream & os, Indenter indent ) const {
 	Statement::print( os, indent ); // print labels
 
@@ -293,22 +298,27 @@
 		os << indent << "... initialization: \n";
 		for ( Statement * stmt : initialization ) {
-			os << indent+1;
-			stmt->print( os, indent+1 );
+			os << indent + 1;
+			stmt->print( os, indent + 1 );
 		}
 	}
 
 	if ( condition != nullptr ) {
-		os << indent << "... condition: \n" << indent+1;
-		condition->print( os, indent+1 );
+		os << indent << "... condition: \n" << indent + 1;
+		condition->print( os, indent + 1 );
 	}
 
 	if ( increment != nullptr ) {
-		os << "\n" << indent << "... increment: \n" << indent+1;
-		increment->print( os, indent+1 );
+		os << "\n" << indent << "... increment: \n" << indent + 1;
+		increment->print( os, indent + 1 );
 	}
 
 	if ( body != nullptr ) {
-		os << "\n" << indent << "... with body: \n" << indent+1;
-		body->print( os, indent+1 );
+		os << "\n" << indent << "... with body: \n" << indent + 1;
+		body->print( os, indent + 1 );
+	}
+
+	if ( else_ != nullptr ) {
+		os << "\n" << indent << "... with body: \n" << indent + 1;
+		else_->print( os, indent + 1 );
 	}
 	os << endl;
@@ -329,15 +339,15 @@
 }
 
-void ThrowStmt::print( std::ostream & os, Indenter indent) const {
+void ThrowStmt::print( ostream & os, Indenter indent) const {
 	if ( target ) os << "Non-Local ";
 	os << "Throw Statement, raising: ";
-	expr->print(os, indent+1);
+	expr->print(os, indent + 1);
 	if ( target ) {
 		os << "... at: ";
-		target->print(os, indent+1);
-	}
-}
-
-TryStmt::TryStmt( CompoundStmt * tryBlock, std::list<CatchStmt *> & handlers, FinallyStmt * finallyBlock ) :
+		target->print(os, indent + 1);
+	}
+}
+
+TryStmt::TryStmt( CompoundStmt * tryBlock, const list<CatchStmt *> & handlers, FinallyStmt * finallyBlock ) :
 	Statement(), block( tryBlock ),  handlers( handlers ), finallyBlock( finallyBlock ) {
 }
@@ -353,20 +363,20 @@
 }
 
-void TryStmt::print( std::ostream & os, Indenter indent ) const {
+void TryStmt::print( ostream & os, Indenter indent ) const {
 	os << "Try Statement" << endl;
-	os << indent << "... with block:" << endl << indent+1;
-	block->print( os, indent+1 );
+	os << indent << "... with block:" << endl << indent + 1;
+	block->print( os, indent + 1 );
 
 	// handlers
 	os << indent << "... and handlers:" << endl;
 	for ( const CatchStmt * stmt : handlers ) {
-		os << indent+1;
-		stmt->print( os, indent+1 );
+		os << indent + 1;
+		stmt->print( os, indent + 1 );
 	}
 
 	// finally block
 	if ( finallyBlock != nullptr ) {
-		os << indent << "... and finally:" << endl << indent+1;
-		finallyBlock->print( os, indent+1 );
+		os << indent << "... and finally:" << endl << indent + 1;
+		finallyBlock->print( os, indent + 1 );
 	} // if
 }
@@ -386,19 +396,19 @@
 }
 
-void CatchStmt::print( std::ostream & os, Indenter indent ) const {
+void CatchStmt::print( ostream & os, Indenter indent ) const {
 	os << "Catch " << ((Terminate == kind) ? "Terminate" : "Resume") << " Statement" << endl;
 
 	os << indent << "... catching: ";
-	decl->printShort( os, indent+1 );
+	decl->printShort( os, indent + 1 );
 	os << endl;
 
 	if ( cond ) {
-		os << indent << "... with conditional:" << endl << indent+1;
-		cond->print( os, indent+1 );
+		os << indent << "... with conditional:" << endl << indent + 1;
+		cond->print( os, indent + 1 );
 	}
 
 	os << indent << "... with block:" << endl;
-	os << indent+1;
-	body->print( os, indent+1 );
+	os << indent + 1;
+	body->print( os, indent + 1 );
 }
 
@@ -414,8 +424,8 @@
 }
 
-void FinallyStmt::print( std::ostream & os, Indenter indent ) const {
+void FinallyStmt::print( ostream & os, Indenter indent ) const {
 	os << "Finally Statement" << endl;
-	os << indent << "... with block:" << endl << indent+1;
-	block->print( os, indent+1 );
+	os << indent << "... with block:" << endl << indent + 1;
+	block->print( os, indent + 1 );
 }
 
@@ -429,5 +439,5 @@
 }
 
-void SuspendStmt::print( std::ostream & os, Indenter indent ) const {
+void SuspendStmt::print( ostream & os, Indenter indent ) const {
 	os << "Suspend Statement";
 	switch (type) {
@@ -486,5 +496,5 @@
 }
 
-void WaitForStmt::print( std::ostream & os, Indenter indent ) const {
+void WaitForStmt::print( ostream & os, Indenter indent ) const {
 	os << "Waitfor Statement" << endl;
 	indent += 1;
@@ -521,5 +531,5 @@
 
 
-WithStmt::WithStmt( const std::list< Expression * > & exprs, Statement * stmt ) : Declaration("", noStorageClasses, LinkageSpec::Cforall), exprs( exprs ), stmt( stmt ) {}
+WithStmt::WithStmt( const list< Expression * > & exprs, Statement * stmt ) : Declaration("", noStorageClasses, LinkageSpec::Cforall), exprs( exprs ), stmt( stmt ) {}
 WithStmt::WithStmt( const WithStmt & other ) : Declaration( other ), stmt( maybeClone( other.stmt ) ) {
 	cloneAll( other.exprs, exprs );
@@ -530,17 +540,17 @@
 }
 
-void WithStmt::print( std::ostream & os, Indenter indent ) const {
+void WithStmt::print( ostream & os, Indenter indent ) const {
 	os << "With statement" << endl;
 	os << indent << "... with expressions: " << endl;
-	printAll( exprs, os, indent+1 );
-	os << indent << "... with statement:" << endl << indent+1;
-	stmt->print( os, indent+1 );
-}
-
-
-NullStmt::NullStmt( const std::list<Label> & labels ) : Statement( labels ) {
-}
-
-void NullStmt::print( std::ostream & os, Indenter indent ) const {
+	printAll( exprs, os, indent + 1 );
+	os << indent << "... with statement:" << endl << indent + 1;
+	stmt->print( os, indent + 1 );
+}
+
+
+NullStmt::NullStmt( const list<Label> & labels ) : Statement( labels ) {
+}
+
+void NullStmt::print( ostream & os, Indenter indent ) const {
 	os << "Null Statement" << endl;
 	Statement::print( os, indent );
@@ -558,12 +568,12 @@
 }
 
-void ImplicitCtorDtorStmt::print( std::ostream & os, Indenter indent ) const {
+void ImplicitCtorDtorStmt::print( ostream & os, Indenter indent ) const {
 	os << "Implicit Ctor Dtor Statement" << endl;
 	os << indent << "... with Ctor/Dtor: ";
-	callStmt->print( os, indent+1);
+	callStmt->print( os, indent + 1);
 	os << endl;
 }
 
-MutexStmt::MutexStmt( Statement * stmt, std::list<Expression *> mutexObjs ) 
+MutexStmt::MutexStmt( Statement * stmt, const list<Expression *> mutexObjs ) 
 	: Statement(), stmt( stmt ), mutexObjs( mutexObjs ) { }
 
@@ -577,14 +587,14 @@
 }
 
-void MutexStmt::print( std::ostream & os, Indenter indent ) const {
+void MutexStmt::print( ostream & os, Indenter indent ) const {
 	os << "Mutex Statement" << endl;
 	os << indent << "... with Expressions: " << endl;
 	for (auto * obj : mutexObjs) {
-		os << indent+1;
-		obj->print( os, indent+1);
+		os << indent + 1;
+		obj->print( os, indent + 1);
 		os << endl;
 	}
-	os << indent << "... with Statement: " << endl << indent+1;
-	stmt->print( os, indent+1 );
+	os << indent << "... with Statement: " << endl << indent + 1;
+	stmt->print( os, indent + 1 );
 }
 
Index: src/SynTree/Statement.h
===================================================================
--- src/SynTree/Statement.h	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/SynTree/Statement.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Jan 10 14:13:24 2020
-// Update Count     : 85
+// Last Modified On : Wed Feb  2 20:15:30 2022
+// Update Count     : 98
 //
 
@@ -107,5 +107,5 @@
 	std::list<Label> gotolabels;
 
-	AsmStmt( bool voltile, Expression * instruction, std::list<Expression *> output, std::list<Expression *> input, std::list<ConstantExpr *> clobber, std::list<Label> gotolabels );
+	AsmStmt( bool voltile, Expression * instruction, const std::list<Expression *> output, const std::list<Expression *> input, const std::list<ConstantExpr *> clobber, const std::list<Label> gotolabels );
 	AsmStmt( const AsmStmt & other );
 	virtual ~AsmStmt();
@@ -148,10 +148,10 @@
   public:
 	Expression * condition;
-	Statement * thenPart;
-	Statement * elsePart;
+	Statement * then;
+	Statement * else_;
 	std::list<Statement *> initialization;
 
-	IfStmt( Expression * condition, Statement * thenPart, Statement * elsePart,
-			std::list<Statement *> initialization = std::list<Statement *>() );
+	IfStmt( Expression * condition, Statement * then, Statement * else_,
+			const std::list<Statement *> initialization = std::list<Statement *>() );
 	IfStmt( const IfStmt & other );
 	virtual ~IfStmt();
@@ -160,8 +160,8 @@
 	Expression * get_condition() { return condition; }
 	void set_condition( Expression * newValue ) { condition = newValue; }
-	Statement * get_thenPart() { return thenPart; }
-	void set_thenPart( Statement * newValue ) { thenPart = newValue; }
-	Statement * get_elsePart() { return elsePart; }
-	void set_elsePart( Statement * newValue ) { elsePart = newValue; }
+	Statement * get_then() { return then; }
+	void set_then( Statement * newValue ) { then = newValue; }
+	Statement * get_else() { return else_; }
+	void set_else( Statement * newValue ) { else_ = newValue; }
 
 	virtual IfStmt * clone() const override { return new IfStmt( *this ); }
@@ -225,14 +225,16 @@
 };
 
-class WhileStmt : public Statement {
+class WhileDoStmt : public Statement {
   public:
 	Expression * condition;
 	Statement * body;
+	Statement * else_;
 	std::list<Statement *> initialization;
 	bool isDoWhile;
 
-	WhileStmt( Expression * condition, Statement * body, std::list<Statement *> & initialization, bool isDoWhile = false );
-	WhileStmt( const WhileStmt & other );
-	virtual ~WhileStmt();
+	WhileDoStmt( Expression * condition, Statement * body, const std::list<Statement *> & initialization, bool isDoWhile = false );
+	WhileDoStmt( Expression * condition, Statement * body, Statement * else_, const std::list<Statement *> & initialization, bool isDoWhile = false );
+	WhileDoStmt( const WhileDoStmt & other );
+	virtual ~WhileDoStmt();
 
 	Expression * get_condition() { return condition; }
@@ -243,5 +245,5 @@
 	void set_isDoWhile( bool newValue ) { isDoWhile = newValue; }
 
-	virtual WhileStmt * clone() const override { return new WhileStmt( *this ); }
+	virtual WhileDoStmt * clone() const override { return new WhileDoStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
 	virtual void accept( Visitor & v ) const override { v.visit( this ); }
@@ -256,6 +258,7 @@
 	Expression * increment;
 	Statement * body;
-
-	ForStmt( std::list<Statement *> initialization, Expression * condition = nullptr, Expression * increment = nullptr, Statement * body = nullptr );
+	Statement * else_;
+
+	ForStmt( const std::list<Statement *> initialization, Expression * condition = nullptr, Expression * increment = nullptr, Statement * body = nullptr, Statement * else_ = nullptr );
 	ForStmt( const ForStmt & other );
 	virtual ~ForStmt();
@@ -278,5 +281,5 @@
 class BranchStmt : public Statement {
   public:
-	enum Type { Goto = 0, Break, Continue, FallThrough, FallThroughDefault };
+	enum Type { Goto, Break, Continue, FallThrough, FallThroughDefault, BranchStmts };
 
 	// originalTarget kept for error messages.
@@ -357,5 +360,5 @@
 	FinallyStmt * finallyBlock;
 
-	TryStmt( CompoundStmt * tryBlock, std::list<CatchStmt *> & handlers, FinallyStmt * finallyBlock = nullptr );
+	TryStmt( CompoundStmt * tryBlock, const std::list<CatchStmt *> & handlers, FinallyStmt * finallyBlock = nullptr );
 	TryStmt( const TryStmt & other );
 	virtual ~TryStmt();
@@ -540,5 +543,5 @@
 	std::list<Expression *> mutexObjs; // list of mutex objects to acquire
 
-	MutexStmt( Statement * stmt, std::list<Expression *> mutexObjs );
+	MutexStmt( Statement * stmt, const std::list<Expression *> mutexObjs );
 	MutexStmt( const MutexStmt & other );
 	virtual ~MutexStmt();
Index: src/SynTree/SynTree.h
===================================================================
--- src/SynTree/SynTree.h	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/SynTree/SynTree.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Mar 12 18:56:44 2021
-// Update Count     : 13
+// Last Modified On : Tue Feb  1 09:22:33 2022
+// Update Count     : 14
 //
 
@@ -45,5 +45,5 @@
 class DirectiveStmt;
 class IfStmt;
-class WhileStmt;
+class WhileDoStmt;
 class ForStmt;
 class SwitchStmt;
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/SynTree/Visitor.h	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Mar 12 18:35:35 2021
-// Update Count     : 15
+// Last Modified On : Tue Feb  1 09:26:57 2022
+// Update Count     : 17
 //
 
@@ -60,6 +60,6 @@
 	virtual void visit( IfStmt * node ) { visit( const_cast<const IfStmt *>(node) ); }
 	virtual void visit( const IfStmt * ifStmt ) = 0;
-	virtual void visit( WhileStmt * node ) { visit( const_cast<const WhileStmt *>(node) ); }
-	virtual void visit( const WhileStmt * whileStmt ) = 0;
+	virtual void visit( WhileDoStmt * node ) { visit( const_cast<const WhileDoStmt *>(node) ); }
+	virtual void visit( const WhileDoStmt * whileDoStmt ) = 0;
 	virtual void visit( ForStmt * node ) { visit( const_cast<const ForStmt *>(node) ); }
 	virtual void visit( const ForStmt * forStmt ) = 0;
Index: src/Validate/Autogen.cpp
===================================================================
--- src/Validate/Autogen.cpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
+++ src/Validate/Autogen.cpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -0,0 +1,778 @@
+//
+// 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.
+//
+// Autogen.cpp -- Generate automatic routines for data types.
+//
+// Author           : Andrew Beach
+// Created On       : Thu Dec  2 13:44:00 2021
+// Last Modified By : Andrew Beach
+// Last Modified On : Thr Jan 27  9:29:00 2022
+// Update Count     : 1
+//
+
+#include "Autogen.hpp"
+
+#include <algorithm>               // for count_if
+#include <cassert>                 // for strict_dynamic_cast, assert, assertf
+#include <iterator>                // for back_insert_iterator, back_inserter
+#include <list>                    // for list, _List_iterator, list<>::iter...
+#include <set>                     // for set, _Rb_tree_const_iterator
+#include <utility>                 // for pair
+#include <vector>                  // for vector
+
+#include "AST/Attribute.hpp"
+#include "AST/Decl.hpp"
+#include "AST/DeclReplacer.hpp"
+#include "AST/Expr.hpp"
+#include "AST/Pass.hpp"
+#include "AST/Stmt.hpp"
+#include "AST/SymbolTable.hpp"
+#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
+#include "Common/ScopedMap.h"      // for ScopedMap<>::const_iterator, Scope...
+#include "Common/utility.h"        // for cloneAll, operator+
+#include "GenPoly/ScopedSet.h"     // for ScopedSet, ScopedSet<>::iterator
+#include "InitTweak/GenInit.h"     // for fixReturnStatements
+#include "InitTweak/InitTweak.h"   // for isAssignment, isCopyConstructor
+#include "SymTab/Mangler.h"        // for Mangler
+#include "CompilationState.h"
+
+// TODO: The other new ast function should be moved over to this file.
+#include "SymTab/Autogen.h"
+
+namespace Validate {
+
+namespace {
+
+// --------------------------------------------------------------------------
+struct AutogenerateRoutines_new final :
+		public ast::WithDeclsToAdd<>,
+		public ast::WithShortCircuiting {
+	void previsit( const ast::EnumDecl * enumDecl );
+	void previsit( const ast::StructDecl * structDecl );
+	void previsit( const ast::UnionDecl * structDecl );
+	void previsit( const ast::TypeDecl * typeDecl );
+	void previsit( const ast::TraitDecl * traitDecl );
+	void previsit( const ast::FunctionDecl * functionDecl );
+	void postvisit( const ast::FunctionDecl * functionDecl );
+
+private:
+	// Current level of nested functions.
+	unsigned int functionNesting = 0;
+};
+
+// --------------------------------------------------------------------------
+/// Class used to generate functions for a particular declaration.
+/// Note it isn't really stored, it is just a class for organization and to
+/// help pass around some of the common arguments.
+class FuncGenerator {
+public:
+	std::list<ast::ptr<ast::Decl>> forwards;
+	std::list<ast::ptr<ast::Decl>> definitions;
+
+	FuncGenerator( const ast::Type * type, unsigned int functionNesting ) :
+		type( type ), functionNesting( functionNesting )
+	{}
+
+	/// Generate functions (and forward decls.) and append them to the list.
+	void generateAndAppendFunctions( std::list<ast::ptr<ast::Decl>> & );
+
+	virtual bool shouldAutogen() const = 0;
+protected:
+	const ast::Type * type;
+	unsigned int functionNesting;
+	ast::Linkage::Spec proto_linkage = ast::Linkage::AutoGen;
+
+	// Internal helpers:
+	void genStandardFuncs();
+	void produceDecl( const ast::FunctionDecl * decl );
+	void produceForwardDecl( const ast::FunctionDecl * decl );
+
+	const CodeLocation& getLocation() const { return getDecl()->location; }
+	ast::FunctionDecl * genProto( const std::string& name,
+		std::vector<ast::ptr<ast::DeclWithType>>&& params,
+		std::vector<ast::ptr<ast::DeclWithType>>&& returns ) const;
+
+	ast::ObjectDecl * dstParam() const;
+	ast::ObjectDecl * srcParam() const;
+	ast::FunctionDecl * genCtorProto() const;
+	ast::FunctionDecl * genCopyProto() const;
+	ast::FunctionDecl * genDtorProto() const;
+	ast::FunctionDecl * genAssignProto() const;
+	ast::FunctionDecl * genFieldCtorProto( unsigned int fields ) const;
+
+	// Internal Hooks:
+	virtual void genFuncBody( ast::FunctionDecl * decl ) = 0;
+	virtual void genFieldCtors() = 0;
+	virtual bool isConcurrentType() const { return false; }
+	virtual const ast::Decl * getDecl() const = 0;
+};
+
+class StructFuncGenerator final : public FuncGenerator {
+	const ast::StructDecl * decl;
+public:
+	StructFuncGenerator( const ast::StructDecl * decl,
+			const ast::StructInstType * type,
+			unsigned int functionNesting ) :
+		FuncGenerator( type, functionNesting ), decl( decl )
+	{}
+
+	// Built-ins do not use autogeneration.
+	bool shouldAutogen() const final { return !decl->linkage.is_builtin; }
+private:
+	void genFuncBody( ast::FunctionDecl * decl ) final;
+	void genFieldCtors() final;
+	bool isConcurrentType() const final {
+		return decl->is_thread() || decl->is_monitor();
+	}
+	virtual const ast::Decl * getDecl() const final { return decl; }
+
+	/// Generates a single struct member operation.
+	/// (constructor call, destructor call, assignment call)
+	// This is managed because it uses another helper that returns a ast::ptr.
+	ast::ptr<ast::Stmt> makeMemberOp(
+		const CodeLocation& location,
+		const ast::ObjectDecl * dstParam, const ast::Expr * src,
+		const ast::ObjectDecl * field, ast::FunctionDecl * func,
+		SymTab::LoopDirection direction );
+
+	/// Generates the body of a struct function by iterating the struct members
+	/// (via parameters). Generates default constructor, copy constructor,
+	/// copy assignment, and destructor bodies. No field constructor bodies.
+	template<typename Iterator>
+	void makeFunctionBody( Iterator member, Iterator end,
+			ast::FunctionDecl * func, SymTab::LoopDirection direction );
+
+	/// Generate the body of a constructor which takes parameters that match
+	/// fields. (With arguments for one to all of the fields.)
+	template<typename Iterator>
+	void makeFieldCtorBody( Iterator member, Iterator end,
+			ast::FunctionDecl * func );
+};
+
+class UnionFuncGenerator final : public FuncGenerator {
+	const ast::UnionDecl * decl;
+public:
+	UnionFuncGenerator( const ast::UnionDecl * decl,
+			const ast::UnionInstType * type,
+			unsigned int functionNesting ) :
+		FuncGenerator( type, functionNesting ), decl( decl )
+	{}
+
+	// Built-ins do not use autogeneration.
+	bool shouldAutogen() const final { return !decl->linkage.is_builtin; }
+private:
+	void genFuncBody( ast::FunctionDecl * decl ) final;
+	void genFieldCtors() final;
+	const ast::Decl * getDecl() const final { return decl; }
+
+	/// Generate a single union assignment expression (using memcpy).
+	ast::ExprStmt * makeAssignOp( const CodeLocation& location,
+		const ast::ObjectDecl * dstParam, const ast::ObjectDecl * srcParam );
+};
+
+class EnumFuncGenerator final : public FuncGenerator {
+	const ast::EnumDecl * decl;
+public:
+	EnumFuncGenerator( const ast::EnumDecl * decl,
+			const ast::EnumInstType * type,
+			unsigned int functionNesting ) :
+		FuncGenerator( type, functionNesting ), decl( decl )
+	{
+		// TODO: These functions are somewhere between instrinsic and autogen,
+		// could possibly use a new linkage type. For now we just make them
+		// intrinsic to code-gen them as C assignments.
+		proto_linkage = ast::Linkage::Intrinsic;
+	}
+
+	bool shouldAutogen() const final { return true; }
+private:
+	void genFuncBody( ast::FunctionDecl * decl ) final;
+	void genFieldCtors() final;
+	const ast::Decl * getDecl() const final { return decl; }
+};
+
+class TypeFuncGenerator final : public FuncGenerator {
+	const ast::TypeDecl * decl;
+public:
+	TypeFuncGenerator( const ast::TypeDecl * decl,
+			ast::TypeInstType * type,
+			unsigned int functionNesting ) :
+		FuncGenerator( type, functionNesting ), decl( decl )
+	{}
+
+	bool shouldAutogen() const final { return true; }
+	void genFieldCtors() final;
+private:
+	void genFuncBody( ast::FunctionDecl * decl ) final;
+	const ast::Decl * getDecl() const final { return decl; }
+};
+
+// --------------------------------------------------------------------------
+const std::vector<ast::ptr<ast::TypeDecl>>& getGenericParams( const ast::Type * t ) {
+	if ( auto inst = dynamic_cast< const ast::StructInstType * >( t ) ) {
+		return inst->base->params;
+	} else if ( auto inst = dynamic_cast< const ast::UnionInstType * >( t ) ) {
+		return inst->base->params;
+	}
+	static std::vector<ast::ptr<ast::TypeDecl>> const empty;
+	return empty;
+}
+
+/// Changes the node inside a pointer so that it has the unused attribute.
+void addUnusedAttribute( ast::ptr<ast::DeclWithType> & declPtr ) {
+	ast::DeclWithType * decl = declPtr.get_and_mutate();
+	decl->attributes.push_back( new ast::Attribute( "unused" ) );
+}
+
+// --------------------------------------------------------------------------
+void AutogenerateRoutines_new::previsit( const ast::EnumDecl * enumDecl ) {
+	// Must visit children (enum constants) to add them to the symbol table.
+	if ( !enumDecl->body ) return;
+
+	ast::EnumInstType enumInst( enumDecl->name );
+	enumInst.base = enumDecl;
+	EnumFuncGenerator gen( enumDecl, &enumInst, functionNesting );
+	gen.generateAndAppendFunctions( declsToAddAfter );
+}
+
+void AutogenerateRoutines_new::previsit( const ast::StructDecl * structDecl ) {
+	visit_children = false;
+	if ( !structDecl->body ) return;
+
+	ast::StructInstType structInst( structDecl->name );
+	structInst.base = structDecl;
+	for ( const ast::TypeDecl * typeDecl : structDecl->params ) {
+		structInst.params.push_back( new ast::TypeExpr(
+			typeDecl->location,
+			new ast::TypeInstType( typeDecl->name, typeDecl )
+		) );
+	}
+	StructFuncGenerator gen( structDecl, &structInst, functionNesting );
+	gen.generateAndAppendFunctions( declsToAddAfter );
+}
+
+void AutogenerateRoutines_new::previsit( const ast::UnionDecl * unionDecl ) {
+	visit_children = false;
+	if ( !unionDecl->body ) return;
+
+	ast::UnionInstType unionInst( unionDecl->name );
+	unionInst.base = unionDecl;
+	for ( const ast::TypeDecl * typeDecl : unionDecl->params ) {
+		unionInst.params.push_back( new ast::TypeExpr(
+			unionDecl->location,
+			new ast::TypeInstType( typeDecl->name, typeDecl )
+		) );
+	}
+	UnionFuncGenerator gen( unionDecl, &unionInst, functionNesting );
+	gen.generateAndAppendFunctions( declsToAddAfter );
+}
+
+/// Generate ctor/dtors/assign for typedecls, e.g., otype T = int *;
+void AutogenerateRoutines_new::previsit( const ast::TypeDecl * typeDecl ) {
+	if ( !typeDecl->base ) return;
+
+	ast::TypeInstType refType( typeDecl->name, typeDecl );
+	TypeFuncGenerator gen( typeDecl, &refType, functionNesting );
+	gen.generateAndAppendFunctions( declsToAddAfter );
+}
+
+void AutogenerateRoutines_new::previsit( const ast::TraitDecl * ) {
+	// Ensure that we don't add assignment ops for types defined as part of the trait
+	visit_children = false;
+}
+
+void AutogenerateRoutines_new::previsit( const ast::FunctionDecl * ) {
+	// Track whether we're currently in a function.
+	// Can ignore function type idiosyncrasies, because function type can never
+	// declare a new type.
+	functionNesting += 1;
+}
+
+void AutogenerateRoutines_new::postvisit( const ast::FunctionDecl * ) {
+	functionNesting -= 1;
+}
+
+void FuncGenerator::generateAndAppendFunctions(
+		std::list<ast::ptr<ast::Decl>> & decls ) {
+	if ( !shouldAutogen() ) return;
+
+	// Generate the functions (they go into forwards and definitions).
+	genStandardFuncs();
+	genFieldCtors();
+
+	// Now export the lists contents.
+	decls.splice( decls.end(), forwards );
+	decls.splice( decls.end(), definitions );
+}
+
+void FuncGenerator::produceDecl( const ast::FunctionDecl * decl ) {
+	assert( nullptr != decl->stmts );
+
+	definitions.push_back( decl );
+}
+
+/// Make a forward declaration of the decl and add it to forwards.
+void FuncGenerator::produceForwardDecl( const ast::FunctionDecl * decl ) {
+	if (0 != functionNesting) return;
+	ast::FunctionDecl * fwd = ast::deepCopy( decl );
+	fwd->stmts = nullptr;
+	fwd->fixUniqueId();
+	forwards.push_back( fwd );
+}
+
+/// Generates a basic prototype function declaration.
+ast::FunctionDecl * FuncGenerator::genProto( const std::string& name,
+		std::vector<ast::ptr<ast::DeclWithType>>&& params,
+		std::vector<ast::ptr<ast::DeclWithType>>&& returns ) const {
+
+	// Handle generic prameters and assertions, if any.
+	auto const & old_type_params = getGenericParams( type );
+	std::vector<ast::ptr<ast::TypeDecl>> type_params;
+	std::vector<ast::ptr<ast::DeclWithType>> assertions;
+	for ( auto & old_param : old_type_params ) {
+		ast::TypeDecl * decl = ast::deepCopy( old_param );
+		for ( auto assertion : decl->assertions ) {
+			assertions.push_back( assertion );
+		}
+		decl->assertions.clear();
+		type_params.push_back( decl );
+	}
+	// TODO: The values in params and returns still may point at the old
+	// generic params, that does not appear to be an issue but perhaps it
+	// should be addressed.
+
+	ast::FunctionDecl * decl = new ast::FunctionDecl(
+		// Auto-generated routines use the type declaration's location.
+		getLocation(),
+		name,
+		std::move( type_params ),
+		std::move( params ),
+		std::move( returns ),
+		// Only a prototype, no body.
+		nullptr,
+		// Use static storage if we are at the top level.
+		(0 < functionNesting) ? ast::Storage::Classes() : ast::Storage::Static,
+		proto_linkage,
+		std::vector<ast::ptr<ast::Attribute>>(),
+		// Auto-generated routines are inline to avoid conflicts.
+		ast::Function::Specs( ast::Function::Inline ) );
+	decl->assertions = std::move( assertions );
+	decl->fixUniqueId();
+	return decl;
+}
+
+ast::ObjectDecl * FuncGenerator::dstParam() const {
+	return new ast::ObjectDecl( getLocation(), "_dst",
+		new ast::ReferenceType( ast::deepCopy( type ) ),
+		nullptr, {}, ast::Linkage::Cforall );
+}
+
+ast::ObjectDecl * FuncGenerator::srcParam() const {
+	return new ast::ObjectDecl( getLocation(), "_src",
+		ast::deepCopy( type ),
+		nullptr, {}, ast::Linkage::Cforall );
+}
+
+/// Use the current type T to create `void ?{}(T & _dst)`.
+ast::FunctionDecl * FuncGenerator::genCtorProto() const {
+	return genProto( "?{}", { dstParam() }, {} );
+}
+
+/// Use the current type T to create `void ?{}(T & _dst, T _src)`.
+ast::FunctionDecl * FuncGenerator::genCopyProto() const {
+	return genProto( "?{}", { dstParam(), srcParam() }, {} );
+}
+
+/// Use the current type T to create `void ?{}(T & _dst)`.
+ast::FunctionDecl * FuncGenerator::genDtorProto() const {
+	// The destructor must be mutex on a concurrent type.
+	auto dst = dstParam();
+	if ( isConcurrentType() ) {
+		add_qualifiers( dst->type, ast::CV::Qualifiers( ast::CV::Mutex ) );
+	}
+	return genProto( "^?{}", { dst }, {} );
+}
+
+/// Use the current type T to create `T ?{}(T & _dst, T _src)`.
+ast::FunctionDecl * FuncGenerator::genAssignProto() const {
+	// Only the name is different, so just reuse the generation function.
+	auto retval = srcParam();
+	retval->name = "_ret";
+	return genProto( "?=?", { dstParam(), srcParam() }, { retval } );
+}
+
+// This one can return null if the last field is an unnamed bitfield.
+ast::FunctionDecl * FuncGenerator::genFieldCtorProto(
+		unsigned int fields ) const {
+	assert( 0 < fields );
+	auto aggr = strict_dynamic_cast<const ast::AggregateDecl *>( getDecl() );
+
+	std::vector<ast::ptr<ast::DeclWithType>> params = { dstParam() };
+	for ( unsigned int index = 0 ; index < fields ; ++index ) {
+		auto member = aggr->members[index].strict_as<ast::DeclWithType>();
+		if ( SymTab::isUnnamedBitfield(
+				dynamic_cast<const ast::ObjectDecl *>( member ) ) ) {
+			if ( index == fields - 1 ) {
+				return nullptr;
+			}
+			continue;
+		}
+
+		auto * paramType = ast::deepCopy( member->get_type() );
+		paramType->attributes.clear();
+		ast::ObjectDecl * param = new ast::ObjectDecl(
+			getLocation(), member->name, paramType );
+		param->linkage = ast::Linkage::Cforall;
+		for ( auto & attr : member->attributes ) {
+			if ( attr->isValidOnFuncParam() ) {
+				param->attributes.push_back( attr );
+			}
+		}
+		params.emplace_back( param );
+	}
+	return genProto( "?{}", std::move( params ), {} );
+}
+
+void appendReturnThis( ast::FunctionDecl * decl ) {
+	assert( 1 <= decl->params.size() );
+	assert( 1 == decl->returns.size() );
+	assert( decl->stmts );
+
+	const CodeLocation& location = (decl->stmts->kids.empty())
+		? decl->stmts->location : decl->stmts->kids.back()->location;
+	const ast::DeclWithType * thisParam = decl->params.front();
+	decl->stmts.get_and_mutate()->push_back(
+		new ast::ReturnStmt( location,
+			new ast::VariableExpr( location, thisParam )
+		)
+	);
+}
+
+void FuncGenerator::genStandardFuncs() {
+	// The order here determines the order that these functions are generated.
+	// Assignment should come last since it uses copy constructor in return.
+	ast::FunctionDecl *(FuncGenerator::*standardProtos[4])() const = {
+			&FuncGenerator::genCtorProto, &FuncGenerator::genCopyProto,
+			&FuncGenerator::genDtorProto, &FuncGenerator::genAssignProto };
+	for ( auto & generator : standardProtos ) {
+		ast::FunctionDecl * decl = (this->*generator)();
+		produceForwardDecl( decl );
+		genFuncBody( decl );
+		if ( CodeGen::isAssignment( decl->name ) ) {
+			appendReturnThis( decl );
+		}
+		produceDecl( decl );
+	}
+}
+
+void StructFuncGenerator::genFieldCtors() {
+	// The field constructors are only generated if the default constructor
+	// and copy constructor are both generated, since the need both.
+	unsigned numCtors = std::count_if( definitions.begin(), definitions.end(),
+		[](const ast::Decl * decl){ return CodeGen::isConstructor( decl->name ); }
+	);
+	if ( 2 != numCtors ) return;
+
+	for ( unsigned int num = 1 ; num <= decl->members.size() ; ++num ) {
+		ast::FunctionDecl * ctor = genFieldCtorProto( num );
+		if ( nullptr == ctor ) {
+			continue;
+		}
+		produceForwardDecl( ctor );
+		makeFieldCtorBody( decl->members.begin(), decl->members.end(), ctor );
+		produceDecl( ctor );
+	}
+}
+
+void StructFuncGenerator::genFuncBody( ast::FunctionDecl * functionDecl ) {
+	// Generate appropriate calls to member constructors and assignment.
+	// Destructor needs to do everything in reverse,
+	// so pass "forward" based on whether the function is a destructor
+	if ( CodeGen::isDestructor( functionDecl->name ) ) {
+		makeFunctionBody( decl->members.rbegin(), decl->members.rend(),
+			functionDecl, SymTab::LoopBackward );
+	} else {
+		makeFunctionBody( decl->members.begin(), decl->members.end(),
+			functionDecl, SymTab::LoopForward );
+	}
+}
+
+ast::ptr<ast::Stmt> StructFuncGenerator::makeMemberOp(
+		const CodeLocation& location, const ast::ObjectDecl * dstParam,
+		const ast::Expr * src, const ast::ObjectDecl * field,
+		ast::FunctionDecl * func, SymTab::LoopDirection direction ) {
+	InitTweak::InitExpander_new srcParam( src );
+	// Assign to destination.
+	ast::Expr * dstSelect = new ast::MemberExpr(
+		location,
+		field,
+		new ast::CastExpr(
+			location,
+			new ast::VariableExpr( location, dstParam ),
+			dstParam->type.strict_as<ast::ReferenceType>()->base
+		)
+	);
+	return genImplicitCall(
+		srcParam, dstSelect, location, func->name,
+		field, direction
+	);
+}
+
+template<typename Iterator>
+void StructFuncGenerator::makeFunctionBody( Iterator current, Iterator end,
+		ast::FunctionDecl * func, SymTab::LoopDirection direction ) {
+	// Trying to get the best code location. Should probably use a helper or
+	// just figure out what that would be given where this is called.
+	assert( nullptr == func->stmts );
+	const CodeLocation& location = func->location;
+
+	ast::CompoundStmt * stmts = new ast::CompoundStmt( location );
+
+	for ( ; current != end ; ++current ) {
+		const ast::ptr<ast::Decl> & member = *current;
+		auto field = member.as<ast::ObjectDecl>();
+		if ( nullptr == field ) {
+			continue;
+		}
+
+		// Don't assign to constant members (but do construct/destruct them).
+		if ( CodeGen::isAssignment( func->name ) ) {
+			// For array types we need to strip off the array layers.
+			const ast::Type * type = field->get_type();
+			while ( auto at = dynamic_cast<const ast::ArrayType *>( type ) ) {
+				type = at->base;
+			}
+			if ( type->is_const() ) {
+				continue;
+			}
+		}
+
+		assert( !func->params.empty() );
+		const ast::ObjectDecl * dstParam =
+			func->params.front().strict_as<ast::ObjectDecl>();
+		const ast::ObjectDecl * srcParam = nullptr;
+		if ( 2 == func->params.size() ) {
+			srcParam = func->params.back().strict_as<ast::ObjectDecl>();
+		}
+
+		ast::Expr * srcSelect = (srcParam) ? new ast::MemberExpr(
+			location, field, new ast::VariableExpr( location, srcParam )
+		) : nullptr;
+		ast::ptr<ast::Stmt> stmt =
+			makeMemberOp( location, dstParam, srcSelect, field, func, direction );
+
+		if ( nullptr != stmt ) {
+			stmts->kids.push_back( stmt );
+		}
+	}
+
+	func->stmts = stmts;
+}
+
+template<typename Iterator>
+void StructFuncGenerator::makeFieldCtorBody( Iterator current, Iterator end,
+		ast::FunctionDecl * func ) {
+	const CodeLocation& location = func->location;
+	auto & params = func->params;
+	// Need at least the constructed parameter and one field parameter.
+	assert( 2 <= params.size() );
+
+	ast::CompoundStmt * stmts = new ast::CompoundStmt( location );
+
+	auto dstParam = params.front().strict_as<ast::ObjectDecl>();
+	// Skip over the 'this' parameter.
+	for ( auto param = params.begin() + 1 ; current != end ; ++current ) {
+		const ast::ptr<ast::Decl> & member = *current;
+		ast::ptr<ast::Stmt> stmt = nullptr;
+		auto field = member.as<ast::ObjectDecl>();
+		// Not sure why it could be null.
+		// Don't make a function for a parameter that is an unnamed bitfield.
+		if ( nullptr == field || SymTab::isUnnamedBitfield( field ) ) {
+			continue;
+		// Matching Parameter: Initialize the field by copy.
+		} else if ( params.end() != param ) {
+			const ast::Expr *srcSelect = new ast::VariableExpr(
+				func->location, param->get() );
+			stmt = makeMemberOp( location, dstParam, srcSelect, field, func, SymTab::LoopForward );
+			++param;
+		// No Matching Parameter: Initialize the field by default constructor.
+		} else {
+			stmt = makeMemberOp( location, dstParam, nullptr, field, func, SymTab::LoopForward );
+		}
+
+		if ( nullptr != stmt ) {
+			stmts->kids.push_back( stmt );
+		}
+	}
+	func->stmts = stmts;
+}
+
+void UnionFuncGenerator::genFieldCtors() {
+	// Field constructors are only generated if default and copy constructor
+	// are generated, since they need access to both
+	unsigned numCtors = std::count_if( definitions.begin(), definitions.end(),
+		[]( const ast::Decl * d ){ return CodeGen::isConstructor( d->name ); }
+	);
+	if ( 2 != numCtors ) {
+		return;
+	}
+
+	// Create a constructor which takes the first member type as a
+	// parameter. For example for `union A { int x; char y; };` generate
+	// a function with signature `void ?{}(A *, int)`. This mimics C's
+	// behaviour which initializes the first member of the union.
+
+	// Still, there must be some members.
+	if ( !decl->members.empty() ) {
+		ast::FunctionDecl * ctor = genFieldCtorProto( 1 );
+		if ( nullptr == ctor ) {
+			return;
+		}
+		produceForwardDecl( ctor );
+		auto params = ctor->params;
+		auto dstParam = params.front().strict_as<ast::ObjectDecl>();
+		auto srcParam = params.back().strict_as<ast::ObjectDecl>();
+		ctor->stmts = new ast::CompoundStmt( getLocation(),
+			{ makeAssignOp( getLocation(), dstParam, srcParam ) }
+		);
+		produceDecl( ctor );
+	}
+}
+
+void UnionFuncGenerator::genFuncBody( ast::FunctionDecl * functionDecl ) {
+	const CodeLocation& location = functionDecl->location;
+	auto & params = functionDecl->params;
+	if ( InitTweak::isCopyConstructor( functionDecl )
+			|| InitTweak::isAssignment( functionDecl ) ) {
+		assert( 2 == params.size() );
+		auto dstParam = params.front().strict_as<ast::ObjectDecl>();
+		auto srcParam = params.back().strict_as<ast::ObjectDecl>();
+		functionDecl->stmts = new ast::CompoundStmt( location,
+			{ makeAssignOp( location, dstParam, srcParam ) }
+		);
+	} else {
+		assert( 1 == params.size() );
+		// Default constructor and destructor is empty.
+		functionDecl->stmts = new ast::CompoundStmt( location );
+		// Add unused attribute to parameter to silence warnings.
+		addUnusedAttribute( params.front() );
+
+		// Just an extra step to make the forward and declaration match.
+		if ( forwards.empty() ) return;
+		ast::FunctionDecl * fwd = strict_dynamic_cast<ast::FunctionDecl *>(
+			forwards.back().get_and_mutate() );
+		addUnusedAttribute( fwd->params.front() );
+	}
+}
+
+ast::ExprStmt * UnionFuncGenerator::makeAssignOp( const CodeLocation& location,
+		const ast::ObjectDecl * dstParam, const ast::ObjectDecl * srcParam ) {
+	return new ast::ExprStmt( location, new ast::UntypedExpr(
+		location,
+		new ast::NameExpr( location, "__builtin_memcpy" ),
+		{
+			new ast::AddressExpr( location,
+				new ast::VariableExpr( location, dstParam ) ),
+			new ast::AddressExpr( location,
+				new ast::VariableExpr( location, srcParam ) ),
+			new ast::SizeofExpr( location, srcParam->type ),
+		} ) );
+}
+
+void EnumFuncGenerator::genFieldCtors() {
+	// Enumerations to not have field constructors.
+}
+
+void EnumFuncGenerator::genFuncBody( ast::FunctionDecl * functionDecl ) {
+	const CodeLocation& location = functionDecl->location;
+	auto & params = functionDecl->params;
+	if ( InitTweak::isCopyConstructor( functionDecl )
+			|| InitTweak::isAssignment( functionDecl ) ) {
+		assert( 2 == params.size() );
+		auto dstParam = params.front().strict_as<ast::ObjectDecl>();
+		auto srcParam = params.back().strict_as<ast::ObjectDecl>();
+
+		/* This looks like a recursive call, but code-gen will turn it into
+		 * a C-style assignment.
+		 *
+		 * This is still before function pointer type conversion,
+		 * so this will have to do it manually.
+		 *
+		 * It will also reference the parent function declaration, creating
+		 * a cycle for references. This also means that the ref-counts are
+		 * now non-zero and the declaration will be deleted if it ever
+		 * returns to zero.
+		 */
+		auto callExpr = new ast::ApplicationExpr( location,
+			ast::VariableExpr::functionPointer( location, functionDecl ),
+			{
+				new ast::VariableExpr( location, dstParam ),
+				new ast::VariableExpr( location, srcParam ),
+			}
+		);
+		functionDecl->stmts = new ast::CompoundStmt( location,
+			{ new ast::ExprStmt( location, callExpr ) }
+		);
+	} else {
+		assert( 1 == params.size() );
+		// Default constructor and destructor is empty.
+		functionDecl->stmts = new ast::CompoundStmt( location );
+		// Just add unused attribute to parameter to silence warnings.
+		addUnusedAttribute( params.front() );
+
+		// Just an extra step to make the forward and declaration match.
+		if ( forwards.empty() ) return;
+		ast::FunctionDecl * fwd = strict_dynamic_cast<ast::FunctionDecl *>(
+			forwards.back().get_and_mutate() );
+		addUnusedAttribute( fwd->params.front() );
+	}
+}
+
+void TypeFuncGenerator::genFieldCtors() {
+	// Opaque types do not have field constructors.
+}
+
+void TypeFuncGenerator::genFuncBody( ast::FunctionDecl * functionDecl ) {
+	const CodeLocation& location = functionDecl->location;
+	auto & params = functionDecl->type->params;
+	assertf( 1 == params.size() || 2 == params.size(),
+		"Incorrect number of parameters in autogenerated typedecl function: %zd",
+		params.size() );
+	auto dstParam = params.front().strict_as<ast::ObjectDecl>();
+	auto srcParam = (2 == params.size())
+		? params.back().strict_as<ast::ObjectDecl>() : nullptr;
+	// Generate appropriate calls to member constructor and assignment.
+	ast::UntypedExpr * expr = new ast::UntypedExpr( location,
+		new ast::NameExpr( location, functionDecl->name )
+	);
+	expr->args.push_back( new ast::CastExpr( location,
+		new ast::VariableExpr( location, dstParam ),
+		new ast::ReferenceType( decl->base )
+	) );
+	if ( srcParam ) {
+		expr->args.push_back( new ast::CastExpr( location,
+			new ast::VariableExpr( location, srcParam ),
+			decl->base
+		) );
+	}
+	functionDecl->stmts = new ast::CompoundStmt( location,
+		{ new ast::ExprStmt( location, expr ) }
+	);
+}
+
+} // namespace
+
+void autogenerateRoutines( ast::TranslationUnit & translationUnit ) {
+	ast::Pass<AutogenerateRoutines_new>::run( translationUnit );
+}
+
+} // Validate
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/Autogen.hpp
===================================================================
--- src/Validate/Autogen.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
+++ src/Validate/Autogen.hpp	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -0,0 +1,32 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// Autogen.hpp -- Generate automatic routines for data types.
+//
+// Author           : Andrew Beach
+// Created On       : Wed Dec  1 13:42:00 2021
+// Last Modified By : Andrew Beach
+// Last Modified On : Thr Dec  2 13:56:00 2021
+// Update Count     : 0
+//
+
+#pragma once
+
+namespace ast {
+    class TranslationUnit;
+}
+
+namespace Validate {
+
+void autogenerateRoutines( ast::TranslationUnit & translationUnit );
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/module.mk
===================================================================
--- src/Validate/module.mk	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/Validate/module.mk	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -16,4 +16,6 @@
 
 SRC_VALIDATE = \
+	Validate/Autogen.cpp \
+	Validate/Autogen.hpp \
 	Validate/CompoundLiteral.cpp \
 	Validate/CompoundLiteral.hpp \
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 5f3ba117d89cd71b0b82121f2363d27a6752b378)
+++ src/main.cc	(revision b56ad5e7e1abbbd650e2765fd6b0429712b6cfe6)
@@ -10,6 +10,6 @@
 // Created On       : Fri May 15 23:12:02 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue Nov 30 10:25:00 2021
-// Update Count     : 659
+// Last Modified On : Wed Jan 26 14:09:00 2022
+// Update Count     : 670
 //
 
@@ -55,4 +55,5 @@
 #include "ControlStruct/ExceptTranslate.h"  // for translateEHM
 #include "ControlStruct/FixLabels.hpp"      // for fixLabels
+#include "ControlStruct/HoistControlDecls.hpp" //  hoistControlDecls
 #include "ControlStruct/Mutate.h"           // for mutate
 #include "GenPoly/Box.h"                    // for box
@@ -73,4 +74,5 @@
 #include "SynTree/Visitor.h"                // for acceptAll
 #include "Tuples/Tuples.h"                  // for expandMemberTuples, expan...
+#include "Validate/Autogen.hpp"             // for autogenerateRoutines
 #include "Validate/FindSpecialDecls.h"      // for findGlobalDecls
 #include "Validate/CompoundLiteral.hpp"     // for handleCompoundLiterals
@@ -78,5 +80,4 @@
 #include "Validate/LabelAddressFixer.hpp"   // for fixLabelAddresses
 #include "Virtual/ExpandCasts.h"            // for expandCasts
-
 
 static void NewPass( const char * const name ) {
@@ -326,9 +327,12 @@
 		PASS( "Validate-B", SymTab::validate_B( translationUnit ) );
 		PASS( "Validate-C", SymTab::validate_C( translationUnit ) );
-		PASS( "Validate-D", SymTab::validate_D( translationUnit ) );
 
 		CodeTools::fillLocations( translationUnit );
 
 		if( useNewAST ) {
+			PASS( "Apply Concurrent Keywords", Concurrency::applyKeywords( translationUnit ) );
+			PASS( "Forall Pointer Decay", SymTab::decayForallPointers( translationUnit ) );
+			CodeTools::fillLocations( translationUnit );
+
 			if (Stats::Counters::enabled) {
 				ast::pass_visitor_stats.avg = Stats::Counters::build<Stats::Counters::AverageCounter<double>>("Average Depth - New");
@@ -338,4 +342,11 @@
 
 			forceFillCodeLocations( transUnit );
+
+			// Must happen before autogen routines are added.
+			PASS( "Hoist Control Declarations", ControlStruct::hoistControlDecls( transUnit ) );
+
+			// Must be after enum and pointer decay.
+			// Must be before compound literals.
+			PASS( "Generate Autogen Routines", Validate::autogenerateRoutines( transUnit ) );
 
 			PASS( "Implement Mutex", Concurrency::implementMutex( transUnit ) );
@@ -409,4 +420,5 @@
 			translationUnit = convert( move( transUnit ) );
 		} else {
+			PASS( "Validate-D", SymTab::validate_D( translationUnit ) );
 			PASS( "Validate-E", SymTab::validate_E( translationUnit ) );
 			PASS( "Validate-F", SymTab::validate_F( translationUnit ) );
