Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision bff09c8c0c9e3f3a60f531ef14be5ead36733eb5)
+++ src/ResolvExpr/Resolver.cc	(revision c0714bfd6119abb84c6c2aa4881ff5f14758638c)
@@ -21,4 +21,5 @@
 #include "Alternative.h"                 // for Alternative, AltList
 #include "AlternativeFinder.h"           // for AlternativeFinder, resolveIn...
+#include "Common/PassVisitor.h"          // for PassVisitor
 #include "Common/SemanticError.h"        // for SemanticError
 #include "Common/utility.h"              // for ValueGuard, group_iterate
@@ -43,41 +44,35 @@
 
 namespace ResolvExpr {
-	class Resolver final : public SymTab::Indexer {
-	  public:
-		Resolver() : SymTab::Indexer( false ) {}
-		Resolver( const SymTab:: Indexer & other ) : SymTab::Indexer( other ) {
-			if ( const Resolver * res = dynamic_cast< const Resolver * >( &other ) ) {
-				functionReturn = res->functionReturn;
-				currentObject = res->currentObject;
-				inEnumDecl = res->inEnumDecl;
-			}
-		}
-
-		typedef SymTab::Indexer Parent;
-		using Parent::visit;
-		virtual void visit( FunctionDecl *functionDecl ) override;
-		virtual void visit( ObjectDecl *functionDecl ) override;
-		virtual void visit( TypeDecl *typeDecl ) override;
-		virtual void visit( EnumDecl * enumDecl ) override;
-
-		virtual void visit( ArrayType * at ) override;
-		virtual void visit( PointerType * at ) override;
-
-		virtual void visit( ExprStmt *exprStmt ) override;
-		virtual void visit( AsmExpr *asmExpr ) override;
-		virtual void visit( AsmStmt *asmStmt ) override;
-		virtual void visit( IfStmt *ifStmt ) override;
-		virtual void visit( WhileStmt *whileStmt ) override;
-		virtual void visit( ForStmt *forStmt ) override;
-		virtual void visit( SwitchStmt *switchStmt ) override;
-		virtual void visit( CaseStmt *caseStmt ) override;
-		virtual void visit( BranchStmt *branchStmt ) override;
-		virtual void visit( ReturnStmt *returnStmt ) override;
-		virtual void visit( ThrowStmt *throwStmt ) override;
-		virtual void visit( CatchStmt *catchStmt ) override;
-
-		virtual void visit( SingleInit *singleInit ) override;
-		virtual void visit( ListInit *listInit ) override;
-		virtual void visit( ConstructorInit *ctorInit ) override;
+	struct Resolver final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver>, public WithShortCircuiting {
+		Resolver() {}
+		Resolver( const SymTab::Indexer & other ) {
+			indexer = other;
+		}
+
+		void previsit( FunctionDecl *functionDecl );
+		void postvisit( FunctionDecl *functionDecl );
+		void previsit( ObjectDecl *functionDecl );
+		void previsit( TypeDecl *typeDecl );
+		void previsit( EnumDecl * enumDecl );
+
+		void previsit( ArrayType * at );
+		void previsit( PointerType * at );
+
+		void previsit( ExprStmt *exprStmt );
+		void previsit( AsmExpr *asmExpr );
+		void previsit( AsmStmt *asmStmt );
+		void previsit( IfStmt *ifStmt );
+		void previsit( WhileStmt *whileStmt );
+		void previsit( ForStmt *forStmt );
+		void previsit( SwitchStmt *switchStmt );
+		void previsit( CaseStmt *caseStmt );
+		void previsit( BranchStmt *branchStmt );
+		void previsit( ReturnStmt *returnStmt );
+		void previsit( ThrowStmt *throwStmt );
+		void previsit( CatchStmt *catchStmt );
+
+		void previsit( SingleInit *singleInit );
+		void previsit( ListInit *listInit );
+		void previsit( ConstructorInit *ctorInit );
 	  private:
   	typedef std::list< Initializer * >::iterator InitIterator;
@@ -96,13 +91,13 @@
 
 	void resolve( std::list< Declaration * > translationUnit ) {
-		Resolver resolver;
+		PassVisitor<Resolver> resolver;
 		acceptAll( translationUnit, resolver );
 	}
 
+	// used in resolveTypeof
 	Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer ) {
 		TypeEnvironment env;
 		return resolveInVoidContext( expr, indexer, env );
 	}
-
 
 	namespace {
@@ -190,6 +185,6 @@
 	}
 
-	void Resolver::visit( ObjectDecl *objectDecl ) {
-		Type *new_type = resolveTypeof( objectDecl->get_type(), *this );
+	void Resolver::previsit( ObjectDecl *objectDecl ) {
+		Type *new_type = resolveTypeof( objectDecl->get_type(), indexer );
 		objectDecl->set_type( new_type );
 		// To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable
@@ -198,5 +193,5 @@
 		// each value of initContext is retained, so the type on the first analysis is preserved and used for selecting
 		// the RHS.
-		ValueGuard<CurrentObject> temp( currentObject );
+		GuardValue( currentObject );
 		currentObject = CurrentObject( objectDecl->get_type() );
 		if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) {
@@ -205,9 +200,4 @@
 			currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
 		}
-		Parent::visit( objectDecl );
-		if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) {
-			// delete newly created signed int type
-			// delete currentObject.getType();
-		}
 	}
 
@@ -216,5 +206,5 @@
 		if ( type->get_dimension() ) {
 			CastExpr *castExpr = new CastExpr( type->get_dimension(), SymTab::SizeType->clone() );
-			Expression *newExpr = findSingleExpression( castExpr, *this );
+			Expression *newExpr = findSingleExpression( castExpr, indexer );
 			delete type->get_dimension();
 			type->set_dimension( newExpr );
@@ -222,34 +212,33 @@
 	}
 
-	void Resolver::visit( ArrayType * at ) {
+	void Resolver::previsit( ArrayType * at ) {
 		handlePtrType( at );
-		Parent::visit( at );
-	}
-
-	void Resolver::visit( PointerType * pt ) {
+	}
+
+	void Resolver::previsit( PointerType * pt ) {
 		handlePtrType( pt );
-		Parent::visit( pt );
-	}
-
-	void Resolver::visit( TypeDecl *typeDecl ) {
+	}
+
+	void Resolver::previsit( TypeDecl *typeDecl ) {
 		if ( typeDecl->get_base() ) {
-			Type *new_type = resolveTypeof( typeDecl->get_base(), *this );
+			Type *new_type = resolveTypeof( typeDecl->get_base(), indexer );
 			typeDecl->set_base( new_type );
 		} // if
-		Parent::visit( typeDecl );
-	}
-
-	void Resolver::visit( FunctionDecl *functionDecl ) {
+	}
+
+	void Resolver::previsit( FunctionDecl *functionDecl ) {
 #if 0
-		std::cout << "resolver visiting functiondecl ";
-		functionDecl->print( std::cout );
-		std::cout << std::endl;
+		std::cerr << "resolver visiting functiondecl ";
+		functionDecl->print( std::cerr );
+		std::cerr << std::endl;
 #endif
-		Type *new_type = resolveTypeof( functionDecl->get_type(), *this );
+		Type *new_type = resolveTypeof( functionDecl->get_type(), indexer );
 		functionDecl->set_type( new_type );
-		ValueGuard< Type * > oldFunctionReturn( functionReturn );
+		GuardValue( functionReturn );
 		functionReturn = ResolvExpr::extractResultType( functionDecl->get_functionType() );
-		Parent::visit( functionDecl );
-
+	}
+
+
+	void Resolver::postvisit( FunctionDecl *functionDecl ) {
 		// default value expressions have an environment which shouldn't be there and trips up later passes.
 		// xxx - it might be necessary to somehow keep the information from this environment, but I can't currently
@@ -265,24 +254,25 @@
 	}
 
-	void Resolver::visit( EnumDecl * enumDecl ) {
+	void Resolver::previsit( EnumDecl * ) {
 		// in case we decide to allow nested enums
-		ValueGuard< bool > oldInEnumDecl( inEnumDecl );
+		GuardValue( inEnumDecl );
 		inEnumDecl = true;
-		Parent::visit( enumDecl );
-	}
-
-	void Resolver::visit( ExprStmt *exprStmt ) {
+	}
+
+	void Resolver::previsit( ExprStmt *exprStmt ) {
+		visit_children = false;
 		assertf( exprStmt->get_expr(), "ExprStmt has null Expression in resolver" );
-		Expression *newExpr = findVoidExpression( exprStmt->get_expr(), *this );
+		Expression *newExpr = findVoidExpression( exprStmt->get_expr(), indexer );
 		delete exprStmt->get_expr();
 		exprStmt->set_expr( newExpr );
 	}
 
-	void Resolver::visit( AsmExpr *asmExpr ) {
-		Expression *newExpr = findVoidExpression( asmExpr->get_operand(), *this );
+	void Resolver::previsit( AsmExpr *asmExpr ) {
+		visit_children = false;
+		Expression *newExpr = findVoidExpression( asmExpr->get_operand(), indexer );
 		delete asmExpr->get_operand();
 		asmExpr->set_operand( newExpr );
 		if ( asmExpr->get_inout() ) {
-			newExpr = findVoidExpression( asmExpr->get_inout(), *this );
+			newExpr = findVoidExpression( asmExpr->get_inout(), indexer );
 			delete asmExpr->get_inout();
 			asmExpr->set_inout( newExpr );
@@ -290,28 +280,25 @@
 	}
 
-	void Resolver::visit( AsmStmt *asmStmt ) {
-		acceptAll( asmStmt->get_input(), *this);
-		acceptAll( asmStmt->get_output(), *this);
-	}
-
-	void Resolver::visit( IfStmt *ifStmt ) {
-		Expression *newExpr = findSingleExpression( ifStmt->get_condition(), *this );
+	void Resolver::previsit( AsmStmt *asmStmt ) {
+		visit_children = false;
+		acceptAll( asmStmt->get_input(), *visitor );
+		acceptAll( asmStmt->get_output(), *visitor );
+	}
+
+	void Resolver::previsit( IfStmt *ifStmt ) {
+		Expression *newExpr = findSingleExpression( ifStmt->get_condition(), indexer );
 		delete ifStmt->get_condition();
 		ifStmt->set_condition( newExpr );
-		Parent::visit( ifStmt );
-	}
-
-	void Resolver::visit( WhileStmt *whileStmt ) {
-		Expression *newExpr = findSingleExpression( whileStmt->get_condition(), *this );
+	}
+
+	void Resolver::previsit( WhileStmt *whileStmt ) {
+		Expression *newExpr = findSingleExpression( whileStmt->get_condition(), indexer );
 		delete whileStmt->get_condition();
 		whileStmt->set_condition( newExpr );
-		Parent::visit( whileStmt );
-	}
-
-	void Resolver::visit( ForStmt *forStmt ) {
-		Parent::visit( forStmt );
-
+	}
+
+	void Resolver::previsit( ForStmt *forStmt ) {
 		if ( forStmt->get_condition() ) {
-			Expression * newExpr = findSingleExpression( forStmt->get_condition(), *this );
+			Expression * newExpr = findSingleExpression( forStmt->get_condition(), indexer );
 			delete forStmt->get_condition();
 			forStmt->set_condition( newExpr );
@@ -319,5 +306,5 @@
 
 		if ( forStmt->get_increment() ) {
-			Expression * newExpr = findVoidExpression( forStmt->get_increment(), *this );
+			Expression * newExpr = findVoidExpression( forStmt->get_increment(), indexer );
 			delete forStmt->get_increment();
 			forStmt->set_increment( newExpr );
@@ -325,21 +312,20 @@
 	}
 
-	void Resolver::visit( SwitchStmt *switchStmt ) {
-		ValueGuard< CurrentObject > oldCurrentObject( currentObject );
+	void Resolver::previsit( SwitchStmt *switchStmt ) {
+		GuardValue( currentObject );
 		Expression *newExpr;
-		newExpr = findIntegralExpression( switchStmt->get_condition(), *this );
+		newExpr = findIntegralExpression( switchStmt->get_condition(), indexer );
 		delete switchStmt->get_condition();
 		switchStmt->set_condition( newExpr );
 
 		currentObject = CurrentObject( newExpr->get_result() );
-		Parent::visit( switchStmt );
-	}
-
-	void Resolver::visit( CaseStmt *caseStmt ) {
+	}
+
+	void Resolver::previsit( CaseStmt *caseStmt ) {
 		if ( caseStmt->get_condition() ) {
 			std::list< InitAlternative > initAlts = currentObject.getOptions();
 			assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." );
 			CastExpr * castExpr = new CastExpr( caseStmt->get_condition(), initAlts.front().type->clone() );
-			Expression * newExpr = findSingleExpression( castExpr, *this );
+			Expression * newExpr = findSingleExpression( castExpr, indexer );
 			castExpr = strict_dynamic_cast< CastExpr * >( newExpr );
 			caseStmt->set_condition( castExpr->get_arg() );
@@ -347,8 +333,8 @@
 			delete castExpr;
 		}
-		Parent::visit( caseStmt );
-	}
-
-	void Resolver::visit( BranchStmt *branchStmt ) {
+	}
+
+	void Resolver::previsit( BranchStmt *branchStmt ) {
+		visit_children = false;
 		// must resolve the argument for a computed goto
 		if ( branchStmt->get_type() == BranchStmt::Goto ) { // check for computed goto statement
@@ -357,5 +343,5 @@
 				PointerType pt( Type::Qualifiers(), v.clone() );
 				CastExpr * castExpr = new CastExpr( arg, pt.clone() );
-				Expression * newExpr = findSingleExpression( castExpr, *this ); // find best expression
+				Expression * newExpr = findSingleExpression( castExpr, indexer ); // find best expression
 				branchStmt->set_target( newExpr );
 			} // if
@@ -363,8 +349,9 @@
 	}
 
-	void Resolver::visit( ReturnStmt *returnStmt ) {
+	void Resolver::previsit( ReturnStmt *returnStmt ) {
+		visit_children = false;
 		if ( returnStmt->get_expr() ) {
 			CastExpr *castExpr = new CastExpr( returnStmt->get_expr(), functionReturn->clone() );
-			Expression *newExpr = findSingleExpression( castExpr, *this );
+			Expression *newExpr = findSingleExpression( castExpr, indexer );
 			delete castExpr;
 			returnStmt->set_expr( newExpr );
@@ -372,9 +359,10 @@
 	}
 
-	void Resolver::visit( ThrowStmt *throwStmt ) {
+	void Resolver::previsit( ThrowStmt *throwStmt ) {
+		visit_children = false;
 		// TODO: Replace *exception type with &exception type.
 		if ( throwStmt->get_expr() ) {
 			StructDecl * exception_decl =
-				lookupStruct( "__cfaehm__base_exception_t" );
+				indexer.lookupStruct( "__cfaehm__base_exception_t" );
 			assert( exception_decl );
 			Expression * wrapped = new CastExpr(
@@ -388,15 +376,10 @@
 					)
 				);
-			Expression * newExpr = findSingleExpression( wrapped, *this );
+			Expression * newExpr = findSingleExpression( wrapped, indexer );
 			throwStmt->set_expr( newExpr );
 		}
 	}
 
-	void Resolver::visit( CatchStmt *catchStmt ) {
-		// inline Indexer::visit so that the exception variable is still in-scope for
-		// findSingleExpression() below
-		Parent::enterScope();
-		Visitor::visit( catchStmt );
-
+	void Resolver::previsit( CatchStmt *catchStmt ) {
 		if ( catchStmt->get_cond() ) {
 			Expression * wrapped = new CastExpr(
@@ -404,8 +387,6 @@
 				new BasicType( noQualifiers, BasicType::Bool )
 				);
-			catchStmt->set_cond( findSingleExpression( wrapped, *this ) );
-		}
-
-		Parent::leaveScope();
+			catchStmt->set_cond( findSingleExpression( wrapped, indexer ) );
+		}
 	}
 
@@ -419,8 +400,9 @@
 	}
 
-	void Resolver::visit( SingleInit *singleInit ) {
+	void Resolver::previsit( SingleInit *singleInit ) {
+		visit_children = false;
 		// resolve initialization using the possibilities as determined by the currentObject cursor
 		UntypedInitExpr * untyped = new UntypedInitExpr( singleInit->get_value(), currentObject.getOptions() );
-		Expression * newExpr = findSingleExpression( untyped, *this );
+		Expression * newExpr = findSingleExpression( untyped, indexer );
 		InitExpr * initExpr = strict_dynamic_cast< InitExpr * >( newExpr );
 
@@ -461,5 +443,6 @@
 	}
 
-	void Resolver::visit( ListInit * listInit ) {
+	void Resolver::previsit( ListInit * listInit ) {
+		visit_children = false;
 		// move cursor into brace-enclosed initializer-list
 		currentObject.enterListInit();
@@ -472,5 +455,5 @@
 			Initializer * init = std::get<1>(p);
 			newDesignations.push_back( currentObject.findNext( des ) );
-			init->accept( *this );
+			init->accept( *visitor );
 		}
 		// set the set of 'resolved' designations and leave the brace-enclosed initializer-list
@@ -501,5 +484,5 @@
 		delete ctorInit->get_dtor();
 		ctorInit->set_dtor( NULL );
-		maybeAccept( ctorInit->get_init(), *this );
+		maybeAccept( ctorInit->get_init(), *visitor );
 	}
 
@@ -507,5 +490,5 @@
 	void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) {
 		assert( ctorInit );
-		Resolver resolver( indexer );
+		PassVisitor<Resolver> resolver( indexer );
 		ctorInit->accept( resolver );
 	}
@@ -513,12 +496,13 @@
 	void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) {
 		assert( stmtExpr );
-		Resolver resolver( indexer );
+		PassVisitor<Resolver> resolver( indexer );
 		stmtExpr->accept( resolver );
 	}
 
-	void Resolver::visit( ConstructorInit *ctorInit ) {
+	void Resolver::previsit( ConstructorInit *ctorInit ) {
+		visit_children = false;
 		// xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
-		maybeAccept( ctorInit->get_ctor(), *this );
-		maybeAccept( ctorInit->get_dtor(), *this );
+		maybeAccept( ctorInit->get_ctor(), *visitor );
+		maybeAccept( ctorInit->get_dtor(), *visitor );
 
 		// found a constructor - can get rid of C-style initializer
