Index: src/CodeGen/FixNames.cc
===================================================================
--- src/CodeGen/FixNames.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/CodeGen/FixNames.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -19,4 +19,5 @@
 #include <string>                  // for string, operator!=, operator==
 
+#include "Common/PassVisitor.h"
 #include "Common/SemanticError.h"  // for SemanticError
 #include "FixMain.h"               // for FixMain
@@ -32,10 +33,10 @@
 
 namespace CodeGen {
-	class FixNames : public Visitor {
+	class FixNames : public WithGuards {
 	  public:
-		virtual void visit( ObjectDecl *objectDecl );
-		virtual void visit( FunctionDecl *functionDecl );
+		void postvisit( ObjectDecl *objectDecl );
+		void postvisit( FunctionDecl *functionDecl );
 
-		virtual void visit( CompoundStmt *compoundStmt );
+		void previsit( CompoundStmt *compoundStmt );
 	  private:
 		int scopeLevel = 1;
@@ -93,10 +94,10 @@
 	}
 
-	void fixNames( std::list< Declaration* > translationUnit ) {
-		FixNames fixer;
+	void fixNames( std::list< Declaration* > & translationUnit ) {
+		PassVisitor<FixNames> fixer;
 		acceptAll( translationUnit, fixer );
 	}
 
-	void FixNames::fixDWT( DeclarationWithType *dwt ) {
+	void FixNames::fixDWT( DeclarationWithType * dwt ) {
 		if ( dwt->get_name() != "" ) {
 			if ( LinkageSpec::isMangled( dwt->get_linkage() ) ) {
@@ -107,11 +108,9 @@
 	}
 
-	void FixNames::visit( ObjectDecl *objectDecl ) {
-		Visitor::visit( objectDecl );
+	void FixNames::postvisit( ObjectDecl * objectDecl ) {
 		fixDWT( objectDecl );
 	}
 
-	void FixNames::visit( FunctionDecl *functionDecl ) {
-		Visitor::visit( functionDecl );
+	void FixNames::postvisit( FunctionDecl * functionDecl ) {
 		fixDWT( functionDecl );
 
@@ -121,13 +120,12 @@
 				throw SemanticError("Main expected to have 0, 2 or 3 arguments\n", functionDecl);
 			}
-			functionDecl->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, new ConstantExpr( Constant::from_int( 0 ) ) ) );
+			functionDecl->get_statements()->get_kids().push_back( new ReturnStmt( new ConstantExpr( Constant::from_int( 0 ) ) ) );
 			CodeGen::FixMain::registerMain( functionDecl );
 		}
 	}
 
-	void FixNames::visit( CompoundStmt *compoundStmt ) {
+	void FixNames::previsit( CompoundStmt * ) {
 		scopeLevel++;
-		Visitor::visit( compoundStmt );
-		scopeLevel--;
+		GuardAction( [this](){ scopeLevel--; } );
 	}
 } // namespace CodeGen
Index: src/CodeGen/FixNames.h
===================================================================
--- src/CodeGen/FixNames.h	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/CodeGen/FixNames.h	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -5,5 +5,5 @@
 // file "LICENCE" distributed with Cforall.
 //
-// FixNames.h -- 
+// FixNames.h --
 //
 // Author           : Richard C. Bilson
@@ -22,5 +22,5 @@
 namespace CodeGen {
 	/// mangles object and function names
-	void fixNames( std::list< Declaration* > translationUnit );
+	void fixNames( std::list< Declaration* > & translationUnit );
 } // namespace CodeGen
 
Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/Common/PassVisitor.impl.h	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -55,5 +55,5 @@
 		it,
 		[](Declaration * decl) -> auto {
-			return new DeclStmt( noLabels, decl );
+			return new DeclStmt( decl );
 		}
 	);
@@ -251,5 +251,5 @@
 	    || ( empty( beforeDecls ) && empty( afterDecls )) );
 
-	CompoundStmt *compound = new CompoundStmt( noLabels );
+	CompoundStmt *compound = new CompoundStmt();
 	if( !empty(beforeDecls) ) { splice( std::back_inserter( compound->get_kids() ), beforeDecls ); }
 	if( !empty(beforeStmts) ) { compound->get_kids().splice( compound->get_kids().end(), *beforeStmts ); }
@@ -400,4 +400,11 @@
 	{
 		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		// implicit add __func__ identifier as specified in the C manual 6.4.2.2
+		static ObjectDecl func(
+			"__func__", noStorageClasses, LinkageSpec::C, nullptr,
+			new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ), nullptr, true, false ),
+			nullptr
+		);
+		indexerAddId( &func );
 		maybeAccept_impl( node->type, *this );
 		maybeAccept_impl( node->statements, *this );
@@ -418,4 +425,11 @@
 	{
 		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
+		// implicit add __func__ identifier as specified in the C manual 6.4.2.2
+		static ObjectDecl func(
+			"__func__", noStorageClasses, LinkageSpec::C, nullptr,
+			new ArrayType( Type::Qualifiers(), new BasicType( Type::Qualifiers( Type::Const ), BasicType::Char ), nullptr, true, false ),
+			nullptr
+		);
+		indexerAddId( &func );
 		maybeMutate_impl( node->type, *this );
 		maybeMutate_impl( node->statements, *this );
Index: src/Concurrency/Keywords.cc
===================================================================
--- src/Concurrency/Keywords.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/Concurrency/Keywords.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -38,12 +38,4 @@
 
 namespace Concurrency {
-
-	namespace {
-		const std::list<Label> noLabels;
-		const std::list< Attribute * > noAttributes;
-		Type::StorageClasses noStorage;
-		Type::Qualifiers noQualifiers;
-	}
-
 	//=============================================================================================
 	// Pass declarations
@@ -296,5 +288,5 @@
 		ObjectDecl * this_decl = new ObjectDecl(
 			"this",
-			noStorage,
+			noStorageClasses,
 			LinkageSpec::Cforall,
 			nullptr,
@@ -313,5 +305,5 @@
 			new ObjectDecl(
 				"ret",
-				noStorage,
+				noStorageClasses,
 				LinkageSpec::Cforall,
 				nullptr,
@@ -346,5 +338,5 @@
 			main_decl = new FunctionDecl(
 				"main",
-				noStorage,
+				noStorageClasses,
 				LinkageSpec::Cforall,
 				main_type,
@@ -363,5 +355,5 @@
 		ObjectDecl * field = new ObjectDecl(
 			field_name,
-			noStorage,
+			noStorageClasses,
 			LinkageSpec::Cforall,
 			nullptr,
@@ -379,8 +371,7 @@
 
 	void ConcurrentSueKeyword::addRoutines( ObjectDecl * field, FunctionDecl * func ) {
-		CompoundStmt * statement = new CompoundStmt( noLabels );
+		CompoundStmt * statement = new CompoundStmt();
 		statement->push_back(
 			new ReturnStmt(
-				noLabels,
 				new AddressExpr(
 					new MemberExpr(
@@ -488,5 +479,5 @@
 		ObjectDecl * monitors = new ObjectDecl(
 			"__monitor",
-			noStorage,
+			noStorageClasses,
 			LinkageSpec::Cforall,
 			nullptr,
@@ -509,7 +500,7 @@
 		// monitor_guard_t __guard = { __monitors, #, func };
 		body->push_front(
-			new DeclStmt( noLabels, new ObjectDecl(
+			new DeclStmt( new ObjectDecl(
 				"__guard",
-				noStorage,
+				noStorageClasses,
 				LinkageSpec::Cforall,
 				nullptr,
@@ -530,5 +521,5 @@
 
 		//monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
-		body->push_front( new DeclStmt( noLabels, monitors) );
+		body->push_front( new DeclStmt( monitors) );
 	}
 
@@ -536,5 +527,5 @@
 		ObjectDecl * monitors = new ObjectDecl(
 			"__monitors",
-			noStorage,
+			noStorageClasses,
 			LinkageSpec::Cforall,
 			nullptr,
@@ -569,7 +560,7 @@
 		// monitor_guard_t __guard = { __monitors, #, func };
 		body->push_front(
-			new DeclStmt( noLabels, new ObjectDecl(
+			new DeclStmt( new ObjectDecl(
 				"__guard",
-				noStorage,
+				noStorageClasses,
 				LinkageSpec::Cforall,
 				nullptr,
@@ -591,5 +582,5 @@
 
 		//monitor_desc * __monitors[] = { get_monitor(a), get_monitor(b) };
-		body->push_front( new DeclStmt( noLabels, monitors) );
+		body->push_front( new DeclStmt( monitors) );
 	}
 
@@ -631,5 +622,4 @@
 		stmt->push_back(
 			new ExprStmt(
-				noLabels,
 				new UntypedExpr(
 					new NameExpr( "__thrd_start" ),
Index: src/Concurrency/Waitfor.cc
===================================================================
--- src/Concurrency/Waitfor.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/Concurrency/Waitfor.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -100,12 +100,4 @@
 
 namespace Concurrency {
-
-	namespace {
-		const std::list<Label> noLabels;
-		const std::list< Attribute * > noAttributes;
-		Type::StorageClasses noStorage;
-		Type::Qualifiers noQualifiers;
-	}
-
 	//=============================================================================================
 	// Pass declarations
@@ -203,5 +195,5 @@
 			ResolvExpr::findVoidExpression( expr, indexer );
 
-			return new ExprStmt( noLabels, expr );
+			return new ExprStmt( expr );
 		}
 
@@ -259,5 +251,5 @@
 		if( !decl_monitor || !decl_acceptable || !decl_mask ) throw SemanticError( "waitfor keyword requires monitors to be in scope, add #include <monitor>", waitfor );
 
-		CompoundStmt * stmt = new CompoundStmt( noLabels );
+		CompoundStmt * stmt = new CompoundStmt();
 
 		ObjectDecl * acceptables = declare( waitfor->clauses.size(), stmt );
@@ -281,7 +273,6 @@
 		);
 
-		CompoundStmt * compound = new CompoundStmt( noLabels );
+		CompoundStmt * compound = new CompoundStmt();
 		stmt->push_back( new IfStmt(
-			noLabels,
 			safeCond( new VariableExpr( flag ) ),
 			compound,
@@ -313,5 +304,5 @@
 		);
 
-		stmt->push_back( new DeclStmt( noLabels, acceptables) );
+		stmt->push_back( new DeclStmt( acceptables) );
 
 		Expression * set = new UntypedExpr(
@@ -326,5 +317,5 @@
 		ResolvExpr::findVoidExpression( set, indexer );
 
-		stmt->push_back( new ExprStmt( noLabels, set ) );
+		stmt->push_back( new ExprStmt( set ) );
 
 		return acceptables;
@@ -341,5 +332,5 @@
 		);
 
-		stmt->push_back( new DeclStmt( noLabels, flag) );
+		stmt->push_back( new DeclStmt( flag) );
 
 		return flag;
@@ -357,5 +348,5 @@
 		ResolvExpr::findVoidExpression( expr, indexer );
 
-		return new ExprStmt( noLabels, expr );
+		return new ExprStmt( expr );
 	}
 
@@ -399,5 +390,5 @@
 		);
 
-		stmt->push_back( new DeclStmt( noLabels, mon) );
+		stmt->push_back( new DeclStmt( mon) );
 
 		return mon;
@@ -411,5 +402,4 @@
 
 		stmt->push_back( new IfStmt(
-			noLabels,
 			safeCond( clause.condition ),
 			new CompoundStmt({
@@ -447,13 +437,11 @@
 		);
 
-		stmt->push_back( new DeclStmt( noLabels, timeout ) );
+		stmt->push_back( new DeclStmt( timeout ) );
 
 		if( time ) {
 			stmt->push_back( new IfStmt(
-				noLabels,
 				safeCond( time_cond ),
 				new CompoundStmt({
 					new ExprStmt(
-						noLabels,
 						makeOpAssign(
 							new VariableExpr( timeout ),
@@ -471,9 +459,7 @@
 		if( has_else ) {
 			stmt->push_back( new IfStmt(
-				noLabels,
 				safeCond( else_cond ),
 				new CompoundStmt({
 					new ExprStmt(
-						noLabels,
 						makeOpAssign(
 							new VariableExpr( timeout ),
@@ -511,5 +497,5 @@
 		);
 
-		stmt->push_back( new DeclStmt( noLabels, index ) );
+		stmt->push_back( new DeclStmt( index ) );
 
 		ObjectDecl * mask = ObjectDecl::newObject(
@@ -526,8 +512,7 @@
 		);
 
-		stmt->push_back( new DeclStmt( noLabels, mask ) );
+		stmt->push_back( new DeclStmt( mask ) );
 
 		stmt->push_back( new ExprStmt(
-			noLabels,
 			new ApplicationExpr(
 				VariableExpr::functionPointer( decl_waitfor ),
@@ -557,5 +542,4 @@
 	) {
 		SwitchStmt * swtch = new SwitchStmt(
-			noLabels,
 			result,
 			std::list<Statement *>()
@@ -566,10 +550,8 @@
 			swtch->statements.push_back(
 				new CaseStmt(
-					noLabels,
 					new ConstantExpr( Constant::from_ulong( i++ ) ),
 					{
 						clause.statement,
 						new BranchStmt(
-							noLabels,
 							"",
 							BranchStmt::Break
@@ -583,10 +565,8 @@
 			swtch->statements.push_back(
 				new CaseStmt(
-					noLabels,
 					new ConstantExpr( Constant::from_int( -2 ) ),
 					{
 						waitfor->timeout.statement,
 						new BranchStmt(
-							noLabels,
 							"",
 							BranchStmt::Break
@@ -600,10 +580,8 @@
 			swtch->statements.push_back(
 				new CaseStmt(
-					noLabels,
 					new ConstantExpr( Constant::from_int( -1 ) ),
 					{
 						waitfor->orelse.statement,
 						new BranchStmt(
-							noLabels,
 							"",
 							BranchStmt::Break
Index: src/ControlStruct/ExceptTranslate.cc
===================================================================
--- src/ControlStruct/ExceptTranslate.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/ControlStruct/ExceptTranslate.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -30,5 +30,5 @@
 #include "SynTree/Expression.h"       // for UntypedExpr, ConstantExpr, Name...
 #include "SynTree/Initializer.h"      // for SingleInit, ListInit
-#include "SynTree/Label.h"            // for Label, noLabels
+#include "SynTree/Label.h"            // for Label
 #include "SynTree/Mutator.h"          // for mutateAll
 #include "SynTree/Statement.h"        // for CompoundStmt, CatchStmt, ThrowStmt
@@ -57,5 +57,5 @@
 
 	void appendDeclStmt( CompoundStmt * block, Declaration * item ) {
-		block->push_back(new DeclStmt(noLabels, item));
+		block->push_back(new DeclStmt(item));
 	}
 
@@ -205,5 +205,5 @@
 		throwStmt->set_expr( nullptr );
 		delete throwStmt;
-		return new ExprStmt( noLabels, call );
+		return new ExprStmt( call );
 	}
 
@@ -220,6 +220,7 @@
 		assert( handler_except_decl );
 
-		CompoundStmt * result = new CompoundStmt( throwStmt->get_labels() );
-		result->push_back( new ExprStmt( noLabels, UntypedExpr::createAssign(
+		CompoundStmt * result = new CompoundStmt();
+		result->labels =  throwStmt->labels;
+		result->push_back( new ExprStmt( UntypedExpr::createAssign(
 			nameOf( handler_except_decl ),
 			new ConstantExpr( Constant::null(
@@ -231,5 +232,4 @@
 			) ) );
 		result->push_back( new ExprStmt(
-			noLabels,
 			new UntypedExpr( new NameExpr( "__cfaabi_ehm__rethrow_terminate" ) )
 			) );
@@ -248,7 +248,7 @@
 		// return false;
 		Statement * result = new ReturnStmt(
-			throwStmt->get_labels(),
 			new ConstantExpr( Constant::from_bool( false ) )
 			);
+		result->labels = throwStmt->labels;
 		delete throwStmt;
 		return result;
@@ -291,5 +291,5 @@
 			// }
 			// return;
-			CompoundStmt * block = new CompoundStmt( noLabels );
+			CompoundStmt * block = new CompoundStmt();
 
 			// Just copy the exception value. (Post Validation)
@@ -304,5 +304,5 @@
 					) })
 				);
-			block->push_back( new DeclStmt( noLabels, local_except ) );
+			block->push_back( new DeclStmt( local_except ) );
 
 			// Add the cleanup attribute.
@@ -324,7 +324,6 @@
 
 			std::list<Statement *> caseBody
-					{ block, new ReturnStmt( noLabels, nullptr ) };
+					{ block, new ReturnStmt( nullptr ) };
 			handler_wrappers.push_back( new CaseStmt(
-				noLabels,
 				new ConstantExpr( Constant::from_int( index ) ),
 				caseBody
@@ -340,9 +339,8 @@
 
 		SwitchStmt * handler_lookup = new SwitchStmt(
-			noLabels,
 			nameOf( index_obj ),
 			stmt_handlers
 			);
-		CompoundStmt * body = new CompoundStmt( noLabels );
+		CompoundStmt * body = new CompoundStmt();
 		body->push_back( handler_lookup );
 
@@ -363,5 +361,5 @@
 		// }
 
-		CompoundStmt * block = new CompoundStmt( noLabels );
+		CompoundStmt * block = new CompoundStmt();
 
 		// Local Declaration
@@ -369,5 +367,5 @@
 			dynamic_cast<ObjectDecl *>( modded_handler->get_decl() );
 		assert( local_except );
-		block->push_back( new DeclStmt( noLabels, local_except ) );
+		block->push_back( new DeclStmt( local_except ) );
 
 		// Check for type match.
@@ -381,5 +379,5 @@
 		}
 		// Construct the match condition.
-		block->push_back( new IfStmt( noLabels,
+		block->push_back( new IfStmt(
 			cond, modded_handler->get_body(), nullptr ) );
 
@@ -397,5 +395,5 @@
 		// }
 
-		CompoundStmt * body = new CompoundStmt( noLabels );
+		CompoundStmt * body = new CompoundStmt();
 
 		FunctionType * func_type = match_func_t.clone();
@@ -413,5 +411,5 @@
 
 			// Create new body.
-			handler->set_body( new ReturnStmt( noLabels,
+			handler->set_body( new ReturnStmt(
 				new ConstantExpr( Constant::from_int( index ) ) ) );
 
@@ -421,5 +419,5 @@
 		}
 
-		body->push_back( new ReturnStmt( noLabels,
+		body->push_back( new ReturnStmt(
 			new ConstantExpr( Constant::from_int( 0 ) ) ) );
 
@@ -441,6 +439,6 @@
 		args.push_back( nameOf( terminate_match ) );
 
-		CompoundStmt * callStmt = new CompoundStmt( noLabels );
-		callStmt->push_back( new ExprStmt( noLabels, caller ) );
+		CompoundStmt * callStmt = new CompoundStmt();
+		callStmt->push_back( new ExprStmt( caller ) );
 		return callStmt;
 	}
@@ -451,5 +449,5 @@
 		//     HANDLER WRAPPERS { `hander->body`; return true; }
 		// }
-		CompoundStmt * body = new CompoundStmt( noLabels );
+		CompoundStmt * body = new CompoundStmt();
 
 		FunctionType * func_type = handle_func_t.clone();
@@ -464,8 +462,8 @@
 				dynamic_cast<CompoundStmt*>( handler->get_body() );
 			if ( ! handling_code ) {
-				handling_code = new CompoundStmt( noLabels );
+				handling_code = new CompoundStmt();
 				handling_code->push_back( handler->get_body() );
 			}
-			handling_code->push_back( new ReturnStmt( noLabels,
+			handling_code->push_back( new ReturnStmt(
 				new ConstantExpr( Constant::from_bool( true ) ) ) );
 			handler->set_body( handling_code );
@@ -476,5 +474,5 @@
 		}
 
-		body->push_back( new ReturnStmt( noLabels,
+		body->push_back( new ReturnStmt(
 			new ConstantExpr( Constant::from_bool( false ) ) ) );
 
@@ -486,5 +484,5 @@
 			Statement * wraps,
 			FunctionDecl * resume_handler ) {
-		CompoundStmt * body = new CompoundStmt( noLabels );
+		CompoundStmt * body = new CompoundStmt();
 
 		// struct __try_resume_node __resume_node
@@ -521,5 +519,5 @@
 		setup->get_args().push_back( nameOf( resume_handler ) );
 
-		body->push_back( new ExprStmt( noLabels, setup ) );
+		body->push_back( new ExprStmt( setup ) );
 
 		body->push_back( wraps );
@@ -646,5 +644,5 @@
 		// Generate a prefix for the function names?
 
-		CompoundStmt * block = new CompoundStmt( noLabels );
+		CompoundStmt * block = new CompoundStmt();
 		CompoundStmt * inner = take_try_block( tryStmt );
 
Index: src/ControlStruct/ForExprMutator.cc
===================================================================
--- src/ControlStruct/ForExprMutator.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/ControlStruct/ForExprMutator.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -29,5 +29,5 @@
 		// Create compound statement, move initializers outside,
 		// the resut of the original stays as is.
-		CompoundStmt *block = new CompoundStmt( std::list< Label >() );
+		CompoundStmt *block = new CompoundStmt();
 		std::list<Statement *> &stmts = block->get_kids();
 		stmts.splice( stmts.end(), init );
Index: src/ControlStruct/LabelFixer.cc
===================================================================
--- src/ControlStruct/LabelFixer.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/ControlStruct/LabelFixer.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -37,21 +37,17 @@
 	}
 
-	void LabelFixer::visit( FunctionDecl *functionDecl ) {
+	void LabelFixer::previsit( FunctionDecl * ) {
 		// need to go into a nested function in a fresh state
-		std::map < Label, Entry *> oldLabelTable = labelTable;
+		GuardValue( labelTable );
 		labelTable.clear();
+	}
 
-		maybeAccept( functionDecl->get_statements(), *this );
-
+	void LabelFixer::postvisit( FunctionDecl * functionDecl ) {
 		MLEMutator mlemut( resolveJumps(), generator );
 		functionDecl->acceptMutator( mlemut );
-
-		// and remember the outer function's labels when
-		// returning to it
-		labelTable = oldLabelTable;
 	}
 
 	// prune to at most one label definition for each statement
-	void LabelFixer::visit( Statement *stmt ) {
+	void LabelFixer::previsit( Statement *stmt ) {
 		std::list< Label > &labels = stmt->get_labels();
 
@@ -62,6 +58,6 @@
 	}
 
-	void LabelFixer::visit( BranchStmt *branchStmt ) {
-		visit ( ( Statement * )branchStmt );
+	void LabelFixer::previsit( BranchStmt *branchStmt ) {
+		previsit( ( Statement *)branchStmt );
 
 		// for labeled branches, add an entry to the label table
@@ -72,15 +68,8 @@
 	}
 
-	void LabelFixer::visit( UntypedExpr *untyped ) {
-		if ( NameExpr * func = dynamic_cast< NameExpr * >( untyped->get_function() ) ) {
-			if ( func->get_name() == "&&" ) {
-				NameExpr * arg = dynamic_cast< NameExpr * >( untyped->get_args().front() );
-				Label target = arg->get_name();
-				assert( target != "" );
-				setLabelsUsg( target, untyped );
-			} else {
-				Visitor::visit( untyped );
-			}
-		}
+	void LabelFixer::previsit( LabelAddressExpr * addrExpr ) {
+		Label & target = addrExpr->arg;
+		assert( target != "" );
+		setLabelsUsg( target, addrExpr );
 	}
 
Index: src/ControlStruct/LabelFixer.h
===================================================================
--- src/ControlStruct/LabelFixer.h	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/ControlStruct/LabelFixer.h	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -19,4 +19,5 @@
 #include <map>                     // for map
 
+#include "Common/PassVisitor.h"
 #include "Common/SemanticError.h"  // for SemanticError
 #include "SynTree/Label.h"         // for Label
@@ -26,8 +27,7 @@
 namespace ControlStruct {
 	/// normalizes label definitions and generates multi-level exit labels
-class LabelGenerator;
+	class LabelGenerator;
 
-	class LabelFixer final : public Visitor {
-		typedef Visitor Parent;
+	class LabelFixer final : public WithGuards {
 	  public:
 		LabelFixer( LabelGenerator *gen = 0 );
@@ -35,26 +35,14 @@
 		std::map < Label, Statement * > *resolveJumps() throw ( SemanticError );
 
-		using Visitor::visit;
-
 		// Declarations
-		virtual void visit( FunctionDecl *functionDecl ) override;
+		void previsit( FunctionDecl *functionDecl );
+		void postvisit( FunctionDecl *functionDecl );
 
 		// Statements
-		void visit( Statement *stmt );
+		void previsit( Statement *stmt );
+		void previsit( BranchStmt *branchStmt );
 
-		virtual void visit( CompoundStmt *stmt ) override { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
-		virtual void visit( NullStmt *stmt ) override { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
-		virtual void visit( ExprStmt *stmt ) override { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
-		virtual void visit( IfStmt *stmt ) override { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
-		virtual void visit( WhileStmt *stmt ) override { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
-		virtual void visit( ForStmt *stmt ) override { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
-		virtual void visit( SwitchStmt *stmt ) override { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
-		virtual void visit( CaseStmt *stmt ) override { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
-		virtual void visit( ReturnStmt *stmt ) override { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
-		virtual void visit( TryStmt *stmt ) override { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
-		virtual void visit( CatchStmt *stmt ) override { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
-		virtual void visit( DeclStmt *stmt ) override { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
-		virtual void visit( BranchStmt *branchStmt ) override;
-		virtual void visit( UntypedExpr *untyped ) override;
+		// Expressions
+		void previsit( LabelAddressExpr *addrExpr );
 
 		Label setLabelsDef( std::list< Label > &, Statement *definition );
Index: src/ControlStruct/MLEMutator.cc
===================================================================
--- src/ControlStruct/MLEMutator.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/ControlStruct/MLEMutator.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -149,6 +149,7 @@
 
 			if ( CaseStmt * c = dynamic_cast< CaseStmt * >( statements.back() ) ) {
-				std::list<Label> temp; temp.push_back( brkLabel );
-				c->get_statements().push_back( new BranchStmt( temp, Label("brkLabel"), BranchStmt::Break ) );
+				Statement * stmt = new BranchStmt( Label("brkLabel"), BranchStmt::Break );
+				stmt->labels.push_back( brkLabel );
+				c->get_statements().push_back( stmt );
 			} else assert(0); // as of this point, all statements of a switch are still CaseStmts
 		} // if
@@ -232,5 +233,5 @@
 		// transform break/continue statements into goto to simplify later handling of branches
 		delete branchStmt;
-		return new BranchStmt( std::list<Label>(), exitLabel, BranchStmt::Goto );
+		return new BranchStmt( exitLabel, BranchStmt::Goto );
 	}
 
@@ -239,5 +240,5 @@
 		CompoundStmt *newBody;
 		if ( ! (newBody = dynamic_cast<CompoundStmt *>( bodyLoop )) ) {
-			newBody = new CompoundStmt( std::list< Label >() );
+			newBody = new CompoundStmt();
 			newBody->get_kids().push_back( bodyLoop );
 		} // if
Index: src/ControlStruct/Mutate.cc
===================================================================
--- src/ControlStruct/Mutate.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/ControlStruct/Mutate.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -24,5 +24,4 @@
 #include "SynTree/Declaration.h"   // for Declaration
 #include "SynTree/Mutator.h"       // for mutateAll
-//#include "ExceptMutator.h"
 
 #include "Common/PassVisitor.h"    // for PassVisitor
@@ -37,11 +36,8 @@
 
 		// normalizes label definitions and generates multi-level exit labels
-		LabelFixer lfix;
-
-		//ExceptMutator exc;
+		PassVisitor<LabelFixer> lfix;
 
 		mutateAll( translationUnit, formut );
 		acceptAll( translationUnit, lfix );
-		//mutateAll( translationUnit, exc );
 	}
 } // namespace CodeGen
Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/GenPoly/Box.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -49,5 +49,5 @@
 #include "SynTree/Expression.h"          // for ApplicationExpr, UntypedExpr
 #include "SynTree/Initializer.h"         // for SingleInit, Initializer, Lis...
-#include "SynTree/Label.h"               // for Label, noLabels
+#include "SynTree/Label.h"               // for Label
 #include "SynTree/Mutator.h"             // for maybeMutate, Mutator, mutateAll
 #include "SynTree/Statement.h"           // for ExprStmt, DeclStmt, ReturnStmt
@@ -293,5 +293,5 @@
 		FunctionDecl *layoutDecl = new FunctionDecl( layoutofName( typeDecl ),
 													 functionNesting > 0 ? Type::StorageClasses() : Type::StorageClasses( Type::Static ),
-													 LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ),
+													 LinkageSpec::AutoGen, layoutFnType, new CompoundStmt(),
 													 std::list< Attribute * >(), Type::FuncSpecifiers( Type::Inline ) );
 		layoutDecl->fixUniqueId();
@@ -321,5 +321,5 @@
 	/// makes an if-statement with a single-expression if-block and no then block
 	Statement *makeCond( Expression *cond, Expression *ifPart ) {
-		return new IfStmt( noLabels, cond, new ExprStmt( noLabels, ifPart ), 0 );
+		return new IfStmt( cond, new ExprStmt( ifPart ), 0 );
 	}
 
@@ -340,5 +340,5 @@
 	/// adds an expression to a compound statement
 	void addExpr( CompoundStmt *stmts, Expression *expr ) {
-		stmts->get_kids().push_back( new ExprStmt( noLabels, expr ) );
+		stmts->get_kids().push_back( new ExprStmt( expr ) );
 	}
 
@@ -629,5 +629,5 @@
 		ObjectDecl *Pass1::makeTemporary( Type *type ) {
 			ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, type, 0 );
-			stmtsToAddBefore.push_back( new DeclStmt( noLabels, newObj ) );
+			stmtsToAddBefore.push_back( new DeclStmt( newObj ) );
 			return newObj;
 		}
@@ -740,9 +740,9 @@
 				ObjectDecl *newObj = ObjectDecl::newObject( tempNamer.newName(), newType, nullptr );
 				newObj->get_type()->get_qualifiers() = Type::Qualifiers(); // TODO: is this right???
-				stmtsToAddBefore.push_back( new DeclStmt( noLabels, newObj ) );
+				stmtsToAddBefore.push_back( new DeclStmt( newObj ) );
 				UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); // TODO: why doesn't this just use initialization syntax?
 				assign->get_args().push_back( new VariableExpr( newObj ) );
 				assign->get_args().push_back( arg );
-				stmtsToAddBefore.push_back( new ExprStmt( noLabels, assign ) );
+				stmtsToAddBefore.push_back( new ExprStmt( assign ) );
 				arg = new AddressExpr( new VariableExpr( newObj ) );
 			} // if
@@ -888,5 +888,5 @@
 				// void return
 				addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
-				bodyStmt = new ExprStmt( noLabels, adapteeApp );
+				bodyStmt = new ExprStmt( adapteeApp );
 			} else if ( isDynType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
 				// return type T
@@ -900,11 +900,11 @@
 				addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
 				assign->get_args().push_back( adapteeApp );
-				bodyStmt = new ExprStmt( noLabels, assign );
+				bodyStmt = new ExprStmt( assign );
 			} else {
 				// adapter for a function that returns a monomorphic value
 				addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
-				bodyStmt = new ReturnStmt( noLabels, adapteeApp );
+				bodyStmt = new ReturnStmt( adapteeApp );
 			} // if
-			CompoundStmt *adapterBody = new CompoundStmt( noLabels );
+			CompoundStmt *adapterBody = new CompoundStmt();
 			adapterBody->get_kids().push_back( bodyStmt );
 			std::string adapterName = makeAdapterName( mangleName );
@@ -952,5 +952,5 @@
 						std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
 						adapter = answer.first;
-						stmtsToAddBefore.push_back( new DeclStmt( noLabels, newAdapter ) );
+						stmtsToAddBefore.push_back( new DeclStmt( newAdapter ) );
 					} // if
 					assert( adapter != adapters.end() );
@@ -1279,5 +1279,5 @@
 						retval->set_name( "_retval" );
 					}
-					functionDecl->get_statements()->get_kids().push_front( new DeclStmt( noLabels, retval ) );
+					functionDecl->get_statements()->get_kids().push_front( new DeclStmt( retval ) );
 					DeclarationWithType * newRet = retval->clone(); // for ownership purposes
 					ftype->get_returnVals().front() = newRet;
@@ -1519,5 +1519,5 @@
 					// (alloca was previously used, but can't be safely used in loops)
 					ObjectDecl *newBuf = ObjectDecl::newObject( bufNamer.newName(), polyToMonoType( objectDecl->type ), nullptr );
-					stmtsToAddBefore.push_back( new DeclStmt( noLabels, newBuf ) );
+					stmtsToAddBefore.push_back( new DeclStmt( newBuf ) );
 
 					delete objectDecl->get_init();
@@ -1598,5 +1598,5 @@
 		ObjectDecl *PolyGenericCalculator::makeVar( const std::string &name, Type *type, Initializer *init ) {
 			ObjectDecl *newObj = new ObjectDecl( name, Type::StorageClasses(), LinkageSpec::C, 0, type, init );
-			stmtsToAddBefore.push_back( new DeclStmt( noLabels, newObj ) );
+			stmtsToAddBefore.push_back( new DeclStmt( newObj ) );
 			return newObj;
 		}
@@ -1677,5 +1677,5 @@
 					addOtypeParamsToLayoutCall( layoutCall, otypeParams );
 
-					stmtsToAddBefore.push_back( new ExprStmt( noLabels, layoutCall ) );
+					stmtsToAddBefore.push_back( new ExprStmt( layoutCall ) );
 				}
 
@@ -1703,5 +1703,5 @@
 				addOtypeParamsToLayoutCall( layoutCall, otypeParams );
 
-				stmtsToAddBefore.push_back( new ExprStmt( noLabels, layoutCall ) );
+				stmtsToAddBefore.push_back( new ExprStmt( layoutCall ) );
 
 				return true;
Index: src/GenPoly/InstantiateGeneric.cc
===================================================================
--- src/GenPoly/InstantiateGeneric.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/GenPoly/InstantiateGeneric.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -526,5 +526,5 @@
 					Expression * init = new CastExpr( new AddressExpr( memberExpr ), new PointerType( Type::Qualifiers(), concType->clone() ) );
 					ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), new ReferenceType( Type::Qualifiers(), concType ), new SingleInit( init ) );
-					stmtsToAddBefore.push_back( new DeclStmt( noLabels, tmp ) );
+					stmtsToAddBefore.push_back( new DeclStmt( tmp ) );
 					return new VariableExpr( tmp );
 				} else {
Index: src/GenPoly/Specialize.cc
===================================================================
--- src/GenPoly/Specialize.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/GenPoly/Specialize.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -35,5 +35,5 @@
 #include "SynTree/Declaration.h"         // for FunctionDecl, DeclarationWit...
 #include "SynTree/Expression.h"          // for ApplicationExpr, Expression
-#include "SynTree/Label.h"               // for Label, noLabels
+#include "SynTree/Label.h"               // for Label
 #include "SynTree/Mutator.h"             // for mutateAll
 #include "SynTree/Statement.h"           // for CompoundStmt, DeclStmt, Expr...
@@ -234,5 +234,5 @@
 		} // if
 		// create new thunk with same signature as formal type (C linkage, empty body)
-		FunctionDecl *thunkFunc = new FunctionDecl( thunkNamer.newName(), Type::StorageClasses(), LinkageSpec::C, newType, new CompoundStmt( noLabels ) );
+		FunctionDecl *thunkFunc = new FunctionDecl( thunkNamer.newName(), Type::StorageClasses(), LinkageSpec::C, newType, new CompoundStmt() );
 		thunkFunc->fixUniqueId();
 
@@ -287,12 +287,12 @@
 		Statement *appStmt;
 		if ( funType->returnVals.empty() ) {
-			appStmt = new ExprStmt( noLabels, appExpr );
-		} else {
-			appStmt = new ReturnStmt( noLabels, appExpr );
+			appStmt = new ExprStmt( appExpr );
+		} else {
+			appStmt = new ReturnStmt( appExpr );
 		} // if
 		thunkFunc->statements->kids.push_back( appStmt );
 
 		// add thunk definition to queue of statements to add
-		stmtsToAddBefore.push_back( new DeclStmt( noLabels, thunkFunc ) );
+		stmtsToAddBefore.push_back( new DeclStmt( thunkFunc ) );
 		// return address of thunk function as replacement expression
 		return new AddressExpr( new VariableExpr( thunkFunc ) );
Index: src/InitTweak/FixGlobalInit.cc
===================================================================
--- src/InitTweak/FixGlobalInit.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/InitTweak/FixGlobalInit.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -20,4 +20,5 @@
 #include <algorithm>               // for replace_if
 
+#include "Common/PassVisitor.h"
 #include "Common/SemanticError.h"  // for SemanticError
 #include "Common/UniqueName.h"     // for UniqueName
@@ -29,5 +30,5 @@
 #include "SynTree/Expression.h"    // for ConstantExpr, Expression (ptr only)
 #include "SynTree/Initializer.h"   // for ConstructorInit, Initializer
-#include "SynTree/Label.h"         // for Label, noLabels
+#include "SynTree/Label.h"         // for Label
 #include "SynTree/Statement.h"     // for CompoundStmt, Statement (ptr only)
 #include "SynTree/Type.h"          // for Type, Type::StorageClasses, Functi...
@@ -35,15 +36,15 @@
 
 namespace InitTweak {
-	class GlobalFixer : public Visitor {
+	class GlobalFixer : public WithShortCircuiting {
 	  public:
 		GlobalFixer( const std::string & name, bool inLibrary );
 
-		virtual void visit( ObjectDecl *objDecl );
-		virtual void visit( FunctionDecl *functionDecl );
-		virtual void visit( StructDecl *aggregateDecl );
-		virtual void visit( UnionDecl *aggregateDecl );
-		virtual void visit( EnumDecl *aggregateDecl );
-		virtual void visit( TraitDecl *aggregateDecl );
-		virtual void visit( TypeDecl *typeDecl );
+		void previsit( ObjectDecl *objDecl );
+		void previsit( FunctionDecl *functionDecl );
+		void previsit( StructDecl *aggregateDecl );
+		void previsit( UnionDecl *aggregateDecl );
+		void previsit( EnumDecl *aggregateDecl );
+		void previsit( TraitDecl *aggregateDecl );
+		void previsit( TypeDecl *typeDecl );
 
 		UniqueName tempNamer;
@@ -53,6 +54,7 @@
 
 	void fixGlobalInit( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ) {
-		GlobalFixer fixer( name, inLibrary );
-		acceptAll( translationUnit, fixer );
+		PassVisitor<GlobalFixer> visitor( name, inLibrary );
+		acceptAll( translationUnit, visitor );
+		GlobalFixer & fixer = visitor.pass;
 		// don't need to include function if it's empty
 		if ( fixer.initFunction->get_statements()->get_kids().empty() ) {
@@ -92,11 +94,11 @@
 			dtorParameters.push_back( new ConstantExpr( Constant::from_int( 102 ) ) );
 		}
-		initFunction = new FunctionDecl( "_init_" + fixedName, Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ) );
+		initFunction = new FunctionDecl( "_init_" + fixedName, Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
 		initFunction->get_attributes().push_back( new Attribute( "constructor", ctorParameters ) );
-		destroyFunction = new FunctionDecl( "_destroy_" + fixedName, Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ) );
+		destroyFunction = new FunctionDecl( "_destroy_" + fixedName, Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
 		destroyFunction->get_attributes().push_back( new Attribute( "destructor", dtorParameters ) );
 	}
 
-	void GlobalFixer::visit( ObjectDecl *objDecl ) {
+	void GlobalFixer::previsit( ObjectDecl *objDecl ) {
 		std::list< Statement * > & initStatements = initFunction->get_statements()->get_kids();
 		std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids();
@@ -134,10 +136,10 @@
 
 	// only modify global variables
-	void GlobalFixer::visit( __attribute__((unused)) FunctionDecl *functionDecl ) {}
-	void GlobalFixer::visit( __attribute__((unused)) StructDecl *aggregateDecl ) {}
-	void GlobalFixer::visit( __attribute__((unused)) UnionDecl *aggregateDecl ) {}
-	void GlobalFixer::visit( __attribute__((unused)) EnumDecl *aggregateDecl ) {}
-	void GlobalFixer::visit( __attribute__((unused)) TraitDecl *aggregateDecl ) {}
-	void GlobalFixer::visit( __attribute__((unused)) TypeDecl *typeDecl ) {}
+	void GlobalFixer::previsit( FunctionDecl * ) { visit_children = false; }
+	void GlobalFixer::previsit( StructDecl * ) { visit_children = false; }
+	void GlobalFixer::previsit( UnionDecl * ) { visit_children = false; }
+	void GlobalFixer::previsit( EnumDecl * ) { visit_children = false; }
+	void GlobalFixer::previsit( TraitDecl * ) { visit_children = false; }
+	void GlobalFixer::previsit( TypeDecl * ) { visit_children = false; }
 
 } // namespace InitTweak
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/InitTweak/FixInit.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -49,5 +49,5 @@
 #include "SynTree/Expression.h"        // for UniqueExpr, VariableExpr, Unty...
 #include "SynTree/Initializer.h"       // for ConstructorInit, SingleInit
-#include "SynTree/Label.h"             // for Label, noLabels, operator<
+#include "SynTree/Label.h"             // for Label, operator<
 #include "SynTree/Mutator.h"           // for mutateAll, Mutator, maybeMutate
 #include "SynTree/Statement.h"         // for ExprStmt, CompoundStmt, Branch...
@@ -544,13 +544,13 @@
 			// add all temporary declarations and their constructors
 			for ( ObjectDecl * obj : tempDecls ) {
-				stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
+				stmtsToAddBefore.push_back( new DeclStmt( obj ) );
 			} // for
 			for ( ObjectDecl * obj : returnDecls ) {
-				stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
+				stmtsToAddBefore.push_back( new DeclStmt( obj ) );
 			} // for
 
 			// add destructors after current statement
 			for ( Expression * dtor : dtors ) {
-				stmtsToAddAfter.push_back( new ExprStmt( noLabels, dtor ) );
+				stmtsToAddAfter.push_back( new ExprStmt( dtor ) );
 			} // for
 
@@ -598,14 +598,14 @@
 			if ( ! result->isVoid() ) {
 				for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) {
-					stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) );
+					stmtsToAddBefore.push_back( new DeclStmt( obj ) );
 				} // for
 				// add destructors after current statement
 				for ( Expression * dtor : stmtExpr->get_dtors() ) {
-					stmtsToAddAfter.push_back( new ExprStmt( noLabels, dtor ) );
+					stmtsToAddAfter.push_back( new ExprStmt( dtor ) );
 				} // for
 				// must have a non-empty body, otherwise it wouldn't have a result
 				assert( ! stmts.empty() );
 				assert( ! stmtExpr->get_returnDecls().empty() );
-				stmts.push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
+				stmts.push_back( new ExprStmt( new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );
 				stmtExpr->get_returnDecls().clear();
 				stmtExpr->get_dtors().clear();
@@ -685,12 +685,12 @@
 
 						// generate body of if
-						CompoundStmt * initStmts = new CompoundStmt( noLabels );
+						CompoundStmt * initStmts = new CompoundStmt();
 						std::list< Statement * > & body = initStmts->get_kids();
 						body.push_back( ctor );
-						body.push_back( new ExprStmt( noLabels, setTrue ) );
+						body.push_back( new ExprStmt( setTrue ) );
 
 						// put it all together
-						IfStmt * ifStmt = new IfStmt( noLabels, new VariableExpr( isUninitializedVar ), initStmts, 0 );
-						stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) );
+						IfStmt * ifStmt = new IfStmt( new VariableExpr( isUninitializedVar ), initStmts, 0 );
+						stmtsToAddAfter.push_back( new DeclStmt( isUninitializedVar ) );
 						stmtsToAddAfter.push_back( ifStmt );
 
@@ -707,5 +707,5 @@
 
 							// void __objName_dtor_atexitN(...) {...}
-							FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ) );
+							FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
 							dtorCaller->fixUniqueId();
 							dtorCaller->get_statements()->push_back( dtorStmt );
@@ -715,5 +715,5 @@
 							callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );
 
-							body.push_back( new ExprStmt( noLabels, callAtexit ) );
+							body.push_back( new ExprStmt( callAtexit ) );
 
 							// hoist variable and dtor caller decls to list of decls that will be added into global scope
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/InitTweak/InitTweak.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -5,4 +5,5 @@
 #include <memory>                  // for __shared_ptr
 
+#include "Common/PassVisitor.h"
 #include "Common/SemanticError.h"  // for SemanticError
 #include "Common/UniqueName.h"     // for UniqueName
@@ -19,5 +20,5 @@
 #include "SynTree/Expression.h"    // for Expression, UntypedExpr, Applicati...
 #include "SynTree/Initializer.h"   // for Initializer, ListInit, Designation
-#include "SynTree/Label.h"         // for Label, noLabels
+#include "SynTree/Label.h"         // for Label
 #include "SynTree/Statement.h"     // for CompoundStmt, ExprStmt, BranchStmt
 #include "SynTree/Type.h"          // for FunctionType, ArrayType, PointerType
@@ -29,15 +30,23 @@
 namespace InitTweak {
 	namespace {
-		class HasDesignations : public Visitor {
-		public:
+		struct HasDesignations : public WithShortCircuiting {
 			bool hasDesignations = false;
-			virtual void visit( Designation * des ) {
-				if ( ! des->get_designators().empty() ) hasDesignations = true;
-				else Visitor::visit( des );
+
+			void previsit( BaseSyntaxNode * ) {
+				// short circuit if we already know there are designations
+				if ( hasDesignations ) visit_children = false;
+			}
+
+			void previsit( Designation * des ) {
+				// short circuit if we already know there are designations
+				if ( hasDesignations ) visit_children = false;
+				else if ( ! des->get_designators().empty() ) {
+					hasDesignations = true;
+					visit_children = false;
+				}
 			}
 		};
 
-		class InitDepthChecker : public Visitor {
-		public:
+		struct InitDepthChecker : public WithGuards {
 			bool depthOkay = true;
 			Type * type;
@@ -51,48 +60,37 @@
 				maxDepth++;
 			}
-			virtual void visit( ListInit * listInit ) {
+			void previsit( ListInit * ) {
 				curDepth++;
+				GuardAction( [this]() { curDepth--; } );
 				if ( curDepth > maxDepth ) depthOkay = false;
-				Visitor::visit( listInit );
-				curDepth--;
 			}
 		};
 
-		class InitFlattener : public Visitor {
-			public:
-			virtual void visit( SingleInit * singleInit );
-			virtual void visit( ListInit * listInit );
+		struct InitFlattener : public WithShortCircuiting {
+			void previsit( SingleInit * singleInit ) {
+				visit_children = false;
+				argList.push_back( singleInit->value->clone() );
+			}
 			std::list< Expression * > argList;
 		};
 
-		void InitFlattener::visit( SingleInit * singleInit ) {
-			argList.push_back( singleInit->get_value()->clone() );
-		}
-
-		void InitFlattener::visit( ListInit * listInit ) {
-			// flatten nested list inits
-			std::list<Initializer*>::iterator it = listInit->begin();
-			for ( ; it != listInit->end(); ++it ) {
-				(*it)->accept( *this );
-			}
-		}
 	}
 
 	std::list< Expression * > makeInitList( Initializer * init ) {
-		InitFlattener flattener;
+		PassVisitor<InitFlattener> flattener;
 		maybeAccept( init, flattener );
-		return flattener.argList;
+		return flattener.pass.argList;
 	}
 
 	bool isDesignated( Initializer * init ) {
-		HasDesignations finder;
+		PassVisitor<HasDesignations> finder;
 		maybeAccept( init, finder );
-		return finder.hasDesignations;
+		return finder.pass.hasDesignations;
 	}
 
 	bool checkInitDepth( ObjectDecl * objDecl ) {
-		InitDepthChecker checker( objDecl->get_type() );
-		maybeAccept( objDecl->get_init(), checker );
-		return checker.depthOkay;
+		PassVisitor<InitDepthChecker> checker( objDecl->type );
+		maybeAccept( objDecl->init, checker );
+		return checker.pass.depthOkay;
 	}
 
@@ -195,9 +193,9 @@
 			callExpr->get_args().splice( callExpr->get_args().end(), args );
 
-			*out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), nullptr );
+			*out++ = new IfStmt( cond, new ExprStmt( callExpr ), nullptr );
 
 			UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
 			increment->get_args().push_back( index->clone() );
-			*out++ = new ExprStmt( noLabels, increment );
+			*out++ = new ExprStmt( increment );
 		}
 
@@ -244,10 +242,10 @@
 					std::list< Statement * > stmts;
 					build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );
-					stmts.push_back( new BranchStmt( noLabels, switchLabel, BranchStmt::Break ) );
-					CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
+					stmts.push_back( new BranchStmt( switchLabel, BranchStmt::Break ) );
+					CaseStmt * caseStmt = new CaseStmt( condition, stmts );
 					branches.push_back( caseStmt );
 				}
-				*out++ = new SwitchStmt( noLabels, index->clone(), branches );
-				*out++ = new NullStmt( std::list<Label>{ switchLabel } );
+				*out++ = new SwitchStmt( index->clone(), branches );
+				*out++ = new NullStmt( { switchLabel } );
 			}
 		}
@@ -262,5 +260,5 @@
 	Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
 		if ( ! init ) return nullptr;
-		CompoundStmt * block = new CompoundStmt( noLabels );
+		CompoundStmt * block = new CompoundStmt();
 		build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );
 		if ( block->get_kids().empty() ) {
@@ -309,14 +307,12 @@
 	}
 
-	class CallFinder : public Visitor {
-	public:
-		typedef Visitor Parent;
+	struct CallFinder {
 		CallFinder( const std::list< std::string > & names ) : names( names ) {}
 
-		virtual void visit( ApplicationExpr * appExpr ) {
+		void postvisit( ApplicationExpr * appExpr ) {
 			handleCallExpr( appExpr );
 		}
 
-		virtual void visit( UntypedExpr * untypedExpr ) {
+		void postvisit( UntypedExpr * untypedExpr ) {
 			handleCallExpr( untypedExpr );
 		}
@@ -328,5 +324,4 @@
 		template< typename CallExpr >
 		void handleCallExpr( CallExpr * expr ) {
-			Parent::visit( expr );
 			std::string fname = getFunctionName( expr );
 			if ( std::find( names.begin(), names.end(), fname ) != names.end() ) {
@@ -337,6 +332,6 @@
 
 	void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) {
-		static CallFinder finder( std::list< std::string >{ "?{}", "^?{}" } );
-		finder.matches = &matches;
+		static PassVisitor<CallFinder> finder( std::list< std::string >{ "?{}", "^?{}" } );
+		finder.pass.matches = &matches;
 		maybeAccept( stmt, finder );
 	}
@@ -544,48 +539,37 @@
 	}
 
-	class ConstExprChecker : public Visitor {
-	public:
-		ConstExprChecker() : isConstExpr( true ) {}
-
-		using Visitor::visit;
-
-		virtual void visit( ApplicationExpr * ) { isConstExpr = false; }
-		virtual void visit( UntypedExpr * ) { isConstExpr = false; }
-		virtual void visit( NameExpr * ) { isConstExpr = false; }
-		// virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
-		virtual void visit( AddressExpr *addressExpr ) {
+	struct ConstExprChecker : public WithShortCircuiting {
+		// most expressions are not const expr
+		void previsit( Expression * ) { isConstExpr = false; visit_children = false; }
+
+		void previsit( AddressExpr *addressExpr ) {
+			visit_children = false;
+
 			// address of a variable or member expression is constexpr
 			Expression * arg = addressExpr->get_arg();
 			if ( ! dynamic_cast< NameExpr * >( arg) && ! dynamic_cast< VariableExpr * >( arg ) && ! dynamic_cast< MemberExpr * >( arg ) && ! dynamic_cast< UntypedMemberExpr * >( arg ) ) isConstExpr = false;
 		}
-		virtual void visit( UntypedMemberExpr * ) { isConstExpr = false; }
-		virtual void visit( MemberExpr * ) { isConstExpr = false; }
-		virtual void visit( VariableExpr * ) { isConstExpr = false; }
-		// these might be okay?
-		// virtual void visit( SizeofExpr *sizeofExpr );
-		// virtual void visit( AlignofExpr *alignofExpr );
-		// virtual void visit( UntypedOffsetofExpr *offsetofExpr );
-		// virtual void visit( OffsetofExpr *offsetofExpr );
-		// virtual void visit( OffsetPackExpr *offsetPackExpr );
-		// virtual void visit( AttrExpr *attrExpr );
-		// virtual void visit( CommaExpr *commaExpr );
-		// virtual void visit( LogicalExpr *logicalExpr );
-		// virtual void visit( ConditionalExpr *conditionalExpr );
-		virtual void visit( TypeExpr * ) { isConstExpr = false; }
-		virtual void visit( AsmExpr * ) { isConstExpr = false; }
-		virtual void visit( UntypedValofExpr * ) { isConstExpr = false; }
-		virtual void visit( CompoundLiteralExpr * ) { isConstExpr = false; }
-		virtual void visit( UntypedTupleExpr * ) { isConstExpr = false; }
-		virtual void visit( TupleExpr * ) { isConstExpr = false; }
-		virtual void visit( TupleAssignExpr * ) { isConstExpr = false; }
-
-		bool isConstExpr;
+
+		// these expressions may be const expr, depending on their children
+		void previsit( SizeofExpr * ) {}
+		void previsit( AlignofExpr * ) {}
+		void previsit( UntypedOffsetofExpr * ) {}
+		void previsit( OffsetofExpr * ) {}
+		void previsit( OffsetPackExpr * ) {}
+		void previsit( AttrExpr * ) {}
+		void previsit( CommaExpr * ) {}
+		void previsit( LogicalExpr * ) {}
+		void previsit( ConditionalExpr * ) {}
+		void previsit( CastExpr * ) {}
+		void previsit( ConstantExpr * ) {}
+
+		bool isConstExpr = true;
 	};
 
 	bool isConstExpr( Expression * expr ) {
 		if ( expr ) {
-			ConstExprChecker checker;
+			PassVisitor<ConstExprChecker> checker;
 			expr->accept( checker );
-			return checker.isConstExpr;
+			return checker.pass.isConstExpr;
 		}
 		return true;
@@ -594,7 +578,7 @@
 	bool isConstExpr( Initializer * init ) {
 		if ( init ) {
-			ConstExprChecker checker;
+			PassVisitor<ConstExprChecker> checker;
 			init->accept( checker );
-			return checker.isConstExpr;
+			return checker.pass.isConstExpr;
 		} // if
 		// for all intents and purposes, no initializer means const expr
Index: src/MakeLibCfa.cc
===================================================================
--- src/MakeLibCfa.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/MakeLibCfa.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -116,5 +116,5 @@
 			} // for
 
-			funcDecl->set_statements( new CompoundStmt( std::list< Label >() ) );
+			funcDecl->set_statements( new CompoundStmt() );
 			newDecls.push_back( funcDecl );
 
@@ -130,10 +130,10 @@
 			  case CodeGen::OT_INFIXASSIGN:
 					// return the recursive call
-					stmt = new ReturnStmt( noLabels, newExpr );
+					stmt = new ReturnStmt( newExpr );
 					break;
 			  case CodeGen::OT_CTOR:
 			  case CodeGen::OT_DTOR:
 					// execute the recursive call
-					stmt = new ExprStmt( noLabels, newExpr );
+					stmt = new ExprStmt( newExpr );
 					break;
 			  case CodeGen::OT_CONSTANT:
Index: src/Makefile.in
===================================================================
--- src/Makefile.in	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/Makefile.in	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -215,6 +215,4 @@
 	SymTab/driver_cfa_cpp-Validate.$(OBJEXT) \
 	SymTab/driver_cfa_cpp-FixFunction.$(OBJEXT) \
-	SymTab/driver_cfa_cpp-ImplementationType.$(OBJEXT) \
-	SymTab/driver_cfa_cpp-TypeEquality.$(OBJEXT) \
 	SymTab/driver_cfa_cpp-Autogen.$(OBJEXT) \
 	SynTree/driver_cfa_cpp-Type.$(OBJEXT) \
@@ -514,6 +512,5 @@
 	ResolvExpr/CurrentObject.cc ResolvExpr/ExplodedActual.cc \
 	SymTab/Indexer.cc SymTab/Mangler.cc SymTab/Validate.cc \
-	SymTab/FixFunction.cc SymTab/ImplementationType.cc \
-	SymTab/TypeEquality.cc SymTab/Autogen.cc SynTree/Type.cc \
+	SymTab/FixFunction.cc SymTab/Autogen.cc SynTree/Type.cc \
 	SynTree/VoidType.cc SynTree/BasicType.cc \
 	SynTree/PointerType.cc SynTree/ArrayType.cc \
@@ -844,8 +841,4 @@
 SymTab/driver_cfa_cpp-FixFunction.$(OBJEXT): SymTab/$(am__dirstamp) \
 	SymTab/$(DEPDIR)/$(am__dirstamp)
-SymTab/driver_cfa_cpp-ImplementationType.$(OBJEXT):  \
-	SymTab/$(am__dirstamp) SymTab/$(DEPDIR)/$(am__dirstamp)
-SymTab/driver_cfa_cpp-TypeEquality.$(OBJEXT): SymTab/$(am__dirstamp) \
-	SymTab/$(DEPDIR)/$(am__dirstamp)
 SymTab/driver_cfa_cpp-Autogen.$(OBJEXT): SymTab/$(am__dirstamp) \
 	SymTab/$(DEPDIR)/$(am__dirstamp)
@@ -1040,8 +1033,6 @@
 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Autogen.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-FixFunction.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-ImplementationType.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Indexer.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Mangler.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-TypeEquality.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Validate.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AddressExpr.Po@am__quote@
@@ -2039,32 +2030,4 @@
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-FixFunction.obj `if test -f 'SymTab/FixFunction.cc'; then $(CYGPATH_W) 'SymTab/FixFunction.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/FixFunction.cc'; fi`
-
-SymTab/driver_cfa_cpp-ImplementationType.o: SymTab/ImplementationType.cc
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-ImplementationType.o -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-ImplementationType.Tpo -c -o SymTab/driver_cfa_cpp-ImplementationType.o `test -f 'SymTab/ImplementationType.cc' || echo '$(srcdir)/'`SymTab/ImplementationType.cc
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-ImplementationType.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-ImplementationType.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='SymTab/ImplementationType.cc' object='SymTab/driver_cfa_cpp-ImplementationType.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-ImplementationType.o `test -f 'SymTab/ImplementationType.cc' || echo '$(srcdir)/'`SymTab/ImplementationType.cc
-
-SymTab/driver_cfa_cpp-ImplementationType.obj: SymTab/ImplementationType.cc
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-ImplementationType.obj -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-ImplementationType.Tpo -c -o SymTab/driver_cfa_cpp-ImplementationType.obj `if test -f 'SymTab/ImplementationType.cc'; then $(CYGPATH_W) 'SymTab/ImplementationType.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/ImplementationType.cc'; fi`
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-ImplementationType.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-ImplementationType.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='SymTab/ImplementationType.cc' object='SymTab/driver_cfa_cpp-ImplementationType.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-ImplementationType.obj `if test -f 'SymTab/ImplementationType.cc'; then $(CYGPATH_W) 'SymTab/ImplementationType.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/ImplementationType.cc'; fi`
-
-SymTab/driver_cfa_cpp-TypeEquality.o: SymTab/TypeEquality.cc
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-TypeEquality.o -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-TypeEquality.Tpo -c -o SymTab/driver_cfa_cpp-TypeEquality.o `test -f 'SymTab/TypeEquality.cc' || echo '$(srcdir)/'`SymTab/TypeEquality.cc
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-TypeEquality.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-TypeEquality.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='SymTab/TypeEquality.cc' object='SymTab/driver_cfa_cpp-TypeEquality.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-TypeEquality.o `test -f 'SymTab/TypeEquality.cc' || echo '$(srcdir)/'`SymTab/TypeEquality.cc
-
-SymTab/driver_cfa_cpp-TypeEquality.obj: SymTab/TypeEquality.cc
-@am__fastdepCXX_TRUE@	$(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-TypeEquality.obj -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-TypeEquality.Tpo -c -o SymTab/driver_cfa_cpp-TypeEquality.obj `if test -f 'SymTab/TypeEquality.cc'; then $(CYGPATH_W) 'SymTab/TypeEquality.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/TypeEquality.cc'; fi`
-@am__fastdepCXX_TRUE@	$(AM_V_at)$(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-TypeEquality.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-TypeEquality.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	$(AM_V_CXX)source='SymTab/TypeEquality.cc' object='SymTab/driver_cfa_cpp-TypeEquality.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@	DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@	$(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-TypeEquality.obj `if test -f 'SymTab/TypeEquality.cc'; then $(CYGPATH_W) 'SymTab/TypeEquality.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/TypeEquality.cc'; fi`
 
 SymTab/driver_cfa_cpp-Autogen.o: SymTab/Autogen.cc
Index: src/Parser/StatementNode.cc
===================================================================
--- src/Parser/StatementNode.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/Parser/StatementNode.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -37,5 +37,5 @@
 	DeclarationNode *agg = decl->extractAggregate();
 	if ( agg ) {
-		StatementNode *nextStmt = new StatementNode( new DeclStmt( noLabels, maybeBuild< Declaration >( decl ) ) );
+		StatementNode *nextStmt = new StatementNode( new DeclStmt( maybeBuild< Declaration >( decl ) ) );
 		set_next( nextStmt );
 		if ( decl->get_next() ) {
@@ -50,5 +50,5 @@
 		agg = decl;
 	} // if
-	stmt.reset( new DeclStmt( noLabels, maybeMoveBuild< Declaration >(agg) ) );
+	stmt.reset( new DeclStmt( maybeMoveBuild< Declaration >(agg) ) );
 } // StatementNode::StatementNode
 
@@ -75,7 +75,7 @@
 
 	if ( e )
-		return new ExprStmt( noLabels, e );
+		return new ExprStmt( e );
 	else
-		return new NullStmt( noLabels );
+		return new NullStmt();
 }
 
@@ -113,5 +113,5 @@
 	}
 	delete ctl;
-	return new IfStmt( noLabels, cond, thenb, elseb, init );
+	return new IfStmt( cond, thenb, elseb, init );
 }
 
@@ -120,13 +120,13 @@
 	buildMoveList< Statement, StatementNode >( stmt, branches );
 	// branches.size() == 0 for switch (...) {}, i.e., no declaration or statements
-	return new SwitchStmt( noLabels, maybeMoveBuild< Expression >(ctl), branches );
+	return new SwitchStmt( maybeMoveBuild< Expression >(ctl), branches );
 }
 Statement *build_case( ExpressionNode *ctl ) {
 	std::list< Statement * > branches;
-	return new CaseStmt( noLabels, maybeMoveBuild< Expression >(ctl), branches );
+	return new CaseStmt( maybeMoveBuild< Expression >(ctl), branches );
 }
 Statement *build_default() {
 	std::list< Statement * > branches;
-	return new CaseStmt( noLabels, nullptr, branches, true );
+	return new CaseStmt( nullptr, branches, true );
 }
 
@@ -135,5 +135,5 @@
 	buildMoveList< Statement, StatementNode >( stmt, branches );
 	assert( branches.size() == 1 );
-	return new WhileStmt( noLabels, notZeroExpr( maybeMoveBuild< Expression >(ctl) ), branches.front(), kind );
+	return new WhileStmt( notZeroExpr( maybeMoveBuild< Expression >(ctl) ), branches.front(), kind );
 }
 
@@ -157,18 +157,18 @@
 
 	delete forctl;
-	return new ForStmt( noLabels, init, cond, incr, branches.front() );
+	return new ForStmt( init, cond, incr, branches.front() );
 }
 
 Statement *build_branch( BranchStmt::Type kind ) {
-	Statement * ret = new BranchStmt( noLabels, "", kind );
+	Statement * ret = new BranchStmt( "", kind );
 	return ret;
 }
 Statement *build_branch( std::string *identifier, BranchStmt::Type kind ) {
-	Statement * ret = new BranchStmt( noLabels, *identifier, kind );
+	Statement * ret = new BranchStmt( *identifier, kind );
 	delete identifier; 									// allocated by lexer
 	return ret;
 }
 Statement *build_computedgoto( ExpressionNode *ctl ) {
-	return new BranchStmt( noLabels, maybeMoveBuild< Expression >(ctl), BranchStmt::Goto );
+	return new BranchStmt( maybeMoveBuild< Expression >(ctl), BranchStmt::Goto );
 }
 
@@ -176,5 +176,5 @@
 	std::list< Expression * > exps;
 	buildMoveList( ctl, exps );
-	return new ReturnStmt( noLabels, exps.size() > 0 ? exps.back() : nullptr );
+	return new ReturnStmt( exps.size() > 0 ? exps.back() : nullptr );
 }
 
@@ -183,5 +183,5 @@
 	buildMoveList( ctl, exps );
 	assertf( exps.size() < 2, "This means we are leaking memory");
-	return new ThrowStmt( noLabels, ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr );
+	return new ThrowStmt( ThrowStmt::Terminate, !exps.empty() ? exps.back() : nullptr );
 }
 
@@ -190,5 +190,5 @@
 	buildMoveList( ctl, exps );
 	assertf( exps.size() < 2, "This means we are leaking memory");
-	return new ThrowStmt( noLabels, ThrowStmt::Resume, !exps.empty() ? exps.back() : nullptr );
+	return new ThrowStmt( ThrowStmt::Resume, !exps.empty() ? exps.back() : nullptr );
 }
 
@@ -204,5 +204,5 @@
 	CompoundStmt *tryBlock = strict_dynamic_cast< CompoundStmt * >(maybeMoveBuild< Statement >(try_stmt));
 	FinallyStmt *finallyBlock = dynamic_cast< FinallyStmt * >(maybeMoveBuild< Statement >(finally_stmt) );
-	return new TryStmt( noLabels, tryBlock, branches, finallyBlock );
+	return new TryStmt( tryBlock, branches, finallyBlock );
 }
 Statement *build_catch( CatchStmt::Kind kind, DeclarationNode *decl, ExpressionNode *cond, StatementNode *body ) {
@@ -210,5 +210,5 @@
 	buildMoveList< Statement, StatementNode >( body, branches );
 	assert( branches.size() == 1 );
-	return new CatchStmt( noLabels, kind, maybeMoveBuild< Declaration >(decl), maybeMoveBuild< Expression >(cond), branches.front() );
+	return new CatchStmt( kind, maybeMoveBuild< Declaration >(decl), maybeMoveBuild< Expression >(cond), branches.front() );
 }
 Statement *build_finally( StatementNode *stmt ) {
@@ -216,5 +216,5 @@
 	buildMoveList< Statement, StatementNode >( stmt, branches );
 	assert( branches.size() == 1 );
-	return new FinallyStmt( noLabels, dynamic_cast< CompoundStmt * >( branches.front() ) );
+	return new FinallyStmt( dynamic_cast< CompoundStmt * >( branches.front() ) );
 }
 
@@ -289,5 +289,5 @@
 
 Statement *build_compound( StatementNode *first ) {
-	CompoundStmt *cs = new CompoundStmt( noLabels );
+	CompoundStmt *cs = new CompoundStmt();
 	buildMoveList( first, cs->get_kids() );
 	return cs;
@@ -301,5 +301,5 @@
 	buildMoveList( input, in );
 	buildMoveList( clobber, clob );
-	return new AsmStmt( noLabels, voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels );
+	return new AsmStmt( voltile, instruction, out, in, clob, gotolabels ? gotolabels->labels : noLabels );
 }
 
Index: src/SymTab/AddVisit.h
===================================================================
--- src/SymTab/AddVisit.h	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/SymTab/AddVisit.h	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -24,5 +24,5 @@
 			// add any new declarations after the previous statement
 			for ( std::list< Declaration* >::iterator decl = visitor.declsToAddAfter.begin(); decl != visitor.declsToAddAfter.end(); ++decl ) {
-				DeclStmt *declStmt = new DeclStmt( noLabels, *decl );
+				DeclStmt *declStmt = new DeclStmt( *decl );
 				stmts.insert( stmt, declStmt );
 			}
@@ -36,5 +36,5 @@
 			// add any new declarations before the statement
 			for ( std::list< Declaration* >::iterator decl = visitor.declsToAdd.begin(); decl != visitor.declsToAdd.end(); ++decl ) {
-				DeclStmt *declStmt = new DeclStmt( noLabels, *decl );
+				DeclStmt *declStmt = new DeclStmt( *decl );
 				stmts.insert( stmt, declStmt );
 			}
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/SymTab/Autogen.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -264,5 +264,5 @@
 		Type::StorageClasses scs = functionNesting > 0 ? Type::StorageClasses() : Type::StorageClasses( Type::Static );
 		LinkageSpec::Spec spec = isIntrinsic ? LinkageSpec::Intrinsic : LinkageSpec::AutoGen;
-		FunctionDecl * decl = new FunctionDecl( fname, scs, spec, ftype, new CompoundStmt( noLabels ),
+		FunctionDecl * decl = new FunctionDecl( fname, scs, spec, ftype, new CompoundStmt(),
 												std::list< Attribute * >(), Type::FuncSpecifiers( Type::Inline ) );
 		decl->fixUniqueId();
@@ -299,5 +299,5 @@
 				assert( assignType->returnVals.size() == 1 );
 				ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( assignType->parameters.front() );
-				dcl->statements->push_back( new ReturnStmt( noLabels, new VariableExpr( dstParam ) ) );
+				dcl->statements->push_back( new ReturnStmt( new VariableExpr( dstParam ) ) );
 			}
 			resolve( dcl );
@@ -468,5 +468,5 @@
 		copy->args.push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
 		copy->args.push_back( new SizeofExpr( srcParam->get_type()->clone() ) );
-		*out++ = new ExprStmt( noLabels, copy );
+		*out++ = new ExprStmt( copy );
 	}
 
@@ -544,5 +544,5 @@
 			callExpr->get_args().push_back( new VariableExpr( dstParam ) );
 			callExpr->get_args().push_back( new VariableExpr( srcParam ) );
-			funcDecl->statements->push_back( new ExprStmt( noLabels, callExpr ) );
+			funcDecl->statements->push_back( new ExprStmt( callExpr ) );
 		} else {
 			// default ctor/dtor body is empty - add unused attribute to parameter to silence warnings
@@ -569,5 +569,5 @@
 		expr->args.push_back( new CastExpr( new VariableExpr( dst ), new ReferenceType( Type::Qualifiers(), typeDecl->base->clone() ) ) );
 		if ( src ) expr->args.push_back( new CastExpr( new VariableExpr( src ), typeDecl->base->clone() ) );
-		dcl->statements->kids.push_back( new ExprStmt( noLabels, expr ) );
+		dcl->statements->kids.push_back( new ExprStmt( expr ) );
 	};
 
@@ -664,6 +664,6 @@
 			untyped->get_args().push_back( new VariableExpr( ftype->get_parameters().back() ) );
 		}
-		function->get_statements()->get_kids().push_back( new ExprStmt( noLabels, untyped ) );
-		function->get_statements()->get_kids().push_back( new ReturnStmt( noLabels, UntypedExpr::createDeref( new VariableExpr( ftype->get_parameters().front() ) ) ) );
+		function->get_statements()->get_kids().push_back( new ExprStmt( untyped ) );
+		function->get_statements()->get_kids().push_back( new ReturnStmt( UntypedExpr::createDeref( new VariableExpr( ftype->get_parameters().front() ) ) ) );
 	}
 
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/SymTab/Autogen.h	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -104,5 +104,5 @@
 		fExpr->args.splice( fExpr->args.end(), args );
 
-		*out++ = new ExprStmt( noLabels, fExpr );
+		*out++ = new ExprStmt( fExpr );
 
 		srcParam.clearArrayIndices();
@@ -162,13 +162,13 @@
 
 		// for stmt's body, eventually containing call
-		CompoundStmt * body = new CompoundStmt( noLabels );
+		CompoundStmt * body = new CompoundStmt();
 		Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->kids ), array->base, addCast, forward );
 
 		// block containing for stmt and index variable
 		std::list<Statement *> initList;
-		CompoundStmt * block = new CompoundStmt( noLabels );
-		block->push_back( new DeclStmt( noLabels, index ) );
+		CompoundStmt * block = new CompoundStmt();
+		block->push_back( new DeclStmt( index ) );
 		if ( listInit ) block->get_kids().push_back( listInit );
-		block->push_back( new ForStmt( noLabels, initList, cond, inc, body ) );
+		block->push_back( new ForStmt( initList, cond, inc, body ) );
 
 		*out++ = block;
Index: c/SymTab/ImplementationType.cc
===================================================================
--- src/SymTab/ImplementationType.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ 	(revision )
@@ -1,114 +1,0 @@
-//
-// 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.
-//
-// ImplementationType.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 21:32:01 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Thu Mar 16 15:54:08 2017
-// Update Count     : 4
-//
-
-#include "ImplementationType.h"
-
-#include <list>                   // for list, _List_iterator, list<>::iterator
-
-#include "SymTab/Indexer.h"       // for Indexer
-#include "SynTree/Declaration.h"  // for NamedTypeDecl
-#include "SynTree/Type.h"         // for TupleType, Type, ArrayType, Pointer...
-#include "SynTree/Visitor.h"      // for Visitor
-
-
-namespace SymTab {
-	class ImplementationType : public Visitor {
-	  public:
-		ImplementationType( const SymTab::Indexer &indexer );
-
-		Type *get_result() { return result; }
-	  private:
-		virtual void visit(VoidType *voidType);
-		virtual void visit(BasicType *basicType);
-		virtual void visit(PointerType *pointerType);
-		virtual void visit(ArrayType *arrayType);
-		virtual void visit(FunctionType *functionType);
-		virtual void visit(StructInstType *aggregateUseType);
-		virtual void visit(UnionInstType *aggregateUseType);
-		virtual void visit(EnumInstType *aggregateUseType);
-		virtual void visit(TraitInstType *aggregateUseType);
-		virtual void visit(TypeInstType *aggregateUseType);
-		virtual void visit(TupleType *tupleType);
-		virtual void visit(VarArgsType *varArgsType);
-		virtual void visit(ZeroType *zeroType);
-		virtual void visit(OneType *oneType);
-
-		Type *result;			// synthesized
-		const SymTab::Indexer &indexer;
-	};
-
-	Type * implementationType( Type *type, const SymTab::Indexer& indexer ) {
-		ImplementationType implementor( indexer );
-		type->accept( implementor );
-		if ( implementor.get_result() == 0 ) {
-			return type->clone();
-		} else {
-			return implementor.get_result();
-		} // if
-	}
-
-	ImplementationType::ImplementationType( const SymTab::Indexer &indexer ) : result( 0 ), indexer( indexer ) {
-	}
-
-	void ImplementationType::visit( __attribute__((unused)) VoidType *voidType ) {}
-	void ImplementationType::visit( __attribute__((unused)) BasicType *basicType ) {}
-
-	void ImplementationType::visit(PointerType *pointerType) {
-		PointerType *newType = pointerType->clone();
-		newType->set_base( implementationType( pointerType->get_base(), indexer ) );
-		result = newType;
-	}
-
-	void ImplementationType::visit(ArrayType *arrayType) {
-		ArrayType *newType = arrayType->clone();
-		newType->set_base( implementationType( arrayType->get_base(), indexer ) );
-		result = newType;
-	}
-
-	void ImplementationType::visit( __attribute__((unused)) FunctionType *functionType ) {}
-	void ImplementationType::visit( __attribute__((unused)) StructInstType * aggregateUseType ) {}
-	void ImplementationType::visit( __attribute__((unused)) UnionInstType * aggregateUseType ) {}
-	void ImplementationType::visit( __attribute__((unused)) EnumInstType * aggregateUseType ) {}
-	void ImplementationType::visit( __attribute__((unused)) TraitInstType * aggregateUseType ) {}
-
-	void ImplementationType::visit(TypeInstType *inst) {
-		NamedTypeDecl *typeDecl = indexer.lookupType( inst->get_name() );
-		if ( typeDecl && typeDecl->get_base() ) {
-			Type *base = implementationType( typeDecl->get_base(), indexer );
-			base->get_qualifiers() |= inst->get_qualifiers();
-			result = base;
-		} // if
-	}
-
-	void ImplementationType::visit(TupleType *tupleType) {
-		std::list< Type * > types;
-		for ( std::list< Type* >::iterator i = tupleType->get_types().begin(); i != tupleType->get_types().end(); ++i ) {
-			Type *implType = implementationType( *i, indexer );
-			implType->get_qualifiers() |= tupleType->get_qualifiers();
-			types.push_back( implType );
-		} // for
-		result = new TupleType( Type::Qualifiers(), types );
-	}
-
-	void ImplementationType::visit( __attribute__((unused)) VarArgsType *varArgsType ) {}
-	void ImplementationType::visit( __attribute__((unused)) ZeroType *zeroType ) {}
-	void ImplementationType::visit( __attribute__((unused)) OneType *oneType ) {}
-} // namespace SymTab
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SymTab/ImplementationType.h
===================================================================
--- src/SymTab/ImplementationType.h	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ 	(revision )
@@ -1,37 +1,0 @@
-//
-// 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.
-//
-// ImplementationType.h -- 
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 21:35:41 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul 22 09:46:19 2017
-// Update Count     : 3
-//
-
-#pragma once
-
-class Type;
-
-namespace SymTab {
-class Indexer;
-
-	Type *implementationType( Type *, const SymTab::Indexer &indexer );
-
-	template< typename InputIterator, typename OutputIterator >
-	void implementationTypeList( InputIterator begin, InputIterator end, OutputIterator out, const SymTab::Indexer &indexer ) {
-		while ( begin != end ) {
-			*out++ = implementationType( *begin++, indexer );
-		} // while
-	}
-} // namespace SymTab
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: c/SymTab/TypeEquality.cc
===================================================================
--- src/SymTab/TypeEquality.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ 	(revision )
@@ -1,218 +1,0 @@
-//
-// 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.
-//
-// TypeEquality.cc --
-//
-// Author           : Rob Schluntz
-// Created On       : Tue Jul 07 16:28:29 2015
-// Last Modified By : Rob Schluntz
-// Last Modified On : Mon Jul 20 14:16:11 2015
-// Update Count     : 37
-//
-#include "TypeEquality.h"
-
-#include <cassert>                // for assert
-#include <list>                   // for list, list<>::iterator, _List_iterator
-#include <string>                 // for operator==, string, basic_string
-
-#include "SynTree/Constant.h"     // for Constant
-#include "SynTree/Declaration.h"  // for DeclarationWithType
-#include "SynTree/Expression.h"   // for ConstantExpr, Expression
-#include "SynTree/Type.h"         // for Type, ArrayType, FunctionType, Enum...
-#include "SynTree/Visitor.h"      // for Visitor
-
-namespace SymTab {
-	class TypeEquality : public Visitor {
-  public:
-		TypeEquality( Type * other, bool vlaErr ) : result( true ), other( other ),
-			vlaErr( vlaErr ) {}
-		bool result;
-
-  private:
-		virtual void visit( FunctionType *funcType );
-		virtual void visit( VoidType *voidType );
-		virtual void visit( BasicType *basicType );
-		virtual void visit( PointerType *pointerType );
-		virtual void visit( ArrayType *arrayType );
-		virtual void visit( StructInstType *structInst );
-		virtual void visit( UnionInstType *unionInst );
-		virtual void visit( EnumInstType *enumInst );
-		virtual void visit( TypeInstType *typeInst );
-		virtual void visit( VarArgsType *varArgsType );
-		virtual void visit( ZeroType *zeroType );
-		virtual void visit( OneType *oneType );
-
-		void handleQualifiers( Type * t );
-
-		Type * other;
-		bool vlaErr;
-	};
-
-	bool typeEquals( Type * t1, Type * t2, bool vlaErr ) {
-		TypeEquality teq( t2, vlaErr );
-		t1->accept( teq );
-		return teq.result;
-	}
-
-	void TypeEquality::handleQualifiers( Type * t ) {
-		result = result && t->get_qualifiers() == other->get_qualifiers();
-	}
-
-	void TypeEquality::visit( VoidType *voidType ) {
-		handleQualifiers( voidType );
-		if ( ! dynamic_cast< VoidType * >( other ) ) {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( BasicType *basicType ) {
-		handleQualifiers( basicType );
-		if ( BasicType * bt = dynamic_cast< BasicType * >( other ) ) {
-			result = result && basicType->get_kind() == bt->get_kind();
-		} else {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( PointerType *pointerType ) {
-		handleQualifiers( pointerType );
-		if ( PointerType * pt = dynamic_cast< PointerType * >( other ) ) {
-			other = pt->get_base();
-			pointerType->get_base()->accept( *this );
-		} else {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( ArrayType *arrayType ) {
-		handleQualifiers( arrayType );
-
-		if ( ArrayType * at = dynamic_cast< ArrayType * >( other ) ) {
-			// to be equal, array types must both be VLA or both not VLA
-			// and must both have a dimension expression or not have a dimension
-			result = result	&& arrayType->get_isVarLen() == at->get_isVarLen()
-				&& ((arrayType->get_dimension() != 0 && at->get_dimension() != 0)
-					|| (arrayType->get_dimension() == 0 && at->get_dimension() == 0));
-
-			if ( vlaErr ) {
-				// useful for comparing typedef types - in this case, we
-				// want types to appear distinct if either is a VLA type
-				if ( arrayType->get_isVarLen() || at->get_isVarLen() ) {
-					result = false;
-				}
-			}
-
-			if ( ! arrayType->get_isVarLen() && ! at->get_isVarLen() &&
-				arrayType->get_dimension() != 0 && at->get_dimension() != 0 ) {
-				ConstantExpr * ce1 = dynamic_cast< ConstantExpr * >( arrayType->get_dimension() );
-				ConstantExpr * ce2 = dynamic_cast< ConstantExpr * >( at->get_dimension() );
-				assert(ce1 && ce2);
-
-				Constant * c1 = ce1->get_constant();
-				Constant * c2 = ce2->get_constant();
-
-				result = result && c1->get_value() == c2->get_value();
-			}
-
-			other = at->get_base();
-			arrayType->get_base()->accept( *this );
-		} else {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( FunctionType *funcType ) {
-		handleQualifiers( funcType );
-
-		if ( FunctionType * ft = dynamic_cast< FunctionType * >( other ) ) {
-			// function types must have the same number of return types
-			// and parameters to be equivalent
-			result = result && funcType->get_returnVals().size() == ft->get_returnVals().size()
-				&& funcType->get_parameters().size() == ft->get_parameters().size()
-				&& funcType->get_isVarArgs() == ft->get_isVarArgs();
-
-			std::list< DeclarationWithType * >::iterator it1, it2;
-
-			// return types must be equivalent
-			it1 = funcType->get_returnVals().begin();
-			it2 = ft->get_returnVals().begin();
-			for ( ; it1 != funcType->get_returnVals().end(); ++it1, ++it2 ) {
-				if ( ! result ) return;
-				other = (*it2)->get_type();
-				(*it1)->get_type()->accept( *this );
-			}
-
-			// parameter types must be equivalent
-			it1 = funcType->get_parameters().begin();
-			it2 = ft->get_parameters().begin();
-			for ( ; it1 != funcType->get_parameters().end(); ++it1, ++it2 ) {
-				if ( ! result ) return;
-				other = (*it2)->get_type();
-				(*it1)->get_type()->accept( *this );
-			}
-		} else {
-			result = false;
-		}
-	}
-
-	// aggregate types only need to have the same name
-	void TypeEquality::visit( StructInstType *structInst )  {
-		handleQualifiers( structInst );
-		if ( StructInstType * st = dynamic_cast< StructInstType * >( other ) ) {
-			result = result && structInst->get_name() == st->get_name();
-		} else {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( UnionInstType *unionInst ) {
-		handleQualifiers( unionInst );
-		if ( UnionInstType * ut = dynamic_cast< UnionInstType * >( other ) ) {
-			result = result && unionInst->get_name() == ut->get_name();
-		} else {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( EnumInstType *enumInst ) {
-		handleQualifiers( enumInst );
-		if ( EnumInstType * et = dynamic_cast< EnumInstType * >( other ) ) {
-			result = result && enumInst->get_name() == et->get_name();
-		} else {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( TypeInstType *typeInst ) {
-		handleQualifiers( typeInst );
-		if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( other ) ) {
-			result = result && typeInst->get_name() == tt->get_name();
-		} else {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( VarArgsType *varArgsType ) {
-		handleQualifiers( varArgsType );
-		if ( ! dynamic_cast< VarArgsType * >( other ) ) {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( ZeroType *zeroType ) {
-		handleQualifiers( zeroType );
-		if ( ! dynamic_cast< ZeroType * >( other ) ) {
-			result = false;
-		}
-	}
-
-	void TypeEquality::visit( OneType *oneType ) {
-		handleQualifiers( oneType );
-		if ( ! dynamic_cast< OneType * >( other ) ) {
-			result = false;
-		}
-	}
-} // namespace SymTab
Index: c/SymTab/TypeEquality.h
===================================================================
--- src/SymTab/TypeEquality.h	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ 	(revision )
@@ -1,23 +1,0 @@
-//
-// 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.
-//
-// TypeEquality.h --
-//
-// Author           : Rob Schluntz
-// Created On       : Tue Jul 07 16:30:07 2015
-// Last Modified By : Rob Schluntz
-// Last Modified On : Wed Jul 08 12:41:15 2015
-// Update Count     : 6
-//
-
-class Type;
-
-namespace SymTab {
-  // compare types t1 and t2 for equality
-  // if vlaErr is true, then if at least one of the types is a
-  // variable-length array type, then the result will be false
-  bool typeEquals( Type * t1, Type * t2, bool vlaErr = false );
-} // namespace SymTab
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/SymTab/Validate.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -81,30 +81,18 @@
 
 namespace SymTab {
-	class HoistStruct final : public Visitor {
-		template< typename Visitor >
-		friend void acceptAndAdd( std::list< Declaration * > &translationUnit, Visitor &visitor );
-	    template< typename Visitor >
-	    friend void addVisitStatementList( std::list< Statement* > &stmts, Visitor &visitor );
-	  public:
+	struct HoistStruct final : public WithDeclsToAdd, public WithGuards {
 		/// Flattens nested struct types
 		static void hoistStruct( std::list< Declaration * > &translationUnit );
 
-		std::list< Declaration * > &get_declsToAdd() { return declsToAdd; }
-
-		virtual void visit( EnumInstType *enumInstType );
-		virtual void visit( StructInstType *structInstType );
-		virtual void visit( UnionInstType *unionInstType );
-		virtual void visit( StructDecl *aggregateDecl );
-		virtual void visit( UnionDecl *aggregateDecl );
-
-		virtual void visit( CompoundStmt *compoundStmt );
-		virtual void visit( SwitchStmt *switchStmt );
+		void previsit( EnumInstType * enumInstType );
+		void previsit( StructInstType * structInstType );
+		void previsit( UnionInstType * unionInstType );
+		void previsit( StructDecl * aggregateDecl );
+		void previsit( UnionDecl * aggregateDecl );
+
 	  private:
-		HoistStruct();
-
 		template< typename AggDecl > void handleAggregate( AggDecl *aggregateDecl );
 
-		std::list< Declaration * > declsToAdd, declsToAddAfter;
-		bool inStruct;
+		bool inStruct = false;
 	};
 
@@ -305,9 +293,6 @@
 
 	void HoistStruct::hoistStruct( std::list< Declaration * > &translationUnit ) {
-		HoistStruct hoister;
-		acceptAndAdd( translationUnit, hoister );
-	}
-
-	HoistStruct::HoistStruct() : inStruct( false ) {
+		PassVisitor<HoistStruct> hoister;
+		acceptAll( translationUnit, hoister );
 	}
 
@@ -320,47 +305,37 @@
 		if ( inStruct ) {
 			// Add elements in stack order corresponding to nesting structure.
-			declsToAdd.push_front( aggregateDecl );
-			Visitor::visit( aggregateDecl );
+			declsToAddBefore.push_front( aggregateDecl );
 		} else {
+			GuardValue( inStruct );
 			inStruct = true;
-			Visitor::visit( aggregateDecl );
-			inStruct = false;
 		} // if
 		// Always remove the hoisted aggregate from the inner structure.
-		filter( aggregateDecl->get_members(), isStructOrUnion, false );
-	}
-
-	void HoistStruct::visit( EnumInstType *structInstType ) {
-		if ( structInstType->get_baseEnum() ) {
-			declsToAdd.push_front( structInstType->get_baseEnum() );
-		}
-	}
-
-	void HoistStruct::visit( StructInstType *structInstType ) {
-		if ( structInstType->get_baseStruct() ) {
-			declsToAdd.push_front( structInstType->get_baseStruct() );
-		}
-	}
-
-	void HoistStruct::visit( UnionInstType *structInstType ) {
-		if ( structInstType->get_baseUnion() ) {
-			declsToAdd.push_front( structInstType->get_baseUnion() );
-		}
-	}
-
-	void HoistStruct::visit( StructDecl *aggregateDecl ) {
+		GuardAction( [this, aggregateDecl]() { filter( aggregateDecl->members, isStructOrUnion, false ); } );
+	}
+
+	void HoistStruct::previsit( EnumInstType * inst ) {
+		if ( inst->baseEnum ) {
+			declsToAddBefore.push_front( inst->baseEnum );
+		}
+	}
+
+	void HoistStruct::previsit( StructInstType * inst ) {
+		if ( inst->baseStruct ) {
+			declsToAddBefore.push_front( inst->baseStruct );
+		}
+	}
+
+	void HoistStruct::previsit( UnionInstType * inst ) {
+		if ( inst->baseUnion ) {
+			declsToAddBefore.push_front( inst->baseUnion );
+		}
+	}
+
+	void HoistStruct::previsit( StructDecl * aggregateDecl ) {
 		handleAggregate( aggregateDecl );
 	}
 
-	void HoistStruct::visit( UnionDecl *aggregateDecl ) {
+	void HoistStruct::previsit( UnionDecl * aggregateDecl ) {
 		handleAggregate( aggregateDecl );
-	}
-
-	void HoistStruct::visit( CompoundStmt *compoundStmt ) {
-		addVisit( compoundStmt, *this );
-	}
-
-	void HoistStruct::visit( SwitchStmt *switchStmt ) {
-		addVisit( switchStmt, *this );
 	}
 
Index: src/SymTab/module.mk
===================================================================
--- src/SymTab/module.mk	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/SymTab/module.mk	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -19,5 +19,3 @@
        SymTab/Validate.cc \
        SymTab/FixFunction.cc \
-       SymTab/ImplementationType.cc \
-       SymTab/TypeEquality.cc \
        SymTab/Autogen.cc
Index: src/SynTree/CompoundStmt.cc
===================================================================
--- src/SynTree/CompoundStmt.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/SynTree/CompoundStmt.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -28,8 +28,8 @@
 using std::endl;
 
-CompoundStmt::CompoundStmt( std::list<Label> labels ) : Statement( labels ) {
+CompoundStmt::CompoundStmt() : Statement() {
 }
 
-CompoundStmt::CompoundStmt( std::list<Statement *> stmts ) : Statement( noLabels ), kids( stmts ) {
+CompoundStmt::CompoundStmt( std::list<Statement *> stmts ) : Statement(), kids( stmts ) {
 }
 
Index: src/SynTree/DeclStmt.cc
===================================================================
--- src/SynTree/DeclStmt.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/SynTree/DeclStmt.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -23,5 +23,5 @@
 #include "SynTree/Label.h"   // for Label
 
-DeclStmt::DeclStmt( std::list<Label> labels, Declaration *decl ) : Statement( labels ), decl( decl ) {
+DeclStmt::DeclStmt( Declaration *decl ) : Statement(), decl( decl ) {
 }
 
Index: src/SynTree/Statement.cc
===================================================================
--- src/SynTree/Statement.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/SynTree/Statement.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -32,5 +32,5 @@
 using std::endl;
 
-Statement::Statement( std::list<Label> labels ) : labels( labels ) {}
+Statement::Statement( const std::list<Label> & labels ) : labels( labels ) {}
 
 void Statement::print( std::ostream & os, Indenter ) const {
@@ -46,5 +46,5 @@
 Statement::~Statement() {}
 
-ExprStmt::ExprStmt( std::list<Label> labels, Expression *expr ) : Statement( labels ), expr( expr ) {}
+ExprStmt::ExprStmt( Expression *expr ) : Statement(), expr( expr ) {}
 
 ExprStmt::ExprStmt( const ExprStmt &other ) : Statement( other ), expr( maybeClone( other.expr ) ) {}
@@ -60,5 +60,5 @@
 
 
-AsmStmt::AsmStmt( std::list<Label> labels, bool voltile, Expression *instruction, std::list<Expression *> output, std::list<Expression *> input, std::list<ConstantExpr *> clobber, std::list<Label> gotolabels ) : Statement( labels ), voltile( voltile ), instruction( instruction ), output( output ), input( input ), clobber( clobber ), gotolabels( gotolabels ) {}
+AsmStmt::AsmStmt( bool voltile, Expression *instruction, std::list<Expression *> output, std::list<Expression *> input, std::list<ConstantExpr *> clobber, std::list<Label> gotolabels ) : Statement(), voltile( voltile ), instruction( instruction ), output( output ), input( input ), clobber( clobber ), gotolabels( gotolabels ) {}
 
 AsmStmt::AsmStmt( const AsmStmt & other ) : Statement( other ), voltile( other.voltile ), instruction( maybeClone( other.instruction ) ), gotolabels( other.gotolabels ) {
@@ -96,6 +96,6 @@
 const char *BranchStmt::brType[] = { "Goto", "Break", "Continue" };
 
-BranchStmt::BranchStmt( std::list<Label> labels, Label target, Type type ) throw ( SemanticError ) :
-	Statement( labels ), originalTarget( target ), target( target ), computedTarget( nullptr ), type( type ) {
+BranchStmt::BranchStmt( Label target, Type type ) throw ( SemanticError ) :
+	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() ) {
@@ -104,6 +104,6 @@
 }
 
-BranchStmt::BranchStmt( std::list<Label> labels, Expression *computedTarget, Type type ) throw ( SemanticError ) :
-	Statement( labels ), computedTarget( computedTarget ), type( type ) {
+BranchStmt::BranchStmt( Expression *computedTarget, Type type ) throw ( SemanticError ) :
+	Statement(), computedTarget( computedTarget ), type( type ) {
 	if ( type != BranchStmt::Goto || computedTarget == nullptr ) {
 		throw SemanticError("Computed target not valid in branch statement");
@@ -118,5 +118,5 @@
 }
 
-ReturnStmt::ReturnStmt( std::list<Label> labels, Expression *expr ) : Statement( labels ), expr( expr ) {}
+ReturnStmt::ReturnStmt( Expression *expr ) : Statement(), expr( expr ) {}
 
 ReturnStmt::ReturnStmt( const ReturnStmt & other ) : Statement( other ), expr( maybeClone( other.expr ) ) {}
@@ -135,6 +135,6 @@
 }
 
-IfStmt::IfStmt( std::list<Label> labels, Expression *condition, Statement *thenPart, Statement *elsePart, std::list<Statement *> initialization ):
-	Statement( labels ), condition( condition ), thenPart( thenPart ), elsePart( elsePart ), initialization( initialization ) {}
+IfStmt::IfStmt( Expression *condition, Statement *thenPart, Statement *elsePart, std::list<Statement *> initialization ):
+	Statement(), condition( condition ), thenPart( thenPart ), elsePart( elsePart ), initialization( initialization ) {}
 
 IfStmt::IfStmt( const IfStmt & other ) :
@@ -176,6 +176,6 @@
 }
 
-SwitchStmt::SwitchStmt( std::list<Label> labels, Expression * condition, const std::list<Statement *> &statements ):
-	Statement( labels ), condition( condition ), statements( statements ) {
+SwitchStmt::SwitchStmt( Expression * condition, const std::list<Statement *> &statements ):
+	Statement(), condition( condition ), statements( statements ) {
 }
 
@@ -201,6 +201,6 @@
 }
 
-CaseStmt::CaseStmt( std::list<Label> labels, Expression *condition, const std::list<Statement *> &statements, bool deflt ) throw ( SemanticError ) :
-	Statement( labels ), condition( condition ), stmts( statements ), _isDefault( deflt ) {
+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);
 }
@@ -216,6 +216,8 @@
 }
 
-CaseStmt * CaseStmt::makeDefault( std::list<Label> labels, std::list<Statement *> stmts ) {
-	return new CaseStmt( labels, 0, stmts, true );
+CaseStmt * CaseStmt::makeDefault( const std::list<Label> & labels, std::list<Statement *> stmts ) {
+	CaseStmt * stmt = new CaseStmt( nullptr, stmts, true );
+	stmt->labels = labels;
+	return stmt;
 }
 
@@ -233,6 +235,6 @@
 }
 
-WhileStmt::WhileStmt( std::list<Label> labels, Expression *condition, Statement *body, bool isDoWhile ):
-	Statement( labels ), condition( condition), body( body), isDoWhile( isDoWhile) {
+WhileStmt::WhileStmt( Expression *condition, Statement *body, bool isDoWhile ):
+	Statement(), condition( condition), body( body), isDoWhile( isDoWhile) {
 }
 
@@ -255,6 +257,6 @@
 }
 
-ForStmt::ForStmt( std::list<Label> labels, std::list<Statement *> initialization, Expression *condition, Expression *increment, Statement *body ):
-	Statement( labels ), initialization( initialization ), condition( condition ), increment( increment ), body( body ) {
+ForStmt::ForStmt( std::list<Statement *> initialization, Expression *condition, Expression *increment, Statement *body ):
+	Statement(), initialization( initialization ), condition( condition ), increment( increment ), body( body ) {
 }
 
@@ -302,6 +304,6 @@
 }
 
-ThrowStmt::ThrowStmt( std::list<Label> labels, Kind kind, Expression * expr, Expression * target ) :
-		Statement( labels ), kind(kind), expr(expr), target(target)	{
+ThrowStmt::ThrowStmt( Kind kind, Expression * expr, Expression * target ) :
+		Statement(), kind(kind), expr(expr), target(target)	{
 	assertf(Resume == kind || nullptr == target, "Non-local termination throw is not accepted." );
 }
@@ -326,6 +328,6 @@
 }
 
-TryStmt::TryStmt( std::list<Label> labels, CompoundStmt *tryBlock, std::list<CatchStmt *> &handlers, FinallyStmt *finallyBlock ) :
-	Statement( labels ), block( tryBlock ),  handlers( handlers ), finallyBlock( finallyBlock ) {
+TryStmt::TryStmt( CompoundStmt *tryBlock, std::list<CatchStmt *> &handlers, FinallyStmt *finallyBlock ) :
+	Statement(), block( tryBlock ),  handlers( handlers ), finallyBlock( finallyBlock ) {
 }
 
@@ -359,6 +361,6 @@
 }
 
-CatchStmt::CatchStmt( std::list<Label> labels, Kind kind, Declaration *decl, Expression *cond, Statement *body ) :
-	Statement( labels ), kind ( kind ), decl ( decl ), cond ( cond ), body( body ) {
+CatchStmt::CatchStmt( Kind kind, Declaration *decl, Expression *cond, Statement *body ) :
+	Statement(), kind ( kind ), decl ( decl ), cond ( cond ), body( body ) {
 		assertf( decl, "Catch clause must have a declaration." );
 }
@@ -391,6 +393,5 @@
 
 
-FinallyStmt::FinallyStmt( std::list<Label> labels, CompoundStmt *block ) : Statement( labels ), block( block ) {
-	assert( labels.empty() ); // finally statement cannot be labeled
+FinallyStmt::FinallyStmt( CompoundStmt *block ) : Statement(), block( block ) {
 }
 
@@ -408,5 +409,5 @@
 }
 
-WaitForStmt::WaitForStmt( std::list<Label> labels ) : Statement( labels ) {
+WaitForStmt::WaitForStmt() : Statement() {
 	timeout.time      = nullptr;
 	timeout.statement = nullptr;
@@ -455,6 +456,6 @@
 }
 
-NullStmt::NullStmt( std::list<Label> labels ) : Statement( labels ) {}
-NullStmt::NullStmt() : Statement( std::list<Label>() ) {}
+NullStmt::NullStmt( const std::list<Label> & labels ) : Statement( labels ) {
+}
 
 void NullStmt::print( std::ostream &os, Indenter ) const {
@@ -462,5 +463,5 @@
 }
 
-ImplicitCtorDtorStmt::ImplicitCtorDtorStmt( Statement * callStmt ) : Statement( std::list<Label>() ), callStmt( callStmt ) {
+ImplicitCtorDtorStmt::ImplicitCtorDtorStmt( Statement * callStmt ) : Statement(), callStmt( callStmt ) {
 	assert( callStmt );
 }
Index: src/SynTree/Statement.h
===================================================================
--- src/SynTree/Statement.h	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/SynTree/Statement.h	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -37,5 +37,5 @@
 	std::list<Label> labels;
 
-	Statement( std::list<Label> labels );
+	Statement( const std::list<Label> & labels = {} );
 	virtual ~Statement();
 
@@ -53,5 +53,5 @@
 	std::list<Statement*> kids;
 
-	CompoundStmt( std::list<Label> labels );
+	CompoundStmt();
 	CompoundStmt( std::list<Statement *> stmts );
 	CompoundStmt( const CompoundStmt &other );
@@ -70,6 +70,5 @@
 class NullStmt : public Statement {
   public:
-	NullStmt();
-	NullStmt( std::list<Label> labels );
+	NullStmt( const std::list<Label> & labels = {} );
 
 	virtual NullStmt *clone() const override { return new NullStmt( *this ); }
@@ -83,5 +82,5 @@
 	Expression *expr;
 
-	ExprStmt( std::list<Label> labels, Expression *expr );
+	ExprStmt( Expression *expr );
 	ExprStmt( const ExprStmt &other );
 	virtual ~ExprStmt();
@@ -104,5 +103,5 @@
 	std::list<Label> gotolabels;
 
-	AsmStmt( std::list<Label> labels, bool voltile, Expression *instruction, std::list<Expression *> output, std::list<Expression *> input, std::list<ConstantExpr *> clobber, std::list<Label> gotolabels );
+	AsmStmt( bool voltile, Expression *instruction, std::list<Expression *> output, std::list<Expression *> input, std::list<ConstantExpr *> clobber, std::list<Label> gotolabels );
 	AsmStmt( const AsmStmt &other );
 	virtual ~AsmStmt();
@@ -134,5 +133,5 @@
 	std::list<Statement *> initialization;
 
-	IfStmt( std::list<Label> labels, Expression *condition, Statement *thenPart, Statement *elsePart,
+	IfStmt( Expression *condition, Statement *thenPart, Statement *elsePart,
 			std::list<Statement *> initialization = std::list<Statement *>() );
 	IfStmt( const IfStmt &other );
@@ -158,5 +157,5 @@
 	std::list<Statement *> statements;
 
-	SwitchStmt( std::list<Label> labels, Expression *condition, const std::list<Statement *> &statements );
+	SwitchStmt( Expression *condition, const std::list<Statement *> &statements );
 	SwitchStmt( const SwitchStmt &other );
 	virtual ~SwitchStmt();
@@ -180,9 +179,9 @@
 	std::list<Statement *> stmts;
 
-	CaseStmt( std::list<Label> labels, Expression *conditions, const std::list<Statement *> &stmts, bool isdef = false ) throw(SemanticError);
+	CaseStmt( Expression *conditions, const std::list<Statement *> &stmts, bool isdef = false ) throw(SemanticError);
 	CaseStmt( const CaseStmt &other );
 	virtual ~CaseStmt();
 
-	static CaseStmt * makeDefault( std::list<Label> labels = std::list<Label>(), std::list<Statement *> stmts = std::list<Statement *>() );
+	static CaseStmt * makeDefault( const std::list<Label> & labels = {}, std::list<Statement *> stmts = std::list<Statement *>() );
 
 	bool isDefault() const { return _isDefault; }
@@ -210,5 +209,5 @@
 	bool isDoWhile;
 
-	WhileStmt( std::list<Label> labels, Expression *condition,
+	WhileStmt( Expression *condition,
 	       Statement *body, bool isDoWhile = false );
 	WhileStmt( const WhileStmt &other );
@@ -235,5 +234,5 @@
 	Statement *body;
 
-	ForStmt( std::list<Label> labels, std::list<Statement *> initialization,
+	ForStmt( std::list<Statement *> initialization,
 	     Expression *condition = 0, Expression *increment = 0, Statement *body = 0 );
 	ForStmt( const ForStmt &other );
@@ -264,6 +263,6 @@
 	Type type;
 
-	BranchStmt( std::list<Label> labels, Label target, Type ) throw (SemanticError);
-	BranchStmt( std::list<Label> labels, Expression *computedTarget, Type ) throw (SemanticError);
+	BranchStmt( Label target, Type ) throw (SemanticError);
+	BranchStmt( Expression *computedTarget, Type ) throw (SemanticError);
 
 	Label get_originalTarget() { return originalTarget; }
@@ -289,5 +288,5 @@
 	Expression *expr;
 
-	ReturnStmt( std::list<Label> labels, Expression *expr );
+	ReturnStmt( Expression *expr );
 	ReturnStmt( const ReturnStmt &other );
 	virtual ~ReturnStmt();
@@ -310,5 +309,5 @@
 	Expression * target;
 
-	ThrowStmt( std::list<Label> labels, Kind kind, Expression * expr, Expression * target = nullptr );
+	ThrowStmt( Kind kind, Expression * expr, Expression * target = nullptr );
 	ThrowStmt( const ThrowStmt &other );
 	virtual ~ThrowStmt();
@@ -332,5 +331,5 @@
 	FinallyStmt * finallyBlock;
 
-	TryStmt( std::list<Label> labels, CompoundStmt *tryBlock, std::list<CatchStmt *> &handlers, FinallyStmt *finallyBlock = 0 );
+	TryStmt( CompoundStmt *tryBlock, std::list<CatchStmt *> &handlers, FinallyStmt *finallyBlock = 0 );
 	TryStmt( const TryStmt &other );
 	virtual ~TryStmt();
@@ -358,5 +357,5 @@
 	Statement *body;
 
-	CatchStmt( std::list<Label> labels, Kind kind, Declaration *decl,
+	CatchStmt( Kind kind, Declaration *decl,
 	           Expression *cond, Statement *body );
 	CatchStmt( const CatchStmt &other );
@@ -381,5 +380,5 @@
 	CompoundStmt *block;
 
-	FinallyStmt( std::list<Label> labels, CompoundStmt *block );
+	FinallyStmt( CompoundStmt *block );
 	FinallyStmt( const FinallyStmt &other );
 	virtual ~FinallyStmt();
@@ -408,5 +407,5 @@
 	};
 
-	WaitForStmt( std::list<Label> labels = noLabels );
+	WaitForStmt();
 	WaitForStmt( const WaitForStmt & );
 	virtual ~WaitForStmt();
@@ -438,5 +437,5 @@
 	Declaration *decl;
 
-	DeclStmt( std::list<Label> labels, Declaration *decl );
+	DeclStmt( Declaration *decl );
 	DeclStmt( const DeclStmt &other );
 	virtual ~DeclStmt();
Index: src/SynTree/TupleExpr.cc
===================================================================
--- src/SynTree/TupleExpr.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/SynTree/TupleExpr.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -23,5 +23,5 @@
 #include "Declaration.h"        // for ObjectDecl
 #include "Expression.h"         // for Expression, TupleExpr, TupleIndexExpr
-#include "SynTree/Label.h"      // for Label, noLabels
+#include "SynTree/Label.h"      // for Label
 #include "SynTree/Statement.h"  // for CompoundStmt, DeclStmt, ExprStmt, Sta...
 #include "Tuples/Tuples.h"      // for makeTupleType
@@ -89,12 +89,12 @@
 	// convert internally into a StmtExpr which contains the declarations and produces the tuple of the assignments
 	set_result( Tuples::makeTupleType( assigns ) );
-	CompoundStmt * compoundStmt = new CompoundStmt( noLabels );
+	CompoundStmt * compoundStmt = new CompoundStmt();
 	std::list< Statement * > & stmts = compoundStmt->get_kids();
 	for ( ObjectDecl * obj : tempDecls ) {
-		stmts.push_back( new DeclStmt( noLabels, obj ) );
+		stmts.push_back( new DeclStmt( obj ) );
 	}
 	TupleExpr * tupleExpr = new TupleExpr( assigns );
 	assert( tupleExpr->get_result() );
-	stmts.push_back( new ExprStmt( noLabels, tupleExpr ) );
+	stmts.push_back( new ExprStmt( tupleExpr ) );
 	stmtExpr = new StmtExpr( compoundStmt );
 }
Index: src/Tuples/TupleAssignment.cc
===================================================================
--- src/Tuples/TupleAssignment.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/Tuples/TupleAssignment.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -23,4 +23,5 @@
 
 #include "CodeGen/OperatorTable.h"
+#include "Common/PassVisitor.h"
 #include "Common/UniqueName.h"             // for UniqueName
 #include "Common/utility.h"                // for zipWith
@@ -61,5 +62,5 @@
 		struct Matcher {
 		  public:
-			Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const 
+			Matcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, const
 				ResolvExpr::AltList& rhs );
 			virtual ~Matcher() {}
@@ -75,5 +76,5 @@
 		struct MassAssignMatcher : public Matcher {
 		  public:
-			MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, 
+			MassAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
 				const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
 			virtual void match( std::list< Expression * > &out );
@@ -82,5 +83,5 @@
 		struct MultipleAssignMatcher : public Matcher {
 		  public:
-			MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs, 
+			MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList& lhs,
 				const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
 			virtual void match( std::list< Expression * > &out );
@@ -119,5 +120,5 @@
 	}
 
-	void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr, 
+	void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr,
 				std::vector<ResolvExpr::AlternativeFinder> &args ) {
 		TupleAssignSpotter spotter( currentFinder );
@@ -128,5 +129,5 @@
 		: currentFinder(f) {}
 
-	void TupleAssignSpotter::spot( UntypedExpr * expr, 
+	void TupleAssignSpotter::spot( UntypedExpr * expr,
 			std::vector<ResolvExpr::AlternativeFinder> &args ) {
 		if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
@@ -137,5 +138,5 @@
 				if ( args.size() == 0 ) return;
 
-				// if an assignment only takes 1 argument, that's odd, but maybe someone wrote 
+				// if an assignment only takes 1 argument, that's odd, but maybe someone wrote
 				// the function, in which case AlternativeFinder will handle it normally
 				if ( args.size() == 1 && CodeGen::isAssignment( fname ) ) return;
@@ -146,11 +147,11 @@
 					if ( ! refToTuple(lhsAlt.expr) ) continue;
 
-					// explode is aware of casts - ensure every LHS expression is sent into explode 
+					// explode is aware of casts - ensure every LHS expression is sent into explode
 					// with a reference cast
-					// xxx - this seems to change the alternatives before the normal 
+					// xxx - this seems to change the alternatives before the normal
 					//  AlternativeFinder flow; maybe this is desired?
 					if ( ! dynamic_cast<CastExpr*>( lhsAlt.expr ) ) {
-						lhsAlt.expr = new CastExpr( lhsAlt.expr, 
-								new ReferenceType( Type::Qualifiers(), 
+						lhsAlt.expr = new CastExpr( lhsAlt.expr,
+								new ReferenceType( Type::Qualifiers(),
 									lhsAlt.expr->get_result()->clone() ) );
 					}
@@ -160,9 +161,9 @@
 					explode( lhsAlt, currentFinder.get_indexer(), back_inserter(lhs), true );
 					for ( ResolvExpr::Alternative& alt : lhs ) {
-						// each LHS value must be a reference - some come in with a cast expression, 
+						// each LHS value must be a reference - some come in with a cast expression,
 						// if not just cast to reference here
 						if ( ! dynamic_cast<ReferenceType*>( alt.expr->get_result() ) ) {
-							alt.expr = new CastExpr( alt.expr, 
-								new ReferenceType( Type::Qualifiers(), 
+							alt.expr = new CastExpr( alt.expr,
+								new ReferenceType( Type::Qualifiers(),
 									alt.expr->get_result()->clone() ) );
 						}
@@ -178,10 +179,10 @@
 						// TODO build iterative version of this instead of using combos
 						std::vector< ResolvExpr::AltList > rhsAlts;
-						combos( std::next(args.begin(), 1), args.end(), 
+						combos( std::next(args.begin(), 1), args.end(),
 							std::back_inserter( rhsAlts ) );
 						for ( const ResolvExpr::AltList& rhsAlt : rhsAlts ) {
 							// multiple assignment
 							ResolvExpr::AltList rhs;
-							explode( rhsAlt, currentFinder.get_indexer(), 
+							explode( rhsAlt, currentFinder.get_indexer(),
 								std::back_inserter(rhs), true );
 							matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) );
@@ -193,5 +194,5 @@
 							if ( isTuple(rhsAlt.expr) ) {
 								// multiple assignment
-								explode( rhsAlt, currentFinder.get_indexer(),  
+								explode( rhsAlt, currentFinder.get_indexer(),
 									std::back_inserter(rhs), true );
 								matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) );
@@ -222,5 +223,5 @@
 		ResolvExpr::AltList current;
 		// now resolve new assignments
-		for ( std::list< Expression * >::iterator i = new_assigns.begin(); 
+		for ( std::list< Expression * >::iterator i = new_assigns.begin();
 				i != new_assigns.end(); ++i ) {
 			PRINT(
@@ -229,5 +230,5 @@
 			)
 
-			ResolvExpr::AlternativeFinder finder{ currentFinder.get_indexer(), 
+			ResolvExpr::AlternativeFinder finder{ currentFinder.get_indexer(),
 				currentFinder.get_environ() };
 			try {
@@ -253,11 +254,11 @@
 		// xxx -- was push_front
 		currentFinder.get_alternatives().push_back( ResolvExpr::Alternative(
-			new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv, 
+			new TupleAssignExpr(solved_assigns, matcher->tmpDecls), matcher->compositeEnv,
 			ResolvExpr::sumCost( current ) + matcher->baseCost ) );
 	}
 
-	TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter, 
-		const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs ) 
-	: lhs(lhs), rhs(rhs), spotter(spotter), 
+	TupleAssignSpotter::Matcher::Matcher( TupleAssignSpotter &spotter,
+		const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs )
+	: lhs(lhs), rhs(rhs), spotter(spotter),
 	  baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) {
 		simpleCombineEnvironments( lhs.begin(), lhs.end(), compositeEnv );
@@ -277,9 +278,8 @@
 	// xxx - maybe this should happen in alternative finder for every StmtExpr?
 	// xxx - it's possible that these environments could contain some useful information. Maybe the right thing to do is aggregate the environments and pass the aggregate back to be added into the compositeEnv
-	struct EnvRemover : public Visitor {
-		virtual void visit( ExprStmt * stmt ) {
-			delete stmt->get_expr()->get_env();
-			stmt->get_expr()->set_env( nullptr );
-			Visitor::visit( stmt );
+	struct EnvRemover {
+		void previsit( ExprStmt * stmt ) {
+			delete stmt->expr->env;
+			stmt->expr->env = nullptr;
 		}
 	};
@@ -293,5 +293,5 @@
 			ret->set_init( ctorInit );
 			ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object
-			EnvRemover rm; // remove environments from subexpressions of StmtExprs
+			PassVisitor<EnvRemover> rm; // remove environments from subexpressions of StmtExprs
 			ctorInit->accept( rm );
 		}
Index: src/Tuples/TupleExpansion.cc
===================================================================
--- src/Tuples/TupleExpansion.cc	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/Tuples/TupleExpansion.cc	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -315,15 +315,14 @@
 	namespace {
 		/// determines if impurity (read: side-effects) may exist in a piece of code. Currently gives a very crude approximation, wherein any function call expression means the code may be impure
-		class ImpurityDetector : public Visitor {
-		public:
+		struct ImpurityDetector : public WithShortCircuiting {
 			ImpurityDetector( bool ignoreUnique ) : ignoreUnique( ignoreUnique ) {}
 
-			typedef Visitor Parent;
-			virtual void visit( ApplicationExpr * appExpr ) {
+			void previsit( ApplicationExpr * appExpr ) {
+				visit_children = false;
 				if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
 					if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
 						if ( function->get_name() == "*?" || function->get_name() == "?[?]" ) {
 							// intrinsic dereference, subscript are pure, but need to recursively look for impurity
-							Parent::visit( appExpr );
+							visit_children = true;
 							return;
 						}
@@ -332,13 +331,13 @@
 				maybeImpure = true;
 			}
-			virtual void visit( UntypedExpr * ) { maybeImpure = true; }
-			virtual void visit( UniqueExpr * unq ) {
+			void previsit( UntypedExpr * ) { maybeImpure = true; visit_children = false; }
+			void previsit( UniqueExpr * ) {
 				if ( ignoreUnique ) {
 					// bottom out at unique expression.
 					// The existence of a unique expression doesn't change the purity of an expression.
 					// That is, even if the wrapped expression is impure, the wrapper protects the rest of the expression.
+					visit_children = false;
 					return;
 				}
-				maybeAccept( unq->expr, *this );
 			}
 
@@ -349,13 +348,13 @@
 
 	bool maybeImpure( Expression * expr ) {
-		ImpurityDetector detector( false );
+		PassVisitor<ImpurityDetector> detector( false );
 		expr->accept( detector );
-		return detector.maybeImpure;
+		return detector.pass.maybeImpure;
 	}
 
 	bool maybeImpureIgnoreUnique( Expression * expr ) {
-		ImpurityDetector detector( true );
+		PassVisitor<ImpurityDetector> detector( true );
 		expr->accept( detector );
-		return detector.maybeImpure;
+		return detector.pass.maybeImpure;
 	}
 } // namespace Tuples
Index: src/tests/except-mac.h
===================================================================
--- src/tests/except-mac.h	(revision f3b9efcc8e56c4be21e2e133209b16b5760e0cdb)
+++ src/tests/except-mac.h	(revision 86ad27677447bd2560527943819518de920d1004)
@@ -30,5 +30,5 @@
 	size_t size; \
 	void (*copy)(except_name *this, except_name * other); \
-	void (*free)(except_name *this); \
+	void (*free)(except_name &this); \
 	const char * (*msg)(except_name *this); \
 	__VA_ARGS__ \
@@ -42,5 +42,5 @@
 // In each constructor the vtable must be initialized.
 #define VTABLE_INIT(this_name,except_name) \
-this_name->virtual_table = &INSTANCE(except_name)
+this_name.virtual_table = &INSTANCE(except_name)
 
 // Declare the vtable instance. This should end an exception declaration.
@@ -73,5 +73,5 @@
     this->virtual_table = other->virtual_table; \
 } \
-void ?{}(name * this) { \
+void ?{}(name & this) { \
 	VTABLE_INIT(this,name); \
 } \
