Index: src/AST/Expr.cpp
===================================================================
--- src/AST/Expr.cpp	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/AST/Expr.cpp	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -9,7 +9,7 @@
 // Author           : Aaron B. Moss
 // Created On       : Wed May 15 17:00:00 2019
-// Last Modified By : Andrew Beach
+// Last Modified By : Peter A. Buhr
 // Created On       : Wed May 18 13:56:00 2022
-// Update Count     : 8
+// Update Count     : 12
 //
 
@@ -168,6 +168,6 @@
 			return addrType( refType->base );
 		} else {
-			SemanticError( loc, arg->result.get(),
-				"Attempt to take address of non-lvalue expression: " );
+			SemanticError( loc, "Attempt to take address of non-lvalue expression %s",
+						   toString( arg->result.get() ).c_str() );
 		}
 	}
@@ -240,5 +240,6 @@
 		return 1;
 	}
-	SemanticError( this, "Constant expression of non-integral type " );
+	SemanticError( this->location, "Constant expression of non-integral type %s",
+				   toString( this ).c_str() );
 }
 
Index: src/AST/LinkageSpec.cpp
===================================================================
--- src/AST/LinkageSpec.cpp	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/AST/LinkageSpec.cpp	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -9,7 +9,7 @@
 // Author           : Aaron B. Moss
 // Created On       : Thu May 9 10:00:00 2019
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Thu May 9 10:00:00 2019
-// Update Count     : 1
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon Dec 11 16:08:58 2023
+// Update Count     : 2
 //
 
@@ -37,5 +37,5 @@
 		return spec;
 	} else {
-		SemanticError( loc, "Invalid linkage specifier " + *cmd );
+		SemanticError( loc, "Invalid linkage specifier %s", cmd->c_str() );
 	}
 }
Index: src/AST/TypeSubstitution.hpp
===================================================================
--- src/AST/TypeSubstitution.hpp	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/AST/TypeSubstitution.hpp	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Thr May 25 12:31:00 2023
-// Update Count     : 10
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon Dec 11 16:07:30 2023
+// Update Count     : 15
 //
 
@@ -156,5 +156,6 @@
 				} // if
 			} else {
-				SemanticError( formal, toString( "Attempt to provide non-type parameter: ", toString( *actualIt ).c_str(), " for type parameter " ) );
+				SemanticError( formal->location, "Attempt to provide non-type parameter %s for type parameter %s",
+							   toString( *actualIt ).c_str(), formal->name.c_str() );
 			} // if
 		} else {
Index: src/Common/SemanticError.cc
===================================================================
--- src/Common/SemanticError.cc	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/Common/SemanticError.cc	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Jun  7 08:05:26 2018
-// Update Count     : 10
+// Last Modified On : Mon Dec 11 15:59:09 2023
+// Update Count     : 14
 //
 
@@ -70,4 +70,5 @@
 //-----------------------------------------------------------------------------
 // Semantic Error
+
 bool SemanticErrorThrow = false;
 
@@ -101,4 +102,15 @@
 		std::cerr << ErrorHelpers::bold() << err.location << ErrorHelpers::error_str() << ErrorHelpers::reset_font() << err.description << std::endl;
 	}
+}
+
+void SemanticError( CodeLocation location, const char * fmt, ... ) {
+	char msg[2048];										// worst-case error-message buffer
+	va_list args;
+	va_start( args, fmt );
+	vsnprintf( msg, sizeof(msg), fmt, args );			// always null terminated, but may be truncated
+	va_end( args );
+
+	SemanticErrorThrow = true;
+	throw SemanticErrorException( location, msg );		// convert msg to string
 }
 
Index: src/Common/SemanticError.h
===================================================================
--- src/Common/SemanticError.h	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/Common/SemanticError.h	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -10,6 +10,6 @@
 // Created On       : Mon May 18 07:44:20 2015
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Feb 25 12:01:31 2023
-// Update Count     : 37
+// Last Modified On : Mon Dec 11 21:54:22 2023
+// Update Count     : 54
 //
 
@@ -18,4 +18,5 @@
 #include "ErrorObjects.h"
 #include "AST/Node.hpp"
+#include "AST/ParseNode.hpp"
 #include <cstring>
 
@@ -25,13 +26,13 @@
 extern bool SemanticErrorThrow;
 
