Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/CodeGen/CodeGenerator.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -18,5 +18,4 @@
 #include <list>                      // for _List_iterator, list, list<>::it...
 
-#include "Common/SemanticError.h"    // for SemanticError
 #include "Common/UniqueName.h"       // for UniqueName
 #include "Common/utility.h"          // for CodeLocation, toString
Index: src/CodeGen/FixMain.cc
===================================================================
--- src/CodeGen/FixMain.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/CodeGen/FixMain.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -39,5 +39,5 @@
 	{
 		if(main_signature) {
-			throw SemanticError(functionDecl, "Multiple definition of main routine\n");
+			SemanticError(functionDecl, "Multiple definition of main routine\n");
 		}
 		main_signature.reset( functionDecl->clone() );
Index: src/CodeGen/FixNames.cc
===================================================================
--- src/CodeGen/FixNames.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/CodeGen/FixNames.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -118,5 +118,5 @@
 			int nargs = functionDecl->get_functionType()->get_parameters().size();
 			if( !(nargs == 0 || nargs == 2 || nargs == 3) ) {
-				throw SemanticError(functionDecl, "Main expected to have 0, 2 or 3 arguments\n");
+				SemanticError(functionDecl, "Main expected to have 0, 2 or 3 arguments\n");
 			}
 			functionDecl->get_statements()->get_kids().push_back( new ReturnStmt( new ConstantExpr( Constant::from_int( 0 ) ) ) );
Index: src/CodeTools/DeclStats.cc
===================================================================
--- src/CodeTools/DeclStats.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/CodeTools/DeclStats.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -24,5 +24,4 @@
 
 #include "Common/PassVisitor.h"
-#include "Common/SemanticError.h"  // for SemanticError
 #include "Common/VectorMap.h"      // for VectorMap
 #include "GenPoly/GenPoly.h"       // for hasPolyBase
Index: src/CodeTools/TrackLoc.cc
===================================================================
--- src/CodeTools/TrackLoc.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/CodeTools/TrackLoc.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -24,5 +24,4 @@
 
 #include "Common/PassVisitor.h"      // for PassVisitor
-#include "Common/SemanticError.h"    // for SemanticError
 #include "Common/utility.h"          // for CodeLocation
 #include "SynTree/BaseSyntaxNode.h"  // for BaseSyntaxNode
Index: src/Common/ErrorObjects.h
===================================================================
--- src/Common/ErrorObjects.h	(revision a16764a6fbfe44300fc8834400a31c89befda091)
+++ src/Common/ErrorObjects.h	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -0,0 +1,59 @@
+//
+// 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.
+//
+// ErrorObjects.h --
+//
+// Author           : Thierry Delisle
+// Created On       : Wed Feb 28 15:16:47 2018
+// Last Modified By :
+// Last Modified On :
+// Update Count     :
+//
+
+#pragma once
+
+
+#include <exception>	// for exception
+#include <iostream>	// for ostream
+#include <list>		// for list
+#include <string>		// for string
+#include <unistd.h>	// for isatty
+
+#include "CodeLocation.h"								// for CodeLocation, toString
+
+struct error {
+	CodeLocation location;
+	std::string description;
+
+	error() = default;
+	error( CodeLocation loc, const std::string & str ) : location( loc ), description( str ) {}
+};
+
+class SemanticErrorException : public std::exception {
+  public:
+  	SemanticErrorException() = default;
+	SemanticErrorException( CodeLocation location, std::string error );
+	~SemanticErrorException() throw() {}
+
+	void append( SemanticErrorException & other );
+	void append( CodeLocation location, const std::string & );
+	bool isEmpty() const;
+	void print();
+  private:
+	std::list< error > errors;
+};
+
+void SemanticWarningImpl( CodeLocation location, std::string error );
+
+template< typename T >
+static inline void SemanticWarningImpl( const T * obj, const std::string & error ) {
+	SemanticWarning( obj->location, toString( error, obj ) );
+}
+
+template< typename T >
+static inline void SemanticWarningImpl( CodeLocation location, const T * obj, const std::string & error ) {
+	SemanticWarningImpl( location, toString( error, obj ) );
+}
Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/Common/PassVisitor.impl.h	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -65,5 +65,5 @@
 	DeclList_t* beforeDecls = visitor.get_beforeDecls();
 	DeclList_t* afterDecls  = visitor.get_afterDecls();
-	SemanticError errors;
+	SemanticErrorException errors;
 
 	for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
@@ -76,5 +76,5 @@
 			// run visitor on declaration
 			maybeAccept_impl( *i, visitor );
-		} catch( SemanticError &e ) {
+		} catch( SemanticErrorException &e ) {
 			errors.append( e );
 		}
@@ -92,5 +92,5 @@
 	DeclList_t* beforeDecls = mutator.get_beforeDecls();
 	DeclList_t* afterDecls  = mutator.get_afterDecls();
-	SemanticError errors;
+	SemanticErrorException errors;
 
 	for ( std::list< Declaration* >::iterator i = decls.begin(); ; ++i ) {
@@ -102,5 +102,5 @@
 			// run mutator on declaration
 			maybeMutate_impl( *i, mutator );
-		} catch( SemanticError &e ) {
+		} catch( SemanticErrorException &e ) {
 			errors.append( e );
 		}
@@ -125,5 +125,5 @@
 inline void maybeAccept_impl( Container & container, PassVisitor< pass_type > & visitor ) {
 	if ( ! visitor.get_visit_children() ) return;
-	SemanticError errors;
+	SemanticErrorException errors;
 	for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
 		try {
@@ -131,5 +131,5 @@
 				(*i)->accept( visitor );
 			}
-		} catch( SemanticError &e ) {
+		} catch( SemanticErrorException &e ) {
 			errors.append( e );
 		}
@@ -152,5 +152,5 @@
 inline void maybeMutate_impl( Container & container, PassVisitor< pass_type > & mutator ) {
 	if ( ! mutator.get_visit_children() ) return;
-	SemanticError errors;
+	SemanticErrorException errors;
 	for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
 		try {
@@ -159,5 +159,5 @@
 				assert( *i );
 			} // if
-		} catch( SemanticError &e ) {
+		} catch( SemanticErrorException &e ) {
 			errors.append( e );
 		} // try
@@ -172,5 +172,5 @@
 void PassVisitor< pass_type >::handleStatementList( std::list< Statement * > & statements, func_t func ) {
 	if ( ! get_visit_children() ) return;
-	SemanticError errors;
+	SemanticErrorException errors;
 
 	// don't want statements from outer CompoundStmts to be added to this CompoundStmt
@@ -195,5 +195,5 @@
 			    || ( empty( beforeDecls ) && empty( afterDecls )) );
 
-		} catch ( SemanticError &e ) {
+		} catch ( SemanticErrorException &e ) {
 			errors.append( e );
 		}
Index: src/Common/SemanticError.cc
===================================================================
--- src/Common/SemanticError.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/Common/SemanticError.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -23,29 +23,71 @@
 #include "SemanticError.h"
 
