Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/AST/Convert.cpp	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -1355,5 +1355,5 @@
 	ast::Node * node = nullptr;
 	/// cache of nodes that might be referenced by readonly<> for de-duplication
-	std::unordered_map< BaseSyntaxNode *, ast::Node * > cache = {};
+	std::unordered_map< const BaseSyntaxNode *, ast::Node * > cache = {};
 
 	// Local Utilities:
@@ -1422,8 +1422,8 @@
 		to<std::vector>::from( make_labels( std::move( labels ) ) )
 
-	static ast::CV::Qualifiers cv( Type * ty ) { return { ty->get_qualifiers().val }; }
+	static ast::CV::Qualifiers cv( const Type * ty ) { return { ty->tq.val }; }
 
 	/// returns true and sets `node` if in cache
-	bool inCache( BaseSyntaxNode * old ) {
+	bool inCache( const BaseSyntaxNode * old ) {
 		auto it = cache.find( old );
 		if ( it == cache.end() ) return false;
@@ -1434,5 +1434,5 @@
 	// Now all the visit functions:
 
-	virtual void visit( ObjectDecl * old ) override final {
+	virtual void visit( const ObjectDecl * old ) override final {
 		auto&& type = GET_ACCEPT_1(type, Type);
 		auto&& init = GET_ACCEPT_1(init, Init);
@@ -1465,5 +1465,5 @@
 	}
 
-	virtual void visit( FunctionDecl * old ) override final {
+	virtual void visit( const FunctionDecl * old ) override final {
 		if ( inCache( old ) ) return;
 		auto decl = new ast::FunctionDecl{
@@ -1498,5 +1498,5 @@
 	}
 
-	virtual void visit( StructDecl * old ) override final {
+	virtual void visit( const StructDecl * old ) override final {
 		if ( inCache( old ) ) return;
 		auto decl = new ast::StructDecl(
@@ -1523,5 +1523,5 @@
 	}
 
-	virtual void visit( UnionDecl * old ) override final {
+	virtual void visit( const UnionDecl * old ) override final {
 		if ( inCache( old ) ) return;
 		auto decl = new ast::UnionDecl(
@@ -1543,5 +1543,5 @@
 	}
 
-	virtual void visit( EnumDecl * old ) override final {
+	virtual void visit( const EnumDecl * old ) override final {
 		if ( inCache( old ) ) return;
 		auto decl = new ast::EnumDecl(
@@ -1563,5 +1563,5 @@
 	}
 
-	virtual void visit( TraitDecl * old ) override final {
+	virtual void visit( const TraitDecl * old ) override final {
 		if ( inCache( old ) ) return;
 		auto decl = new ast::TraitDecl(
@@ -1583,5 +1583,5 @@
 	}
 
-	virtual void visit( TypeDecl * old ) override final {
+	virtual void visit( const TypeDecl * old ) override final {
 		if ( inCache( old ) ) return;
 		auto decl = new ast::TypeDecl{
@@ -1603,5 +1603,5 @@
 	}
 
-	virtual void visit( TypedefDecl * old ) override final {
+	virtual void visit( const TypedefDecl * old ) override final {
 		auto decl = new ast::TypedefDecl(
 			old->location,
@@ -1620,5 +1620,5 @@
 	}
 
-	virtual void visit( AsmDecl * old ) override final {
+	virtual void visit( const AsmDecl * old ) override final {
 		auto decl = new ast::AsmDecl{
 			old->location,
@@ -1632,5 +1632,5 @@
 	}
 
-	virtual void visit( StaticAssertDecl * old ) override final {
+	virtual void visit( const StaticAssertDecl * old ) override final {
 		auto decl = new ast::StaticAssertDecl{
 			old->location,
@@ -1645,5 +1645,5 @@
 	}
 
-	virtual void visit( CompoundStmt * old ) override final {
+	virtual void visit( const CompoundStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		auto stmt = new ast::CompoundStmt(
@@ -1657,5 +1657,5 @@
 	}
 
-	virtual void visit( ExprStmt * old ) override final {
+	virtual void visit( const ExprStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		this->node = new ast::ExprStmt(
@@ -1667,5 +1667,5 @@
 	}
 
-	virtual void visit( AsmStmt * old ) override final {
+	virtual void visit( const AsmStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		this->node = new ast::AsmStmt(
@@ -1682,5 +1682,5 @@
 	}
 
-	virtual void visit( DirectiveStmt * old ) override final {
+	virtual void visit( const DirectiveStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		this->node = new ast::DirectiveStmt(
@@ -1692,5 +1692,5 @@
 	}
 
-	virtual void visit( IfStmt * old ) override final {
+	virtual void visit( const IfStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		this->node = new ast::IfStmt(
@@ -1705,5 +1705,5 @@
 	}
 
-	virtual void visit( SwitchStmt * old ) override final {
+	virtual void visit( const SwitchStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		this->node = new ast::SwitchStmt(
@@ -1716,5 +1716,5 @@
 	}
 
-	virtual void visit( CaseStmt * old ) override final {
+	virtual void visit( const CaseStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		this->node = new ast::CaseStmt(
@@ -1727,5 +1727,5 @@
 	}
 
-	virtual void visit( WhileStmt * old ) override final {
+	virtual void visit( const WhileStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		this->node = new ast::WhileStmt(
@@ -1740,5 +1740,5 @@
 	}
 
-	virtual void visit( ForStmt * old ) override final {
+	virtual void visit( const ForStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		this->node = new ast::ForStmt(
@@ -1753,5 +1753,5 @@
 	}
 
-	virtual void visit( BranchStmt * old ) override final {
+	virtual void visit( const BranchStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		if (old->computedTarget) {
@@ -1790,5 +1790,5 @@
 	}
 
-	virtual void visit( ReturnStmt * old ) override final {
+	virtual void visit( const ReturnStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		this->node = new ast::ReturnStmt(
@@ -1800,5 +1800,5 @@
 	}
 
-	virtual void visit( ThrowStmt * old ) override final {
+	virtual void visit( const ThrowStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		ast::ExceptionKind kind;
@@ -1824,5 +1824,5 @@
 	}
 
-	virtual void visit( TryStmt * old ) override final {
+	virtual void visit( const TryStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		this->node = new ast::TryStmt(
@@ -1836,5 +1836,5 @@
 	}
 
-	virtual void visit( CatchStmt * old ) override final {
+	virtual void visit( const CatchStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		ast::ExceptionKind kind;
@@ -1861,5 +1861,5 @@
 	}
 
-	virtual void visit( FinallyStmt * old ) override final {
+	virtual void visit( const FinallyStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		this->node = new ast::FinallyStmt(
@@ -1871,5 +1871,5 @@
 	}
 
-	virtual void visit( WaitForStmt * old ) override final {
+	virtual void visit( const WaitForStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		ast::WaitForStmt * stmt = new ast::WaitForStmt(
@@ -1903,5 +1903,5 @@
 	}
 
-	virtual void visit( WithStmt * old ) override final {
+	virtual void visit( const WithStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		this->node = new ast::WithStmt(
@@ -1914,5 +1914,5 @@
 	}
 
-	virtual void visit( NullStmt * old ) override final {
+	virtual void visit( const NullStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		this->node = new ast::NullStmt(
@@ -1923,5 +1923,5 @@
 	}
 
-	virtual void visit( DeclStmt * old ) override final {
+	virtual void visit( const DeclStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		this->node = new ast::DeclStmt(
@@ -1933,5 +1933,5 @@
 	}
 
-	virtual void visit( ImplicitCtorDtorStmt * old ) override final {
+	virtual void visit( const ImplicitCtorDtorStmt * old ) override final {
 		if ( inCache( old ) ) return;
 		auto stmt = new ast::ImplicitCtorDtorStmt(
@@ -1990,5 +1990,5 @@
 	}
 
-	ast::Expr * visitBaseExpr_SkipResultType(Expression * old, ast::Expr * nw) {
+	ast::Expr * visitBaseExpr_SkipResultType( const Expression * old, ast::Expr * nw) {
 
 		nw->env    = convertTypeSubstitution(old->env);
@@ -2000,5 +2000,5 @@
 	}
 
-	ast::Expr * visitBaseExpr(Expression * old, ast::Expr * nw) {
+	ast::Expr * visitBaseExpr( const Expression * old, ast::Expr * nw) {
 
 		nw->result = GET_ACCEPT_1(result, Type);
@@ -2006,5 +2006,5 @@
 	}
 
-	virtual void visit( ApplicationExpr * old ) override final {
+	virtual void visit( const ApplicationExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::ApplicationExpr(
@@ -2016,5 +2016,5 @@
 	}
 
-	virtual void visit( UntypedExpr * old ) override final {
+	virtual void visit( const UntypedExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::UntypedExpr(
@@ -2026,5 +2026,5 @@
 	}
 
-	virtual void visit( NameExpr * old ) override final {
+	virtual void visit( const NameExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::NameExpr(
@@ -2035,5 +2035,5 @@
 	}
 
-	virtual void visit( CastExpr * old ) override final {
+	virtual void visit( const CastExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::CastExpr(
@@ -2045,5 +2045,5 @@
 	}
 
-	virtual void visit( KeywordCastExpr * old) override final {
+	virtual void visit( const KeywordCastExpr * old) override final {
 		ast::KeywordCastExpr::Target castTarget = ast::KeywordCastExpr::NUMBER_OF_TARGETS;
 		switch (old->target) {
@@ -2070,5 +2070,5 @@
 	}
 
-	virtual void visit( VirtualCastExpr * old ) override final {
+	virtual void visit( const VirtualCastExpr * old ) override final {
 		this->node = visitBaseExpr_SkipResultType( old,
 			new ast::VirtualCastExpr(
@@ -2080,5 +2080,5 @@
 	}
 
-	virtual void visit( AddressExpr * old ) override final {
+	virtual void visit( const AddressExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::AddressExpr(
@@ -2089,5 +2089,5 @@
 	}
 
-	virtual void visit( LabelAddressExpr * old ) override final {
+	virtual void visit( const LabelAddressExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::LabelAddressExpr(
@@ -2098,5 +2098,5 @@
 	}
 
-	virtual void visit( UntypedMemberExpr * old ) override final {
+	virtual void visit( const UntypedMemberExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::UntypedMemberExpr(
@@ -2108,5 +2108,5 @@
 	}
 
-	virtual void visit( MemberExpr * old ) override final {
+	virtual void visit( const MemberExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::MemberExpr(
@@ -2118,5 +2118,5 @@
 	}
 
-	virtual void visit( VariableExpr * old ) override final {
+	virtual void visit( const VariableExpr * old ) override final {
 		auto expr = new ast::VariableExpr(
 			old->location
@@ -2129,16 +2129,16 @@
 	}
 
-	virtual void visit( ConstantExpr * old ) override final {
+	virtual void visit( const ConstantExpr * old ) override final {
 		ast::ConstantExpr *rslt = new ast::ConstantExpr(
 			old->location,
 			GET_ACCEPT_1(result, Type),
-			old->constant.get_value(),
+			old->constant.rep,
 			old->constant.ival
 		);
-		rslt->underlyer = getAccept1< ast::Type, Type* >( old->constant.get_type() );
+		rslt->underlyer = getAccept1< ast::Type, Type* >( old->constant.type );
 		this->node = visitBaseExpr( old, rslt );
 	}
 
-	virtual void visit( SizeofExpr * old ) override final {
+	virtual void visit( const SizeofExpr * old ) override final {
 		assert (old->expr || old->type);
 		assert (! (old->expr && old->type));
@@ -2161,5 +2161,5 @@
 	}
 
-	virtual void visit( AlignofExpr * old ) override final {
+	virtual void visit( const AlignofExpr * old ) override final {
 		assert (old->expr || old->type);
 		assert (! (old->expr && old->type));
@@ -2182,5 +2182,5 @@
 	}
 
-	virtual void visit( UntypedOffsetofExpr * old ) override final {
+	virtual void visit( const UntypedOffsetofExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::UntypedOffsetofExpr(
@@ -2192,5 +2192,5 @@
 	}
 
-	virtual void visit( OffsetofExpr * old ) override final {
+	virtual void visit( const OffsetofExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::OffsetofExpr(
@@ -2202,5 +2202,5 @@
 	}
 
-	virtual void visit( OffsetPackExpr * old ) override final {
+	virtual void visit( const OffsetPackExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::OffsetPackExpr(
@@ -2211,5 +2211,5 @@
 	}
 
-	virtual void visit( LogicalExpr * old ) override final {
+	virtual void visit( const LogicalExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::LogicalExpr(
@@ -2224,5 +2224,5 @@
 	}
 
-	virtual void visit( ConditionalExpr * old ) override final {
+	virtual void visit( const ConditionalExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::ConditionalExpr(
@@ -2235,5 +2235,5 @@
 	}
 
-	virtual void visit( CommaExpr * old ) override final {
+	virtual void visit( const CommaExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::CommaExpr(
@@ -2245,5 +2245,5 @@
 	}
 
-	virtual void visit( TypeExpr * old ) override final {
+	virtual void visit( const TypeExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::TypeExpr(
@@ -2254,5 +2254,5 @@
 	}
 
-	virtual void visit( AsmExpr * old ) override final {
+	virtual void visit( const AsmExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::AsmExpr(
@@ -2265,5 +2265,5 @@
 	}
 
-	virtual void visit( ImplicitCopyCtorExpr * old ) override final {
+	virtual void visit( const ImplicitCopyCtorExpr * old ) override final {
 		auto rslt = new ast::ImplicitCopyCtorExpr(
 			old->location,
@@ -2274,5 +2274,5 @@
 	}
 
-	virtual void visit( ConstructorExpr * old ) override final {
+	virtual void visit( const ConstructorExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::ConstructorExpr(
@@ -2283,5 +2283,5 @@
 	}
 
-	virtual void visit( CompoundLiteralExpr * old ) override final {
+	virtual void visit( const CompoundLiteralExpr * old ) override final {
 		this->node = visitBaseExpr_SkipResultType( old,
 			new ast::CompoundLiteralExpr(
@@ -2293,5 +2293,5 @@
 	}
 
-	virtual void visit( RangeExpr * old ) override final {
+	virtual void visit( const RangeExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::RangeExpr(
@@ -2303,5 +2303,5 @@
 	}
 
-	virtual void visit( UntypedTupleExpr * old ) override final {
+	virtual void visit( const UntypedTupleExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::UntypedTupleExpr(
@@ -2312,5 +2312,5 @@
 	}
 
-	virtual void visit( TupleExpr * old ) override final {
+	virtual void visit( const TupleExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::TupleExpr(
@@ -2321,5 +2321,5 @@
 	}
 
-	virtual void visit( TupleIndexExpr * old ) override final {
+	virtual void visit( const TupleIndexExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::TupleIndexExpr(
@@ -2331,5 +2331,5 @@
 	}
 
-	virtual void visit( TupleAssignExpr * old ) override final {
+	virtual void visit( const TupleAssignExpr * old ) override final {
 		this->node = visitBaseExpr_SkipResultType( old,
 			new ast::TupleAssignExpr(
@@ -2341,5 +2341,5 @@
 	}
 
-	virtual void visit( StmtExpr * old ) override final {
+	virtual void visit( const StmtExpr * old ) override final {
 		auto rslt = new ast::StmtExpr(
 			old->location,
@@ -2352,5 +2352,5 @@
 	}
 
-	virtual void visit( UniqueExpr * old ) override final {
+	virtual void visit( const UniqueExpr * old ) override final {
 		auto rslt = new ast::UniqueExpr(
 			old->location,
@@ -2364,5 +2364,5 @@
 	}
 
-	virtual void visit( UntypedInitExpr * old ) override final {
+	virtual void visit( const UntypedInitExpr * old ) override final {
 		std::deque<ast::InitAlternative> initAlts;
 		for (auto ia : old->initAlts) {
@@ -2381,5 +2381,5 @@
 	}
 
-	virtual void visit( InitExpr * old ) override final {
+	virtual void visit( const InitExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::InitExpr(
@@ -2391,5 +2391,5 @@
 	}
 
-	virtual void visit( DeletedExpr * old ) override final {
+	virtual void visit( const DeletedExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::DeletedExpr(
@@ -2403,5 +2403,5 @@
 	}
 
-	virtual void visit( DefaultArgExpr * old ) override final {
+	virtual void visit( const DefaultArgExpr * old ) override final {
 		this->node = visitBaseExpr( old,
 			new ast::DefaultArgExpr(
@@ -2412,5 +2412,5 @@
 	}
 
-	virtual void visit( GenericExpr * old ) override final {
+	virtual void visit( const GenericExpr * old ) override final {
 		std::vector<ast::GenericExpr::Association> associations;
 		for (auto association : old->associations) {
@@ -2429,5 +2429,5 @@
 	}
 
-	void visitType( Type * old, ast::Type * type ) {
+	void visitType( const Type * old, ast::Type * type ) {
 		// Some types do this in their constructor so add a check.
 		if ( !old->attributes.empty() && type->attributes.empty() ) {
@@ -2437,9 +2437,9 @@
 	}
 
-	virtual void visit( VoidType * old ) override final {
+	virtual void visit( const VoidType * old ) override final {
 		visitType( old, new ast::VoidType{ cv( old ) } );
 	}
 
-	virtual void visit( BasicType * old ) override final {
+	virtual void visit( const BasicType * old ) override final {
 		auto type = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind, cv( old ) };
 		// I believe this should always be a BasicType.
@@ -2450,5 +2450,5 @@
 	}
 
-	virtual void visit( PointerType * old ) override final {
+	virtual void visit( const PointerType * old ) override final {
 		visitType( old, new ast::PointerType{
 			GET_ACCEPT_1( base, Type ),
@@ -2460,5 +2460,5 @@
 	}
 
-	virtual void visit( ArrayType * old ) override final {
+	virtual void visit( const ArrayType * old ) override final {
 		visitType( old, new ast::ArrayType{
 			GET_ACCEPT_1( base, Type ),
@@ -2470,5 +2470,5 @@
 	}
 
-	virtual void visit( ReferenceType * old ) override final {
+	virtual void visit( const ReferenceType * old ) override final {
 		visitType( old, new ast::ReferenceType{
 			GET_ACCEPT_1( base, Type ),
@@ -2477,5 +2477,5 @@
 	}
 
-	virtual void visit( QualifiedType * old ) override final {
+	virtual void visit( const QualifiedType * old ) override final {
 		visitType( old, new ast::QualifiedType{
 			GET_ACCEPT_1( parent, Type ),
@@ -2485,5 +2485,5 @@
 	}
 
-	virtual void visit( FunctionType * old ) override final {
+	virtual void visit( const FunctionType * old ) override final {
 		auto ty = new ast::FunctionType {
 			(ast::ArgumentFlag)old->isVarArgs,
@@ -2496,5 +2496,5 @@
 	}
 
-	void postvisit( ReferenceToType * old, ast::ReferenceToType * ty ) {
+	void postvisit( const ReferenceToType * old, ast::ReferenceToType * ty ) {
 		ty->forall = GET_ACCEPT_V( forall, TypeDecl );
 		ty->params = GET_ACCEPT_V( parameters, Expr );
@@ -2503,5 +2503,5 @@
 	}
 
-	virtual void visit( StructInstType * old ) override final {
+	virtual void visit( const StructInstType * old ) override final {
 		ast::StructInstType * ty;
 		if ( old->baseStruct ) {
@@ -2521,5 +2521,5 @@
 	}
 
-	virtual void visit( UnionInstType * old ) override final {
+	virtual void visit( const UnionInstType * old ) override final {
 		ast::UnionInstType * ty;
 		if ( old->baseUnion ) {
@@ -2539,5 +2539,5 @@
 	}
 
-	virtual void visit( EnumInstType * old ) override final {
+	virtual void visit( const EnumInstType * old ) override final {
 		ast::EnumInstType * ty;
 		if ( old->baseEnum ) {
@@ -2557,5 +2557,5 @@
 	}
 
-	virtual void visit( TraitInstType * old ) override final {
+	virtual void visit( const TraitInstType * old ) override final {
 		ast::TraitInstType * ty;
 		if ( old->baseTrait ) {
@@ -2575,5 +2575,5 @@
 	}
 
-	virtual void visit( TypeInstType * old ) override final {
+	virtual void visit( const TypeInstType * old ) override final {
 		ast::TypeInstType * ty;
 		if ( old->baseType ) {
@@ -2595,5 +2595,5 @@
 	}
 
-	virtual void visit( TupleType * old ) override final {
+	virtual void visit( const TupleType * old ) override final {
 		visitType( old, new ast::TupleType{
 			GET_ACCEPT_V( types, Type ),
@@ -2603,5 +2603,5 @@
 	}
 
-	virtual void visit( TypeofType * old ) override final {
+	virtual void visit( const TypeofType * old ) override final {
 		visitType( old, new ast::TypeofType{
 			GET_ACCEPT_1( expr, Expr ),
@@ -2611,25 +2611,25 @@
 	}
 
-	virtual void visit( AttrType * ) override final {
+	virtual void visit( const AttrType * ) override final {
 		assertf( false, "AttrType deprecated in new AST." );
 	}
 
-	virtual void visit( VarArgsType * old ) override final {
+	virtual void visit( const VarArgsType * old ) override final {
 		visitType( old, new ast::VarArgsType{ cv( old ) } );
 	}
 
-	virtual void visit( ZeroType * old ) override final {
+	virtual void visit( const ZeroType * old ) override final {
 		visitType( old, new ast::ZeroType{ cv( old ) } );
 	}
 
-	virtual void visit( OneType * old ) override final {
+	virtual void visit( const OneType * old ) override final {
 		visitType( old, new ast::OneType{ cv( old ) } );
 	}
 
-	virtual void visit( GlobalScopeType * old ) override final {
+	virtual void visit( const GlobalScopeType * old ) override final {
 		visitType( old, new ast::GlobalScopeType{} );
 	}
 
-	virtual void visit( Designation * old ) override final {
+	virtual void visit( const Designation * old ) override final {
 		this->node = new ast::Designation(
 			old->location,
@@ -2638,5 +2638,5 @@
 	}
 
-	virtual void visit( SingleInit * old ) override final {
+	virtual void visit( const SingleInit * old ) override final {
 		this->node = new ast::SingleInit(
 			old->location,
@@ -2646,5 +2646,5 @@
 	}
 
-	virtual void visit( ListInit * old ) override final {
+	virtual void visit( const ListInit * old ) override final {
 		this->node = new ast::ListInit(
 			old->location,
@@ -2655,5 +2655,5 @@
 	}
 
-	virtual void visit( ConstructorInit * old ) override final {
+	virtual void visit( const ConstructorInit * old ) override final {
 		this->node = new ast::ConstructorInit(
 			old->location,
@@ -2664,5 +2664,5 @@
 	}
 
-	virtual void visit( Constant * ) override final {
+	virtual void visit( const Constant * ) override final {
 		// Handled in visit( ConstantEpxr * ).
 		// In the new tree, Constant fields are inlined into containing ConstantExpression.
@@ -2670,5 +2670,5 @@
 	}
 
-	virtual void visit( Attribute * old ) override final {
+	virtual void visit( const Attribute * old ) override final {
 		this->node = new ast::Attribute(
 			old->name,
@@ -2677,5 +2677,5 @@
 	}
 
-	virtual void visit( AttrExpr * ) override final {
+	virtual void visit( const AttrExpr * ) override final {
 		assertf( false, "AttrExpr deprecated in new AST." );
 	}
Index: src/AST/Expr.hpp
===================================================================
--- src/AST/Expr.hpp	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/AST/Expr.hpp	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -47,6 +47,6 @@
 
 	ParamEntry() : decl( 0 ), declptr( nullptr ), actualType( nullptr ), formalType( nullptr ), expr( nullptr ) {}
-	ParamEntry( 
-		UniqueId id, const Decl * declptr, const Type * actual, const Type * formal, 
+	ParamEntry(
+		UniqueId id, const Decl * declptr, const Type * actual, const Type * formal,
 		const Expr * e )
 	: decl( id ), declptr( declptr ), actualType( actual ), formalType( formal ), expr( e ) {}
@@ -112,7 +112,6 @@
 			case Empty: new(&data.resnSlots) ResnSlots{}; mode = Slots; // fallthrough
 			case Slots: return data.resnSlots;
-			case Params: assert(!"Cannot return to resnSlots from Params");
+			case Params: assertf(false, "Cannot return to resnSlots from Params"); abort();
 			}
-			return *((ResnSlots*)nullptr);
 		}
 
@@ -121,6 +120,6 @@
 				return data.resnSlots;
 			}
-			assert(!"Mode was not already resnSlots");
-			return *((ResnSlots*)nullptr);
+			assertf(false, "Mode was not already resnSlots");
+			abort();
 		}
 
@@ -131,6 +130,5 @@
 			case Params: return data.inferParams;
 			}
-			assert(!"unreachable");
-			return *((InferredParams*)nullptr);
+			assertf(false, "unreachable");
 		}
 
@@ -139,14 +137,14 @@
 				return data.inferParams;
 			}
-			assert(!"Mode was not already Params");
-			return *((InferredParams*)nullptr);
+			assertf(false, "Mode was not already Params");
+			abort();
 		}
 
 		void set_inferParams( InferredParams && ps ) {
 			switch(mode) {
-			case Slots: 
+			case Slots:
 				data.resnSlots.~ResnSlots();
 				// fallthrough
-			case Empty: 
+			case Empty:
 				new(&data.inferParams) InferredParams{ std::move( ps ) };
 				mode = Params;
@@ -172,5 +170,5 @@
 					data.inferParams[p.first] = std::move(p.second);
 				}
-			} else assert(!"invalid mode");
+			} else assertf(false, "invalid mode");
 		}
 	};
@@ -384,5 +382,5 @@
 
 	ConstantExpr(
-		const CodeLocation & loc, const Type * ty, const std::string & r, 
+		const CodeLocation & loc, const Type * ty, const std::string & r,
 			std::optional<unsigned long long> i )
 	: Expr( loc, ty ), rep( r ), ival( i ) {}
Index: src/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/Common/PassVisitor.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -60,102 +60,195 @@
 
 	virtual void visit( ObjectDecl * objectDecl ) override final;
+	virtual void visit( const ObjectDecl * objectDecl ) override final;
 	virtual void visit( FunctionDecl * functionDecl ) override final;
+	virtual void visit( const FunctionDecl * functionDecl ) override final;
 	virtual void visit( StructDecl * aggregateDecl ) override final;
+	virtual void visit( const StructDecl * aggregateDecl ) override final;
 	virtual void visit( UnionDecl * aggregateDecl ) override final;
+	virtual void visit( const UnionDecl * aggregateDecl ) override final;
 	virtual void visit( EnumDecl * aggregateDecl ) override final;
+	virtual void visit( const EnumDecl * aggregateDecl ) override final;
 	virtual void visit( TraitDecl * aggregateDecl ) override final;
+	virtual void visit( const TraitDecl * aggregateDecl ) override final;
 	virtual void visit( TypeDecl * typeDecl ) override final;
+	virtual void visit( const TypeDecl * typeDecl ) override final;
 	virtual void visit( TypedefDecl * typeDecl ) override final;
+	virtual void visit( const TypedefDecl * typeDecl ) override final;
 	virtual void visit( AsmDecl * asmDecl ) override final;
+	virtual void visit( const AsmDecl * asmDecl ) override final;
 	virtual void visit( StaticAssertDecl * assertDecl ) override final;
+	virtual void visit( const StaticAssertDecl * assertDecl ) override final;
 
 	virtual void visit( CompoundStmt * compoundStmt ) override final;
+	virtual void visit( const CompoundStmt * compoundStmt ) override final;
 	virtual void visit( ExprStmt * exprStmt ) override final;
+	virtual void visit( const ExprStmt * exprStmt ) override final;
 	virtual void visit( AsmStmt * asmStmt ) override final;
+	virtual void visit( const AsmStmt * asmStmt ) override final;
 	virtual void visit( DirectiveStmt * dirStmt ) override final;
+	virtual void visit( const DirectiveStmt * dirStmt ) override final;
 	virtual void visit( IfStmt * ifStmt ) override final;
+	virtual void visit( const IfStmt * ifStmt ) override final;
 	virtual void visit( WhileStmt * whileStmt ) override final;
+	virtual void visit( const WhileStmt * whileStmt ) override final;
 	virtual void visit( ForStmt * forStmt ) override final;
+	virtual void visit( const ForStmt * forStmt ) override final;
 	virtual void visit( SwitchStmt * switchStmt ) override final;
+	virtual void visit( const SwitchStmt * switchStmt ) override final;
 	virtual void visit( CaseStmt * caseStmt ) override final;
+	virtual void visit( const CaseStmt * caseStmt ) override final;
 	virtual void visit( BranchStmt * branchStmt ) override final;
+	virtual void visit( const BranchStmt * branchStmt ) override final;
 	virtual void visit( ReturnStmt * returnStmt ) override final;
+	virtual void visit( const ReturnStmt * returnStmt ) override final;
 	virtual void visit( ThrowStmt * throwStmt ) override final;
+	virtual void visit( const ThrowStmt * throwStmt ) override final;
 	virtual void visit( TryStmt * tryStmt ) override final;
+	virtual void visit( const TryStmt * tryStmt ) override final;
 	virtual void visit( CatchStmt * catchStmt ) override final;
+	virtual void visit( const CatchStmt * catchStmt ) override final;
 	virtual void visit( FinallyStmt * finallyStmt ) override final;
+	virtual void visit( const FinallyStmt * finallyStmt ) override final;
 	virtual void visit( WaitForStmt * waitforStmt ) override final;
+	virtual void visit( const WaitForStmt * waitforStmt ) override final;
 	virtual void visit( WithStmt * withStmt ) override final;
+	virtual void visit( const WithStmt * withStmt ) override final;
 	virtual void visit( NullStmt * nullStmt ) override final;
+	virtual void visit( const NullStmt * nullStmt ) override final;
 	virtual void visit( DeclStmt * declStmt ) override final;
+	virtual void visit( const DeclStmt * declStmt ) override final;
 	virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) override final;
+	virtual void visit( const ImplicitCtorDtorStmt * impCtorDtorStmt ) override final;
 
 	virtual void visit( ApplicationExpr * applicationExpr ) override final;
+	virtual void visit( const ApplicationExpr * applicationExpr ) override final;
 	virtual void visit( UntypedExpr * untypedExpr ) override final;
+	virtual void visit( const UntypedExpr * untypedExpr ) override final;
 	virtual void visit( NameExpr * nameExpr ) override final;
+	virtual void visit( const NameExpr * nameExpr ) override final;
 	virtual void visit( CastExpr * castExpr ) override final;
+	virtual void visit( const CastExpr * castExpr ) override final;
 	virtual void visit( KeywordCastExpr * castExpr ) override final;
+	virtual void visit( const KeywordCastExpr * castExpr ) override final;
 	virtual void visit( VirtualCastExpr * castExpr ) override final;
+	virtual void visit( const VirtualCastExpr * castExpr ) override final;
 	virtual void visit( AddressExpr * addressExpr ) override final;
+	virtual void visit( const AddressExpr * addressExpr ) override final;
 	virtual void visit( LabelAddressExpr * labAddressExpr ) override final;
+	virtual void visit( const LabelAddressExpr * labAddressExpr ) override final;
 	virtual void visit( UntypedMemberExpr * memberExpr ) override final;
+	virtual void visit( const UntypedMemberExpr * memberExpr ) override final;
 	virtual void visit( MemberExpr * memberExpr ) override final;
+	virtual void visit( const MemberExpr * memberExpr ) override final;
 	virtual void visit( VariableExpr * variableExpr ) override final;
+	virtual void visit( const VariableExpr * variableExpr ) override final;
 	virtual void visit( ConstantExpr * constantExpr ) override final;
+	virtual void visit( const ConstantExpr * constantExpr ) override final;
 	virtual void visit( SizeofExpr * sizeofExpr ) override final;
+	virtual void visit( const SizeofExpr * sizeofExpr ) override final;
 	virtual void visit( AlignofExpr * alignofExpr ) override final;
+	virtual void visit( const AlignofExpr * alignofExpr ) override final;
 	virtual void visit( UntypedOffsetofExpr * offsetofExpr ) override final;
+	virtual void visit( const UntypedOffsetofExpr * offsetofExpr ) override final;
 	virtual void visit( OffsetofExpr * offsetofExpr ) override final;
+	virtual void visit( const OffsetofExpr * offsetofExpr ) override final;
 	virtual void visit( OffsetPackExpr * offsetPackExpr ) override final;
+	virtual void visit( const OffsetPackExpr * offsetPackExpr ) override final;
 	virtual void visit( AttrExpr * attrExpr ) override final;
+	virtual void visit( const AttrExpr * attrExpr ) override final;
 	virtual void visit( LogicalExpr * logicalExpr ) override final;
+	virtual void visit( const LogicalExpr * logicalExpr ) override final;
 	virtual void visit( ConditionalExpr * conditionalExpr ) override final;
+	virtual void visit( const ConditionalExpr * conditionalExpr ) override final;
 	virtual void visit( CommaExpr * commaExpr ) override final;
+	virtual void visit( const CommaExpr * commaExpr ) override final;
 	virtual void visit( TypeExpr * typeExpr ) override final;
+	virtual void visit( const TypeExpr * typeExpr ) override final;
 	virtual void visit( AsmExpr * asmExpr ) override final;
+	virtual void visit( const AsmExpr * asmExpr ) override final;
 	virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) override final;
+	virtual void visit( const ImplicitCopyCtorExpr * impCpCtorExpr ) override final;
 	virtual void visit( ConstructorExpr *  ctorExpr ) override final;
+	virtual void visit( const ConstructorExpr *  ctorExpr ) override final;
 	virtual void visit( CompoundLiteralExpr * compLitExpr ) override final;
+	virtual void visit( const CompoundLiteralExpr * compLitExpr ) override final;
 	virtual void visit( RangeExpr * rangeExpr ) override final;
+	virtual void visit( const RangeExpr * rangeExpr ) override final;
 	virtual void visit( UntypedTupleExpr * tupleExpr ) override final;
+	virtual void visit( const UntypedTupleExpr * tupleExpr ) override final;
 	virtual void visit( TupleExpr * tupleExpr ) override final;
+	virtual void visit( const TupleExpr * tupleExpr ) override final;
 	virtual void visit( TupleIndexExpr * tupleExpr ) override final;
+	virtual void visit( const TupleIndexExpr * tupleExpr ) override final;
 	virtual void visit( TupleAssignExpr * assignExpr ) override final;
+	virtual void visit( const TupleAssignExpr * assignExpr ) override final;
 	virtual void visit( StmtExpr *  stmtExpr ) override final;
+	virtual void visit( const StmtExpr *  stmtExpr ) override final;
 	virtual void visit( UniqueExpr *  uniqueExpr ) override final;
+	virtual void visit( const UniqueExpr *  uniqueExpr ) override final;
 	virtual void visit( UntypedInitExpr *  initExpr ) override final;
+	virtual void visit( const UntypedInitExpr *  initExpr ) override final;
 	virtual void visit( InitExpr *  initExpr ) override final;
+	virtual void visit( const InitExpr *  initExpr ) override final;
 	virtual void visit( DeletedExpr *  delExpr ) override final;
+	virtual void visit( const DeletedExpr *  delExpr ) override final;
 	virtual void visit( DefaultArgExpr * argExpr ) override final;
+	virtual void visit( const DefaultArgExpr * argExpr ) override final;
 	virtual void visit( GenericExpr * genExpr ) override final;
+	virtual void visit( const GenericExpr * genExpr ) override final;
 
 	virtual void visit( VoidType * basicType ) override final;
+	virtual void visit( const VoidType * basicType ) override final;
 	virtual void visit( BasicType * basicType ) override final;
+	virtual void visit( const BasicType * basicType ) override final;
 	virtual void visit( PointerType * pointerType ) override final;
+	virtual void visit( const PointerType * pointerType ) override final;
 	virtual void visit( ArrayType * arrayType ) override final;
+	virtual void visit( const ArrayType * arrayType ) override final;
 	virtual void visit( ReferenceType * referenceType ) override final;
+	virtual void visit( const ReferenceType * referenceType ) override final;
 	virtual void visit( QualifiedType * qualType ) override final;
+	virtual void visit( const QualifiedType * qualType ) override final;
 	virtual void visit( FunctionType * functionType ) override final;
+	virtual void visit( const FunctionType * functionType ) override final;
 	virtual void visit( StructInstType * aggregateUseType ) override final;
+	virtual void visit( const StructInstType * aggregateUseType ) override final;
 	virtual void visit( UnionInstType * aggregateUseType ) override final;
+	virtual void visit( const UnionInstType * aggregateUseType ) override final;
 	virtual void visit( EnumInstType * aggregateUseType ) override final;
+	virtual void visit( const EnumInstType * aggregateUseType ) override final;
 	virtual void visit( TraitInstType * aggregateUseType ) override final;
+	virtual void visit( const TraitInstType * aggregateUseType ) override final;
 	virtual void visit( TypeInstType * aggregateUseType ) override final;
+	virtual void visit( const TypeInstType * aggregateUseType ) override final;
 	virtual void visit( TupleType * tupleType ) override final;
+	virtual void visit( const TupleType * tupleType ) override final;
 	virtual void visit( TypeofType * typeofType ) override final;
+	virtual void visit( const TypeofType * typeofType ) override final;
 	virtual void visit( AttrType * attrType ) override final;
+	virtual void visit( const AttrType * attrType ) override final;
 	virtual void visit( VarArgsType * varArgsType ) override final;
+	virtual void visit( const VarArgsType * varArgsType ) override final;
 	virtual void visit( ZeroType * zeroType ) override final;
+	virtual void visit( const ZeroType * zeroType ) override final;
 	virtual void visit( OneType * oneType ) override final;
+	virtual void visit( const OneType * oneType ) override final;
 	virtual void visit( GlobalScopeType * globalType ) override final;
+	virtual void visit( const GlobalScopeType * globalType ) override final;
 
 	virtual void visit( Designation * designation ) override final;
+	virtual void visit( const Designation * designation ) override final;
 	virtual void visit( SingleInit * singleInit ) override final;
+	virtual void visit( const SingleInit * singleInit ) override final;
 	virtual void visit( ListInit * listInit ) override final;
+	virtual void visit( const ListInit * listInit ) override final;
 	virtual void visit( ConstructorInit * ctorInit ) override final;
+	virtual void visit( const ConstructorInit * ctorInit ) override final;
 
 	virtual void visit( Constant * constant ) override final;
+	virtual void visit( const Constant * constant ) override final;
 
 	virtual void visit( Attribute * attribute ) override final;
+	virtual void visit( const Attribute * attribute ) override final;
 
 	virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override final;
@@ -265,12 +358,17 @@
 
 	template<typename pass_t> friend void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
+	template<typename pass_t> friend void acceptAll( const std::list< const Declaration * > &decls, PassVisitor< pass_t >& visitor );
 	template<typename pass_t> friend void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
 	template< typename TreeType, typename pass_t > friend void maybeAccept_impl( TreeType * tree, PassVisitor< pass_t > & visitor );
+	template< typename TreeType, typename pass_t > friend void maybeAccept_impl( const TreeType * tree, PassVisitor< pass_t > & visitor );
 	template< typename TreeType, typename pass_t > friend void maybeMutate_impl( TreeType *& tree, PassVisitor< pass_t > & mutator );
 	template< typename Container, typename pass_t > friend void maybeAccept_impl( Container & container, PassVisitor< pass_t > & visitor );
+	template< typename Container, typename pass_t > friend void maybeAccept_impl( const Container & container, PassVisitor< pass_t > & visitor );
 	template< typename Container, typename pass_t > friend void maybeMutate_impl( Container & container, PassVisitor< pass_t > & mutator );
 
 	template<typename node_type> void call_previsit ( node_type * node ) { previsit_impl ( pass, node, 0 ); }
+	template<typename node_type> void call_previsit ( const node_type * node ) { previsit_impl ( pass, node, 0 ); }
 	template<typename node_type> void call_postvisit( node_type * node ) { postvisit_impl( pass, node, 0 ); }
+	template<typename node_type> void call_postvisit( const node_type * node ) { postvisit_impl( pass, node, 0 ); }
 
 	template<typename node_type> void call_premutate ( node_type * node ) { premutate_impl( pass, node, 0 ); }
@@ -286,4 +384,5 @@
 	void visitStatementList ( std::list< Statement* > &statements );
 	void mutateStatementList( std::list< Statement* > &statements );
+	void visitStatementList ( const std::list< Statement * > & statements );
 
 	template< typename func_t >
@@ -291,4 +390,5 @@
 	Statement * visitStatement ( Statement * stmt );
 	Statement * mutateStatement( Statement * stmt );
+	void visitStatement ( const Statement * stmt );
 
 	template< typename func_t >
@@ -296,4 +396,5 @@
 	Expression * visitExpression ( Expression * expr );
 	Expression * mutateExpression( Expression * expr );
+	void visitExpression ( const Expression * expr );
 
 
Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/Common/PassVisitor.impl.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -80,4 +80,26 @@
 
 template< typename pass_type >
+inline void acceptAll( const std::list< const Declaration * > & decls, PassVisitor< pass_type >& visitor ) {
+	SemanticErrorException errors;
+
+	pass_visitor_stats.depth++;
+	pass_visitor_stats.max->push(pass_visitor_stats.depth);
+	pass_visitor_stats.avg->push(pass_visitor_stats.depth);
+	for ( const Declaration * decl : decls ) {
+		try {
+			// run visitor on declaration
+			maybeAccept_impl( decl, visitor );
+		}
+		catch( SemanticErrorException &e ) {
+			errors.append( e );
+		}
+	}
+	pass_visitor_stats.depth--;
+	if ( ! errors.isEmpty() ) {
+		throw errors;
+	}
+}
+
+template< typename pass_type >
 inline void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& mutator ) {
 	DeclList_t* beforeDecls = mutator.get_beforeDecls();
@@ -117,4 +139,12 @@
 }
 
+template< typename TreeType, typename pass_type >
+inline void maybeAccept_impl( const TreeType * tree, PassVisitor< pass_type > & visitor ) {
+	if ( ! visitor.get_visit_children() ) return;
+	if ( tree ) {
+		tree->accept( visitor );
+	}
+}
+
 template< typename Container, typename pass_type >
 inline void maybeAccept_impl( Container & container, PassVisitor< pass_type > & visitor ) {
@@ -129,4 +159,27 @@
 			if ( *i ) {
 				(*i)->accept( visitor );
+			}
+		} catch( SemanticErrorException &e ) {
+			errors.append( e );
+		}
+	}
+	pass_visitor_stats.depth--;
+	if ( ! errors.isEmpty() ) {
+		throw errors;
+	}
+}
+
+template< typename Container, typename pass_type >
+inline void maybeAccept_impl( const Container & container, PassVisitor< pass_type > & visitor ) {
+	if ( ! visitor.get_visit_children() ) return;
+	SemanticErrorException errors;
+
+	pass_visitor_stats.depth++;
+	pass_visitor_stats.max->push(pass_visitor_stats.depth);
+	pass_visitor_stats.avg->push(pass_visitor_stats.depth);
+	for ( const auto & i : container ) {
+		try {
+			if ( i ) {
+				i->accept( visitor );
 			}
 		} catch( SemanticErrorException &e ) {
@@ -227,4 +280,23 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visitStatementList( const std::list< Statement * > & statements ) {
+	if ( ! get_visit_children() ) return;
+	SemanticErrorException errors;
+
+	pass_visitor_stats.depth++;
+	pass_visitor_stats.max->push(pass_visitor_stats.depth);
+	pass_visitor_stats.avg->push(pass_visitor_stats.depth);
+	for ( const Statement * i : statements ) {
+		try {
+			maybeAccept_impl( i, *this );
+		} catch ( SemanticErrorException &e ) {
+			errors.append( e );
+		}
+	}
+	pass_visitor_stats.depth--;
+	if ( !errors.isEmpty() ) { throw errors; }
+}
+
+template< typename pass_type >
 void PassVisitor< pass_type >::mutateStatementList( std::list< Statement * > & statements ) {
 	handleStatementList( statements, [this]( Statement *& stmt) {
@@ -275,4 +347,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visitStatement( const Statement * stmt ) {
+	if ( ! get_visit_children() ) return;
+
+	// don't want statements from outer CompoundStmts to be added to this CompoundStmt
+	ValueGuardPtr< typename std::remove_pointer<decltype(get_env_ptr())>::type >  oldEnv( get_env_ptr() );
+
+	maybeAccept_impl( stmt, *this );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutateStatement( Statement * stmt ) {
 	return handleStatement( stmt, [this]( Statement * stmt ) {
@@ -306,4 +388,17 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visitExpression( const Expression * expr ) {
+	if ( ! get_visit_children() ) return;
+	if( !expr ) return;
+
+	auto env_ptr = get_env_ptr();
+	if ( env_ptr && expr->get_env() ) {
+		*env_ptr = expr->get_env();
+	}
+
+	maybeAccept_impl( expr, *this );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutateExpression( Expression * expr ) {
 	return handleExpression(expr, [this]( Expression * expr ) {
@@ -315,4 +410,14 @@
 template< typename TreeType, typename VisitorType >
 inline void indexerScopedAccept( TreeType * tree, VisitorType & visitor ) {
+	if ( ! visitor.get_visit_children() ) return;
+	auto guard = makeFuncGuard(
+		[&visitor]() { visitor.indexerScopeEnter(); },
+		[&visitor]() { visitor.indexerScopeLeave(); }
+	);
+	maybeAccept_impl( tree, visitor );
+}
+
+template< typename TreeType, typename VisitorType >
+inline void indexerScopedAccept( const TreeType * tree, VisitorType & visitor ) {
 	if ( ! visitor.get_visit_children() ) return;
 	auto guard = makeFuncGuard(
@@ -372,4 +477,16 @@
 
 	indexerAddId( node );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ObjectDecl * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->type         , *this );
+	maybeAccept_impl( node->init         , *this );
+	maybeAccept_impl( node->bitfieldWidth, *this );
+	maybeAccept_impl( node->attributes   , *this );
 
 	VISIT_END( node );
@@ -428,4 +545,28 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const FunctionDecl * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->withExprs, *this );
+	{
+		// 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
+		);
+		maybeAccept_impl( node->type, *this );
+		// function body needs to have the same scope as parameters - CompoundStmt will not enter
+		// a new scope if inFunction is true
+		ValueGuard< bool > oldInFunction( inFunction );
+		inFunction = true;
+		maybeAccept_impl( node->statements, *this );
+		maybeAccept_impl( node->attributes, *this );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 DeclarationWithType * PassVisitor< pass_type >::mutate( FunctionDecl * node ) {
 	MUTATE_START( node );
@@ -484,4 +625,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const StructDecl * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->parameters, *this );
+	maybeAccept_impl( node->members   , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Declaration * PassVisitor< pass_type >::mutate( StructDecl * node ) {
 	MUTATE_START( node );
@@ -522,4 +673,13 @@
 	VISIT_END( node );
 }
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const UnionDecl * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->parameters, *this );
+	maybeAccept_impl( node->members   , *this );
+
+	VISIT_END( node );
+}
 
 template< typename pass_type >
@@ -557,4 +717,15 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const EnumDecl * node ) {
+	VISIT_START( node );
+
+	// unlike structs, traits, and unions, enums inject their members into the global scope
+	maybeAccept_impl( node->parameters, *this );
+	maybeAccept_impl( node->members   , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Declaration * PassVisitor< pass_type >::mutate( EnumDecl * node ) {
 	MUTATE_START( node );
@@ -587,4 +758,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const TraitDecl * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->parameters, *this );
+	maybeAccept_impl( node->members   , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Declaration * PassVisitor< pass_type >::mutate( TraitDecl * node ) {
 	MUTATE_START( node );
@@ -625,4 +806,16 @@
 }
 
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const TypeDecl * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->parameters, *this );
+	maybeAccept_impl( node->base      , *this );
+	maybeAccept_impl( node->assertions, *this );
+
+	VISIT_END( node );
+}
+
 template< typename pass_type >
 Declaration * PassVisitor< pass_type >::mutate( TypeDecl * node ) {
@@ -667,4 +860,15 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const TypedefDecl * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->parameters, *this );
+	maybeAccept_impl( node->base      , *this );
+	maybeAccept_impl( node->assertions, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Declaration * PassVisitor< pass_type >::mutate( TypedefDecl * node ) {
 	MUTATE_START( node );
@@ -695,4 +899,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const AsmDecl * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->stmt, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 AsmDecl * PassVisitor< pass_type >::mutate( AsmDecl * node ) {
 	MUTATE_START( node );
@@ -710,4 +923,14 @@
 
 	node->condition = visitExpression( node->condition );
+	maybeAccept_impl( node->message, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const StaticAssertDecl * node ) {
+	VISIT_START( node );
+
+	visitExpression( node->condition );
 	maybeAccept_impl( node->message, *this );
 
@@ -742,4 +965,18 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const CompoundStmt * node ) {
+	VISIT_START( node );
+	{
+		// do not enter a new scope if inFunction is true - needs to check old state before the assignment
+		ValueGuard< bool > oldInFunction( inFunction );
+		auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
+		auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
+		inFunction = false;
+		visitStatementList( node->kids );
+	}
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 CompoundStmt * PassVisitor< pass_type >::mutate( CompoundStmt * node ) {
 	MUTATE_START( node );
@@ -767,4 +1004,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ExprStmt * node ) {
+	VISIT_START( node );
+
+	visitExpression( node->expr );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( ExprStmt * node ) {
 	MUTATE_START( node );
@@ -790,4 +1036,16 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const AsmStmt * node ) {
+	VISIT_START( node )
+
+	maybeAccept_impl( node->instruction, *this );
+	maybeAccept_impl( node->output, *this );
+	maybeAccept_impl( node->input, *this );
+	maybeAccept_impl( node->clobber, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( AsmStmt * node ) {
 	MUTATE_START( node );
@@ -811,4 +1069,11 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const DirectiveStmt * node ) {
+	VISIT_START( node )
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( DirectiveStmt * node ) {
 	MUTATE_START( node );
@@ -825,5 +1090,5 @@
 		// if statements introduce a level of scope (for the initialization)
 		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeAccept_impl( node->get_initialization(), *this );
+		maybeAccept_impl( node->initialization, *this );
 		visitExpression ( node->condition );
 		node->thenPart = visitStatement( node->thenPart );
@@ -834,4 +1099,16 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const IfStmt * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->initialization, *this );
+	visitExpression ( node->condition );
+	visitStatement( node->thenPart );
+	visitStatement( node->elsePart );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( IfStmt * node ) {
 	MUTATE_START( node );
@@ -839,5 +1116,5 @@
 		// if statements introduce a level of scope (for the initialization)
 		auto guard = makeFuncGuard( [this]() { indexerScopeEnter(); }, [this]() { indexerScopeLeave(); } );
-		maybeMutate_impl( node->get_initialization(), *this );
+		maybeMutate_impl( node->initialization, *this );
 		node->condition = mutateExpression( node->condition );
 		node->thenPart  = mutateStatement ( node->thenPart  );
@@ -860,4 +1137,15 @@
 		node->body = visitStatement( node->body );
 	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const WhileStmt * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->initialization, *this );
+	visitExpression ( node->condition );
+	visitStatement( node->body );
 
 	VISIT_END( node );
@@ -897,4 +1185,16 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ForStmt * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->initialization, *this );
+	visitExpression( node->condition );
+	visitExpression( node->increment );
+	visitStatement( node->body );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( ForStmt * node ) {
 	MUTATE_START( node );
@@ -923,4 +1223,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const SwitchStmt * node ) {
+	VISIT_START( node );
+
+	visitExpression   ( node->condition  );
+	visitStatementList( node->statements );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( SwitchStmt * node ) {
 	MUTATE_START( node );
@@ -945,4 +1255,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const CaseStmt * node ) {
+	VISIT_START( node );
+
+	visitExpression   ( node->condition );
+	visitStatementList( node->stmts     );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( CaseStmt * node ) {
 	MUTATE_START( node );
@@ -963,4 +1283,10 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const BranchStmt * node ) {
+	VISIT_START( node );
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( BranchStmt * node ) {
 	MUTATE_START( node );
@@ -980,4 +1306,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ReturnStmt * node ) {
+	VISIT_START( node );
+
+	visitExpression( node->expr );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( ReturnStmt * node ) {
 	MUTATE_START( node );
@@ -990,5 +1325,4 @@
 //--------------------------------------------------------------------------
 // ThrowStmt
-
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( ThrowStmt * node ) {
@@ -1002,4 +1336,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ThrowStmt * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->expr, *this );
+	maybeAccept_impl( node->target, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( ThrowStmt * node ) {
 	MUTATE_START( node );
@@ -1015,4 +1359,15 @@
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( TryStmt * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->block       , *this );
+	maybeAccept_impl( node->handlers    , *this );
+	maybeAccept_impl( node->finallyBlock, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const TryStmt * node ) {
 	VISIT_START( node );
 
@@ -1051,4 +1406,15 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const CatchStmt * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->decl, *this );
+	visitExpression( node->cond );
+	visitStatement ( node->body );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( CatchStmt * node ) {
 	MUTATE_START( node );
@@ -1075,4 +1441,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const FinallyStmt * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->block, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( FinallyStmt * node ) {
 	MUTATE_START( node );
@@ -1107,4 +1482,25 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const WaitForStmt * node ) {
+	VISIT_START( node );
+
+	for( auto & clause : node->clauses ) {
+		maybeAccept_impl( clause.target.function, *this );
+		maybeAccept_impl( clause.target.arguments, *this );
+
+		maybeAccept_impl( clause.statement, *this );
+		maybeAccept_impl( clause.condition, *this );
+	}
+
+	maybeAccept_impl( node->timeout.time, *this );
+	maybeAccept_impl( node->timeout.statement, *this );
+	maybeAccept_impl( node->timeout.condition, *this );
+	maybeAccept_impl( node->orelse.statement, *this );
+	maybeAccept_impl( node->orelse.condition, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( WaitForStmt * node ) {
 	MUTATE_START( node );
@@ -1130,5 +1526,5 @@
 
 //--------------------------------------------------------------------------
-// NullStmt
+// WithStmt
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( WithStmt * node ) {
@@ -1145,4 +1541,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const WithStmt * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->exprs, *this );
+	maybeAccept_impl( node->stmt, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( WithStmt * node ) {
 	MUTATE_START( node );
@@ -1166,4 +1572,10 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const NullStmt * node ) {
+	VISIT_START( node );
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 NullStmt * PassVisitor< pass_type >::mutate( NullStmt * node ) {
 	MUTATE_START( node );
@@ -1183,4 +1595,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const DeclStmt * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->decl, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Statement * PassVisitor< pass_type >::mutate( DeclStmt * node ) {
 	MUTATE_START( node );
@@ -1195,4 +1616,13 @@
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( ImplicitCtorDtorStmt * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->callStmt, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ImplicitCtorDtorStmt * node ) {
 	VISIT_START( node );
 
@@ -1220,4 +1650,15 @@
 	maybeAccept_impl        ( node->function, *this );
 	maybeAccept_impl        ( node->args    , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ApplicationExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result  , *this );
+	maybeAccept_impl( node->function, *this );
+	maybeAccept_impl( node->args    , *this );
 
 	VISIT_END( node );
@@ -1253,4 +1694,17 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const UntypedExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+
+	for ( auto expr : node->args ) {
+		visitExpression( expr );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( UntypedExpr * node ) {
 	MUTATE_START( node );
@@ -1278,4 +1732,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const NameExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( NameExpr * node ) {
 	MUTATE_START( node );
@@ -1295,4 +1758,14 @@
 	indexerScopedAccept( node->result, *this );
 	maybeAccept_impl        ( node->arg   , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const CastExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->arg   , *this );
 
 	VISIT_END( node );
@@ -1323,4 +1796,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const KeywordCastExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->arg   , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( KeywordCastExpr * node ) {
 	MUTATE_START( node );
@@ -1346,4 +1829,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const VirtualCastExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->arg, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( VirtualCastExpr * node ) {
 	MUTATE_START( node );
@@ -1369,4 +1862,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const AddressExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->arg   , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( AddressExpr * node ) {
 	MUTATE_START( node );
@@ -1391,4 +1894,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const LabelAddressExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( LabelAddressExpr * node ) {
 	MUTATE_START( node );
@@ -1409,4 +1921,15 @@
 	maybeAccept_impl   ( node->aggregate, *this );
 	maybeAccept_impl   ( node->member   , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const UntypedMemberExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result   , *this );
+	maybeAccept_impl( node->aggregate, *this );
+	maybeAccept_impl( node->member   , *this );
 
 	VISIT_END( node );
@@ -1438,4 +1961,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const MemberExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result   , *this );
+	maybeAccept_impl( node->aggregate, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( MemberExpr * node ) {
 	MUTATE_START( node );
@@ -1460,4 +1993,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const VariableExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( VariableExpr * node ) {
 	MUTATE_START( node );
@@ -1477,4 +2019,14 @@
 	indexerScopedAccept( node->result   , *this );
 	maybeAccept_impl   ( &node->constant, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ConstantExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result   , *this );
+	maybeAccept_impl( &node->constant, *this );
 
 	VISIT_END( node );
@@ -1501,4 +2053,18 @@
 
 	indexerScopedAccept( node->result, *this );
+	if ( node->get_isType() ) {
+		maybeAccept_impl( node->type, *this );
+	} else {
+		maybeAccept_impl( node->expr, *this );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const SizeofExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
 	if ( node->get_isType() ) {
 		maybeAccept_impl( node->type, *this );
@@ -1542,4 +2108,18 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const AlignofExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	if ( node->get_isType() ) {
+		maybeAccept_impl( node->type, *this );
+	} else {
+		maybeAccept_impl( node->expr, *this );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( AlignofExpr * node ) {
 	MUTATE_START( node );
@@ -1569,4 +2149,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const UntypedOffsetofExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->type  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( UntypedOffsetofExpr * node ) {
 	MUTATE_START( node );
@@ -1592,4 +2182,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const OffsetofExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->type  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( OffsetofExpr * node ) {
 	MUTATE_START( node );
@@ -1615,4 +2215,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const OffsetPackExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->type  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( OffsetPackExpr * node ) {
 	MUTATE_START( node );
@@ -1632,4 +2242,18 @@
 
 	indexerScopedAccept( node->result, *this );
+	if ( node->get_isType() ) {
+		maybeAccept_impl( node->type, *this );
+	} else {
+		maybeAccept_impl( node->expr, *this );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const AttrExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
 	if ( node->get_isType() ) {
 		maybeAccept_impl( node->type, *this );
@@ -1670,4 +2294,15 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const LogicalExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->arg1  , *this );
+	maybeAccept_impl( node->arg2  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( LogicalExpr * node ) {
 	MUTATE_START( node );
@@ -1691,4 +2326,16 @@
 	maybeAccept_impl        ( node->arg2  , *this );
 	maybeAccept_impl        ( node->arg3  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ConditionalExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->arg1  , *this );
+	maybeAccept_impl( node->arg2  , *this );
+	maybeAccept_impl( node->arg3  , *this );
 
 	VISIT_END( node );
@@ -1722,4 +2369,15 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const CommaExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->arg1  , *this );
+	maybeAccept_impl( node->arg2  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( CommaExpr * node ) {
 	MUTATE_START( node );
@@ -1746,4 +2404,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const TypeExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->type, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( TypeExpr * node ) {
 	MUTATE_START( node );
@@ -1766,4 +2434,16 @@
 	maybeAccept_impl   ( node->constraint, *this );
 	maybeAccept_impl   ( node->operand   , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const AsmExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result    , *this );
+	maybeAccept_impl( node->inout     , *this );
+	maybeAccept_impl( node->constraint, *this );
+	maybeAccept_impl( node->operand   , *this );
 
 	VISIT_END( node );
@@ -1796,4 +2476,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ImplicitCopyCtorExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result    , *this );
+	maybeAccept_impl( node->callExpr  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( ImplicitCopyCtorExpr * node ) {
 	MUTATE_START( node );
@@ -1819,4 +2509,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ConstructorExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result  , *this );
+	maybeAccept_impl( node->callExpr, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( ConstructorExpr * node ) {
 	MUTATE_START( node );
@@ -1842,4 +2542,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const CompoundLiteralExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result     , *this );
+	maybeAccept_impl( node->initializer, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( CompoundLiteralExpr * node ) {
 	MUTATE_START( node );
@@ -1861,4 +2571,15 @@
 	maybeAccept_impl   ( node->low   , *this );
 	maybeAccept_impl   ( node->high  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const RangeExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->low   , *this );
+	maybeAccept_impl( node->high  , *this );
 
 	VISIT_END( node );
@@ -1890,4 +2611,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const UntypedTupleExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->exprs , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( UntypedTupleExpr * node ) {
 	MUTATE_START( node );
@@ -1913,4 +2644,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const TupleExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->exprs , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( TupleExpr * node ) {
 	MUTATE_START( node );
@@ -1936,4 +2677,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const TupleIndexExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->tuple , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( TupleIndexExpr * node ) {
 	MUTATE_START( node );
@@ -1954,4 +2705,14 @@
 	indexerScopedAccept( node->result  , *this );
 	maybeAccept_impl   ( node->stmtExpr, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const TupleAssignExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result  , *this );
+	maybeAccept_impl( node->stmtExpr, *this );
 
 	VISIT_END( node );
@@ -1989,4 +2750,16 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const StmtExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result     , *this );
+	maybeAccept_impl( node->statements , *this );
+	maybeAccept_impl( node->returnDecls, *this );
+	maybeAccept_impl( node->dtors      , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( StmtExpr * node ) {
 	MUTATE_START( node );
@@ -2018,4 +2791,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const UniqueExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->expr  , *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( UniqueExpr * node ) {
 	MUTATE_START( node );
@@ -2036,4 +2819,15 @@
 	indexerScopedAccept( node->result, *this );
 	maybeAccept_impl   ( node->expr  , *this );
+	// not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const UntypedInitExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->expr  , *this );
 	// not currently visiting initAlts, but this doesn't matter since this node is only used in the resolver.
 
@@ -2067,4 +2861,15 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const InitExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->expr  , *this );
+	maybeAccept_impl( node->designation, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( InitExpr * node ) {
 	MUTATE_START( node );
@@ -2092,4 +2897,15 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const DeletedExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->expr, *this );
+	// don't visit deleteStmt, because it is a pointer to somewhere else in the tree.
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Expression * PassVisitor< pass_type >::mutate( DeletedExpr * node ) {
 	MUTATE_START( node );
@@ -2109,4 +2925,14 @@
 
 	indexerScopedAccept( node->result, *this );
+	maybeAccept_impl( node->expr, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const DefaultArgExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
 	maybeAccept_impl( node->expr, *this );
 
@@ -2135,4 +2961,18 @@
 	for ( GenericExpr::Association & assoc : node->associations ) {
 		indexerScopedAccept( assoc.type, *this );
+		maybeAccept_impl( assoc.expr, *this );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const GenericExpr * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->result, *this );
+	maybeAccept_impl( node->control, *this );
+	for ( const GenericExpr::Association & assoc : node->associations ) {
+		maybeAccept_impl( assoc.type, *this );
 		maybeAccept_impl( assoc.expr, *this );
 	}
@@ -2168,4 +3008,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const VoidType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( VoidType * node ) {
 	MUTATE_START( node );
@@ -2180,4 +3029,13 @@
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( BasicType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const BasicType * node ) {
 	VISIT_START( node );
 
@@ -2210,4 +3068,15 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const PointerType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+	// xxx - should PointerType visit/mutate dimension?
+	maybeAccept_impl( node->base, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( PointerType * node ) {
 	MUTATE_START( node );
@@ -2234,4 +3103,15 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ArrayType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+	maybeAccept_impl( node->dimension, *this );
+	maybeAccept_impl( node->base, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( ArrayType * node ) {
 	MUTATE_START( node );
@@ -2257,4 +3137,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ReferenceType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+	maybeAccept_impl( node->base, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( ReferenceType * node ) {
 	MUTATE_START( node );
@@ -2280,4 +3170,15 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const QualifiedType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+	maybeAccept_impl( node->parent, *this );
+	maybeAccept_impl( node->child, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( QualifiedType * node ) {
 	MUTATE_START( node );
@@ -2294,4 +3195,15 @@
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( FunctionType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+	maybeAccept_impl( node->returnVals, *this );
+	maybeAccept_impl( node->parameters, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const FunctionType * node ) {
 	VISIT_START( node );
 
@@ -2332,4 +3244,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const StructInstType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall    , *this );
+	maybeAccept_impl( node->parameters, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( StructInstType * node ) {
 	MUTATE_START( node );
@@ -2364,4 +3286,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const UnionInstType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall    , *this );
+	maybeAccept_impl( node->parameters, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( UnionInstType * node ) {
 	MUTATE_START( node );
@@ -2391,4 +3323,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const EnumInstType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+	maybeAccept_impl( node->parameters, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( EnumInstType * node ) {
 	MUTATE_START( node );
@@ -2413,4 +3355,14 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const TraitInstType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall    , *this );
+	maybeAccept_impl( node->parameters, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( TraitInstType * node ) {
 	MUTATE_START( node );
@@ -2426,4 +3378,14 @@
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( TypeInstType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall    , *this );
+	maybeAccept_impl( node->parameters, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const TypeInstType * node ) {
 	VISIT_START( node );
 
@@ -2458,4 +3420,15 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const TupleType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+	maybeAccept_impl( node->types, *this );
+	maybeAccept_impl( node->members, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( TupleType * node ) {
 	MUTATE_START( node );
@@ -2472,4 +3445,14 @@
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( TypeofType * node ) {
+	VISIT_START( node );
+
+	assert( node->expr );
+	maybeAccept_impl( node->expr, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const TypeofType * node ) {
 	VISIT_START( node );
 
@@ -2508,4 +3491,19 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const AttrType * node ) {
+	VISIT_START( node );
+
+	if ( node->isType ) {
+		assert( node->type );
+		maybeAccept_impl( node->type, *this );
+	} else {
+		assert( node->expr );
+		maybeAccept_impl( node->expr, *this );
+	} // if
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( AttrType * node ) {
 	MUTATE_START( node );
@@ -2534,4 +3532,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const VarArgsType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( VarArgsType * node ) {
 	MUTATE_START( node );
@@ -2554,4 +3561,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ZeroType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( ZeroType * node ) {
 	MUTATE_START( node );
@@ -2574,4 +3590,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const OneType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( OneType * node ) {
 	MUTATE_START( node );
@@ -2594,4 +3619,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const GlobalScopeType * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->forall, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Type * PassVisitor< pass_type >::mutate( GlobalScopeType * node ) {
 	MUTATE_START( node );
@@ -2614,4 +3648,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const Designation * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->designators, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Designation * PassVisitor< pass_type >::mutate( Designation * node ) {
 	MUTATE_START( node );
@@ -2634,4 +3677,13 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const SingleInit * node ) {
+	VISIT_START( node );
+
+	visitExpression( node->value );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Initializer * PassVisitor< pass_type >::mutate( SingleInit * node ) {
 	MUTATE_START( node );
@@ -2646,4 +3698,14 @@
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( ListInit * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->designations, *this );
+	maybeAccept_impl( node->initializers, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ListInit * node ) {
 	VISIT_START( node );
 
@@ -2678,4 +3740,15 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const ConstructorInit * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->ctor, *this );
+	maybeAccept_impl( node->dtor, *this );
+	maybeAccept_impl( node->init, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Initializer * PassVisitor< pass_type >::mutate( ConstructorInit * node ) {
 	MUTATE_START( node );
@@ -2698,4 +3771,11 @@
 
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( const Constant * node ) {
+	VISIT_START( node );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 Constant * PassVisitor< pass_type >::mutate( Constant * node  )  {
 	MUTATE_START( node );
@@ -2708,4 +3788,13 @@
 template< typename pass_type >
 void PassVisitor< pass_type >::visit( Attribute * node ) {
+	VISIT_START( node );
+
+	maybeAccept_impl( node->parameters, *this );
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( const Attribute * node ) {
 	VISIT_START( node );
 
Index: src/Common/PassVisitor.proto.h
===================================================================
--- src/Common/PassVisitor.proto.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/Common/PassVisitor.proto.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -118,4 +118,21 @@
 static inline void postvisit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) node_type * node, __attribute__((unused)) long unused ) {}
 
+template<typename pass_type, typename node_type>
+static inline auto previsit_impl( pass_type& pass, const node_type * node, __attribute__((unused)) int unused ) -> decltype( pass.previsit( node ), void() ) {
+	pass.previsit( node );
+}
+
+template<typename pass_type, typename node_type>
+static inline void previsit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) const node_type * node, __attribute__((unused)) long unused ) {}
+
+
+template<typename pass_type, typename node_type>
+static inline auto postvisit_impl( pass_type& pass, const node_type * node, __attribute__((unused)) int unused ) -> decltype( pass.postvisit( node ), void() ) {
+	pass.postvisit( node );
+}
+
+template<typename pass_type, typename node_type>
+static inline void postvisit_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) const node_type * node, __attribute__((unused)) long unused ) {}
+
 //---------------------------------------------------------
 // Mutate
@@ -200,7 +217,6 @@
 	pass.indexer.func( arg );                                                                                                \
 }                                                                                                                              \
-                                                                                                                               \
-template<typename pass_type>                                                                                                   \
-static inline void indexer_impl_##func ( pass_type &, long, type ) { }                                                          \
+template<typename pass_type>                                                                                                   \
+static inline void indexer_impl_##func ( pass_type &, long, type ) { }
 
 #define INDEXER_FUNC2( func, type1, type2 )                                                                                             \
@@ -209,5 +225,4 @@
 	pass.indexer.func( arg1, arg2 );                                                                                                \
 }                                                                                                                              \
-                                                                                                                               \
 template<typename pass_type>                                                                                                   \
 static inline void indexer_impl_##func ( pass_type &, long, type1, type2 ) { }
@@ -233,5 +248,5 @@
 
 template<typename pass_type>
-static inline auto indexer_impl_addStructFwd( pass_type &, long, StructDecl * ) {}
+static inline auto indexer_impl_addStructFwd( pass_type &, long, const StructDecl * ) {}
 
 template<typename pass_type>
@@ -243,5 +258,5 @@
 
 template<typename pass_type>
-static inline auto indexer_impl_addUnionFwd( pass_type &, long, UnionDecl * ) {}
+static inline auto indexer_impl_addUnionFwd( pass_type &, long, const UnionDecl * ) {}
 
 template<typename pass_type>
Index: src/ResolvExpr/CastCost.cc
===================================================================
--- src/ResolvExpr/CastCost.cc	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/ResolvExpr/CastCost.cc	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -37,15 +37,15 @@
 	struct CastCost_old : public ConversionCost {
 	  public:
-		CastCost_old( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
+		CastCost_old( const Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
 
 		using ConversionCost::previsit;
 		using ConversionCost::postvisit;
-		void postvisit( BasicType * basicType );
-		void postvisit( PointerType * pointerType );
+		void postvisit( const BasicType * basicType );
+		void postvisit( const PointerType * pointerType );
 	};
 
-	Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
-		if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
-			if ( const EqvClass* eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
+	Cost castCost( const Type *src, const Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
+		if ( const TypeInstType *destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) {
+			if ( const EqvClass* eqvClass = env.lookup( destAsTypeInst->name ) ) {
 				if ( eqvClass->type ) {
 					return castCost( src, eqvClass->type, indexer, env );
@@ -53,7 +53,7 @@
 					return Cost::infinity;
 				}
-			} else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) {
+			} else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->name ) ) {
 				// all typedefs should be gone by this point
-				TypeDecl *type = strict_dynamic_cast< TypeDecl* >( namedType );
+				const TypeDecl * type = strict_dynamic_cast< const TypeDecl* >( namedType );
 				if ( type->base ) {
 					return castCost( src, type->base, indexer, env ) + Cost::safe;
@@ -74,15 +74,15 @@
 			PRINT( std::cerr << "compatible!" << std::endl; )
 			return Cost::zero;
-		} else if ( dynamic_cast< VoidType* >( dest ) ) {
+		} else if ( dynamic_cast< const VoidType* >( dest ) ) {
 			return Cost::safe;
-		} else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
+		} else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
 			PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
-			return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
+			return convertToReferenceCost( src, refType, indexer, env, [](const Type * t1, const Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
 				return ptrsCastable( t1, t2, env, indexer );
 			});
 		} else {
-			PassVisitor<CastCost_old> converter( 
-				dest, indexer, env, 
-				(Cost (*)( Type *, Type *, const SymTab::Indexer &, const TypeEnvironment & ))
+			PassVisitor<CastCost_old> converter(
+				dest, indexer, env,
+				(Cost (*)( const Type *, const Type *, const SymTab::Indexer &, const TypeEnvironment & ))
 					castCost );
 			src->accept( converter );
@@ -96,10 +96,10 @@
 	}
 
-	CastCost_old::CastCost_old( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
+	CastCost_old::CastCost_old( const Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
 		: ConversionCost( dest, indexer, env, costFunc ) {
 	}
 
-	void CastCost_old::postvisit( BasicType *basicType ) {
-		PointerType *destAsPointer = dynamic_cast< PointerType* >( dest );
+	void CastCost_old::postvisit( const BasicType *basicType ) {
+		const PointerType *destAsPointer = dynamic_cast< const PointerType* >( dest );
 		if ( destAsPointer && basicType->isInteger() ) {
 			// necessary for, e.g. unsigned long => void*
@@ -110,7 +110,7 @@
 	}
 
-	void CastCost_old::postvisit( PointerType *pointerType ) {
-		if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
-			if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
+	void CastCost_old::postvisit( const PointerType *pointerType ) {
+		if ( const PointerType *destAsPtr = dynamic_cast< const PointerType* >( dest ) ) {
+			if ( pointerType->tq <= destAsPtr->tq && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
 				cost = Cost::safe;
 			} else {
@@ -125,5 +125,5 @@
 				} // if
 			} // if
-		} else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
+		} else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
 			if ( destAsBasic->isInteger() ) {
 				// necessary for, e.g. void* => unsigned long
@@ -138,6 +138,6 @@
 		using ConversionCost_new::postvisit;
 
-		CastCost_new( 
-			const ast::Type * dst, const ast::SymbolTable & symtab, 
+		CastCost_new(
+			const ast::Type * dst, const ast::SymbolTable & symtab,
 			const ast::TypeEnvironment & env, CostCalculation costFunc )
 		: ConversionCost_new( dst, symtab, env, costFunc ) {}
@@ -182,7 +182,7 @@
 } // anonymous namespace
 
-Cost castCost( 
-	const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 
-	const ast::TypeEnvironment & env 
+Cost castCost(
+	const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
+	const ast::TypeEnvironment & env
 ) {
 	if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
@@ -220,8 +220,8 @@
 		PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
 		#warning cast on ptrsCastable artifact of having two functions, remove when port done
-		return convertToReferenceCost( 
-			src, refType, symtab, env, 
-			( int (*)( 
-				const ast::Type *, const ast::Type *, const ast::SymbolTable &, 
+		return convertToReferenceCost(
+			src, refType, symtab, env,
+			( int (*)(
+				const ast::Type *, const ast::Type *, const ast::SymbolTable &,
 				const ast::TypeEnvironment & )
 			) ptrsCastable );
@@ -229,7 +229,7 @@
 		#warning cast on castCost artifact of having two functions, remove when port done
 		ast::Pass< CastCost_new > converter{
-			dst, symtab, env, 
-			( Cost (*)( 
-				const ast::Type *, const ast::Type *, const ast::SymbolTable &, 
+			dst, symtab, env,
+			( Cost (*)(
+				const ast::Type *, const ast::Type *, const ast::SymbolTable &,
 				const ast::TypeEnvironment & )
 			) castCost };
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/ResolvExpr/ConversionCost.cc	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -46,6 +46,6 @@
 #endif
 
-	Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
-		if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
+	Cost conversionCost( const Type * src, const Type * dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
+		if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) {
 			PRINT( std::cerr << "type inst " << destAsTypeInst->name; )
 			if ( const EqvClass* eqvClass = env.lookup( destAsTypeInst->name ) ) {
@@ -55,7 +55,7 @@
 					return Cost::infinity;
 				}
-			} else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->name ) ) {
+			} else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
 				PRINT( std::cerr << " found" << std::endl; )
-				TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
+				const TypeDecl *type = dynamic_cast< const TypeDecl* >( namedType );
 				// all typedefs should be gone by this point
 				assert( type );
@@ -77,15 +77,15 @@
 			PRINT( std::cerr << "compatible!" << std::endl; )
 			return Cost::zero;
-		} else if ( dynamic_cast< VoidType* >( dest ) ) {
+		} else if ( dynamic_cast< const VoidType * >( dest ) ) {
 			return Cost::safe;
-		} else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
+		} else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
 			PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
-			return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
+			return convertToReferenceCost( src, refType, indexer, env, [](const Type * const t1, const Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
 				return ptrsAssignable( t1, t2, env );
 			});
 		} else {
-			PassVisitor<ConversionCost> converter( 
-				dest, indexer, env, 
-				(Cost (*)(Type*, Type*, const SymTab::Indexer&, const TypeEnvironment&))
+			PassVisitor<ConversionCost> converter(
+				dest, indexer, env,
+				(Cost (*)(const Type*, const Type*, const SymTab::Indexer&, const TypeEnvironment&))
 					conversionCost );
 			src->accept( converter );
@@ -98,23 +98,23 @@
 	}
 
-	Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
+	Cost convertToReferenceCost( const Type * src, const Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
 		PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; )
 		if ( diff > 0 ) {
 			// TODO: document this
-			Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->base, dest, diff-1, indexer, env, func );
+			Cost cost = convertToReferenceCost( strict_dynamic_cast< const ReferenceType * >( src )->base, dest, diff-1, indexer, env, func );
 			cost.incReference();
 			return cost;
 		} else if ( diff < -1 ) {
 			// TODO: document this
-			Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->base, diff+1, indexer, env, func );
+			Cost cost = convertToReferenceCost( src, strict_dynamic_cast< const ReferenceType * >( dest )->base, diff+1, indexer, env, func );
 			cost.incReference();
 			return cost;
 		} else if ( diff == 0 ) {
-			ReferenceType * srcAsRef = dynamic_cast< ReferenceType * >( src );
-			ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
+			const ReferenceType * srcAsRef = dynamic_cast< const ReferenceType * >( src );
+			const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
 			if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
 				PRINT( std::cerr << "converting between references" << std::endl; )
-				Type::Qualifiers tq1 = srcAsRef->base->get_qualifiers();
-				Type::Qualifiers tq2 = destAsRef->base->get_qualifiers();
+				Type::Qualifiers tq1 = srcAsRef->base->tq;
+				Type::Qualifiers tq2 = destAsRef->base->tq;
 				if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) {
 					PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
@@ -137,7 +137,7 @@
 			} else {
 				PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
-				PassVisitor<ConversionCost> converter( 
-					dest, indexer, env, 
-					(Cost (*)(Type*, Type*, const SymTab::Indexer&, const TypeEnvironment&))
+				PassVisitor<ConversionCost> converter(
+					dest, indexer, env,
+					(Cost (*)(const Type*, const Type*, const SymTab::Indexer&, const TypeEnvironment&))
 						conversionCost );
 				src->accept( converter );
@@ -145,5 +145,5 @@
 			} // if
 		} else {
-			ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
+			const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
 			assert( diff == -1 && destAsRef );
 			PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
@@ -156,7 +156,7 @@
 					)
 					// lvalue-to-reference conversion:  cv lvalue T => cv T &
-					if ( src->get_qualifiers() == destAsRef->base->get_qualifiers() ) {
+					if ( src->tq == destAsRef->base->tq ) {
 						return Cost::reference; // cost needs to be non-zero to add cast
-					} if ( src->get_qualifiers() < destAsRef->base->get_qualifiers() ) {
+					} if ( src->tq < destAsRef->base->tq ) {
 						return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
 					} else {
@@ -178,5 +178,5 @@
 	}
 
-	Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
+	Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
 		int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
 		Cost cost = convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env, func );
@@ -185,5 +185,5 @@
 	}
 
-	ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
+	ConversionCost::ConversionCost( const Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
 		: dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) {
 	}
@@ -193,22 +193,22 @@
 	/* EXTENDED INTEGRAL RANK HIERARCHY (root to leaves)
 	                         _Bool
-	char                signed char         unsigned char       
-	          signed short int         unsigned short int       
-	          signed int               unsigned int             
-	          signed long int          unsigned long int        
-	          signed long long int     unsigned long long int   
-	          __int128                 unsigned __int128        
-	          _Float16                 _Float16 _Complex        
-	          _Float32                 _Float32 _Complex        
-	          float                    float _Complex           
-	          _Float32x                _Float32x _Complex       
-	          _Float64                 _Float64 _Complex        
-	          double                   double _Complex          
-	          _Float64x                _Float64x _Complex       
+	char                signed char         unsigned char
+	          signed short int         unsigned short int
+	          signed int               unsigned int
+	          signed long int          unsigned long int
+	          signed long long int     unsigned long long int
+	          __int128                 unsigned __int128
+	          _Float16                 _Float16 _Complex
+	          _Float32                 _Float32 _Complex
+	          float                    float _Complex
+	          _Float32x                _Float32x _Complex
+	          _Float64                 _Float64 _Complex
+	          double                   double _Complex
+	          _Float64x                _Float64x _Complex
 	                     __float80
-	          _Float128                _Float128 _Complex       
+	          _Float128                _Float128 _Complex
 	                    __float128
-	          long double              long double _Complex     
-	          _Float128x               _Float128x _Complex      
+	          long double              long double _Complex
+	          _Float128x               _Float128x _Complex
 	*/
 	// GENERATED END
@@ -309,11 +309,11 @@
 	);
 
-	void ConversionCost::postvisit( VoidType * ) {
+	void ConversionCost::postvisit( const VoidType * ) {
 		cost = Cost::infinity;
 	}
 
-	void ConversionCost::postvisit(BasicType *basicType) {
-		if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
-			int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
+	void ConversionCost::postvisit(const BasicType *basicType) {
+		if ( const BasicType * destAsBasic = dynamic_cast< const BasicType* >( dest ) ) {
+			int tableResult = costMatrix[ basicType->kind ][ destAsBasic->kind ];
 			if ( tableResult == -1 ) {
 				cost = Cost::unsafe;
@@ -321,7 +321,7 @@
 				cost = Cost::zero;
 				cost.incSafe( tableResult );
-				cost.incSign( signMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ] );
-			} // if
-		} else if ( dynamic_cast< EnumInstType *>( dest ) ) {
+				cost.incSign( signMatrix[ basicType->kind ][ destAsBasic->kind ] );
+			} // if
+		} else if ( dynamic_cast< const EnumInstType * >( dest ) ) {
 			// xxx - not positive this is correct, but appears to allow casting int => enum
 			cost = Cost::unsafe;
@@ -330,9 +330,9 @@
 	}
 
-	void ConversionCost::postvisit( PointerType * pointerType ) {
-		if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
+	void ConversionCost::postvisit( const PointerType * pointerType ) {
+		if ( const PointerType *destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
 			PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
-			Type::Qualifiers tq1 = pointerType->base->get_qualifiers();
-			Type::Qualifiers tq2 = destAsPtr->base->get_qualifiers();
+			Type::Qualifiers tq1 = pointerType->base->tq;
+			Type::Qualifiers tq2 = destAsPtr->base->tq;
 			if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
 				PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
@@ -363,16 +363,16 @@
 	}
 
-	void ConversionCost::postvisit( ArrayType * ) {}
-
-	void ConversionCost::postvisit( ReferenceType * refType ) {
+	void ConversionCost::postvisit( const ArrayType * ) {}
+
+	void ConversionCost::postvisit( const ReferenceType * refType ) {
 		// Note: dest can never be a reference, since it would have been caught in an earlier check
-		assert( ! dynamic_cast< ReferenceType * >( dest ) );
+		assert( ! dynamic_cast< const ReferenceType * >( dest ) );
 		// convert reference to rvalue: cv T1 & => T2
 		// recursively compute conversion cost from T1 to T2.
 		// cv can be safely dropped because of 'implicit dereference' behavior.
 		cost = costFunc( refType->base, dest, indexer, env );
-		if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) {
+		if ( refType->base->tq == dest->tq ) {
 			cost.incReference();  // prefer exact qualifiers
-		} else if ( refType->base->get_qualifiers() < dest->get_qualifiers() ) {
+		} else if ( refType->base->tq < dest->tq ) {
 			cost.incSafe(); // then gaining qualifiers
 		} else {
@@ -382,8 +382,8 @@
 	}
 
-	void ConversionCost::postvisit( FunctionType * ) {}
-
-	void ConversionCost::postvisit( StructInstType * inst ) {
-		if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
+	void ConversionCost::postvisit( const FunctionType * ) {}
+
+	void ConversionCost::postvisit( const StructInstType * inst ) {
+		if ( const StructInstType *destAsInst = dynamic_cast< const StructInstType * >( dest ) ) {
 			if ( inst->name == destAsInst->name ) {
 				cost = Cost::zero;
@@ -392,6 +392,6 @@
 	}
 
-	void ConversionCost::postvisit( UnionInstType * inst ) {
-		if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) {
+	void ConversionCost::postvisit( const UnionInstType * inst ) {
+		if ( const UnionInstType *destAsInst = dynamic_cast< const UnionInstType * >( dest ) ) {
 			if ( inst->name == destAsInst->name ) {
 				cost = Cost::zero;
@@ -400,5 +400,5 @@
 	}
 
-	void ConversionCost::postvisit( EnumInstType * ) {
+	void ConversionCost::postvisit( const EnumInstType * ) {
 		static Type::Qualifiers q;
 		static BasicType integer( q, BasicType::SignedInt );
@@ -409,15 +409,15 @@
 	}
 
-	void ConversionCost::postvisit( TraitInstType * ) {}
-
-	void ConversionCost::postvisit( TypeInstType *inst ) {
+	void ConversionCost::postvisit( const TraitInstType * ) {}
+
+	void ConversionCost::postvisit( const TypeInstType *inst ) {
 		if ( const EqvClass *eqvClass = env.lookup( inst->name ) ) {
 			cost = costFunc( eqvClass->type, dest, indexer, env );
-		} else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) {
+		} else if ( const TypeInstType *destAsInst = dynamic_cast< const TypeInstType* >( dest ) ) {
 			if ( inst->name == destAsInst->name ) {
 				cost = Cost::zero;
 			}
 		} else if ( NamedTypeDecl *namedType = indexer.lookupType( inst->name ) ) {
-			TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
+			const TypeDecl *type = dynamic_cast< const TypeDecl* >( namedType );
 			// all typedefs should be gone by this point
 			assert( type );
@@ -428,7 +428,7 @@
 	}
 
-	void ConversionCost::postvisit( TupleType * tupleType ) {
+	void ConversionCost::postvisit( const TupleType * tupleType ) {
 		Cost c = Cost::zero;
-		if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) {
+		if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) {
 			std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
 			std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
@@ -448,16 +448,16 @@
 	}
 
-	void ConversionCost::postvisit( VarArgsType * ) {
-		if ( dynamic_cast< VarArgsType* >( dest ) ) {
-			cost = Cost::zero;
-		}
-	}
-
-	void ConversionCost::postvisit( ZeroType * ) {
-		if ( dynamic_cast< ZeroType * >( dest ) ) {
-			cost = Cost::zero;
-		} else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
+	void ConversionCost::postvisit( const VarArgsType * ) {
+		if ( dynamic_cast< const VarArgsType* >( dest ) ) {
+			cost = Cost::zero;
+		}
+	}
+
+	void ConversionCost::postvisit( const ZeroType * ) {
+		if ( dynamic_cast< const ZeroType * >( dest ) ) {
+			cost = Cost::zero;
+		} else if ( const BasicType *destAsBasic = dynamic_cast< const BasicType* >( dest ) ) {
 			// copied from visit(BasicType*) for signed int, but +1 for safe conversions
-			int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
+			int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
 			if ( tableResult == -1 ) {
 				cost = Cost::unsafe;
@@ -465,7 +465,7 @@
 				cost = Cost::zero;
 				cost.incSafe( tableResult + 1 );
-				cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ] );
-			} // if
-		} else if ( dynamic_cast< PointerType* >( dest ) ) {
+				cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
+			} // if
+		} else if ( dynamic_cast< const PointerType* >( dest ) ) {
 			cost = Cost::zero;
 			cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
@@ -473,10 +473,10 @@
 	}
 
-	void ConversionCost::postvisit( OneType * ) {
-		if ( dynamic_cast< OneType * >( dest ) ) {
-			cost = Cost::zero;
-		} else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
+	void ConversionCost::postvisit( const OneType * ) {
+		if ( dynamic_cast< const OneType * >( dest ) ) {
+			cost = Cost::zero;
+		} else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
 			// copied from visit(BasicType*) for signed int, but +1 for safe conversions
-			int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
+			int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
 			if ( tableResult == -1 ) {
 				cost = Cost::unsafe;
@@ -484,5 +484,5 @@
 				cost = Cost::zero;
 				cost.incSafe( tableResult + 1 );
-				cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ] );
+				cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
 			} // if
 		} // if
Index: src/ResolvExpr/ConversionCost.h
===================================================================
--- src/ResolvExpr/ConversionCost.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/ResolvExpr/ConversionCost.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -33,30 +33,30 @@
 	class TypeEnvironment;
 
-	typedef std::function<Cost(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> CostFunction;
+	typedef std::function<Cost(const Type *, const Type *, const SymTab::Indexer &, const TypeEnvironment &)> CostFunction;
 	struct ConversionCost : public WithShortCircuiting {
 	  public:
-		ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction );
+		ConversionCost( const Type * dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction );
 
 		Cost get_cost() const { return cost; }
 
-		void previsit( BaseSyntaxNode * ) { visit_children = false; }
+		void previsit( const BaseSyntaxNode * ) { visit_children = false; }
 
-		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( TraitInstType * aggregateUseType );
-		void postvisit( TypeInstType * aggregateUseType );
-		void postvisit( TupleType * tupleType );
-		void postvisit( VarArgsType * varArgsType );
-		void postvisit( ZeroType * zeroType );
-		void postvisit( OneType * oneType );
+		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 TraitInstType * aggregateUseType );
+		void postvisit( const TypeInstType * aggregateUseType );
+		void postvisit( const TupleType * tupleType );
+		void postvisit( const VarArgsType * varArgsType );
+		void postvisit( const ZeroType * zeroType );
+		void postvisit( const OneType * oneType );
 	  protected:
-		Type *dest;
+		const Type * dest;
 		const SymTab::Indexer &indexer;
 		Cost cost;
@@ -65,6 +65,6 @@
 	};
 
-	typedef std::function<int(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction;
-	Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func );
+	typedef std::function<int(const Type *, const Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction;
+	Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func );
 
 // Some function pointer types, differ in return type.
Index: src/ResolvExpr/PtrsAssignable.cc
===================================================================
--- src/ResolvExpr/PtrsAssignable.cc	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/ResolvExpr/PtrsAssignable.cc	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -27,38 +27,38 @@
 namespace ResolvExpr {
 	struct PtrsAssignable : public WithShortCircuiting {
-		PtrsAssignable( Type *dest, const TypeEnvironment &env );
+		PtrsAssignable( const Type * dest, const TypeEnvironment &env );
 
 		int get_result() const { return result; }
 
-		void previsit( Type * ) { visit_children = false; }
-
-		void postvisit( VoidType * voidType );
-		void postvisit( BasicType * basicType );
-		void postvisit( PointerType * pointerType );
-		void postvisit( ArrayType * arrayType );
-		void postvisit( FunctionType * functionType );
-		void postvisit( StructInstType * inst );
-		void postvisit( UnionInstType * inst );
-		void postvisit( EnumInstType * inst );
-		void postvisit( TraitInstType * inst );
-		void postvisit( TypeInstType * inst );
-		void postvisit( TupleType * tupleType );
-		void postvisit( VarArgsType * varArgsType );
-		void postvisit( ZeroType * zeroType );
-		void postvisit( OneType * oneType );
+		void previsit( const Type * ) { visit_children = false; }
+
+		void postvisit( const VoidType * voidType );
+		void postvisit( const BasicType * basicType );
+		void postvisit( const PointerType * pointerType );
+		void postvisit( const ArrayType * arrayType );
+		void postvisit( const FunctionType * functionType );
+		void postvisit( const StructInstType * inst );
+		void postvisit( const UnionInstType * inst );
+		void postvisit( const EnumInstType * inst );
+		void postvisit( const TraitInstType * inst );
+		void postvisit( const TypeInstType * inst );
+		void postvisit( const TupleType * tupleType );
+		void postvisit( const VarArgsType * varArgsType );
+		void postvisit( const ZeroType * zeroType );
+		void postvisit( const OneType * oneType );
 	  private:
-		Type *dest;
+		const Type * dest;
 		int result;
 		const TypeEnvironment &env;
 	};
 
-	int ptrsAssignable( Type *src, Type *dest, const TypeEnvironment &env ) {
+	int ptrsAssignable( const Type *src, const Type * dest, const TypeEnvironment &env ) {
 		// std::cerr << "assignable: " << src << " | " << dest << std::endl;
-		if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
-			if ( const EqvClass *eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
+		if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) {
+			if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
 				return ptrsAssignable( src, eqvClass->type, env );
 			} // if
 		} // if
-		if ( dynamic_cast< VoidType* >( dest ) ) {
+		if ( dynamic_cast< const VoidType* >( dest ) ) {
 			// void * = T * for any T is unsafe
 			// xxx - this should be safe, but that currently breaks the build
@@ -71,21 +71,21 @@
 	}
 
-	PtrsAssignable::PtrsAssignable( Type *dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {}
-
-	void PtrsAssignable::postvisit( VoidType * ) {
+	PtrsAssignable::PtrsAssignable( const Type * dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {}
+
+	void PtrsAssignable::postvisit( const VoidType * ) {
 		// T * = void * is disallowed - this is a change from C, where any
 		// void * can be assigned or passed to a non-void pointer without a cast.
 	}
 
-	void PtrsAssignable::postvisit( __attribute__((unused)) BasicType *basicType ) {}
-	void PtrsAssignable::postvisit( __attribute__((unused)) PointerType *pointerType ) {}
-	void PtrsAssignable::postvisit( __attribute__((unused)) ArrayType *arrayType ) {}
-	void PtrsAssignable::postvisit( __attribute__((unused)) FunctionType *functionType ) {}
-
-	void PtrsAssignable::postvisit(  __attribute__((unused)) StructInstType *inst ) {}
-	void PtrsAssignable::postvisit(  __attribute__((unused)) UnionInstType *inst ) {}
-
-	void PtrsAssignable::postvisit( EnumInstType * ) {
-		if ( dynamic_cast< BasicType* >( dest ) ) {
+	void PtrsAssignable::postvisit( const BasicType * ) {}
+	void PtrsAssignable::postvisit( const PointerType * ) {}
+	void PtrsAssignable::postvisit( const ArrayType * ) {}
+	void PtrsAssignable::postvisit( const FunctionType * ) {}
+
+	void PtrsAssignable::postvisit( const StructInstType * ) {}
+	void PtrsAssignable::postvisit( const UnionInstType * ) {}
+
+	void PtrsAssignable::postvisit( const EnumInstType * ) {
+		if ( dynamic_cast< const BasicType* >( dest ) ) {
 			// int * = E *, etc. is safe. This isn't technically correct, as each
 			// enum has one basic type that it is compatible with, an that type can
@@ -97,7 +97,7 @@
 	}
 
-	void PtrsAssignable::postvisit(  __attribute__((unused)) TraitInstType *inst ) {}
-	void PtrsAssignable::postvisit( TypeInstType *inst ) {
-		if ( const EqvClass *eqvClass = env.lookup( inst->get_name() ) ) {
+	void PtrsAssignable::postvisit(  const TraitInstType * ) {}
+	void PtrsAssignable::postvisit( const TypeInstType * inst ) {
+		if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
 			if ( eqvClass->type ) {
 				// T * = S * for any S depends on the type bound to T
@@ -107,8 +107,8 @@
 	}
 
-	void PtrsAssignable::postvisit(  __attribute__((unused)) TupleType *tupleType ) {}
-	void PtrsAssignable::postvisit(  __attribute__((unused)) VarArgsType *varArgsType ) {}
-	void PtrsAssignable::postvisit(  __attribute__((unused)) ZeroType *zeroType ) {}
-	void PtrsAssignable::postvisit(  __attribute__((unused)) OneType *oneType ) {}
+	void PtrsAssignable::postvisit( const TupleType * ) {}
+	void PtrsAssignable::postvisit( const VarArgsType * ) {}
+	void PtrsAssignable::postvisit( const ZeroType * ) {}
+	void PtrsAssignable::postvisit( const OneType * ) {}
 
 // TODO: Get rid of the `_new` suffix when the old version is removed.
Index: src/ResolvExpr/PtrsCastable.cc
===================================================================
--- src/ResolvExpr/PtrsCastable.cc	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/ResolvExpr/PtrsCastable.cc	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -29,26 +29,26 @@
 	struct PtrsCastable_old : public WithShortCircuiting  {
 	  public:
-		PtrsCastable_old( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
+		PtrsCastable_old( const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
 
 		int get_result() const { return result; }
 
-		void previsit( Type * ) { visit_children = false; }
-
-		void postvisit( VoidType * voidType );
-		void postvisit( BasicType * basicType );
-		void postvisit( PointerType * pointerType );
-		void postvisit( ArrayType * arrayType );
-		void postvisit( FunctionType * functionType );
-		void postvisit( StructInstType * inst );
-		void postvisit( UnionInstType * inst );
-		void postvisit( EnumInstType * inst );
-		void postvisit( TraitInstType * inst );
-		void postvisit( TypeInstType * inst );
-		void postvisit( TupleType * tupleType );
-		void postvisit( VarArgsType * varArgsType );
-		void postvisit( ZeroType * zeroType );
-		void postvisit( OneType * oneType );
+		void previsit( const Type * ) { visit_children = false; }
+
+		void postvisit( const VoidType * voidType );
+		void postvisit( const BasicType * basicType );
+		void postvisit( const PointerType * pointerType );
+		void postvisit( const ArrayType * arrayType );
+		void postvisit( const FunctionType * functionType );
+		void postvisit( const StructInstType * inst );
+		void postvisit( const UnionInstType * inst );
+		void postvisit( const EnumInstType * inst );
+		void postvisit( const TraitInstType * inst );
+		void postvisit( const TypeInstType * inst );
+		void postvisit( const TupleType * tupleType );
+		void postvisit( const VarArgsType * varArgsType );
+		void postvisit( const ZeroType * zeroType );
+		void postvisit( const OneType * oneType );
 	  private:
-		Type *dest;
+		const Type * dest;
 		int result;
 		const TypeEnvironment &env;
@@ -57,15 +57,15 @@
 
 	namespace {
-		int objectCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
-			if ( dynamic_cast< FunctionType* >( src ) ) {
+		int objectCast( const Type * src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
+			if ( dynamic_cast< const FunctionType* >( src ) ) {
 				return -1;
-			} else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( src ) ) {
-				if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
-					if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) {
-						if ( tyDecl->get_kind() == TypeDecl::Ftype ) {
+			} else if ( const TypeInstType * typeInst = dynamic_cast< const TypeInstType* >( src ) ) {
+				if ( const NamedTypeDecl * ntDecl = indexer.lookupType( typeInst->name ) ) {
+					if ( const TypeDecl * tyDecl = dynamic_cast< const TypeDecl* >( ntDecl ) ) {
+						if ( tyDecl->kind == TypeDecl::Ftype ) {
 							return -1;
 						} // if
 					} //if
-				} else if ( const EqvClass *eqvClass = env.lookup( typeInst->get_name() ) ) {
+				} else if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) {
 					if ( eqvClass->data.kind == TypeDecl::Ftype ) {
 						return -1;
@@ -75,17 +75,17 @@
 			return 1;
 		}
-		int functionCast( Type *src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
+		int functionCast( const Type * src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
 			return -1 * objectCast( src, env, indexer );  // reverse the sense of objectCast
 		}
 	}
 
-	int ptrsCastable( Type *src, Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
-		if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
-			if ( const EqvClass *eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
+	int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
+		if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) {
+			if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
 				// xxx - should this be ptrsCastable?
 				return ptrsAssignable( src, eqvClass->type, env );
 			} // if
 		} // if
-		if ( dynamic_cast< VoidType* >( dest ) ) {
+		if ( dynamic_cast< const VoidType* >( dest ) ) {
 			return objectCast( src, env, indexer );
 		} else {
@@ -96,42 +96,42 @@
 	}
 
-	PtrsCastable_old::PtrsCastable_old( Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer )
+	PtrsCastable_old::PtrsCastable_old( const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer )
 		: dest( dest ), result( 0 ), env( env ), indexer( indexer )	{
 	}
 
-	void PtrsCastable_old::postvisit( VoidType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( BasicType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( PointerType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( ArrayType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( FunctionType * ) {
+	void PtrsCastable_old::postvisit( const VoidType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( const BasicType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( const PointerType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( const ArrayType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( const FunctionType * ) {
 		// result = -1;
 		result = functionCast( dest, env, indexer );
 	}
 
-	void PtrsCastable_old::postvisit( StructInstType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( UnionInstType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( EnumInstType * ) {
-		if ( dynamic_cast< EnumInstType* >( dest ) ) {
+	void PtrsCastable_old::postvisit( const StructInstType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( const UnionInstType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( const EnumInstType * ) {
+		if ( dynamic_cast< const EnumInstType * >( dest ) ) {
 			result = 1;
-		} else if ( BasicType *bt = dynamic_cast< BasicType* >( dest ) ) {
-			if ( bt->get_kind() == BasicType::SignedInt ) {
+		} else if ( const BasicType * bt = dynamic_cast< const BasicType * >( dest ) ) {
+			if ( bt->kind == BasicType::SignedInt ) {
 				result = 0;
 			} else {
@@ -143,24 +143,24 @@
 	}
 
-	void PtrsCastable_old::postvisit( TraitInstType * ) {}
-
-	void PtrsCastable_old::postvisit(TypeInstType *inst ) {
+	void PtrsCastable_old::postvisit( const TraitInstType * ) {}
+
+	void PtrsCastable_old::postvisit( const TypeInstType *inst ) {
 		//result = objectCast( inst, env, indexer ) > 0 && objectCast( dest, env, indexer ) > 0 ? 1 : -1;
 		result = objectCast( inst, env, indexer ) == objectCast( dest, env, indexer ) ? 1 : -1;
 	}
 
-	void PtrsCastable_old::postvisit( TupleType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( VarArgsType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( ZeroType * ) {
-		result = objectCast( dest, env, indexer );
-	}
-
-	void PtrsCastable_old::postvisit( OneType * ) {
+	void PtrsCastable_old::postvisit( const TupleType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( const VarArgsType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( const ZeroType * ) {
+		result = objectCast( dest, env, indexer );
+	}
+
+	void PtrsCastable_old::postvisit( const OneType * ) {
 		result = objectCast( dest, env, indexer );
 	}
@@ -168,6 +168,6 @@
 namespace {
 	// can this type be cast to an object (1 for yes, -1 for no)
-	int objectCast( 
-		const ast::Type * src, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab 
+	int objectCast(
+		const ast::Type * src, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab
 	) {
 		if ( dynamic_cast< const ast::FunctionType * >( src ) ) {
@@ -191,6 +191,6 @@
 
 	// can this type be cast to a function (inverse of objectCast)
-	int functionCast( 
-		const ast::Type * src, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab 
+	int functionCast(
+		const ast::Type * src, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab
 	) {
 		return -1 * objectCast( src, env, symtab );
@@ -204,5 +204,5 @@
 		int result;
 
-		PtrsCastable_new( 
+		PtrsCastable_new(
 			const ast::Type * d, const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
 		: dst( d ), env( e ), symtab( syms ), result( 0 ) {}
@@ -278,7 +278,7 @@
 } // anonymous namespace
 
-int ptrsCastable( 
-	const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 
-	const ast::TypeEnvironment & env 
+int ptrsCastable(
+	const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
+	const ast::TypeEnvironment & env
 ) {
 	if ( auto inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/ResolvExpr/Unify.cc	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -97,7 +97,7 @@
 	bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
 
-	bool unifyExact( 
-		const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 
-		ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 
+	bool unifyExact(
+		const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
+		ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
 		WidenMode widen, const ast::SymbolTable & symtab );
 
@@ -121,6 +121,6 @@
 	}
 
-	bool typesCompatible( 
-			const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab, 
+	bool typesCompatible(
+			const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,
 			const ast::TypeEnvironment & env ) {
 		ast::TypeEnvironment newEnv;
@@ -135,9 +135,9 @@
 		findOpenVars( newSecond, open, closed, need, have, FirstOpen );
 
-		return unifyExact( 
+		return unifyExact(
 			newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
 	}
 
-	bool typesCompatibleIgnoreQualifiers( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
+	bool typesCompatibleIgnoreQualifiers( const Type * first, const Type * second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
 		TypeEnvironment newEnv;
 		OpenVarSet openVars;
@@ -163,11 +163,11 @@
 	}
 
-	bool typesCompatibleIgnoreQualifiers( 
-			const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab, 
+	bool typesCompatibleIgnoreQualifiers(
+			const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,
 			const ast::TypeEnvironment & env ) {
 		ast::TypeEnvironment newEnv;
 		ast::OpenVarSet open;
 		ast::AssertionSet need, have;
-		
+
 		ast::ptr<ast::Type> newFirst{ first }, newSecond{ second };
 		env.apply( newFirst );
@@ -176,5 +176,5 @@
 		reset_qualifiers( newSecond );
 
-		return unifyExact( 
+		return unifyExact(
 			newFirst, newSecond, newEnv, need, have, open, noWiden(), symtab );
 	}
@@ -490,9 +490,9 @@
 
 			// sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors
-			if ( 
-					(flatFunc->parameters.size() == flatOther->parameters.size() && 
-						flatFunc->returnVals.size() == flatOther->returnVals.size()) 
-					|| flatFunc->isTtype() 
-					|| flatOther->isTtype() 
+			if (
+					(flatFunc->parameters.size() == flatOther->parameters.size() &&
+						flatFunc->returnVals.size() == flatOther->returnVals.size())
+					|| flatFunc->isTtype()
+					|| flatOther->isTtype()
 			) {
 				if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
@@ -711,13 +711,13 @@
 		bool result;
 
-		Unify_new( 
-			const ast::Type * type2, ast::TypeEnvironment & env, ast::AssertionSet & need, 
-			ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen, 
+		Unify_new(
+			const ast::Type * type2, ast::TypeEnvironment & env, ast::AssertionSet & need,
+			ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen,
 			const ast::SymbolTable & symtab )
-		: type2(type2), tenv(env), need(need), have(have), open(open), widen(widen), 
+		: type2(type2), tenv(env), need(need), have(have), open(open), widen(widen),
 		  symtab(symtab), result(false) {}
 
 		void previsit( const ast::Node * ) { visit_children = false; }
-		
+
 		void postvisit( const ast::VoidType * ) {
 			result = dynamic_cast< const ast::VoidType * >( type2 );
@@ -732,6 +732,6 @@
 		void postvisit( const ast::PointerType * pointer ) {
 			if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) {
-				result = unifyExact( 
-					pointer->base, pointer2->base, tenv, need, have, open, 
+				result = unifyExact(
+					pointer->base, pointer2->base, tenv, need, have, open,
 					noWiden(), symtab );
 			}
@@ -742,8 +742,8 @@
 			if ( ! array2 ) return;
 
-			// to unify, array types must both be VLA or both not VLA and both must have a 
+			// to unify, array types must both be VLA or both not VLA and both must have a
 			// dimension expression or not have a dimension
 			if ( array->isVarLen != array2->isVarLen ) return;
-			if ( ! array->isVarLen && ! array2->isVarLen 
+			if ( ! array->isVarLen && ! array2->isVarLen
 					&& array->dimension && array2->dimension ) {
 				auto ce1 = array->dimension.as< ast::ConstantExpr >();
@@ -751,11 +751,11 @@
 
 				// see C11 Reference Manual 6.7.6.2.6
-				// two array types with size specifiers that are integer constant expressions are 
+				// two array types with size specifiers that are integer constant expressions are
 				// compatible if both size specifiers have the same constant value
 				if ( ce1 && ce2 && ce1->intValue() != ce2->intValue() ) return;
 			}
 
-			result = unifyExact( 
-				array->base, array2->base, tenv, need, have, open, noWiden(), 
+			result = unifyExact(
+				array->base, array2->base, tenv, need, have, open, noWiden(),
 				symtab );
 		}
@@ -763,6 +763,6 @@
 		void postvisit( const ast::ReferenceType * ref ) {
 			if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) {
-				result = unifyExact( 
-					ref->base, ref2->base, tenv, need, have, open, noWiden(), 
+				result = unifyExact(
+					ref->base, ref2->base, tenv, need, have, open, noWiden(),
 					symtab );
 			}
@@ -771,5 +771,5 @@
 	private:
 		/// Replaces ttype variables with their bound types.
-		/// If this isn't done when satifying ttype assertions, then argument lists can have 
+		/// If this isn't done when satifying ttype assertions, then argument lists can have
 		/// different size and structure when they should be compatible.
 		struct TtypeExpander_new : public ast::WithShortCircuiting {
@@ -800,9 +800,9 @@
 				auto types = flatten( d->get_type() );
 				for ( ast::ptr< ast::Type > & t : types ) {
-					// outermost const, volatile, _Atomic qualifiers in parameters should not play 
-					// a role in the unification of function types, since they do not determine 
+					// outermost const, volatile, _Atomic qualifiers in parameters should not play
+					// a role in the unification of function types, since they do not determine
 					// whether a function is callable.
-					// NOTE: **must** consider at least mutex qualifier, since functions can be 
-					// overloaded on outermost mutex and a mutex function has different 
+					// NOTE: **must** consider at least mutex qualifier, since functions can be
+					// overloaded on outermost mutex and a mutex function has different
 					// requirements than a non-mutex function
 					remove_qualifiers( t, ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic );
@@ -818,5 +818,5 @@
 			std::vector< ast::ptr< ast::Type > > types;
 			while ( crnt != end ) {
-				// it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure 
+				// it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
 				// that this results in a flat tuple
 				flatten( (*crnt)->get_type(), types );
@@ -829,7 +829,7 @@
 
 		template< typename Iter >
-		static bool unifyDeclList( 
-			Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env, 
-			ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 
+		static bool unifyDeclList(
+			Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env,
+			ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
 			const ast::SymbolTable & symtab
 		) {
@@ -843,16 +843,16 @@
 				if ( isTuple1 && ! isTuple2 ) {
 					// combine remainder of list2, then unify
-					return unifyExact( 
-						t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 
+					return unifyExact(
+						t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
 						noWiden(), symtab );
 				} else if ( ! isTuple1 && isTuple2 ) {
 					// combine remainder of list1, then unify
-					return unifyExact( 
-						tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 
+					return unifyExact(
+						tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
 						noWiden(), symtab );
 				}
 
-				if ( ! unifyExact( 
-					t1, t2, env, need, have, open, noWiden(), symtab ) 
+				if ( ! unifyExact(
+					t1, t2, env, need, have, open, noWiden(), symtab )
 				) return false;
 
@@ -860,5 +860,5 @@
 			}
 
-			// May get to the end of one argument list before the other. This is only okay if the 
+			// May get to the end of one argument list before the other. This is only okay if the
 			// other is a ttype
 			if ( crnt1 != end1 ) {
@@ -866,6 +866,6 @@
 				const ast::Type * t1 = (*crnt1)->get_type();
 				if ( ! Tuples::isTtype( t1 ) ) return false;
-				return unifyExact( 
-					t1, tupleFromDecls( crnt2, end2 ), env, need, have, open, 
+				return unifyExact(
+					t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,
 					noWiden(), symtab );
 			} else if ( crnt2 != end2 ) {
@@ -873,6 +873,6 @@
 				const ast::Type * t2 = (*crnt2)->get_type();
 				if ( ! Tuples::isTtype( t2 ) ) return false;
-				return unifyExact( 
-					tupleFromDecls( crnt1, end1 ), t2, env, need, have, open, 
+				return unifyExact(
+					tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,
 					noWiden(), symtab );
 			}
@@ -881,12 +881,12 @@
 		}
 
-		static bool unifyDeclList( 
-			const std::vector< ast::ptr< ast::DeclWithType > > & list1, 
-			const std::vector< ast::ptr< ast::DeclWithType > > & list2, 
-			ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 
+		static bool unifyDeclList(
+			const std::vector< ast::ptr< ast::DeclWithType > > & list1,
+			const std::vector< ast::ptr< ast::DeclWithType > > & list2,
+			ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
 			const ast::OpenVarSet & open, const ast::SymbolTable & symtab
 		) {
-			return unifyDeclList( 
-				list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open, 
+			return unifyDeclList(
+				list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,
 				symtab );
 		}
@@ -900,7 +900,7 @@
 
 		/// mark all assertions in `type` used in both `assn1` and `assn2`
-		static void markAssertions( 
-			ast::AssertionSet & assn1, ast::AssertionSet & assn2, 
-			const ast::ParameterizedType * type 
+		static void markAssertions(
+			ast::AssertionSet & assn1, ast::AssertionSet & assn2,
+			const ast::ParameterizedType * type
 		) {
 			for ( const auto & tyvar : type->forall ) {
@@ -918,13 +918,13 @@
 
 			if ( func->isVarArgs != func2->isVarArgs ) return;
-			
-			// Flatten the parameter lists for both functions so that tuple structure does not 
+
+			// Flatten the parameter lists for both functions so that tuple structure does not
 			// affect unification. Does not actually mutate function parameters.
 			auto params = flattenList( func->params, tenv );
 			auto params2 = flattenList( func2->params, tenv );
 
-			// sizes don't have to match if ttypes are involved; need to be more precise w.r.t. 
+			// sizes don't have to match if ttypes are involved; need to be more precise w.r.t.
 			// where the ttype is to prevent errors
-			if ( 
+			if (
 				( params.size() != params2.size() || func->returns.size() != func2->returns.size() )
 				&& ! func->isTtype()
@@ -933,7 +933,7 @@
 
 			if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return;
-			if ( ! unifyDeclList( 
+			if ( ! unifyDeclList(
 				func->returns, func2->returns, tenv, need, have, open, symtab ) ) return;
-			
+
 			markAssertions( have, need, func );
 			markAssertions( have, need, func2 );
@@ -941,5 +941,5 @@
 			result = true;
 		}
-	
+
 	private:
 		template< typename RefType >
@@ -953,5 +953,5 @@
 		/// Creates a tuple type based on a list of TypeExpr
 		template< typename Iter >
-		static const ast::Type * tupleFromExprs( 
+		static const ast::Type * tupleFromExprs(
 			const ast::TypeExpr * param, Iter & crnt, Iter end, ast::CV::Qualifiers qs
 		) {
@@ -973,5 +973,5 @@
 			const RefType * inst2 = handleRefType( inst, other );
 			if ( ! inst2 ) return;
-			
+
 			// check that parameters of types unify, if any
 			const std::vector< ast::ptr< ast::Expr > > & params = inst->params;
@@ -1002,5 +1002,5 @@
 				}
 
-				if ( ! unifyExact( 
+				if ( ! unifyExact(
 						pty, pty2, tenv, need, have, open, noWiden(), symtab ) ) {
 					result = false;
@@ -1038,10 +1038,10 @@
 	private:
 		/// Creates a tuple type based on a list of Type
-		static ast::ptr< ast::Type > tupleFromTypes( 
+		static ast::ptr< ast::Type > tupleFromTypes(
 			const std::vector< ast::ptr< ast::Type > > & tys
 		) {
 			std::vector< ast::ptr< ast::Type > > out;
 			for ( const ast::Type * ty : tys ) {
-				// it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure 
+				// it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure
 				// that this results in a flat tuple
 				flatten( ty, out );
@@ -1051,8 +1051,8 @@
 		}
 
-		static bool unifyList( 
-			const std::vector< ast::ptr< ast::Type > > & list1, 
-			const std::vector< ast::ptr< ast::Type > > & list2, ast::TypeEnvironment & env, 
-			ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 
+		static bool unifyList(
+			const std::vector< ast::ptr< ast::Type > > & list1,
+			const std::vector< ast::ptr< ast::Type > > & list2, ast::TypeEnvironment & env,
+			ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
 			const ast::SymbolTable & symtab
 		) {
@@ -1068,16 +1068,16 @@
 				if ( isTuple1 && ! isTuple2 ) {
 					// combine entirety of list2, then unify
-					return unifyExact( 
-						t1, tupleFromTypes( list2 ), env, need, have, open, 
+					return unifyExact(
+						t1, tupleFromTypes( list2 ), env, need, have, open,
 						noWiden(), symtab );
 				} else if ( ! isTuple1 && isTuple2 ) {
 					// combine entirety of list1, then unify
 					return unifyExact(
-						tupleFromTypes( list1 ), t2, env, need, have, open, 
+						tupleFromTypes( list1 ), t2, env, need, have, open,
 						noWiden(), symtab );
 				}
 
-				if ( ! unifyExact( 
-					t1, t2, env, need, have, open, noWiden(), symtab ) 
+				if ( ! unifyExact(
+					t1, t2, env, need, have, open, noWiden(), symtab )
 				) return false;
 
@@ -1089,8 +1089,8 @@
 				const ast::Type * t1 = *crnt1;
 				if ( ! Tuples::isTtype( t1 ) ) return false;
-				// xxx - this doesn't generate an empty tuple, contrary to comment; both ported 
+				// xxx - this doesn't generate an empty tuple, contrary to comment; both ported
 				// from Rob's code
-				return unifyExact( 
-						t1, tupleFromTypes( list2 ), env, need, have, open, 
+				return unifyExact(
+						t1, tupleFromTypes( list2 ), env, need, have, open,
 						noWiden(), symtab );
 			} else if ( crnt2 != list2.end() ) {
@@ -1098,8 +1098,8 @@
 				const ast::Type * t2 = *crnt2;
 				if ( ! Tuples::isTtype( t2 ) ) return false;
-				// xxx - this doesn't generate an empty tuple, contrary to comment; both ported 
+				// xxx - this doesn't generate an empty tuple, contrary to comment; both ported
 				// from Rob's code
 				return unifyExact(
-						tupleFromTypes( list1 ), t2, env, need, have, open, 
+						tupleFromTypes( list1 ), t2, env, need, have, open,
 						noWiden(), symtab );
 			}
@@ -1133,5 +1133,5 @@
 		void postvisit( const ast::OneType * ) {
 			result = dynamic_cast< const ast::OneType * >( type2 );
-		}	
+		}
 
 	  private:
@@ -1140,7 +1140,7 @@
 	};
 
-	bool unify( 
-			const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 
-			ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 
+	bool unify(
+			const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
+			ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
 			ast::OpenVarSet & open, const ast::SymbolTable & symtab
 	) {
@@ -1149,19 +1149,19 @@
 	}
 
-	bool unify( 
-			const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 
-			ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 
-			ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common 
+	bool unify(
+			const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
+			ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
+			ast::OpenVarSet & open, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common
 	) {
 		ast::OpenVarSet closed;
 		findOpenVars( type1, open, closed, need, have, FirstClosed );
 		findOpenVars( type2, open, closed, need, have, FirstOpen );
-		return unifyInexact( 
+		return unifyInexact(
 			type1, type2, env, need, have, open, WidenMode{ true, true }, symtab, common );
 	}
 
-	bool unifyExact( 
-			const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 
-			ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 
+	bool unifyExact(
+			const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
+			ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
 			WidenMode widen, const ast::SymbolTable & symtab
 	) {
@@ -1170,6 +1170,6 @@
 		auto var1 = dynamic_cast< const ast::TypeInstType * >( type1 );
 		auto var2 = dynamic_cast< const ast::TypeInstType * >( type2 );
-		ast::OpenVarSet::const_iterator 
-			entry1 = var1 ? open.find( var1->name ) : open.end(), 
+		ast::OpenVarSet::const_iterator
+			entry1 = var1 ? open.find( var1->name ) : open.end(),
 			entry2 = var2 ? open.find( var2->name ) : open.end();
 		bool isopen1 = entry1 != open.end();
@@ -1178,6 +1178,6 @@
 		if ( isopen1 && isopen2 ) {
 			if ( entry1->second.kind != entry2->second.kind ) return false;
-			return env.bindVarToVar( 
-				var1, var2, ast::TypeDecl::Data{ entry1->second, entry2->second }, need, have, 
+			return env.bindVarToVar(
+				var1, var2, ast::TypeDecl::Data{ entry1->second, entry2->second }, need, have,
 				open, widen, symtab );
 		} else if ( isopen1 ) {
@@ -1192,18 +1192,18 @@
 	}
 
-	bool unifyInexact( 
-			const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 
-			ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 
-			const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab, 
-			ast::ptr<ast::Type> & common 
+	bool unifyInexact(
+			const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2,
+			ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,
+			const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,
+			ast::ptr<ast::Type> & common
 	) {
 		ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;
-		
-		// force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and 
+
+		// force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and
 		// type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 1
 		ast::ptr<ast::Type> t1{ type1 }, t2{ type2 };
 		reset_qualifiers( t1 );
 		reset_qualifiers( t2 );
-		
+
 		if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {
 			t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones
Index: src/ResolvExpr/typeops.h
===================================================================
--- src/ResolvExpr/typeops.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/ResolvExpr/typeops.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -73,37 +73,37 @@
 
 	/// Replaces array types with equivalent pointer, and function types with a pointer-to-function
-	const ast::Type * adjustExprType( 
+	const ast::Type * adjustExprType(
 		const ast::Type * type, const ast::TypeEnvironment & env, const ast::SymbolTable & symtab );
 
 	// in CastCost.cc
-	Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
-	Cost castCost( 
-		const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 
+	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,
 		const ast::TypeEnvironment & env );
 
 	// in ConversionCost.cc
-	Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );
-	Cost conversionCost( 
-		const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 
+	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,
 		const ast::TypeEnvironment & env );
 
 	// in AlternativeFinder.cc
-	Cost computeConversionCost( Type *actualType, Type *formalType, 
+	Cost computeConversionCost( Type *actualType, Type *formalType,
 		const SymTab::Indexer &indexer, const TypeEnvironment &env );
 
 	// in PtrsAssignable.cc
-	int ptrsAssignable( Type *src, 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( Type *src, Type *dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
-	int ptrsCastable( 
-		const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab, 
+	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,
 		const ast::TypeEnvironment & env );
 
 	// in Unify.cc
 	bool typesCompatible( Type *, Type *, const SymTab::Indexer &indexer, const TypeEnvironment &env );
-	bool typesCompatibleIgnoreQualifiers( 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 ) {
@@ -112,15 +112,15 @@
 	}
 
-	inline bool typesCompatibleIgnoreQualifiers( Type *t1, 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 );
 	}
 
-	bool typesCompatible( 
-		const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {}, 
+	bool typesCompatible(
+		const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {},
 		const ast::TypeEnvironment & env = {} );
-	
+
 	bool typesCompatibleIgnoreQualifiers(
-		const ast::Type *, const ast::Type *, const ast::SymbolTable &, 
+		const ast::Type *, const ast::Type *, const ast::SymbolTable &,
 		const ast::TypeEnvironment & env = {} );
 
@@ -133,10 +133,10 @@
 	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, 
+		const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, WidenMode widen,
 		const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open );
 
 	// in PolyCost.cc
 	int polyCost( Type *type, const TypeEnvironment &env, const SymTab::Indexer &indexer );
-	int polyCost( 
+	int polyCost(
 		const ast::Type * type, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env );
 
@@ -149,5 +149,5 @@
 	// new AST version in TypeEnvironment.cpp (only place it was used in old AST)
 
-	template<typename Iter> 
+	template<typename Iter>
 	bool occursIn( Type* ty, Iter begin, Iter end, const TypeEnvironment &env ) {
 		while ( begin != end ) {
@@ -176,8 +176,8 @@
 
 	/// flatten tuple type into existing list of types
-	static inline void flatten( 
-		const ast::Type * type, std::vector< ast::ptr< ast::Type > > & out 
+	static inline void flatten(
+		const ast::Type * type, std::vector< ast::ptr< ast::Type > > & out
 	) {
-		if ( auto tupleType = dynamic_cast< const ast::TupleType * >( type ) ) {	
+		if ( auto tupleType = dynamic_cast< const ast::TupleType * >( type ) ) {
 			for ( const ast::Type * t : tupleType->types ) {
 				flatten( t, out );
Index: src/SymTab/Validate.h
===================================================================
--- src/SymTab/Validate.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/SymTab/Validate.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -19,7 +19,7 @@
 #include <list>  // for list
 
-class CodeLocation;
-class Declaration;
-class Type;
+struct CodeLocation;
+class  Declaration;
+class  Type;
 
 namespace ast {
@@ -35,5 +35,5 @@
 	void validateType( Type *type, const Indexer *indexer );
 
-	const ast::Type * validateType( 
+	const ast::Type * validateType(
 		const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab );
 } // namespace SymTab
Index: src/SynTree/Attribute.h
===================================================================
--- src/SynTree/Attribute.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/SynTree/Attribute.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -50,4 +50,5 @@
 	Attribute * clone() const override { return new Attribute( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Attribute * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
Index: src/SynTree/BaseSyntaxNode.h
===================================================================
--- src/SynTree/BaseSyntaxNode.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/SynTree/BaseSyntaxNode.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -32,9 +32,10 @@
 	BaseSyntaxNode( const BaseSyntaxNode & o ) : location(o.location) { ++*new_nodes; }
 	BaseSyntaxNode & operator=( const BaseSyntaxNode & ) = default;
-	
+
 	virtual ~BaseSyntaxNode() {}
 
 	virtual BaseSyntaxNode * clone() const = 0;
 	virtual void accept( Visitor & v ) = 0;
+	virtual void accept( Visitor & v ) const = 0;
 	virtual BaseSyntaxNode * acceptMutator( Mutator & m ) = 0;
 	/// Notes:
Index: src/SynTree/Constant.h
===================================================================
--- src/SynTree/Constant.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/SynTree/Constant.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -33,5 +33,5 @@
 	virtual ~Constant();
 
-	virtual Constant * clone() const { return new Constant( *this ); }
+	virtual Constant * clone() const override { return new Constant( *this ); }
 
 	Type * get_type() { return type; }
@@ -51,13 +51,12 @@
 	static Constant null( Type * ptrtype = nullptr );
 
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Constant * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = 0 ) const;
-  private:
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Constant * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = 0 ) const override;
+
 	Type * type;
 	std::string rep;
 	std::optional<unsigned long long> ival;
-
-	friend class ConverterOldToNew;
 };
 
Index: src/SynTree/Declaration.h
===================================================================
--- src/SynTree/Declaration.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/SynTree/Declaration.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -63,5 +63,6 @@
 	void fixUniqueId( void );
 	virtual Declaration *clone() const override = 0;
-	virtual void accept( Visitor &v ) override = 0;
+	virtual void accept( Visitor & v ) override = 0;
+	virtual void accept( Visitor & v ) const override = 0;
 	virtual Declaration *acceptMutator( Mutator &m ) override = 0;
 	virtual void print( std::ostream &os, Indenter indent = {} ) const override = 0;
@@ -139,5 +140,6 @@
 
 	virtual ObjectDecl *clone() const override { return new ObjectDecl( *this ); }
-	virtual void accept( Visitor &v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual DeclarationWithType *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
@@ -169,5 +171,6 @@
 
 	virtual FunctionDecl *clone() const override { return new FunctionDecl( *this ); }
-	virtual void accept( Visitor &v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual DeclarationWithType *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
@@ -238,5 +241,6 @@
 
 	virtual TypeDecl *clone() const override { return new TypeDecl( *this ); }
-	virtual void accept( Visitor &v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
@@ -256,5 +260,6 @@
 
 	virtual TypedefDecl *clone() const override { return new TypedefDecl( *this ); }
-	virtual void accept( Visitor &v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
   private:
@@ -300,5 +305,6 @@
 
 	virtual StructDecl *clone() const override { return new StructDecl( *this ); }
-	virtual void accept( Visitor &v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
 	DeclarationNode::Aggregate kind;
@@ -314,5 +320,6 @@
 
 	virtual UnionDecl *clone() const override { return new UnionDecl( *this ); }
-	virtual void accept( Visitor &v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
   private:
@@ -329,5 +336,6 @@
 
 	virtual EnumDecl *clone() const override { return new EnumDecl( *this ); }
-	virtual void accept( Visitor &v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
   private:
@@ -345,5 +353,6 @@
 
 	virtual TraitDecl *clone() const override { return new TraitDecl( *this ); }
-	virtual void accept( Visitor &v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Declaration *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
   private:
@@ -363,5 +372,6 @@
 
 	virtual AsmDecl *clone() const override { return new AsmDecl( *this ); }
-	virtual void accept( Visitor &v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual AsmDecl *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
@@ -379,5 +389,6 @@
 
 	virtual StaticAssertDecl * clone() const override { return new StaticAssertDecl( *this ); }
-	virtual void accept( Visitor &v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual StaticAssertDecl * acceptMutator( Mutator &m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/SynTree/Expression.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -82,4 +82,5 @@
 	virtual Expression * clone() const override = 0;
 	virtual void accept( Visitor & v ) override = 0;
+	virtual void accept( Visitor & v ) const override = 0;
 	virtual Expression * acceptMutator( Mutator & m ) override = 0;
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -101,8 +102,9 @@
 	std::list<Expression *>& get_args() { return args; }
 
-	virtual ApplicationExpr * clone() const { return new ApplicationExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual ApplicationExpr * clone() const override { return new ApplicationExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -129,8 +131,9 @@
 	static UntypedExpr * createAssign( Expression * arg1, Expression * arg2 );
 
-	virtual UntypedExpr * clone() const { return new UntypedExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual UntypedExpr * clone() const override { return new UntypedExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -147,8 +150,9 @@
 	void set_name( std::string newValue ) { name = newValue; }
 
-	virtual NameExpr * clone() const { return new NameExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual NameExpr * clone() const override { return new NameExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -168,8 +172,9 @@
 	void set_arg(Expression * newValue ) { arg = newValue; }
 
-	virtual AddressExpr * clone() const { return new AddressExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual AddressExpr * clone() const override { return new AddressExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -184,8 +189,9 @@
 	virtual ~LabelAddressExpr();
 
-	virtual LabelAddressExpr * clone() const { return new LabelAddressExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual LabelAddressExpr * clone() const override { return new LabelAddressExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -205,8 +211,9 @@
 	void set_arg( Expression * newValue ) { arg = newValue; }
 
-	virtual CastExpr * clone() const { return new CastExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual CastExpr * clone() const override { return new CastExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -225,8 +232,9 @@
 	const std::string & targetString() const;
 
-	virtual KeywordCastExpr * clone() const { return new KeywordCastExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual KeywordCastExpr * clone() const override { return new KeywordCastExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -243,8 +251,9 @@
 	void set_arg( Expression * newValue ) { arg = newValue; }
 
-	virtual VirtualCastExpr * clone() const { return new VirtualCastExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual VirtualCastExpr * clone() const override { return new VirtualCastExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -264,8 +273,9 @@
 	void set_aggregate( Expression * newValue ) { aggregate = newValue; }
 
-	virtual UntypedMemberExpr * clone() const { return new UntypedMemberExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual UntypedMemberExpr * clone() const override { return new UntypedMemberExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -286,8 +296,9 @@
 	void set_aggregate( Expression * newValue ) { aggregate = newValue; }
 
-	virtual MemberExpr * clone() const { return new MemberExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual MemberExpr * clone() const override { return new MemberExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -308,8 +319,9 @@
 	static VariableExpr * functionPointer( FunctionDecl * decl );
 
-	virtual VariableExpr * clone() const { return new VariableExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual VariableExpr * clone() const override { return new VariableExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -329,8 +341,9 @@
 	long long int intValue() const;
 
-	virtual ConstantExpr * clone() const { return new ConstantExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual ConstantExpr * clone() const override { return new ConstantExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -354,8 +367,9 @@
 	void set_isType( bool newValue ) { isType = newValue; }
 
-	virtual SizeofExpr * clone() const { return new SizeofExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual SizeofExpr * clone() const override { return new SizeofExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -379,8 +393,9 @@
 	void set_isType( bool newValue ) { isType = newValue; }
 
-	virtual AlignofExpr * clone() const { return new AlignofExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual AlignofExpr * clone() const override { return new AlignofExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -400,8 +415,9 @@
 	void set_type( Type * newValue ) { type = newValue; }
 
-	virtual UntypedOffsetofExpr * clone() const { return new UntypedOffsetofExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual UntypedOffsetofExpr * clone() const override { return new UntypedOffsetofExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -421,8 +437,9 @@
 	void set_member( DeclarationWithType * newValue ) { member = newValue; }
 
-	virtual OffsetofExpr * clone() const { return new OffsetofExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual OffsetofExpr * clone() const override { return new OffsetofExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -439,8 +456,9 @@
 	void set_type( StructInstType * newValue ) { type = newValue; }
 
-	virtual OffsetPackExpr * clone() const { return new OffsetPackExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual OffsetPackExpr * clone() const override { return new OffsetPackExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -467,8 +485,9 @@
 	void set_isType( bool newValue ) { isType = newValue; }
 
-	virtual AttrExpr * clone() const { return new AttrExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual AttrExpr * clone() const override { return new AttrExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -489,8 +508,9 @@
 	void set_arg2( Expression * newValue ) { arg2 = newValue; }
 
-	virtual LogicalExpr * clone() const { return new LogicalExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual LogicalExpr * clone() const override { return new LogicalExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 
   private:
@@ -516,8 +536,9 @@
 	void set_arg3( Expression * newValue ) { arg3 = newValue; }
 
-	virtual ConditionalExpr * clone() const { return new ConditionalExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual ConditionalExpr * clone() const override { return new ConditionalExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -537,8 +558,9 @@
 	void set_arg2( Expression * newValue ) { arg2 = newValue; }
 
-	virtual CommaExpr * clone() const { return new CommaExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual CommaExpr * clone() const override { return new CommaExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -555,8 +577,9 @@
 	void set_type( Type * newValue ) { type = newValue; }
 
-	virtual TypeExpr * clone() const { return new TypeExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual TypeExpr * clone() const override { return new TypeExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -581,8 +604,9 @@
 	void set_operand( Expression * newValue ) { operand = newValue; }
 
-	virtual AsmExpr * clone() const { return new AsmExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual AsmExpr * clone() const override { return new AsmExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 
 	// https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Machine-Constraints.html#Machine-Constraints
@@ -599,8 +623,9 @@
 	virtual ~ImplicitCopyCtorExpr();
 
-	virtual ImplicitCopyCtorExpr * clone() const { return new ImplicitCopyCtorExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual ImplicitCopyCtorExpr * clone() const override { return new ImplicitCopyCtorExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -617,8 +642,9 @@
 	void set_callExpr( Expression * newValue ) { callExpr = newValue; }
 
-	virtual ConstructorExpr * clone() const { return new ConstructorExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual ConstructorExpr * clone() const override { return new ConstructorExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -635,8 +661,9 @@
 	void set_initializer( Initializer * i ) { initializer = i; }
 
-	virtual CompoundLiteralExpr * clone() const { return new CompoundLiteralExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual CompoundLiteralExpr * clone() const override { return new CompoundLiteralExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -654,8 +681,9 @@
 	RangeExpr * set_high( Expression * high ) { RangeExpr::high = high; return this; }
 
-	virtual RangeExpr * clone() const { return new RangeExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual RangeExpr * clone() const override { return new RangeExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -671,8 +699,9 @@
 	std::list<Expression*>& get_exprs() { return exprs; }
 
-	virtual UntypedTupleExpr * clone() const { return new UntypedTupleExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual UntypedTupleExpr * clone() const override { return new UntypedTupleExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -688,8 +717,9 @@
 	std::list<Expression*>& get_exprs() { return exprs; }
 
-	virtual TupleExpr * clone() const { return new TupleExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual TupleExpr * clone() const override { return new TupleExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -709,8 +739,9 @@
 	TupleIndexExpr * set_index( unsigned int newValue ) { index = newValue; return this; }
 
-	virtual TupleIndexExpr * clone() const { return new TupleIndexExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual TupleIndexExpr * clone() const override { return new TupleIndexExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -727,8 +758,9 @@
 	StmtExpr * get_stmtExpr() const { return stmtExpr; }
 
-	virtual TupleAssignExpr * clone() const { return new TupleAssignExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual TupleAssignExpr * clone() const override { return new TupleAssignExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 
 	friend class ConverterNewToOld;
@@ -760,8 +792,9 @@
 	std::list< Expression * > & get_dtors() { return dtors; }
 
-	virtual StmtExpr * clone() const { return new StmtExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual StmtExpr * clone() const override { return new StmtExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -787,8 +820,9 @@
 	int get_id() const { return id; }
 
-	virtual UniqueExpr * clone() const { return new UniqueExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual UniqueExpr * clone() const override { return new UniqueExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 
 private:
@@ -821,8 +855,9 @@
 	std::list<InitAlternative> & get_initAlts() { return initAlts; }
 
-	virtual UntypedInitExpr * clone() const { return new UntypedInitExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual UntypedInitExpr * clone() const override { return new UntypedInitExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -842,8 +877,9 @@
 	InitExpr * set_designation( Designation * newValue ) { designation = newValue; return this; }
 
-	virtual InitExpr * clone() const { return new InitExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual InitExpr * clone() const override { return new InitExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -858,8 +894,9 @@
 	~DeletedExpr();
 
-	virtual DeletedExpr * clone() const { return new DeletedExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual DeletedExpr * clone() const override { return new DeletedExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -873,8 +910,9 @@
 	~DefaultArgExpr();
 
-	virtual DefaultArgExpr * clone() const { return new DefaultArgExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual DefaultArgExpr * clone() const override { return new DefaultArgExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -901,8 +939,9 @@
 	virtual ~GenericExpr();
 
-	virtual GenericExpr * clone() const { return new GenericExpr( * this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Expression * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual GenericExpr * clone() const override { return new GenericExpr( * this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Expression * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
Index: src/SynTree/Initializer.h
===================================================================
--- src/SynTree/Initializer.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/SynTree/Initializer.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -38,5 +38,6 @@
 
 	virtual Designation * clone() const override { return new Designation( *this ); };
-	virtual void accept( Visitor &v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Designation * acceptMutator( Mutator &m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
@@ -52,8 +53,9 @@
 	virtual ~Initializer();
 
-	bool get_maybeConstructed() { return maybeConstructed; }
+	bool get_maybeConstructed() const { return maybeConstructed; }
 
 	virtual Initializer *clone() const override = 0;
-	virtual void accept( Visitor &v ) override = 0;
+	virtual void accept( Visitor & v ) override = 0;
+	virtual void accept( Visitor & v ) const override = 0;
 	virtual Initializer *acceptMutator( Mutator &m ) override = 0;
 	virtual void print( std::ostream &os, Indenter indent = {} ) const override = 0;
@@ -76,5 +78,6 @@
 
 	virtual SingleInit *clone() const override { return new SingleInit( *this); }
-	virtual void accept( Visitor &v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
@@ -104,5 +107,6 @@
 
 	virtual ListInit *clone() const override { return new ListInit( *this ); }
-	virtual void accept( Visitor &v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
@@ -133,5 +137,6 @@
 
 	ConstructorInit *clone() const override { return new ConstructorInit( *this ); }
-	virtual void accept( Visitor &v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Initializer *acceptMutator( Mutator &m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream &os, Indenter indent = {} ) const override;
Index: src/SynTree/Statement.h
===================================================================
--- src/SynTree/Statement.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/SynTree/Statement.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -45,4 +45,5 @@
 	virtual Statement * clone() const override = 0;
 	virtual void accept( Visitor & v ) override = 0;
+	virtual void accept( Visitor & v ) const override = 0;
 	virtual Statement * acceptMutator( Mutator & m ) override = 0;
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -64,4 +65,5 @@
 	virtual CompoundStmt * clone() const override { return new CompoundStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual CompoundStmt * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -74,4 +76,5 @@
 	virtual NullStmt * clone() const override { return new NullStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual NullStmt * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -91,4 +94,5 @@
 	virtual ExprStmt * clone() const override { return new ExprStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -120,8 +124,9 @@
 	void set_gotolabels( const std::list<Label> & newValue ) { gotolabels = newValue; }
 
-	virtual AsmStmt * clone() const { return new AsmStmt( *this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual AsmStmt * clone() const override { return new AsmStmt( *this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Statement * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -133,8 +138,9 @@
 	virtual ~DirectiveStmt(){}
 
-	virtual DirectiveStmt * clone() const { return new DirectiveStmt( *this ); }
-	virtual void accept( Visitor & v ) { v.visit( this ); }
-	virtual Statement * acceptMutator( Mutator & m ) { return m.mutate( this ); }
-	virtual void print( std::ostream & os, Indenter indent = {} ) const;
+	virtual DirectiveStmt * clone() const override { return new DirectiveStmt( *this ); }
+	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
+	virtual Statement * acceptMutator( Mutator & m ) override { return m.mutate( this ); }
+	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
 };
 
@@ -161,4 +167,5 @@
 	virtual IfStmt * clone() const override { return new IfStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -180,4 +187,5 @@
 
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 
@@ -208,4 +216,5 @@
 
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 
@@ -236,4 +245,5 @@
 	virtual WhileStmt * clone() const override { return new WhileStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -261,4 +271,5 @@
 	virtual ForStmt * clone() const override { return new ForStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -290,4 +301,5 @@
 	virtual BranchStmt * clone() const override { return new BranchStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -309,4 +321,5 @@
 	virtual ReturnStmt * clone() const override { return new ReturnStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -333,4 +346,5 @@
 	virtual ThrowStmt * clone() const override { return new ThrowStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -356,4 +370,5 @@
 	virtual TryStmt * clone() const override { return new TryStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -384,4 +399,5 @@
 	virtual CatchStmt * clone() const override { return new CatchStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -401,4 +417,5 @@
 	virtual FinallyStmt * clone() const override { return new FinallyStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -438,4 +455,5 @@
 	virtual WaitForStmt * clone() const override { return new WaitForStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -454,4 +472,5 @@
 	virtual WithStmt * clone() const override { return new WithStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -473,4 +492,5 @@
 	virtual DeclStmt * clone() const override { return new DeclStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -494,4 +514,5 @@
 	virtual ImplicitCtorDtorStmt * clone() const override { return new ImplicitCtorDtorStmt( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Statement * acceptMutator( Mutator & m )  override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/SynTree/Type.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -144,10 +144,10 @@
 
 	Qualifiers & get_qualifiers() { return tq; }
-	bool get_const() { return tq.is_const; }
-	bool get_volatile() { return tq.is_volatile; }
-	bool get_restrict() { return tq.is_restrict; }
-	bool get_lvalue() { return tq.is_lvalue; }
-	bool get_mutex() { return tq.is_mutex; }
-	bool get_atomic() { return tq.is_atomic; }
+	bool get_const() const { return tq.is_const; }
+	bool get_volatile() const { return tq.is_volatile; }
+	bool get_restrict() const { return tq.is_restrict; }
+	bool get_lvalue() const { return tq.is_lvalue; }
+	bool get_mutex() const { return tq.is_mutex; }
+	bool get_atomic() const { return tq.is_atomic; }
 	void set_const( bool newValue ) { tq.is_const = newValue; }
 	void set_volatile( bool newValue ) { tq.is_volatile = newValue; }
@@ -184,4 +184,5 @@
 	virtual Type *clone() const = 0;
 	virtual void accept( Visitor & v ) = 0;
+	virtual void accept( Visitor & v ) const = 0;
 	virtual Type *acceptMutator( Mutator & m ) = 0;
 	virtual void print( std::ostream & os, Indenter indent = {} ) const;
@@ -201,4 +202,5 @@
 	virtual VoidType *clone() const override { return new VoidType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -259,4 +261,5 @@
 	virtual BasicType *clone() const override { return new BasicType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -294,4 +297,5 @@
 	virtual PointerType *clone() const override { return new PointerType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -325,4 +329,5 @@
 	virtual ArrayType *clone() const override { return new ArrayType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -340,4 +345,5 @@
 	virtual QualifiedType *clone() const override { return new QualifiedType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -366,4 +372,5 @@
 	virtual ReferenceType *clone() const override { return new ReferenceType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -395,4 +402,5 @@
 	virtual FunctionType *clone() const override { return new FunctionType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -455,4 +463,5 @@
 	virtual StructInstType *clone() const override { return new StructInstType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 
@@ -492,4 +501,5 @@
 	virtual UnionInstType *clone() const override { return new UnionInstType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 
@@ -519,4 +529,5 @@
 	virtual EnumInstType *clone() const override { return new EnumInstType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 
@@ -542,4 +553,5 @@
 	virtual TraitInstType *clone() const override { return new TraitInstType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
   private:
@@ -569,4 +581,5 @@
 	virtual TypeInstType *clone() const override { return new TypeInstType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -606,4 +619,5 @@
 	virtual TupleType *clone() const override { return new TupleType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -616,5 +630,5 @@
 
 	TypeofType( const Type::Qualifiers & tq, Expression *expr, const std::list< Attribute * > & attributes = std::list< Attribute * >() );
-	TypeofType( const Type::Qualifiers & tq, Expression *expr, bool is_basetypeof, 
+	TypeofType( const Type::Qualifiers & tq, Expression *expr, bool is_basetypeof,
 		const std::list< Attribute * > & attributes = std::list< Attribute * >() );
 	TypeofType( const TypeofType& );
@@ -628,4 +642,5 @@
 	virtual TypeofType *clone() const override { return new TypeofType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -657,4 +672,5 @@
 	virtual AttrType *clone() const override { return new AttrType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -671,4 +687,5 @@
 	virtual VarArgsType *clone() const override { return new VarArgsType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -683,4 +700,5 @@
 	virtual ZeroType *clone() const override { return new ZeroType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -695,4 +713,5 @@
 	virtual OneType *clone() const override { return new OneType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
@@ -705,4 +724,5 @@
 	virtual GlobalScopeType *clone() const override { return new GlobalScopeType( *this ); }
 	virtual void accept( Visitor & v ) override { v.visit( this ); }
+	virtual void accept( Visitor & v ) const override { v.visit( this ); }
 	virtual Type *acceptMutator( Mutator & m ) override { return m.mutate( this ); }
 	virtual void print( std::ostream & os, Indenter indent = {} ) const override;
Index: src/SynTree/Visitor.h
===================================================================
--- src/SynTree/Visitor.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/SynTree/Visitor.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -27,103 +27,196 @@
 	// of the given syntax node, but performs no other action.
 
-	virtual void visit( ObjectDecl * objectDecl ) = 0;
-	virtual void visit( FunctionDecl * functionDecl ) = 0;
-	virtual void visit( StructDecl * aggregateDecl ) = 0;
-	virtual void visit( UnionDecl * aggregateDecl ) = 0;
-	virtual void visit( EnumDecl * aggregateDecl ) = 0;
-	virtual void visit( TraitDecl * aggregateDecl ) = 0;
-	virtual void visit( TypeDecl * typeDecl ) = 0;
-	virtual void visit( TypedefDecl * typeDecl ) = 0;
-	virtual void visit( AsmDecl * asmDecl ) = 0;
-	virtual void visit( StaticAssertDecl * assertDecl ) = 0;
-
-	virtual void visit( CompoundStmt * compoundStmt ) = 0;
-	virtual void visit( ExprStmt * exprStmt ) = 0;
-	virtual void visit( AsmStmt * asmStmt ) = 0;
-	virtual void visit( DirectiveStmt * directiveStmt ) = 0;
-	virtual void visit( IfStmt * ifStmt ) = 0;
-	virtual void visit( WhileStmt * whileStmt ) = 0;
-	virtual void visit( ForStmt * forStmt ) = 0;
-	virtual void visit( SwitchStmt * switchStmt ) = 0;
-	virtual void visit( CaseStmt * caseStmt ) = 0;
-	virtual void visit( BranchStmt * branchStmt ) = 0;
-	virtual void visit( ReturnStmt * returnStmt ) = 0;
-	virtual void visit( ThrowStmt * throwStmt ) = 0;
-	virtual void visit( TryStmt * tryStmt ) = 0;
-	virtual void visit( CatchStmt * catchStmt ) = 0;
-	virtual void visit( FinallyStmt * finallyStmt ) = 0;
-	virtual void visit( WaitForStmt * waitforStmt ) = 0;
-	virtual void visit( WithStmt * withStmt ) = 0;
-	virtual void visit( NullStmt * nullStmt ) = 0;
-	virtual void visit( DeclStmt * declStmt ) = 0;
-	virtual void visit( ImplicitCtorDtorStmt * impCtorDtorStmt ) = 0;
-
-	virtual void visit( ApplicationExpr * applicationExpr ) = 0;
-	virtual void visit( UntypedExpr * untypedExpr ) = 0;
-	virtual void visit( NameExpr * nameExpr ) = 0;
-	virtual void visit( CastExpr * castExpr ) = 0;
-	virtual void visit( KeywordCastExpr * castExpr ) = 0;
-	virtual void visit( VirtualCastExpr * castExpr ) = 0;
-	virtual void visit( AddressExpr * addressExpr ) = 0;
-	virtual void visit( LabelAddressExpr * labAddressExpr ) = 0;
-	virtual void visit( UntypedMemberExpr * memberExpr ) = 0;
-	virtual void visit( MemberExpr * memberExpr ) = 0;
-	virtual void visit( VariableExpr * variableExpr ) = 0;
-	virtual void visit( ConstantExpr * constantExpr ) = 0;
-	virtual void visit( SizeofExpr * sizeofExpr ) = 0;
-	virtual void visit( AlignofExpr * alignofExpr ) = 0;
-	virtual void visit( UntypedOffsetofExpr * offsetofExpr ) = 0;
-	virtual void visit( OffsetofExpr * offsetofExpr ) = 0;
-	virtual void visit( OffsetPackExpr * offsetPackExpr ) = 0;
-	virtual void visit( AttrExpr * attrExpr ) = 0;
-	virtual void visit( LogicalExpr * logicalExpr ) = 0;
-	virtual void visit( ConditionalExpr * conditionalExpr ) = 0;
-	virtual void visit( CommaExpr * commaExpr ) = 0;
-	virtual void visit( TypeExpr * typeExpr ) = 0;
-	virtual void visit( AsmExpr * asmExpr ) = 0;
-	virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ) = 0;
-	virtual void visit( ConstructorExpr *  ctorExpr ) = 0;
-	virtual void visit( CompoundLiteralExpr * compLitExpr ) = 0;
-	virtual void visit( RangeExpr * rangeExpr ) = 0;
-	virtual void visit( UntypedTupleExpr * tupleExpr ) = 0;
-	virtual void visit( TupleExpr * tupleExpr ) = 0;
-	virtual void visit( TupleIndexExpr * tupleExpr ) = 0;
-	virtual void visit( TupleAssignExpr * assignExpr ) = 0;
-	virtual void visit( StmtExpr *  stmtExpr ) = 0;
-	virtual void visit( UniqueExpr *  uniqueExpr ) = 0;
-	virtual void visit( UntypedInitExpr *  initExpr ) = 0;
-	virtual void visit( InitExpr *  initExpr ) = 0;
-	virtual void visit( DeletedExpr * delExpr ) = 0;
-	virtual void visit( DefaultArgExpr * argExpr ) = 0;
-	virtual void visit( GenericExpr * genExpr ) = 0;
-
-	virtual void visit( VoidType * basicType ) = 0;
-	virtual void visit( BasicType * basicType ) = 0;
-	virtual void visit( PointerType * pointerType ) = 0;
-	virtual void visit( ArrayType * arrayType ) = 0;
-	virtual void visit( ReferenceType * refType ) = 0;
-	virtual void visit( QualifiedType * qualType ) = 0;
-	virtual void visit( FunctionType * functionType ) = 0;
-	virtual void visit( StructInstType * aggregateUseType ) = 0;
-	virtual void visit( UnionInstType * aggregateUseType ) = 0;
-	virtual void visit( EnumInstType * aggregateUseType ) = 0;
-	virtual void visit( TraitInstType * aggregateUseType ) = 0;
-	virtual void visit( TypeInstType * aggregateUseType ) = 0;
-	virtual void visit( TupleType * tupleType ) = 0;
-	virtual void visit( TypeofType * typeofType ) = 0;
-	virtual void visit( AttrType * attrType ) = 0;
-	virtual void visit( VarArgsType * varArgsType ) = 0;
-	virtual void visit( ZeroType * zeroType ) = 0;
-	virtual void visit( OneType * oneType ) = 0;
-	virtual void visit( GlobalScopeType * globalType ) = 0;
-
-	virtual void visit( Designation * designation ) = 0;
-	virtual void visit( SingleInit * singleInit ) = 0;
-	virtual void visit( ListInit * listInit ) = 0;
-	virtual void visit( ConstructorInit * ctorInit ) = 0;
-
-	virtual void visit( Constant * constant ) = 0;
-
-	virtual void visit( Attribute * attribute ) = 0;
+	virtual void visit( ObjectDecl * node ) { visit( const_cast<const ObjectDecl *>(node) ); }
+	virtual void visit( const ObjectDecl * objectDecl ) = 0;
+	virtual void visit( FunctionDecl * node ) { visit( const_cast<const FunctionDecl *>(node) ); }
+	virtual void visit( const FunctionDecl * functionDecl ) = 0;
+	virtual void visit( StructDecl * node ) { visit( const_cast<const StructDecl *>(node) ); }
+	virtual void visit( const StructDecl * aggregateDecl ) = 0;
+	virtual void visit( UnionDecl * node ) { visit( const_cast<const UnionDecl *>(node) ); }
+	virtual void visit( const UnionDecl * aggregateDecl ) = 0;
+	virtual void visit( EnumDecl * node ) { visit( const_cast<const EnumDecl *>(node) ); }
+	virtual void visit( const EnumDecl * aggregateDecl ) = 0;
+	virtual void visit( TraitDecl * node ) { visit( const_cast<const TraitDecl *>(node) ); }
+	virtual void visit( const TraitDecl * aggregateDecl ) = 0;
+	virtual void visit( TypeDecl * node ) { visit( const_cast<const TypeDecl *>(node) ); }
+	virtual void visit( const TypeDecl * typeDecl ) = 0;
+	virtual void visit( TypedefDecl * node ) { visit( const_cast<const TypedefDecl *>(node) ); }
+	virtual void visit( const TypedefDecl * typeDecl ) = 0;
+	virtual void visit( AsmDecl * node ) { visit( const_cast<const AsmDecl *>(node) ); }
+	virtual void visit( const AsmDecl * asmDecl ) = 0;
+	virtual void visit( StaticAssertDecl * node ) { visit( const_cast<const StaticAssertDecl *>(node) ); }
+	virtual void visit( const StaticAssertDecl * assertDecl ) = 0;
+
+	virtual void visit( CompoundStmt * node ) { visit( const_cast<const CompoundStmt *>(node) ); }
+	virtual void visit( const CompoundStmt * compoundStmt ) = 0;
+	virtual void visit( ExprStmt * node ) { visit( const_cast<const ExprStmt *>(node) ); }
+	virtual void visit( const ExprStmt * exprStmt ) = 0;
+	virtual void visit( AsmStmt * node ) { visit( const_cast<const AsmStmt *>(node) ); }
+	virtual void visit( const AsmStmt * asmStmt ) = 0;
+	virtual void visit( DirectiveStmt * node ) { visit( const_cast<const DirectiveStmt *>(node) ); }
+	virtual void visit( const DirectiveStmt * directiveStmt ) = 0;
+	virtual void visit( IfStmt * node ) { visit( const_cast<const IfStmt *>(node) ); }
+	virtual void visit( const IfStmt * ifStmt ) = 0;
+	virtual void visit( WhileStmt * node ) { visit( const_cast<const WhileStmt *>(node) ); }
+	virtual void visit( const WhileStmt * whileStmt ) = 0;
+	virtual void visit( ForStmt * node ) { visit( const_cast<const ForStmt *>(node) ); }
+	virtual void visit( const ForStmt * forStmt ) = 0;
+	virtual void visit( SwitchStmt * node ) { visit( const_cast<const SwitchStmt *>(node) ); }
+	virtual void visit( const SwitchStmt * switchStmt ) = 0;
+	virtual void visit( CaseStmt * node ) { visit( const_cast<const CaseStmt *>(node) ); }
+	virtual void visit( const CaseStmt * caseStmt ) = 0;
+	virtual void visit( BranchStmt * node ) { visit( const_cast<const BranchStmt *>(node) ); }
+	virtual void visit( const BranchStmt * branchStmt ) = 0;
+	virtual void visit( ReturnStmt * node ) { visit( const_cast<const ReturnStmt *>(node) ); }
+	virtual void visit( const ReturnStmt * returnStmt ) = 0;
+	virtual void visit( ThrowStmt * node ) { visit( const_cast<const ThrowStmt *>(node) ); }
+	virtual void visit( const ThrowStmt * throwStmt ) = 0;
+	virtual void visit( TryStmt * node ) { visit( const_cast<const TryStmt *>(node) ); }
+	virtual void visit( const TryStmt * tryStmt ) = 0;
+	virtual void visit( CatchStmt * node ) { visit( const_cast<const CatchStmt *>(node) ); }
+	virtual void visit( const CatchStmt * catchStmt ) = 0;
+	virtual void visit( FinallyStmt * node ) { visit( const_cast<const FinallyStmt *>(node) ); }
+	virtual void visit( const FinallyStmt * finallyStmt ) = 0;
+	virtual void visit( WaitForStmt * node ) { visit( const_cast<const WaitForStmt *>(node) ); }
+	virtual void visit( const WaitForStmt * waitforStmt ) = 0;
+	virtual void visit( WithStmt * node ) { visit( const_cast<const WithStmt *>(node) ); }
+	virtual void visit( const WithStmt * withStmt ) = 0;
+	virtual void visit( NullStmt * node ) { visit( const_cast<const NullStmt *>(node) ); }
+	virtual void visit( const NullStmt * nullStmt ) = 0;
+	virtual void visit( DeclStmt * node ) { visit( const_cast<const DeclStmt *>(node) ); }
+	virtual void visit( const DeclStmt * declStmt ) = 0;
+	virtual void visit( ImplicitCtorDtorStmt * node ) { visit( const_cast<const ImplicitCtorDtorStmt *>(node) ); }
+	virtual void visit( const ImplicitCtorDtorStmt * impCtorDtorStmt ) = 0;
+
+	virtual void visit( ApplicationExpr * node ) { visit( const_cast<const ApplicationExpr *>(node) ); }
+	virtual void visit( const ApplicationExpr * applicationExpr ) = 0;
+	virtual void visit( UntypedExpr * node ) { visit( const_cast<const UntypedExpr *>(node) ); }
+	virtual void visit( const UntypedExpr * untypedExpr ) = 0;
+	virtual void visit( NameExpr * node ) { visit( const_cast<const NameExpr *>(node) ); }
+	virtual void visit( const NameExpr * nameExpr ) = 0;
+	virtual void visit( CastExpr * node ) { visit( const_cast<const CastExpr *>(node) ); }
+	virtual void visit( const CastExpr * castExpr ) = 0;
+	virtual void visit( KeywordCastExpr * node ) { visit( const_cast<const KeywordCastExpr *>(node) ); }
+	virtual void visit( const KeywordCastExpr * castExpr ) = 0;
+	virtual void visit( VirtualCastExpr * node ) { visit( const_cast<const VirtualCastExpr *>(node) ); }
+	virtual void visit( const VirtualCastExpr * castExpr ) = 0;
+	virtual void visit( AddressExpr * node ) { visit( const_cast<const AddressExpr *>(node) ); }
+	virtual void visit( const AddressExpr * addressExpr ) = 0;
+	virtual void visit( LabelAddressExpr * node ) { visit( const_cast<const LabelAddressExpr *>(node) ); }
+	virtual void visit( const LabelAddressExpr * labAddressExpr ) = 0;
+	virtual void visit( UntypedMemberExpr * node ) { visit( const_cast<const UntypedMemberExpr *>(node) ); }
+	virtual void visit( const UntypedMemberExpr * memberExpr ) = 0;
+	virtual void visit( MemberExpr * node ) { visit( const_cast<const MemberExpr *>(node) ); }
+	virtual void visit( const MemberExpr * memberExpr ) = 0;
+	virtual void visit( VariableExpr * node ) { visit( const_cast<const VariableExpr *>(node) ); }
+	virtual void visit( const VariableExpr * variableExpr ) = 0;
+	virtual void visit( ConstantExpr * node ) { visit( const_cast<const ConstantExpr *>(node) ); }
+	virtual void visit( const ConstantExpr * constantExpr ) = 0;
+	virtual void visit( SizeofExpr * node ) { visit( const_cast<const SizeofExpr *>(node) ); }
+	virtual void visit( const SizeofExpr * sizeofExpr ) = 0;
+	virtual void visit( AlignofExpr * node ) { visit( const_cast<const AlignofExpr *>(node) ); }
+	virtual void visit( const AlignofExpr * alignofExpr ) = 0;
+	virtual void visit( UntypedOffsetofExpr * node ) { visit( const_cast<const UntypedOffsetofExpr *>(node) ); }
+	virtual void visit( const UntypedOffsetofExpr * offsetofExpr ) = 0;
+	virtual void visit( OffsetofExpr * node ) { visit( const_cast<const OffsetofExpr *>(node) ); }
+	virtual void visit( const OffsetofExpr * offsetofExpr ) = 0;
+	virtual void visit( OffsetPackExpr * node ) { visit( const_cast<const OffsetPackExpr *>(node) ); }
+	virtual void visit( const OffsetPackExpr * offsetPackExpr ) = 0;
+	virtual void visit( AttrExpr * node ) { visit( const_cast<const AttrExpr *>(node) ); }
+	virtual void visit( const AttrExpr * attrExpr ) = 0;
+	virtual void visit( LogicalExpr * node ) { visit( const_cast<const LogicalExpr *>(node) ); }
+	virtual void visit( const LogicalExpr * logicalExpr ) = 0;
+	virtual void visit( ConditionalExpr * node ) { visit( const_cast<const ConditionalExpr *>(node) ); }
+	virtual void visit( const ConditionalExpr * conditionalExpr ) = 0;
+	virtual void visit( CommaExpr * node ) { visit( const_cast<const CommaExpr *>(node) ); }
+	virtual void visit( const CommaExpr * commaExpr ) = 0;
+	virtual void visit( TypeExpr * node ) { visit( const_cast<const TypeExpr *>(node) ); }
+	virtual void visit( const TypeExpr * typeExpr ) = 0;
+	virtual void visit( AsmExpr * node ) { visit( const_cast<const AsmExpr *>(node) ); }
+	virtual void visit( const AsmExpr * asmExpr ) = 0;
+	virtual void visit( ImplicitCopyCtorExpr * node ) { visit( const_cast<const ImplicitCopyCtorExpr *>(node) ); }
+	virtual void visit( const ImplicitCopyCtorExpr * impCpCtorExpr ) = 0;
+	virtual void visit( ConstructorExpr * node ) { visit( const_cast<const ConstructorExpr *>(node) ); }
+	virtual void visit( const ConstructorExpr *  ctorExpr ) = 0;
+	virtual void visit( CompoundLiteralExpr * node ) { visit( const_cast<const CompoundLiteralExpr *>(node) ); }
+	virtual void visit( const CompoundLiteralExpr * compLitExpr ) = 0;
+	virtual void visit( RangeExpr * node ) { visit( const_cast<const RangeExpr *>(node) ); }
+	virtual void visit( const RangeExpr * rangeExpr ) = 0;
+	virtual void visit( UntypedTupleExpr * node ) { visit( const_cast<const UntypedTupleExpr *>(node) ); }
+	virtual void visit( const UntypedTupleExpr * tupleExpr ) = 0;
+	virtual void visit( TupleExpr * node ) { visit( const_cast<const TupleExpr *>(node) ); }
+	virtual void visit( const TupleExpr * tupleExpr ) = 0;
+	virtual void visit( TupleIndexExpr * node ) { visit( const_cast<const TupleIndexExpr *>(node) ); }
+	virtual void visit( const TupleIndexExpr * tupleExpr ) = 0;
+	virtual void visit( TupleAssignExpr * node ) { visit( const_cast<const TupleAssignExpr *>(node) ); }
+	virtual void visit( const TupleAssignExpr * assignExpr ) = 0;
+	virtual void visit( StmtExpr * node ) { visit( const_cast<const StmtExpr *>(node) ); }
+	virtual void visit( const StmtExpr *  stmtExpr ) = 0;
+	virtual void visit( UniqueExpr * node ) { visit( const_cast<const UniqueExpr *>(node) ); }
+	virtual void visit( const UniqueExpr *  uniqueExpr ) = 0;
+	virtual void visit( UntypedInitExpr * node ) { visit( const_cast<const UntypedInitExpr *>(node) ); }
+	virtual void visit( const UntypedInitExpr *  initExpr ) = 0;
+	virtual void visit( InitExpr * node ) { visit( const_cast<const InitExpr *>(node) ); }
+	virtual void visit( const InitExpr *  initExpr ) = 0;
+	virtual void visit( DeletedExpr * node ) { visit( const_cast<const DeletedExpr *>(node) ); }
+	virtual void visit( const DeletedExpr * delExpr ) = 0;
+	virtual void visit( DefaultArgExpr * node ) { visit( const_cast<const DefaultArgExpr *>(node) ); }
+	virtual void visit( const DefaultArgExpr * argExpr ) = 0;
+	virtual void visit( GenericExpr * node ) { visit( const_cast<const GenericExpr *>(node) ); }
+	virtual void visit( const GenericExpr * genExpr ) = 0;
+
+	virtual void visit( VoidType * node ) { visit( const_cast<const VoidType *>(node) ); }
+	virtual void visit( const VoidType * basicType ) = 0;
+	virtual void visit( BasicType * node ) { visit( const_cast<const BasicType *>(node) ); }
+	virtual void visit( const BasicType * basicType ) = 0;
+	virtual void visit( PointerType * node ) { visit( const_cast<const PointerType *>(node) ); }
+	virtual void visit( const PointerType * pointerType ) = 0;
+	virtual void visit( ArrayType * node ) { visit( const_cast<const ArrayType *>(node) ); }
+	virtual void visit( const ArrayType * arrayType ) = 0;
+	virtual void visit( ReferenceType * node ) { visit( const_cast<const ReferenceType *>(node) ); }
+	virtual void visit( const ReferenceType * refType ) = 0;
+	virtual void visit( QualifiedType * node ) { visit( const_cast<const QualifiedType *>(node) ); }
+	virtual void visit( const QualifiedType * qualType ) = 0;
+	virtual void visit( FunctionType * node ) { visit( const_cast<const FunctionType *>(node) ); }
+	virtual void visit( const FunctionType * functionType ) = 0;
+	virtual void visit( StructInstType * node ) { visit( const_cast<const StructInstType *>(node) ); }
+	virtual void visit( const StructInstType * aggregateUseType ) = 0;
+	virtual void visit( UnionInstType * node ) { visit( const_cast<const UnionInstType *>(node) ); }
+	virtual void visit( const UnionInstType * aggregateUseType ) = 0;
+	virtual void visit( EnumInstType * node ) { visit( const_cast<const EnumInstType *>(node) ); }
+	virtual void visit( const EnumInstType * aggregateUseType ) = 0;
+	virtual void visit( TraitInstType * node ) { visit( const_cast<const TraitInstType *>(node) ); }
+	virtual void visit( const TraitInstType * aggregateUseType ) = 0;
+	virtual void visit( TypeInstType * node ) { visit( const_cast<const TypeInstType *>(node) ); }
+	virtual void visit( const TypeInstType * aggregateUseType ) = 0;
+	virtual void visit( TupleType * node ) { visit( const_cast<const TupleType *>(node) ); }
+	virtual void visit( const TupleType * tupleType ) = 0;
+	virtual void visit( TypeofType * node ) { visit( const_cast<const TypeofType *>(node) ); }
+	virtual void visit( const TypeofType * typeofType ) = 0;
+	virtual void visit( AttrType * node ) { visit( const_cast<const AttrType *>(node) ); }
+	virtual void visit( const AttrType * attrType ) = 0;
+	virtual void visit( VarArgsType * node ) { visit( const_cast<const VarArgsType *>(node) ); }
+	virtual void visit( const VarArgsType * varArgsType ) = 0;
+	virtual void visit( ZeroType * node ) { visit( const_cast<const ZeroType *>(node) ); }
+	virtual void visit( const ZeroType * zeroType ) = 0;
+	virtual void visit( OneType * node ) { visit( const_cast<const OneType *>(node) ); }
+	virtual void visit( const OneType * oneType ) = 0;
+	virtual void visit( GlobalScopeType * node ) { visit( const_cast<const GlobalScopeType *>(node) ); }
+	virtual void visit( const GlobalScopeType * globalType ) = 0;
+
+	virtual void visit( Designation * node ) { visit( const_cast<const Designation *>(node) ); }
+	virtual void visit( const Designation * designation ) = 0;
+	virtual void visit( SingleInit * node ) { visit( const_cast<const SingleInit *>(node) ); }
+	virtual void visit( const SingleInit * singleInit ) = 0;
+	virtual void visit( ListInit * node ) { visit( const_cast<const ListInit *>(node) ); }
+	virtual void visit( const ListInit * listInit ) = 0;
+	virtual void visit( ConstructorInit * node ) { visit( const_cast<const ConstructorInit *>(node) ); }
+	virtual void visit( const ConstructorInit * ctorInit ) = 0;
+
+	virtual void visit( Constant * node ) { visit( const_cast<const Constant *>(node) ); }
+	virtual void visit( const Constant * constant ) = 0;
+
+	virtual void visit( Attribute * node ) { visit( const_cast<const Attribute *>(node) ); }
+	virtual void visit( const Attribute * attribute ) = 0;
 };
 
Index: src/Tuples/Explode.h
===================================================================
--- src/Tuples/Explode.h	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/Tuples/Explode.h	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -51,5 +51,5 @@
 	template<typename OutputIterator>
 	void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env,
-			const ResolvExpr::OpenVarSet& openVars, const ResolvExpr::AssertionList& need, 
+			const ResolvExpr::OpenVarSet& openVars, const ResolvExpr::AssertionList& need,
 			const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) {
 		*out++ = ResolvExpr::Alternative{ expr, env, openVars, need, cost, cvtCost };
@@ -58,5 +58,5 @@
 	/// Append alternative to an ExplodedActual
 	static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr,
-			const ResolvExpr::TypeEnvironment&, const ResolvExpr::OpenVarSet&, 
+			const ResolvExpr::TypeEnvironment&, const ResolvExpr::OpenVarSet&,
 			const ResolvExpr::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
 		ea.exprs.emplace_back( expr );
@@ -111,5 +111,5 @@
 		} else {
 			// atomic (non-tuple) type - output a clone of the expression in a new alternative
-			append( std::forward<Output>(out), expr->clone(), alt.env, alt.openVars, alt.need,  
+			append( std::forward<Output>(out), expr->clone(), alt.env, alt.openVars, alt.need,
 				alt.cost, alt.cvtCost );
 		}
@@ -174,6 +174,6 @@
 template< typename Output >
 void explodeRecursive(
-	const ast::CastExpr * expr, const ResolvExpr::Candidate & arg,
-	const ast::SymbolTable & symtab, Output && out
+	const ast::CastExpr *, const ResolvExpr::Candidate &,
+	const ast::SymbolTable &, Output &&
 ) {
 }
@@ -240,6 +240,6 @@
 /// explode list of candidates into flattened list of candidates
 template< typename Output >
-void explode( 
-	const ResolvExpr::CandidateList & cands, const ast::SymbolTable & symtab, Output && out, 
+void explode(
+	const ResolvExpr::CandidateList & cands, const ast::SymbolTable & symtab, Output && out,
 	bool isTupleAssign = false
 ) {
Index: src/Tuples/TupleAssignment.cc
===================================================================
--- src/Tuples/TupleAssignment.cc	(revision ee6dbae804951fefcbb843a4ed8910026bd82302)
+++ src/Tuples/TupleAssignment.cc	(revision 7870799883ca946218c97fb6a189d1da90a16e8e)
@@ -67,8 +67,8 @@
 		struct Matcher {
 		  public:
-			Matcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs, 
+			Matcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
 				const ResolvExpr::AltList& rhs );
 			virtual ~Matcher() {}
-			
+
 			virtual void match( std::list< Expression * > &out ) = 0;
 			ObjectDecl * newObject( UniqueName & namer, Expression * expr );
@@ -83,5 +83,5 @@
 				for ( const ResolvExpr::Alternative& alt : alts ) { combineState( alt ); }
 			}
-			
+
 			ResolvExpr::AltList lhs, rhs;
 			TupleAssignSpotter_old &spotter;
@@ -264,5 +264,5 @@
 		}
 
-		// extract expressions from the assignment alternatives to produce a list of assignments 
+		// extract expressions from the assignment alternatives to produce a list of assignments
 		// that together form a single alternative
 		std::list< Expression *> solved_assigns;
@@ -271,10 +271,10 @@
 			matcher->combineState( alt );
 		}
-		
+
 		// xxx -- was push_front
 		currentFinder.get_alternatives().push_back( ResolvExpr::Alternative{
-			new TupleAssignExpr{ solved_assigns, matcher->tmpDecls }, matcher->compositeEnv, 
-			matcher->openVars, 
-			ResolvExpr::AssertionList( matcher->need.begin(), matcher->need.end() ), 
+			new TupleAssignExpr{ solved_assigns, matcher->tmpDecls }, matcher->compositeEnv,
+			matcher->openVars,
+			ResolvExpr::AssertionList( matcher->need.begin(), matcher->need.end() ),
 			ResolvExpr::sumCost( current ) + matcher->baseCost } );
 	}
@@ -284,5 +284,5 @@
 	: lhs(lhs), rhs(rhs), spotter(spotter),
 	  baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) {
-		combineState( lhs ); 
+		combineState( lhs );
 		combineState( rhs );
 	}
@@ -390,5 +390,5 @@
 		return dynamic_cast< const ast::TupleType * >( expr->result->stripReferences() );
 	}
-	
+
 	/// true if `expr` is of tuple type or a reference to one
 	bool refToTuple( const ast::Expr * expr ) {
@@ -421,18 +421,19 @@
 			}
 
-			Matcher( 
+			Matcher(
 				TupleAssignSpotter_new & s, const CodeLocation & loc,
 				const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )
-			: lhs( l ), rhs( r ), spotter( s ), location( loc ), 
-			  baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ), tmpDecls(), 
+			: lhs( l ), rhs( r ), spotter( s ), location( loc ),
+			  baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ), tmpDecls(),
 			  env(), open(), need() {
 				for ( auto & cand : lhs ) combineState( *cand );
 				for ( auto & cand : rhs ) combineState( *cand );
 			}
+			virtual ~Matcher() = default;
 
 			virtual std::vector< ast::ptr< ast::Expr > > match() = 0;
 
-			/// removes environments from subexpressions within statement expressions, which could 
-			/// throw off later passes like those in Box which rely on PolyMutator, and adds the 
+			/// removes environments from subexpressions within statement expressions, which could
+			/// throw off later passes like those in Box which rely on PolyMutator, and adds the
 			/// bindings to the env
 			struct EnvRemover {
@@ -455,13 +456,13 @@
 			ast::ObjectDecl * newObject( UniqueName & namer, const ast::Expr * expr ) {
 				assert( expr->result && ! expr->result->isVoid() );
-				
-				ast::ObjectDecl * ret = new ast::ObjectDecl{ 
-					location, namer.newName(), expr->result, new ast::SingleInit{ location, expr }, 
+
+				ast::ObjectDecl * ret = new ast::ObjectDecl{
+					location, namer.newName(), expr->result, new ast::SingleInit{ location, expr },
 					ast::Storage::Classes{}, ast::Linkage::Cforall };
-				
+
 				// if expression type is a reference, just need an initializer, otherwise construct
 				if ( ! expr->result.as< ast::ReferenceType >() ) {
 					// resolve ctor/dtor for the new object
-					ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit( 
+					ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit(
 							InitTweak::genCtorInit( location, ret ), spotter.crntFinder.symtab );
 					// remove environments from subexpressions of stmtExpr
@@ -474,7 +475,7 @@
 			}
 
-			ast::UntypedExpr * createFunc( 
-				const std::string & fname, const ast::ObjectDecl * left, 
-				const ast::ObjectDecl * right 
+			ast::UntypedExpr * createFunc(
+				const std::string & fname, const ast::ObjectDecl * left,
+				const ast::ObjectDecl * right
 			) {
 				assert( left );
@@ -486,8 +487,8 @@
 					args.front() = new ast::AddressExpr{ location, args.front() };
 					if ( right ) { args.back() = new ast::AddressExpr{ location, args.back() }; }
-					return new ast::UntypedExpr{ 
+					return new ast::UntypedExpr{
 						location, new ast::NameExpr{ location, "?=?" }, std::move(args) };
 				} else {
-					return new ast::UntypedExpr{ 
+					return new ast::UntypedExpr{
 						location, new ast::NameExpr{ location, fname }, std::move(args) };
 				}
@@ -498,5 +499,5 @@
 		struct MassAssignMatcher final : public Matcher {
 			MassAssignMatcher(
-				TupleAssignSpotter_new & s, const CodeLocation & loc, 
+				TupleAssignSpotter_new & s, const CodeLocation & loc,
 				const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )
 			: Matcher( s, loc, l, r ) {}
@@ -508,10 +509,10 @@
 				assert( lhs.empty() ? rhs.empty() : rhs.size() <= 1 );
 
-				ast::ptr< ast::ObjectDecl > rtmp = 
+				ast::ptr< ast::ObjectDecl > rtmp =
 					rhs.size() == 1 ? newObject( rhsNamer, rhs.front()->expr ) : nullptr;
 
 				std::vector< ast::ptr< ast::Expr > > out;
 				for ( ResolvExpr::CandidateRef & lhsCand : lhs ) {
-					// create a temporary object for each value in the LHS and create a call 
+					// create a temporary object for each value in the LHS and create a call
 					// involving the RHS
 					ast::ptr< ast::ObjectDecl > ltmp = newObject( lhsNamer, lhsCand->expr );
@@ -528,5 +529,5 @@
 		struct MultipleAssignMatcher final : public Matcher {
 			MultipleAssignMatcher(
-				TupleAssignSpotter_new & s, const CodeLocation & loc, 
+				TupleAssignSpotter_new & s, const CodeLocation & loc,
 				const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )
 			: Matcher( s, loc, l, r ) {}
@@ -538,5 +539,5 @@
 				if ( lhs.size() != rhs.size() ) return {};
 
-				// produce a new temporary object for each value in the LHS and RHS and pairwise 
+				// produce a new temporary object for each value in the LHS and RHS and pairwise
 				// create the calls
 				std::vector< ast::ptr< ast::ObjectDecl > > ltmp, rtmp;
@@ -547,5 +548,5 @@
 					ResolvExpr::CandidateRef & rhsCand = rhs[i];
 
-					// convert RHS to LHS type minus one reference -- important for case where LHS 
+					// convert RHS to LHS type minus one reference -- important for case where LHS
 					// is && and RHS is lvalue
 					auto lhsType = lhsCand->expr->result.strict_as< ast::ReferenceType >();
@@ -557,5 +558,5 @@
 					rtmp.emplace_back( std::move( robj ) );
 
-					// resolve the cast expression so that rhsCand return type is bound by the cast 
+					// resolve the cast expression so that rhsCand return type is bound by the cast
 					// type as needed, and transfer the resulting environment
 					ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, env };
@@ -564,8 +565,8 @@
 					env = std::move( finder.candidates.front()->env );
 				}
-				
+
 				splice( tmpDecls, ltmp );
 				splice( tmpDecls, rtmp );
-				
+
 				return out;
 			}
@@ -575,12 +576,12 @@
 		std::string fname;
 		std::unique_ptr< Matcher > matcher;
-	
+
 	public:
-		TupleAssignSpotter_new( ResolvExpr::CandidateFinder & f ) 
+		TupleAssignSpotter_new( ResolvExpr::CandidateFinder & f )
 		: crntFinder( f ), fname(), matcher() {}
 
 		// find left- and right-hand-sides for mass or multiple assignment
-		void spot( 
-			const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args 
+		void spot(
+			const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args
 		) {
 			if ( auto op = expr->func.as< ast::NameExpr >() ) {
@@ -599,8 +600,8 @@
 					if ( ! refToTuple( lhsCand->expr ) ) continue;
 
-					// explode is aware of casts - ensure every LHS is sent into explode with a 
+					// explode is aware of casts - ensure every LHS is sent into explode with a
 					// reference cast
 					if ( ! lhsCand->expr.as< ast::CastExpr >() ) {
-						lhsCand->expr = new ast::CastExpr{ 
+						lhsCand->expr = new ast::CastExpr{
 							lhsCand->expr, new ast::ReferenceType{ lhsCand->expr->result } };
 					}
@@ -610,5 +611,5 @@
 					explode( *lhsCand, crntFinder.symtab, back_inserter(lhs), true );
 					for ( ResolvExpr::CandidateRef & cand : lhs ) {
-						// each LHS value must be a reference - some come in with a cast, if not 
+						// each LHS value must be a reference - some come in with a cast, if not
 						// just cast to reference here
 						if ( ! cand->expr->result.as< ast::ReferenceType >() ) {
@@ -629,10 +630,10 @@
 								// multiple assignment
 								explode( *rhsCand, crntFinder.symtab, back_inserter(rhs), true );
-								matcher.reset( 
+								matcher.reset(
 									new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
 							} else {
 								// mass assignment
 								rhs.emplace_back( rhsCand );
-								matcher.reset( 
+								matcher.reset(
 									new MassAssignMatcher{ *this, expr->location, lhs, rhs } );
 							}
@@ -642,5 +643,5 @@
 						// expand all possible RHS possibilities
 						std::vector< ResolvExpr::CandidateList > rhsCands;
-						combos( 
+						combos(
 							std::next( args.begin(), 1 ), args.end(), back_inserter( rhsCands ) );
 						for ( const ResolvExpr::CandidateList & rhsCand : rhsCands ) {
@@ -648,5 +649,5 @@
 							ResolvExpr::CandidateList rhs;
 							explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true );
-							matcher.reset( 
+							matcher.reset(
 								new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
 							match();
@@ -663,6 +664,6 @@
 
 			if ( ! ( matcher->lhs.empty() && matcher->rhs.empty() ) ) {
-				// if both LHS and RHS are empty than this is the empty tuple case, wherein it's 
-				// okay for newAssigns to be empty. Otherwise, return early so that no new 
+				// if both LHS and RHS are empty than this is the empty tuple case, wherein it's
+				// okay for newAssigns to be empty. Otherwise, return early so that no new
 				// candidates are generated
 				if ( newAssigns.empty() ) return;
@@ -692,5 +693,5 @@
 			}
 
-			// extract expressions from the assignment candidates to produce a list of assignments 
+			// extract expressions from the assignment candidates to produce a list of assignments
 			// that together form a sigle candidate
 			std::vector< ast::ptr< ast::Expr > > solved;
@@ -701,7 +702,7 @@
 
 			crntFinder.candidates.emplace_back( std::make_shared< ResolvExpr::Candidate >(
-				new ast::TupleAssignExpr{ 
-					matcher->location, std::move( solved ), std::move( matcher->tmpDecls ) }, 
-				std::move( matcher->env ), std::move( matcher->open ), std::move( matcher->need ), 
+				new ast::TupleAssignExpr{
+					matcher->location, std::move( solved ), std::move( matcher->tmpDecls ) },
+				std::move( matcher->env ), std::move( matcher->open ), std::move( matcher->need ),
 				ResolvExpr::sumCost( crnt ) + matcher->baseCost ) );
 		}
@@ -709,6 +710,6 @@
 } // anonymous namespace
 
-void handleTupleAssignment( 
-	ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign, 
+void handleTupleAssignment(
+	ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,
 	std::vector< ResolvExpr::CandidateFinder > & args
 ) {
