Index: src/CodeGen/CodeGenerator.cc
===================================================================
--- src/CodeGen/CodeGenerator.cc	(revision acdfb4519df953ddab9076276b4f00ec543dfe2f)
+++ src/CodeGen/CodeGenerator.cc	(revision 9857e8db3b41cbdb308e59c3e43dc20b013a25b7)
@@ -139,7 +139,20 @@
 	} // CodeGenerator::genAttributes
 
+	// *** BaseSyntaxNode
+	void CodeGenerator::previsit( BaseSyntaxNode * ) {
+		// turn off automatic recursion for all nodes, to allow each visitor to
+		// precisely control the order in which its children are visited.
+		visit_children = false;
+	}
+
+	// *** BaseSyntaxNode
+	void CodeGenerator::postvisit( BaseSyntaxNode * node ) {
+		std::stringstream ss;
+		node->print( ss );
+		assertf( false, "Unhandled node reached in CodeGenerator: %s", ss.str().c_str() );
+	}
 
 	// *** Declarations
-	void CodeGenerator::visit( FunctionDecl * functionDecl ) {
+	void CodeGenerator::postvisit( FunctionDecl * functionDecl ) {
 		extension( functionDecl );
 		genAttributes( functionDecl->get_attributes() );
@@ -152,11 +165,11 @@
 		asmName( functionDecl );
 
-		// acceptAll( functionDecl->get_oldDecls(), *this );
+		// acceptAll( functionDecl->get_oldDecls(), *visitor );
 		if ( functionDecl->get_statements() ) {
-			functionDecl->get_statements()->accept( *this );
-		} // if
-	}
-
-	void CodeGenerator::visit( ObjectDecl * objectDecl ) {
+			functionDecl->get_statements()->accept( *visitor );
+		} // if
+	}
+
+	void CodeGenerator::postvisit( ObjectDecl * objectDecl ) {
 		if (objectDecl->get_name().empty() && genC ) {
 			// only generate an anonymous name when generating C code, otherwise it clutters the output too much
@@ -175,10 +188,10 @@
 		if ( objectDecl->get_init() ) {
 			output << " = ";
-			objectDecl->get_init()->accept( *this );
+			objectDecl->get_init()->accept( *visitor );
 		} // if
 
 		if ( objectDecl->get_bitfieldWidth() ) {
 			output << ":";
-			objectDecl->get_bitfieldWidth()->accept( *this );
+			objectDecl->get_bitfieldWidth()->accept( *visitor );
 		} // if
 	}
@@ -205,5 +218,5 @@
 				updateLocation( *i );
 				output << indent;
-				(*i)->accept( *this );
+				(*i)->accept( *visitor );
 				output << ";" << endl;
 			} // for
@@ -215,15 +228,15 @@
 	}
 