-SemanticError::SemanticError( CodeLocation location, std::string error ) {
+SemanticErrorException::SemanticErrorException( CodeLocation location, std::string error ) {
 	append( location, error );
 }
 
-void SemanticError::append( SemanticError &other ) {
+void SemanticErrorException::append( SemanticErrorException &other ) {
 	errors.splice( errors.end(), other.errors );
 }
 
-void SemanticError::append( CodeLocation location, const std::string & msg ) {
+void SemanticErrorException::append( CodeLocation location, const std::string & msg ) {
 	errors.emplace_back( location, msg );
 }
 
-bool SemanticError::isEmpty() const {
+bool SemanticErrorException::isEmpty() const {
 	return errors.empty();
 }
 
-void SemanticError::print() {
+void SemanticErrorException::print() {
 	using std::to_string;
 	for( auto err : errors ) {
-		std::cerr << bold() << err.location << error_str() << reset_font() << err.description << std::endl;
+		std::cerr << ErrorHelpers::bold() << err.location << ErrorHelpers::error_str() << ErrorHelpers::reset_font() << err.description << std::endl;
 	}
 }
 
-SemanticWarning::SemanticWarning( CodeLocation location, std::string msg ) {
-	std::cerr << bold() << location << warning_str() << reset_font() << msg << std::endl;
+void SemanticError( CodeLocation location, std::string error ) {
+	throw SemanticErrorException(location, error);
+}
+
+void SemanticWarningImpl( CodeLocation location, std::string msg ) {
+	std::cerr << ErrorHelpers::bold() << location << ErrorHelpers::warning_str() << ErrorHelpers::reset_font() << msg << std::endl;
+}
+
+//-----------------------------------------------------------------------------
+// Helpers
+namespace ErrorHelpers {
+	const std::string & error_str() {
+		static std::string str = isatty( STDERR_FILENO ) ? "\e[31merror:\e[39m " : "error: ";
+		return str;
+	}
+
+	const std::string & warning_str() {
+		static std::string str = isatty( STDERR_FILENO ) ? "\e[95mwarning:\e[39m " : "warning: ";
+		return str;
+	}
+
+	const std::string & bold_ttycode() {
+		static std::string str = isatty( STDERR_FILENO ) ? "\e[1m" : "";
+		return str;
+	}
+
+	const std::string & reset_font_ttycode() {
+		static std::string str = isatty( STDERR_FILENO ) ? "\e[0m" : "";
+		return str;
+	}
+
+	std::string make_bold( const std::string & str ) {
+		return bold_ttycode() + str + reset_font_ttycode();
+	}
+
+	std::ostream & operator<<(std::ostream & os, bold) {
+		os << bold_ttycode();
+		return os;
+	}
+
+	std::ostream & operator<<(std::ostream & os, reset_font) {
+		os << reset_font_ttycode();
+		return os;
+	}
 }
 
Index: src/Common/SemanticError.h
===================================================================
--- src/Common/SemanticError.h	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/Common/SemanticError.h	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -16,111 +16,61 @@
 #pragma once
 
-#include <exception>									// for exception
-#include <iostream>										// for ostream
-#include <list>											// for list
-#include <string>										// for string
-#include <unistd.h>										// for isatty
-
-#include "CodeLocation.h"								// for CodeLocation, toString
+#include "ErrorObjects.h"
 
 //-----------------------------------------------------------------------------
 // Errors
-struct error {
-	CodeLocation location;
-	std::string description;
 
-	error() = default;
-	error( CodeLocation loc, const std::string & str ) : location( loc ), description( str ) {}
-};
-
-class SemanticError : public std::exception {
-  public:
-  	SemanticError() = default;
-	SemanticError( CodeLocation location, std::string error );
-	~SemanticError() throw() {}
-
-	// constructs an exception using the given message and the printed representation of the obj (T must have a print method)
-	template< typename T > SemanticError(const T * obj, const std::string & error);
-	template< typename T > SemanticError( CodeLocation location, const T * obj, const std::string & error);
-
-	static inline const std::string & error_str() {
-		static std::string str = isatty( STDERR_FILENO ) ? "\e[31merror:\e[39m " : "error: ";
-		return str;
-	}
-
-	void append( SemanticError & other );
-	void append( CodeLocation location, const std::string & );
-	bool isEmpty() const;
-	void print();
-  private:
-	std::list< error > errors;
-};
+__attribute__((noreturn)) void SemanticError( CodeLocation location, std::string error );
 
 template< typename T >
-SemanticError::SemanticError( const T * obj, const std::string & error )
-	: SemanticError( obj->location, toString( error, obj ) )
-{}
+__attribute__((noreturn)) static inline void SemanticError( const T * obj, const std::string & error ) {
+	SemanticError( obj->location, toString( error, obj ) );
+}
 
 template< typename T >
-SemanticError::SemanticError( CodeLocation location, const T * obj, const std::string & error )
-	: SemanticError( location, toString( error, obj ) )
-{}
+__attribute__((noreturn)) static inline void SemanticError( CodeLocation location, const T * obj, const std::string & error ) {
+	SemanticError( location, toString( error, obj ) );
+}
 
 //-----------------------------------------------------------------------------
 // Warnings
-class SemanticWarning {
-  public:
-  	SemanticWarning( CodeLocation location, std::string error );
-	~SemanticWarning() throw() {}
 
-	// constructs an exception using the given message and the printed representation of the obj (T must have a print method)
-	template< typename T > SemanticWarning(const T * obj, const std::string & error);
-	template< typename T > SemanticWarning( CodeLocation location, const T * obj, const std::string & error);
+constexpr const char * const WarningFormats[] = {
 
-	static inline const std::string & warning_str() {
-		static std::string str = isatty( STDERR_FILENO ) ? "\e[95mwarning:\e[39m " : "warning: ";
-		return str;
-	}
-
-  private:
 };
 
-template< typename T >
-SemanticWarning::SemanticWarning( const T * obj, const std::string & error )
-	: SemanticWarning( obj->location, toString( error, obj ) )
-{}
+enum class Warning {
+	NUMBER_OF_WARNINGS, //This MUST be the last warning
+};
 
-template< typename T >
-SemanticWarning::SemanticWarning( CodeLocation location, const T * obj, const std::string & error )
-	: SemanticWarning( location, toString( error, obj ) )
-{}
+static_assert(
+	(sizeof(WarningFormats) / sizeof(WarningFormats[0])) == ((unsigned long)Warning::NUMBER_OF_WARNINGS),
+	"Each warning format should have a corresponding warning enum value"
+);
+
+#define SemanticWarning(loc, id, ...) SemanticWarningImpl(loc, id, WarningFormats[id], __VA_ARGS__)
+
+void SemanticWarningImpl (CodeLocation loc, Warning warn, const char * const fmt, ...) __attribute__((format(printf, 3, 4)));
+
 
 //-----------------------------------------------------------------------------
 // Helpers
-static inline const std::string & bold_ttycode() {
-	static std::string str = isatty( STDERR_FILENO ) ? "\e[1m" : "";
-	return str;
+namespace ErrorHelpers {
+	const std::string & error_str();
+	const std::string & warning_str();
+	const std::string & bold_ttycode();
+	const std::string & reset_font_ttycode();
+
+	std::string make_bold( const std::string & str );
+
+	struct bold {};
+	std::ostream & operator<<(std::ostream & os, bold);
+
+	struct reset_font {};
+	std::ostream & operator<<(std::ostream & os, reset_font);
 }
 
-static inline const std::string & reset_font_ttycode() {
-	static std::string str = isatty( STDERR_FILENO ) ? "\e[0m" : "";
-	return str;
-}
 
-static inline std::string make_bold( const std::string & str ) {
-	return bold_ttycode() + str + reset_font_ttycode();
-}
 
-struct bold {};
-static inline std::ostream & operator<<(std::ostream & os, bold) {
-	os << bold_ttycode();
-	return os;
-}
-
-struct reset_font {};
-static inline std::ostream & operator<<(std::ostream & os, reset_font) {
-	os << reset_font_ttycode();
-	return os;
-}
 
 // Local Variables: //
Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/Concurrency/Keywords.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -280,5 +280,5 @@
 		if( ! decl->body ) return;
 
-		if( !type_decl ) throw SemanticError( decl, context_error );
+		if( !type_decl ) SemanticError( decl, context_error );
 
 		FunctionDecl * func = forwardDeclare( decl );
@@ -417,9 +417,9 @@
 		if( mutexArgs.empty() ) return;
 
-		if( CodeGen::isConstructor(decl->name) ) throw SemanticError( decl, "constructors cannot have mutex parameters" );
+		if( CodeGen::isConstructor(decl->name) ) SemanticError( decl, "constructors cannot have mutex parameters" );
 
 		bool isDtor = CodeGen::isDestructor( decl->name );
 
-		if( isDtor && mutexArgs.size() != 1 ) throw SemanticError( decl, "destructors can only have 1 mutex argument" );
+		if( isDtor && mutexArgs.size() != 1 ) SemanticError( decl, "destructors can only have 1 mutex argument" );
 
 		for(auto arg : mutexArgs) {
@@ -430,7 +430,6 @@
 		if( ! body ) return;
 
-		if( !monitor_decl ) throw SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>" );
-		if( !guard_decl ) throw SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>" );
-		if( !dtor_guard_decl ) throw SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>" );
+		if( !monitor_decl || !guard_decl || !dtor_guard_decl )
+			SemanticError( decl, "mutex keyword requires monitors to be in scope, add #include <monitor>" );
 
 		if( isDtor ) {
@@ -478,13 +477,13 @@
 		//Makes sure it's not a copy
 		ReferenceType* rty = dynamic_cast< ReferenceType * >( ty );
-		if( ! rty ) throw SemanticError( arg, "Mutex argument must be of reference type " );
+		if( ! rty ) SemanticError( arg, "Mutex argument must be of reference type " );
 
 		//Make sure the we are pointing directly to a type
 		Type* base = rty->get_base();
-		if( dynamic_cast< ReferenceType * >( base ) ) throw SemanticError( arg, "Mutex argument have exactly one level of indirection " );
-		if( dynamic_cast< PointerType * >( base ) ) throw SemanticError( arg, "Mutex argument have exactly one level of indirection " );
+		if( dynamic_cast< ReferenceType * >( base ) ) SemanticError( arg, "Mutex argument have exactly one level of indirection " );
+		if( dynamic_cast< PointerType * >( base ) ) SemanticError( arg, "Mutex argument have exactly one level of indirection " );
 
 		//Make sure that typed isn't mutex
-		if( base->get_mutex() ) throw SemanticError( arg, "mutex keyword may only appear once per argument " );
+		if( base->get_mutex() ) SemanticError( arg, "mutex keyword may only appear once per argument " );
 	}
 
@@ -624,5 +623,5 @@
 		if( type && type->get_baseStruct()->is_thread() ) {
 			if( !thread_decl || !thread_ctor_seen ) {
-				throw SemanticError( type->get_baseStruct()->location, "thread keyword requires threads to be in scope, add #include <thread>");
+				SemanticError( type->get_baseStruct()->location, "thread keyword requires threads to be in scope, add #include <thread>");
 			}
 
Index: src/Concurrency/Waitfor.cc
===================================================================
--- src/Concurrency/Waitfor.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/Concurrency/Waitfor.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -250,5 +250,5 @@
 	Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
 		if( !decl_monitor || !decl_acceptable || !decl_mask )
-			throw SemanticError( waitfor, "waitfor keyword requires monitors to be in scope, add #include <monitor>" );
+			SemanticError( waitfor, "waitfor keyword requires monitors to be in scope, add #include <monitor>" );
 
 		CompoundStmt * stmt = new CompoundStmt();
Index: src/ControlStruct/ExceptTranslate.cc
===================================================================
--- src/ControlStruct/ExceptTranslate.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/ControlStruct/ExceptTranslate.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -572,7 +572,7 @@
 			// Pass.
 		} else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
-			throw SemanticError(catchStmt->location, "catch must have exception type");
+			SemanticError(catchStmt->location, "catch must have exception type");
 		} else {
-			throw SemanticError(catchStmt->location, "catchResume must have exception type");
+			SemanticError(catchStmt->location, "catchResume must have exception type");
 		}
 
Index: src/ControlStruct/LabelFixer.cc
===================================================================
--- src/ControlStruct/LabelFixer.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/ControlStruct/LabelFixer.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -92,5 +92,5 @@
 			} else if ( labelTable[ l ]->defined() ) {
 				// defined twice, error
-				throw SemanticError( l.get_statement()->location, "Duplicate definition of label: " + l.get_name() );
+				SemanticError( l.get_statement()->location, "Duplicate definition of label: " + l.get_name() );
 			}	else {
 				// used previously, but undefined until now -> link with this entry
@@ -117,9 +117,9 @@
 
 	// Builds a table that maps a label to its defining statement.
-	std::map<Label, Statement * > *LabelFixer::resolveJumps() throw ( SemanticError ) {
+	std::map<Label, Statement * > *LabelFixer::resolveJumps() throw ( SemanticErrorException ) {
 		std::map< Label, Statement * > *ret = new std::map< Label, Statement * >();
 		for ( std::map< Label, Entry * >::iterator i = labelTable.begin(); i != labelTable.end(); ++i ) {
 			if ( ! i->second->defined() ) {
-				throw SemanticError( i->first.get_statement()->location, "Use of undefined label: " + i->first.get_name() );
+				SemanticError( i->first.get_statement()->location, "Use of undefined label: " + i->first.get_name() );
 			}
 			(*ret)[ i->first ] = i->second->get_definition();
Index: src/ControlStruct/LabelFixer.h
===================================================================
--- src/ControlStruct/LabelFixer.h	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/ControlStruct/LabelFixer.h	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -33,5 +33,5 @@
 		LabelFixer( LabelGenerator *gen = 0 );
 
-		std::map < Label, Statement * > *resolveJumps() throw ( SemanticError );
+		std::map < Label, Statement * > *resolveJumps() throw ( SemanticErrorException );
 
 		// Declarations
Index: src/ControlStruct/MLEMutator.cc
===================================================================
--- src/ControlStruct/MLEMutator.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/ControlStruct/MLEMutator.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -98,5 +98,5 @@
 
 
-	Statement *MLEMutator::postmutate( BranchStmt *branchStmt ) throw ( SemanticError ) {
+	Statement *MLEMutator::postmutate( BranchStmt *branchStmt ) throw ( SemanticErrorException ) {
 		std::string originalTarget = branchStmt->originalTarget;
 
@@ -115,5 +115,5 @@
 					} else {
 						// break target is outmost control structure
-						if ( enclosingControlStructures.empty() ) throw SemanticError( branchStmt->location, "'break' outside a loop, switch, or labelled block" );
+						if ( enclosingControlStructures.empty() ) SemanticError( branchStmt->location, "'break' outside a loop, switch, or labelled block" );
 						targetEntry = enclosingControlStructures.rbegin();
 					} // if
@@ -124,5 +124,5 @@
 				// ensure that selected target is valid
 				if ( targetEntry == enclosingControlStructures.rend() || (isContinue && ! isLoop( targetEntry->get_controlStructure() ) ) ) {
-					throw SemanticError( branchStmt->location, toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) );
+					SemanticError( branchStmt->location, toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) );
 				} // if
 				break;
Index: src/ControlStruct/MLEMutator.h
===================================================================
--- src/ControlStruct/MLEMutator.h	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/ControlStruct/MLEMutator.h	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -37,5 +37,5 @@
 
 		void premutate( CompoundStmt *cmpndStmt );
-		Statement * postmutate( BranchStmt *branchStmt ) throw ( SemanticError );
+		Statement * postmutate( BranchStmt *branchStmt ) throw ( SemanticErrorException );
 		void premutate( WhileStmt *whileStmt );
 		Statement * postmutate( WhileStmt *whileStmt );
Index: src/ControlStruct/Mutate.cc
===================================================================
--- src/ControlStruct/Mutate.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/ControlStruct/Mutate.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -18,5 +18,4 @@
 
 #include "Common/PassVisitor.h"    // for mutateAll
-#include "Common/SemanticError.h"  // for SemanticError
 #include "ForExprMutator.h"        // for ForExprMutator
 #include "LabelFixer.h"            // for LabelFixer
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/GenPoly/Box.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -215,5 +215,5 @@
 	inline void mutateTranslationUnit( std::list< Declaration* > &translationUnit, MutatorType &mutator ) {
 		bool seenIntrinsic = false;
-		SemanticError errors;
+		SemanticErrorException errors;
 		for ( typename std::list< Declaration* >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
 			try {
@@ -228,5 +228,5 @@
 					assert( *i );
 				} // if
-			} catch( SemanticError &e ) {
+			} catch( SemanticErrorException &e ) {
 				errors.append( e );
 			} // try
@@ -575,5 +575,5 @@
 						}
 					} else {
-						throw SemanticError( argBaseType, "Cannot pass non-struct type for generic struct: " );
+						SemanticError( argBaseType, "Cannot pass non-struct type for generic struct: " );
 					}
 				}
@@ -597,5 +597,5 @@
 					} else {
 						// xxx - should this be an assertion?
-						throw SemanticError( appExpr, toString( *env, "\nunbound type variable: ", tyParm->first, " in application " ) );
+						SemanticError( appExpr, toString( *env, "\nunbound type variable: ", tyParm->first, " in application " ) );
 					} // if
 				} // if
Index: src/GenPoly/FindFunction.cc
===================================================================
--- src/GenPoly/FindFunction.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/GenPoly/FindFunction.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -19,5 +19,4 @@
 
 #include "Common/PassVisitor.h"         // for PassVisitor
-#include "Common/SemanticError.h"       // for SemanticError
 #include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::iterator
 #include "GenPoly/GenPoly.h"            // for TyVarMap
Index: src/GenPoly/InstantiateGeneric.cc
===================================================================
--- src/GenPoly/InstantiateGeneric.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/GenPoly/InstantiateGeneric.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -24,5 +24,4 @@
 #include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
 #include "Common/ScopedMap.h"          // for ScopedMap
-#include "Common/SemanticError.h"      // for SemanticError
 #include "Common/UniqueName.h"         // for UniqueName
 #include "Common/utility.h"            // for deleteAll, cloneAll
Index: src/GenPoly/Lvalue.cc
===================================================================
--- src/GenPoly/Lvalue.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/GenPoly/Lvalue.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -18,5 +18,4 @@
 
 #include "Common/PassVisitor.h"
-#include "Common/SemanticError.h"        // for SemanticError
 #include "GenPoly.h"                     // for isPolyType
 #include "Lvalue.h"
Index: src/GenPoly/Specialize.cc
===================================================================
--- src/GenPoly/Specialize.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/GenPoly/Specialize.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -23,5 +23,4 @@
 
 #include "Common/PassVisitor.h"
-#include "Common/SemanticError.h"        // for SemanticError
 #include "Common/UniqueName.h"           // for UniqueName
 #include "Common/utility.h"              // for group_iterate
Index: src/InitTweak/FixGlobalInit.cc
===================================================================
--- src/InitTweak/FixGlobalInit.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/InitTweak/FixGlobalInit.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -21,5 +21,4 @@
 
 #include "Common/PassVisitor.h"
-#include "Common/SemanticError.h"  // for SemanticError
 #include "Common/UniqueName.h"     // for UniqueName
 #include "InitTweak.h"             // for isIntrinsicSingleArgCallStmt
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/InitTweak/FixInit.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -213,5 +213,5 @@
 			Expression * postmutate( UntypedExpr * expr );
 
-			SemanticError errors;
+			SemanticErrorException errors;
 		  private:
 			template< typename... Params >
@@ -276,10 +276,10 @@
 			// can't use mutateAll, because need to insert declarations at top-level
 			// can't use DeclMutator, because sometimes need to insert IfStmt, etc.
-			SemanticError errors;
+			SemanticErrorException errors;
 			for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
 				try {
 					maybeMutate( *i, fixer );
 					translationUnit.splice( i, fixer.pass.staticDtorDecls );
-				} catch( SemanticError &e ) {
+				} catch( SemanticErrorException &e ) {
 					errors.append( e );
 				} // try
@@ -894,5 +894,5 @@
 			)
 			if ( ! diff.empty() ) {
-				throw SemanticError( stmt, std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " " );
+				SemanticError( stmt, std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " " );
 			} // if
 			// S_G-S_L results in set of objects that must be destructed
@@ -945,5 +945,5 @@
 			GuardValue( isCtor );
 			GuardValue( structDecl );
-			errors = SemanticError();  // clear previous errors
+			errors = SemanticErrorException();  // clear previous errors
 
 			// need to start with fresh sets
@@ -1034,5 +1034,5 @@
 								function->get_statements()->push_back( callStmt );
 							}
-						} catch ( SemanticError & error ) {
+						} catch ( SemanticErrorException & error ) {
 							emit( funcDecl->location, "in ", CodeGen::genPrettyType( function->get_functionType(), function->get_name() ), ", field ", field->get_name(), " not explicitly ", isCtor ? "constructed" : "destructed",  " and no ", isCtor ? "default constructor" : "destructor", " found" );
 						}
@@ -1110,5 +1110,5 @@
 		template< typename Visitor, typename... Params >
 		void error( Visitor & v, CodeLocation loc, const Params &... params ) {
-			SemanticError err( loc, toString( params... ) );
+			SemanticErrorException err( loc, toString( params... ) );
 			v.errors.append( err );
 		}
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/InitTweak/GenInit.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -317,7 +317,7 @@
 		if ( tryConstruct( objDecl ) && ( managedTypes.isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) {
 			// constructed objects cannot be designated
-			if ( isDesignated( objDecl->get_init() ) ) throw SemanticError( objDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n" );
+			if ( isDesignated( objDecl->get_init() ) ) SemanticError( objDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n" );
 			// constructed objects should not have initializers nested too deeply
-			if ( ! checkInitDepth( objDecl ) ) throw SemanticError( objDecl, "Managed object's initializer is too deep " );
+			if ( ! checkInitDepth( objDecl ) ) SemanticError( objDecl, "Managed object's initializer is too deep " );
 
 			objDecl->set_init( genCtorInit( objDecl ) );
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/InitTweak/InitTweak.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -225,5 +225,5 @@
 					// xxx - this shouldn't be an error, but need a way to
 					// terminate without creating output, so should catch this error
-					throw SemanticError( init->location, "unbalanced list initializers" );
+					SemanticError( init->location, "unbalanced list initializers" );
 				}
 
Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/Parser/DeclarationNode.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -576,15 +576,15 @@
 					dst->basictype = src->basictype;
 				} else if ( src->basictype != DeclarationNode::NoBasicType )
-					throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::basicTypeNames[ src->basictype ] + " in type: " );
+					SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::basicTypeNames[ src->basictype ] + " in type: " );
 
 				if ( dst->complextype == DeclarationNode::NoComplexType ) {
 					dst->complextype = src->complextype;
 				} else if ( src->complextype != DeclarationNode::NoComplexType )
-					throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::complexTypeNames[ src->complextype ] + " in type: " );
+					SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::complexTypeNames[ src->complextype ] + " in type: " );
 
 				if ( dst->signedness == DeclarationNode::NoSignedness ) {
 					dst->signedness = src->signedness;
 				} else if ( src->signedness != DeclarationNode::NoSignedness )
-					throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::signednessNames[ src->signedness ] + " in type: " );
+					SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::signednessNames[ src->signedness ] + " in type: " );
 
 				if ( dst->length == DeclarationNode::NoLength ) {
@@ -593,5 +593,5 @@
 					dst->length = DeclarationNode::LongLong;
 				} else if ( src->length != DeclarationNode::NoLength )
