Index: src/CodeGen/FixMain.cc
===================================================================
--- src/CodeGen/FixMain.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/CodeGen/FixMain.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -39,5 +39,5 @@
 	{
 		if(main_signature) {
-			throw SemanticError("Multiple definition of main routine\n", functionDecl);
+			throw SemanticError(functionDecl, "Multiple definition of main routine\n");
 		}
 		main_signature.reset( functionDecl->clone() );
Index: src/CodeGen/FixNames.cc
===================================================================
--- src/CodeGen/FixNames.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/CodeGen/FixNames.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -118,5 +118,5 @@
 			int nargs = functionDecl->get_functionType()->get_parameters().size();
 			if( !(nargs == 0 || nargs == 2 || nargs == 3) ) {
-				throw SemanticError("Main expected to have 0, 2 or 3 arguments\n", functionDecl);
+				throw 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/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/Common/PassVisitor.impl.h	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -77,5 +77,4 @@
 			maybeAccept_impl( *i, visitor );
 		} catch( SemanticError &e ) {
-			e.set_location( (*i)->location );
 			errors.append( e );
 		}
@@ -104,5 +103,4 @@
 			maybeMutate_impl( *i, mutator );
 		} catch( SemanticError &e ) {
-			e.set_location( (*i)->location );
 			errors.append( e );
 		}
@@ -134,5 +132,4 @@
 			}
 		} catch( SemanticError &e ) {
-			e.set_location( (*i)->location );
 			errors.append( e );
 		}
@@ -163,5 +160,4 @@
 			} // if
 		} catch( SemanticError &e ) {
-			e.set_location( (*i)->location );
 			errors.append( e );
 		} // try
@@ -200,5 +196,4 @@
 
 		} catch ( SemanticError &e ) {
-			e.set_location( (*i)->location );
 			errors.append( e );
 		}
Index: src/Common/SemanticError.cc
===================================================================
--- src/Common/SemanticError.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/Common/SemanticError.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -23,9 +23,6 @@
 #include "SemanticError.h"
 
-SemanticError::SemanticError() {
-}
-
-SemanticError::SemanticError( std::string error ) {
-	append( error );
+SemanticError::SemanticError( CodeLocation location, std::string error ) {
+	append( location, error );
 }
 
@@ -34,6 +31,6 @@
 }
 
-void SemanticError::append( const std::string & msg ) {
-	errors.emplace_back( error_str() + msg );
+void SemanticError::append( CodeLocation location, const std::string & msg ) {
+	errors.emplace_back( location, msg );
 }
 
@@ -42,13 +39,13 @@
 }
 
-void SemanticError::print( std::ostream &os ) {
+void SemanticError::print() {
 	using std::to_string;
 	for( auto err : errors ) {
-		os << err.location << err.description << std::endl;
+		std::cerr << bold() << err.location << error_str() << reset_font() << err.description << std::endl;
 	}
 }
 
-void SemanticError::set_location( const CodeLocation& location ) {
-	errors.begin()->maybeSet( location );
+SemanticWarning::SemanticWarning( CodeLocation location, std::string msg ) {
+	std::cerr << bold() << location << warning_str() << reset_font() << msg << std::endl;
 }
 
Index: src/Common/SemanticError.h
===================================================================
--- src/Common/SemanticError.h	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/Common/SemanticError.h	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -24,24 +24,23 @@
 #include "CodeLocation.h"								// for CodeLocation, toString
 
+//-----------------------------------------------------------------------------
+// Errors
 struct error {
+	CodeLocation location;
 	std::string description;
-	CodeLocation location;
 
 	error() = default;
-	error( const std::string & str ) : description( str ) {}
-
-	void maybeSet( const CodeLocation & location ) {
-		if( this->location.isUnset() ) {
-			this->location = location;
-		}
-	}
+	error( CodeLocation loc, const std::string & str ) : location( loc ), description( str ) {}
 };
 
 class SemanticError : public std::exception {
   public:
-	SemanticError();
-	SemanticError( std::string error );
-	template< typename T > SemanticError( const std::string & error, const T * obj );
+  	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() {
@@ -51,11 +50,7 @@
 
 	void append( SemanticError & other );
-	void append( const std::string & );
+	void append( CodeLocation location, const std::string & );
 	bool isEmpty() const;
-	void print( std::ostream & os );
-
-	void set_location( const CodeLocation & location );
-	// constructs an exception using the given message and the printed representation of the obj (T must have a print
-	// method)
+	void print();
   private:
 	std::list< error > errors;
@@ -63,6 +58,68 @@
 
 template< typename T >
-SemanticError::SemanticError( const std::string & error, const T * obj ) {
-	append( toString( error, obj ) );
+SemanticError::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 ) )
+{}
+
+//-----------------------------------------------------------------------------
+// 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);
+
+	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 ) )
+{}
+
+template< typename T >
+SemanticWarning::SemanticWarning( CodeLocation location, const T * obj, const std::string & error )
+	: SemanticWarning( location, toString( error, obj ) )
+{}
+
+//-----------------------------------------------------------------------------
+// Helpers
+static inline const std::string & bold_ttycode() {
+	static std::string str = isatty( STDERR_FILENO ) ? "\e[1m" : "";
+	return str;
+}
+
+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;
 }
 
Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/Concurrency/Keywords.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -276,5 +276,4 @@
 			handle( decl );
 		}
