Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/AST/Convert.cpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -10,6 +10,6 @@
 // Created On       : Thu May 09 15::37::05 2019
 // Last Modified By : Andrew Beach
-// Last Modified On : Wed Mar 16 15:01:00 2022
-// Update Count     : 42
+// Last Modified On : Wed Apr 20 13:58:00 2022
+// Update Count     : 43
 //
 
@@ -562,21 +562,27 @@
 		for ( auto clause : node->clauses ) {
 			stmt->clauses.push_back({{
-					get<Expression>().accept1( clause.target.func ),
-					get<Expression>().acceptL( clause.target.args ),
+					get<Expression>().accept1( clause->target_func ),
+					get<Expression>().acceptL( clause->target_args ),
 				},
-				get<Statement>().accept1( clause.stmt ),
-				get<Expression>().accept1( clause.cond ),
+				get<Statement>().accept1( clause->stmt ),
+				get<Expression>().accept1( clause->cond ),
 			});
 		}
 		stmt->timeout = {
-			get<Expression>().accept1( node->timeout.time ),
-			get<Statement>().accept1( node->timeout.stmt ),
-			get<Expression>().accept1( node->timeout.cond ),
+			get<Expression>().accept1( node->timeout_time ),
+			get<Statement>().accept1( node->timeout_stmt ),
+			get<Expression>().accept1( node->timeout_cond ),
 		};
 		stmt->orelse = {
-			get<Statement>().accept1( node->orElse.stmt ),
-			get<Expression>().accept1( node->orElse.cond ),
+			get<Statement>().accept1( node->else_stmt ),
+			get<Expression>().accept1( node->else_cond ),
 		};
 		return stmtPostamble( stmt, node );
+	}
+
+	const ast::WaitForClause * visit( const ast::WaitForClause * node ) override final {
+		// There is no old-AST WaitForClause, so this should never be called.
+		assert( !node );
+		return nullptr;
 	}
 
@@ -2096,22 +2102,18 @@
 		stmt->clauses.reserve( old->clauses.size() );
 		for (size_t i = 0 ; i < old->clauses.size() ; ++i) {
-			stmt->clauses.push_back({
-				ast::WaitForStmt::Target{
-					GET_ACCEPT_1(clauses[i].target.function, Expr),
-					GET_ACCEPT_V(clauses[i].target.arguments, Expr)
-				},
-				GET_ACCEPT_1(clauses[i].statement, Stmt),
-				GET_ACCEPT_1(clauses[i].condition, Expr)
-			});
-		}
-		stmt->timeout = {
-			GET_ACCEPT_1(timeout.time, Expr),
-			GET_ACCEPT_1(timeout.statement, Stmt),
-			GET_ACCEPT_1(timeout.condition, Expr),
-		};
-		stmt->orElse = {
-			GET_ACCEPT_1(orelse.statement, Stmt),
-			GET_ACCEPT_1(orelse.condition, Expr),
-		};
+			auto clause = new ast::WaitForClause( old->location );
+
+			clause->target_func = GET_ACCEPT_1(clauses[i].target.function, Expr);
+			clause->target_args = GET_ACCEPT_V(clauses[i].target.arguments, Expr);
+			clause->stmt = GET_ACCEPT_1(clauses[i].statement, Stmt);
+			clause->cond = GET_ACCEPT_1(clauses[i].condition, Expr);
+
+			stmt->clauses.push_back( clause );
+		}
+		stmt->timeout_time = GET_ACCEPT_1(timeout.time, Expr);
+		stmt->timeout_stmt = GET_ACCEPT_1(timeout.statement, Stmt);
+		stmt->timeout_cond = GET_ACCEPT_1(timeout.condition, Expr);
+		stmt->else_stmt = GET_ACCEPT_1(orelse.statement, Stmt);
+		stmt->else_cond = GET_ACCEPT_1(orelse.condition, Expr);
 
 		this->node = stmt;
@@ -2727,5 +2729,6 @@
 			ty->forall.emplace_back(new ast::TypeInstType(param));
 			for (auto asst : param->assertions) {
-				ty->assertions.emplace_back(new ast::VariableExpr({}, asst));
+				ty->assertions.emplace_back(
+					new ast::VariableExpr(param->location, asst));
 			}
 		}
Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/AST/Fwd.hpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -56,4 +56,5 @@
 class SuspendStmt;
 class WaitForStmt;
+class WaitForClause;
 class WithStmt;
 class DeclStmt;
Index: src/AST/Node.cpp
===================================================================
--- src/AST/Node.cpp	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/AST/Node.cpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -176,4 +176,6 @@
 template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::weak >;
 template class ast::ptr_base< ast::WaitForStmt, ast::Node::ref_type::strong >;
+template class ast::ptr_base< ast::WaitForClause, ast::Node::ref_type::weak >;
+template class ast::ptr_base< ast::WaitForClause, ast::Node::ref_type::strong >;
 template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::weak >;
 template class ast::ptr_base< ast::WithStmt, ast::Node::ref_type::strong >;
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/AST/Pass.hpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -158,4 +158,5 @@
 	const ast::Stmt *             visit( const ast::SuspendStmt          * ) override final;
 	const ast::Stmt *             visit( const ast::WaitForStmt          * ) override final;