-					throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::lengthNames[ src->length ] + " in type: " );
+					SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::lengthNames[ src->length ] + " in type: " );
 			} // if
 			break;
@@ -940,5 +940,5 @@
 
 void buildList( const DeclarationNode * firstNode, std::list< Declaration * > &outputList ) {
-	SemanticError errors;
+	SemanticErrorException errors;
 	std::back_insert_iterator< std::list< Declaration * > > out( outputList );
 
@@ -960,5 +960,5 @@
 				* out++ = decl;
 			} // if
-		} catch( SemanticError &e ) {
+		} catch( SemanticErrorException &e ) {
 			errors.append( e );
 		} // try
@@ -971,5 +971,5 @@
 
 void buildList( const DeclarationNode * firstNode, std::list< DeclarationWithType * > &outputList ) {
-	SemanticError errors;
+	SemanticErrorException errors;
 	std::back_insert_iterator< std::list< DeclarationWithType * > > out( outputList );
 
@@ -994,5 +994,5 @@
 				} // if
 			} // if
-		} catch( SemanticError &e ) {
+		} catch( SemanticErrorException &e ) {
 			errors.append( e );
 		} // try
@@ -1005,5 +1005,5 @@
 
 void buildTypeList( const DeclarationNode * firstNode, std::list< Type * > &outputList ) {
-	SemanticError errors;
+	SemanticErrorException errors;
 	std::back_insert_iterator< std::list< Type * > > out( outputList );
 	const DeclarationNode * cur = firstNode;
@@ -1012,5 +1012,5 @@
 		try {
 			* out++ = cur->buildType();
-		} catch( SemanticError &e ) {
+		} catch( SemanticErrorException &e ) {
 			errors.append( e );
 		} // try
@@ -1024,5 +1024,5 @@
 
 Declaration * DeclarationNode::build() const {
-	if ( ! error.empty() ) throw SemanticError( this, error + " in declaration of " );
+	if ( ! error.empty() ) SemanticError( this, error + " in declaration of " );
 
 	if ( asmStmt ) {
@@ -1047,5 +1047,5 @@
 		//    inline _Noreturn int i;			// disallowed
 		if ( type->kind != TypeData::Function && funcSpecs.any() ) {
-			throw SemanticError( this, "invalid function specifier for " );
+			SemanticError( this, "invalid function specifier for " );
 		} // if
 		return buildDecl( type, name ? *name : string( "" ), storageClasses, maybeBuild< Expression >( bitfieldWidth ), funcSpecs, linkage, asmName, maybeBuild< Initializer >(initializer), attributes )->set_extension( extension );
@@ -1057,5 +1057,5 @@
 	//    inlne _Noreturn enum   E { ... };		// disallowed
 	if ( funcSpecs.any() ) {
-		throw SemanticError( this, "invalid function specifier for " );
+		SemanticError( this, "invalid function specifier for " );
 	} // if
 	assertf( name, "ObjectDecl must a have name\n" );
Index: src/Parser/ExpressionNode.cc
===================================================================
--- src/Parser/ExpressionNode.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/Parser/ExpressionNode.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -356,5 +356,5 @@
 
 Expression * build_field_name_FLOATING_FRACTIONconstant( const string & str ) {
-	if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) throw SemanticError( yylloc, "invalid tuple index " + str );
+	if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) SemanticError( yylloc, "invalid tuple index " + str );
 	Expression * ret = build_constantInteger( *new string( str.substr(1) ) );
 	delete &str;
@@ -363,5 +363,5 @@
 
 Expression * build_field_name_FLOATING_DECIMALconstant( const string & str ) {
-	if ( str[str.size()-1] != '.' ) throw SemanticError( yylloc, "invalid tuple index " + str );
+	if ( str[str.size()-1] != '.' ) SemanticError( yylloc, "invalid tuple index " + str );
 	Expression * ret = build_constantInteger( *new string( str.substr( 0, str.size()-1 ) ) );
 	delete &str;
Index: src/Parser/LinkageSpec.cc
===================================================================
--- src/Parser/LinkageSpec.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/Parser/LinkageSpec.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -34,5 +34,5 @@
 		return BuiltinC;
 	} else {
-		throw SemanticError( location, "Invalid linkage specifier " + *spec );
+		SemanticError( location, "Invalid linkage specifier " + *spec );
 	} // if
 }
@@ -48,5 +48,5 @@
 		return old_spec;
 	} else {
-		throw SemanticError( location, "Invalid linkage specifier " + *cmd );
+		SemanticError( location, "Invalid linkage specifier " + *cmd );
 	} // if
 }
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/Parser/ParseNode.h	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -419,5 +419,5 @@
 template< typename SynTreeType, typename NodeType, template< typename, typename...> class Container, typename... Args >
 void buildList( const NodeType * firstNode, Container< SynTreeType *, Args... > &outputList ) {
-	SemanticError errors;
+	SemanticErrorException errors;
 	std::back_insert_iterator< Container< SynTreeType *, Args... > > out( outputList );
 	const NodeType * cur = firstNode;
@@ -432,5 +432,5 @@
 				assertf(false, "buildList unknown type");
 			} // if