-
 	}
 
@@ -282,5 +281,5 @@
 		if( ! decl->body ) return;
 
-		if( !type_decl ) throw SemanticError( context_error, decl );
+		if( !type_decl ) throw SemanticError( decl, context_error );
 
 		FunctionDecl * func = forwardDeclare( decl );
@@ -419,9 +418,9 @@
 		if( mutexArgs.empty() ) return;
 
-		if( CodeGen::isConstructor(decl->name) ) throw SemanticError( "constructors cannot have mutex parameters", decl );
+		if( CodeGen::isConstructor(decl->name) ) throw SemanticError( decl, "constructors cannot have mutex parameters" );
 
 		bool isDtor = CodeGen::isDestructor( decl->name );
 
-		if( isDtor && mutexArgs.size() != 1 ) throw SemanticError( "destructors can only have 1 mutex argument", decl );
+		if( isDtor && mutexArgs.size() != 1 ) throw SemanticError( decl, "destructors can only have 1 mutex argument" );
 
 		for(auto arg : mutexArgs) {
@@ -432,7 +431,7 @@
 		if( ! body ) return;
 
-		if( !monitor_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
-		if( !guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
-		if( !dtor_guard_decl ) throw SemanticError( "mutex keyword requires monitors to be in scope, add #include <monitor>", decl );
+		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( isDtor ) {
@@ -480,13 +479,13 @@
 		//Makes sure it's not a copy
 		ReferenceType* rty = dynamic_cast< ReferenceType * >( ty );
-		if( ! rty ) throw SemanticError( "Mutex argument must be of reference type ", arg );
+		if( ! rty ) throw 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( "Mutex argument have exactly one level of indirection ", arg );
-		if( dynamic_cast< PointerType * >( base ) ) throw SemanticError( "Mutex argument have exactly one level of indirection ", arg );
+		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 " );
 
 		//Make sure that typed isn't mutex
-		if( base->get_mutex() ) throw SemanticError( "mutex keyword may only appear once per argument ", arg );
+		if( base->get_mutex() ) throw SemanticError( arg, "mutex keyword may only appear once per argument " );
 	}
 
@@ -626,5 +625,5 @@
 		if( type && type->get_baseStruct()->is_thread() ) {
 			if( !thread_decl || !thread_ctor_seen ) {
-				throw SemanticError("thread keyword requires threads to be in scope, add #include <thread>");
+				throw 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 d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/Concurrency/Waitfor.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -249,5 +249,6 @@
 
 	Statement * GenerateWaitForPass::postmutate( WaitForStmt * waitfor ) {
-		if( !decl_monitor || !decl_acceptable || !decl_mask ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor );
+		if( !decl_monitor || !decl_acceptable || !decl_mask )
+			throw 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 d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/ControlStruct/ExceptTranslate.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -572,7 +572,7 @@
 			// Pass.
 		} else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
-			throw SemanticError("catch must have exception type");
+			throw SemanticError(catchStmt->location, "catch must have exception type");
 		} else {
-			throw SemanticError("catchResume must have exception type");
+			throw SemanticError(catchStmt->location, "catchResume must have exception type");
 		}
 
Index: src/ControlStruct/LabelFixer.cc
===================================================================
--- src/ControlStruct/LabelFixer.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/ControlStruct/LabelFixer.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -92,5 +92,5 @@
 			} else if ( labelTable[ l ]->defined() ) {
 				// defined twice, error
-				throw SemanticError( "Duplicate definition of label: " + l.get_name() );
+				throw SemanticError( l.get_statement()->location, "Duplicate definition of label: " + l.get_name() );
 			}	else {
 				// used previously, but undefined until now -> link with this entry
@@ -121,5 +121,5 @@
 		for ( std::map< Label, Entry * >::iterator i = labelTable.begin(); i != labelTable.end(); ++i ) {
 			if ( ! i->second->defined() ) {
-				throw SemanticError( "Use of undefined label: " + i->first.get_name() );
+				throw SemanticError( i->first.get_statement()->location, "Use of undefined label: " + i->first.get_name() );
 			}
 			(*ret)[ i->first ] = i->second->get_definition();
Index: src/ControlStruct/MLEMutator.cc
===================================================================
--- src/ControlStruct/MLEMutator.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/ControlStruct/MLEMutator.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -115,5 +115,5 @@
 					} else {
 						// break target is outmost control structure
-						if ( enclosingControlStructures.empty() ) throw SemanticError( "'break' outside a loop, switch, or labelled block" );
+						if ( enclosingControlStructures.empty() ) throw 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( toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) );
+					throw SemanticError( branchStmt->location, toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) );
 				} // if
 				break;
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/GenPoly/Box.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -229,5 +229,4 @@
 				} // if
 			} catch( SemanticError &e ) {
-				e.set_location( (*i)->location );
 				errors.append( e );
 			} // try