-	void CodeGenerator::visit( StructDecl * structDecl ) {
+	void CodeGenerator::postvisit( StructDecl * structDecl ) {
 		extension( structDecl );
 		handleAggregate( structDecl, "struct " );
 	}
 
-	void CodeGenerator::visit( UnionDecl * unionDecl ) {
+	void CodeGenerator::postvisit( UnionDecl * unionDecl ) {
 		extension( unionDecl );
 		handleAggregate( unionDecl, "union " );
 	}
 
-	void CodeGenerator::visit( EnumDecl * enumDecl ) {
+	void CodeGenerator::postvisit( EnumDecl * enumDecl ) {
 		extension( enumDecl );
 		updateLocation( enumDecl );
@@ -246,5 +259,5 @@
 				if ( obj->get_init() ) {
 					output << " = ";
-					obj->get_init()->accept( *this );
+					obj->get_init()->accept( *visitor );
 				} // if
 				output << "," << endl;
@@ -257,5 +270,5 @@
 	}
 
-	void CodeGenerator::visit( TraitDecl * traitDecl ) {
+	void CodeGenerator::postvisit( TraitDecl * traitDecl ) {
 		assertf( ! genC, "TraitDecls should not reach code generation." );
 		extension( traitDecl );
@@ -263,5 +276,5 @@
 	}
 
-	void CodeGenerator::visit( TypedefDecl * typeDecl ) {
+	void CodeGenerator::postvisit( TypedefDecl * typeDecl ) {
 		assertf( ! genC, "Typedefs are removed and substituted in earlier passes." );
 		updateLocation( typeDecl );
@@ -270,5 +283,5 @@
 	}
 
-	void CodeGenerator::visit( TypeDecl * typeDecl ) {
+	void CodeGenerator::postvisit( TypeDecl * typeDecl ) {
 		assertf( ! genC, "TypeDecls should not reach code generation." );
 		output << typeDecl->genTypeString() << " " << typeDecl->get_name();
@@ -283,5 +296,5 @@
 	}
 
-	void CodeGenerator::visit( Designation * designation ) {
+	void CodeGenerator::postvisit( Designation * designation ) {
 		std::list< Expression * > designators = designation->get_designators();
 		if ( designators.size() == 0 ) return;
@@ -290,9 +303,9 @@
 				// if expression is a NameExpr or VariableExpr, then initializing aggregate member
 				output << ".";
-				des->accept( *this );
+				des->accept( *visitor );
 			} else {
 				// otherwise, it has to be a ConstantExpr or CastExpr, initializing array eleemnt
 				output << "[";
-				des->accept( *this );
+				des->accept( *visitor );
 				output << "]";
 			} // if
@@ -301,9 +314,9 @@
 	}
 
-	void CodeGenerator::visit( SingleInit * init ) {
-		init->get_value()->accept( *this );
-	}
-
-	void CodeGenerator::visit( ListInit * init ) {
+	void CodeGenerator::postvisit( SingleInit * init ) {
+		init->get_value()->accept( *visitor );
+	}
+
+	void CodeGenerator::postvisit( ListInit * init ) {
 		auto initBegin = init->begin();
 		auto initEnd = init->end();
@@ -313,6 +326,6 @@
 		output << "{ ";
 		for ( ; initBegin != initEnd && desigBegin != desigEnd; ) {
-			(*desigBegin)->accept( *this );
-			(*initBegin)->accept( *this );
+			(*desigBegin)->accept( *visitor );
+			(*initBegin)->accept( *visitor );
 			++initBegin, ++desigBegin;
 			if ( initBegin != initEnd ) {
@@ -324,20 +337,20 @@
 	}
 
-	void CodeGenerator::visit( __attribute__((unused)) ConstructorInit * init ){
+	void CodeGenerator::postvisit( __attribute__((unused)) ConstructorInit * init ){
 		assertf( ! genC, "ConstructorInit nodes should not reach code generation." );
 		// pseudo-output for constructor/destructor pairs
 		output << "<ctorinit>{" << std::endl << ++indent << "ctor: ";
-		maybeAccept( init->get_ctor(), *this );
+		maybeAccept( init->get_ctor(), *visitor );
 		output << ", " << std::endl << indent << "dtor: ";
-		maybeAccept( init->get_dtor(), *this );
+		maybeAccept( init->get_dtor(), *visitor );
 		output << std::endl << --indent << "}";
 	}
 
-	void CodeGenerator::visit( Constant * constant ) {
+	void CodeGenerator::postvisit( Constant * constant ) {
 		output << constant->get_value() ;
 	}
 
 	// *** Expressions
-	void CodeGenerator::visit( ApplicationExpr * applicationExpr ) {
+	void CodeGenerator::postvisit( ApplicationExpr * applicationExpr ) {
 		extension( applicationExpr );
 		if ( VariableExpr * varExpr = dynamic_cast< VariableExpr* >( applicationExpr->get_function() ) ) {
@@ -348,7 +361,7 @@
 				  case OT_INDEX:
 					assert( applicationExpr->get_args().size() == 2 );
-					(*arg++)->accept( *this );
+					(*arg++)->accept( *visitor );
 					output << "[";
-					(*arg)->accept( *this );
+					(*arg)->accept( *visitor );
 					output << "]";
 					break;
@@ -365,12 +378,12 @@
 						// effects, so must still output this expression
 						output << "(";
-						(*arg++)->accept( *this );
+						(*arg++)->accept( *visitor );
 						output << ") /* " << opInfo.inputName << " */";
 					} else if ( applicationExpr->get_args().size() == 2 ) {
 						// intrinsic two parameter constructors are essentially bitwise assignment
 						output << "(";
-						(*arg++)->accept( *this );
+						(*arg++)->accept( *visitor );
 						output << opInfo.symbol;
-						(*arg)->accept( *this );
+						(*arg)->accept( *visitor );
 						output << ") /* " << opInfo.inputName << " */";
 					} else {
@@ -385,5 +398,5 @@
 					output << "(";
 					output << opInfo.symbol;
-					(*arg)->accept( *this );
+					(*arg)->accept( *visitor );
 					output << ")";
 					break;
@@ -392,5 +405,5 @@
 				  case OT_POSTFIXASSIGN:
 					assert( applicationExpr->get_args().size() == 1 );
-					(*arg)->accept( *this );
+					(*arg)->accept( *visitor );
 					output << opInfo.symbol;
 					break;
@@ -401,7 +414,7 @@
 					assert( applicationExpr->get_args().size() == 2 );
 					output << "(";
-					(*arg++)->accept( *this );
+					(*arg++)->accept( *visitor );
 					output << opInfo.symbol;
-					(*arg)->accept( *this );
+					(*arg)->accept( *visitor );
 					output << ")";
 					break;
@@ -413,5 +426,5 @@
 				} // switch
 			} else {
-				varExpr->accept( *this );
+				varExpr->accept( *visitor );
 				output << "(";
 				genCommaList( applicationExpr->get_args().begin(), applicationExpr->get_args().end() );
@@ -419,5 +432,5 @@
 			} // if
 		} else {
-			applicationExpr->get_function()->accept( *this );
+			applicationExpr->get_function()->accept( *visitor );
 			output << "(";
 			genCommaList( applicationExpr->get_args().begin(), applicationExpr->get_args().end() );
@@ -426,5 +439,5 @@
 	}
 
-	void CodeGenerator::visit( UntypedExpr * untypedExpr ) {
+	void CodeGenerator::postvisit( UntypedExpr * untypedExpr ) {
 		extension( untypedExpr );
 		if ( NameExpr * nameExpr = dynamic_cast< NameExpr* >( untypedExpr->get_function() ) ) {
@@ -435,7 +448,7 @@
 				  case OT_INDEX:
 					assert( untypedExpr->get_args().size() == 2 );
-					(*arg++)->accept( *this );
+					(*arg++)->accept( *visitor );
 					output << "[";
-					(*arg)->accept( *this );
+					(*arg)->accept( *visitor );
 					output << "]";
 					break;
@@ -450,12 +463,12 @@
 						// effects, so must still output this expression
 						output << "(";
-						(*arg++)->accept( *this );
+						(*arg++)->accept( *visitor );
 						output << ") /* " << opInfo.inputName << " */";
 					} else if ( untypedExpr->get_args().size() == 2 ) {
 						// intrinsic two parameter constructors are essentially bitwise assignment
 						output << "(";
-						(*arg++)->accept( *this );
+						(*arg++)->accept( *visitor );
 						output << opInfo.symbol;
-						(*arg)->accept( *this );
+						(*arg)->accept( *visitor );
 						output << ") /* " << opInfo.inputName << " */";
 					} else {
@@ -471,5 +484,5 @@
 					output << "(";
 					output << opInfo.symbol;
-					(*arg)->accept( *this );
+					(*arg)->accept( *visitor );
 					output << ")";
 					break;
@@ -478,5 +491,5 @@
 				  case OT_POSTFIXASSIGN:
 					assert( untypedExpr->get_args().size() == 1 );
-					(*arg)->accept( *this );
+					(*arg)->accept( *visitor );
 					output << opInfo.symbol;
 					break;
@@ -486,7 +499,7 @@
 					assert( untypedExpr->get_args().size() == 2 );
 					output << "(";
-					(*arg++)->accept( *this );
+					(*arg++)->accept( *visitor );
 					output << opInfo.symbol;
-					(*arg)->accept( *this );
+					(*arg)->accept( *visitor );
 					output << ")";
 					break;
@@ -499,9 +512,9 @@
 				if ( nameExpr->get_name() == "..." ) { // case V1 ... V2 or case V1~V2
 					assert( untypedExpr->get_args().size() == 2 );
-					(*untypedExpr->get_args().begin())->accept( *this );
+					(*untypedExpr->get_args().begin())->accept( *visitor );
 					output << " ... ";
-					(*--untypedExpr->get_args().end())->accept( *this );
+					(*--untypedExpr->get_args().end())->accept( *visitor );
 				} else {								// builtin routines
-					nameExpr->accept( *this );
+					nameExpr->accept( *visitor );
 					output << "(";
 					genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
@@ -510,5 +523,5 @@
 			} // if
 		} else {
-			untypedExpr->get_function()->accept( *this );
+			untypedExpr->get_function()->accept( *visitor );
 			output << "(";
 			genCommaList( untypedExpr->get_args().begin(), untypedExpr->get_args().end() );
@@ -517,11 +530,11 @@
 	}
 
-	void CodeGenerator::visit( RangeExpr * rangeExpr ) {
-		rangeExpr->get_low()->accept( *this );
+	void CodeGenerator::postvisit( RangeExpr * rangeExpr ) {
+		rangeExpr->get_low()->accept( *visitor );
 		output << " ... ";
-		rangeExpr->get_high()->accept( *this );
-	}
-
-	void CodeGenerator::visit( NameExpr * nameExpr ) {
+		rangeExpr->get_high()->accept( *visitor );
+	}
+
+	void CodeGenerator::postvisit( NameExpr * nameExpr ) {
 		extension( nameExpr );
 		OperatorInfo opInfo;
@@ -534,17 +547,17 @@
 	}
 
-	void CodeGenerator::visit( AddressExpr * addressExpr ) {
+	void CodeGenerator::postvisit( AddressExpr * addressExpr ) {
 		extension( addressExpr );
 		output << "(&";
-		addressExpr->arg->accept( *this );
+		addressExpr->arg->accept( *visitor );
 		output << ")";
 	}
 
-	void CodeGenerator::visit( LabelAddressExpr *addressExpr ) {
+	void CodeGenerator::postvisit( LabelAddressExpr *addressExpr ) {
 		extension( addressExpr );
 		output << "(&&" << addressExpr->arg << ")";
 	}
 
-	void CodeGenerator::visit( CastExpr * castExpr ) {
+	void CodeGenerator::postvisit( CastExpr * castExpr ) {
 		extension( castExpr );
 		output << "(";
@@ -559,31 +572,31 @@
 			output << ")";
 		} // if
-		castExpr->get_arg()->accept( *this );
+		castExpr->get_arg()->accept( *visitor );
 		output << ")";
 	}
 
-	void CodeGenerator::visit( VirtualCastExpr * castExpr ) {
+	void CodeGenerator::postvisit( VirtualCastExpr * castExpr ) {
 		assertf( ! genC, "VirtualCastExpr should not reach code generation." );
 		extension( castExpr );
 		output << "(virtual ";
-		castExpr->get_arg()->accept( *this );
+		castExpr->get_arg()->accept( *visitor );
 		output << ")";
 	}
 
-	void CodeGenerator::visit( UntypedMemberExpr * memberExpr ) {
+	void CodeGenerator::postvisit( UntypedMemberExpr * memberExpr ) {
 		assertf( ! genC, "UntypedMemberExpr should not reach code generation." );
 		extension( memberExpr );
-		memberExpr->get_aggregate()->accept( *this );
+		memberExpr->get_aggregate()->accept( *visitor );
 		output << ".";
-		memberExpr->get_member()->accept( *this );
-	}
-
-	void CodeGenerator::visit( MemberExpr * memberExpr ) {
+		memberExpr->get_member()->accept( *visitor );
+	}
+
+	void CodeGenerator::postvisit( MemberExpr * memberExpr ) {
 		extension( memberExpr );
-		memberExpr->get_aggregate()->accept( *this );
+		memberExpr->get_aggregate()->accept( *visitor );
 		output << "." << mangleName( memberExpr->get_member() );
 	}
 
-	void CodeGenerator::visit( VariableExpr * variableExpr ) {
+	void CodeGenerator::postvisit( VariableExpr * variableExpr ) {
 		extension( variableExpr );
 		OperatorInfo opInfo;
@@ -595,11 +608,11 @@
 	}
 
-	void CodeGenerator::visit( ConstantExpr * constantExpr ) {
+	void CodeGenerator::postvisit( ConstantExpr * constantExpr ) {
 		assert( constantExpr->get_constant() );
 		extension( constantExpr );
-		constantExpr->get_constant()->accept( *this );
-	}
-
-	void CodeGenerator::visit( SizeofExpr * sizeofExpr ) {
+		constantExpr->get_constant()->accept( *visitor );
+	}
+
+	void CodeGenerator::postvisit( SizeofExpr * sizeofExpr ) {
 		extension( sizeofExpr );
 		output << "sizeof(";
@@ -607,10 +620,10 @@
 			output << genType( sizeofExpr->get_type(), "", pretty, genC );
 		} else {
-			sizeofExpr->get_expr()->accept( *this );
+			sizeofExpr->get_expr()->accept( *visitor );
 		} // if
 		output << ")";
 	}
 
-	void CodeGenerator::visit( AlignofExpr * alignofExpr ) {
+	void CodeGenerator::postvisit( AlignofExpr * alignofExpr ) {
 		// use GCC extension to avoid bumping std to C11
 		extension( alignofExpr );
@@ -619,10 +632,10 @@
 			output << genType( alignofExpr->get_type(), "", pretty, genC );
 		} else {
-			alignofExpr->get_expr()->accept( *this );
+			alignofExpr->get_expr()->accept( *visitor );
 		} // if
 		output << ")";
 	}
 
-	void CodeGenerator::visit( UntypedOffsetofExpr * offsetofExpr ) {
+	void CodeGenerator::postvisit( UntypedOffsetofExpr * offsetofExpr ) {
 		assertf( ! genC, "UntypedOffsetofExpr should not reach code generation." );
 		output << "offsetof(";
@@ -632,5 +645,5 @@
 	}
 
-	void CodeGenerator::visit( OffsetofExpr * offsetofExpr ) {
+	void CodeGenerator::postvisit( OffsetofExpr * offsetofExpr ) {
 		// use GCC builtin
 		output << "__builtin_offsetof(";
@@ -640,13 +653,13 @@
 	}
 
-	void CodeGenerator::visit( OffsetPackExpr * offsetPackExpr ) {
+	void CodeGenerator::postvisit( OffsetPackExpr * offsetPackExpr ) {
 		assertf( ! genC, "OffsetPackExpr should not reach code generation." );
 		output << "__CFA_offsetpack(" << genType( offsetPackExpr->get_type(), "", pretty, genC ) << ")";
 	}
 
-	void CodeGenerator::visit( LogicalExpr * logicalExpr ) {
+	void CodeGenerator::postvisit( LogicalExpr * logicalExpr ) {
 		extension( logicalExpr );
 		output << "(";
-		logicalExpr->get_arg1()->accept( *this );
+		logicalExpr->get_arg1()->accept( *visitor );
 		if ( logicalExpr->get_isAnd() ) {
 			output << " && ";
@@ -654,20 +667,20 @@
 			output << " || ";
 		} // if
-		logicalExpr->get_arg2()->accept( *this );
+		logicalExpr->get_arg2()->accept( *visitor );
 		output << ")";
 	}
 
-	void CodeGenerator::visit( ConditionalExpr * conditionalExpr ) {
+	void CodeGenerator::postvisit( ConditionalExpr * conditionalExpr ) {
 		extension( conditionalExpr );
 		output << "(";
-		conditionalExpr->get_arg1()->accept( *this );
+		conditionalExpr->get_arg1()->accept( *visitor );
 		output << " ? ";
-		conditionalExpr->get_arg2()->accept( *this );
+		conditionalExpr->get_arg2()->accept( *visitor );
 		output << " : ";
-		conditionalExpr->get_arg3()->accept( *this );
+		conditionalExpr->get_arg3()->accept( *visitor );
 		output << ")";
 	}
 
-	void CodeGenerator::visit( CommaExpr * commaExpr ) {
+	void CodeGenerator::postvisit( CommaExpr * commaExpr ) {
 		extension( commaExpr );
 		output << "(";
@@ -676,16 +689,16 @@
 			commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) );
 		}
-		commaExpr->get_arg1()->accept( *this );
+		commaExpr->get_arg1()->accept( *visitor );
 		output << " , ";
-		commaExpr->get_arg2()->accept( *this );
+		commaExpr->get_arg2()->accept( *visitor );
 		output << ")";
 	}
 
-	void CodeGenerator::visit( TupleAssignExpr * tupleExpr ) {
+	void CodeGenerator::postvisit( TupleAssignExpr * tupleExpr ) {
 		assertf( ! genC, "TupleAssignExpr should not reach code generation." );
-		tupleExpr->stmtExpr->accept( *this );
-	}
-
-	void CodeGenerator::visit( UntypedTupleExpr * tupleExpr ) {
+		tupleExpr->stmtExpr->accept( *visitor );
+	}
+
+	void CodeGenerator::postvisit( UntypedTupleExpr * tupleExpr ) {
 		assertf( ! genC, "UntypedTupleExpr should not reach code generation." );
 		extension( tupleExpr );
@@ -695,5 +708,5 @@
 	}
 
-	void CodeGenerator::visit( TupleExpr * tupleExpr ) {
+	void CodeGenerator::postvisit( TupleExpr * tupleExpr ) {
 		assertf( ! genC, "TupleExpr should not reach code generation." );
 		extension( tupleExpr );
@@ -703,12 +716,12 @@
 	}
 
-	void CodeGenerator::visit( TupleIndexExpr * tupleExpr ) {
+	void CodeGenerator::postvisit( TupleIndexExpr * tupleExpr ) {
 		assertf( ! genC, "TupleIndexExpr should not reach code generation." );
 		extension( tupleExpr );
-		tupleExpr->get_tuple()->accept( *this );
+		tupleExpr->get_tuple()->accept( *visitor );
 		output << "." << tupleExpr->get_index();
 	}
 
-	void CodeGenerator::visit( TypeExpr * typeExpr ) {
+	void CodeGenerator::postvisit( TypeExpr * typeExpr ) {
 		// if ( genC ) std::cerr << "typeexpr still exists: " << typeExpr << std::endl;
 		// assertf( ! genC, "TypeExpr should not reach code generation." );
@@ -718,30 +731,30 @@
 	}
 
-	void CodeGenerator::visit( AsmExpr * asmExpr ) {
+	void CodeGenerator::postvisit( AsmExpr * asmExpr ) {
 		if ( asmExpr->get_inout() ) {
 			output << "[ ";
-			asmExpr->get_inout()->accept( *this );
+			asmExpr->get_inout()->accept( *visitor );
 			output << " ] ";
 		} // if
-		asmExpr->get_constraint()->accept( *this );
+		asmExpr->get_constraint()->accept( *visitor );
 		output << " ( ";
-		asmExpr->get_operand()->accept( *this );
+		asmExpr->get_operand()->accept( *visitor );
 		output << " )";
 	}
 
-	void CodeGenerator::visit( CompoundLiteralExpr *compLitExpr ) {
+	void CodeGenerator::postvisit( CompoundLiteralExpr *compLitExpr ) {
 		assert( compLitExpr->get_result() && dynamic_cast< ListInit * > ( compLitExpr->get_initializer() ) );
 		output << "(" << genType( compLitExpr->get_result(), "", pretty, genC ) << ")";
-		compLitExpr->get_initializer()->accept( *this );
-	}
-
-	void CodeGenerator::visit( UniqueExpr * unqExpr ) {
+		compLitExpr->get_initializer()->accept( *visitor );
+	}
+
+	void CodeGenerator::postvisit( UniqueExpr * unqExpr ) {
 		assertf( ! genC, "Unique expressions should not reach code generation." );
 		output << "unq<" << unqExpr->get_id() << ">{ ";
-		unqExpr->get_expr()->accept( *this );
+		unqExpr->get_expr()->accept( *visitor );
 		output << " }";
 	}
 
-	void CodeGenerator::visit( StmtExpr * stmtExpr ) {
+	void CodeGenerator::postvisit( StmtExpr * stmtExpr ) {
 		std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids();
 		updateLocation( stmtExpr );
@@ -757,5 +770,5 @@
 				// cannot cast to void, otherwise the expression statement has no value
 				if ( ExprStmt * exprStmt = dynamic_cast< ExprStmt * >( stmt ) ) {
-					exprStmt->get_expr()->accept( *this );
+					exprStmt->get_expr()->accept( *visitor );
 					output << ";" << endl;
 					++i;
@@ -763,5 +776,5 @@
 				}
 			}
-			stmt->accept( *this );
+			stmt->accept( *visitor );
 			output << endl;
 			if ( wantSpacing( stmt ) ) {
@@ -775,5 +788,5 @@
 
 	// *** Statements
-	void CodeGenerator::visit( CompoundStmt * compoundStmt ) {
+	void CodeGenerator::postvisit( CompoundStmt * compoundStmt ) {
 		std::list<Statement*> ks = compoundStmt->get_kids();
 		output << "{" << endl;
@@ -783,5 +796,5 @@
 		for ( std::list<Statement *>::iterator i = ks.begin(); i != ks.end();  i++ ) {
 			output << indent << printLabels( (*i)->get_labels() );
-			(*i)->accept( *this );
+			(*i)->accept( *visitor );
 
 			output << endl;
@@ -795,5 +808,5 @@
 	}
 
-	void CodeGenerator::visit( ExprStmt * exprStmt ) {
+	void CodeGenerator::postvisit( ExprStmt * exprStmt ) {
 		assert( exprStmt );
 		if ( genC ) {
@@ -801,14 +814,14 @@
 			exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) );
 		}
-		exprStmt->get_expr()->accept( *this );
+		exprStmt->get_expr()->accept( *visitor );
 		output << ";";
 	}
 
-	void CodeGenerator::visit( AsmStmt * asmStmt ) {
+	void CodeGenerator::postvisit( AsmStmt * asmStmt ) {
 		output << "asm ";
 		if ( asmStmt->get_voltile() ) output << "volatile ";
 		if ( ! asmStmt->get_gotolabels().empty()  ) output << "goto ";
 		output << "( ";
-		if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *this );
+		if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *visitor );
 		output << " : ";
 		genCommaList( asmStmt->get_output().begin(), asmStmt->get_output().end() );
@@ -828,40 +841,40 @@
 	}
 
-	void CodeGenerator::visit( AsmDecl * asmDecl ) {
+	void CodeGenerator::postvisit( AsmDecl * asmDecl ) {
 		output << "asm ";
 		AsmStmt * asmStmt = asmDecl->get_stmt();
 		output << "( ";
-		if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *this );
+		if ( asmStmt->get_instruction() ) asmStmt->get_instruction()->accept( *visitor );
 		output << " )" ;
 	}
 
-	void CodeGenerator::visit( IfStmt * ifStmt ) {
+	void CodeGenerator::postvisit( IfStmt * ifStmt ) {
 		updateLocation( ifStmt );
 		output << "if ( ";
-		ifStmt->get_condition()->accept( *this );
+		ifStmt->get_condition()->accept( *visitor );
 		output << " ) ";
 
-		ifStmt->get_thenPart()->accept( *this );
+		ifStmt->get_thenPart()->accept( *visitor );
 
 		if ( ifStmt->get_elsePart() != 0) {
 			output << " else ";
-			ifStmt->get_elsePart()->accept( *this );
-		} // if
-	}
-
-	void CodeGenerator::visit( SwitchStmt * switchStmt ) {
+			ifStmt->get_elsePart()->accept( *visitor );
+		} // if
+	}
+
+	void CodeGenerator::postvisit( SwitchStmt * switchStmt ) {
 		updateLocation( switchStmt );
 		output << "switch ( " ;
-		switchStmt->get_condition()->accept( *this );
+		switchStmt->get_condition()->accept( *visitor );
 		output << " ) ";
 
 		output << "{" << std::endl;
 		++indent;
-		acceptAll( switchStmt->get_statements(), *this );
+		acceptAll( switchStmt->get_statements(), *visitor );
 		--indent;
 		output << indent << "}";
 	}
 
-	void CodeGenerator::visit( CaseStmt * caseStmt ) {
+	void CodeGenerator::postvisit( CaseStmt * caseStmt ) {
 		updateLocation( caseStmt );
 		if ( caseStmt->isDefault()) {
@@ -869,5 +882,5 @@
 		} else {
 			output << "case ";
-			caseStmt->get_condition()->accept( *this );
+			caseStmt->get_condition()->accept( *visitor );
 		} // if
 		output << ":\n";
@@ -878,5 +891,5 @@
 		for ( std::list<Statement *>::iterator i = sts.begin(); i != sts.end();  i++) {
 			output << indent << printLabels( (*i)->get_labels() )  ;
-			(*i)->accept( *this );
+			(*i)->accept( *visitor );
 			output << endl;
 		} // for
@@ -884,5 +897,5 @@
 	}
 
-	void CodeGenerator::visit( BranchStmt * branchStmt ) {
+	void CodeGenerator::postvisit( BranchStmt * branchStmt ) {
 		switch ( branchStmt->get_type()) {
 		  case BranchStmt::Goto:
@@ -892,5 +905,5 @@
 				if ( branchStmt->get_computedTarget() != 0 ) {
 					output << "goto *";
-					branchStmt->get_computedTarget()->accept( *this );
+					branchStmt->get_computedTarget()->accept( *visitor );
 				} // if
 			} // if
@@ -906,11 +919,11 @@
 	}
 
-	void CodeGenerator::visit( ReturnStmt * returnStmt ) {
+	void CodeGenerator::postvisit( ReturnStmt * returnStmt ) {
 		output << "return ";
-		maybeAccept( returnStmt->get_expr(), *this );
+		maybeAccept( returnStmt->get_expr(), *visitor );
 		output << ";";
 	}
 
-	void CodeGenerator::visit( ThrowStmt * throwStmt ) {
+	void CodeGenerator::postvisit( ThrowStmt * throwStmt ) {
 		assertf( ! genC, "Throw statements should not reach code generation." );
 
@@ -919,19 +932,19 @@
 		if (throwStmt->get_expr()) {
 			output << " ";
-			throwStmt->get_expr()->accept( *this );
+			throwStmt->get_expr()->accept( *visitor );
 		}
 		if (throwStmt->get_target()) {
 			output << " _At ";
-			throwStmt->get_target()->accept( *this );
+			throwStmt->get_target()->accept( *visitor );
 		}
 		output << ";";
 	}
 
-	void CodeGenerator::visit( WhileStmt * whileStmt ) {
+	void CodeGenerator::postvisit( WhileStmt * whileStmt ) {
 		if ( whileStmt->get_isDoWhile() ) {
 			output << "do" ;
 		} else {
 			output << "while (" ;
-			whileStmt->get_condition()->accept( *this );
+			whileStmt->get_condition()->accept( *visitor );
 			output << ")";
 		} // if
@@ -939,5 +952,5 @@
 
 		output << CodeGenerator::printLabels( whileStmt->get_body()->get_labels() );
-		whileStmt->get_body()->accept( *this );
+		whileStmt->get_body()->accept( *visitor );
 
 		output << indent;
@@ -945,15 +958,15 @@
 		if ( whileStmt->get_isDoWhile() ) {
 			output << " while (" ;
-			whileStmt->get_condition()->accept( *this );
+			whileStmt->get_condition()->accept( *visitor );
 			output << ");";
 		} // if
 	}
 
-	void CodeGenerator::visit( ForStmt * forStmt ) {
+	void CodeGenerator::postvisit( ForStmt * forStmt ) {
 		// initialization is always hoisted, so don't bother doing anything with that
 		output << "for (;";
 
 		if ( forStmt->get_condition() != 0 ) {
-			forStmt->get_condition()->accept( *this );
+			forStmt->get_condition()->accept( *visitor );
 		} // if
 		output << ";";
@@ -962,5 +975,5 @@
 			// cast the top-level expression to void to reduce gcc warnings.
 			Expression * expr = new CastExpr( forStmt->get_increment() );
-			expr->accept( *this );
+			expr->accept( *visitor );
 		} // if
 		output << ") ";
@@ -968,19 +981,24 @@
 		if ( forStmt->get_body() != 0 ) {
 			output << CodeGenerator::printLabels( forStmt->get_body()->get_labels() );
-			forStmt->get_body()->accept( *this );
-		} // if
-	}
-
-	void CodeGenerator::visit( __attribute__((unused)) NullStmt * nullStmt ) {
+			forStmt->get_body()->accept( *visitor );
+		} // if
+	}
+
+	void CodeGenerator::postvisit( __attribute__((unused)) NullStmt * nullStmt ) {
 		//output << indent << CodeGenerator::printLabels( nullStmt->get_labels() );
 		output << "/* null statement */ ;";
 	}
 
-	void CodeGenerator::visit( DeclStmt * declStmt ) {
-		declStmt->get_decl()->accept( *this );
+	void CodeGenerator::postvisit( DeclStmt * declStmt ) {
+		declStmt->get_decl()->accept( *visitor );
 
 		if ( doSemicolon( declStmt->get_decl() ) ) {
 			output << ";";
 		} // if
+	}
+
+	void CodeGenerator::postvisit( ImplicitCtorDtorStmt * stmt ) {
+		assertf( ! genC, "ImplicitCtorDtorStmts should not reach code generation." );
+		stmt->callStmt->accept( *visitor );
 	}
 
Index: src/CodeGen/CodeGenerator.h
===================================================================
--- src/CodeGen/CodeGenerator.h	(revision acdfb4519df953ddab9076276b4f00ec543dfe2f)
+++ src/CodeGen/CodeGenerator.h	(revision 9857e8db3b41cbdb308e59c3e43dc20b013a25b7)
@@ -21,4 +21,5 @@
 
 #include "Common/Indenter.h"      // for Indenter
+#include "Common/PassVisitor.h"   // for PassVisitor
 #include "SynTree/Declaration.h"  // for DeclarationWithType (ptr only), Fun...
 #include "SynTree/Visitor.h"      // for Visitor
@@ -26,7 +27,6 @@
 
 namespace CodeGen {
-	class CodeGenerator : public Visitor {
-	  public:
-		static int tabsize;
+	struct CodeGenerator : public WithShortCircuiting, public WithVisitorRef<CodeGenerator> {
+	  static int tabsize;
 
 		CodeGenerator( std::ostream &os, bool pretty = false, bool genC = false, bool lineMarks = false );
@@ -34,69 +34,76 @@
 		CodeGenerator( std::ostream &os, char *, int indent = 0, bool infun = false );
 
+		//*** Turn off visit_children for all nodes
+		void previsit( BaseSyntaxNode * );
+
+		//*** Error for unhandled node types
+		void postvisit( BaseSyntaxNode * );
+
 		//*** Declaration
-		virtual void visit( StructDecl * );
-		virtual void visit( FunctionDecl * );
-		virtual void visit( ObjectDecl * );
-		virtual void visit( UnionDecl *aggregateDecl );
-		virtual void visit( EnumDecl *aggregateDecl );
-		virtual void visit( TraitDecl *aggregateDecl );
-		virtual void visit( TypedefDecl *typeDecl );
-		virtual void visit( TypeDecl *typeDecl );
+		void postvisit( StructDecl * );
+		void postvisit( FunctionDecl * );
+		void postvisit( ObjectDecl * );
+		void postvisit( UnionDecl *aggregateDecl );
+		void postvisit( EnumDecl *aggregateDecl );
+		void postvisit( TraitDecl *aggregateDecl );
+		void postvisit( TypedefDecl *typeDecl );
+		void postvisit( TypeDecl *typeDecl );
 
 		//*** Initializer
-		virtual void visit( Designation * );
-		virtual void visit( SingleInit * );
-		virtual void visit( ListInit * );
-		virtual void visit( ConstructorInit * );
+		void postvisit( Designation * );
+		void postvisit( SingleInit * );
+		void postvisit( ListInit * );
+		void postvisit( ConstructorInit * );
 
 		//*** Constant
-		virtual void visit( Constant * );
+		void postvisit( Constant * );
 
 		//*** Expression
-		virtual void visit( ApplicationExpr *applicationExpr );
-		virtual void visit( UntypedExpr *untypedExpr );
-		virtual void visit( RangeExpr * rangeExpr );
-		virtual void visit( NameExpr *nameExpr );
-		virtual void visit( AddressExpr *addressExpr );
-		virtual void visit( LabelAddressExpr *addressExpr );
-		virtual void visit( CastExpr *castExpr );
-		virtual void visit( VirtualCastExpr *castExpr );
-		virtual void visit( UntypedMemberExpr *memberExpr );
-		virtual void visit( MemberExpr *memberExpr );
-		virtual void visit( VariableExpr *variableExpr );
-		virtual void visit( ConstantExpr *constantExpr );
-		virtual void visit( SizeofExpr *sizeofExpr );
-		virtual void visit( AlignofExpr *alignofExpr );
-		virtual void visit( UntypedOffsetofExpr *offsetofExpr );
-		virtual void visit( OffsetofExpr *offsetofExpr );
-		virtual void visit( OffsetPackExpr *offsetPackExpr );
-		virtual void visit( LogicalExpr *logicalExpr );
-		virtual void visit( ConditionalExpr *conditionalExpr );
-		virtual void visit( CommaExpr *commaExpr );
-		virtual void visit( CompoundLiteralExpr *compLitExpr );
-		virtual void visit( UniqueExpr * );
-		virtual void visit( TupleAssignExpr * tupleExpr );
-		virtual void visit( UntypedTupleExpr *tupleExpr );
-		virtual void visit( TupleExpr *tupleExpr );
-		virtual void visit( TupleIndexExpr * tupleExpr );
-		virtual void visit( TypeExpr *typeExpr );
-		virtual void visit( AsmExpr * );
-		virtual void visit( StmtExpr * );
+		void postvisit( ApplicationExpr *applicationExpr );
+		void postvisit( UntypedExpr *untypedExpr );
+		void postvisit( RangeExpr * rangeExpr );
+		void postvisit( NameExpr *nameExpr );
+		void postvisit( AddressExpr *addressExpr );
+		void postvisit( LabelAddressExpr *addressExpr );
+		void postvisit( CastExpr *castExpr );
+		void postvisit( VirtualCastExpr *castExpr );
+		void postvisit( UntypedMemberExpr *memberExpr );
+		void postvisit( MemberExpr *memberExpr );
+		void postvisit( VariableExpr *variableExpr );
+		void postvisit( ConstantExpr *constantExpr );
+		void postvisit( SizeofExpr *sizeofExpr );
+		void postvisit( AlignofExpr *alignofExpr );
+		void postvisit( UntypedOffsetofExpr *offsetofExpr );
+		void postvisit( OffsetofExpr *offsetofExpr );
+		void postvisit( OffsetPackExpr *offsetPackExpr );
+		void postvisit( LogicalExpr *logicalExpr );
+		void postvisit( ConditionalExpr *conditionalExpr );
+		void postvisit( CommaExpr *commaExpr );
+		void postvisit( CompoundLiteralExpr *compLitExpr );
+		void postvisit( UniqueExpr * );
+		void postvisit( TupleAssignExpr * tupleExpr );
+		void postvisit( UntypedTupleExpr *tupleExpr );
+		void postvisit( TupleExpr *tupleExpr );
+		void postvisit( TupleIndexExpr * tupleExpr );
+		void postvisit( TypeExpr *typeExpr );
+		void postvisit( AsmExpr * );
+		void postvisit( StmtExpr * );
 
 		//*** Statements
-		virtual void visit( CompoundStmt * );
-		virtual void visit( ExprStmt * );
-		virtual void visit( AsmStmt * );
-		virtual void visit( AsmDecl * );				// special: statement in declaration context
-		virtual void visit( IfStmt * );
-		virtual void visit( SwitchStmt * );
-		virtual void visit( CaseStmt * );
-		virtual void visit( BranchStmt * );
-		virtual void visit( ReturnStmt * );
-		virtual void visit( ThrowStmt * );
-		virtual void visit( WhileStmt * );
-		virtual void visit( ForStmt * );
-		virtual void visit( NullStmt * );
-		virtual void visit( DeclStmt * );
+		void postvisit( CompoundStmt * );
+		void postvisit( ExprStmt * );
+		void postvisit( AsmStmt * );
+		void postvisit( AsmDecl * );				// special: statement in declaration context
+		void postvisit( IfStmt * );
+		void postvisit( SwitchStmt * );
+		void postvisit( CaseStmt * );
+		void postvisit( BranchStmt * );
+		void postvisit( ReturnStmt * );
+		void postvisit( ThrowStmt * );
+		void postvisit( WhileStmt * );
+		void postvisit( ForStmt * );
+		void postvisit( NullStmt * );
+		void postvisit( DeclStmt * );
+		void postvisit( ImplicitCtorDtorStmt * );
 
 		void genAttributes( std::list< Attribute * > & attributes );
@@ -140,5 +147,5 @@
 	  if ( begin == end ) return;
 		for ( ;; ) {
-			(*begin++)->accept( *this );
+			(*begin++)->accept( *visitor );
 		  if ( begin == end ) break;
 			output << ", ";								// separator
Index: src/CodeGen/GenType.cc
===================================================================
--- src/CodeGen/GenType.cc	(revision acdfb4519df953ddab9076276b4f00ec543dfe2f)
+++ src/CodeGen/GenType.cc	(revision 9857e8db3b41cbdb308e59c3e43dc20b013a25b7)
@@ -63,6 +63,6 @@
 
 		if ( ! type->get_attributes().empty() ) {
-			CodeGenerator cg( os, pretty, genC, lineMarks );
-			cg.genAttributes( type->get_attributes() );
+			PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
+			cg.pass.genAttributes( type->get_attributes() );
 		} // if
 
@@ -116,5 +116,5 @@
 		} // if
 		if ( dimension != 0 ) {
-			CodeGenerator cg( os, pretty, genC, lineMarks );
+			PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
 			dimension->accept( cg );
 		} else if ( isVarLen ) {
@@ -178,8 +178,8 @@
 			} // if
 		} else {
-			CodeGenerator cg( os, pretty, genC, lineMarks );
+			PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
 			os << "(" ;
 
-			cg.genCommaList( pars.begin(), pars.end() );
+			cg.pass.genCommaList( pars.begin(), pars.end() );
 
 			if ( funcType->get_isVarArgs() ) {
@@ -201,7 +201,7 @@
 			// assertf( ! genC, "Aggregate type parameters should not reach code generation." );
 			std::ostringstream os;
-			CodeGenerator cg( os, pretty, genC, lineMarks );
+			PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
 			os << "forall(";
-			cg.genCommaList( funcType->get_forall().begin(), funcType->get_forall().end() );
+			cg.pass.genCommaList( funcType->get_forall().begin(), funcType->get_forall().end() );
 			os << ")" << std::endl;
 			typeString = os.str() + typeString;
@@ -212,7 +212,7 @@
 		if ( ! refType->get_parameters().empty() ) {
 			std::ostringstream os;
-			CodeGenerator cg( os, pretty, genC, lineMarks );
+			PassVisitor<CodeGenerator> cg( os, pretty, genC, lineMarks );
 			os << "(";
-			cg.genCommaList( refType->get_parameters().begin(), refType->get_parameters().end() );
+			cg.pass.genCommaList( refType->get_parameters().begin(), refType->get_parameters().end() );
 			os << ") ";
 			return os.str();
Index: src/CodeGen/Generate.cc
===================================================================
--- src/CodeGen/Generate.cc	(revision acdfb4519df953ddab9076276b4f00ec543dfe2f)
+++ src/CodeGen/Generate.cc	(revision 9857e8db3b41cbdb308e59c3e43dc20b013a25b7)
@@ -49,8 +49,8 @@
 		cleanTree( translationUnit );
 
-		CodeGen::CodeGenerator cgv( os, pretty, generateC, lineMarks );
+		PassVisitor<CodeGenerator> cgv( os, pretty, generateC, lineMarks );
 		for ( auto & dcl : translationUnit ) {
 			if ( LinkageSpec::isGeneratable( dcl->get_linkage() ) && (doIntrinsics || ! LinkageSpec::isBuiltin( dcl->get_linkage() ) ) ) {
-				cgv.updateLocation( dcl );
+				cgv.pass.updateLocation( dcl );
 				dcl->accept(cgv);
 				if ( doSemicolon( dcl ) ) {
Index: src/SynTree/BaseSyntaxNode.h
===================================================================
--- src/SynTree/BaseSyntaxNode.h	(revision acdfb4519df953ddab9076276b4f00ec543dfe2f)
+++ src/SynTree/BaseSyntaxNode.h	(revision 9857e8db3b41cbdb308e59c3e43dc20b013a25b7)
@@ -26,4 +26,5 @@
 
 	virtual void accept( Visitor & v ) = 0;
+  virtual void print( std::ostream & os, int indent = 0 ) const = 0;
 };
 