-		} catch( SemanticError &e ) {
+		} catch( SemanticErrorException &e ) {
 			errors.append( e );
 		} // try
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/Parser/TypeData.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -519,5 +519,5 @@
 
 static string genTSError( string msg, DeclarationNode::BasicType basictype ) {
-	throw SemanticError( yylloc, string( "invalid type specifier \"" ) + msg + "\" for type \"" + DeclarationNode::basicTypeNames[basictype] + "\"." );
+	SemanticError( yylloc, string( "invalid type specifier \"" ) + msg + "\" for type \"" + DeclarationNode::basicTypeNames[basictype] + "\"." );
 } // genTSError
 
@@ -919,8 +919,8 @@
 				// type set => parameter name already transformed by a declaration names so there is a duplicate
 				// declaration name attempting a second transformation
-				if ( param->type ) throw SemanticError( param->location, string( "duplicate declaration name " ) + *param->name );
+				if ( param->type ) SemanticError( param->location, string( "duplicate declaration name " ) + *param->name );
 				// declaration type reset => declaration already transformed by a parameter name so there is a duplicate
 				// parameter name attempting a second transformation
-				if ( ! decl->type ) throw SemanticError( param->location, string( "duplicate parameter name " ) + *param->name );
+				if ( ! decl->type ) SemanticError( param->location, string( "duplicate parameter name " ) + *param->name );
 				param->type = decl->type;				// set copy declaration type to parameter type
 				decl->type = nullptr;					// reset declaration type