@@ -576,5 +575,5 @@
 						}
 					} else {
-						throw SemanticError( "Cannot pass non-struct type for generic struct: ", argBaseType );
+						throw SemanticError( argBaseType, "Cannot pass non-struct type for generic struct: " );
 					}
 				}
@@ -598,5 +597,5 @@
 					} else {
 						// xxx - should this be an assertion?
-						throw SemanticError( toString( *env, "\nunbound type variable: ", tyParm->first, " in application " ), appExpr );
+						throw SemanticError( appExpr, toString( *env, "\nunbound type variable: ", tyParm->first, " in application " ) );
 					} // if
 				} // if
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/InitTweak/FixInit.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -282,5 +282,4 @@
 					translationUnit.splice( i, fixer.pass.staticDtorDecls );
 				} catch( SemanticError &e ) {
-					e.set_location( (*i)->location );
 					errors.append( e );
 				} // try
@@ -895,5 +894,5 @@
 			)
 			if ( ! diff.empty() ) {
-				throw SemanticError( std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " ", stmt );
+				throw 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
@@ -1111,6 +1110,5 @@
 		template< typename Visitor, typename... Params >
 		void error( Visitor & v, CodeLocation loc, const Params &... params ) {
-			SemanticError err( toString( params... ) );
-			err.set_location( loc );
+			SemanticError err( loc, toString( params... ) );
 			v.errors.append( err );
 		}
Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/InitTweak/GenInit.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -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( "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n", objDecl );
+			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" );
 			// constructed objects should not have initializers nested too deeply
-			if ( ! checkInitDepth( objDecl ) ) throw SemanticError( "Managed object's initializer is too deep ", objDecl );
+			if ( ! checkInitDepth( objDecl ) ) throw SemanticError( objDecl, "Managed object's initializer is too deep " );
 
 			objDecl->set_init( genCtorInit( objDecl ) );
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/InitTweak/InitTweak.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -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( "unbalanced list initializers" );
+					throw SemanticError( init->location, "unbalanced list initializers" );
 				}
 
Index: src/Parser/DeclarationNode.cc
===================================================================
--- src/Parser/DeclarationNode.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/Parser/DeclarationNode.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -581,15 +581,15 @@
 					dst->basictype = src->basictype;
 				} else if ( src->basictype != DeclarationNode::NoBasicType )
-					throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::basicTypeNames[ src->basictype ] + " in type: ", src );
+					throw 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( string( "conflicting type specifier " ) + DeclarationNode::complexTypeNames[ src->complextype ] + " in type: ", src );
+					throw 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( string( "conflicting type specifier " ) + DeclarationNode::signednessNames[ src->signedness ] + " in type: ", src );
+					throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::signednessNames[ src->signedness ] + " in type: " );
 
 				if ( dst->length == DeclarationNode::NoLength ) {
@@ -598,5 +598,5 @@
 					dst->length = DeclarationNode::LongLong;
 				} else if ( src->length != DeclarationNode::NoLength )