+__attribute__((noreturn, format(printf, 2, 3))) void SemanticError( CodeLocation location, const char fmt[], ... );
+
 __attribute__((noreturn)) void SemanticError( CodeLocation location, std::string error );
 
-template< typename T >
-__attribute__((noreturn)) static inline void SemanticError( const T * obj, const std::string & error ) {
+__attribute__((noreturn)) static inline void SemanticError( const ast::ParseNode * obj, const std::string & error ) {
 	SemanticError( obj->location, toString( error, obj ) );
 }
 
-template< typename T >
-__attribute__((noreturn)) static inline void SemanticError( CodeLocation location, const T * obj, const std::string & error ) {
+__attribute__((noreturn)) static inline void SemanticError( CodeLocation location, const ast::Node * obj, const std::string & error ) {
 	SemanticError( location, toString( error, obj ) );
 }
@@ -54,13 +55,13 @@
 
 constexpr WarningData WarningFormats[] = {
-	{"self-assign"              , Severity::Warn    , "self assignment of expression: %s"                          },
-	{"reference-conversion"     , Severity::Warn    , "rvalue to reference conversion of rvalue: %s"               },
-	{"qualifiers-zero_t-one_t"  , Severity::Warn    , "questionable use of type qualifier(s) with %s"              },
-	{"aggregate-forward-decl"   , Severity::Warn    , "forward declaration of nested aggregate: %s"                },
-	{"superfluous-decl"         , Severity::Warn    , "declaration does not allocate storage: %s"                  },
-	{"superfluous-else"         , Severity::Warn    , "else clause never executed for empty loop conditional"      },
-	{"gcc-attributes"           , Severity::Warn    , "invalid attribute: %s"                                      },
-	{"c++-like-copy"            , Severity::Warn    , "Constructor from reference is not a valid copy constructor" },
-	{"depreciated-trait-syntax" , Severity::Warn    , "trait type-parameters are now specified using the forall clause" },
+	{"self-assign"              , Severity::Warn, "self assignment of expression: %s"                          },
+	{"reference-conversion"     , Severity::Warn, "rvalue to reference conversion of rvalue: %s"               },
+	{"qualifiers-zero_t-one_t"  , Severity::Warn, "questionable use of type qualifier(s) with %s"              },
+	{"aggregate-forward-decl"   , Severity::Warn, "forward declaration of nested aggregate: %s"                },
+	{"superfluous-decl"         , Severity::Warn, "declaration does not allocate storage: %s"                  },
+	{"superfluous-else"         , Severity::Warn, "else clause never executed for empty loop conditional"      },
+	{"gcc-attributes"           , Severity::Warn, "invalid attribute: %s"                                      },
+	{"c++-like-copy"            , Severity::Warn, "Constructor from reference is not a valid copy constructor" },
+	{"depreciated-trait-syntax" , Severity::Warn, "trait type-parameters are now specified using the forall clause" },
 };
 
@@ -75,5 +76,5 @@
 	CppCopy,
 	DeprecTraitSyntax,
-	NUMBER_OF_WARNINGS, // This MUST be the last warning
+	NUMBER_OF_WARNINGS, // MUST be the last warning
 };
 
Index: src/ControlStruct/FixLabels.cpp
===================================================================
--- src/ControlStruct/FixLabels.cpp	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/ControlStruct/FixLabels.cpp	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -10,6 +10,6 @@
 // Created On       : Mon Nov  1 09:39:00 2021
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Jan 31 22:19:17 2022
-// Update Count     : 9
+// Last Modified On : Sun Nov 26 15:06:51 2023
+// Update Count     : 10
 //
 
@@ -47,6 +47,5 @@
 	for ( auto kvp : labelTable ) {
 		if ( nullptr == kvp.second ) {
-			SemanticError( kvp.first.location,
-						   "Use of undefined label: " + kvp.first.name );
+			SemanticError( kvp.first.location, "Use of undefined label %s.", kvp.first.name.c_str() );
 		}
 	}
Index: src/ControlStruct/MultiLevelExit.cpp
===================================================================
--- src/ControlStruct/MultiLevelExit.cpp	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/ControlStruct/MultiLevelExit.cpp	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -9,7 +9,7 @@
 // Author           : Andrew Beach
 // Created On       : Mon Nov  1 13:48:00 2021
-// Last Modified By : Andrew Beach
-// Last Modified On : Fri Sep  8 17:04:00 2023
-// Update Count     : 36
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon Dec 11 13:44:45 2023
+// Update Count     : 38
 //
 
@@ -521,5 +521,5 @@
 		assert(0);
 	}
