Index: src/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision 6065b3aad7ca045ec48fc6103d1c55f0b5fb74b0)
+++ src/Common/PassVisitor.h	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
@@ -1,40 +1,17 @@
 #pragma once
 
+#include <stack>
+
+#include "SynTree/Mutator.h"
 #include "SynTree/Visitor.h"
 
-//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-//Deep magic (a.k.a template meta programming) to make the templated visitor work
-//Basically the goal is to make 2 previsit_impl
-// 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of 
-//     'pass.previsit( node )' that compiles will be used for that node for that type
-//     This requires that this option only compile for passes that actually define an appropriate visit.
-//     SFINAE will make sure the compilation errors in this function don't halt the build.
-//     See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE
-// 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing.
-//     This is needed only to eliminate the need for passes to specify any kind of handlers.
-//     The second implementation only works because it has a lower priority. This is due to the bogus last parameter.
-//     The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0
-//     the first implementation takes priority in regards to overloading.
-//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-template<typename pass_type, typename node_type>
-static inline auto previsit_impl( pass_type& pass, 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, node_type * node, __attribute__((unused)) long unused ) {
-	//Do nothing
-}
-
-
-template<typename pass_type, typename node_type>
-static inline auto postvisit_impl( pass_type& pass, node_type * node, __attribute__((unused)) int unused ) ->decltype( pass.postvisit( node ), void() ) {
-	pass.postvisit( node );
-}
-
-template<typename pass_type, typename node_type>
-static inline auto postvisit_impl( __attribute__((unused)) pass_type& pass, node_type * node, __attribute__((unused)) long unused ) {
-	//Do nothing
-}
+#include "SynTree/Initializer.h"
+#include "SynTree/Statement.h"
+#include "SynTree/Type.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Constant.h"
+
+#include "PassVisitor.proto.h"
 
 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -44,18 +21,16 @@
 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 template< typename pass_type >