-					throw SemanticError( string( "conflicting type specifier " ) + DeclarationNode::lengthNames[ src->length ] + " in type: ", src );
+					throw SemanticError( yylloc, src, string( "conflicting type specifier " ) + DeclarationNode::lengthNames[ src->length ] + " in type: " );
 			} // if
 			break;
@@ -966,5 +966,4 @@
 			} // if
 		} catch( SemanticError &e ) {
-			e.set_location( cur->location );
 			errors.append( e );
 		} // try
@@ -1001,5 +1000,4 @@
 			} // if
 		} catch( SemanticError &e ) {
-			e.set_location( cur->location );
 			errors.append( e );
 		} // try
@@ -1020,5 +1018,4 @@
 			* out++ = cur->buildType();
 		} catch( SemanticError &e ) {
-			e.set_location( cur->location );
 			errors.append( e );
 		} // try
@@ -1032,5 +1029,5 @@
 
 Declaration * DeclarationNode::build() const {
-	if ( ! error.empty() ) throw SemanticError( error + " in declaration of ", this );
+	if ( ! error.empty() ) throw SemanticError( this, error + " in declaration of " );
 
 	if ( asmStmt ) {
@@ -1055,5 +1052,5 @@
 		//    inline _Noreturn int i;			// disallowed
 		if ( type->kind != TypeData::Function && funcSpecs.any() ) {
-			throw SemanticError( "invalid function specifier for ", this );
+			throw 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 );
@@ -1065,5 +1062,5 @@
 	//    inlne _Noreturn enum   E { ... };		// disallowed
 	if ( funcSpecs.any() ) {
-		throw SemanticError( "invalid function specifier for ", this );
+		throw 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 d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/Parser/ExpressionNode.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -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( "invalid tuple index " + str );
+	if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) throw 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( "invalid tuple index " + str );
+	if ( str[str.size()-1] != '.' ) throw 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 d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/Parser/LinkageSpec.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -24,5 +24,5 @@
 namespace LinkageSpec {
 
-Spec linkageCheck( const string * spec ) {
+Spec linkageCheck( CodeLocation location, const string * spec ) {
 	assert( spec );
 	unique_ptr<const string> guard( spec );	// allocated by lexer
@@ -34,9 +34,9 @@
 		return BuiltinC;
 	} else {
-		throw SemanticError( "Invalid linkage specifier " + *spec );
+		throw SemanticError( location, "Invalid linkage specifier " + *spec );
 	} // if
 }
 
-Spec linkageUpdate( Spec old_spec, const string * cmd ) {
+Spec linkageUpdate( CodeLocation location, Spec old_spec, const string * cmd ) {
 	assert( cmd );
 	unique_ptr<const string> guard( cmd ); // allocated by lexer
@@ -48,5 +48,5 @@
 		return old_spec;
 	} else {
-		throw SemanticError( "Invalid linkage specifier " + *cmd );
+		throw SemanticError( location, "Invalid linkage specifier " + *cmd );
 	} // if
 }
Index: src/Parser/LinkageSpec.h
===================================================================
--- src/Parser/LinkageSpec.h	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/Parser/LinkageSpec.h	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -17,4 +17,6 @@
 
 #include <string>
+
+#include "Common/CodeLocation.h"
 
 namespace LinkageSpec {
@@ -45,7 +47,7 @@
 
 
-	Spec linkageCheck( const std::string * );
+	Spec linkageCheck( CodeLocation location, const std::string * );
 	// Returns the Spec with the given name (limited to C, Cforall & BuiltinC)
-	Spec linkageUpdate( Spec old_spec, const std::string * cmd );
+	Spec linkageUpdate( CodeLocation location, Spec old_spec, const std::string * cmd );
 	/* If cmd = "C" returns a Spec that is old_spec with is_mangled = false
 	 * If cmd = "Cforall" returns old_spec Spec with is_mangled = true
Index: src/Parser/ParseNode.h
===================================================================
--- src/Parser/ParseNode.h	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/Parser/ParseNode.h	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -434,5 +434,4 @@
 			} // if
 		} catch( SemanticError &e ) {
-			e.set_location( cur->location );
 			errors.append( e );
 		} // try
Index: src/Parser/TypeData.cc
===================================================================
--- src/Parser/TypeData.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/Parser/TypeData.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -521,5 +521,5 @@
 
 static string genTSError( string msg, DeclarationNode::BasicType basictype ) {
-	throw SemanticError( string( "invalid type specifier \"" ) + msg + "\" for type \"" + DeclarationNode::basicTypeNames[basictype] + "\"." );
+	throw SemanticError( yylloc, string( "invalid type specifier \"" ) + msg + "\" for type \"" + DeclarationNode::basicTypeNames[basictype] + "\"." );
 } // genTSError
 
@@ -923,8 +923,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( string( "duplicate declaration name " ) + *param->name );
+				if ( param->type ) throw 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( string( "duplicate parameter name " ) + *param->name );
+				if ( ! decl->type ) throw 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
@@ -933,5 +933,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( string( "missing name in parameter list " ) + *decl->name );
+		if ( decl->type ) throw SemanticError( decl->location, string( "missing name in parameter list " ) + *decl->name );
 	} // for
 
Index: src/Parser/parser.yy
===================================================================
--- src/Parser/parser.yy	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/Parser/parser.yy	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -482,7 +482,7 @@
 		{ $$ = new ExpressionNode( new StmtExpr( dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >($2) ) ) ); }
 	| type_name '.' no_attr_identifier					// CFA, nested type
-		{ throw SemanticError("Qualified names are currently unimplemented."); $$ = nullptr; } // FIX ME
+		{ throw SemanticError(yylloc, "Qualified names are currently unimplemented."); $$ = nullptr; } // FIX ME
 	| type_name '.' '[' push field_list pop ']'			// CFA, nested type / tuple field selector
-		{ throw SemanticError("Qualified names are currently unimplemented."); $$ = nullptr; } // FIX ME
+		{ throw SemanticError(yylloc, "Qualified names are currently unimplemented."); $$ = nullptr; } // FIX ME
 	;
 
@@ -1072,5 +1072,5 @@
 mutex_statement:
 	MUTEX '(' argument_expression_list ')' statement
-		{ throw SemanticError("Mutex statement is currently unimplemented."); $$ = nullptr; } // FIX ME
+		{ throw SemanticError(yylloc, "Mutex statement is currently unimplemented."); $$ = nullptr; } // FIX ME
 	;
 
@@ -1293,5 +1293,5 @@
 static_assert:
 	STATICASSERT '(' constant_expression ',' string_literal ')' ';' // C11
-		{ throw SemanticError("Static assert is currently unimplemented."); $$ = nullptr; }	// FIX ME
+		{ throw 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
@@ -2381,5 +2381,5 @@
 		{
 			linkageStack.push( linkage );				// handle nested extern "C"/"Cforall"
-			linkage = LinkageSpec::linkageUpdate( linkage, $2 );
+			linkage = LinkageSpec::linkageUpdate( yylloc, linkage, $2 );
 		}
 	  '{' external_definition_list_opt '}'
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -252,5 +252,5 @@
 				std::cerr << "No reasonable alternatives for expression " << expr << std::endl;
 			)
-			throw SemanticError( "No reasonable alternatives for expression ", expr );
+			throw SemanticError( expr, "No reasonable alternatives for expression " );
 		}
 		if ( prune ) {
@@ -270,5 +270,5 @@
 				stream << "Alternatives are:\n";
 				printAlts( winners, stream, 1 );
-				throw SemanticError( stream.str() );
+				throw SemanticError( expr->location, stream.str() );
 			}
 			alternatives = move(pruned);
@@ -507,5 +507,5 @@
 				return;
 			} else if ( level >= recursionLimit ) {
-				throw SemanticError( "Too many recursive assertions" );
+				throw SemanticError( newAlt.expr->location, "Too many recursive assertions" );
 			} else {
 				AssertionSet newerNeed;
@@ -1421,5 +1421,5 @@
 			findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) );
 			if ( winners.size() != 1 ) {
-				throw SemanticError( "Ambiguous expression in sizeof operand: ", sizeofExpr->get_expr() );
+				throw SemanticError( sizeofExpr->get_expr(), "Ambiguous expression in sizeof operand: " );
 			} // if
 			// return the lowest cost alternative for the argument
@@ -1442,5 +1442,5 @@
 			findMinCost( finder.alternatives.begin(), finder.alternatives.end(), back_inserter( winners ) );
 			if ( winners.size() != 1 ) {
-				throw SemanticError( "Ambiguous expression in alignof operand: ", alignofExpr->get_expr() );
+				throw 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 d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/ResolvExpr/CurrentObject.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -141,5 +141,5 @@
 			base = at->get_base();
 			memberIter = createMemberIterator( base );
-			if ( at->isVarLen ) throw SemanticError( "VLA initialization does not support @=", at );
+			if ( at->isVarLen ) throw SemanticError( at, "VLA initialization does not support @=" );
 			setSize( at->get_dimension() );
 		}
@@ -156,5 +156,5 @@
 					PRINT( std::cerr << "array type with size: " << size << std::endl; )
 				} catch ( SemanticError & ) {
-					throw SemanticError( "Constant expression of non-integral type in array dimension: ", expr );
+					throw SemanticError( expr, "Constant expression of non-integral type in array dimension: " );
 				}
 			}	else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
@@ -179,5 +179,5 @@
 					index = constExpr->intValue();
 				} catch( SemanticError & ) {
-					throw SemanticError( "Constant expression of non-integral type in array designator: ", expr );
+					throw 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( toString("Too many alternatives (", desigAlts.size(), ") for designation: "), designation );
+			throw SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
 		} else if ( desigAlts.size() == 0 ) {
-			throw SemanticError( "No reasonable alternatives for designation: ", designation );
+			throw SemanticError( designation, "No reasonable alternatives for designation: " );
 		}
 		DesignatorChain & d = desigAlts.back();
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/ResolvExpr/Resolver.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -188,5 +188,5 @@
 			findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) );
 			if ( winners.size() == 0 ) {
-				throw SemanticError( "No reasonable alternatives for " + kindStr + " expression: ", untyped );
+				throw SemanticError( untyped, "No reasonable alternatives for " + kindStr + " expression: " );
 			} else if ( winners.size() != 1 ) {
 				std::ostringstream stream;
@@ -195,5 +195,5 @@
 				stream << "Alternatives are:\n";
 				printAlts( winners, stream, 1 );
-				throw SemanticError( stream.str() );
+				throw SemanticError( untyped->location, stream.str() );
 			}
 
@@ -429,5 +429,5 @@
 				ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
 				ss << "' in call to waitfor";
-				throw SemanticError( ss.str() );
+				throw SemanticError( stmt->location, ss.str() );
 			}
 
@@ -451,10 +451,10 @@
 					PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
 					if( !pointer ) {
-						throw SemanticError( "candidate not viable: not a pointer type\n", func.expr->get_result() );
+						throw 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( "candidate not viable: not a function type\n", pointer->get_base() );
+						throw SemanticError( pointer->get_base(), "candidate not viable: not a function type\n" );
 					}
 
@@ -465,5 +465,5 @@
 
 						if( !advance_to_mutex( param, param_end ) ) {
-							throw SemanticError("candidate function not viable: no mutex parameters\n", function);
+							throw SemanticError(function, "candidate function not viable: no mutex parameters\n");
 						}
 					}
@@ -504,5 +504,5 @@
 									// We ran out of parameters but still have arguments
 									// this function doesn't match
-									throw SemanticError("candidate function not viable: too many mutex arguments\n", function);
+									throw SemanticError( function, "candidate function not viable: too many mutex arguments\n" );
 								}
 
@@ -516,5 +516,5 @@
 									(*param)->get_type()->print( ss );
 									ss << "'\n";
-									throw SemanticError(ss.str(), function);
+									throw SemanticError( function, ss.str() );
 								}
 
@@ -528,5 +528,5 @@
 								// We ran out of arguments but still have parameters left
 								// this function doesn't match
-								throw SemanticError("candidate function not viable: too few mutex arguments\n", function);
+								throw SemanticError( function, "candidate function not viable: too few mutex arguments\n" );
 							}
 
@@ -555,8 +555,8 @@
 
 			// Make sure we got the right number of arguments
-			if( func_candidates.empty() )    { SemanticError top( "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
-			if( args_candidates.empty() )    { SemanticError top( "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
-			if( func_candidates.size() > 1 ) { SemanticError top( "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
-			if( args_candidates.size() > 1 ) { SemanticError top( "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
+			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; }
 
 
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/SymTab/Indexer.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -388,5 +388,5 @@
 			if ( newentry && oldentry ) {
 				if ( newentry->get_statements() && oldentry->get_statements() ) {
-					throw SemanticError( "duplicate function definition for ", added );
+					throw SemanticError( added, "duplicate function definition for " );
 				} // if
 			} else {
@@ -398,9 +398,9 @@
 				ObjectDecl *oldobj = dynamic_cast< ObjectDecl* >( existing );
 				if ( ! newobj->get_storageClasses().is_extern && ! oldobj->get_storageClasses().is_extern ) {
-					throw SemanticError( "duplicate object definition for ", added );
+					throw SemanticError( added, "duplicate object definition for " );
 				} // if
 			} // if
 		} else {
-			throw SemanticError( "duplicate definition for ", added );
+			throw SemanticError( added, "duplicate definition for " );
 		} // if
 
@@ -431,10 +431,10 @@
 			// isomorphic to C type-compatibility, which it may not be.
 			if ( hasIncompatibleCDecl( name, mangleName, scope ) ) {
-				throw SemanticError( "conflicting overload of C function ", decl );
+				throw SemanticError( decl, "conflicting overload of C function " );
 			}
 		} else {
 			// Check that a Cforall declaration doesn't overload any C declaration
 			if ( hasCompatibleCDecl( name, mangleName, scope ) ) {
-				throw SemanticError( "Cforall declaration hides C function ", decl );
+				throw SemanticError( decl, "Cforall declaration hides C function " );
 			}
 		}
@@ -455,5 +455,5 @@
 			return true;
 		} else {
-			throw SemanticError( "redeclaration of ", added );
+			throw SemanticError( added, "redeclaration of " );
 		}
 	}
@@ -482,5 +482,5 @@
 			return false;
 		} else if ( ! added->get_members().empty() ) {
-			throw SemanticError( "redeclaration of ", added );
+			throw SemanticError( added, "redeclaration of " );
 		} // if
 		return true;
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/SymTab/Validate.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -366,5 +366,5 @@
 				dwts.erase( j );
 				if ( i != end ) {
-					throw SemanticError( "invalid type void in function type ", func );
+					throw SemanticError( func, "invalid type void in function type " );
 				} // if
 			} else {
@@ -374,5 +374,5 @@
 					*i = (*i)->acceptMutator( fixer );
 					if ( fixer.pass.isVoid ) {
-						throw SemanticError( "invalid type void in function type ", func );
+						throw SemanticError( func, "invalid type void in function type " );
 					} // if
 				} // for
@@ -411,5 +411,5 @@
 		for ( Expression * param : inst->parameters ) {
 			if ( ! dynamic_cast< TypeExpr * >( param ) ) {
-				throw SemanticError( "Expression parameters for generic types are currently unsupported: ", inst );
+				throw SemanticError( inst, "Expression parameters for generic types are currently unsupported: " );
 			}
 		}
@@ -511,8 +511,8 @@
 		TraitDecl *traitDecl = local_indexer->lookupTrait( traitInst->name );
 		if ( ! traitDecl ) {
-			throw SemanticError( "use of undeclared trait " + traitInst->name );
+			throw SemanticError( traitInst->location, "use of undeclared trait " + traitInst->name );
 		} // if
 		if ( traitDecl->get_parameters().size() != traitInst->get_parameters().size() ) {
-			throw SemanticError( "incorrect number of trait parameters: ", traitInst );
+			throw SemanticError( traitInst, "incorrect number of trait parameters: " );
 		} // if
 		traitInst->baseTrait = traitDecl;
@@ -522,5 +522,5 @@
 			TypeExpr * expr = dynamic_cast< TypeExpr * >( std::get<1>(p) );
 			if ( ! expr ) {
-				throw SemanticError( "Expression parameters for trait instances are currently unsupported: ", std::get<1>(p) );
+				throw SemanticError( std::get<1>(p), "Expression parameters for trait instances are currently unsupported: " );
 			}
 			if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( expr->get_type() ) ) {
@@ -629,5 +629,5 @@
 				assertion = assertion->acceptMutator( fixer );
 				if ( fixer.pass.isVoid ) {
-					throw SemanticError( "invalid type void in assertion of function ", node );
+					throw SemanticError( node, "invalid type void in assertion of function " );
 				} // if
 			} // for
@@ -673,5 +673,5 @@
 		// were cast to void.
 		if ( ! returnStmt->get_expr() && returnVals.size() != 0 ) {
-			throw SemanticError( "Non-void function returns no values: " , returnStmt );
+			throw SemanticError( returnStmt, "Non-void function returns no values: " );
 		}
 	}
@@ -714,5 +714,5 @@
 				ReferenceToType *rtt = dynamic_cast<ReferenceToType*>(ret);
 				if ( ! rtt ) {
-					throw SemanticError("Cannot apply type parameters to base type of " + typeInst->name);
+					throw SemanticError( typeInst->location, "Cannot apply type parameters to base type of " + typeInst->name );
 				}
 				rtt->get_parameters().clear();
@@ -752,5 +752,5 @@
 			Type * t2 = typedefNames[ tyDecl->get_name() ].first->get_base();
 			if ( ! ResolvExpr::typesCompatible( t1, t2, Indexer() ) ) {
-				throw SemanticError( "Cannot redefine typedef: " + tyDecl->name );
+				throw SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name );
 			}
 			// Cannot redefine VLA typedefs. Note: this is slightly incorrect, because our notion of VLAs
@@ -759,5 +759,5 @@
 			// to fix this corner case likely outweighs the utility of allowing it.
 			if ( isVariableLength( t1 ) || isVariableLength( t2 ) ) {
-				throw SemanticError( "Cannot redefine typedef: " + tyDecl->name );
+				throw SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name );
 			}
 		} else {
@@ -908,12 +908,12 @@
 		if ( CodeGen::isCtorDtorAssign( funcDecl->get_name() ) ) { // TODO: also check /=, etc.
 			if ( params.size() == 0 ) {
-				throw SemanticError( "Constructors, destructors, and assignment functions require at least one parameter ", funcDecl );
+				throw 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( "First parameter of a constructor, destructor, or assignment function must be a reference ", funcDecl );
+				throw 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( "Constructors and destructors cannot have explicit return values ", funcDecl );
+				throw SemanticError( funcDecl, "Constructors and destructors cannot have explicit return values " );
 			}
 		}
@@ -950,6 +950,6 @@
 
 			sub.apply( inst );
-			if ( args.size() < params->size() ) throw SemanticError( "Too few type arguments in generic type ", inst );
-			if ( args.size() > params->size() ) throw SemanticError( "Too many type arguments in generic type ", 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 " );
 		}
 	}
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/SynTree/Expression.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -93,5 +93,5 @@
 		return 0;
 	}
-	throw SemanticError( "Constant expression of non-integral type ", this );
+	throw SemanticError( this, "Constant expression of non-integral type " );
 }
 
Index: src/SynTree/Mutator.h
===================================================================
--- src/SynTree/Mutator.h	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/SynTree/Mutator.h	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -148,5 +148,4 @@
 			} // if
 		} catch( SemanticError &e ) {
-			e.set_location( (*i)->location );
 			errors.append( e );
 		} // try
Index: src/SynTree/Statement.cc
===================================================================
--- src/SynTree/Statement.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/SynTree/Statement.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -100,5 +100,5 @@
 	//actually this is a syntactic error signaled by the parser
 	if ( type == BranchStmt::Goto && target.empty() ) {
-		throw SemanticError("goto without target");
+		throw SemanticError( target.get_statement()->location, "goto without target");
 	}
 }
@@ -107,5 +107,5 @@
 	Statement(), computedTarget( computedTarget ), type( type ) {
 	if ( type != BranchStmt::Goto || computedTarget == nullptr ) {
-		throw SemanticError("Computed target not valid in branch statement");
+		throw SemanticError( computedTarget->location, "Computed target not valid in branch statement");
 	}
 }
@@ -203,5 +203,5 @@
 CaseStmt::CaseStmt( Expression *condition, const std::list<Statement *> &statements, bool deflt ) throw ( SemanticError ) :
 	Statement(), condition( condition ), stmts( statements ), _isDefault( deflt ) {
-	if ( isDefault() && condition != 0 ) throw SemanticError("default case with condition: ", condition);
+	if ( isDefault() && condition != 0 ) throw SemanticError( condition, "default case with condition: " );
 }
 
Index: src/SynTree/TypeSubstitution.h
===================================================================
--- src/SynTree/TypeSubstitution.h	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/SynTree/TypeSubstitution.h	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -98,5 +98,5 @@
 				} // if
 			} else {
-				throw SemanticError( toString( "Attempt to provide non-type parameter: ", toString( *actualIt ).c_str(), " for type parameter " ), formal );
+				throw 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 d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/SynTree/Visitor.h	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -142,5 +142,4 @@
 			}
 		} catch( SemanticError &e ) {
-			e.set_location( (*i)->location );
 			errors.append( e );
 		}
Index: src/main.cc
===================================================================
--- src/main.cc	(revision d27e340b8e30b8c3db286ab5e415cea7c6705b57)
+++ src/main.cc	(revision d55d7a68246b165aeaa9e161109032ddd07146d8)
@@ -361,5 +361,5 @@
 			cerr << endl << "---End of AST, begin error message:---\n" << endl;
 		} // if
-		e.print( cerr );
+		e.print();
 		if ( output != &cout ) {
 			delete output;