-	SemanticError( stmt->location, toString( "'return' may not appear in a ", context ) );
+	SemanticError( stmt->location, "'return' may not appear in a %s", context );
 }
 
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/Parser/ParseNode.h	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -9,7 +9,7 @@
 // Author           : Rodolfo G. Esteves
 // Created On       : Sat May 16 13:28:16 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Apr  3 17:55:00 2023
-// Update Count     : 942
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat Dec  9 17:39:34 2023
+// Update Count     : 945
 //
 
@@ -37,4 +37,5 @@
 class ExpressionNode;
 struct StatementNode;
+
 
 //##############################################################################
@@ -97,4 +98,8 @@
 std::ostream & operator<<( std::ostream & out, const ParseNode * node );
 
+__attribute__((noreturn)) static inline void SemanticError( const ParseNode * obj, const std::string & error ) {
+	SemanticError( obj->location, toString( error, obj ) );
+}
+
 // Local Variables: //
 // tab-width: 4 //
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/Parser/TypeData.cc	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -9,7 +9,7 @@
 // Author           : Rodolfo G. Esteves
 // Created On       : Sat May 16 15:12:51 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Tue Apr  4 13:39:00 2023
-// Update Count     : 680
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sun Nov 26 15:51:05 2023
+// Update Count     : 681
 //
 
@@ -864,5 +864,5 @@
 
 static string genTSError( string msg, DeclarationNode::BasicType basictype ) {
-	SemanticError( yylloc, string( "invalid type specifier \"" ) + msg + "\" for type \"" + DeclarationNode::basicTypeNames[basictype] + "\"." );
+	SemanticError( yylloc, "invalid type specifier \"%s\" for type \"%s\".", msg.c_str(), DeclarationNode::basicTypeNames[basictype] );
 } // genTSError
 
@@ -1507,5 +1507,5 @@
 		} // for
 		// declaration type still set => type not moved to a matching parameter so there is a missing parameter name
-		if ( decl->type ) SemanticError( decl->location, string( "missing name in parameter list " ) + *decl->name );
+		if ( decl->type ) SemanticError( decl->location, "missing name in parameter list %s", decl->name->c_str() );
 	} // for
 
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/Parser/parser.yy	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -10,6 +10,6 @@
 // Created On       : Sat Sep  1 20:22:55 2001
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Oct  3 17:14:12 2023
-// Update Count     : 6396
+// Last Modified On : Sun Nov 26 13:18:06 2023
+// Update Count     : 6398
 //
 
@@ -260,16 +260,18 @@
 		} // if
 	} else {
-		SemanticError( yylloc, "syntax error, loop-index name missing. Expression disallowed. ." ); return nullptr;
+		SemanticError( yylloc, "syntax error, loop-index name missing. Expression disallowed." ); return nullptr;
 	} // if
 } // forCtrl
 
 static void IdentifierBeforeIdentifier( string & identifier1, string & identifier2, const char * kind ) {
-	SemanticError( yylloc, ::toString( "syntax error, adjacent identifiers \"", identifier1, "\" and \"", identifier2, "\" are not meaningful in a", kind, ".\n"
-				   "Possible cause is misspelled type name or missing generic parameter." ) );
+	SemanticError( yylloc, "syntax error, adjacent identifiers \"%s\" and \"%s\" are not meaningful in an %s.\n"
+				   "Possible cause is misspelled type name or missing generic parameter.",
+				   identifier1.c_str(), identifier2.c_str(), kind );
 } // IdentifierBeforeIdentifier
 
 static void IdentifierBeforeType( string & identifier, const char * kind ) {
-	SemanticError( yylloc, ::toString( "syntax error, identifier \"", identifier, "\" cannot appear before a ", kind, ".\n"
-				   "Possible cause is misspelled storage/CV qualifier, misspelled typename, or missing generic parameter." ) );
+	SemanticError( yylloc, "syntax error, identifier \"%s\" cannot appear before a %s.\n"
+				   "Possible cause is misspelled storage/CV qualifier, misspelled typename, or missing generic parameter.",
+				   identifier.c_str(), kind );
 } // IdentifierBeforeType
 
