Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 93068e535c44a1666ca99eec1149cbb6591b517f)
+++ src/AST/Pass.hpp	(revision c6c682cfa1a2b3a58b9c8cde325953a89154db7a)
@@ -296,4 +296,5 @@
 private:
 	bool inFunction = false;
+	bool atFunctionTop = false;
 };
 
Index: src/AST/Pass.impl.hpp
===================================================================
--- src/AST/Pass.impl.hpp	(revision 93068e535c44a1666ca99eec1149cbb6591b517f)
+++ src/AST/Pass.impl.hpp	(revision c6c682cfa1a2b3a58b9c8cde325953a89154db7a)
@@ -502,8 +502,11 @@
 				// foralls are still in function type
 				maybe_accept( node, &FunctionDecl::type );
-				// function body needs to have the same scope as parameters - CompoundStmt will not enter
-				// a new scope if inFunction is true
+				// First remember that we are now within a function.
 				ValueGuard< bool > oldInFunction( inFunction );
 				inFunction = true;
+				// The function body needs to have the same scope as parameters.
+				// A CompoundStmt will not enter a new scope if atFunctionTop is true.
+				ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
+				atFunctionTop = true;
 				maybe_accept( node, &FunctionDecl::stmts );
 				maybe_accept( node, &FunctionDecl::attributes );
@@ -672,9 +675,9 @@
 	VISIT_START( node );
 	VISIT({
-		// do not enter a new scope if inFunction is true - needs to check old state before the assignment
-		auto guard1 = makeFuncGuard( [this, inFunctionCpy = this->inFunction]() {
-			if ( ! inFunctionCpy ) __pass::symtab::enter(core, 0);
-		}, [this, inFunctionCpy = this->inFunction]() {
-			if ( ! inFunctionCpy ) __pass::symtab::leave(core, 0);
+		// Do not enter (or leave) a new scope if atFunctionTop. Remember to save the result.
+		auto guard1 = makeFuncGuard( [this, enterScope = !this->atFunctionTop]() {
+			if ( enterScope ) __pass::symtab::enter(core, 0);
+		}, [this, leaveScope = !this->atFunctionTop]() {
+			if ( leaveScope ) __pass::symtab::leave(core, 0);
 		});
 		ValueGuard< bool > guard2( inFunction );
Index: src/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision 93068e535c44a1666ca99eec1149cbb6591b517f)
+++ src/Common/PassVisitor.h	(revision c6c682cfa1a2b3a58b9c8cde325953a89154db7a)
@@ -360,4 +360,5 @@
 private:
 	bool inFunction = false;
+	bool atFunctionTop = false;
 
 	template<typename pass_t> friend void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_t >& visitor );
@@ -532,5 +533,5 @@
 
 	bool isInFunction() const {
-		return visitor->inFunction;
+		return visitor->isInFunction();
 	}
 };
Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision 93068e535c44a1666ca99eec1149cbb6591b517f)
+++ src/Common/PassVisitor.impl.h	(revision c6c682cfa1a2b3a58b9c8cde325953a89154db7a)
@@ -532,8 +532,11 @@
 			indexerAddId( &func );
 			maybeAccept_impl( node->type, *this );
-			// function body needs to have the same scope as parameters - CompoundStmt will not enter
-			// a new scope if inFunction is true
+			// First remember that we are now within a function.
 			ValueGuard< bool > oldInFunction( inFunction );
 			inFunction = true;
+			// The function body needs to have the same scope as parameters.
+			// A CompoundStmt will not enter a new scope if atFunctionTop is true.
+			ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
+			atFunctionTop = true;
 			maybeAccept_impl( node->statements, *this );
 			maybeAccept_impl( node->attributes, *this );
@@ -567,8 +570,11 @@
 			indexerAddId( &func );
 			maybeAccept_impl( node->type, *this );
-			// function body needs to have the same scope as parameters - CompoundStmt will not enter
-			// a new scope if inFunction is true
+			// First remember that we are now within a function.
 			ValueGuard< bool > oldInFunction( inFunction );
 			inFunction = true;
+			// The function body needs to have the same scope as parameters.
+			// A CompoundStmt will not enter a new scope if atFunctionTop is true.
+			ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
+			atFunctionTop = true;
 			maybeAccept_impl( node->statements, *this );
 			maybeAccept_impl( node->attributes, *this );
@@ -601,8 +607,11 @@
 			indexerAddId( &func );
 			maybeMutate_impl( node->type, *this );
-			// function body needs to have the same scope as parameters - CompoundStmt will not enter
-			// a new scope if inFunction is true
+			// First remember that we are now within a function.
 			ValueGuard< bool > oldInFunction( inFunction );
 			inFunction = true;
+			// The function body needs to have the same scope as parameters.
+			// A CompoundStmt will not enter a new scope if atFunctionTop is true.
+			ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
+			atFunctionTop = true;
 			maybeMutate_impl( node->statements, *this );
 			maybeMutate_impl( node->attributes, *this );
@@ -1007,9 +1016,9 @@
 	VISIT_START( node );
 	{
-		// do not enter a new scope if inFunction is true - needs to check old state before the assignment
-		ValueGuard< bool > oldInFunction( inFunction );
-		auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
+		// Do not enter a new scope if atFunctionTop is true, don't leave one either.
+		ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
+		auto guard1 = makeFuncGuard( [this, go = !atFunctionTop]() { if ( go ) indexerScopeEnter(); }, [this, go = !atFunctionTop]() { if ( go ) indexerScopeLeave(); } );
 		auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
-		inFunction = false;
+		atFunctionTop = false;
 		visitStatementList( node->kids );
 	}
@@ -1021,9 +1030,9 @@
 	VISIT_START( node );
 	{
-		// do not enter a new scope if inFunction is true - needs to check old state before the assignment
-		ValueGuard< bool > oldInFunction( inFunction );
-		auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
+		// Do not enter a new scope if atFunctionTop is true, don't leave one either.
+		ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
+		auto guard1 = makeFuncGuard( [this, go = !atFunctionTop]() { if ( go ) indexerScopeEnter(); }, [this, go = !atFunctionTop]() { if ( go ) indexerScopeLeave(); } );
 		auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
-		inFunction = false;
+		atFunctionTop = false;
 		visitStatementList( node->kids );
 	}
@@ -1035,9 +1044,9 @@
 	MUTATE_START( node );
 	{
-		// do not enter a new scope if inFunction is true - needs to check old state before the assignment
-		ValueGuard< bool > oldInFunction( inFunction );
-		auto guard1 = makeFuncGuard( [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeEnter(); }, [this, &oldInFunction]() { if ( ! oldInFunction.old ) indexerScopeLeave(); } );
+		// Do not enter a new scope if atFunctionTop is true, don't leave one either.
+		ValueGuard< bool > oldAtFunctionTop( atFunctionTop );
+		auto guard1 = makeFuncGuard( [this, go = !atFunctionTop]() { if ( go ) indexerScopeEnter(); }, [this, go = !atFunctionTop]() { if ( go ) indexerScopeLeave(); } );
 		auto guard2 = makeFuncGuard( [this]() { call_beginScope();   }, [this]() { call_endScope();     } );
-		inFunction = false;
+		atFunctionTop = false;
 		mutateStatementList( node->kids );
 	}