@@ -929,5 +929,5 @@
 		} // for
 		// declaration type still set => type not moved to a matching parameter so there is a missing parameter name
-		if ( decl->type ) throw SemanticError( decl->location, string( "missing name in parameter list " ) + *decl->name );
+		if ( decl->type ) SemanticError( decl->location, string( "missing name in parameter list " ) + *decl->name );
 	} // for
 
Index: src/Parser/lex.ll
===================================================================
--- src/Parser/lex.ll	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/Parser/lex.ll	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -453,5 +453,5 @@
 void yyerror( const char * errmsg ) {
 	cout << (yyfilename ? yyfilename : "*unknown file*") << ':' << yylineno << ':' << column - yyleng + 1
-		 << ": " << SemanticError::error_str() << errmsg << " at token \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl;
+		 << ": " << ErrorHelpers::error_str() << errmsg << " at token \"" << (yytext[0] == '\0' ? "EOF" : yytext) << '"' << endl;
 }
 
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/Parser/parser.yy	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -482,9 +482,9 @@
 		{ $$ = new ExpressionNode( new StmtExpr( dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >($2) ) ) ); }
 	| type_name '.' no_attr_identifier					// CFA, nested type
-		{ throw SemanticError( yylloc, "Qualified names are currently unimplemented." ); $$ = nullptr; } // FIX ME
+		{ SemanticError( yylloc, "Qualified names are currently unimplemented." ); $$ = nullptr; } // FIX ME
 	| type_name '.' '[' push field_list pop ']'			// CFA, nested type / tuple field selector
