Index: src/Validate/EnumAndPointerDecay.cpp
===================================================================
--- src/Validate/EnumAndPointerDecay.cpp	(revision 4520b77e192c372763501afd950a0f1452141b3b)
+++ src/Validate/EnumAndPointerDecay.cpp	(revision e9e9f561e08b390229ff9a102aa25333c265fb49)
@@ -10,6 +10,6 @@
 // Created On       : Tue Jun 28 15:50:00 2022
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue Jul 12 14:45:00 2022
-// Update Count     : 0
+// Last Modified On : Tue Sep 20 16:14:00 2022
+// Update Count     : 1
 //
 
@@ -26,15 +26,9 @@
 namespace {
 
-struct EnumAndPointerDecayCore final : public ast::WithGuards {
-	CodeLocation const * location = nullptr;
-	void previsit( ast::ParseNode const * node );
+struct EnumAndPointerDecayCore final : public ast::WithCodeLocation {
 	ast::EnumDecl const * previsit( ast::EnumDecl const * decl );
 	ast::FunctionDecl const * previsit( ast::FunctionDecl const * decl );
 	ast::FunctionType const * previsit( ast::FunctionType const * type );
 };
-
-void EnumAndPointerDecayCore::previsit( ast::ParseNode const * node ) {
-	GuardValue( location ) = &node->location;
-}
 
 ast::EnumDecl const * EnumAndPointerDecayCore::previsit(
@@ -50,5 +44,4 @@
 			new ast::EnumInstType( decl, ast::CV::Const ) );
 	}
-	GuardValue( location ) = &decl->location;
 	return mut;
 }
