Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/CodeGen/CodeGenerator.cc	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/Common/DeclStats.cpp	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/Common/ResolvProtoDump.cpp	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 9feb34b1fca12748b7d48737024da48e342f5c07)
+++ src/Common/ToString.hpp	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/Common/module.mk	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/Common/utility.h	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/ControlStruct/ExceptDeclNew.cpp	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -15,4 +15,6 @@
 
 #include "ExceptDecl.h"
+
+#include <sstream>
 
 #include "AST/Decl.hpp"
Index: src/ControlStruct/MLEMutator.cc
===================================================================
--- src/ControlStruct/MLEMutator.cc	(revision 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/ControlStruct/MLEMutator.cc	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/GenPoly/Box.cc	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/GenPoly/Lvalue.cc	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/GenPoly/LvalueNew.cpp	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/InitTweak/FixInit.cc	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/InitTweak/FixInitNew.cpp	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/InitTweak/GenInit.cc	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/Parser/parser.yy	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -44,4 +44,5 @@
 
 #include <cstdio>
+#include <sstream>
 #include <stack>
 using namespace std;
Index: src/ResolvExpr/Candidate.cpp
===================================================================
--- src/ResolvExpr/Candidate.cpp	(revision 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/ResolvExpr/Candidate.cpp	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/ResolvExpr/Resolver.cc	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/SymTab/FixFunction.cc	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/SymTab/Mangler.cc	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/SymTab/Validate.cc	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/SymTab/ValidateType.cc	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/SynTree/Type.cc	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/SynTree/Type.h	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/Validate/FixQualifiedTypes.cpp	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/Validate/ForallPointerDecay.cpp	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/Validate/HandleAttributes.cc	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/Validate/HoistStruct.cpp	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -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 60380a1a5424e5d6fdf76591dede27674d609f5e)
+++ src/include/cassert	(revision 9feb34b1fca12748b7d48737024da48e342f5c07)
@@ -20,8 +20,5 @@
 #include_next <cassert>
 
-#include <string>
-
-template < typename ... Params >
-std::string toString( const Params & ... params );
+#include "Common/ToString.hpp"
 
 #ifdef NDEBUG