-		{ throw SemanticError( yylloc, "Qualified names are currently unimplemented." ); $$ = nullptr; } // FIX ME
+		{ SemanticError( yylloc, "Qualified names are currently unimplemented." ); $$ = nullptr; } // FIX ME
 	| GENERIC '(' assignment_expression ',' generic_assoc_list ')' // C11
-		{ throw SemanticError( yylloc, "_Generic is currently unimplemented." ); $$ = nullptr; } // FIX ME
+		{ SemanticError( yylloc, "_Generic is currently unimplemented." ); $$ = nullptr; } // FIX ME
 	;
 
@@ -780,5 +780,5 @@
 		{ $$ = new ExpressionNode( build_binary_val( $2, $1, $3 ) ); }
 	| unary_expression '=' '{' initializer_list comma_opt '}'
-		{ throw SemanticError( yylloc, "Initializer assignment is currently unimplemented." ); $$ = nullptr; } // FIX ME
+		{ SemanticError( yylloc, "Initializer assignment is currently unimplemented." ); $$ = nullptr; } // FIX ME
 	;
 
@@ -850,5 +850,5 @@
 	| exception_statement
 	| enable_disable_statement
-		{ throw SemanticError( yylloc, "enable/disable statement is currently unimplemented." ); $$ = nullptr; } // FIX ME
+		{ SemanticError( yylloc, "enable/disable statement is currently unimplemented." ); $$ = nullptr; } // FIX ME
 	| asm_statement
 	;
@@ -1067,5 +1067,5 @@
 		{ $$ = new StatementNode( build_return( $2 ) ); }
 	| RETURN '{' initializer_list comma_opt '}'
-		{ throw SemanticError( yylloc, "Initializer return is currently unimplemented." ); $$ = nullptr; } // FIX ME
+		{ SemanticError( yylloc, "Initializer return is currently unimplemented." ); $$ = nullptr; } // FIX ME
 	| THROW assignment_expression_opt ';'				// handles rethrow
 		{ $$ = new StatementNode( build_throw( $2 ) ); }
@@ -1086,5 +1086,5 @@
 mutex_statement:
 	MUTEX '(' argument_expression_list ')' statement
-		{ throw SemanticError( yylloc, "Mutex statement is currently unimplemented." ); $$ = nullptr; } // FIX ME
+		{ SemanticError( yylloc, "Mutex statement is currently unimplemented." ); $$ = nullptr; } // FIX ME
 	;
 
@@ -1316,5 +1316,5 @@
 static_assert:
 	STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11
-		{ throw SemanticError( yylloc, "Static assert is currently unimplemented." ); $$ = nullptr; }	// FIX ME
+		{ SemanticError( yylloc, "Static assert is currently unimplemented." ); $$ = nullptr; }	// FIX ME
 
 // C declaration syntax is notoriously confusing and error prone. Cforall provides its own type, variable and function
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -240,5 +240,5 @@
 				std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
 			)
-			throw SemanticError( expr, "No reasonable alternatives for expression " );
+			SemanticError( expr, "No reasonable alternatives for expression " );
 		}
 		if ( prune ) {
@@ -258,5 +258,5 @@
 				stream << " Alternatives are:\n";
 				printAlts( winners, stream, 1 );
-				throw SemanticError( expr->location, stream.str() );
+				SemanticError( expr->location, stream.str() );
 			}
 			alternatives = move(pruned);
@@ -495,5 +495,5 @@
 				return;
 			} else if ( level >= recursionLimit ) {
-				throw SemanticError( newAlt.expr->location, "Too many recursive assertions" );
+				SemanticError( newAlt.expr->location, "Too many recursive assertions" );
 			} else {
 				AssertionSet newerNeed;
@@ -1112,5 +1112,5 @@
 
 		AltList candidates;
-		SemanticError errors;
+		SemanticErrorException errors;
 		for ( AltList::iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
 			try {
@@ -1138,5 +1138,5 @@
 					} // if
 				}
-			} catch ( SemanticError &e ) {
+			} catch ( SemanticErrorException &e ) {
 				errors.append( e );
 			}
@@ -1167,5 +1167,5 @@
 						}
 					}
-				} catch ( SemanticError &e ) {
+				} catch ( SemanticErrorException &e ) {
 					errors.append( e );
 				}
@@ -1409,5 +1409,5 @@
 			findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) );
 			if ( winners.size() != 1 ) {
-				throw SemanticError( sizeofExpr->get_expr(), "Ambiguous expression in sizeof operand: " );
+				SemanticError( sizeofExpr->get_expr(), "Ambiguous expression in sizeof operand: " );
 			} // if
 			// return the lowest cost alternative for the argument
@@ -1430,5 +1430,5 @@
 			findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) );
 			if ( winners.size() != 1 ) {
-				throw SemanticError( alignofExpr->get_expr(), "Ambiguous expression in alignof operand: " );
+				SemanticError( alignofExpr->get_expr(), "Ambiguous expression in alignof operand: " );
 			} // if
 			// return the lowest cost alternative for the argument
Index: src/ResolvExpr/CurrentObject.cc
===================================================================
--- src/ResolvExpr/CurrentObject.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/ResolvExpr/CurrentObject.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -141,5 +141,5 @@
 			base = at->get_base();
 			memberIter = createMemberIterator( base );
-			if ( at->isVarLen ) throw SemanticError( at, "VLA initialization does not support @=" );
+			if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=" );
 			setSize( at->get_dimension() );
 		}
@@ -155,6 +155,6 @@
 					size = constExpr->intValue();
 					PRINT( std::cerr << "array type with size: " << size << std::endl; )
-				} catch ( SemanticError & ) {
-					throw SemanticError( expr, "Constant expression of non-integral type in array dimension: " );
+				} catch ( SemanticErrorException & ) {
+					SemanticError( expr, "Constant expression of non-integral type in array dimension: " );
 				}
 			}	else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
@@ -178,6 +178,6 @@
 				try {
 					index = constExpr->intValue();
-				} catch( SemanticError & ) {
-					throw SemanticError( expr, "Constant expression of non-integral type in array designator: " );
+				} catch( SemanticErrorException & ) {
+					SemanticError( expr, "Constant expression of non-integral type in array designator: " );
 				}
 			} else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
@@ -532,7 +532,7 @@
 		} // for
 		if ( desigAlts.size() > 1 ) {
-			throw SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
+			SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
 		} else if ( desigAlts.size() == 0 ) {
-			throw SemanticError( designation, "No reasonable alternatives for designation: " );
+			SemanticError( designation, "No reasonable alternatives for designation: " );
 		}
 		DesignatorChain & d = desigAlts.back();
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/ResolvExpr/Resolver.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -174,5 +174,5 @@
 			findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
 			if ( winners.size() == 0 ) {
-				throw SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
+				SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
 			} else if ( winners.size() != 1 ) {
 				std::ostringstream stream;
@@ -181,5 +181,5 @@
 				stream << " Alternatives are:\n";
 				printAlts( winners, stream, 1 );
-				throw SemanticError( untyped->location, stream.str() );
+				SemanticError( untyped->location, stream.str() );
 			}
 