@@ -79,5 +72,4 @@
 		ast::FunctionDecl const * decl ) {
 	auto mut = ast::mutate( decl );
-	GuardValue( location ) = &decl->location;
 	ast::ArgumentFlag isVarArgs = mut->type->isVarArgs;
 	// It seems fixFunction (via fixFunctionList) does the pointer decay part.
Index: src/Validate/FixQualifiedTypes.cpp
===================================================================
--- src/Validate/FixQualifiedTypes.cpp	(revision 4520b77e192c372763501afd950a0f1452141b3b)
+++ src/Validate/FixQualifiedTypes.cpp	(revision e9e9f561e08b390229ff9a102aa25333c265fb49)
@@ -10,6 +10,6 @@
 // Created On       : Thr Apr 21 11:13:00 2022
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri Apr 22 11:36:00 2022
-// Update Count     : 0
+// Last Modified On : Tue Sep 20 16:15:00 2022
+// Update Count     : 1
 //
 
@@ -27,11 +27,6 @@
 
 struct FixQualifiedTypesCore :
-		public WithNoIdSymbolTable, public ast::WithGuards {
-	CodeLocation const * location = nullptr;
-
-	void previsit( ast::ParseNode const * node ) {
-		GuardValue( location ) = &node->location;
-	}
-
+		public WithNoIdSymbolTable,
+		public ast::WithCodeLocation {
 	ast::Type const * postvisit( ast::QualifiedType const * type ) {
 		assert( location );
Index: src/Validate/GenericParameter.cpp
===================================================================
--- src/Validate/GenericParameter.cpp	(revision 4520b77e192c372763501afd950a0f1452141b3b)
+++ src/Validate/GenericParameter.cpp	(revision e9e9f561e08b390229ff9a102aa25333c265fb49)
@@ -5,11 +5,11 @@
 // file "LICENCE" distributed with Cforall.
 //
-// GenericParameter.hpp -- Generic parameter related passes.
+// GenericParameter.cpp -- Generic parameter related passes.
 //
 // Author           : Andrew Beach
 // Created On       : Fri Mar 21 10:02:00 2022
 // Last Modified By : Andrew Beach
-// Last Modified On : Fri Apr 22 16:43:00 2022
-// Update Count     : 1
+// Last Modified On : Tue Sep 20 16:28:00 2022
+// Update Count     : 2
 //
 
@@ -119,19 +119,13 @@
 }
 
-struct ValidateGenericParamsCore : public ast::WithGuards {
-	const CodeLocation * locationPtr = nullptr;
-
-	void previsit( const ast::ParseNode * node ) {
-		GuardValue( locationPtr ) = &node->location;
-	}
-
+struct ValidateGenericParamsCore : public ast::WithCodeLocation {
 	const ast::StructInstType * previsit( const ast::StructInstType * type ) {
-		assert( locationPtr );
-		return validateGeneric( *locationPtr, type );
+		assert( location );
+		return validateGeneric( *location, type );
 	}
 
 	const ast::UnionInstType * previsit( const ast::UnionInstType * type ) {
-		assert( locationPtr );
-		return validateGeneric( *locationPtr, type );
+		assert( location );
+		return validateGeneric( *location, type );
 	}
 };
Index: src/Validate/LinkReferenceToTypes.cpp
===================================================================
--- src/Validate/LinkReferenceToTypes.cpp	(revision 4520b77e192c372763501afd950a0f1452141b3b)
+++ src/Validate/LinkReferenceToTypes.cpp	(revision e9e9f561e08b390229ff9a102aa25333c265fb49)
@@ -10,6 +10,6 @@
 // Created On       : Thr Apr 21 11:41:00 2022
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue Jun 28 14:58:00 2022
-// Update Count     : 1
+// Last Modified On : Tue Sep 20 16:17:00 2022
+// Update Count     : 2
 //
 
@@ -26,8 +26,8 @@
 
 struct LinkTypesCore : public WithNoIdSymbolTable,
+		public ast::WithCodeLocation,
 		public ast::WithGuards,
-		public ast::WithVisitorRef<LinkTypesCore>,
-		public ast::WithShortCircuiting {
-
+		public ast::WithShortCircuiting,
+		public ast::WithVisitorRef<LinkTypesCore> {
 	ast::TypeInstType const * postvisit( ast::TypeInstType const * type );
 	ast::EnumInstType const * postvisit( ast::EnumInstType const * type );
@@ -38,6 +38,4 @@
 	void postvisit( ast::QualifiedType const * type );
 
-	void previsit( ast::ParseNode const * node );
-
 	ast::EnumDecl const * postvisit( ast::EnumDecl const * decl );
 	ast::StructDecl const * previsit( ast::StructDecl const * decl );
@@ -60,5 +58,4 @@
 	ForwardEnumsType forwardEnums;
 
-	const CodeLocation * location = nullptr;
 	/// true if currently in a generic type body,
 	/// so that type parameter instances can be renamed appropriately
@@ -177,8 +174,4 @@
 	// Linking only makes sense for the 'oldest ancestor' of the qualified type.
 	type->parent->accept( *visitor );
-}
-
-void LinkTypesCore::previsit( ast::ParseNode const * node ) {
-	GuardValue( location ) = &node->location;
 }
 
@@ -225,9 +218,7 @@
 	GuardValue( inGeneric ) = !decl->params.empty();
 	if ( !inGeneric ) {
-		GuardValue( location ) = &decl->location;
 		return decl;
 	}
 	auto mut = ast::mutate( decl );
-	GuardValue( location ) = &mut->location;
 	for ( ast::ptr<ast::TypeDecl> & typeDecl : mut->params ) {
 		typeDecl.get_and_mutate()->name = "__" + typeDecl->name + "_generic_";
Index: src/Validate/ReplaceTypedef.cpp
===================================================================
--- src/Validate/ReplaceTypedef.cpp	(revision 4520b77e192c372763501afd950a0f1452141b3b)
+++ src/Validate/ReplaceTypedef.cpp	(revision e9e9f561e08b390229ff9a102aa25333c265fb49)
@@ -10,6 +10,6 @@
 // Created On       : Tue Jun 29 14:59:00 2022
 // Last Modified By : Andrew Beach
-// Last Modified On : Wed Jul 13 14:45:00 2022
-// Update Count     : 1
+// Last Modified On : Tue Sep 20 17:00:00 2022
+// Update Count     : 2
 //
 
@@ -39,10 +39,10 @@
 
 struct ReplaceTypedefCore final :
-		public ast::WithVisitorRef<ReplaceTypedefCore>,
+		public ast::WithCodeLocation,
+		public ast::WithDeclsToAdd<>,
 		public ast::WithGuards,
 		public ast::WithShortCircuiting,
-		public ast::WithDeclsToAdd<> {
-
-	void previsit( ast::ParseNode const * node );
+		public ast::WithVisitorRef<ReplaceTypedefCore> {
+
 	void previsit( ast::QualifiedType const * );
 	ast::Type const * postvisit( ast::QualifiedType const * );
@@ -74,12 +74,7 @@
 	TypedefMap typedefNames;
 	TypeDeclMap typedeclNames;
-	CodeLocation const * nearestLocation = nullptr;
 	int scopeLevel;
 	bool isAtFunctionTop = false;
 };
-
-void ReplaceTypedefCore::previsit( ast::ParseNode const * node ) {
-	GuardValue( nearestLocation ) = &node->location;
-}
 
 void ReplaceTypedefCore::previsit( ast::QualifiedType const * ) {
@@ -115,6 +110,6 @@
 			auto rtt = dynamic_cast<ast::BaseInstType *>( ret );
 			if ( !rtt ) {
-				assert( nearestLocation );
-				SemanticError( *nearestLocation, "Cannot apply type parameters to base type of " + type->name );
+				assert( location );
+				SemanticError( *location, "Cannot apply type parameters to base type of " + type->name );
 			}
 			rtt->params.clear();
@@ -129,6 +124,6 @@
 		TypeDeclMap::const_iterator base = typedeclNames.find( type->name );
 		if ( base == typedeclNames.end() ) {
-			assert( nearestLocation );
-			SemanticError( *nearestLocation, toString( "Use of undefined type ", type->name ) );
+			assert( location );
+			SemanticError( *location, toString( "Use of undefined type ", type->name ) );
 		}
 		return ast::mutate_field( type, &ast::TypeInstType::base, base->second );
@@ -191,5 +186,4 @@
 
 void ReplaceTypedefCore::previsit( ast::TypeDecl const * decl ) {
-	previsit( (ast::ParseNode const *)decl );
 	TypedefMap::iterator iter = typedefNames.find( decl->name );
 	if ( iter != typedefNames.end() ) {
@@ -200,5 +194,4 @@
 
 void ReplaceTypedefCore::previsit( ast::FunctionDecl const * decl ) {
-	previsit( (ast::ParseNode const *)decl );
 	GuardScope( typedefNames );
 	GuardScope( typedeclNames );
@@ -207,5 +200,4 @@
 
 void ReplaceTypedefCore::previsit( ast::ObjectDecl const * decl ) {
-	previsit( (ast::ParseNode const *)decl );
 	GuardScope( typedefNames );
 	GuardScope( typedeclNames );
@@ -217,10 +209,10 @@
 		using DWTVector = std::vector<ast::ptr<ast::DeclWithType>>;
 		using DeclVector = std::vector<ast::ptr<ast::TypeDecl>>;
-		CodeLocation const & location = decl->location;
+		CodeLocation const & declLocation = decl->location;
 		UniqueName paramNamer( decl->name + "Param" );
 
 		// Replace the current object declaration with a function declaration.
 		ast::FunctionDecl const * newDecl = new ast::FunctionDecl(
-			location,
+			declLocation,
 			decl->name,
 			map_range<DeclVector>( type->forall, []( const ast::TypeInstType * inst ) {
@@ -230,11 +222,11 @@
 				return ast::deepCopy( expr->var );
 			} ),
-			map_range<DWTVector>( type->params, [&location, &paramNamer]( const ast::Type * type ) {
+			map_range<DWTVector>( type->params, [&declLocation, &paramNamer]( const ast::Type * type ) {
 				assert( type );
-				return new ast::ObjectDecl( location, paramNamer.newName(), ast::deepCopy( type ) );
+				return new ast::ObjectDecl( declLocation, paramNamer.newName(), ast::deepCopy( type ) );
 			} ),
-			map_range<DWTVector>( type->returns, [&location, &paramNamer]( const ast::Type * type ) {
+			map_range<DWTVector>( type->returns, [&declLocation, &paramNamer]( const ast::Type * type ) {
 				assert( type );
-				return new ast::ObjectDecl( location, paramNamer.newName(), ast::deepCopy( type ) );
+				return new ast::ObjectDecl( declLocation, paramNamer.newName(), ast::deepCopy( type ) );
 			} ),
 			nullptr,
@@ -250,5 +242,4 @@
 
 void ReplaceTypedefCore::previsit( ast::CastExpr const * expr ) {
-	previsit( (ast::ParseNode const *)expr );
 	GuardScope( typedefNames );
 	GuardScope( typedeclNames );
@@ -256,5 +247,4 @@
 
 void ReplaceTypedefCore::previsit( ast::CompoundStmt const * expr ) {
-	previsit( (ast::ParseNode const *)expr );
 	GuardScope( typedefNames );
 	GuardScope( typedeclNames );
@@ -268,5 +258,4 @@
 
 ast::StructDecl const * ReplaceTypedefCore::previsit( ast::StructDecl const * decl ) {
-	previsit( (ast::ParseNode const *)decl );
 	visit_children = false;
 	addImplicitTypedef( decl );
@@ -275,5 +264,4 @@
 
 ast::UnionDecl const * ReplaceTypedefCore::previsit( ast::UnionDecl const * decl ) {
-	previsit( (ast::ParseNode const *)decl );
 	visit_children = false;
 	addImplicitTypedef( decl );
@@ -282,10 +270,8 @@
 
 void ReplaceTypedefCore::previsit( ast::EnumDecl const * decl ) {
-	previsit( (ast::ParseNode const *)decl );
 	addImplicitTypedef( decl );
 }
 
 void ReplaceTypedefCore::previsit( ast::TraitDecl const * decl ) {
-	previsit( (ast::ParseNode const *)decl );
 	GuardScope( typedefNames );
 	GuardScope( typedeclNames );
