Index: Jenkins/Promote
===================================================================
--- Jenkins/Promote	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ Jenkins/Promote	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -36,5 +36,5 @@
 		dir (BuildDir) {
 		    sh 'rm -rf *'
-			sshagent (credentials: ['github_key_jun1']) {
+			sshagent (credentials: ['git_key_mar27']) {
 				sh "git clone --bare ${RemoteRepo} repo"
 			}
@@ -69,5 +69,5 @@
 			sh "git status"
 			sh "git diff-index --quiet HEAD || git commit -m 'Push from build machine: ${name}'"
-			sshagent (credentials: ['github_key_jun1']) {
+			sshagent (credentials: ['git_key_mar27']) {
 				sh "git push origin master"
 			}
Index: libcfa/src/concurrency/pthread.cfa
===================================================================
--- libcfa/src/concurrency/pthread.cfa	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ libcfa/src/concurrency/pthread.cfa	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -152,5 +152,5 @@
 
 //######################### Attr helpers #########################
-struct cfaPthread_attr_t {								// thread attributes
+typedef struct cfaPthread_attr_t {						// thread attributes
 		int contentionscope;
 		int detachstate;
@@ -160,5 +160,5 @@
 		int inheritsched;
 		struct sched_param param;
-} typedef cfaPthread_attr_t;
+} cfaPthread_attr_t;
 
 static const cfaPthread_attr_t default_attrs {
Index: libcfa/src/interpose.cfa
===================================================================
--- libcfa/src/interpose.cfa	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ libcfa/src/interpose.cfa	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -10,6 +10,6 @@
 // Created On       : Wed Mar 29 16:10:31 2017
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Mar 13 22:39:12 2023
-// Update Count     : 193
+// Last Modified On : Mon Mar 27 21:09:03 2023
+// Update Count     : 196
 //
 
@@ -40,6 +40,15 @@
 	union { generic_fptr_t fptr; void * ptr; } originalFunc;
 
+	#if defined( _GNU_SOURCE )
+	if ( version ) {
+		originalFunc.ptr = dlvsym( library, symbol, version );
+	} else {
+		originalFunc.ptr = dlsym( library, symbol );
+	} // if
+	#else
 	originalFunc.ptr = dlsym( library, symbol );
-	if ( ! originalFunc.ptr ) {								// == nullptr
+	#endif // _GNU_SOURCE
+
+	if ( ! originalFunc.ptr ) {							// == nullptr
 		abort( "interpose_symbol : internal error, %s\n", dlerror() );
 	} // if
@@ -49,4 +58,5 @@
 static generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) {
 	void * library;
+
 	#if defined( RTLD_NEXT )
 	library = RTLD_NEXT;
Index: libcfa/src/interpose_thread.cfa
===================================================================
--- libcfa/src/interpose_thread.cfa	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ libcfa/src/interpose_thread.cfa	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -14,4 +14,5 @@
 //
 
+// BUG in 32-bit gcc with interpose: fixed in >= gcc-9.5, gcc-10.4, gcc-12.2
 #ifdef __i386__											// 32-bit architecture
 #undef _GNU_SOURCE
@@ -33,9 +34,9 @@
 typedef void (* generic_fptr_t)(void);
 
-generic_fptr_t interpose_symbol(
+generic_fptr_t libcfa_public interpose_symbol(
 	generic_fptr_t (*do_interpose_symbol)( void * library, const char symbol[], const char version[] ),
 	const char symbol[],
 	const char version[]
-) libcfa_public {
+) {
 	void * library;
 
Index: src/AST/ParseNode.hpp
===================================================================
--- src/AST/ParseNode.hpp	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/AST/ParseNode.hpp	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -40,4 +40,6 @@
 	template<typename node_t>
 	friend node_t * mutate(const node_t * node);
+	template<typename node_t>
+	friend node_t * shallowCopy(const node_t * node);
 };
 
Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/CodeGen/CodeGenerator.cc	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -17,8 +17,8 @@
 #include <cassert>                   // for assert, assertf
 #include <list>                      // for _List_iterator, list, list<>::it...
+#include <sstream>                   // for stringstream
 
 #include "AST/Decl.hpp"              // for DeclWithType
 #include "Common/UniqueName.h"       // for UniqueName
-#include "Common/utility.h"          // for CodeLocation, toString
 #include "GenType.h"                 // for genType
 #include "InitTweak/InitTweak.h"     // for getPointerBase
Index: src/Common/DeclStats.cpp
===================================================================
--- src/Common/DeclStats.cpp	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/Common/DeclStats.cpp	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -23,4 +23,5 @@
 #include <iostream>
 #include <map>
+#include <sstream>
 #include <unordered_map>
 #include <unordered_set>
Index: src/Common/ResolvProtoDump.cpp
===================================================================
--- src/Common/ResolvProtoDump.cpp	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/Common/ResolvProtoDump.cpp	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -19,4 +19,5 @@
 #include <iostream>
 #include <set>
+#include <sstream>
 #include <unordered_set>
 
@@ -26,5 +27,4 @@
 #include "AST/Type.hpp"
 #include "CodeGen/OperatorTable.h"
-#include "Common/utility.h"
 
 namespace {
Index: src/Common/ToString.hpp
===================================================================
--- src/Common/ToString.hpp	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
+++ src/Common/ToString.hpp	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -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.
+//
+// ToString.hpp -- Tools to convert to string.
+//
+// Author           : Andrew Beach
+// Created On       : Tue Mar 28  9:24:00 2023
+// Last Modified By : Andrew Beach
+// Last Modified On : Tue Mar 28  9:24:00 2023
+// Update Count     : 0
+//
+
+#pragma once
+
+#include <string>
+#include <sstream>
+
+/// Convert all arguments to strings and concatenate them.
+template<typename... Params>
+std::string toString( const Params &... params ) {
+	std::ostringstream buffer;
+	(buffer << ... << params);
+	return buffer.str();
+}
+
+/// Convert all arguments to a C-string.
+/// It is a macro so that a underlying std::string manages the memory.
+#define toCString( ... ) toString( __VA_ARGS__ ).c_str()
Index: src/Common/module.mk
===================================================================
--- src/Common/module.mk	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/Common/module.mk	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -52,4 +52,5 @@
 	Common/Stats/Time.cc \
 	Common/Stats/Time.h \
+	Common/ToString.hpp \
 	Common/UniqueName.cc \
 	Common/UniqueName.h \
Index: src/Common/utility.h
===================================================================
--- src/Common/utility.h	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/Common/utility.h	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -22,5 +22,4 @@
 #include <list>
 #include <memory>
-#include <sstream>
 #include <string>
 #include <type_traits>
@@ -143,24 +142,4 @@
 	dst.swap( src );
 }
-
-template < typename T >
-void toString_single( std::ostream & os, const T & value ) {
-	os << value;
-}
-
-template < typename T, typename... Params >
-void toString_single( std::ostream & os, const T & value, const Params & ... params ) {
-	os << value;
-	toString_single( os, params ... );
-}
-
-template < typename ... Params >
-std::string toString( const Params & ... params ) {
-	std::ostringstream os;
-	toString_single( os, params... );
-	return os.str();
-}
-
-#define toCString( ... ) toString( __VA_ARGS__ ).c_str()
 
 template< typename... Args >
Index: src/ControlStruct/ExceptDeclNew.cpp
===================================================================
--- src/ControlStruct/ExceptDeclNew.cpp	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/ControlStruct/ExceptDeclNew.cpp	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -15,4 +15,6 @@
 
 #include "ExceptDecl.h"
+
+#include <sstream>
 
 #include "AST/Decl.hpp"
Index: src/ControlStruct/MLEMutator.cc
===================================================================
--- src/ControlStruct/MLEMutator.cc	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/ControlStruct/MLEMutator.cc	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -25,5 +25,5 @@
 #include <memory>                          // for allocator_traits<>::value_...
 
-#include "Common/utility.h"                // for toString, operator+
+#include "Common/ToString.hpp"             // for toString
 #include "ControlStruct/LabelGenerator.h"  // for LabelGenerator
 #include "MLEMutator.h"
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/GenPoly/Box.cc	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -31,5 +31,5 @@
 #include "Common/SemanticError.h"        // for SemanticError
 #include "Common/UniqueName.h"           // for UniqueName
-#include "Common/utility.h"              // for toString
+#include "Common/ToString.hpp"           // for toCString
 #include "FindFunction.h"                // for findFunction, findAndReplace...
 #include "GenPoly/ErasableScopedMap.h"   // for ErasableScopedMap<>::const_i...
Index: src/GenPoly/Lvalue.cc
===================================================================
--- src/GenPoly/Lvalue.cc	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/GenPoly/Lvalue.cc	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -17,4 +17,5 @@
 #include <string>                        // for string
 
+#include "Common/ToString.hpp"           // for toCString
 #include "Common/UniqueName.h"
 #include "Common/PassVisitor.h"
Index: src/GenPoly/LvalueNew.cpp
===================================================================
--- src/GenPoly/LvalueNew.cpp	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/GenPoly/LvalueNew.cpp	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -25,4 +25,5 @@
 #include "AST/Pass.hpp"
 #include "Common/SemanticError.h"      // for SemanticWarning
+#include "Common/ToString.hpp"         // for toCString
 #include "Common/UniqueName.h"         // for UniqueName
 #include "GenPoly/GenPoly.h"           // for genFunctionType
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/InitTweak/FixInit.cc	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -32,6 +32,6 @@
 #include "Common/PassVisitor.h"        // for PassVisitor, WithStmtsToAdd
 #include "Common/SemanticError.h"      // for SemanticError
+#include "Common/ToString.hpp"         // for toCString
 #include "Common/UniqueName.h"         // for UniqueName
-#include "Common/utility.h"            // for CodeLocation, ValueGuard, toSt...
 #include "FixGlobalInit.h"             // for fixGlobalInit
 #include "GenInit.h"                   // for genCtorDtor
Index: src/InitTweak/FixInitNew.cpp
===================================================================
--- src/InitTweak/FixInitNew.cpp	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/InitTweak/FixInitNew.cpp	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -20,6 +20,6 @@
 #include "Common/PassVisitor.h"        // for PassVisitor, WithStmtsToAdd
 #include "Common/SemanticError.h"      // for SemanticError
+#include "Common/ToString.hpp"         // for toCString
 #include "Common/UniqueName.h"         // for UniqueName
-#include "Common/utility.h"            // for CodeLocation, ValueGuard, toSt...
 #include "FixGlobalInit.h"             // for fixGlobalInit
 #include "GenInit.h"                   // for genCtorDtor
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/InitTweak/GenInit.cc	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -31,4 +31,5 @@
 #include "Common/PassVisitor.h"        // for PassVisitor, WithGuards, WithShort...
 #include "Common/SemanticError.h"      // for SemanticError
+#include "Common/ToString.hpp"         // for toCString
 #include "Common/UniqueName.h"         // for UniqueName
 #include "Common/utility.h"            // for ValueGuard, maybeClone
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/Parser/ParseNode.h	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -10,6 +10,6 @@
 // Created On       : Sat May 16 13:28:16 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sun Feb 19 09:02:37 2023
-// Update Count     : 940
+// Last Modified On : Wed Mar 29 08:40:27 2023
+// Update Count     : 948
 //
 
@@ -425,8 +425,7 @@
 Statement * build_directive( std::string * directive );
 SuspendStmt * build_suspend( StatementNode *, SuspendStmt::Type = SuspendStmt::None);
-WaitForStmt * build_waitfor( ExpressionNode * target, StatementNode * stmt, ExpressionNode * when );
-WaitForStmt * build_waitfor( ExpressionNode * target, StatementNode * stmt, ExpressionNode * when, WaitForStmt * existing );
-WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when );
-WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when, StatementNode * else_stmt, ExpressionNode * else_when );
+WaitForStmt * build_waitfor( WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt );
+WaitForStmt * build_waitfor_else( WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt );
+WaitForStmt * build_waitfor_timeout( WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt );
 Statement * build_with( ExpressionNode * exprs, StatementNode * stmt );
 Statement * build_mutex( ExpressionNode * exprs, StatementNode * stmt );
Index: src/Parser/StatementNode.cc
===================================================================
--- src/Parser/StatementNode.cc	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/Parser/StatementNode.cc	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -11,6 +11,6 @@
 // Created On       : Sat May 16 14:59:41 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  2 20:29:30 2022
-// Update Count     : 425
+// Last Modified On : Wed Mar 29 08:51:23 2023
+// Update Count     : 454
 //
 
@@ -268,9 +268,7 @@
 
 	return node;
-}
-
-WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when ) {
-	auto node = new WaitForStmt();
-
+} // build_suspend
+
+WaitForStmt * build_waitfor( WaitForStmt * existing, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) {
 	WaitForStmt::Target target;
 	target.function = maybeBuild( targetExpr );
@@ -282,24 +280,5 @@
 	delete targetExpr;
 
-	node->clauses.push_back( WaitForStmt::Clause{
-		target,
-		maybeMoveBuild( stmt ),
-		notZeroExpr( maybeMoveBuild( when ) )
-	});
-
-	return node;
-} // build_waitfor
-
-WaitForStmt * build_waitfor( ExpressionNode * targetExpr, StatementNode * stmt, ExpressionNode * when, WaitForStmt * node ) {
-	WaitForStmt::Target target;
-	target.function = maybeBuild( targetExpr );
-
-	ExpressionNode * next = dynamic_cast<ExpressionNode *>( targetExpr->get_next() );
-	targetExpr->set_next( nullptr );
-	buildMoveList< Expression >( next, target.arguments );
-
-	delete targetExpr;
-
-	node->clauses.insert( node->clauses.begin(), WaitForStmt::Clause{
+	existing->clauses.insert( existing->clauses.begin(), WaitForStmt::Clause{
 		std::move( target ),
 		maybeMoveBuild( stmt ),
@@ -307,33 +286,20 @@
 	});
 
-	return node;
+	return existing;
 } // build_waitfor
 
-WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when ) {
-	auto node = new WaitForStmt();
-
-	if( timeout ) {
-		node->timeout.time      = maybeMoveBuild( timeout );
-		node->timeout.statement = maybeMoveBuild( stmt    );
-		node->timeout.condition = notZeroExpr( maybeMoveBuild( when ) );
-	} else {
-		node->orelse.statement  = maybeMoveBuild( stmt );
-		node->orelse.condition  = notZeroExpr( maybeMoveBuild( when ) );
-	} // if
-
-	return node;
-} // build_waitfor_timeout
-
-WaitForStmt * build_waitfor_timeout( ExpressionNode * timeout, StatementNode * stmt, ExpressionNode * when,  StatementNode * else_, ExpressionNode * else_when ) {
-	auto node = new WaitForStmt();
-
-	node->timeout.time      = maybeMoveBuild( timeout );
-	node->timeout.statement = maybeMoveBuild( stmt    );
-	node->timeout.condition = notZeroExpr( maybeMoveBuild( when ) );
-
-	node->orelse.statement  = maybeMoveBuild( else_ );
-	node->orelse.condition  = notZeroExpr( maybeMoveBuild( else_when ) );
-
-	return node;
+WaitForStmt * build_waitfor_else( WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt ) {
+	existing->orelse.statement  = maybeMoveBuild( stmt );
+	existing->orelse.condition  = notZeroExpr( maybeMoveBuild( when ) );
+
+	return existing;
+} // build_waitfor_else
+
+WaitForStmt * build_waitfor_timeout( WaitForStmt * existing, ExpressionNode * when, ExpressionNode * timeout, StatementNode * stmt ) {
+	existing->timeout.time      = maybeMoveBuild( timeout );
+	existing->timeout.statement = maybeMoveBuild( stmt );
+	existing->timeout.condition = notZeroExpr( maybeMoveBuild( when ) );
+
+	return existing;
 } // build_waitfor_timeout
 
Index: src/Parser/lex.ll
===================================================================
--- src/Parser/lex.ll	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/Parser/lex.ll	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -10,6 +10,6 @@
  * Created On       : Sat Sep 22 08:58:10 2001
  * Last Modified By : Peter A. Buhr
- * Last Modified On : Mon Jan 30 19:03:34 2023
- * Update Count     : 767
+ * Last Modified On : Sat Mar 25 08:09:03 2023
+ * Update Count     : 768
  */
 
@@ -214,4 +214,5 @@
 __alignof		{ KEYWORD_RETURN(ALIGNOF); }			// GCC
 __alignof__		{ KEYWORD_RETURN(ALIGNOF); }			// GCC
+and				{ QKEYWORD_RETURN(WAND); }				// CFA
 asm				{ KEYWORD_RETURN(ASM); }
 __asm			{ KEYWORD_RETURN(ASM); }				// GCC
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/Parser/parser.yy	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -10,6 +10,6 @@
 // Created On       : Sat Sep  1 20:22:55 2001
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Mar 22 21:26:01 2023
-// Update Count     : 6002
+// Last Modified On : Wed Mar 29 17:56:42 2023
+// Update Count     : 6325
 //
 
@@ -44,4 +44,5 @@
 
 #include <cstdio>
+#include <sstream>
 #include <stack>
 using namespace std;
@@ -270,12 +271,4 @@
 	SemanticError( yylloc, ::toString( "Identifier \"", identifier, "\" cannot appear before a ", kind, ".\n"
 				   "Possible cause is misspelled storage/CV qualifier, misspelled typename, or missing generic parameter." ) );
-} // IdentifierBeforeType
-
-static bool TypedefForall( DeclarationNode * decl ) {
-	if ( decl->type->forall || (decl->type->kind == TypeData::Aggregate && decl->type->aggregate.params) ) {
-		SemanticError( yylloc, "forall qualifier in typedef is currently unimplemented." );
-		return true;
-	} // if
-	return false;
 } // IdentifierBeforeType
 
@@ -359,6 +352,6 @@
 
 // names and constants: lexer differentiates between identifier and typedef names
-%token<tok> IDENTIFIER		QUOTED_IDENTIFIER	TYPEDIMname		TYPEDEFname		TYPEGENname
-%token<tok> TIMEOUT			WOR					CATCH			RECOVER			CATCHRESUME		FIXUP		FINALLY		// CFA
+%token<tok> IDENTIFIER		TYPEDIMname		TYPEDEFname		TYPEGENname
+%token<tok> TIMEOUT			WAND	WOR			CATCH			RECOVER			CATCHRESUME		FIXUP		FINALLY		// CFA
 %token<tok> INTEGERconstant	CHARACTERconstant	STRINGliteral
 %token<tok> DIRECTIVE
@@ -429,7 +422,7 @@
 %type<catch_kind> handler_key
 %type<sn> mutex_statement
-%type<en> when_clause					when_clause_opt				waitfor						timeout
-%type<sn> waitfor_statement
-%type<wfs> waitfor_clause
+%type<en> when_clause					when_clause_opt				waitfor		waituntil		timeout
+%type<sn> waitfor_statement				waituntil_statement
+%type<wfs> wor_waitfor_clause			waituntil_clause			wand_waituntil_clause	wor_waituntil_clause
 
 // declarations
@@ -535,7 +528,10 @@
 // Similar issues exit with the waitfor statement.
 
-// Order of these lines matters (low-to-high precedence). THEN is left associative over WOR/TIMEOUT/ELSE, WOR is left
-// associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE.
+// Order of these lines matters (low-to-high precedence). THEN is left associative over WAND/WOR/TIMEOUT/ELSE, WAND/WOR
+// is left associative over TIMEOUT/ELSE, and TIMEOUT is left associative over ELSE.
 %precedence THEN		// rule precedence for IF/WAITFOR statement
+%precedence ANDAND		// token precedence for start of WAND in WAITFOR statement
+%precedence WAND		// token precedence for start of WAND in WAITFOR statement
+%precedence OROR		// token precedence for start of WOR in WAITFOR statement
 %precedence WOR			// token precedence for start of WOR in WAITFOR statement
 %precedence TIMEOUT		// token precedence for start of TIMEOUT in WAITFOR statement
@@ -624,4 +620,5 @@
 quasi_keyword:											// CFA
 	TIMEOUT
+	| WAND
 	| WOR
 	| CATCH
@@ -774,7 +771,7 @@
 		{ $$ = new ExpressionNode( build_pfieldSel( $1, build_tuple( $4 ) ) ); }
 	| postfix_expression ICR
-	  	{ $$ = new ExpressionNode( build_unary_val( OperKinds::IncrPost, $1 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( OperKinds::IncrPost, $1 ) ); }
 	| postfix_expression DECR
-	  	{ $$ = new ExpressionNode( build_unary_val( OperKinds::DecrPost, $1 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( OperKinds::DecrPost, $1 ) ); }
 	| '(' type_no_function ')' '{' initializer_list_opt comma_opt '}' // C99, compound-literal
 		{ $$ = new ExpressionNode( build_compoundLiteral( $2, new InitializerNode( $5, true ) ) ); }
@@ -804,5 +801,5 @@
 	'@'													// CFA, default parameter
 		{ SemanticError( yylloc, "Default parameter for argument is currently unimplemented." ); $$ = nullptr; }
-	 	// { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
+		// { $$ = new ExpressionNode( build_constantInteger( *new string( "2" ) ) ); }
 	| assignment_expression
 	;
@@ -879,9 +876,9 @@
 		}
 	| unary_operator cast_expression
-	  	{ $$ = new ExpressionNode( build_unary_val( $1, $2 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( $1, $2 ) ); }
 	| ICR unary_expression
-	  	{ $$ = new ExpressionNode( build_unary_val( OperKinds::Incr, $2 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( OperKinds::Incr, $2 ) ); }
 	| DECR unary_expression
-	  	{ $$ = new ExpressionNode( build_unary_val( OperKinds::Decr, $2 ) ); }
+		{ $$ = new ExpressionNode( build_unary_val( OperKinds::Decr, $2 ) ); }
 	| SIZEOF unary_expression
 		{ $$ = new ExpressionNode( new SizeofExpr( maybeMoveBuild( $2 ) ) ); }
@@ -1136,4 +1133,5 @@
 	| mutex_statement
 	| waitfor_statement
+	| waituntil_statement
 	| exception_statement
 	| enable_disable_statement
@@ -1245,5 +1243,5 @@
 	| declaration comma_expression						// semi-colon separated
 		{ $$ = new CondCtl( $1, $2 ); }
- 	;
+	;
 
 // CASE and DEFAULT clauses are only allowed in the SWITCH statement, precluding Duff's device. In addition, a case
@@ -1328,5 +1326,5 @@
 		}
 	| FOR '(' for_control_expression_list ')' statement	%prec THEN
-	  	{ $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
+		{ $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ) ) ); }
 	| FOR '(' for_control_expression_list ')' statement ELSE statement // CFA
 		{ $$ = new StatementNode( build_for( $3, maybe_build_compound( $5 ), $7 ) ); }
@@ -1520,5 +1518,5 @@
 			SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr;
 		}
- 	;
+	;
 
 downupdowneq:
@@ -1529,5 +1527,5 @@
 	| ErangeDownEq
 		{ $$ = OperKinds::GEThan; }
- 	;
+	;
 
 updown:
@@ -1536,5 +1534,5 @@
 	| ErangeDown
 		{ $$ = OperKinds::GThan; }
- 	;
+	;
 
 updowneq:
@@ -1544,5 +1542,5 @@
 	| ErangeDownEq
 		{ $$ = OperKinds::GEThan; }
- 	;
+	;
 
 jump_statement:
@@ -1627,13 +1625,4 @@
 	;
 
-waitfor:
-	WAITFOR '(' cast_expression ')'
-		{ $$ = $3; }
-//	| WAITFOR '(' cast_expression ',' argument_expression_list_opt ')'
-//	  	{ $$ = (ExpressionNode *)$3->set_last( $5 ); }
-	| WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'
-		{ $$ = (ExpressionNode *)($3->set_last( $5 )); }
-	;
-
 cast_expression_list:
 	cast_expression
@@ -1644,32 +1633,87 @@
 
 timeout:
-	TIMEOUT '(' comma_expression ')'	 		{ $$ = $3; }
-	;
-
-waitfor_clause:
+	TIMEOUT '(' comma_expression ')'			{ $$ = $3; }
+	;
+
+wor:
+	OROR
+	| WOR
+
+waitfor:
+	WAITFOR '(' cast_expression ')'
+		{ $$ = $3; }
+	| WAITFOR '(' cast_expression_list ':' argument_expression_list_opt ')'
+		{ $$ = (ExpressionNode *)($3->set_last( $5 )); }
+	;
+
+wor_waitfor_clause:
 	when_clause_opt waitfor statement					%prec THEN
-		{ $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1 ); }
-	| when_clause_opt waitfor statement WOR waitfor_clause
-		{ $$ = build_waitfor( $2, maybe_build_compound( $3 ), $1, $5 ); }
-	| when_clause_opt timeout statement					%prec THEN
-		{ $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1 ); }
-	| when_clause_opt ELSE statement
-		{ $$ = build_waitfor_timeout( nullptr, maybe_build_compound( $3 ), $1 ); }
+		// Called first: create header for WaitForStmt.
+		{ $$ = build_waitfor( new WaitForStmt(), $1, $2, maybe_build_compound( $3 ) ); }
+	| wor_waitfor_clause wor when_clause_opt waitfor statement	%prec THEN
+		{ $$ = build_waitfor( $1, $3, $4, maybe_build_compound( $5 ) ); }
+	| wor_waitfor_clause wor when_clause_opt ELSE statement
+		{ $$ = build_waitfor_else( $1, $3, maybe_build_compound( $5 ) ); }
+	| wor_waitfor_clause wor when_clause_opt timeout statement	%prec THEN
+		{ $$ = build_waitfor_timeout( $1, $3, $4, maybe_build_compound( $5 ) ); }
 	// "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