+	const ast::WaitForClause *    visit( const ast::WaitForClause        * ) override final;
 	const ast::Decl *             visit( const ast::WithStmt             * ) override final;
 	const ast::NullStmt *         visit( const ast::NullStmt             * ) override final;
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/AST/Pass.impl.hpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -1010,81 +1010,31 @@
 const ast::Stmt * ast::Pass< core_t >::visit( const ast::WaitForStmt * node ) {
 	VISIT_START( node );
-		// for( auto & clause : node->clauses ) {
-		// 	maybeAccept_impl( clause.target.function, *this );
-		// 	maybeAccept_impl( clause.target.arguments, *this );
-
-		// 	maybeAccept_impl( clause.statement, *this );
-		// 	maybeAccept_impl( clause.condition, *this );
-		// }
-
-	if ( __visit_children() ) {
-		std::vector<WaitForStmt::Clause> new_clauses;
-		new_clauses.reserve( node->clauses.size() );
-		bool mutated = false;
-		for( const auto & clause : node->clauses ) {
-
-			const Expr * func = clause.target.func ? clause.target.func->accept(*this) : nullptr;
-			if(func != clause.target.func) mutated = true;
-			else func = nullptr;
-
-			std::vector<ptr<Expr>> new_args;
-			new_args.reserve(clause.target.args.size());
-			for( const auto & arg : clause.target.args ) {
-				auto a = arg->accept(*this);
-				if( a != arg ) {
-					mutated = true;
-					new_args.push_back( a );
-				} else
-					new_args.push_back( nullptr );
-			}
-
-			const Stmt * stmt = clause.stmt ? clause.stmt->accept(*this) : nullptr;
-			if(stmt != clause.stmt) mutated = true;
-			else stmt = nullptr;
-
-			const Expr * cond = clause.cond ? clause.cond->accept(*this) : nullptr;
-			if(cond != clause.cond) mutated = true;
-			else cond = nullptr;
-
-			new_clauses.push_back( WaitForStmt::Clause{ {func, std::move(new_args) }, stmt, cond } );
-		}
-
-		if(mutated) {
-			auto n = __pass::mutate<core_t>(node);
-			for(size_t i = 0; i < new_clauses.size(); i++) {
-				if(new_clauses.at(i).target.func != nullptr) swap(n->clauses.at(i).target.func, new_clauses.at(i).target.func);
-
-				for(size_t j = 0; j < new_clauses.at(i).target.args.size(); j++) {
-					if(new_clauses.at(i).target.args.at(j) != nullptr) swap(n->clauses.at(i).target.args.at(j), new_clauses.at(i).target.args.at(j));
-				}
-
-				if(new_clauses.at(i).stmt != nullptr) swap(n->clauses.at(i).stmt, new_clauses.at(i).stmt);
-				if(new_clauses.at(i).cond != nullptr) swap(n->clauses.at(i).cond, new_clauses.at(i).cond);
-			}
-			node = n;
-		}
-	}
-
-	#define maybe_accept(field) \
-		if(node->field) { \
-			auto nval = call_accept( node->field ); \
-			if(nval.differs ) { \
-				auto nparent = __pass::mutate<core_t>(node); \
-				nparent->field = nval.value; \
-				node = nparent; \
-			} \
-		}
-
-	if ( __visit_children() ) {
-		maybe_accept( timeout.time );
-		maybe_accept( timeout.stmt );
-		maybe_accept( timeout.cond );
-		maybe_accept( orElse.stmt  );
-		maybe_accept( orElse.cond  );
-	}
-
-	#undef maybe_accept
+
+	if ( __visit_children() ) {
+		maybe_accept( node, &WaitForStmt::clauses );
+		maybe_accept( node, &WaitForStmt::timeout_time );
+		maybe_accept( node, &WaitForStmt::timeout_stmt );
+		maybe_accept( node, &WaitForStmt::timeout_cond );
+		maybe_accept( node, &WaitForStmt::else_stmt );
+		maybe_accept( node, &WaitForStmt::else_cond );
+	}
 
 	VISIT_END( Stmt, node );
+}
+
+//--------------------------------------------------------------------------
+// WaitForClause
+template< typename core_t >
+const ast::WaitForClause * ast::Pass< core_t >::visit( const ast::WaitForClause * node ) {
+	VISIT_START( node );
+
+	if ( __visit_children() ) {
+		maybe_accept( node, &WaitForClause::target_func );
+		maybe_accept( node, &WaitForClause::target_args );
+		maybe_accept( node, &WaitForClause::stmt );
+		maybe_accept( node, &WaitForClause::cond );
+	}
+
+	VISIT_END( WaitForClause, node );
 }
 