@@ -689,5 +691,5 @@
 	//   	{ SemanticError( yylloc, "Resume expression is currently unimplemented." ); $$ = nullptr; }
 	| IDENTIFIER IDENTIFIER								// invalid syntax rule
-		{ IdentifierBeforeIdentifier( *$1.str, *$2.str, "n expression" ); $$ = nullptr; }
+		{ IdentifierBeforeIdentifier( *$1.str, *$2.str, "expression" ); $$ = nullptr; }
 	| IDENTIFIER type_qualifier							// invalid syntax rule
 		{ IdentifierBeforeType( *$1.str, "type qualifier" ); $$ = nullptr; }
@@ -1155,7 +1157,7 @@
 	| identifier_or_type_name ':' attribute_list_opt error // invalid syntax rule
 		{
-			SemanticError( yylloc, ::toString( "syntx error, label \"", *$1.str, "\" must be associated with a statement, "
-											   "where a declaration, case, or default is not a statement. "
-											   "Move the label or terminate with a semi-colon." ) );
+			SemanticError( yylloc, "syntx error, label \"%s\" must be associated with a statement, "
+						   "where a declaration, case, or default is not a statement.\n"
+						   "Move the label or terminate with a semicolon.", $1.str->c_str() );
 			$$ = nullptr;
 		}
@@ -2101,7 +2103,6 @@
 	| sue_declaration_specifier invalid_types			// invalid syntax rule
 		{
-			SemanticError( yylloc, ::toString( "syntax error, expecting ';' at end of ",
-				$1->type->enumeration.name ? "enum" : ast::AggregateDecl::aggrString( $1->type->aggregate.kind ),
-				" declaration." ) );
+			SemanticError( yylloc, "syntax error, expecting ';' at end of \"%s\" declaration.",
+						   $1->type->enumeration.name ? "enum" : ast::AggregateDecl::aggrString( $1->type->aggregate.kind ) );
 			$$ = nullptr;
 		}
@@ -2161,5 +2162,5 @@
 type_qualifier:
 	type_qualifier_name
-	| attribute											// trick handles most atrribute locations
+	| attribute											// trick handles most attribute locations
 	;
 
@@ -2585,5 +2586,5 @@
 	| type_specifier field_declaring_list_opt '}'		// invalid syntax rule
 		{
-			SemanticError( yylloc, ::toString( "syntax error, expecting ';' at end of previous declaration." ) );
+			SemanticError( yylloc, "syntax error, expecting ';' at end of previous declaration." );
 			$$ = nullptr;
 		}
Index: src/ResolvExpr/CurrentObject.cc
===================================================================
--- src/ResolvExpr/CurrentObject.cc	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/ResolvExpr/CurrentObject.cc	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -9,7 +9,7 @@
 // Author           : Rob Schluntz
 // Created On       : Tue Jun 13 15:28:32 2017
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon Apr 10  9:40:00 2023
-// Update Count     : 18
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sat Dec  9 17:49:51 2023
+// Update Count     : 20
 //
 
@@ -181,5 +181,5 @@
 		auto res = eval( expr );
 		if ( !res.hasKnownValue ) {
-			SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) );
+			SemanticError( location, "Array designator must be a constant expression %s", toString( expr ).c_str() );
 		}
 		return res.knownValue;
Index: src/Validate/FixQualifiedTypes.cpp
===================================================================
--- src/Validate/FixQualifiedTypes.cpp	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/Validate/FixQualifiedTypes.cpp	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -9,7 +9,7 @@
 // Author           : Andrew Beach
 // Created On       : Thr Apr 21 11:13:00 2022
-// Last Modified By : Andrew Beach
-// Last Modified On : Tue Sep 20 16:15:00 2022
-// Update Count     : 1
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Wed Dec 13 09:00:25 2023
+// Update Count     : 6
 //
 
@@ -41,5 +41,5 @@
 				auto td = symtab.globalLookupType( inst->name );
 				if ( !td ) {
-					SemanticError( *location, toString("Use of undefined global type ", inst->name) );
+					SemanticError( *location, "Use of undefined global type %s.", inst->name.c_str() );
 				}
 				auto base = td->base;
