Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision cdbab558c7734aaa7ebe27165f8fc27f3514ad1a)
+++ src/ResolvExpr/Resolver.cc	(revision 305581dbced29c2fe6bb06909e03de5f7b8a6b9f)
@@ -75,5 +75,4 @@
 		void previsit( CatchStmt *catchStmt );
 		void previsit( WaitForStmt * stmt );
-		void previsit( WithStmt * withStmt );
 
 		void previsit( SingleInit *singleInit );
@@ -86,5 +85,4 @@
 		void handlePtrType( PtrType * type );
 
-		void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
 		void fallbackInit( ConstructorInit * ctorInit );
 
@@ -92,4 +90,11 @@
 		CurrentObject currentObject = nullptr;
 		bool inEnumDecl = false;
+	};
+
+	struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd {
+		void previsit( FunctionDecl * );
+		void previsit( WithStmt * );
+
+		void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
 	};
 
@@ -300,4 +305,55 @@
 	}
 
+
+	bool isStructOrUnion( const Alternative & alt ) {
+		Type * t = alt.expr->result->stripReferences();
+		return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
+	}
+
+	void resolveWithExprs( std::list< Declaration * > & translationUnit ) {
+		PassVisitor<ResolveWithExprs> resolver;
+		acceptAll( translationUnit, resolver );
+	}
+
+	void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
+		for ( Expression *& expr : withExprs )  {
+			// only struct- and union-typed expressions are viable candidates
+			findKindExpression( expr, indexer, "with statement", isStructOrUnion );
+
+			// if with expression might be impure, create a temporary so that it is evaluated once
+			if ( Tuples::maybeImpure( expr ) ) {
+				static UniqueName tmpNamer( "_with_tmp_" );
+				ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
+				expr = new VariableExpr( tmp );
+				newStmts.push_back( new DeclStmt( tmp ) );
+				if ( InitTweak::isConstructable( tmp->type ) ) {
+					// generate ctor/dtor and resolve them
+					tmp->init = InitTweak::genCtorInit( tmp );
+					tmp->accept( *visitor );
+				}
+			}
+		}
+	}
+
+	void ResolveWithExprs::previsit( WithStmt * withStmt ) {
+		resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
+	}
+
+	void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) {
+		{
+			// resolve with-exprs with parameters in scope and add any newly generated declarations to the
+			// front of the function body.
+			auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this](){ indexer.leaveScope(); } );
+			indexer.addFunctionType( functionDecl->type );
+			std::list< Statement * > newStmts;
+			resolveWithExprs( functionDecl->withExprs, newStmts );
+			if ( functionDecl->statements ) {
+				functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts );
+			} else {
+				assertf( functionDecl->withExprs.empty() && newStmts.empty(), "Function %s without a body has with-clause and/or generated with declarations.", functionDecl->name.c_str() );
+			}
+		}
+	}
+
 	void Resolver::previsit( ObjectDecl *objectDecl ) {
 		// To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that class-variable
@@ -338,18 +394,4 @@
 		GuardValue( functionReturn );
 		functionReturn = ResolvExpr::extractResultType( functionDecl->type );
-
-		{
-			// resolve with-exprs with parameters in scope and add any newly generated declarations to the
-			// front of the function body.
-			auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this](){ indexer.leaveScope(); } );
-			indexer.addFunctionType( functionDecl->type );
-			std::list< Statement * > newStmts;
-			resolveWithExprs( functionDecl->withExprs, newStmts );
-			if ( functionDecl->statements ) {
-				functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts );
-			} else {
-				assertf( functionDecl->withExprs.empty() && newStmts.empty(), "Function %s without a body has with-clause and/or generated with declarations.", functionDecl->name.c_str() );
-			}
-		}
 	}
 
@@ -682,33 +724,4 @@
 			stmt->orelse.statement->accept( *visitor );
 		}
-	}
-
-	bool isStructOrUnion( const Alternative & alt ) {
-		Type * t = alt.expr->result->stripReferences();
-		return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
-	}
-
-	void Resolver::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
-		for ( Expression *& expr : withExprs )  {
-			// only struct- and union-typed expressions are viable candidates
-			findKindExpression( expr, indexer, "with statement", isStructOrUnion );
-
-			// if with expression might be impure, create a temporary so that it is evaluated once
-			if ( Tuples::maybeImpure( expr ) ) {
-				static UniqueName tmpNamer( "_with_tmp_" );
-				ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
-				expr = new VariableExpr( tmp );
-				newStmts.push_back( new DeclStmt( tmp ) );
-				if ( InitTweak::isConstructable( tmp->type ) ) {
-					// generate ctor/dtor and resolve them
-					tmp->init = InitTweak::genCtorInit( tmp );
-					tmp->accept( *visitor );
-				}
-			}
-		}
-	}
-
-	void Resolver::previsit( WithStmt * withStmt ) {
-		resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
 	}
 
Index: src/ResolvExpr/Resolver.h
===================================================================
--- src/ResolvExpr/Resolver.h	(revision cdbab558c7734aaa7ebe27165f8fc27f3514ad1a)
+++ src/ResolvExpr/Resolver.h	(revision 305581dbced29c2fe6bb06909e03de5f7b8a6b9f)
@@ -38,4 +38,6 @@
 	/// Searches expr and returns the first DeletedExpr found, otherwise nullptr
 	DeletedExpr * findDeletedExpr( Expression * expr );
+	/// Resolves with-stmts and with-clauses on functions
+	void resolveWithExprs( std::list< Declaration * > & translationUnit );
 } // namespace ResolvExpr
 
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision cdbab558c7734aaa7ebe27165f8fc27f3514ad1a)
+++ src/SymTab/Validate.cc	(revision 305581dbced29c2fe6bb06909e03de5f7b8a6b9f)
@@ -322,4 +322,5 @@
 		Concurrency::implementThreadStarter( translationUnit );
 		mutateAll( translationUnit, compoundliteral );
+		ResolvExpr::resolveWithExprs( translationUnit ); // must happen before FixObjectType because user-code is resolved and may contain with variables
 		FixObjectType::fix( translationUnit );
 		ArrayLength::computeLength( translationUnit );