Index: src/AST/Print.cpp
===================================================================
--- src/AST/Print.cpp	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/AST/Print.cpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -760,50 +760,55 @@
 		indent += 2;
 		for( const auto & clause : node->clauses ) {
-			os << indent-1 << "target function: ";
-			safe_print( clause.target.func );
-
-			if ( ! clause.target.args.empty() ) {
-				os << endl << indent-1 << "... with arguments:" << endl;
-				for( const ast::Expr * arg : clause.target.args ) {
-					arg->accept( *this );
-				}
+			clause->accept( *this );
+		}
+
+		if ( node->timeout_time ) {
+			os << indent-1 << "timeout of:" << endl;
+			node->timeout_time->accept( *this );
+
+			if ( node->timeout_stmt ) {
+				os << indent-1 << "... with statment:" << endl;
+				node->timeout_stmt->accept( *this );
 			}
 
-			if ( clause.stmt ) {
-				os << indent-1 << "... with statment:" << endl;
-				clause.stmt->accept( *this );
+			if ( node->timeout_cond ) {
+				os << indent-1 << "... with condition:" << endl;
+				node->timeout_cond->accept( *this );
 			}
-
-			if ( clause.cond ) {
+		}
+
+		if ( node->else_stmt ) {
+			os << indent-1 << "else:" << endl;
+			node->else_stmt->accept( *this );
+
+			if ( node->else_cond ) {
 				os << indent-1 << "... with condition:" << endl;
-				clause.cond->accept( *this );
+				node->else_cond->accept( *this );
 			}
 		}
 
-		if ( node->timeout.time ) {
-			os << indent-1 << "timeout of:" << endl;
-			node->timeout.time->accept( *this );
-
-			if ( node->timeout.stmt ) {
-				os << indent-1 << "... with statment:" << endl;
-				node->timeout.stmt->accept( *this );
+		return node;
+	}
+
+	virtual const ast::WaitForClause * visit( const ast::WaitForClause * node ) override final {
+		os << indent-1 << "target function: ";
+		safe_print( node->target_func );
+
+		if ( !node->target_args.empty() ) {
+			os << endl << indent-1 << "... with arguments:" << endl;
+			for( const ast::Expr * arg : node->target_args ) {
+				arg->accept( *this );
 			}
-
-			if ( node->timeout.cond ) {
-				os << indent-1 << "... with condition:" << endl;
-				node->timeout.cond->accept( *this );
-			}
-		}
-
-		if ( node->orElse.stmt ) {
-			os << indent-1 << "else:" << endl;
-			node->orElse.stmt->accept( *this );
-
-			if ( node->orElse.cond ) {
-				os << indent-1 << "... with condition:" << endl;
-				node->orElse.cond->accept( *this );
-			}
-		}
-		indent -= 2;
+		}
+
+		if ( node->stmt ) {
+			os << indent-1 << "... with statment:" << endl;
+			node->stmt->accept( *this );
+		}
+
+		if ( node->cond ) {
+			os << indent-1 << "... with condition:" << endl;
+			node->cond->accept( *this );
+		}
 
 		return node;
Index: src/AST/Stmt.hpp
===================================================================
--- src/AST/Stmt.hpp	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/AST/Stmt.hpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -10,6 +10,6 @@
 // Created On       : Wed May  8 13:00:00 2019
 // Last Modified By : Andrew Beach
-// Last Modified On : Mon Mar 28  9:50:00 2022
-// Update Count     : 35
+// Last Modified On : Wed Apr 20 14:34:00 2022
+// Update Count     : 36
 //
 
@@ -378,29 +378,10 @@
 class WaitForStmt final : public Stmt {
   public:
-	struct Target {
-		ptr<Expr> func;
-		std::vector<ptr<Expr>> args;
-	};
-
-	struct Clause {
-		Target target;
-		ptr<Stmt> stmt;
-		ptr<Expr> cond;
-	};
-
-	struct Timeout {
-		ptr<Expr> time;
-		ptr<Stmt> stmt;
-		ptr<Expr> cond;
-	};
-
-	struct OrElse {
-		ptr<Stmt> stmt;
-		ptr<Expr> cond;
-	};
-
-	std::vector<Clause> clauses;
-	Timeout timeout;
-	OrElse orElse;
+	std::vector<ptr<WaitForClause>> clauses;
+	ptr<Expr> timeout_time;
+	ptr<Stmt> timeout_stmt;
+	ptr<Expr> timeout_cond;
+	ptr<Stmt> else_stmt;
+	ptr<Expr> else_cond;
 
 	WaitForStmt( const CodeLocation & loc, const std::vector<Label> && labels = {} )
@@ -411,4 +392,20 @@
 	WaitForStmt * clone() const override { return new WaitForStmt{ *this }; }
 	MUTATE_FRIEND
+};
+
+class WaitForClause final : public StmtClause {
+  public:
+    ptr<Expr> target_func;
+    std::vector<ptr<Expr>> target_args;
+    ptr<Stmt> stmt;
+    ptr<Expr> cond;
+
+    WaitForClause( const CodeLocation & loc )
+		: StmtClause( loc ) {}
+
+	const WaitForClause * accept( Visitor & v ) const override { return v.visit( this ); }
+  private:
+    WaitForClause * clone() const override { return new WaitForClause{ *this }; }
+    MUTATE_FRIEND
 };
 
Index: src/AST/Visitor.hpp
===================================================================
--- src/AST/Visitor.hpp	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/AST/Visitor.hpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -50,4 +50,5 @@
     virtual const ast::Stmt *             visit( const ast::SuspendStmt          * ) = 0;
     virtual const ast::Stmt *             visit( const ast::WaitForStmt          * ) = 0;
+    virtual const ast::WaitForClause *    visit( const ast::WaitForClause        * ) = 0;
     virtual const ast::Decl *             visit( const ast::WithStmt             * ) = 0;
     virtual const ast::NullStmt *         visit( const ast::NullStmt             * ) = 0;
Index: src/Common/CodeLocationTools.cpp
===================================================================
--- src/Common/CodeLocationTools.cpp	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/Common/CodeLocationTools.cpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -121,4 +121,5 @@
     macro(SuspendStmt, Stmt) \
     macro(WaitForStmt, Stmt) \
+    macro(WaitForClause, WaitForClause) \
     macro(WithStmt, Decl) \
     macro(NullStmt, NullStmt) \
Index: src/Common/utility.h
===================================================================
--- src/Common/utility.h	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/Common/utility.h	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Feb 11 13:00:36 2020
-// Update Count     : 50
+// Last Modified By : Andrew Beach
+// Last Modified On : Mon Apr 25 14:26:00 2022
+// Update Count     : 51
 //
 
@@ -230,4 +230,10 @@
 }
 
+template<typename Container, typename Pred>
+void erase_if( Container & cont, Pred && pred ) {
+	auto keep_end = std::remove_if( cont.begin(), cont.end(), pred );
+	cont.erase( keep_end, cont.end() );
+}
+
 template< typename... Args >
 auto zip(Args&&... args) -> decltype(zipWith(std::forward<Args>(args)..., std::make_pair)) {
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/ResolvExpr/Resolver.cc	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 12:17:01 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri Mar 18 10:41:00 2022
-// Update Count     : 247
+// Last Modified On : Wed Apr 20 10:41:00 2022
+// Update Count     : 248
 //
 
@@ -1722,5 +1722,5 @@
 		// Resolve all clauses first
 		for ( unsigned i = 0; i < stmt->clauses.size(); ++i ) {
-			const ast::WaitForStmt::Clause & clause = stmt->clauses[i];
+			const ast::WaitForClause & clause = *stmt->clauses[i];
 
 			ast::TypeEnvironment env;
@@ -1728,15 +1728,15 @@
 
 			// Find all candidates for a function in canonical form
-			funcFinder.find( clause.target.func, ResolvMode::withAdjustment() );
+			funcFinder.find( clause.target_func, ResolvMode::withAdjustment() );
 
 			if ( funcFinder.candidates.empty() ) {
 				stringstream ss;
 				ss << "Use of undeclared indentifier '";
-				ss << clause.target.func.strict_as< ast::NameExpr >()->name;
+				ss << clause.target_func.strict_as< ast::NameExpr >()->name;
 				ss << "' in call to waitfor";
 				SemanticError( stmt->location, ss.str() );
 			}
 
-			if ( clause.target.args.empty() ) {
+			if ( clause.target_args.empty() ) {
 				SemanticError( stmt->location,
 					"Waitfor clause must have at least one mutex parameter");
@@ -1745,5 +1745,5 @@
 			// Find all alternatives for all arguments in canonical form
 			std::vector< CandidateFinder > argFinders =
-				funcFinder.findSubExprs( clause.target.args );
+				funcFinder.findSubExprs( clause.target_args );
 
 			// List all combinations of arguments
@@ -1918,9 +1918,9 @@
 
 			// build new clause
-			ast::WaitForStmt::Clause clause2;
-
-			clause2.target.func = funcCandidates.front()->expr;
-
-			clause2.target.args.reserve( clause.target.args.size() );
+			auto clause2 = new ast::WaitForClause( clause.location );
+
+			clause2->target_func = funcCandidates.front()->expr;
+
+			clause2->target_args.reserve( clause.target_args.size() );
 			const ast::StructDecl * decl_monitor = symtab.lookupStruct( "monitor$" );
 			for ( auto arg : argsCandidates.front() ) {
@@ -1939,43 +1939,42 @@
 				);
 
-				clause2.target.args.emplace_back( findSingleExpression( init, context ) );
+				clause2->target_args.emplace_back( findSingleExpression( init, context ) );
 			}
 
 			// Resolve the conditions as if it were an IfStmt, statements normally
-			clause2.cond = findSingleExpression( clause.cond, context );
-			clause2.stmt = clause.stmt->accept( *visitor );
+			clause2->cond = findSingleExpression( clause.cond, context );
+			clause2->stmt = clause.stmt->accept( *visitor );
 
 			// set results into stmt
 			auto n = mutate( stmt );
-			n->clauses[i] = std::move( clause2 );
+			n->clauses[i] = clause2;
 			stmt = n;
 		}
 
-		if ( stmt->timeout.stmt ) {
+		if ( stmt->timeout_stmt ) {
 			// resolve the timeout as a size_t, the conditions like IfStmt, and stmts normally
-			ast::WaitForStmt::Timeout timeout2;
-
 			ast::ptr< ast::Type > target =
 				new ast::BasicType{ ast::BasicType::LongLongUnsignedInt };
-			timeout2.time = findSingleExpression( stmt->timeout.time, target, context );
-			timeout2.cond = findSingleExpression( stmt->timeout.cond, context );
-			timeout2.stmt = stmt->timeout.stmt->accept( *visitor );
+			auto timeout_time = findSingleExpression( stmt->timeout_time, target, context );
+			auto timeout_cond = findSingleExpression( stmt->timeout_cond, context );
+			auto timeout_stmt = stmt->timeout_stmt->accept( *visitor );
 
 			// set results into stmt
 			auto n = mutate( stmt );
-			n->timeout = std::move( timeout2 );
+			n->timeout_time = std::move( timeout_time );
+			n->timeout_cond = std::move( timeout_cond );
+			n->timeout_stmt = std::move( timeout_stmt );
 			stmt = n;
 		}
 
-		if ( stmt->orElse.stmt ) {
+		if ( stmt->else_stmt ) {
 			// resolve the condition like IfStmt, stmts normally
-			ast::WaitForStmt::OrElse orElse2;
-
-			orElse2.cond = findSingleExpression( stmt->orElse.cond, context );
-			orElse2.stmt = stmt->orElse.stmt->accept( *visitor );
+			auto else_cond = findSingleExpression( stmt->else_cond, context );
+			auto else_stmt = stmt->else_stmt->accept( *visitor );
 
 			// set results into stmt
 			auto n = mutate( stmt );
-			n->orElse = std::move( orElse2 );
+			n->else_cond = std::move( else_cond );
+			n->else_stmt = std::move( else_stmt );
 			stmt = n;
 		}
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/SymTab/Validate.cc	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 21:50:04 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri Nov 12 11:00:00 2021
-// Update Count     : 364
+// Last Modified On : Fri Apr 29  9:45:00 2022
+// Update Count     : 365
 //
 
@@ -143,4 +143,5 @@
 	struct LinkReferenceToTypes_old final : public WithIndexer, public WithGuards, public WithVisitorRef<LinkReferenceToTypes_old>, public WithShortCircuiting {
 		LinkReferenceToTypes_old( const Indexer * indexer );
+
 		void postvisit( TypeInstType * typeInst );
 
@@ -370,11 +371,15 @@
 	}
 
+	void linkReferenceToTypes( std::list< Declaration * > & translationUnit ) {
+		PassVisitor<LinkReferenceToTypes_old> lrt( nullptr );
+		acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions
+	}
+
 	void validate_B( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<LinkReferenceToTypes_old> lrt( nullptr );
 		PassVisitor<FixQualifiedTypes> fixQual;
 		{
 			Stats::Heap::newPass("validate-B");
 			Stats::Time::BlockGuard guard("validate-B");
-			acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions
+			//linkReferenceToTypes( translationUnit );
 			mutateAll( translationUnit, fixQual ); // must happen after LinkReferenceToTypes_old, because aggregate members are accessed
 			HoistStruct::hoistStruct( translationUnit );
Index: src/SymTab/Validate.h
===================================================================
--- src/SymTab/Validate.h	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/SymTab/Validate.h	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -42,4 +42,5 @@
 	void validate_E( std::list< Declaration * > &translationUnit );
 	void validate_F( std::list< Declaration * > &translationUnit );
+	void linkReferenceToTypes( std::list< Declaration * > &translationUnit );
 
 	const ast::Type * validateType(
Index: src/Validate/EliminateTypedef.cpp
===================================================================
--- src/Validate/EliminateTypedef.cpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
+++ src/Validate/EliminateTypedef.cpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -0,0 +1,79 @@
+//
+// 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.
+//
+// EliminateTypedef.cpp -- Removes TypedefDecl nodes from the AST.
+//
+// Author           : Andrew Beach
+// Created On       : Wed Apr 20 16:37:00 2022
+// Last Modified By : Andrew Beach
+// Last Modified On : Mon Apr 25 14:26:00 2022
+// Update Count     : 0
+//
+
+#include "Validate/EliminateTypedef.hpp"
+
+#include <algorithm>
+
+#include "AST/Decl.hpp"
+#include "AST/Pass.hpp"
+#include "AST/Stmt.hpp"
+#include "Common/utility.h"
+
+namespace Validate {
+
+namespace {
+
+struct EliminateTypedefCore {
+	ast::StructDecl const * previsit( ast::StructDecl const * decl );
+	ast::UnionDecl const * previsit( ast::UnionDecl const * decl );
+	ast::CompoundStmt const * previsit( ast::CompoundStmt const * stmt );
+};
+
+bool isTypedef( ast::ptr<ast::Decl> const & decl ) {
+	return (nullptr != decl.as<ast::TypedefDecl>());
+}
+
+bool isTypedefStmt( ast::ptr<ast::Stmt> const & stmt ) {
+	if ( auto declStmt = stmt.as<ast::DeclStmt>() ) {
+		return isTypedef( declStmt->decl );
+	}
+	return false;
+}
+
+template<typename node_t, typename super_t, typename field_t, typename pred_t>
+node_t const * field_erase_if( node_t const * node, field_t super_t::*field, pred_t && pred) {
+	node_t * mut = ast::mutate( node );
+	erase_if( mut->*field, pred );
+	return mut;
+}
+
+ast::StructDecl const * EliminateTypedefCore::previsit( ast::StructDecl const * decl ) {
+	return field_erase_if( decl, &ast::StructDecl::members, isTypedef );
+}
+
+ast::UnionDecl const * EliminateTypedefCore::previsit( ast::UnionDecl const * decl ) {
+	return field_erase_if( decl, &ast::UnionDecl::members, isTypedef );
+}
+
+ast::CompoundStmt const * EliminateTypedefCore::previsit( ast::CompoundStmt const * stmt ) {
+	return field_erase_if( stmt, &ast::CompoundStmt::kids, isTypedefStmt );
+}
+
+} // namespace
+
+/// Removes TypedefDecl nodes from the AST.
+void eliminateTypedef( ast::TranslationUnit & translationUnit ) {
+	ast::Pass<EliminateTypedefCore>::run( translationUnit );
+	erase_if( translationUnit.decls, isTypedef );
+}
+
+} // namespace Validate
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/EliminateTypedef.hpp
===================================================================
--- src/Validate/EliminateTypedef.hpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
+++ src/Validate/EliminateTypedef.hpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -0,0 +1,33 @@
+//
+// 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.
+//
+// EliminateTypedef.hpp -- Removes TypedefDecl nodes from the AST.
+//
+// Author           : Andrew Beach
+// Created On       : Wed Apr 20 16:35:00 2022
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Apr 20 16:38:00 2022
+// Update Count     : 0
+//
+
+#pragma once
+
+namespace ast {
+	class TranslationUnit;
+}
+
+namespace Validate {
+
+/// Removes TypedefDecl nodes from the AST.
+void eliminateTypedef( ast::TranslationUnit & translationUnit );
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/FixQualifiedTypes.cpp
===================================================================
--- src/Validate/FixQualifiedTypes.cpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
+++ src/Validate/FixQualifiedTypes.cpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -0,0 +1,106 @@
+//
+// 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.
+//
+// FixQualifiedTypes.cpp --
+//
+// Author           : Andrew Beach
+// Created On       : Thr Apr 21 11:13:00 2022
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Apr 22 11:36:00 2022
+// Update Count     : 0
+//
+
+#include "Validate/FixQualifiedTypes.hpp"
+
+#include "AST/Pass.hpp"
+#include "AST/TranslationUnit.hpp"
+#include "Validate/NoIdSymbolTable.hpp"
+
+namespace Validate {
+
+namespace {
+
+struct FixQualifiedTypesCore :
+		public WithNoIdSymbolTable, public ast::WithGuards {
+	CodeLocation const * location = nullptr;
+
+	void previsit( ast::ParseNode const * node ) {
+		GuardValue( location ) = &node->location;
+	}
+
+	ast::Type const * postvisit( ast::QualifiedType const * type ) {
+		assert( location );
+
+		ast::ptr<ast::Type> const & parent = type->parent;
+		ast::ptr<ast::Type> const & child = type->child;
+		if ( parent.as<ast::GlobalScopeType>() ) {
+			// .T => lookup T at global scope.
+			if ( auto inst = child.as<ast::TypeInstType>() ) {
+				auto td = symtab.globalLookupType( inst->name );
+				if ( !td ) {
+					SemanticError( *location, toString("Use of undefined global type ", inst->name) );
+				}
+				auto base = td->base;
+				assert( base );
+				ast::Type * ret = ast::deepCopy( base );
+				ret->qualifiers = type->qualifiers;
+				return ret;
+			} else {
+				// .T => T is not a type name.
+				assertf( false, "unhandled global qualified child type: %s", toCString(child) );
+			}
+		} else {
+			// S.T => S must be an aggregate type, find the declaration for T in S.
+			ast::AggregateDecl const * aggr = nullptr;
+			ast::BaseInstType const * instp = nullptr;
+			if ( auto inst = parent.as<ast::StructInstType>() ) {
+				aggr = inst->base;
+				instp = inst;
+			} else if ( auto inst = parent.as<ast::UnionInstType>() ) {
+				aggr = inst->base;
+				instp = inst;
+			} else {
+				SemanticError( *location, toString("Qualified type requires an aggregate on the left, but has: ", parent) );
+			}
+			// TODO: Need to handle forward declarations.
+			assert( aggr );
+			for ( ast::ptr<ast::Decl> const & member : aggr->members ) {
+				if ( auto inst = child.as<ast::TypeInstType>() ) {
+					if ( auto decl = member.as<ast::NamedTypeDecl>() ) {
+						if ( decl->name == inst->name ) {
+							assert( decl->base );
+							ast::Type * ret = ast::deepCopy( decl->base );
+							ret->qualifiers = type->qualifiers;
+							ast::TypeSubstitution sub( aggr->params, instp->params );
+							// = parent->genericSubstitution();
+							auto result = sub.apply(ret);
+							return result.node.release();
+						}
+					}
+				} else {
+					// S.T - S is not an aggregate => error.
+					assertf( false, "unhandled qualified child type: %s", toCString(type) );
+				}
+			}
+			// failed to find a satisfying definition of type
+			SemanticError( *location, toString("Undefined type in qualified type: ", type) );
+		}
+	}
+};
+
+} // namespace
+
+void fixQualifiedTypes( ast::TranslationUnit & translationUnit ) {
+	ast::Pass<FixQualifiedTypesCore>::run( translationUnit );
+}
+
+} // namespace Validate
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/FixQualifiedTypes.hpp
===================================================================
--- src/Validate/FixQualifiedTypes.hpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
+++ src/Validate/FixQualifiedTypes.hpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -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.
+//
+// FixQualifiedTypes.hpp --
+//
+// Author           : Andrew Beach
+// Created On       : Thr Apr 21 11:11:00 2022
+// Last Modified By : Andrew Beach
+// Last Modified On : Thr Apr 21 11:11:00 2022
+// Update Count     : 0
+//
+
+#pragma once
+
+namespace ast {
+	class TranslationUnit;
+}
+
+namespace Validate {
+
+void fixQualifiedTypes( ast::TranslationUnit & translationUnit );
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/ForallPointerDecay.cpp
===================================================================
--- src/Validate/ForallPointerDecay.cpp	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/Validate/ForallPointerDecay.cpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -10,6 +10,6 @@
 // Created On       : Tue Dec  7 16:15:00 2021
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri Feb 11 10:59:00 2022
-// Update Count     : 0
+// Last Modified On : Sat Apr 23 13:10:00 2022
+// Update Count     : 1
 //
 
@@ -237,4 +237,9 @@
 }
 
+std::vector<ast::ptr<ast::DeclWithType>> expandAssertions(
+		std::vector<ast::ptr<ast::DeclWithType>> const & old ) {
+	return TraitExpander::expandAssertions( old );
+}
+
 } // namespace Validate
 
Index: src/Validate/ForallPointerDecay.hpp
===================================================================
--- src/Validate/ForallPointerDecay.hpp	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/Validate/ForallPointerDecay.hpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -10,11 +10,15 @@
 // Created On       : Tue Dec  7 16:15:00 2021
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue Dec  8 11:50:00 2021
-// Update Count     : 0
+// Last Modified On : Sat Apr 23 13:13:00 2022
+// Update Count     : 1
 //
 
 #pragma once
 
+#include <vector>
+#include "AST/Node.hpp"
+
 namespace ast {
+	class DeclWithType;
 	class TranslationUnit;
 }
@@ -27,4 +31,8 @@
 void decayForallPointers( ast::TranslationUnit & transUnit );
 
+/// Expand all traits in an assertion list.
+std::vector<ast::ptr<ast::DeclWithType>> expandAssertions(
+        std::vector<ast::ptr<ast::DeclWithType>> const & );
+
 }
 
Index: src/Validate/GenericParameter.cpp
===================================================================
--- src/Validate/GenericParameter.cpp	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/Validate/GenericParameter.cpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -10,6 +10,6 @@
 // Created On       : Fri Mar 21 10:02:00 2022
 // Last Modified By : Andrew Beach
-// Last Modified On : Wed Apr 13 10:09:00 2022
-// Update Count     : 0
+// Last Modified On : Fri Apr 22 16:43:00 2022
+// Update Count     : 1
 //
 
@@ -22,4 +22,5 @@
 #include "AST/TranslationUnit.hpp"
 #include "AST/Type.hpp"
+#include "Validate/NoIdSymbolTable.hpp"
 
 namespace Validate {
@@ -138,31 +139,6 @@
 // --------------------------------------------------------------------------
 
-// A SymbolTable that only has the operations used in the Translate Dimension
-// pass. More importantly, it doesn't have some methods that should no be
-// called by the Pass template (lookupId and addId).
-class NoIdSymbolTable {
-	ast::SymbolTable base;
-public:
-#	define FORWARD_X( func, types_and_names, just_names ) \
-	inline auto func types_and_names -> decltype( base.func just_names ) { \
-		return base.func just_names ; \
-	}
-#	define FORWARD_0( func )         FORWARD_X( func, (),             () )
-#	define FORWARD_1( func, type )   FORWARD_X( func, (type arg),     (arg) )
-#	define FORWARD_2( func, t0, t1 ) FORWARD_X( func, (t0 a0, t1 a1), (a0, a1) )
-
-	FORWARD_0( enterScope )
-	FORWARD_0( leaveScope )
-	FORWARD_1( lookupType, const std::string &        )
-	FORWARD_1( addType   , const ast::NamedTypeDecl * )
-	FORWARD_1( addStruct , const ast::StructDecl *    )
-	FORWARD_1( addEnum   , const ast::EnumDecl *      )
-	FORWARD_1( addUnion  , const ast::UnionDecl *     )
-	FORWARD_1( addTrait  , const ast::TraitDecl *     )
-	FORWARD_2( addWith   , const std::vector< ast::ptr<ast::Expr> > &, const ast::Decl * )
-};
-
-struct TranslateDimensionCore : public ast::WithGuards {
-	NoIdSymbolTable symtab;
+struct TranslateDimensionCore :
+		public WithNoIdSymbolTable, public ast::WithGuards {
 
 	// SUIT: Struct- or Union- InstType
Index: src/Validate/HoistStruct.cpp
===================================================================
--- src/Validate/HoistStruct.cpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
+++ src/Validate/HoistStruct.cpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -0,0 +1,145 @@
+//
+// 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.
+//
+// HoistStruct.cpp -- Flattens nested type declarations.
+//
+// Author           : Andrew Beach
+// Created On       : Thr Apr 21 10:34:00 2022
+// Last Modified By : Andrew Beach
+// Last Modified On : Thr Apr 21 10:34:00 2022
+// Update Count     : 0
+//
+
+#include "Validate/HoistStruct.hpp"
+
+#include "AST/Pass.hpp"
+#include "AST/TranslationUnit.hpp"
+#include "Common/utility.h"
+
+namespace Validate {
+
+namespace {
+
+bool shouldHoist( ast::Decl const * decl ) {
+	return dynamic_cast< ast::StructDecl const * >( decl )
+		|| dynamic_cast< ast::UnionDecl const * >( decl )
+		|| dynamic_cast< ast::StaticAssertDecl const * >( decl );
+}
+
+/* This pass also does some renaming and internal field alteration, but the
+ * complex part is the actual hoisting. Hoisted declarations should always
+ * appear before the declaration they are hoisted out of and if two types are
+ * nested in the same declaration their order should not change.
+ */
+struct HoistStructCore final :
+		public ast::WithDeclsToAdd<>, public ast::WithGuards {
+	ast::StructDecl const * previsit( ast::StructDecl const * decl );
+	ast::StructDecl const * postvisit( ast::StructDecl const * decl );
+	ast::UnionDecl const * previsit( ast::UnionDecl const * decl );
+	ast::UnionDecl const * postvisit( ast::UnionDecl const * decl );
+	ast::StructInstType const * previsit( ast::StructInstType const * type );
+	ast::UnionInstType const * previsit( ast::UnionInstType const * type );
+	ast::EnumInstType const * previsit( ast::EnumInstType const * type );
+
+private:
+	template<typename AggrDecl>
+	AggrDecl const * preAggregate( AggrDecl const * );
+	template<typename AggrDecl>
+	AggrDecl const * postAggregate( AggrDecl const * );
+
+	ast::AggregateDecl const * parent = nullptr;
+};
+
+void qualifiedName( ast::AggregateDecl const * decl, std::ostringstream & ss ) {
+	if ( decl->parent ) {
+		qualifiedName( decl->parent, ss );
+	}
+	ss << "__" << decl->name;
+}
+
+std::string qualifiedName( ast::AggregateDecl const * decl ) {
+	std::ostringstream ss;
+	qualifiedName( decl, ss );
+	return ss.str();
+}
+
+template<typename AggrDecl>
+AggrDecl const * HoistStructCore::preAggregate( AggrDecl const * decl ) {
+	if ( parent ) {
+		auto mut = ast::mutate( decl );
+		mut->parent = parent;
+		mut->name = qualifiedName( mut );
+		return mut;
+	} else {
+		GuardValue( parent ) = decl;
+		return decl;
+	}
+}
+
+template<typename AggrDecl>
+AggrDecl const * HoistStructCore::postAggregate( AggrDecl const * decl ) {
+	auto mut = ast::mutate( decl );
+	for ( auto it = mut->members.begin() ; it != mut->members.end() ; ) {
+		if ( shouldHoist( *it ) ) {
+			// This is the place where the actual hoisting happens.
+			declsToAddBefore.push_back( it->get() );
+			it = mut->members.erase( it );
+		} else {
+			++it;
+		}
+	}
+	return mut;
+}
+
+ast::StructDecl const * HoistStructCore::previsit( ast::StructDecl const * decl ) {
+	return preAggregate( decl );
+}
+
+ast::StructDecl const * HoistStructCore::postvisit( ast::StructDecl const * decl ) {
+	return postAggregate( decl );
+}
+
+ast::UnionDecl const * HoistStructCore::previsit( ast::UnionDecl const * decl ) {
+	return preAggregate( decl );
+}
+
+ast::UnionDecl const * HoistStructCore::postvisit( ast::UnionDecl const * decl ) {
+	return postAggregate( decl );
+}
+
+template<typename InstType>
+InstType const * preInstType( InstType const * type ) {
+	assert( type->base );
+	auto mut = ast::mutate( type );
+	mut->name = mut->base->name;
+	return mut;
+}
+
+ast::StructInstType const * HoistStructCore::previsit( ast::StructInstType const * type ) {
+	return preInstType( type );
+}
+
+ast::UnionInstType const * HoistStructCore::previsit( ast::UnionInstType const * type ) {
+	return preInstType( type );
+}
+
+ast::EnumInstType const * HoistStructCore::previsit( ast::EnumInstType const * type ) {
+	return preInstType( type );
+}
+
+} // namespace
+
+void hoistStruct( ast::TranslationUnit & translationUnit ) {
+	ast::Pass<HoistStructCore>::run( translationUnit );
+}
+
+} // namespace Validate
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/HoistStruct.hpp
===================================================================
--- src/Validate/HoistStruct.hpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
+++ src/Validate/HoistStruct.hpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -0,0 +1,33 @@
+//
+// 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.
+//
+// HoistStruct.hpp -- Flattens nested type declarations.
+//
+// Author           : Andrew Beach
+// Created On       : Thr Apr 21 10:33:00 2022
+// Last Modified By : Andrew Beach
+// Last Modified On : Thr Apr 21 10:39:00 2022
+// Update Count     : 0
+//
+
+#pragma once
+
+namespace ast {
+	class TranslationUnit;
+}
+
+namespace Validate {
+
+/// Flattens nested type declarations.
+void hoistStruct( ast::TranslationUnit & translationUnit );
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/NoIdSymbolTable.hpp
===================================================================
--- src/Validate/NoIdSymbolTable.hpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
+++ src/Validate/NoIdSymbolTable.hpp	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -0,0 +1,70 @@
+//
+// 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.
+//
+// NoIdSymbolTable.hpp -- Special WithSymbolTable variant ast::Pass helper.
+//
+// Author           : Andrew Beach
+// Created On       : Thr Apr 21 11:57:00 2022
+// Last Modified By : Andrew Beach
+// Last Modified On : Thr Apr 21 11:57:00 2022
+// Update Count     : 0
+//
+
+#pragma once
+
+#include "AST/SymbolTable.hpp"
+
+namespace Validate {
+
+// A SymbolTable that only has the operations used in the Translate Dimension
+// pass. More importantly, it doesn't have some methods that should no be
+// called by the Pass template (lookupId and addId).
+class NoIdSymbolTable {
+	ast::SymbolTable base;
+public:
+#	define FORWARD_X( func, types_and_names, just_names ) \
+	inline auto func types_and_names -> decltype( base.func just_names ) { \
+		return base.func just_names ; \
+	}
+#	define FORWARD_0( func )         FORWARD_X( func, (),             () )
+#	define FORWARD_1( func, type )   FORWARD_X( func, (type arg),     (arg) )
+#	define FORWARD_2( func, t0, t1 ) FORWARD_X( func, (t0 a0, t1 a1), (a0, a1) )
+
+	FORWARD_0( enterScope )
+	FORWARD_0( leaveScope )
+	FORWARD_1( lookupType  , const std::string & )
+	FORWARD_1( lookupStruct, const std::string & )
+	FORWARD_1( lookupEnum  , const std::string & )
+	FORWARD_1( lookupUnion , const std::string & )
+	FORWARD_1( lookupTrait , const std::string & )
+	FORWARD_1( addType  , const ast::NamedTypeDecl * )
+	FORWARD_1( addStruct, const ast::StructDecl *    )
+	FORWARD_1( addEnum  , const ast::EnumDecl *      )
+	FORWARD_1( addUnion , const ast::UnionDecl *     )
+	FORWARD_1( addTrait , const ast::TraitDecl *     )
+	FORWARD_1( addStruct, const std::string &        )
+	FORWARD_1( addUnion , const std::string &        )
+	FORWARD_2( addWith  , const std::vector< ast::ptr<ast::Expr> > &, const ast::Decl * )
+
+	FORWARD_1( globalLookupType, const std::string & )
+
+#	undef FORWARD_2
+#	undef FORWARD_1
+#	undef FORWARD_0
+#	undef FORWARD_X
+};
+
+struct WithNoIdSymbolTable {
+	NoIdSymbolTable symtab;
+};
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/module.mk
===================================================================
--- src/Validate/module.mk	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/Validate/module.mk	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -20,4 +20,8 @@
 	Validate/CompoundLiteral.cpp \
 	Validate/CompoundLiteral.hpp \
+	Validate/EliminateTypedef.cpp \
+	Validate/EliminateTypedef.hpp \
+	Validate/FixQualifiedTypes.cpp \
+	Validate/FixQualifiedTypes.hpp \
 	Validate/ForallPointerDecay.cpp \
 	Validate/ForallPointerDecay.hpp \
@@ -26,8 +30,11 @@
 	Validate/HandleAttributes.cc \
 	Validate/HandleAttributes.h \
+	Validate/HoistStruct.cpp \
+	Validate/HoistStruct.hpp \
 	Validate/InitializerLength.cpp \
 	Validate/InitializerLength.hpp \
 	Validate/LabelAddressFixer.cpp \
 	Validate/LabelAddressFixer.hpp \
+	Validate/NoIdSymbolTable.hpp \
 	Validate/ReturnCheck.cpp \
 	Validate/ReturnCheck.hpp \
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 9e7236f4ea98982d55cddf21f808b612dbfe6ddf)
+++ src/main.cc	(revision 3b80db89ad8057ef837786b049cd89765ab7a20d)
@@ -10,6 +10,6 @@
 // Created On       : Fri May 15 23:12:02 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Wed Apr 13 11:11:00 2022
-// Update Count     : 672
+// Last Modified On : Fri Apr 29  9:52:00 2022
+// Update Count     : 673
 //
 
@@ -75,8 +75,11 @@
 #include "Tuples/Tuples.h"                  // for expandMemberTuples, expan...
 #include "Validate/Autogen.hpp"             // for autogenerateRoutines
+#include "Validate/CompoundLiteral.hpp"     // for handleCompoundLiterals
+#include "Validate/EliminateTypedef.hpp"    // for eliminateTypedef
+#include "Validate/FindSpecialDecls.h"      // for findGlobalDecls
+#include "Validate/FixQualifiedTypes.hpp"   // for fixQualifiedTypes
+#include "Validate/ForallPointerDecay.hpp"  // for decayForallPointers
 #include "Validate/GenericParameter.hpp"    // for fillGenericParameters, tr...
-#include "Validate/FindSpecialDecls.h"      // for findGlobalDecls
-#include "Validate/ForallPointerDecay.hpp"  // for decayForallPointers
-#include "Validate/CompoundLiteral.hpp"     // for handleCompoundLiterals
+#include "Validate/HoistStruct.hpp"         // for hoistStruct
 #include "Validate/InitializerLength.hpp"   // for setLengthFromInitializer
 #include "Validate/LabelAddressFixer.hpp"   // for fixLabelAddresses
@@ -328,5 +331,7 @@
 		// add the assignment statement after the initialization of a type parameter
 		PASS( "Validate-A", SymTab::validate_A( translationUnit ) );
-		PASS( "Validate-B", SymTab::validate_B( translationUnit ) );
+
+		// Must happen before auto-gen, because it uses the sized flag.
+		PASS( "Link Reference To Types", SymTab::linkReferenceToTypes( translationUnit ) );
 
 		CodeTools::fillLocations( translationUnit );
@@ -342,4 +347,11 @@
 
 			forceFillCodeLocations( transUnit );
+
+			// Must happen after Link References To Types,
+			// because aggregate members are accessed.
+			PASS( "Fix Qualified Types", Validate::fixQualifiedTypes( transUnit ) );
+
+			PASS( "Hoist Struct", Validate::hoistStruct( transUnit ) );
+			PASS( "Eliminate Typedef", Validate::eliminateTypedef( transUnit ) );
 
 			// Check as early as possible. Can't happen before
@@ -438,4 +450,5 @@
 			translationUnit = convert( move( transUnit ) );
 		} else {
+			PASS( "Validate-B", SymTab::validate_B( translationUnit ) );
 			PASS( "Validate-C", SymTab::validate_C( translationUnit ) );
 			PASS( "Validate-D", SymTab::validate_D( translationUnit ) );