@@ -50,5 +50,5 @@
 			} else {
 				// .T => T is not a type name.
-				assertf( false, "unhandled global qualified child type: %s", toCString(child) );
+				assertf( false, "unhandled global qualified child type: %s", toCString( child ) );
 			}
 		} else {
@@ -63,5 +63,5 @@
 				instp = inst;
 			} else {
-				SemanticError( *location, toString("Qualified type requires an aggregate on the left, but has: ", parent) );
+				SemanticError( *location, "Qualified type requires an aggregate on the left, but has %s.", toCString( parent ) );
 			}
 			// TODO: Need to handle forward declarations.
@@ -81,9 +81,9 @@
 				} else {
 					// S.T - S is not an aggregate => error.
-					assertf( false, "unhandled qualified child type: %s", toCString(type) );
+					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) );
+			SemanticError( *location, "Undefined type in qualified type %s", toCString( type ) );
 		}
 	}
Index: src/Validate/ForallPointerDecay.cpp
===================================================================
--- src/Validate/ForallPointerDecay.cpp	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/Validate/ForallPointerDecay.cpp	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -9,7 +9,7 @@
 // Author           : Andrew Beach
 // Created On       : Tue Dec  7 16:15:00 2021
-// Last Modified By : Andrew Beach
-// Last Modified On : Sat Apr 23 13:10:00 2022
-// Update Count     : 1
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Sun Nov 26 18:49:57 2023
+// Update Count     : 2
 //
 
@@ -213,7 +213,5 @@
 		auto type = obj->type->stripDeclarator();
 		if ( dynamic_cast< const ast::FunctionType * >( type ) ) return;
-		SemanticError( obj->location,
-			toCString( "operator ", obj->name.c_str(),
-			" is not a function or function pointer." ) );
+		SemanticError( obj->location, "operator %s is not a function or function pointer.", obj->name.c_str() );
 	}
 };
Index: src/Validate/ReplaceTypedef.cpp
===================================================================
--- src/Validate/ReplaceTypedef.cpp	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/Validate/ReplaceTypedef.cpp	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -9,7 +9,7 @@
 // Author           : Andrew Beach
 // Created On       : Tue Jun 29 14:59:00 2022
-// Last Modified By : Andrew Beach
-// Last Modified On : Tue Sep 20 17:00:00 2022
-// Update Count     : 2
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon Nov 27 08:55:06 2023
+// Update Count     : 3
 //
 
@@ -111,5 +111,5 @@
 			if ( !rtt ) {
 				assert( location );
-				SemanticError( *location, "Cannot apply type parameters to base type of " + type->name );
+				SemanticError( *location, "Cannot apply type parameters to base type of %s.", type->name.c_str() );
 			}
 			rtt->params.clear();
@@ -125,5 +125,5 @@
 		if ( base == typedeclNames.end() ) {
 			assert( location );
-			SemanticError( *location, toString( "Use of undefined type ", type->name ) );
+			SemanticError( *location, "Use of undefined type %s.", type->name.c_str() );
 		}
 		return ast::mutate_field( type, &ast::TypeInstType::base, base->second );
Index: src/Virtual/ExpandCasts.cc
===================================================================
--- src/Virtual/ExpandCasts.cc	(revision c40157ec46899c5e6a8afa9d8f9f0dba822d528f)
+++ src/Virtual/ExpandCasts.cc	(revision b1f2007d03a9290ff9a472f7132714791f65e6b4)
@@ -9,7 +9,7 @@
 // Author           : Andrew Beach
 // Created On       : Mon Jul 24 13:59:00 2017
-// Last Modified By : Andrew Beach
-// Last Modified On : Thu Aug 11 12:06:00 2022
-// Update Count     : 5
+// Last Modified By : Peter A. Buhr
+// Last Modified On : Mon Nov 27 09:28:20 2023
+// Update Count     : 10
 //
 
@@ -160,9 +160,7 @@
 
 	// Helper function for throwing semantic errors.
-	auto throwError = [&fieldName, &errorLocation, &oldDecl](
-			std::string const & message ) {
-		std::string const & context = "While following head pointer of " +
-			oldDecl->name + " named '" + fieldName + "': ";
-		SemanticError( errorLocation, context + message );
+	auto throwError = [&fieldName, &errorLocation, &oldDecl]( std::string const & message ) {
+		SemanticError( errorLocation, "While following head pointer of %s named \"%s\": %s",
+					   oldDecl->name.c_str(), fieldName.c_str(), message.c_str() );
 	};
 
