Index: src/Common/SemanticError.cc
===================================================================
--- src/Common/SemanticError.cc	(revision 4f1b2d6944aa29a9e7a67edffd9ed44c3b919a18)
+++ src/Common/SemanticError.cc	(revision 4c2fe47e178e4074ffe9d1387cbe05d69e4c0db3)
@@ -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 4f1b2d6944aa29a9e7a67edffd9ed44c3b919a18)
+++ src/Common/SemanticError.h	(revision 4c2fe47e178e4074ffe9d1387cbe05d69e4c0db3)
@@ -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
 };
 
