Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
+++ src/AST/Expr.hpp	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
@@ -114,4 +114,5 @@
 			case Params: assertf(false, "Cannot return to resnSlots from Params"); abort();
 			}
+			assertf(false, "unreachable");
 		}
 
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
+++ src/InitTweak/InitTweak.cc	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
@@ -318,5 +318,5 @@
 	virtual ~ExpanderImpl() = default;
 	virtual std::vector< ast::ptr< ast::Expr > > next( IndexList & indices ) = 0;
-	virtual ast::ptr< ast::Stmt > buildListInit( 
+	virtual ast::ptr< ast::Stmt > buildListInit(
 		ast::UntypedExpr * callExpr, IndexList & indices ) = 0;
 };
@@ -324,13 +324,13 @@
 namespace {
 	template< typename Out >
-	void buildCallExpr( 
-		ast::UntypedExpr * callExpr, const ast::Expr * index, const ast::Expr * dimension, 
+	void buildCallExpr(
+		ast::UntypedExpr * callExpr, const ast::Expr * index, const ast::Expr * dimension,
 		const ast::Init * init, Out & out
 	) {
 		const CodeLocation & loc = init->location;
 
-		auto cond = new ast::UntypedExpr{ 
+		auto cond = new ast::UntypedExpr{
 			loc, new ast::NameExpr{ loc, "?<?" }, { index, dimension } };
-		
+
 		std::vector< ast::ptr< ast::Expr > > args = makeInitList( init );
 		splice( callExpr->args, args );
@@ -338,5 +338,5 @@
 		out.emplace_back( new ast::IfStmt{ loc, cond, new ast::ExprStmt{ loc, callExpr } } );
 
-		out.emplace_back( new ast::ExprStmt{ 
+		out.emplace_back( new ast::ExprStmt{
 			loc, new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, "++?" }, { index } } } );
 	}
@@ -344,5 +344,5 @@
 	template< typename Out >
 	void build(
-		ast::UntypedExpr * callExpr, const InitExpander_new::IndexList & indices, 
+		ast::UntypedExpr * callExpr, const InitExpander_new::IndexList & indices,
 		const ast::Init * init, Out & out
 	) {
@@ -371,7 +371,7 @@
 
 			static UniqueName targetLabel( "L__autogen__" );
-			ast::Label switchLabel{ 
+			ast::Label switchLabel{
 				loc, targetLabel.newName(), { new ast::Attribute{ "unused" } } };
-			
+
 			std::vector< ast::ptr< ast::Stmt > > branches;
 			for ( const ast::Init * init : *listInit ) {
@@ -381,5 +381,5 @@
 				std::vector< ast::ptr< ast::Stmt > > stmts;
 				build( callExpr, indices, init, stmts );
-				stmts.emplace_back( 
+				stmts.emplace_back(
 					new ast::BranchStmt{ loc, ast::BranchStmt::Break, switchLabel } );
 				branches.emplace_back( new ast::CaseStmt{ loc, condition, std::move( stmts ) } );
@@ -398,12 +398,12 @@
 			return makeInitList( init );
 		}
-		
-		ast::ptr< ast::Stmt > buildListInit( 
-			ast::UntypedExpr * callExpr, InitExpander_new::IndexList & indices 
+
+		ast::ptr< ast::Stmt > buildListInit(
+			ast::UntypedExpr * callExpr, InitExpander_new::IndexList & indices
 		) override {
-			// If array came with an initializer list, initialize each element. We may have more 
-			// initializers than elements of the array; need to check at each index that we have 
-			// not exceeded size. We may have fewer initializers than elements in the array; need 
-			// to default-construct remaining elements. To accomplish this, generate switch 
+			// If array came with an initializer list, initialize each element. We may have more
+			// initializers than elements of the array; need to check at each index that we have
+			// not exceeded size. We may have fewer initializers than elements in the array; need
+			// to default-construct remaining elements. To accomplish this, generate switch
 			// statement consuming all of expander's elements
 
@@ -427,6 +427,6 @@
 		ExprImpl_new( const ast::Expr * a ) : arg( a ) {}
 
-		std::vector< ast::ptr< ast::Expr > > next( 
-			InitExpander_new::IndexList & indices 
+		std::vector< ast::ptr< ast::Expr > > next(
+			InitExpander_new::IndexList & indices
 		) override {
 			if ( ! arg ) return {};
@@ -437,13 +437,13 @@
 				// go through indices and layer on subscript exprs ?[?]
 				++it;
-				expr = new ast::UntypedExpr{ 
+				expr = new ast::UntypedExpr{
 					loc, new ast::NameExpr{ loc, "?[?]" }, { expr, *it } };
 			}
 			return { expr };
 		}
-		
-		ast::ptr< ast::Stmt > buildListInit( 
-			ast::UntypedExpr *, InitExpander_new::IndexList & 
-		) override { 
+
+		ast::ptr< ast::Stmt > buildListInit(
+			ast::UntypedExpr *, InitExpander_new::IndexList &
+		) override {
 			return {};
 		}
@@ -464,5 +464,5 @@
 }
 
-/// builds statement which has the same semantics as a C-style list initializer (for array 
+/// builds statement which has the same semantics as a C-style list initializer (for array
 /// initializers) using callExpr as the base expression to perform initialization
 ast::ptr< ast::Stmt > InitExpander_new::buildListInit( ast::UntypedExpr * callExpr ) {
@@ -668,9 +668,9 @@
 
 		const ast::DeclWithType * func = getCalledFunction( appExpr->func );
-		assertf( func, 
+		assertf( func,
 			"getCalledFunction returned nullptr: %s", toString( appExpr->func ).c_str() );
-		
-		// check for Intrinsic only -- don't want to remove all overridable ctor/dtor because 
-		// autogenerated ctor/dtor will call all member dtors, and some members may have a 
+
+		// check for Intrinsic only -- don't want to remove all overridable ctor/dtor because
+		// autogenerated ctor/dtor will call all member dtors, and some members may have a
 		// user-defined dtor
 		return func->linkage == ast::Linkage::Intrinsic ? appExpr : nullptr;
@@ -707,5 +707,5 @@
 		return allofCtorDtor( stmt, []( const ast::Expr * callExpr ){
 			if ( const ast::ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
-				const ast::FunctionType * funcType = 
+				const ast::FunctionType * funcType =
 					GenPoly::getFunctionType( appExpr->func->result );
 				assert( funcType );
@@ -997,6 +997,6 @@
 	bool isCtorDtorAssign( const std::string & str ) { return isCtorDtor( str ) || isAssignment( str ); }
 
-	FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname ) {
-		FunctionDecl * function = dynamic_cast< FunctionDecl * >( decl );
+	const FunctionDecl * isCopyFunction( const Declaration * decl, const std::string & fname ) {
+		const FunctionDecl * function = dynamic_cast< const FunctionDecl * >( decl );
 		if ( ! function ) return nullptr;
 		if ( function->name != fname ) return nullptr;
@@ -1022,20 +1022,20 @@
 		if ( ! t1 ) return false;
 		const ast::Type * t2 = ftype->params.back()->get_type();
-		
+
 		return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, ast::SymbolTable{} );
 	}
 
-	FunctionDecl * isAssignment( Declaration * decl ) {
+	const FunctionDecl * isAssignment( const Declaration * decl ) {
 		return isCopyFunction( decl, "?=?" );
 	}
-	FunctionDecl * isDestructor( Declaration * decl ) {
-		if ( isDestructor( decl->get_name() ) ) {
-			return dynamic_cast< FunctionDecl * >( decl );
+	const FunctionDecl * isDestructor( const Declaration * decl ) {
+		if ( isDestructor( decl->name ) ) {
+			return dynamic_cast< const FunctionDecl * >( decl );
 		}
 		return nullptr;
 	}
-	FunctionDecl * isDefaultConstructor( Declaration * decl ) {
+	const FunctionDecl * isDefaultConstructor( const Declaration * decl ) {
 		if ( isConstructor( decl->name ) ) {
-			if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) {
+			if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) {
 				if ( func->type->parameters.size() == 1 ) {
 					return func;
@@ -1045,5 +1045,5 @@
 		return nullptr;
 	}
-	FunctionDecl * isCopyConstructor( Declaration * decl ) {
+	const FunctionDecl * isCopyConstructor( const Declaration * decl ) {
 		return isCopyFunction( decl, "?{}" );
 	}
Index: src/InitTweak/InitTweak.h
===================================================================
--- src/InitTweak/InitTweak.h	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
+++ src/InitTweak/InitTweak.h	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
@@ -26,9 +26,9 @@
 // helper functions for initialization
 namespace InitTweak {
-	FunctionDecl * isAssignment( Declaration * decl );
-	FunctionDecl * isDestructor( Declaration * decl );
-	FunctionDecl * isDefaultConstructor( Declaration * decl );
-	FunctionDecl * isCopyConstructor( Declaration * decl );
-	FunctionDecl * isCopyFunction( Declaration * decl, const std::string & fname );
+	const FunctionDecl * isAssignment( const Declaration * decl );
+	const FunctionDecl * isDestructor( const Declaration * decl );
+	const FunctionDecl * isDefaultConstructor( const Declaration * decl );
+	const FunctionDecl * isCopyConstructor( const Declaration * decl );
+	const FunctionDecl * isCopyFunction( const Declaration * decl, const std::string & fname );
 	bool isCopyFunction( const ast::FunctionDecl * decl );
 
@@ -153,6 +153,6 @@
 		InitExpander_new & operator++ ();
 
-		/// builds statement which has the same semantics as a C-style list initializer (for array 
-		/// initializers) using callExpr as the base expression to perform initialization. 
+		/// builds statement which has the same semantics as a C-style list initializer (for array
+		/// initializers) using callExpr as the base expression to perform initialization.
 		/// Mutates callExpr
 		ast::ptr< ast::Stmt > buildListInit( ast::UntypedExpr * callExpr );
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
@@ -336,7 +336,7 @@
 		}
 
-		if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
+		if ( StructInstType * structInst = dynamic_cast< StructInstType* >( aggrExpr->result ) ) {
 			addAggMembers( structInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
-		} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
+		} else if ( UnionInstType * unionInst = dynamic_cast< UnionInstType* >( aggrExpr->result ) ) {
 			addAggMembers( unionInst, aggrExpr.get(), alt, alt.cost+Cost::safe, "" );
 		} // if
@@ -344,10 +344,10 @@
 
 	template< typename StructOrUnionType >
-	void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Alternative& alt, const Cost &newCost, const std::string & name ) {
+	void AlternativeFinder::Finder::addAggMembers( StructOrUnionType * aggInst, Expression * expr, const Alternative& alt, const Cost &newCost, const std::string & name ) {
 		std::list< Declaration* > members;
 		aggInst->lookup( name, members );
 
 		for ( Declaration * decl : members ) {
-			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
+			if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType* >( decl ) ) {
 				// addAnonAlternatives uses vector::push_back, which invalidates references to existing elements, so
 				// can't construct in place and use vector::back
@@ -362,5 +362,5 @@
 	}
 
-	void AlternativeFinder::Finder::addTupleMembers( TupleType *tupleType, Expression *expr, 			const Alternative &alt, const Cost &newCost, Expression *member ) {
+	void AlternativeFinder::Finder::addTupleMembers( TupleType * tupleType, Expression * expr, const Alternative &alt, const Cost &newCost, Expression * member ) {
 		if ( ConstantExpr * constantExpr = dynamic_cast< ConstantExpr * >( member ) ) {
 			// get the value of the constant expression as an int, must be between 0 and the length of the tuple type to have meaning
@@ -368,5 +368,5 @@
 			std::string tmp;
 			if ( val >= 0 && (unsigned long long)val < tupleType->size() ) {
-				alternatives.push_back( Alternative{ 
+				alternatives.push_back( Alternative{
 					alt, new TupleIndexExpr( expr->clone(), val ), newCost } );
 			} // if
@@ -374,5 +374,5 @@
 	}
 
-	void AlternativeFinder::Finder::postvisit( ApplicationExpr *applicationExpr ) {
+	void AlternativeFinder::Finder::postvisit( ApplicationExpr * applicationExpr ) {
 		alternatives.push_back( Alternative{ applicationExpr->clone(), env } );
 	}
@@ -475,5 +475,5 @@
 		}
 
-		// specialization cost of return types can't be accounted for directly, it disables 
+		// specialization cost of return types can't be accounted for directly, it disables
 		// otherwise-identical calls, like this example based on auto-newline in the I/O lib:
 		//
@@ -1226,6 +1226,6 @@
 				// count one safe conversion for each value that is thrown away
 				thisCost.incSafe( discardedValues );
-				Alternative newAlt{ 
-					restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ), 
+				Alternative newAlt{
+					restructureCast( alt.expr->clone(), toType, castExpr->isGenerated ),
 					alt.env, openVars, needAssertions, alt.cost, alt.cost + thisCost };
 				inferParameters( newAlt, back_inserter( candidates ) );
@@ -1328,5 +1328,5 @@
 		if ( sizeofExpr->get_isType() ) {
 			Type * newType = sizeofExpr->get_type()->clone();
-			alternatives.push_back( Alternative{ 
+			alternatives.push_back( Alternative{
 				new SizeofExpr{ resolveTypeof( newType, indexer ) }, env } );
 		} else {
@@ -1343,5 +1343,5 @@
 			Alternative &choice = winners.front();
 			referenceToRvalueConversion( choice.expr, choice.cost );
-			alternatives.push_back( Alternative{ 
+			alternatives.push_back( Alternative{
 				choice, new SizeofExpr( choice.expr->clone() ), Cost::zero } );
 		} // if
@@ -1351,5 +1351,5 @@
 		if ( alignofExpr->get_isType() ) {
 			Type * newType = alignofExpr->get_type()->clone();
-			alternatives.push_back( Alternative{ 
+			alternatives.push_back( Alternative{
 				new AlignofExpr{ resolveTypeof( newType, indexer ) }, env } );
 		} else {
@@ -1366,5 +1366,5 @@
 			Alternative &choice = winners.front();
 			referenceToRvalueConversion( choice.expr, choice.cost );
-			alternatives.push_back( Alternative{ 
+			alternatives.push_back( Alternative{
 				choice, new AlignofExpr{ choice.expr->clone() }, Cost::zero } );
 		} // if
@@ -1377,5 +1377,5 @@
 		for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
 			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
-				alternatives.push_back( Alternative{ 
+				alternatives.push_back( Alternative{
 					new OffsetofExpr{ aggInst->clone(), dwt }, env } );
 				renameTypes( alternatives.back().expr );
@@ -1405,8 +1405,8 @@
 
 	namespace {
-		void resolveAttr( SymTab::Indexer::IdData data, FunctionType *function, Type *argType, const TypeEnvironment &env, AlternativeFinder & finder ) {
+		void resolveAttr( SymTab::Indexer::IdData data, const FunctionType * function, Type * argType, const TypeEnvironment &env, AlternativeFinder & finder ) {
 			// assume no polymorphism
 			// assume no implicit conversions
-			assert( function->get_parameters().size() == 1 );
+			assert( function->parameters.size() == 1 );
 			PRINT(
 				std::cerr << "resolvAttr: funcDecl is ";
@@ -1418,9 +1418,9 @@
 			const SymTab::Indexer & indexer = finder.get_indexer();
 			AltList & alternatives = finder.get_alternatives();
-			if ( typesCompatibleIgnoreQualifiers( argType, function->get_parameters().front()->get_type(), indexer, env ) ) {
+			if ( typesCompatibleIgnoreQualifiers( argType, function->parameters.front()->get_type(), indexer, env ) ) {
 				Cost cost = Cost::zero;
 				Expression * newExpr = data.combine( cost );
-				alternatives.push_back( Alternative{ 
-					new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{}, 
+				alternatives.push_back( Alternative{
+					new AttrExpr{ newExpr, argType->clone() }, env, OpenVarSet{},
 					AssertionList{}, Cost::zero, cost } );
 				for ( DeclarationWithType * retVal : function->returnVals ) {
@@ -1431,7 +1431,7 @@
 	}
 
-	void AlternativeFinder::Finder::postvisit( AttrExpr *attrExpr ) {
+	void AlternativeFinder::Finder::postvisit( AttrExpr * attrExpr ) {
 		// assume no 'pointer-to-attribute'
-		NameExpr *nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() );
+		NameExpr * nameExpr = dynamic_cast< NameExpr* >( attrExpr->get_attr() );
 		assert( nameExpr );
 		std::list< SymTab::Indexer::IdData > attrList;
@@ -1439,9 +1439,9 @@
 		if ( attrExpr->get_isType() || attrExpr->get_expr() ) {
 			for ( auto & data : attrList ) {
-				DeclarationWithType * id = data.id;
+				const DeclarationWithType * id = data.id;
 				// check if the type is function
-				if ( FunctionType *function = dynamic_cast< FunctionType* >( id->get_type() ) ) {
+				if ( const FunctionType * function = dynamic_cast< const FunctionType * >( id->get_type() ) ) {
 					// assume exactly one parameter
-					if ( function->get_parameters().size() == 1 ) {
+					if ( function->parameters.size() == 1 ) {
 						if ( attrExpr->get_isType() ) {
 							resolveAttr( data, function, attrExpr->get_type(), env, altFinder);
@@ -1462,5 +1462,5 @@
 				Cost cost = Cost::zero;
 				Expression * newExpr = data.combine( cost );
-				alternatives.push_back( Alternative{ 
+				alternatives.push_back( Alternative{
 					newExpr, env, OpenVarSet{}, AssertionList{}, Cost::zero, cost } );
 				renameTypes( alternatives.back().expr );
@@ -1469,5 +1469,5 @@
 	}
 
-	void AlternativeFinder::Finder::postvisit( LogicalExpr *logicalExpr ) {
+	void AlternativeFinder::Finder::postvisit( LogicalExpr * logicalExpr ) {
 		AlternativeFinder firstFinder( indexer, env );
 		firstFinder.findWithAdjustment( logicalExpr->get_arg1() );
@@ -1486,8 +1486,8 @@
 				cloneAll( second.need, need );
 
-				LogicalExpr *newExpr = new LogicalExpr{ 
+				LogicalExpr *newExpr = new LogicalExpr{
 					first.expr->clone(), second.expr->clone(), logicalExpr->get_isAnd() };
-				alternatives.push_back( Alternative{ 
-					newExpr, std::move(compositeEnv), std::move(openVars), 
+				alternatives.push_back( Alternative{
+					newExpr, std::move(compositeEnv), std::move(openVars),
 					AssertionList( need.begin(), need.end() ), first.cost + second.cost } );
 			}
@@ -1522,21 +1522,21 @@
 					cloneAll( third.need, need );
 					AssertionSet have;
-					
+
 					// unify true and false types, then infer parameters to produce new alternatives
 					Type* commonType = nullptr;
-					if ( unify( second.expr->result, third.expr->result, compositeEnv, 
+					if ( unify( second.expr->result, third.expr->result, compositeEnv,
 							need, have, openVars, indexer, commonType ) ) {
-						ConditionalExpr *newExpr = new ConditionalExpr{ 
+						ConditionalExpr *newExpr = new ConditionalExpr{
 							first.expr->clone(), second.expr->clone(), third.expr->clone() };
 						newExpr->result = commonType ? commonType : second.expr->result->clone();
 						// convert both options to the conditional result type
 						Cost cost = first.cost + second.cost + third.cost;
-						cost += computeExpressionConversionCost( 
+						cost += computeExpressionConversionCost(
 							newExpr->arg2, newExpr->result, indexer, compositeEnv );
-						cost += computeExpressionConversionCost( 
+						cost += computeExpressionConversionCost(
 							newExpr->arg3, newExpr->result, indexer, compositeEnv );
 						// output alternative
-						Alternative newAlt{ 
-							newExpr, std::move(compositeEnv), std::move(openVars), 
+						Alternative newAlt{
+							newExpr, std::move(compositeEnv), std::move(openVars),
 							AssertionList( need.begin(), need.end() ), cost };
 						inferParameters( newAlt, back_inserter( alternatives ) );
@@ -1553,5 +1553,5 @@
 		secondFinder.findWithAdjustment( commaExpr->get_arg2() );
 		for ( const Alternative & alt : secondFinder.alternatives ) {
-			alternatives.push_back( Alternative{ 
+			alternatives.push_back( Alternative{
 				alt, new CommaExpr{ newFirstArg->clone(), alt.expr->clone() }, alt.cost } );
 		} // for
@@ -1579,11 +1579,11 @@
 
 				Type* commonType = nullptr;
-				if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have, 
+				if ( unify( first.expr->result, second.expr->result, compositeEnv, need, have,
 						openVars, indexer, commonType ) ) {
-					RangeExpr * newExpr = 
+					RangeExpr * newExpr =
 						new RangeExpr{ first.expr->clone(), second.expr->clone() };
 					newExpr->result = commonType ? commonType : first.expr->result->clone();
-					Alternative newAlt{ 
-						newExpr, std::move(compositeEnv), std::move(openVars), 
+					Alternative newAlt{
+						newExpr, std::move(compositeEnv), std::move(openVars),
 						AssertionList( need.begin(), need.end() ), first.cost + second.cost };
 					inferParameters( newAlt, back_inserter( alternatives ) );
@@ -1612,7 +1612,7 @@
 				cloneAll( alt.need, need );
 			}
-			
-			alternatives.push_back( Alternative{ 
-				new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars), 
+
+			alternatives.push_back( Alternative{
+				new TupleExpr{ exprs }, std::move(compositeEnv), std::move(openVars),
 				AssertionList( need.begin(), need.end() ), sumCost( alts ) } );
 		} // for
@@ -1633,5 +1633,5 @@
 		finder.findWithoutPrune( ctorExpr->get_callExpr() );
 		for ( Alternative & alt : finder.alternatives ) {
-			alternatives.push_back( Alternative{ 
+			alternatives.push_back( Alternative{
 				alt, new ConstructorExpr( alt.expr->clone() ), alt.cost } );
 		}
@@ -1685,21 +1685,21 @@
 				cloneAll( alt.need, need );
 				AssertionSet have;
-				OpenVarSet openVars( alt.openVars );  
-				// xxx - find things in env that don't have a "representative type" and claim 
+				OpenVarSet openVars( alt.openVars );
+				// xxx - find things in env that don't have a "representative type" and claim
 				// those are open vars?
 				PRINT(
 					std::cerr << "  @ " << toType << " " << initAlt.designation << std::endl;
 				)
-				// It's possible that a cast can throw away some values in a multiply-valued 
-				// expression. (An example is a cast-to-void, which casts from one value to 
-				// zero.)  Figure out the prefix of the subexpression results that are cast 
-				// directly.  The candidate is invalid if it has fewer results than there are 
+				// It's possible that a cast can throw away some values in a multiply-valued
+				// expression. (An example is a cast-to-void, which casts from one value to
+				// zero.)  Figure out the prefix of the subexpression results that are cast
+				// directly.  The candidate is invalid if it has fewer results than there are
 				// types to cast to.
 				int discardedValues = alt.expr->result->size() - toType->size();
 				if ( discardedValues < 0 ) continue;
-				// xxx - may need to go into tuple types and extract relevant types and use 
-				// unifyList. Note that currently, this does not allow casting a tuple to an 
+				// xxx - may need to go into tuple types and extract relevant types and use
+				// unifyList. Note that currently, this does not allow casting a tuple to an
 				// atomic type (e.g. (int)([1, 2, 3]))
-				
+
 				// unification run for side-effects
 				unify( toType, alt.expr->result, newEnv, need, have, openVars, indexer );
@@ -1710,8 +1710,8 @@
 					// count one safe conversion for each value that is thrown away
 					thisCost.incSafe( discardedValues );
-					Alternative newAlt{ 
-						new InitExpr{ 
-							restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() }, 
-						std::move(newEnv), std::move(openVars), 
+					Alternative newAlt{
+						new InitExpr{
+							restructureCast( alt.expr->clone(), toType, true ), initAlt.designation->clone() },
+						std::move(newEnv), std::move(openVars),
 						AssertionList( need.begin(), need.end() ), alt.cost, thisCost };
 					inferParameters( newAlt, back_inserter( candidates ) );
Index: src/ResolvExpr/ResolveAssertions.cc
===================================================================
--- src/ResolvExpr/ResolveAssertions.cc	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
+++ src/ResolvExpr/ResolveAssertions.cc	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
@@ -197,5 +197,5 @@
 			}
 			if ( i == b.size() /* && i < a.size() */ ) return 1;
-			
+
 			int c = a[i].compare( b[i] );
 			if ( c != 0 ) return c;
@@ -220,5 +220,5 @@
 
 		/// Initial resolution state for an alternative
-		ResnState( Alternative& a, SymTab::Indexer& indexer )
+		ResnState( Alternative & a, SymTab::Indexer & indexer )
 		: alt(a), need(), newNeed(), deferred(), inferred(), costs{ Cost::zero }, indexer(indexer) {
 			need.swap( a.need );
@@ -226,5 +226,5 @@
 
 		/// Updated resolution state with new need-list
-		ResnState( ResnState&& o, IterateFlag )
+		ResnState( ResnState && o, IterateFlag )
 		: alt(std::move(o.alt)), need(o.newNeed.begin(), o.newNeed.end()), newNeed(), deferred(),
 		  inferred(std::move(o.inferred)), costs(o.costs), indexer(o.indexer) {
@@ -234,11 +234,11 @@
 
 	/// Binds a single assertion, updating resolution state
-	void bindAssertion( const DeclarationWithType* decl, AssertionSetValue info, Alternative& alt,
-			AssnCandidate& match, InferCache& inferred ) {
-
-		DeclarationWithType* candidate = match.cdata.id;
-		assertf( candidate->get_uniqueId(), "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
-
-		Expression* varExpr = match.cdata.combine( alt.cvtCost );
+	void bindAssertion( const DeclarationWithType * decl, AssertionSetValue info, Alternative & alt,
+			AssnCandidate & match, InferCache & inferred ) {
+
+		const DeclarationWithType * candidate = match.cdata.id;
+		assertf( candidate->uniqueId, "Assertion candidate does not have a unique ID: %s", toString( candidate ).c_str() );
+
+		Expression * varExpr = match.cdata.combine( alt.cvtCost );
 		delete varExpr->result;
 		varExpr->result = match.adjType->clone();
@@ -247,10 +247,10 @@
 		// place newly-inferred assertion in proper place in cache
 		inferred[ info.resnSlot ][ decl->get_uniqueId() ] = ParamEntry{
-				candidate->get_uniqueId(), candidate->clone(), match.adjType->clone(), decl->get_type()->clone(),
+				candidate->uniqueId, candidate->clone(), match.adjType->clone(), decl->get_type()->clone(),
 				varExpr };
 	}
 
 	/// Adds a captured assertion to the symbol table
-	void addToIndexer( AssertionSet &assertSet, SymTab::Indexer &indexer ) {
+	void addToIndexer( AssertionSet & assertSet, SymTab::Indexer & indexer ) {
 		for ( auto&  i : assertSet ) {
 			if ( i.second.isUsed ) {
@@ -264,5 +264,5 @@
 
 	/// Resolve a single assertion, in context
-	bool resolveAssertion( AssertionItem& assn, ResnState& resn ) {
+	bool resolveAssertion( AssertionItem & assn, ResnState & resn ) {
 		// skip unused assertions
 		if ( ! assn.info.isUsed ) return true;
@@ -274,6 +274,6 @@
 		// find the candidates that unify with the desired type
 		CandidateList matches;
-		for ( const auto& cdata : candidates ) {
-			DeclarationWithType* candidate = cdata.id;
+		for ( const auto & cdata : candidates ) {
+			const DeclarationWithType * candidate = cdata.id;
 
 			// build independent unification context for candidate
@@ -281,5 +281,5 @@
 			TypeEnvironment newEnv{ resn.alt.env };
 			OpenVarSet newOpenVars{ resn.alt.openVars };
-			Type* adjType = candidate->get_type()->clone();
+			Type * adjType = candidate->get_type()->clone();
 			adjustExprType( adjType, newEnv, resn.indexer );
 			renameTyVars( adjType );
@@ -370,6 +370,6 @@
 		return resKey;
 	}
-	
-	/// Replace resnSlots with inferParams and add alternative to output list, if meets pruning 
+
+	/// Replace resnSlots with inferParams and add alternative to output list, if meets pruning
 	/// threshold.
 	void finalizeAssertions( ResnState& resn, PruneMap & pruneThresholds, AltList& out ) {
@@ -406,5 +406,5 @@
 		ResnList resns{ ResnState{ alt, root_indexer } };
 		ResnList new_resns{};
-		
+
 		// Pruning thresholds by result type of the output alternatives.
 		// Alternatives *should* be generated in sorted order, so no need to retroactively prune
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
+++ src/ResolvExpr/Unify.cc	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
@@ -102,9 +102,9 @@
 		WidenMode widen, const ast::SymbolTable & symtab );
 
-	bool typesCompatible( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
+	bool typesCompatible( const Type * first, const Type * second, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
 		TypeEnvironment newEnv;
 		OpenVarSet openVars, closedVars; // added closedVars
 		AssertionSet needAssertions, haveAssertions;
-		Type *newFirst = first->clone(), *newSecond = second->clone();
+		Type * newFirst = first->clone(), * newSecond = second->clone();
 		env.apply( newFirst );
 		env.apply( newSecond );
Index: src/ResolvExpr/typeops.h
===================================================================
--- src/ResolvExpr/typeops.h	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
+++ src/ResolvExpr/typeops.h	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
@@ -28,5 +28,8 @@
 #include "SynTree/SynTree.h"
 #include "SynTree/Type.h"
-#include "SymTab/Indexer.h"
+
+namespace SymTab {
+	class Indexer;
+}
 
 namespace ResolvExpr {
@@ -60,5 +63,5 @@
 	// in AdjustExprType.cc
 	/// Replaces array types with the equivalent pointer, and function types with a pointer-to-function
-	void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer );
+	void adjustExprType( Type *& type, const TypeEnvironment & env, const SymTab::Indexer & indexer );
 
 	/// Replaces array types with the equivalent pointer, and function types with a pointer-to-function using empty TypeEnvironment and Indexer
@@ -66,5 +69,5 @@
 
 	template< typename ForwardIterator >
-	void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
+	void adjustExprTypeList( ForwardIterator begin, ForwardIterator end, const TypeEnvironment & env, const SymTab::Indexer & indexer ) {
 		while ( begin != end ) {
 			adjustExprType( *begin++, env, indexer );
@@ -77,5 +80,5 @@
 
 	// in CastCost.cc
-	Cost castCost( const Type * src, const Type * dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
+	Cost castCost( const Type * src, const Type * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env );
 	Cost castCost(
 		const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
@@ -83,5 +86,5 @@
 
 	// in ConversionCost.cc
-	Cost conversionCost( const Type *src, const Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
+	Cost conversionCost( const Type * src, const Type * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env );
 	Cost conversionCost(
 		const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
@@ -89,14 +92,14 @@
 
 	// in AlternativeFinder.cc
-	Cost computeConversionCost( Type *actualType, Type *formalType,
-		const SymTab::Indexer &indexer, const TypeEnvironment &env );
+	Cost computeConversionCost( Type * actualType, Type * formalType,
+		const SymTab::Indexer & indexer, const TypeEnvironment & env );
 
 	// in PtrsAssignable.cc
-	int ptrsAssignable( const Type * src, const Type * dest, const TypeEnvironment &env );
+	int ptrsAssignable( const Type * src, const Type * dest, const TypeEnvironment & env );
 	int ptrsAssignable( const ast::Type * src, const ast::Type * dst,
 		const ast::TypeEnvironment & env );
 
 	// in PtrsCastable.cc
-	int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
+	int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment & env, const SymTab::Indexer & indexer );
 	int ptrsCastable(
 		const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
@@ -104,13 +107,13 @@
 
 	// in Unify.cc
-	bool typesCompatible( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env );
-	bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env );
-
-	inline bool typesCompatible( Type *t1, Type *t2, const SymTab::Indexer &indexer ) {
+	bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
+	bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
+
+	inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
 		TypeEnvironment env;
 		return typesCompatible( t1, t2, indexer, env );
 	}
 
-	inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer &indexer ) {
+	inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
 		TypeEnvironment env;
 		return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env );
@@ -131,5 +134,5 @@
 
 	// in CommonType.cc
-	Type * commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
+	Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer & indexer, TypeEnvironment & env, const OpenVarSet & openVars );
 	ast::ptr< ast::Type > commonType(
 		const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, WidenMode widen,
@@ -137,18 +140,18 @@
 
 	// in PolyCost.cc
-	int polyCost( Type *type, const TypeEnvironment &env, const SymTab::Indexer &indexer );
+	int polyCost( Type * type, const TypeEnvironment & env, const SymTab::Indexer & indexer );
 	int polyCost(
 		const ast::Type * type, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
 
 	// in SpecCost.cc
-	int specCost( Type *type );
+	int specCost( Type * type );
 	int specCost( const ast::Type * type );
 
 	// in Occurs.cc
-	bool occurs( Type *type, std::string varName, const TypeEnvironment &env );
+	bool occurs( Type * type, std::string varName, const TypeEnvironment & env );
 	// new AST version in TypeEnvironment.cpp (only place it was used in old AST)
 
 	template<typename Iter>
-	bool occursIn( Type* ty, Iter begin, Iter end, const TypeEnvironment &env ) {
+	bool occursIn( Type* ty, Iter begin, Iter end, const TypeEnvironment & env ) {
 		while ( begin != end ) {
 			if ( occurs( ty, *begin, env ) ) return true;
@@ -197,5 +200,5 @@
 
 	// in TypeEnvironment.cc
-	bool isFtype( Type *type );
+	bool isFtype( Type * type );
 } // namespace ResolvExpr
 
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
+++ src/SymTab/Indexer.cc	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
@@ -188,14 +188,14 @@
 	}
 
-	bool isFunction( DeclarationWithType * decl ) {
+	bool isFunction( const DeclarationWithType * decl ) {
 		return GenPoly::getFunctionType( decl->get_type() );
 	}
 
-	bool isObject( DeclarationWithType * decl ) {
+	bool isObject( const DeclarationWithType * decl ) {
 		return ! isFunction( decl );
 	}
 
-	bool isDefinition( DeclarationWithType * decl ) {
-		if ( FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl ) ) {
+	bool isDefinition( const DeclarationWithType * decl ) {
+		if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) {
 			// a function is a definition if it has a body
 			return func->statements;
@@ -209,6 +209,6 @@
 
 	bool Indexer::addedIdConflicts(
-			const Indexer::IdData & existing, DeclarationWithType * added,
-			Indexer::OnConflict handleConflicts, BaseSyntaxNode * deleteStmt ) {
+			const Indexer::IdData & existing, const DeclarationWithType * added,
+			Indexer::OnConflict handleConflicts, const BaseSyntaxNode * deleteStmt ) {
 		// if we're giving the same name mangling to things of different types then there is
 		// something wrong
@@ -274,6 +274,5 @@
 	}
 
-	bool Indexer::hasIncompatibleCDecl(
-			const std::string & id, const std::string &mangleName ) const {
+	bool Indexer::hasIncompatibleCDecl(const std::string & id, const std::string &mangleName ) const {
 		if ( ! idTable ) return false;
 
@@ -295,5 +294,5 @@
 
 	/// gets the base type of the first parameter; decl must be a ctor/dtor/assignment function
-	std::string getOtypeKey( FunctionDecl * function ) {
+	std::string getOtypeKey( const FunctionDecl * function ) {
 		auto& params = function->type->parameters;
 		assert( ! params.empty() );
@@ -306,12 +305,11 @@
 	/// gets the declaration for the function acting on a type specified by otype key,
 	/// nullptr if none such
-	FunctionDecl * getFunctionForOtype( DeclarationWithType * decl, const std::string& otypeKey ) {
-		FunctionDecl * func = dynamic_cast< FunctionDecl * >( decl );
+	const FunctionDecl * getFunctionForOtype( const DeclarationWithType * decl, const std::string& otypeKey ) {
+		const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl );
 		if ( ! func || otypeKey != getOtypeKey( func ) ) return nullptr;
 		return func;
 	}
 
-	bool Indexer::removeSpecialOverrides(
-			Indexer::IdData& data, Indexer::MangleTable::Ptr& mangleTable ) {
+	bool Indexer::removeSpecialOverrides(Indexer::IdData& data, Indexer::MangleTable::Ptr& mangleTable ) {
 		// if a type contains user defined ctor/dtor/assign, then special rules trigger, which
 		// determinethe set of ctor/dtor/assign that can be used  by the requester. In particular,
@@ -324,5 +322,5 @@
 
 		// only relevant on function declarations
-		FunctionDecl * function = dynamic_cast< FunctionDecl * >( data.id );
+		const FunctionDecl * function = dynamic_cast< const FunctionDecl * >( data.id );
 		if ( ! function ) return true;
 		// only need to perform this check for constructors, destructors, and assignment functions
@@ -343,5 +341,5 @@
 			for ( const auto& entry : * mangleTable ) {
 				// skip decls that aren't functions or are for the wrong type
-				FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
+				const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
 				if ( ! decl ) continue;
 
@@ -382,5 +380,5 @@
 			for ( const auto& entry : * mangleTable ) {
 				// skip decls that aren't functions or are for the wrong type
-				FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
+				const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
 				if ( ! decl ) continue;
 
@@ -410,5 +408,5 @@
 			for ( const auto& entry : * mangleTable ) {
 				// skip decls that aren't functions or are for the wrong type
-				FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
+				const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
 				if ( ! decl ) continue;
 
@@ -433,7 +431,6 @@
 	}
 
-	void Indexer::addId(
-			DeclarationWithType * decl, OnConflict handleConflicts, Expression * baseExpr,
-			BaseSyntaxNode * deleteStmt ) {
+	void Indexer::addId(const DeclarationWithType * decl, OnConflict handleConflicts, const Expression * baseExpr,
+			const BaseSyntaxNode * deleteStmt ) {
 		++* stats().add_calls;
 		const std::string &name = decl->name;
@@ -508,15 +505,15 @@
 	}
 
-	void Indexer::addId( DeclarationWithType * decl, Expression * baseExpr ) {
+	void Indexer::addId( const DeclarationWithType * decl, const Expression * baseExpr ) {
 		// default handling of conflicts is to raise an error
 		addId( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );
 	}
 
-	void Indexer::addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt ) {
+	void Indexer::addDeletedId( const DeclarationWithType * decl, const BaseSyntaxNode * deleteStmt ) {
 		// default handling of conflicts is to raise an error
 		addId( decl, OnConflict::error(), nullptr, deleteStmt );
 	}
 
-	bool addedTypeConflicts( NamedTypeDecl * existing, NamedTypeDecl * added ) {
+	bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) {
 		if ( existing->base == nullptr ) {
 			return false;
@@ -535,5 +532,5 @@
 	}
 
-	void Indexer::addType( NamedTypeDecl * decl ) {
+	void Indexer::addType( const NamedTypeDecl * decl ) {
 		++* stats().add_calls;
 		const std::string & id = decl->name;
@@ -554,5 +551,5 @@
 	}
 
-	bool addedDeclConflicts( AggregateDecl * existing, AggregateDecl * added ) {
+	bool addedDeclConflicts( const AggregateDecl * existing, const AggregateDecl * added ) {
 		if ( ! existing->body ) {
 			return false;
@@ -567,5 +564,5 @@
 	}
 
-	void Indexer::addStruct( StructDecl * decl ) {
+	void Indexer::addStruct( const StructDecl * decl ) {
 		++* stats().add_calls;
 		const std::string & id = decl->name;
@@ -586,5 +583,5 @@
 	}
 
-	void Indexer::addEnum( EnumDecl * decl ) {
+	void Indexer::addEnum( const EnumDecl * decl ) {
 		++* stats().add_calls;
 		const std::string & id = decl->name;
@@ -609,5 +606,5 @@
 	}
 
-	void Indexer::addUnion( UnionDecl * decl ) {
+	void Indexer::addUnion( const UnionDecl * decl ) {
 		++* stats().add_calls;
 		const std::string & id = decl->name;
@@ -628,5 +625,5 @@
 	}
 
-	void Indexer::addTrait( TraitDecl * decl ) {
+	void Indexer::addTrait( const TraitDecl * decl ) {
 		++* stats().add_calls;
 		const std::string & id = decl->name;
@@ -647,12 +644,11 @@
 	}
 
-	void Indexer::addMembers( AggregateDecl * aggr, Expression * expr,
-			OnConflict handleConflicts ) {
+	void Indexer::addMembers( const AggregateDecl * aggr, const Expression * expr, OnConflict handleConflicts ) {
 		for ( Declaration * decl : aggr->members ) {
 			if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
 				addId( dwt, handleConflicts, expr );
 				if ( dwt->name == "" ) {
-					Type * t = dwt->get_type()->stripReferences();
-					if ( dynamic_cast<StructInstType *>( t ) || dynamic_cast<UnionInstType *>( t ) ) {
+					const Type * t = dwt->get_type()->stripReferences();
+					if ( dynamic_cast<const StructInstType *>( t ) || dynamic_cast<const UnionInstType *>( t ) ) {
 						Expression * base = expr->clone();
 						ResolvExpr::Cost cost = ResolvExpr::Cost::zero; // xxx - carry this cost into the indexer as a base cost?
@@ -665,6 +661,6 @@
 	}
 
-	void Indexer::addWith( std::list< Expression * > & withExprs, BaseSyntaxNode * withStmt ) {
-		for ( Expression * expr : withExprs ) {
+	void Indexer::addWith( const std::list< Expression * > & withExprs, const BaseSyntaxNode * withStmt ) {
+		for ( const Expression * expr : withExprs ) {
 			if ( expr->result ) {
 				AggregateDecl * aggr = expr->result->stripReferences()->getAggr();
@@ -689,5 +685,5 @@
 	}
 
-	void Indexer::addFunctionType( FunctionType * ftype ) {
+	void Indexer::addFunctionType( const FunctionType * ftype ) {
 		addTypes( ftype->forall );
 		addIds( ftype->returnVals );
@@ -700,5 +696,5 @@
 			Expression * base = baseExpr->clone();
 			ResolvExpr::referenceToRvalueConversion( base, cost );
-			ret = new MemberExpr( id, base );
+			ret = new MemberExpr( const_cast<DeclarationWithType *>(id), base );
 			// xxx - this introduces hidden environments, for now remove them.
 			// std::swap( base->env, ret->env );
@@ -706,7 +702,7 @@
 			base->env = nullptr;
 		} else {
-			ret = new VariableExpr( id );
-		}
-		if ( deleteStmt ) ret = new DeletedExpr( ret, deleteStmt );
+			ret = new VariableExpr( const_cast<DeclarationWithType *>(id) );
+		}
+		if ( deleteStmt ) ret = new DeletedExpr( ret, const_cast<BaseSyntaxNode *>(deleteStmt) );
 		return ret;
 	}
Index: src/SymTab/Indexer.h
===================================================================
--- src/SymTab/Indexer.h	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
+++ src/SymTab/Indexer.h	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
@@ -40,9 +40,9 @@
 
 		struct IdData {
-			DeclarationWithType * id = nullptr;
-			Expression * baseExpr = nullptr; // WithExpr
+			const DeclarationWithType * id = nullptr;
+			const Expression * baseExpr = nullptr; // WithExpr
 
 			/// non-null if this declaration is deleted
-			BaseSyntaxNode * deleteStmt = nullptr;
+			const BaseSyntaxNode * deleteStmt = nullptr;
 			/// scope of identifier
 			unsigned long scope = 0;
@@ -51,8 +51,8 @@
 			IdData() = default;
 			IdData(
-				DeclarationWithType * id, Expression * baseExpr, BaseSyntaxNode * deleteStmt,
+				const DeclarationWithType * id, const Expression * baseExpr, const BaseSyntaxNode * deleteStmt,
 				unsigned long scope )
 				: id( id ), baseExpr( baseExpr ), deleteStmt( deleteStmt ), scope( scope ) {}
-			IdData( const IdData& o, BaseSyntaxNode * deleteStmt )
+			IdData( const IdData& o, const BaseSyntaxNode * deleteStmt )
 				: id( o.id ), baseExpr( o.baseExpr ), deleteStmt( deleteStmt ), scope( o.scope ) {}
 
@@ -82,17 +82,17 @@
 		const EnumDecl * globalLookupEnum( const std::string & id ) const;
 
-		void addId( DeclarationWithType * decl, Expression * baseExpr = nullptr );
-		void addDeletedId( DeclarationWithType * decl, BaseSyntaxNode * deleteStmt );
+		void addId( const DeclarationWithType * decl, const Expression * baseExpr = nullptr );
+		void addDeletedId( const DeclarationWithType * decl, const BaseSyntaxNode * deleteStmt );
 
-		void addType( NamedTypeDecl * decl );
+		void addType( const NamedTypeDecl * decl );
 		void addStruct( const std::string & id );
-		void addStruct( StructDecl * decl );
-		void addEnum( EnumDecl * decl );
+		void addStruct( const StructDecl * decl );
+		void addEnum( const EnumDecl * decl );
 		void addUnion( const std::string & id );
-		void addUnion( UnionDecl * decl );
-		void addTrait( TraitDecl * decl );
+		void addUnion( const UnionDecl * decl );
+		void addTrait( const TraitDecl * decl );
 
 		/// adds all of the IDs from WithStmt exprs
-		void addWith( std::list< Expression * > & withExprs, BaseSyntaxNode * withStmt );
+		void addWith( const std::list< Expression * > & withExprs, const BaseSyntaxNode * withStmt );
 
 		/// convenience function for adding a list of Ids to the indexer
@@ -103,5 +103,5 @@
 
 		/// convenience function for adding all of the declarations in a function type to the indexer
-		void addFunctionType( FunctionType * ftype );
+		void addFunctionType( const FunctionType * ftype );
 
 	  private:
@@ -109,8 +109,8 @@
 	  	template<typename Decl>
 		struct Scoped {
-			Decl * decl;           ///< declaration
+			const Decl * decl;           ///< declaration
 			unsigned long scope;  ///< scope of this declaration
 
-			Scoped(Decl * d, unsigned long s) : decl(d), scope(s) {}
+			Scoped(const Decl * d, unsigned long s) : decl(d), scope(s) {}
 		};
 
@@ -144,5 +144,5 @@
 		/// Removes matching autogenerated constructors and destructors so that they will not be
 		/// selected. If returns false, passed decl should not be added.
-		bool removeSpecialOverrides( IdData& decl, MangleTable::Ptr& mangleTable );
+		bool removeSpecialOverrides( IdData & decl, MangleTable::Ptr & mangleTable );
 
 		/// Options for handling identifier conflicts
@@ -152,33 +152,32 @@
 				Delete  ///< Delete the earlier version with the delete statement
 			} mode;
-			BaseSyntaxNode * deleteStmt;  ///< Statement that deletes this expression
+			const BaseSyntaxNode * deleteStmt;  ///< Statement that deletes this expression
 
 		private:
 			OnConflict() : mode(Error), deleteStmt(nullptr) {}
-			OnConflict( BaseSyntaxNode * d ) : mode(Delete), deleteStmt(d) {}
+			OnConflict( const BaseSyntaxNode * d ) : mode(Delete), deleteStmt(d) {}
 		public:
 			OnConflict( const OnConflict& ) = default;
 
 			static OnConflict error() { return {}; }
-			static OnConflict deleteWith( BaseSyntaxNode * d ) { return { d }; }
+			static OnConflict deleteWith( const BaseSyntaxNode * d ) { return { d }; }
 		};
 
 		/// true if the existing identifier conflicts with the added identifier
 		bool addedIdConflicts(
-			const IdData& existing, DeclarationWithType * added, OnConflict handleConflicts,
-			BaseSyntaxNode * deleteStmt );
+			const IdData & existing, const DeclarationWithType * added, OnConflict handleConflicts,
+			const BaseSyntaxNode * deleteStmt );
 
 		/// common code for addId, addDeletedId, etc.
-		void addId(
-			DeclarationWithType * decl, OnConflict handleConflicts,
-			Expression * baseExpr = nullptr, BaseSyntaxNode * deleteStmt = nullptr );
+		void addId(const DeclarationWithType * decl, OnConflict handleConflicts,
+			const Expression * baseExpr = nullptr, const BaseSyntaxNode * deleteStmt = nullptr );
 
 		/// adds all of the members of the Aggregate (addWith helper)
-		void addMembers( AggregateDecl * aggr, Expression * expr, OnConflict handleConflicts );
+		void addMembers( const AggregateDecl * aggr, const Expression * expr, OnConflict handleConflicts );
 
 		/// returns true if there exists a declaration with C linkage and the given name with the same mangled name
-		bool hasCompatibleCDecl( const std::string & id, const std::string &mangleName ) const;
+		bool hasCompatibleCDecl( const std::string & id, const std::string & mangleName ) const;
 		/// returns true if there exists a declaration with C linkage and the given name with a different mangled name
-		bool hasIncompatibleCDecl( const std::string & id, const std::string &mangleName ) const;
+		bool hasIncompatibleCDecl( const std::string & id, const std::string & mangleName ) const;
 	};
 } // namespace SymTab
Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
+++ src/SymTab/Mangler.cc	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
@@ -42,26 +42,26 @@
 				Mangler_old( const Mangler_old & ) = delete;
 
-				void previsit( BaseSyntaxNode * ) { visit_children = false; }
-
-				void postvisit( ObjectDecl * declaration );
-				void postvisit( FunctionDecl * declaration );
-				void postvisit( TypeDecl * declaration );
-
-				void postvisit( VoidType * voidType );
-				void postvisit( BasicType * basicType );
-				void postvisit( PointerType * pointerType );
-				void postvisit( ArrayType * arrayType );
-				void postvisit( ReferenceType * refType );
-				void postvisit( FunctionType * functionType );
-				void postvisit( StructInstType * aggregateUseType );
-				void postvisit( UnionInstType * aggregateUseType );
-				void postvisit( EnumInstType * aggregateUseType );
-				void postvisit( TypeInstType * aggregateUseType );
-				void postvisit( TraitInstType * inst );
-				void postvisit( TupleType * tupleType );
-				void postvisit( VarArgsType * varArgsType );
-				void postvisit( ZeroType * zeroType );
-				void postvisit( OneType * oneType );
-				void postvisit( QualifiedType * qualType );
+				void previsit( const BaseSyntaxNode * ) { visit_children = false; }
+
+				void postvisit( const ObjectDecl * declaration );
+				void postvisit( const FunctionDecl * declaration );
+				void postvisit( const TypeDecl * declaration );
+
+				void postvisit( const VoidType * voidType );
+				void postvisit( const BasicType * basicType );
+				void postvisit( const PointerType * pointerType );
+				void postvisit( const ArrayType * arrayType );
+				void postvisit( const ReferenceType * refType );
+				void postvisit( const FunctionType * functionType );
+				void postvisit( const StructInstType * aggregateUseType );
+				void postvisit( const UnionInstType * aggregateUseType );
+				void postvisit( const EnumInstType * aggregateUseType );
+				void postvisit( const TypeInstType * aggregateUseType );
+				void postvisit( const TraitInstType * inst );
+				void postvisit( const TupleType * tupleType );
+				void postvisit( const VarArgsType * varArgsType );
+				void postvisit( const ZeroType * zeroType );
+				void postvisit( const OneType * oneType );
+				void postvisit( const QualifiedType * qualType );
 
 				std::string get_mangleName() { return mangleName.str(); }
@@ -79,16 +79,16 @@
 
 			  public:
-				Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 
+				Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
 					int nextVarNum, const VarMapType& varNums );
 
 			  private:
-				void mangleDecl( DeclarationWithType *declaration );
-				void mangleRef( ReferenceToType *refType, std::string prefix );
-
-				void printQualifiers( Type *type );
+				void mangleDecl( const DeclarationWithType * declaration );
+				void mangleRef( const ReferenceToType * refType, std::string prefix );
+
+				void printQualifiers( const Type *type );
 			}; // Mangler_old
 		} // namespace
 
-		std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
+		std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
 			PassVisitor<Mangler_old> mangler( mangleOverridable, typeMode, mangleGenericParams );
 			maybeAccept( decl, mangler );
@@ -96,5 +96,5 @@
 		}
 
-		std::string mangleType( Type * ty ) {
+		std::string mangleType( const Type * ty ) {
 			PassVisitor<Mangler_old> mangler( false, true, true );
 			maybeAccept( ty, mangler );
@@ -102,5 +102,5 @@
 		}
 
-		std::string mangleConcrete( Type * ty ) {
+		std::string mangleConcrete( const Type * ty ) {
 			PassVisitor<Mangler_old> mangler( false, false, false );
 			maybeAccept( ty, mangler );
@@ -110,15 +110,15 @@
 		namespace {
 			Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
-				: nextVarNum( 0 ), isTopLevel( true ), 
-				mangleOverridable( mangleOverridable ), typeMode( typeMode ), 
+				: nextVarNum( 0 ), isTopLevel( true ),
+				mangleOverridable( mangleOverridable ), typeMode( typeMode ),
 				mangleGenericParams( mangleGenericParams ) {}
-			
-			Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 
+
+			Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
 				int nextVarNum, const VarMapType& varNums )
-				: varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), 
-				mangleOverridable( mangleOverridable ), typeMode( typeMode ), 
+				: varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
+				mangleOverridable( mangleOverridable ), typeMode( typeMode ),
 				mangleGenericParams( mangleGenericParams ) {}
 
-			void Mangler_old::mangleDecl( DeclarationWithType * declaration ) {
+			void Mangler_old::mangleDecl( const DeclarationWithType * declaration ) {
 				bool wasTopLevel = isTopLevel;
 				if ( isTopLevel ) {
@@ -150,24 +150,24 @@
 			}
 
-			void Mangler_old::postvisit( ObjectDecl * declaration ) {
+			void Mangler_old::postvisit( const ObjectDecl * declaration ) {
 				mangleDecl( declaration );
 			}
 
-			void Mangler_old::postvisit( FunctionDecl * declaration ) {
+			void Mangler_old::postvisit( const FunctionDecl * declaration ) {
 				mangleDecl( declaration );
 			}
 
-			void Mangler_old::postvisit( VoidType * voidType ) {
+			void Mangler_old::postvisit( const VoidType * voidType ) {
 				printQualifiers( voidType );
 				mangleName << Encoding::void_t;
 			}
 
-			void Mangler_old::postvisit( BasicType * basicType ) {
+			void Mangler_old::postvisit( const BasicType * basicType ) {
 				printQualifiers( basicType );
-				assertf( basicType->get_kind() < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->get_kind() );
-				mangleName << Encoding::basicTypes[ basicType->get_kind() ];
-			}
-
-			void Mangler_old::postvisit( PointerType * pointerType ) {
+				assertf( basicType->kind < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
+				mangleName << Encoding::basicTypes[ basicType->kind ];
+			}
+
+			void Mangler_old::postvisit( const PointerType * pointerType ) {
 				printQualifiers( pointerType );
 				// mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
@@ -176,5 +176,5 @@
 			}
 
-			void Mangler_old::postvisit( ArrayType * arrayType ) {
+			void Mangler_old::postvisit( const ArrayType * arrayType ) {
 				// TODO: encode dimension
 				printQualifiers( arrayType );
@@ -183,5 +183,5 @@
 			}
 
-			void Mangler_old::postvisit( ReferenceType * refType ) {
+			void Mangler_old::postvisit( const ReferenceType * refType ) {
 				// don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
 				// Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
@@ -202,5 +202,5 @@
 			}
 
-			void Mangler_old::postvisit( FunctionType * functionType ) {
+			void Mangler_old::postvisit( const FunctionType * functionType ) {
 				printQualifiers( functionType );
 				mangleName << Encoding::function;
@@ -219,5 +219,5 @@
 			}
 
-			void Mangler_old::mangleRef( ReferenceToType * refType, std::string prefix ) {
+			void Mangler_old::mangleRef( const ReferenceToType * refType, std::string prefix ) {
 				printQualifiers( refType );
 
@@ -225,10 +225,10 @@
 
 				if ( mangleGenericParams ) {
-					std::list< Expression* >& params = refType->parameters;
+					const std::list< Expression* > & params = refType->parameters;
 					if ( ! params.empty() ) {
 						mangleName << "_";
-						for ( std::list< Expression* >::const_iterator param = params.begin(); param != params.end(); ++param ) {
-							TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
-							assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(*param));
+						for ( const Expression * param : params ) {
+							const TypeExpr * paramType = dynamic_cast< const TypeExpr * >( param );
+							assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
 							maybeAccept( paramType->type, *visitor );
 						}
@@ -238,17 +238,17 @@
 			}
 
-			void Mangler_old::postvisit( StructInstType * aggregateUseType ) {
+			void Mangler_old::postvisit( const StructInstType * aggregateUseType ) {
 				mangleRef( aggregateUseType, Encoding::struct_t );
 			}
 
-			void Mangler_old::postvisit( UnionInstType * aggregateUseType ) {
+			void Mangler_old::postvisit( const UnionInstType * aggregateUseType ) {
 				mangleRef( aggregateUseType, Encoding::union_t );
 			}
 
-			void Mangler_old::postvisit( EnumInstType * aggregateUseType ) {
+			void Mangler_old::postvisit( const EnumInstType * aggregateUseType ) {
 				mangleRef( aggregateUseType, Encoding::enum_t );
 			}
 
-			void Mangler_old::postvisit( TypeInstType * typeInst ) {
+			void Mangler_old::postvisit( const TypeInstType * typeInst ) {
 				VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
 				if ( varNum == varNums.end() ) {
@@ -266,10 +266,10 @@
 			}
 
-			void Mangler_old::postvisit( TraitInstType * inst ) {
+			void Mangler_old::postvisit( const TraitInstType * inst ) {
 				printQualifiers( inst );
 				mangleName << inst->name.size() << inst->name;
 			}
 
-			void Mangler_old::postvisit( TupleType * tupleType ) {
+			void Mangler_old::postvisit( const TupleType * tupleType ) {
 				printQualifiers( tupleType );
 				mangleName << Encoding::tuple << tupleType->types.size();
@@ -277,5 +277,5 @@
 			}
 
-			void Mangler_old::postvisit( VarArgsType * varArgsType ) {
+			void Mangler_old::postvisit( const VarArgsType * varArgsType ) {
 				printQualifiers( varArgsType );
 				static const std::string vargs = "__builtin_va_list";
@@ -283,13 +283,13 @@
 			}
 
-			void Mangler_old::postvisit( ZeroType * ) {
+			void Mangler_old::postvisit( const ZeroType * ) {
 				mangleName << Encoding::zero;
 			}
 
-			void Mangler_old::postvisit( OneType * ) {
+			void Mangler_old::postvisit( const OneType * ) {
 				mangleName << Encoding::one;
 			}
 
-			void Mangler_old::postvisit( QualifiedType * qualType ) {
+			void Mangler_old::postvisit( const QualifiedType * qualType ) {
 				bool inqual = inQualifiedType;
 				if (! inqual ) {
@@ -307,5 +307,5 @@
 			}
 
-			void Mangler_old::postvisit( TypeDecl * decl ) {
+			void Mangler_old::postvisit( const TypeDecl * decl ) {
 				// TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
 				// fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
@@ -314,6 +314,6 @@
 				// aside from the assert false.
 				assertf(false, "Mangler_old should not visit typedecl: %s", toCString(decl));
-				assertf( decl->get_kind() < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->get_kind() );
-				mangleName << Encoding::typeVariables[ decl->get_kind() ] << ( decl->name.length() ) << decl->name;
+				assertf( decl->kind < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
+				mangleName << Encoding::typeVariables[ decl->kind ] << ( decl->name.length() ) << decl->name;
 			}
 
@@ -324,13 +324,13 @@
 			}
 
-			void Mangler_old::printQualifiers( Type * type ) {
+			void Mangler_old::printQualifiers( const Type * type ) {
 				// skip if not including qualifiers
 				if ( typeMode ) return;
-				if ( ! type->get_forall().empty() ) {
+				if ( ! type->forall.empty() ) {
 					std::list< std::string > assertionNames;
 					int dcount = 0, fcount = 0, vcount = 0, acount = 0;
 					mangleName << Encoding::forall;
-					for ( Type::ForallList::iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
-						switch ( (*i)->get_kind() ) {
+					for ( const TypeDecl * i : type->forall ) {
+						switch ( i->kind ) {
 						  case TypeDecl::Dtype:
 							dcount++;
@@ -345,9 +345,9 @@
 							assert( false );
 						} // switch
-						varNums[ (*i)->name ] = std::make_pair( nextVarNum, (int)(*i)->get_kind() );
-						for ( std::list< DeclarationWithType* >::iterator assert = (*i)->assertions.begin(); assert != (*i)->assertions.end(); ++assert ) {
-							PassVisitor<Mangler_old> sub_mangler( 
+						varNums[ i->name ] = std::make_pair( nextVarNum, (int)i->kind );
+						for ( const DeclarationWithType * assert : i->assertions ) {
+							PassVisitor<Mangler_old> sub_mangler(
 								mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
-							(*assert)->accept( sub_mangler );
+							assert->accept( sub_mangler );
 							assertionNames.push_back( sub_mangler.pass.get_mangleName() );
 							acount++;
@@ -436,5 +436,5 @@
 
 		  private:
-			Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,  
+			Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
 				int nextVarNum, const VarMapType& varNums );
 			friend class ast::Pass<Mangler_new>;
@@ -457,13 +457,13 @@
 	namespace {
 		Mangler_new::Mangler_new( Mangle::Mode mode )
-			: nextVarNum( 0 ), isTopLevel( true ), 
+			: nextVarNum( 0 ), isTopLevel( true ),
 			mangleOverridable  ( ! mode.no_overrideable   ),
-			typeMode           (   mode.type              ), 
+			typeMode           (   mode.type              ),
 			mangleGenericParams( ! mode.no_generic_params ) {}
-		
-		Mangler_new::Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams, 
+
+		Mangler_new::Mangler_new( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
 			int nextVarNum, const VarMapType& varNums )
-			: varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ), 
-			mangleOverridable( mangleOverridable ), typeMode( typeMode ), 
+			: varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
+			mangleOverridable( mangleOverridable ), typeMode( typeMode ),
 			mangleGenericParams( mangleGenericParams ) {}
 
@@ -693,5 +693,5 @@
 						varNums[ decl->name ] = std::make_pair( nextVarNum, (int)decl->kind );
 						for ( const ast::DeclWithType * assert : decl->assertions ) {
-							ast::Pass<Mangler_new> sub_mangler( 
+							ast::Pass<Mangler_new> sub_mangler(
 								mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
 							assert->accept( sub_mangler );
Index: src/SymTab/Mangler.h
===================================================================
--- src/SymTab/Mangler.h	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
+++ src/SymTab/Mangler.h	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
@@ -40,10 +40,10 @@
 	namespace Mangler {
 		/// Mangle syntax tree object; primary interface to clients
-		std::string mangle( BaseSyntaxNode * decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true );
+		std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true );
 
 		/// Mangle a type name; secondary interface
-		std::string mangleType( Type* ty );
+		std::string mangleType( const Type * ty );
 		/// Mangle ignoring generic type parameters
-		std::string mangleConcrete( Type* ty );
+		std::string mangleConcrete( const Type * ty );
 
 		namespace Encoding {
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
+++ src/SynTree/Visitor.h	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
@@ -222,5 +222,5 @@
 
 template< typename TreeType, typename VisitorType >
-inline void maybeAccept( TreeType *tree, VisitorType &visitor ) {
+inline void maybeAccept( TreeType * tree, VisitorType & visitor ) {
 	if ( tree ) {
 		tree->accept( visitor );
@@ -228,11 +228,35 @@
 }
 
+template< typename TreeType, typename VisitorType >
+inline void maybeAccept( const TreeType * tree, VisitorType & visitor ) {
+	if ( tree ) {
+		tree->accept( visitor );
+	}
+}
+
 template< typename Container, typename VisitorType >
-inline void acceptAll( Container &container, VisitorType &visitor ) {
+inline void acceptAll( Container & container, VisitorType & visitor ) {
 	SemanticErrorException errors;
-	for ( typename Container::iterator i = container.begin(); i != container.end(); ++i ) {
+	for ( const auto * i : container ) {
 		try {
-			if ( *i ) {
-				(*i)->accept( visitor );
+			if ( i ) {
+				i->accept( visitor );
+			}
+		} catch( SemanticErrorException & e ) {
+			errors.append( e );
+		}
+	}
+	if ( ! errors.isEmpty() ) {
+		throw errors;
+	}
+}
+
+template< typename Container, typename VisitorType >
+inline void acceptAll( const Container & container, VisitorType & visitor ) {
+	SemanticErrorException errors;
+	for ( const auto * i : container ) {
+		try {
+			if ( i ) {
+				i->accept( visitor );
 			}
 		} catch( SemanticErrorException &e ) {