@@ -187,5 +187,5 @@
 			Alternative & choice = winners.front();
 			if ( findDeletedExpr( choice.expr ) ) {
-				throw SemanticError( choice.expr, "Unique best alternative includes deleted identifier in " );
+				SemanticError( choice.expr, "Unique best alternative includes deleted identifier in " );
 			}
 			alt = std::move( choice );
@@ -484,5 +484,5 @@
 				ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
 				ss << "' in call to waitfor";
-				throw SemanticError( stmt->location, ss.str() );
+				SemanticError( stmt->location, ss.str() );
 			}
 
@@ -501,15 +501,15 @@
 			// 	try matching the arguments to the parameters
 			// 	not the other way around because we have more arguments than parameters
-			SemanticError errors;
+			SemanticErrorException errors;
 			for ( Alternative & func : funcFinder.get_alternatives() ) {
 				try {
 					PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
 					if( !pointer ) {
-						throw SemanticError( func.expr->get_result(), "candidate not viable: not a pointer type\n" );
+						SemanticError( func.expr->get_result(), "candidate not viable: not a pointer type\n" );
 					}
 
 					FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
 					if( !function ) {
-						throw SemanticError( pointer->get_base(), "candidate not viable: not a function type\n" );
+						SemanticError( pointer->get_base(), "candidate not viable: not a function type\n" );
 					}
 
@@ -520,5 +520,5 @@
 
 						if( !advance_to_mutex( param, param_end ) ) {
-							throw SemanticError(function, "candidate function not viable: no mutex parameters\n");
+							SemanticError(function, "candidate function not viable: no mutex parameters\n");
 						}
 					}
@@ -559,5 +559,5 @@
 									// We ran out of parameters but still have arguments
 									// this function doesn't match
-									throw SemanticError( function, "candidate function not viable: too many mutex arguments\n" );
+									SemanticError( function, "candidate function not viable: too many mutex arguments\n" );
 								}
 
@@ -571,5 +571,5 @@
 									(*param)->get_type()->print( ss );
 									ss << "'\n";
-									throw SemanticError( function, ss.str() );
+									SemanticError( function, ss.str() );
 								}
 
@@ -583,5 +583,5 @@
 								// We ran out of arguments but still have parameters left
 								// this function doesn't match
-								throw SemanticError( function, "candidate function not viable: too few mutex arguments\n" );
+								SemanticError( function, "candidate function not viable: too few mutex arguments\n" );
 							}
 
@@ -599,10 +599,10 @@
 
 						}
-						catch( SemanticError &e ) {
+						catch( SemanticErrorException &e ) {
 							errors.append( e );
 						}
 					}
 				}
-				catch( SemanticError &e ) {
+				catch( SemanticErrorException &e ) {
 					errors.append( e );
 				}
@@ -610,8 +610,8 @@
 
 			// Make sure we got the right number of arguments
-			if( func_candidates.empty() )    { SemanticError top( stmt->location, "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
-			if( args_candidates.empty() )    { SemanticError top( stmt->location, "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
-			if( func_candidates.size() > 1 ) { SemanticError top( stmt->location, "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
-			if( args_candidates.size() > 1 ) { SemanticError top( stmt->location, "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
+			if( func_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
+			if( args_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
+			if( func_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
+			if( args_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
 			// TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
 
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/SymTab/Autogen.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -331,5 +331,5 @@
 			definitions.push_back( dcl );
 			indexer.addId( dcl );
-		} catch ( SemanticError err ) {
+		} catch ( SemanticErrorException err ) {
 			// okay if decl does not resolve - that means the function should not be generated
 			delete dcl;
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/SymTab/Indexer.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -443,10 +443,10 @@
 			// isomorphic to C type-compatibility, which it may not be.
 			if ( hasIncompatibleCDecl( name, mangleName, scope ) ) {
-				throw SemanticError( decl, "conflicting overload of C function " );
+				SemanticError( decl, "conflicting overload of C function " );
 			}
 		} else {
 			// Check that a Cforall declaration doesn't override any C declaration
 			if ( hasCompatibleCDecl( name, mangleName, scope ) ) {
-				throw SemanticError( decl, "Cforall declaration hides C function " );
+				SemanticError( decl, "Cforall declaration hides C function " );
 			}
 		}
@@ -463,10 +463,10 @@
 	void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) {
 		// default handling of conflicts is to raise an error
-		addId( decl, [decl](IdData &, const std::string & msg) { throw SemanticError( decl, msg ); return true; }, baseExpr );
+		addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, baseExpr );
 	}
 
 	void Indexer::addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt ) {
 		// default handling of conflicts is to raise an error
-		addId( decl, [decl](IdData &, const std::string & msg) { throw SemanticError( decl, msg ); return true; }, nullptr, deleteStmt );
+		addId( decl, [decl](IdData &, const std::string & msg) { SemanticError( decl, msg ); return true; }, nullptr, deleteStmt );
 	}
 
@@ -477,5 +477,5 @@
 			return true;
 		} else {
-			throw SemanticError( added, "redeclaration of " );
+			SemanticError( added, "redeclaration of " );
 		}
 	}
@@ -504,5 +504,5 @@
 			return false;
 		} else if ( ! added->get_members().empty() ) {
-			throw SemanticError( added, "redeclaration of " );
+			SemanticError( added, "redeclaration of " );
 		} // if
 		return true;
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/SymTab/Validate.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -360,5 +360,5 @@
 			// the only case in which "void" is valid is where it is the only one in the list
 			if ( containsVoid && ( nvals > 1 || isVarArgs ) ) {
-				throw SemanticError( func, "invalid type void in function type " );
+				SemanticError( func, "invalid type void in function type " );
 			}
 
@@ -401,5 +401,5 @@
 		for ( Expression * param : inst->parameters ) {
 			if ( ! dynamic_cast< TypeExpr * >( param ) ) {
-				throw SemanticError( inst, "Expression parameters for generic types are currently unsupported: " );
+				SemanticError( inst, "Expression parameters for generic types are currently unsupported: " );
 			}
 		}
@@ -501,8 +501,8 @@
 		TraitDecl *traitDecl = local_indexer->lookupTrait( traitInst->name );
 		if ( ! traitDecl ) {
-			throw SemanticError( traitInst->location, "use of undeclared trait " + traitInst->name );
+			SemanticError( traitInst->location, "use of undeclared trait " + traitInst->name );
 		} // if
 		if ( traitDecl->get_parameters().size() != traitInst->get_parameters().size() ) {
-			throw SemanticError( traitInst, "incorrect number of trait parameters: " );
+			SemanticError( traitInst, "incorrect number of trait parameters: " );
 		} // if
 		traitInst->baseTrait = traitDecl;
@@ -512,5 +512,5 @@
 			TypeExpr * expr = dynamic_cast< TypeExpr * >( std::get<1>(p) );
 			if ( ! expr ) {
-				throw SemanticError( std::get<1>(p), "Expression parameters for trait instances are currently unsupported: " );
+				SemanticError( std::get<1>(p), "Expression parameters for trait instances are currently unsupported: " );
 			}
 			if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( expr->get_type() ) ) {
@@ -618,5 +618,5 @@
 				bool isVoid = fixFunction( assertion );
 				if ( isVoid ) {
-					throw SemanticError( node, "invalid type void in assertion of function " );
+					SemanticError( node, "invalid type void in assertion of function " );
 				} // if
 			} // for
@@ -662,5 +662,5 @@
 		// were cast to void.
 		if ( ! returnStmt->get_expr() && returnVals.size() != 0 ) {
-			throw SemanticError( returnStmt, "Non-void function returns no values: " );
+			SemanticError( returnStmt, "Non-void function returns no values: " );
 		}
 	}
@@ -703,5 +703,5 @@
 				ReferenceToType *rtt = dynamic_cast<ReferenceToType*>(ret);
 				if ( ! rtt ) {
-					throw SemanticError( typeInst->location, "Cannot apply type parameters to base type of " + typeInst->name );
+					SemanticError( typeInst->location, "Cannot apply type parameters to base type of " + typeInst->name );
 				}
 				rtt->get_parameters().clear();
@@ -741,5 +741,5 @@
 			Type * t2 = typedefNames[ tyDecl->get_name() ].first->get_base();
 			if ( ! ResolvExpr::typesCompatible( t1, t2, Indexer() ) ) {
-				throw SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name );
+				SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name );
 			}
 			// Cannot redefine VLA typedefs. Note: this is slightly incorrect, because our notion of VLAs
@@ -748,5 +748,5 @@
 			// to fix this corner case likely outweighs the utility of allowing it.
 			if ( isVariableLength( t1 ) || isVariableLength( t2 ) ) {
-				throw SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name );
+				SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name );
 			}
 		} else {
@@ -897,12 +897,12 @@
 		if ( CodeGen::isCtorDtorAssign( funcDecl->get_name() ) ) { // TODO: also check /=, etc.
 			if ( params.size() == 0 ) {
-				throw SemanticError( funcDecl, "Constructors, destructors, and assignment functions require at least one parameter " );
+				SemanticError( funcDecl, "Constructors, destructors, and assignment functions require at least one parameter " );
 			}
 			ReferenceType * refType = dynamic_cast< ReferenceType * >( params.front()->get_type() );
 			if ( ! refType ) {
-				throw SemanticError( funcDecl, "First parameter of a constructor, destructor, or assignment function must be a reference " );
+				SemanticError( funcDecl, "First parameter of a constructor, destructor, or assignment function must be a reference " );
 			}
 			if ( CodeGen::isCtorDtor( funcDecl->get_name() ) && returnVals.size() != 0 ) {
-				throw SemanticError( funcDecl, "Constructors and destructors cannot have explicit return values " );
+				SemanticError( funcDecl, "Constructors and destructors cannot have explicit return values " );
 			}
 		}
@@ -939,6 +939,6 @@
 
 			sub.apply( inst );
-			if ( args.size() < params->size() ) throw SemanticError( inst, "Too few type arguments in generic type " );
-			if ( args.size() > params->size() ) throw SemanticError( inst, "Too many type arguments in generic type " );
+			if ( args.size() < params->size() ) SemanticError( inst, "Too few type arguments in generic type " );
+			if ( args.size() > params->size() ) SemanticError( inst, "Too many type arguments in generic type " );
 		}
 	}
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/SynTree/Expression.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -93,5 +93,5 @@
 		return 0;
 	}
