Index: src/CodeTools/DeclStats.cc
===================================================================
--- src/CodeTools/DeclStats.cc	(revision 014450e33b5a1ecb7cc5da18bfb993f637575c59)
+++ src/CodeTools/DeclStats.cc	(revision e5c74d14db88d2ac040e770e4f6124f9017858ed)
@@ -23,4 +23,5 @@
 #include <utility>                 // for pair, make_pair
 
+#include "Common/PassVisitor.h"
 #include "Common/SemanticError.h"  // for SemanticError
 #include "Common/VectorMap.h"      // for VectorMap
@@ -35,5 +36,5 @@
 namespace CodeTools {
 
-	class DeclStats : public Visitor {
+	struct DeclStats : public WithShortCircuiting {
 		template<typename T>
 		static void sum(T& a, const T& b) { a += b; }
@@ -200,46 +201,39 @@
 
 	public:
-		using Visitor::visit;
-
-		virtual void visit( FunctionDecl *decl ) {
+		void previsit( FunctionDecl *decl ) {
 			// skip if already seen declaration for this function
-			const std::string& mangleName = decl->get_mangleName().empty() ? decl->get_name() : decl->get_mangleName();
-			if ( ! seen_names.insert( mangleName ).second ) {
-				maybeAccept( decl->get_statements(), *this );
-				return;
-			}
-
-			Stats& stats = for_linkage[ decl->get_linkage() ];
-
-			++stats.n_decls;
-			FunctionType* fnTy = decl->get_functionType();
-			const Type::ForallList& forall = fnTy->get_forall();
-			++stats.n_type_params.at( forall.size() );
-			unsigned n_assns = 0;
-			for ( TypeDecl* fdecl : forall ) {
-				n_assns += fdecl->get_assertions().size();
-				for ( DeclarationWithType* assn : fdecl->get_assertions() ) {
-					FunctionType *assnTy = 0;
-					if ( ObjectDecl *assnObj = dynamic_cast<ObjectDecl*>(assn) ) {
-						if ( PointerType *ptrTy = dynamic_cast<PointerType*>(assnObj->get_type()) ) {
-							assnTy = dynamic_cast<FunctionType*>(ptrTy->get_base());
-						} else assnTy = dynamic_cast<FunctionType*>(assnObj->get_type());
-					} else if ( FunctionDecl *assnDecl = dynamic_cast<FunctionDecl*>(assn) ) {
-						assnTy = assnDecl->get_functionType();
+			const std::string& mangleName = decl->get_mangleName().empty() ? decl->name : decl->get_mangleName();
+			if ( seen_names.insert( mangleName ).second ) {
+				Stats& stats = for_linkage[ decl->linkage ];
+
+				++stats.n_decls;
+				FunctionType* fnTy = decl->type;
+				const Type::ForallList& forall = fnTy->forall;
+				++stats.n_type_params.at( forall.size() );
+				unsigned n_assns = 0;
+				for ( TypeDecl* fdecl : forall ) {
+					n_assns += fdecl->assertions.size();
+					for ( DeclarationWithType* assn : fdecl->assertions ) {
+						FunctionType *assnTy = nullptr;
+						if ( ObjectDecl *assnObj = dynamic_cast<ObjectDecl*>(assn) ) {
+							if ( PointerType *ptrTy = dynamic_cast<PointerType*>(assnObj->get_type()) ) {
+								assnTy = dynamic_cast<FunctionType*>(ptrTy->get_base());
+							} else assnTy = dynamic_cast<FunctionType*>(assnObj->get_type());
+						} else if ( FunctionDecl *assnDecl = dynamic_cast<FunctionDecl*>(assn) ) {
+							assnTy = assnDecl->type;
+						}
+						if ( assnTy ) analyzeFunc( assnTy, stats, stats.assn_params, stats.assn_returns );
 					}
-					if ( assnTy ) analyzeFunc( assnTy, stats, stats.assn_params, stats.assn_returns );
-				}
-			}
-			++stats.n_assns[ n_assns ];
-
-			++stats.by_name[ decl->get_name() ];
-
-			analyzeFunc( fnTy, stats, stats.params, stats.returns );
-
-			// analyze expressions in decl statements
-			maybeAccept( decl->get_statements(), *this );
-		}
-
-		virtual void visit( UntypedExpr *expr ) {
+				}
+				++stats.n_assns[ n_assns ];
+
+				++stats.by_name[ decl->get_name() ];
+
+				analyzeFunc( fnTy, stats, stats.params, stats.returns );
+			}
+		}
+
+		void previsit( UntypedExpr *expr ) {
+			visit_children = false;
 			analyzeExpr( expr, 0 );
 		}
@@ -366,7 +360,7 @@
 
 	void printDeclStats( std::list< Declaration * > &translationUnit ) {
-		DeclStats stats;
+		PassVisitor<DeclStats> stats;
 		acceptAll( translationUnit, stats );
-		stats.print();
+		stats.pass.print();
 	}
 