-class PassVisitor final : public Visitor {
+class PassVisitor final : public Visitor, public Mutator {
 public:
 	PassVisitor() = default;
 
 	template< typename... Args >
-	PassVisitor(Args &&... args) 
+	PassVisitor(Args &&... args)
 		: pass( std::forward<Args>( args )... )
 	{}
 
 	virtual ~PassVisitor() = default;
-private:
+
 	pass_type pass;
-
-public:
 
 	virtual void visit( ObjectDecl *objectDecl ) override final;
@@ -145,18 +120,115 @@
 	virtual void visit( Constant *constant ) override final;
 
+	virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ) override final;
+	virtual DeclarationWithType* mutate( FunctionDecl *functionDecl ) override final;
+	virtual Declaration* mutate( StructDecl *aggregateDecl ) override final;
+	virtual Declaration* mutate( UnionDecl *aggregateDecl ) override final;
+	virtual Declaration* mutate( EnumDecl *aggregateDecl ) override final;
+	virtual Declaration* mutate( TraitDecl *aggregateDecl ) override final;
+	virtual TypeDecl* mutate( TypeDecl *typeDecl ) override final;
+	virtual Declaration* mutate( TypedefDecl *typeDecl ) override final;
+	virtual AsmDecl* mutate( AsmDecl *asmDecl ) override final;
+
+	virtual CompoundStmt* mutate( CompoundStmt *compoundStmt ) override final;
+	virtual Statement* mutate( ExprStmt *exprStmt ) override final;
+	virtual Statement* mutate( AsmStmt *asmStmt ) override final;
+	virtual Statement* mutate( IfStmt *ifStmt ) override final;
+	virtual Statement* mutate( WhileStmt *whileStmt ) override final;
+	virtual Statement* mutate( ForStmt *forStmt ) override final;
+	virtual Statement* mutate( SwitchStmt *switchStmt ) override final;
+	virtual Statement* mutate( CaseStmt *caseStmt ) override final;
+	virtual Statement* mutate( BranchStmt *branchStmt ) override final;
+	virtual Statement* mutate( ReturnStmt *returnStmt ) override final;
+	virtual Statement* mutate( TryStmt *returnStmt ) override final;
+	virtual Statement* mutate( CatchStmt *catchStmt ) override final;
+	virtual Statement* mutate( FinallyStmt *catchStmt ) override final;
+	virtual NullStmt* mutate( NullStmt *nullStmt ) override final;
+	virtual Statement* mutate( DeclStmt *declStmt ) override final;
+	virtual Statement* mutate( ImplicitCtorDtorStmt *impCtorDtorStmt ) override final;
+
+	virtual Expression* mutate( ApplicationExpr *applicationExpr ) override final;
+	virtual Expression* mutate( UntypedExpr *untypedExpr ) override final;
+	virtual Expression* mutate( NameExpr *nameExpr ) override final;
+	virtual Expression* mutate( AddressExpr *castExpr ) override final;
+	virtual Expression* mutate( LabelAddressExpr *labAddressExpr ) override final;
+	virtual Expression* mutate( CastExpr *castExpr ) override final;
+	virtual Expression* mutate( UntypedMemberExpr *memberExpr ) override final;
+	virtual Expression* mutate( MemberExpr *memberExpr ) override final;
+	virtual Expression* mutate( VariableExpr *variableExpr ) override final;
+	virtual Expression* mutate( ConstantExpr *constantExpr ) override final;
+	virtual Expression* mutate( SizeofExpr *sizeofExpr ) override final;
+	virtual Expression* mutate( AlignofExpr *alignofExpr ) override final;
+	virtual Expression* mutate( UntypedOffsetofExpr *offsetofExpr ) override final;
+	virtual Expression* mutate( OffsetofExpr *offsetofExpr ) override final;
+	virtual Expression* mutate( OffsetPackExpr *offsetPackExpr ) override final;
+	virtual Expression* mutate( AttrExpr *attrExpr ) override final;
+	virtual Expression* mutate( LogicalExpr *logicalExpr ) override final;
+	virtual Expression* mutate( ConditionalExpr *conditionalExpr ) override final;
+	virtual Expression* mutate( CommaExpr *commaExpr ) override final;
+	virtual Expression* mutate( TypeExpr *typeExpr ) override final;
+	virtual Expression* mutate( AsmExpr *asmExpr ) override final;
+	virtual Expression* mutate( ImplicitCopyCtorExpr *impCpCtorExpr ) override final;
+	virtual Expression* mutate( ConstructorExpr *ctorExpr ) override final;
+	virtual Expression* mutate( CompoundLiteralExpr *compLitExpr ) override final;
+	virtual Expression* mutate( UntypedValofExpr *valofExpr ) override final;
+	virtual Expression* mutate( RangeExpr *rangeExpr ) override final;
+	virtual Expression* mutate( UntypedTupleExpr *tupleExpr ) override final;
+	virtual Expression* mutate( TupleExpr *tupleExpr ) override final;
+	virtual Expression* mutate( TupleIndexExpr *tupleExpr ) override final;
+	virtual Expression* mutate( MemberTupleExpr *tupleExpr ) override final;
+	virtual Expression* mutate( TupleAssignExpr *assignExpr ) override final;
+	virtual Expression* mutate( StmtExpr * stmtExpr ) override final;
+	virtual Expression* mutate( UniqueExpr * uniqueExpr ) override final;
+
+	virtual Type* mutate( VoidType *basicType ) override final;
+	virtual Type* mutate( BasicType *basicType ) override final;
+	virtual Type* mutate( PointerType *pointerType ) override final;
+	virtual Type* mutate( ArrayType *arrayType ) override final;
+	virtual Type* mutate( FunctionType *functionType ) override final;
+	virtual Type* mutate( StructInstType *aggregateUseType ) override final;
+	virtual Type* mutate( UnionInstType *aggregateUseType ) override final;
+	virtual Type* mutate( EnumInstType *aggregateUseType ) override final;
+	virtual Type* mutate( TraitInstType *aggregateUseType ) override final;
+	virtual Type* mutate( TypeInstType *aggregateUseType ) override final;
+	virtual Type* mutate( TupleType *tupleType ) override final;
+	virtual Type* mutate( TypeofType *typeofType ) override final;
+	virtual Type* mutate( AttrType *attrType ) override final;
+	virtual Type* mutate( VarArgsType *varArgsType ) override final;
+	virtual Type* mutate( ZeroType *zeroType ) override final;
+	virtual Type* mutate( OneType *oneType ) override final;
+
+	virtual Initializer* mutate( SingleInit *singleInit ) override final;
+	virtual Initializer* mutate( ListInit *listInit ) override final;
+	virtual Initializer* mutate( ConstructorInit *ctorInit ) override final;
+
+	virtual Subrange *mutate( Subrange *subrange ) override final;
+
+	virtual Constant *mutate( Constant *constant ) override final;
+
 private:
-	template<typename node_type> 
-	auto call_previsit ( node_type * node ) 
-		-> decltype( previsit_impl ( pass, node, 0 ), void() ) 
-	{ 
-		previsit_impl ( pass, node, 0 ); 
-	}
-
-	template<typename node_type> 
-	auto call_postvisit( node_type * node )
-		-> decltype( postvisit_impl( pass, node, 0 ), void() ) 
-	{ 
-		postvisit_impl( pass, node, 0 ); 
-	}
+	template<typename node_type> void call_previsit ( 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_premutate ( node_type * node ) { premutate_impl( pass, node, 0 ); }
+	template<typename return_type, typename node_type> return_type call_postmutate ( node_type * node ) { return postmutate_impl<return_type>( pass, node, 0 ); }
+
+	void call_beginScope() { begin_scope_impl( pass, 0 ); }
+	void call_endScope  () { end_scope_impl  ( pass, 0 ); }
+
+	void set_env( TypeSubstitution * env ) { set_env_impl( pass, env, 0); }
+
+	void visitStatementList( std::list< Statement* > &statements );
+	void mutateStatementList( std::list< Statement* > &statements );
+
+	Statement * visitStatement( Statement * stmt );
+	Statement * mutateStatement( Statement * stmt );
+
+	void visitExpression( Expression * expr );
+	Expression * mutateExpression( Expression * expr );
+
+
+	TypeSubstitution ** 		get_env_ptr    () { return env_impl             ( pass, 0); }
+	std::list< Statement* > * 	get_beforeStmts() { return stmtsToAddBefore_impl( pass, 0); }
+	std::list< Statement* > * 	get_afterStmts () { return stmtsToAddAfter_impl ( pass, 0); }
 };
 
Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision 6065b3aad7ca045ec48fc6103d1c55f0b5fb74b0)
+++ src/Common/PassVisitor.impl.h	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
@@ -1,3 +1,11 @@
 #pragma once
+
+#define MUTATE_START( node )  \
+	call_premutate( node ); \
+
+
+#define MUTATE_END( type, node )                \
+	return call_postmutate< type * >( node ); \
+
 
 #define VISIT_BODY( node )    \
