Index: src/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision c1ed2eed49812bcfa4987e47ccc9eda7d2fbf8c0)
+++ src/Common/PassVisitor.h	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
@@ -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 c1ed2eed49812bcfa4987e47ccc9eda7d2fbf8c0)
+++ src/Common/PassVisitor.impl.h	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
@@ -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 c1ed2eed49812bcfa4987e47ccc9eda7d2fbf8c0)
+++ src/Common/PassVisitor.proto.h	(revision 8fd52e90372722cd58a940aabae4889d3072d17a)
@@ -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>