-	throw SemanticError( this, "Constant expression of non-integral type " );
+	SemanticError( this, "Constant expression of non-integral type " );
 }
 
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/SynTree/Mutator.h	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -136,5 +136,5 @@
 template< typename Container, typename MutatorType >
 inline void mutateAll( Container &container, MutatorType &mutator ) {
-	SemanticError errors;
+	SemanticErrorException errors;
 	for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
 		try {
@@ -144,5 +144,5 @@
 				assert( *i );
 			} // if
-		} catch( SemanticError &e ) {
+		} catch( SemanticErrorException &e ) {
 			errors.append( e );
 		} // try
Index: src/SynTree/Statement.cc
===================================================================
--- src/SynTree/Statement.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/SynTree/Statement.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -96,16 +96,16 @@
 const char *BranchStmt::brType[] = { "Goto", "Break", "Continue" };
 
-BranchStmt::BranchStmt( Label target, Type type ) throw ( SemanticError ) :
+BranchStmt::BranchStmt( Label target, Type type ) throw ( SemanticErrorException ) :
 	Statement(), originalTarget( target ), target( target ), computedTarget( nullptr ), type( type ) {
 	//actually this is a syntactic error signaled by the parser
 	if ( type == BranchStmt::Goto && target.empty() ) {
-		throw SemanticError( target.get_statement()->location, "goto without target");
-	}
-}
-
-BranchStmt::BranchStmt( Expression *computedTarget, Type type ) throw ( SemanticError ) :
+		SemanticError( target.get_statement()->location, "goto without target");
+	}
+}
+
+BranchStmt::BranchStmt( Expression *computedTarget, Type type ) throw ( SemanticErrorException ) :
 	Statement(), computedTarget( computedTarget ), type( type ) {
 	if ( type != BranchStmt::Goto || computedTarget == nullptr ) {
-		throw SemanticError( computedTarget->location, "Computed target not valid in branch statement");
+		SemanticError( computedTarget->location, "Computed target not valid in branch statement");
 	}
 }
@@ -201,7 +201,7 @@
 }
 
-CaseStmt::CaseStmt( Expression *condition, const std::list<Statement *> &statements, bool deflt ) throw ( SemanticError ) :
+CaseStmt::CaseStmt( Expression *condition, const std::list<Statement *> &statements, bool deflt ) throw ( SemanticErrorException ) :
 	Statement(), condition( condition ), stmts( statements ), _isDefault( deflt ) {
-	if ( isDefault() && condition != 0 ) throw SemanticError( condition, "default case with condition: " );
+	if ( isDefault() && condition != 0 ) SemanticError( condition, "default case with condition: " );
 }
 
Index: src/SynTree/Statement.h
===================================================================
--- src/SynTree/Statement.h	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/SynTree/Statement.h	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -179,5 +179,5 @@
 	std::list<Statement *> stmts;
 
-	CaseStmt( Expression *conditions, const std::list<Statement *> &stmts, bool isdef = false ) throw(SemanticError);
+	CaseStmt( Expression *conditions, const std::list<Statement *> &stmts, bool isdef = false ) throw (SemanticErrorException);
 	CaseStmt( const CaseStmt &other );
 	virtual ~CaseStmt();
@@ -263,6 +263,6 @@
 	Type type;
 
-	BranchStmt( Label target, Type ) throw (SemanticError);
-	BranchStmt( Expression *computedTarget, Type ) throw (SemanticError);
+	BranchStmt( Label target, Type ) throw (SemanticErrorException);
+	BranchStmt( Expression *computedTarget, Type ) throw (SemanticErrorException);
 
 	Label get_originalTarget() { return originalTarget; }
Index: src/SynTree/TypeSubstitution.h
===================================================================
--- src/SynTree/TypeSubstitution.h	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/SynTree/TypeSubstitution.h	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -98,5 +98,5 @@
 				} // if
 			} else {
-				throw SemanticError( formal, toString( "Attempt to provide non-type parameter: ", toString( *actualIt ).c_str(), " for type parameter " ) );
+				SemanticError( formal, toString( "Attempt to provide non-type parameter: ", toString( *actualIt ).c_str(), " for type parameter " ) );
 			} // if
 		} else {
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/SynTree/Visitor.h	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -132,5 +132,5 @@
 template< typename Container, typename VisitorType >
 inline void acceptAll( Container &container, VisitorType &visitor ) {
-	SemanticError errors;
+	SemanticErrorException errors;
 	for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
 		try {
@@ -138,5 +138,5 @@
 				(*i)->accept( visitor );
 			}
-		} catch( SemanticError &e ) {
+		} catch( SemanticErrorException &e ) {
 			errors.append( e );
 		}
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 6a8df56b96e7e40ef5c0d1153e55003dad3b57f1)
+++ src/main.cc	(revision a16764a6fbfe44300fc8834400a31c89befda091)
@@ -357,5 +357,5 @@
 			delete output;
 		} // if
-	} catch ( SemanticError &e ) {
+	} catch ( SemanticErrorException &e ) {
 		if ( errorp ) {
 			cerr << "---AST at error:---" << endl;