-	| when_clause_opt timeout statement WOR ELSE statement // syntax error
+	| wor_waitfor_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
 		{ SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
-	| when_clause_opt timeout statement WOR when_clause ELSE statement
-		{ $$ = build_waitfor_timeout( $2, maybe_build_compound( $3 ), $1, maybe_build_compound( $7 ), $5 ); }
-	;
+	| wor_waitfor_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
+		{ $$ = build_waitfor_else( build_waitfor_timeout( $1, $3, $4, maybe_build_compound( $5 ) ), $7, maybe_build_compound( $9 ) ); }
 
 waitfor_statement:
-	when_clause_opt waitfor statement					%prec THEN
- 		{ $$ = new StatementNode( build_waitfor( $2, $3, $1 ) ); }
-	| when_clause_opt waitfor statement WOR waitfor_clause
- 		{ $$ = new StatementNode( build_waitfor( $2, $3, $1, $5 ) ); }
+	wor_waitfor_clause									%prec THEN
+		{ $$ = new StatementNode( $1 ); }
+	;
+
+wand:
+	ANDAND
+	| WAND
+	;
+
+waituntil:
+	WAITUNTIL '(' cast_expression ')'
+		{ $$ = $3; }
+	;
+
+waituntil_clause:
+	when_clause_opt waituntil statement
+		{ printf( "waituntil_clause 1\n" ); $$ = nullptr; }
+	| '(' wor_waituntil_clause ')'
+		{ printf( "waituntil_clause 2\n" ); $$ = nullptr; }
+	;
+
+wand_waituntil_clause:
+	waituntil_clause									%prec THEN
+		{ printf( "wand_waituntil_clause 1\n" ); $$ = nullptr; }
+	| waituntil_clause wand wand_waituntil_clause
+		{ printf( "wand_waituntil_clause 2\n" ); $$ = nullptr; }
+	;
+
+wor_waituntil_clause:
+	wand_waituntil_clause
+		{ printf( "wor_waituntil_clause 1\n" ); $$ = nullptr; }
+	| wor_waituntil_clause wor wor_waituntil_clause		%prec THEN
+		{ printf( "wor_waituntil_clause 2\n" ); $$ = nullptr; }
+	| wor_waituntil_clause wor when_clause_opt ELSE statement
+		{ printf( "wor_waituntil_clause 3\n" ); $$ = nullptr; }
+	| wor_waituntil_clause wor when_clause_opt timeout statement	%prec THEN
+		{ printf( "wor_waituntil_clause 4\n" ); $$ = nullptr; }
+	// "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
+	| wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error
+		{ SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
+	| wor_waituntil_clause wor when_clause_opt timeout statement wor when_clause ELSE statement
+		{ printf( "wor_waituntil_clause 6\n" ); $$ = nullptr; }
+	;
+
+waituntil_statement:
+	wor_waituntil_clause								%prec THEN
+		// SKULLDUGGERY: create an empty compound statement to test parsing of waituntil statement.
+		{ $$ = new StatementNode( build_compound( (StatementNode *)0 ) ); }
 	;
 
 exception_statement:
-	TRY compound_statement handler_clause 					%prec THEN
+	TRY compound_statement handler_clause				%prec THEN
 		{ $$ = new StatementNode( build_try( $2, $3, nullptr ) ); }
 	| TRY compound_statement finally_clause
@@ -1831,5 +1875,5 @@
 		{
 			// printf( "C_DECLARATION1 %p %s\n", $$, $$->name ? $$->name->c_str() : "(nil)" );
-		  	// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
+			// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
 			//   printf( "\tattr %s\n", attr->name.c_str() );
 			// } // for
@@ -1967,6 +2011,7 @@
 		{
 			typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "4" );
-			if ( TypedefForall( $2 ) ) $$ = nullptr;
-			else $$ = $3->addType( $2 )->addTypedef();		// watchout frees $2 and $3
+			if ( $2->type->forall || ($2->type->kind == TypeData::Aggregate && $2->type->aggregate.params) ) {
+				SemanticError( yylloc, "forall qualifier in typedef is currently unimplemented." ); $$ = nullptr;
+			} else $$ = $3->addType( $2 )->addTypedef(); // watchout frees $2 and $3
 		}
 	| typedef_declaration pop ',' push declarator
@@ -1976,21 +2021,9 @@
 		}
 	| type_qualifier_list TYPEDEF type_specifier declarator // remaining OBSOLESCENT (see 2 )
-		{
-			typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "6" );
-			if ( TypedefForall( $1 ) ) $$ = nullptr;
-			else $$ = $4->addQualifiers( $1 )->addType( $3 )->addTypedef();
-		}
+		{ SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
 	| type_specifier TYPEDEF declarator
-		{
-			typedefTable.addToEnclosingScope( *$3->name, TYPEDEFname, "7" );
-			if ( TypedefForall( $1 ) ) $$ = nullptr;
-			else $$ = $3->addType( $1 )->addTypedef();
-		}
+		{ SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
 	| type_specifier TYPEDEF type_qualifier_list declarator
-		{
-			typedefTable.addToEnclosingScope( *$4->name, TYPEDEFname, "8" );
-			if ( TypedefForall( $3 ) ) $$ = nullptr;
-			else $$ = $4->addQualifiers( $1 )->addType( $1 )->addTypedef();
-		}
+		{ SemanticError( yylloc, "Type qualifiers/specifiers before TYPEDEF is deprecated, move after TYPEDEF." ); $$ = nullptr; }
 	;
 
@@ -1999,9 +2032,9 @@
 	TYPEDEF identifier '=' assignment_expression
 		{
-			SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
+			SemanticError( yylloc, "TYPEDEF expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
 		}
 	| typedef_expression pop ',' push identifier '=' assignment_expression
 		{
-			SemanticError( yylloc, "Typedef expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
+			SemanticError( yylloc, "TYPEDEF expression is deprecated, use typeof(...) instead." ); $$ = nullptr;
 		}
 	;
@@ -2301,5 +2334,5 @@
 		{
 			// printf( "sue_declaration_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
-		  	// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
+			// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
 			//   printf( "\tattr %s\n", attr->name.c_str() );
 			// } // for
@@ -2317,5 +2350,5 @@
 		{
 			// printf( "sue_type_specifier %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
-		  	// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
+			// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
 			//   printf( "\tattr %s\n", attr->name.c_str() );
 			// } // for
@@ -2395,5 +2428,5 @@
 		{
 			// printf( "elaborated_type %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
-		  	// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
+			// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
 			//   printf( "\tattr %s\n", attr->name.c_str() );
 			// } // for
@@ -2522,5 +2555,5 @@
 			$$ = fieldDecl( $1, $2 );
 			// printf( "type_specifier2 %p %s\n", $$, $$->type->aggregate.name ? $$->type->aggregate.name->c_str() : "(nil)" );
-		  	// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
+			// for ( Attribute * attr: reverseIterate( $$->attributes ) ) {
 			//   printf( "\tattr %s\n", attr->name.c_str() );
 			// } // for
@@ -2529,5 +2562,5 @@
 		{ $$ = fieldDecl( $2, $3 ); distExt( $$ ); }
 	| STATIC type_specifier field_declaring_list_opt ';' // CFA
-	   	{ SemanticError( yylloc, "STATIC aggregate field qualifier currently unimplemented." ); $$ = nullptr; }
+		{ SemanticError( yylloc, "STATIC aggregate field qualifier currently unimplemented." ); $$ = nullptr; }
 	| INLINE type_specifier field_abstract_list_opt ';'	// CFA
 		{
@@ -2540,5 +2573,5 @@
 		}
 	| INLINE aggregate_control ';'						// CFA
-	   	{ SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; }
+		{ SemanticError( yylloc, "INLINE aggregate control currently unimplemented." ); $$ = nullptr; }
 	| typedef_declaration ';'							// CFA
 	| cfa_field_declaring_list ';'						// CFA, new style field declaration
@@ -2623,5 +2656,5 @@
 		{ $$ = DeclarationNode::newEnum( $3->name, $6, true, false, nullptr, $4 )->addQualifiers( $2 ); }
 	| ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}'
-	 	{
+		{
 			if ( $3->storageClasses.val != 0 || $3->type->qualifiers.any() )
 			{ SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }
@@ -3157,5 +3190,5 @@
 		{
 			distQual( $5, $1 );
- 			forall = false;
+			forall = false;
 			$$ = $5;
 		}
@@ -3168,5 +3201,5 @@
 		{
 			distQual( $5, $1 );
- 			forall = false;
+			forall = false;
 			$$ = $5;
 		}
@@ -3179,5 +3212,5 @@
 		{
 			distQual( $6, $1->addQualifiers( $2 ) );
- 			forall = false;
+			forall = false;
 			$$ = $6;
 		}
@@ -3386,5 +3419,5 @@
 	| '(' attribute_list variable_ptr ')' array_dimension
 		{ $$ = $3->addQualifiers( $2 )->addArray( $5 ); }
-	| '(' variable_array ')' multi_array_dimension 		// redundant parenthesis
+	| '(' variable_array ')' multi_array_dimension		// redundant parenthesis
 		{ $$ = $2->addArray( $4 ); }
 	| '(' attribute_list variable_array ')' multi_array_dimension // redundant parenthesis
@@ -3809,5 +3842,5 @@
 	| ErangeUpEq
 		{ $$ = OperKinds::LEThan; }
- 	;
+	;
 
 multi_array_dimension:
Index: src/ResolvExpr/Candidate.cpp
===================================================================
--- src/ResolvExpr/Candidate.cpp	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/ResolvExpr/Candidate.cpp	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -17,4 +17,5 @@
 
 #include <iostream>
+#include <sstream>
 
 #include "AST/Print.hpp"
@@ -44,5 +45,5 @@
 	sorted.reserve(cands.size());
 	for(const auto & c : cands) {
-		std::stringstream ss;
+		std::ostringstream ss;
 		print( ss, *c, indent );
 		sorted.push_back(ss.str());
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/ResolvExpr/Resolver.cc	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -39,8 +39,9 @@
 #include "AST/Type.hpp"
 #include "Common/Eval.h"                 // for eval
+#include "Common/Iterate.hpp"            // for group_iterate
 #include "Common/PassVisitor.h"          // for PassVisitor
 #include "Common/SemanticError.h"        // for SemanticError
 #include "Common/Stats/ResolveTime.h"    // for ResolveTime::start(), ResolveTime::stop()
-#include "Common/utility.h"              // for ValueGuard, group_iterate
+#include "Common/ToString.hpp"           // for toCString
 #include "InitTweak/GenInit.h"
 #include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
Index: src/SymTab/FixFunction.cc
===================================================================
--- src/SymTab/FixFunction.cc	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/SymTab/FixFunction.cc	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -21,5 +21,5 @@
 #include "AST/Pass.hpp"
 #include "AST/Type.hpp"
-#include "Common/utility.h"       // for maybeClone, copy
+#include "Common/utility.h"       // for copy
 #include "SynTree/Declaration.h"  // for FunctionDecl, ObjectDecl, Declarati...
 #include "SynTree/Expression.h"   // for Expression
Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/SymTab/Mangler.cc	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -24,6 +24,6 @@
 #include "CodeGen/OperatorTable.h"       // for OperatorInfo, operatorLookup
 #include "Common/PassVisitor.h"
+#include "Common/ToString.hpp"           // for toCString
 #include "Common/SemanticError.h"        // for SemanticError
-#include "Common/utility.h"              // for toString
 #include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
 #include "SynTree/LinkageSpec.h"         // for Spec, isOverridable, AutoGen, Int...
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/SymTab/Validate.cc	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -55,6 +55,7 @@
 #include "Common/ScopedMap.h"          // for ScopedMap
 #include "Common/SemanticError.h"      // for SemanticError
+#include "Common/ToString.hpp"         // for toCString
 #include "Common/UniqueName.h"         // for UniqueName
-#include "Common/utility.h"            // for operator+, cloneAll, deleteAll
+#include "Common/utility.h"            // for cloneAll, deleteAll
 #include "CompilationState.h"          // skip some passes in new-ast build
 #include "Concurrency/Keywords.h"      // for applyKeywords
Index: src/SymTab/ValidateType.cc
===================================================================
--- src/SymTab/ValidateType.cc	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/SymTab/ValidateType.cc	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -18,4 +18,5 @@
 #include "CodeGen/OperatorTable.h"
 #include "Common/PassVisitor.h"
+#include "Common/ToString.hpp"
 #include "SymTab/FixFunction.h"
 #include "SynTree/Declaration.h"
Index: src/SynTree/Type.cc
===================================================================
--- src/SynTree/Type.cc	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/SynTree/Type.cc	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -16,4 +16,5 @@
 
 #include "Attribute.h"                // for Attribute
+#include "Common/ToString.hpp"        // for toCString
 #include "Common/utility.h"           // for cloneAll, deleteAll, printAll
 #include "InitTweak/InitTweak.h"      // for getPointerBase
@@ -105,4 +106,8 @@
 int Type::referenceDepth() const { return 0; }
 
+AggregateDecl * Type::getAggr() const {
+	assertf( false, "Non-aggregate type: %s", toCString( this ) );
+}
+
 TypeSubstitution Type::genericSubstitution() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
 
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/SynTree/Type.h	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -24,5 +24,4 @@
 #include "BaseSyntaxNode.h"  // for BaseSyntaxNode
 #include "Common/Iterate.hpp"// for operator+
-#include "Common/utility.h"  // for toCString
 #include "Mutator.h"         // for Mutator
 #include "SynTree.h"         // for AST nodes
@@ -186,5 +185,5 @@
 	virtual bool isComplete() const { return true; }
 
-	virtual AggregateDecl * getAggr() const { assertf( false, "Non-aggregate type: %s", toCString( this ) ); }
+	virtual AggregateDecl * getAggr() const;
 
 	virtual TypeSubstitution genericSubstitution() const;
Index: src/Validate/FixQualifiedTypes.cpp
===================================================================
--- src/Validate/FixQualifiedTypes.cpp	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/Validate/FixQualifiedTypes.cpp	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -16,9 +16,10 @@
 #include "Validate/FixQualifiedTypes.hpp"
 
+#include "AST/LinkageSpec.hpp"             // for Linkage
 #include "AST/Pass.hpp"
 #include "AST/TranslationUnit.hpp"
+#include "Common/ToString.hpp"             // for toString
+#include "SymTab/Mangler.h"                // for Mangler
 #include "Validate/NoIdSymbolTable.hpp"
-#include "SymTab/Mangler.h"            // for Mangler
-#include "AST/LinkageSpec.hpp"			   // for Linkage
 
 namespace Validate {
Index: src/Validate/ForallPointerDecay.cpp
===================================================================
--- src/Validate/ForallPointerDecay.cpp	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/Validate/ForallPointerDecay.cpp	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -22,4 +22,5 @@
 #include "CodeGen/OperatorTable.h"
 #include "Common/CodeLocation.h"
+#include "Common/ToString.hpp"
 #include "SymTab/FixFunction.h"
 
Index: src/Validate/HandleAttributes.cc
===================================================================
--- src/Validate/HandleAttributes.cc	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/Validate/HandleAttributes.cc	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -19,4 +19,5 @@
 #include "Common/Eval.h"
 #include "Common/PassVisitor.h"
+#include "Common/ToString.hpp"
 #include "Common/SemanticError.h"
 #include "ResolvExpr/Resolver.h"
Index: src/Validate/HoistStruct.cpp
===================================================================
--- src/Validate/HoistStruct.cpp	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/Validate/HoistStruct.cpp	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -16,7 +16,8 @@
 #include "Validate/HoistStruct.hpp"
 
+#include <sstream>
+
 #include "AST/Pass.hpp"
 #include "AST/TranslationUnit.hpp"
-#include "Common/utility.h"
 
 namespace Validate {
Index: src/include/cassert
===================================================================
--- src/include/cassert	(revision d24b19859212bff453dd4289255f7846be0d55a5)
+++ src/include/cassert	(revision 9082d7e82d9a7493aed9e548946de1837caa325a)
@@ -20,8 +20,5 @@
 #include_next <cassert>
 
-#include <string>
-
-template < typename ... Params >
-std::string toString( const Params & ... params );
+#include "Common/ToString.hpp"
 
 #ifdef NDEBUG