@@ -7,396 +15,992 @@
 
 
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( ObjectDecl * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( FunctionDecl * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( StructDecl * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( UnionDecl * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( EnumDecl * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( TraitDecl * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( TypeDecl * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( TypedefDecl * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( AsmDecl * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( CompoundStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( ExprStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( AsmStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( IfStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( WhileStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( ForStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( SwitchStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( CaseStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( BranchStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( ReturnStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( TryStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( CatchStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( FinallyStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( NullStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( DeclStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( ImplicitCtorDtorStmt * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( ApplicationExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( UntypedExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( NameExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( CastExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( AddressExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( LabelAddressExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( UntypedMemberExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( MemberExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( VariableExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( ConstantExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( SizeofExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( AlignofExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( UntypedOffsetofExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( OffsetofExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( OffsetPackExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( AttrExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( LogicalExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( ConditionalExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( CommaExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( TypeExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( AsmExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( ImplicitCopyCtorExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( ConstructorExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( CompoundLiteralExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( UntypedValofExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( RangeExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( UntypedTupleExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( TupleExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( TupleIndexExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( MemberTupleExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( TupleAssignExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( StmtExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( UniqueExpr * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( VoidType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( BasicType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( PointerType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( ArrayType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( FunctionType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( StructInstType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( UnionInstType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( EnumInstType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( TraitInstType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( TypeInstType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( TupleType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( TypeofType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( AttrType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( VarArgsType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( ZeroType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( OneType * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( SingleInit * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( ListInit * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( ConstructorInit * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( Subrange * node ) { 
-	VISIT_BODY( node ); 
-}
-
-template< typename pass_type >
-void PassVisitor< pass_type>::visit( Constant * node ) { 
-	VISIT_BODY( node ); 
-}
+#define MUTATE_BODY( type, node ) \
+	MUTATE_START( node );       \
+	Mutator::mutate( node );    \
+	MUTATE_END( type, node );   \
+
+
+
+template<typename T>
+static inline bool empty( T * ptr ) {
+	return !ptr || ptr->empty();
+}
+
+typedef std::list< Statement * > StmtList_t;
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visitStatementList( std::list< Statement * > & statements ) {
+	SemanticError errors;
+
+	StmtList_t* beforeStmts = get_beforeStmts();
+	StmtList_t* afterStmts  = get_afterStmts();
+
+	for ( std::list< Statement* >::iterator i = statements.begin(); i != statements.end(); ++i ) {
+		if ( !empty( afterStmts ) ) { statements.splice( i, *afterStmts ); }
+		try {
+			*i = (*i)->accept( *this );
+		} catch ( SemanticError &e ) {
+			errors.append( e );
+		}
+		if ( !empty( beforeStmts ) ) { statements.splice( i, *beforeStmts ); }
+	}
+
+	if ( !empty( afterStmts ) ) { statements.splice( statements.end(), *afterStmts ); }
+	if ( !errors.isEmpty() ) { throw errors; }
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::mutateStatementList( std::list< Statement * > & statements ) {
+	SemanticError errors;
+
+	StmtList_t* beforeStmts = get_beforeStmts();
+	StmtList_t* afterStmts  = get_afterStmts();
+
+	for ( std::list< Statement* >::iterator i = statements.begin(); i != statements.end(); ++i ) {
+		if ( !empty( afterStmts ) ) { statements.splice( i, *afterStmts ); }
+		try {
+			*i = (*i)->acceptMutator( *this );
+		} catch ( SemanticError &e ) {
+			errors.append( e );
+		}
+		if ( !empty( beforeStmts ) ) { statements.splice( i, *beforeStmts ); }
+	}
+
+	if ( !empty( afterStmts ) ) { statements.splice( statements.end(), *afterStmts ); }
+	if ( !errors.isEmpty() ) { throw errors; }
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::visitStatement( Statement * stmt ) {
+	// don't want statements from outer CompoundStmts to be added to this CompoundStmt
+	ValueGuardPtr< TypeSubstitution * >      oldEnv        ( get_env_ptr() );
+	ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
+	ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
+
+	Statement *newStmt = maybeVisit( stmt, *this );
+
+	StmtList_t* beforeStmts = get_beforeStmts();
+	StmtList_t* afterStmts  = get_afterStmts();
+
+	if( empty(beforeStmts) && empty(afterStmts) ) { return newStmt; }
+
+	CompoundStmt *compound = new CompoundStmt( noLabels );
+	if( !empty(beforeStmts) ) { compound->get_kids().splice( compound->get_kids().end(), *beforeStmts ); }
+	compound->get_kids().push_back( newStmt );
+	if( !empty(afterStmts) ) { compound->get_kids().splice( compound->get_kids().end(), *afterStmts ); }
+	return compound;
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutateStatement( Statement * stmt ) {
+	// don't want statements from outer CompoundStmts to be added to this CompoundStmt
+	ValueGuardPtr< TypeSubstitution * >      oldEnv        ( get_env_ptr() );
+	ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
+	ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
+
+	Statement *newStmt = maybeMutate( stmt, *this );
+
+	StmtList_t* beforeStmts = get_beforeStmts();
+	StmtList_t* afterStmts  = get_afterStmts();
+
+	if( empty(beforeStmts) && empty(afterStmts) ) { return newStmt; }
+
+	CompoundStmt *compound = new CompoundStmt( noLabels );
+	if( !empty(beforeStmts) ) { compound->get_kids().splice( compound->get_kids().end(), *beforeStmts ); }
+	compound->get_kids().push_back( newStmt );
+	if( !empty(afterStmts) ) { compound->get_kids().splice( compound->get_kids().end(), *afterStmts ); }
+	return compound;
+}
+
+
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visitExpression( Expression * expr ) {
+	if( !expr ) return;
+
+	auto env_ptr = get_env_ptr();
+	if ( env_ptr && expr->get_env() ) {
+		*env_ptr = expr->get_env();
+	}
+	// xxx - should env be cloned (or moved) onto the result of the mutate?
+	expr->accept( *this );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutateExpression( Expression * expr ) {
+	if( !expr ) return nullptr;
+
+	auto env_ptr = get_env_ptr();
+	if ( env_ptr && expr->get_env() ) {
+		*env_ptr = expr->get_env();
+	}
+	// xxx - should env be cloned (or moved) onto the result of the mutate?
+	return expr->acceptMutator( *this );
+}
+
+
+//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ObjectDecl * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( FunctionDecl * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( StructDecl * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( UnionDecl * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( EnumDecl * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( TraitDecl * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( TypeDecl * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( TypedefDecl * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( AsmDecl * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( CompoundStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+CompoundStmt * PassVisitor< pass_type >::mutate( CompoundStmt * node ) {
+	MUTATE_START( node );
+	call_beginScope();
+
+	mutateStatementList( node->get_kids() );
+
+	call_endScope();
+	MUTATE_END( CompoundStmt, node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ExprStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( ExprStmt * node ) {
+	MUTATE_START( node );
+
+	node->set_expr( mutateExpression( node->get_expr() ) );
+
+	MUTATE_END( Statement, node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( AsmStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( IfStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( IfStmt * node ) {
+	MUTATE_START( node ); 
+
+	node->set_condition( mutateExpression( node->get_condition() ) );
+	node->set_thenPart ( mutateStatement ( node->get_thenPart()  ) );
+	node->set_elsePart ( mutateStatement ( node->get_elsePart()  ) );
+
+	MUTATE_END( Statement, node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( WhileStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( WhileStmt * node ) {
+	MUTATE_START( node ); 
+
+	node->set_condition( mutateExpression( node->get_condition() ) );
+	node->set_body( mutateStatement( node->get_body() ) );
+
+	MUTATE_END( Statement, node );
+}
+
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ForStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( ForStmt * node ) {
+	MUTATE_START( node ); 
+
+	mutateAll( node->get_initialization(), *this );
+	node->set_condition(  mutateExpression( node->get_condition() ) );
+	node->set_increment(  mutateExpression( node->get_increment() ) );
+	node->set_body(  mutateStatement( node->get_body() ) );
+
+	MUTATE_END( Statement, node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( SwitchStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( SwitchStmt * node ) {
+	MUTATE_START( node ); 
+	
+	node->set_condition( mutateExpression( node->get_condition() ) );
+	mutateStatementList( node->get_statements() );
+	
+	MUTATE_END( Statement, node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( CaseStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( CaseStmt * node ) {
+	MUTATE_START( node ); 
+	
+	node->set_condition(  mutateExpression( node->get_condition() ) );
+	mutateStatementList( node->get_statements() );
+	
+	MUTATE_END( Statement, node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( BranchStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ReturnStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( ReturnStmt * node ) {
+	MUTATE_START( node );
+
+	node->set_expr( mutateExpression( node->get_expr() ) );
+
+	MUTATE_END( Statement, node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( TryStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( TryStmt * node ) {
+	MUTATE_START( node );
+
+	node->set_block(  maybeMutate( node->get_block(), *this ) );
+	mutateAll( node->get_catchers(), *this );
+	
+	MUTATE_END( Statement, node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( CatchStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( CatchStmt * node ) {
+	MUTATE_START( node );
+	
+	node->set_body(  mutateStatement( node->get_body() ) );
+	node->set_decl(  maybeMutate( node->get_decl(), *this ) );
+	
+	MUTATE_END( Statement, node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( FinallyStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( NullStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( DeclStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ImplicitCtorDtorStmt * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ApplicationExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( UntypedExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( UntypedExpr * node ) {
+	MUTATE_START( node );
+
+	for ( auto& expr : node->get_args() ) {
+		expr = mutateExpression( expr );
+	}
+
+	MUTATE_END( Expression, node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( NameExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( CastExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( AddressExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( LabelAddressExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( UntypedMemberExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( MemberExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( VariableExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ConstantExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( SizeofExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( AlignofExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( UntypedOffsetofExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( OffsetofExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( OffsetPackExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( AttrExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( LogicalExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ConditionalExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( CommaExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( TypeExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( AsmExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ImplicitCopyCtorExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ConstructorExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( CompoundLiteralExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( UntypedValofExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( RangeExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( UntypedTupleExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( TupleExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( TupleIndexExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( MemberTupleExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( TupleAssignExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( StmtExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( StmtExpr * node ) {
+	MUTATE_START( node );
+	
+	// don't want statements from outer CompoundStmts to be added to this StmtExpr
+	ValueGuardPtr< TypeSubstitution * >      oldEnv        ( get_env_ptr() );
+	ValueGuardPtr< std::list< Statement* > > oldBeforeStmts( get_beforeStmts() );
+	ValueGuardPtr< std::list< Statement* > > oldAfterStmts ( get_afterStmts () );
+
+	Mutator::mutate( node );
+
+	MUTATE_END( Expression, node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( UniqueExpr * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( VoidType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( BasicType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( PointerType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ArrayType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( FunctionType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( StructInstType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( UnionInstType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( EnumInstType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( TraitInstType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( TypeInstType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( TupleType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( TypeofType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( AttrType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( VarArgsType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ZeroType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( OneType * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( SingleInit * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+Initializer * PassVisitor< pass_type >::mutate( SingleInit * node ) {
+	MUTATE_START( node );
+
+	node->set_value( mutateExpression( node->get_value() ) );
+
+	MUTATE_END( Initializer, node );
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ListInit * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( ConstructorInit * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( Subrange * node ) {
+	VISIT_BODY( node ); 
+}
+
+template< typename pass_type >
+void PassVisitor< pass_type >::visit( Constant * node ) {
+	VISIT_BODY( node ); 
+}
+
+//---------------------------------------------------------------------------------------------------------------
+
+template< typename pass_type >
+DeclarationWithType * PassVisitor< pass_type >::mutate( ObjectDecl * node ) {
+	MUTATE_BODY( DeclarationWithType, node );
+}
+
+template< typename pass_type >
+DeclarationWithType * PassVisitor< pass_type >::mutate( FunctionDecl * node ) {
+	MUTATE_BODY( DeclarationWithType, node );
+}
+
+template< typename pass_type >
+Declaration * PassVisitor< pass_type >::mutate( StructDecl * node ) {
+	MUTATE_BODY( Declaration, node );
+}
+
+template< typename pass_type >
+Declaration * PassVisitor< pass_type >::mutate( UnionDecl * node ) {
+	MUTATE_BODY( Declaration, node );
+}
+
+template< typename pass_type >
+Declaration * PassVisitor< pass_type >::mutate( EnumDecl * node ) {
+	MUTATE_BODY( Declaration, node );
+}
+
+template< typename pass_type >
+Declaration * PassVisitor< pass_type >::mutate( TraitDecl * node ) {
+	MUTATE_BODY( Declaration, node );
+}
+
+template< typename pass_type >
+TypeDecl * PassVisitor< pass_type >::mutate( TypeDecl * node ) {
+	MUTATE_BODY( TypeDecl, node );
+}
+
+template< typename pass_type >
+Declaration * PassVisitor< pass_type >::mutate( TypedefDecl * node ) {
+	MUTATE_BODY( Declaration, node );
+}
+
+template< typename pass_type >
+AsmDecl * PassVisitor< pass_type >::mutate( AsmDecl * node ) {
+	MUTATE_BODY( AsmDecl, node );
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( AsmStmt * node ) {
+	MUTATE_BODY( Statement, node );
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( BranchStmt * node ) {
+	MUTATE_BODY( Statement, node );
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( FinallyStmt * node ) {
+	MUTATE_BODY( Statement, node );
+}
+
+template< typename pass_type >
+NullStmt * PassVisitor< pass_type >::mutate( NullStmt * node ) {
+	MUTATE_BODY( NullStmt, node );
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( DeclStmt * node ) {
+	MUTATE_BODY( Statement, node );
+}
+
+template< typename pass_type >
+Statement * PassVisitor< pass_type >::mutate( ImplicitCtorDtorStmt * node ) {
+	MUTATE_BODY( Statement, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( ApplicationExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( NameExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( AddressExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( LabelAddressExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( CastExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( UntypedMemberExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( MemberExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( VariableExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( ConstantExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( SizeofExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( AlignofExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( UntypedOffsetofExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( OffsetofExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( OffsetPackExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( AttrExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( LogicalExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( ConditionalExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( CommaExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( TypeExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( AsmExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( ImplicitCopyCtorExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( ConstructorExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( CompoundLiteralExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( UntypedValofExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( RangeExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( UntypedTupleExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( TupleExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( TupleIndexExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( MemberTupleExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( TupleAssignExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Expression * PassVisitor< pass_type >::mutate( UniqueExpr * node ) {
+	MUTATE_BODY( Expression, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( VoidType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( BasicType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( PointerType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( ArrayType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( FunctionType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( StructInstType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( UnionInstType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( EnumInstType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( TraitInstType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( TypeInstType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( TupleType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( TypeofType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( AttrType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( VarArgsType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( ZeroType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Type * PassVisitor< pass_type >::mutate( OneType * node ) {
+	MUTATE_BODY( Type, node );
+}
+
+template< typename pass_type >
+Initializer * PassVisitor< pass_type >::mutate( ListInit * node ) {
+	MUTATE_BODY( Initializer, node );
+}
+
+template< typename pass_type >
+Initializer * PassVisitor< pass_type >::mutate( ConstructorInit * node ) {
+	MUTATE_BODY( Initializer, node );
+}
+
+template< typename pass_type >
+Subrange * PassVisitor< pass_type >::mutate( Subrange * node  )  {
+	MUTATE_BODY( Subrange, node );
+}
+
+template< typename pass_type >
+Constant * PassVisitor< pass_type >::mutate( Constant * node  )  {
+	MUTATE_BODY( Constant, node );
+}
Index: src/Common/PassVisitor.proto.h
===================================================================
--- src/Common/PassVisitor.proto.h	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
+++ src/Common/PassVisitor.proto.h	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
@@ -0,0 +1,82 @@
+#pragma once
+
+//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+// Deep magic (a.k.a template meta programming) to make the templated visitor work
+// Basically the goal is to make 2 previsit_impl
+// 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of 
+//     'pass.previsit( node )' that compiles will be used for that node for that type
+//     This requires that this option only compile for passes that actually define an appropriate visit.
+//     SFINAE will make sure the compilation errors in this function don't halt the build.
+//     See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE
+// 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing.
+//     This is needed only to eliminate the need for passes to specify any kind of handlers.
+//     The second implementation only works because it has a lower priority. This is due to the bogus last parameter.
+//     The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0
+//     the first implementation takes priority in regards to overloading.
+// Mutator functions work along the same principal
+//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+// Visit
+template<typename pass_type, typename node_type>
+static inline auto previsit_impl( pass_type& pass, 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, node_type * node, __attribute__((unused)) long unused ) {}
+
+
+template<typename pass_type, typename node_type>
+static inline auto postvisit_impl( pass_type& pass, 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, node_type * node, __attribute__((unused)) long unused ) {}
+
+// Mutate
+template<typename pass_type, typename node_type>
+static inline auto premutate_impl( pass_type& pass, node_type * node, __attribute__((unused)) int unused ) ->decltype( pass.premutate( node ), void() ) {
+	return pass.premutate( node );
+}
+
+template<typename pass_type, typename node_type>
+static inline void premutate_impl( __attribute__((unused)) pass_type& pass, node_type * node, __attribute__((unused)) long unused ) {}
+
+
+template<typename return_type, typename pass_type, typename node_type>
+static inline auto postmutate_impl( pass_type& pass, node_type * node, __attribute__((unused)) int unused ) ->decltype( pass.postmutate( node ) ) {
+	return pass.postmutate( node );
+}
+
+template<typename return_type, typename pass_type, typename node_type>
+static inline return_type postmutate_impl( __attribute__((unused)) pass_type& pass, node_type * node, __attribute__((unused)) long unused ) { return node; }
+
+// Begin/End scope
+template<typename pass_type>
+static inline auto begin_scope_impl( pass_type& pass, __attribute__((unused)) int unused ) ->decltype( pass.beginScope(), void() ) {
+	pass.beginScope();
+}
+
+template<typename pass_type>
+static inline void begin_scope_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) long unused ) {}
+
+
+template<typename pass_type>
+static inline auto end_scope_impl( pass_type& pass, __attribute__((unused)) int unused ) ->decltype( pass.endScope(), void() ) {
+	pass.endScope();
+}
+
+template<typename pass_type>
+static inline void end_scope_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) long unused ) {}
+
+// Fields
+#define FIELD_PTR( type, name )                                                                                                                  \
+template<typename pass_type>                                                                                                                     \
+static inline auto name##_impl( pass_type& pass, __attribute__((unused)) int unused ) ->decltype( &pass.name ) { return &pass.name; }          \
+                                                                                                                                                 \
+template<typename pass_type>                                                                                                                     \
+static inline type * name##_impl( __attribute__((unused)) pass_type& pass, __attribute__((unused)) long unused ) { return nullptr;}    \
+
+FIELD_PTR( TypeSubstitution *, env )
+FIELD_PTR( std::list< Statement* >, stmtsToAddBefore )
+FIELD_PTR( std::list< Statement* >, stmtsToAddAfter  )
Index: src/Common/utility.h
===================================================================
--- src/Common/utility.h	(revision 6065b3aad7ca045ec48fc6103d1c55f0b5fb74b0)
+++ src/Common/utility.h	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
@@ -244,4 +244,24 @@
 	ValueGuard(T& inRef) : old(inRef), ref(inRef) {}
 	~ValueGuard() { ref = old; }
+};
+
+template< typename T >
+struct ValueGuardPtr {
+	T old;
+	T* ref;
+
+	ValueGuardPtr(T * inRef) : old( inRef ? *inRef : T() ), ref(inRef) {}
+	~ValueGuardPtr() { if( ref ) *ref = old; }
+};
+
+template< typename T >
+struct ValueGuardPtr< std::list< T > > {
+	std::list< T > old;
+	std::list< T >* ref;
+
+	ValueGuardPtr( std::list< T > * inRef) : old(), ref(inRef) {
+		if( ref ) { swap( *ref, old ); }
+	}
+	~ValueGuardPtr() { if( ref ) { swap( *ref, old ); } }
 };
 
Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 6065b3aad7ca045ec48fc6103d1c55f0b5fb74b0)
+++ src/InitTweak/FixInit.cc	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
@@ -20,23 +20,25 @@
 #include <unordered_map>
 #include <unordered_set>
+
 #include "InitTweak.h"
 #include "GenInit.h"
 #include "FixInit.h"
 #include "FixGlobalInit.h"
+#include "CodeGen/GenType.h"  // for warning/error messages
+#include "Common/PassVisitor.h"
+#include "GenPoly/DeclMutator.h"
+#include "GenPoly/PolyMutator.h"
 #include "ResolvExpr/Resolver.h"
 #include "ResolvExpr/typeops.h"
+#include "SymTab/Autogen.h"
+#include "SymTab/Indexer.h"
+#include "SynTree/AddStmtVisitor.h"
+#include "SynTree/Attribute.h"
 #include "SynTree/Declaration.h"
-#include "SynTree/Type.h"
 #include "SynTree/Expression.h"
-#include "SynTree/Attribute.h"
-#include "SynTree/Statement.h"
 #include "SynTree/Initializer.h"
 #include "SynTree/Mutator.h"
-#include "SymTab/Indexer.h"
-#include "SymTab/Autogen.h"
-#include "GenPoly/PolyMutator.h"
-#include "GenPoly/DeclMutator.h"
-#include "SynTree/AddStmtVisitor.h"
-#include "CodeGen/GenType.h"  // for warning/error messages
+#include "SynTree/Statement.h"
+#include "SynTree/Type.h"
 #include "Tuples/Tuples.h"
 
@@ -54,5 +56,5 @@
 		typedef std::unordered_map< int, int > UnqCount;
 
-		class InsertImplicitCalls final : public GenPoly::PolyMutator {
+		class InsertImplicitCalls {
 		public:
 			/// wrap function application expressions as ImplicitCopyCtorExpr nodes so that it is easy to identify which
@@ -61,11 +63,11 @@
 
 			InsertImplicitCalls( EnvMap & envMap ) : envMap( envMap ) {}
-			typedef GenPoly::PolyMutator Parent;
-			using Parent::mutate;
-			virtual Expression * mutate( ApplicationExpr * appExpr ) override;
-			virtual Expression * mutate( StmtExpr * stmtExpr ) override;
+
+			Expression * postmutate( ApplicationExpr * appExpr );
+			void premutate( StmtExpr * stmtExpr );
 
 			// collects environments for relevant nodes
 			EnvMap & envMap;
+			TypeSubstitution * env; //Magically populated by the PassVisitor
 		};
 
@@ -190,14 +192,13 @@
 		};
 
-		class FixInit final : public GenPoly::PolyMutator {
+		class FixInit {
 		  public:
 			/// expand each object declaration to use its constructor after it is declared.
 			static void fixInitializers( std::list< Declaration * > &translationUnit );
 
-			typedef GenPoly::PolyMutator Parent;
-			using Parent::mutate;
-			virtual DeclarationWithType * mutate( ObjectDecl *objDecl ) override;
+			DeclarationWithType * postmutate( ObjectDecl *objDecl );
 
 			std::list< Declaration * > staticDtorDecls;
+			std::list< Statement * > stmtsToAddAfter; // found by PassVisitor
 		};
 
@@ -300,5 +301,5 @@
 	namespace {
 		void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit, EnvMap & envMap ) {
-			InsertImplicitCalls inserter( envMap );
+			PassVisitor<InsertImplicitCalls> inserter( envMap );
 			mutateAll( translationUnit, inserter );
 		}
@@ -310,5 +311,5 @@
 
 		void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) {
-			FixInit fixer;
+			PassVisitor<FixInit> fixer;
 
 			// can't use mutateAll, because need to insert declarations at top-level
@@ -318,5 +319,5 @@
 				try {
 					*i = maybeMutate( *i, fixer );
-					translationUnit.splice( i, fixer.staticDtorDecls );
+					translationUnit.splice( i, fixer.pass.staticDtorDecls );
 				} catch( SemanticError &e ) {
 					e.set_location( (*i)->location );
@@ -350,6 +351,5 @@
 		}
 
-		Expression * InsertImplicitCalls::mutate( ApplicationExpr * appExpr ) {
-			appExpr = dynamic_cast< ApplicationExpr * >( Parent::mutate( appExpr ) );
+		Expression * InsertImplicitCalls::postmutate( ApplicationExpr * appExpr ) {
 			assert( appExpr );
 
@@ -393,8 +393,7 @@
 		}
 
-		Expression * InsertImplicitCalls::mutate( StmtExpr * stmtExpr ) {
+		void InsertImplicitCalls::premutate( StmtExpr * stmtExpr ) {
 			assert( env );
 			envMap[stmtExpr] = env;
-			return Parent::mutate( stmtExpr );
 		}
 
@@ -696,8 +695,6 @@
 		}
 
-		DeclarationWithType *FixInit::mutate( ObjectDecl *objDecl ) {
-			// first recursively handle pieces of ObjectDecl so that they aren't missed by other visitors when the init
-			// is removed from the ObjectDecl
-			objDecl = dynamic_cast< ObjectDecl * >( Parent::mutate( objDecl ) );
+		DeclarationWithType *FixInit::postmutate( ObjectDecl *objDecl ) {
+			// since this removes the init field from objDecl, it must occur after children are mutated (i.e. postmutate)
 			if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
 				// a decision should have been made by the resolver, so ctor and init are not both non-NULL
Index: src/Tuples/TupleExpansion.cc
===================================================================
--- src/Tuples/TupleExpansion.cc	(revision 6065b3aad7ca045ec48fc6103d1c55f0b5fb74b0)
+++ src/Tuples/TupleExpansion.cc	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
@@ -18,16 +18,17 @@
 #include <cassert>
 #include "Tuples.h"
+#include "Common/PassVisitor.h"
+#include "Common/ScopedMap.h"
 #include "GenPoly/DeclMutator.h"
+#include "InitTweak/GenInit.h"
+#include "InitTweak/InitTweak.h"
+#include "ResolvExpr/typeops.h"
+#include "SymTab/Mangler.h"
+#include "SynTree/Declaration.h"
+#include "SynTree/Expression.h"
+#include "SynTree/Initializer.h"
 #include "SynTree/Mutator.h"
 #include "SynTree/Statement.h"
-#include "SynTree/Declaration.h"
 #include "SynTree/Type.h"
-#include "SynTree/Expression.h"
-#include "SynTree/Initializer.h"
-#include "SymTab/Mangler.h"
-#include "Common/ScopedMap.h"
-#include "ResolvExpr/typeops.h"
-#include "InitTweak/GenInit.h"
-#include "InitTweak/InitTweak.h"
 
 namespace Tuples {
@@ -82,10 +83,7 @@
 		};
 
-		class TupleIndexExpander final : public Mutator {
-		public:
-			typedef Mutator Parent;
-			using Parent::mutate;
-
-			virtual Expression * mutate( TupleIndexExpr * tupleExpr ) override;
+		class TupleIndexExpander {
+		public:
+			Expression * postmutate( TupleIndexExpr * tupleExpr );
 		};
 
@@ -116,5 +114,5 @@
 		replacer.mutateDeclarationList( translationUnit );
 
-		TupleIndexExpander idxExpander;
+		PassVisitor<TupleIndexExpander> idxExpander;
 		mutateAll( translationUnit, idxExpander );
 
@@ -250,6 +248,6 @@
 	}
 
-	Expression * TupleIndexExpander::mutate( TupleIndexExpr * tupleExpr ) {
-		Expression * tuple = maybeMutate( tupleExpr->get_tuple(), *this );
+	Expression * TupleIndexExpander::postmutate( TupleIndexExpr * tupleExpr ) {
+		Expression * tuple = tupleExpr->get_tuple();
 		assert( tuple );
 		tupleExpr->set_tuple( nullptr );
Index: src/benchmark/create_cfaCor.c
===================================================================
--- src/benchmark/create_cfaCor.c	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
+++ src/benchmark/create_cfaCor.c	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
@@ -0,0 +1,18 @@
+#include <coroutine>
+#include <stdlib.h>
+#include <stdio.h>
+
+coroutine MyCoroutine {};
+void main(MyCoroutine * this) {}
+
+int main(int argc, char* argv[]) {
+	size_t n = 1000000;
+	if( argc > 2 ) return 1;
+	if( argc == 2 ) {
+		n = atoi(argv[1]);
+	}
+	printf("%lu\n", n);
+	for (size_t i = 0; i < n; i++) {
+		MyCoroutine m;
+	}
+}
Index: src/benchmark/create_cfaThrd.c
===================================================================
--- src/benchmark/create_cfaThrd.c	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
+++ src/benchmark/create_cfaThrd.c	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
@@ -0,0 +1,18 @@
+#include <thread>
+#include <stdlib.h>
+#include <stdio.h>
+
+thread MyThread {};
+void main(MyThread * this) {}
+
+int main(int argc, char* argv[]) {
+	size_t n = 1000000;
+	if( argc > 2 ) return 1;
+	if( argc == 2 ) {
+		n = atoi(argv[1]);
+	}
+	printf("%lu\n", n);
+	for (size_t i = 0; i < n; i++) {
+		MyThread m;
+	}
+}
Index: src/benchmark/create_pthrd.c
===================================================================
--- src/benchmark/create_pthrd.c	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
+++ src/benchmark/create_pthrd.c	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
@@ -0,0 +1,33 @@
+#include <pthread.h>
+#include <err.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+static void *foo(void *arg) {
+    return arg;
+}
+
+int main(int argc, char* argv[]) {
+	size_t n = 1000000;
+	if( argc > 2 ) return 1;
+	if( argc == 2 ) {
+		n = atoi(argv[1]);
+	}
+	printf("%lu\n", n);
+
+	for (size_t i = 0; i < n; i++) {
+		pthread_attr_t attr;
+		if (pthread_attr_init(&attr) < 0) {
+			return 1;
+		}
+		if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) < 0) {
+			return 1;
+		}
+		pthread_t thread;
+		if (pthread_create(&thread, &attr, foo, NULL) < 0) {
+			return 1;
+		}
+	}
+	pthread_exit(NULL);
+	return 0;
+}
Index: src/benchmark/create_uCor.cpp
===================================================================
--- src/benchmark/create_uCor.cpp	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
+++ src/benchmark/create_uCor.cpp	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
@@ -0,0 +1,19 @@
+#include <cstdlib>
+#include <cstdio>
+
+_Coroutine MyCor {
+	void main() {}
+};
+
+int main(int argc, char* argv[]) {
+	size_t n = 1000000;
+	if( argc > 2 ) return 1;
+	if( argc == 2 ) {
+		n = atoi(argv[1]);
+	}
+	printf("%lu\n", n);
+	for (size_t i = 0; i < n; i++) {
+		MyCor m;
+	}
+	return 0;
+}
Index: src/benchmark/create_uTask.cpp
===================================================================
--- src/benchmark/create_uTask.cpp	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
+++ src/benchmark/create_uTask.cpp	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
@@ -0,0 +1,19 @@
+#include <cstdlib>
+#include <cstdio>
+
+_Task MyThread {
+	void main() {}
+};
+
+int main(int argc, char* argv[]) {
+	size_t n = 1000000;
+	if( argc > 2 ) return 1;
+	if( argc == 2 ) {
+		n = atoi(argv[1]);
+	}
+	printf("%lu\n", n);
+	for (size_t i = 0; i < n; i++) {
+		MyThread m;
+	}
+	return 0;
+}
Index: src/tests/test.py
===================================================================
--- src/tests/test.py	(revision 6065b3aad7ca045ec48fc6103d1c55f0b5fb74b0)
+++ src/tests/test.py	(revision 49c977357660cc1dd2b3d7775733ba7cdc52aa4c)
@@ -253,5 +253,5 @@
 	# for each test to run
 	try :
-		results = pool.map_async(partial(run_test_worker, generate=generate, dry_run=dry_run, debug=debug), tests, chunksize = 1 ).get(3600)
+		results = pool.map_async(partial(run_test_worker, generate=generate, dry_run=dry_run, debug=debug), tests, chunksize = 1 ).get(7200)
 	except KeyboardInterrupt:
 		pool.terminate()
