Index: src/AST/Convert.cpp
===================================================================
--- src/AST/Convert.cpp	(revision 9d8124f79ccec28447cabfc84649853818e887f2)
+++ src/AST/Convert.cpp	(revision 39d89504881cd88008aec5648412e27d45b19c6e)
@@ -9,7 +9,7 @@
 // Author           : Thierry Delisle
 // Created On       : Thu May 09 15::37::05 2019
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Wed Feb  2 13:19:22 2022
-// Update Count     : 41
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Mar 16 15:01:00 2022
+// Update Count     : 42
 //
 
@@ -49,14 +49,11 @@
 //================================================================================================
 namespace ast {
-
-// This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not)
-// allow us to use the same stratagy in the new ast.
-// xxx - since convert back pass works, this concern seems to be unnecessary.
-
-// these need to be accessed in new FixInit now
-ast::ptr<ast::Type> sizeType = nullptr;
-const ast::FunctionDecl * dereferenceOperator = nullptr;
-const ast::StructDecl   * dtorStruct = nullptr;
-const ast::FunctionDecl * dtorStructDestroy = nullptr;
+// These are the shared local information used by ConverterNewToOld and
+// ConverterOldToNew to update the global information in the two versions.
+
+static ast::ptr<ast::Type> sizeType = nullptr;
+static const ast::FunctionDecl * dereferenceOperator = nullptr;
+static const ast::StructDecl   * dtorStruct = nullptr;
+static const ast::FunctionDecl * dtorStructDestroy = nullptr;
 
 }
Index: src/AST/Fwd.hpp
===================================================================
--- src/AST/Fwd.hpp	(revision 9d8124f79ccec28447cabfc84649853818e887f2)
+++ src/AST/Fwd.hpp	(revision 39d89504881cd88008aec5648412e27d45b19c6e)
@@ -141,9 +141,5 @@
 
 class TranslationUnit;
-// TODO: Get from the TranslationUnit:
-extern ptr<Type> sizeType;
-extern const FunctionDecl * dereferenceOperator;
-extern const StructDecl   * dtorStruct;
-extern const FunctionDecl * dtorStructDestroy;
+class TranslationGlobal;
 
 }
Index: src/AST/TranslationUnit.hpp
===================================================================
--- src/AST/TranslationUnit.hpp	(revision 9d8124f79ccec28447cabfc84649853818e887f2)
+++ src/AST/TranslationUnit.hpp	(revision 39d89504881cd88008aec5648412e27d45b19c6e)
@@ -10,6 +10,6 @@
 // Created On       : Tue Jun 11 15:30:00 2019
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue Jun 11 15:42:00 2019
-// Update Count     : 0
+// Last Modified On : Tue Mar 11 11:19:00 2022
+// Update Count     : 1
 //
 
@@ -23,16 +23,18 @@
 namespace ast {
 
+class TranslationGlobal {
+public:
+	std::map< UniqueId, Decl * > idMap;
+
+	ptr<Type> sizeType;
+	const FunctionDecl * dereference;
+	const StructDecl * dtorStruct;
+	const FunctionDecl * dtorDestroy;
+};
+
 class TranslationUnit {
 public:
 	std::list< ptr< Decl > > decls;
-
-	struct Global {
-		std::map< UniqueId, Decl * > idMap;
-
-		ptr<Type> sizeType;
-		const FunctionDecl * dereference;
-		const StructDecl * dtorStruct;
-		const FunctionDecl * dtorDestroy;
-	} global;
+	TranslationGlobal global;
 };
 
Index: src/InitTweak/FixInitNew.cpp
===================================================================
--- src/InitTweak/FixInitNew.cpp	(revision 9d8124f79ccec28447cabfc84649853818e887f2)
+++ src/InitTweak/FixInitNew.cpp	(revision 39d89504881cd88008aec5648412e27d45b19c6e)
@@ -86,5 +86,5 @@
 	/// generate/resolve copy construction expressions for each, and generate/resolve destructors for both
 	/// arguments and return value temporaries
-	struct ResolveCopyCtors final : public ast::WithGuards, public ast::WithStmtsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithVisitorRef<ResolveCopyCtors> {
+	struct ResolveCopyCtors final : public ast::WithGuards, public ast::WithStmtsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithVisitorRef<ResolveCopyCtors>, public ast::WithConstTranslationUnit {
 		const ast::Expr * postvisit( const ast::ImplicitCopyCtorExpr * impCpCtorExpr );
 		const ast::StmtExpr * previsit( const ast::StmtExpr * stmtExpr );
@@ -190,5 +190,5 @@
 	/// for any member that is missing a corresponding ctor/dtor call.
 	/// error if a member is used before constructed
-	struct GenStructMemberCalls final : public ast::WithGuards, public ast::WithShortCircuiting, public ast::WithSymbolTable, public ast::WithVisitorRef<GenStructMemberCalls> {
+	struct GenStructMemberCalls final : public ast::WithGuards, public ast::WithShortCircuiting, public ast::WithSymbolTable, public ast::WithVisitorRef<GenStructMemberCalls>, public ast::WithConstTranslationUnit {
 		void previsit( const ast::FunctionDecl * funcDecl );
 		const ast::DeclWithType * postvisit( const ast::FunctionDecl * funcDecl );
@@ -215,5 +215,5 @@
 
 	/// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument
-	struct FixCtorExprs final : public ast::WithDeclsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting {
+	struct FixCtorExprs final : public ast::WithDeclsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithConstTranslationUnit {
 		const ast::Expr * postvisit( const ast::ConstructorExpr * ctorExpr );
 	};
@@ -510,5 +510,5 @@
 		// (VariableExpr and already resolved expression)
 		CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )
-		ast::ptr<ast::Expr> resolved = ResolvExpr::findVoidExpression(untyped, symtab);
+		ast::ptr<ast::Expr> resolved = ResolvExpr::findVoidExpression(untyped, { symtab, transUnit().global } );
 		assert( resolved );
 		if ( resolved->env ) {
@@ -588,11 +588,12 @@
 
 	ast::Expr * ResolveCopyCtors::destructRet( const ast::ObjectDecl * ret, const ast::Expr * arg ) {
+		auto global = transUnit().global;
 		// TODO: refactor code for generating cleanup attribute, since it's common and reused in ~3-4 places
 		// check for existing cleanup attribute before adding another(?)
 		// need to add __Destructor for _tmp_cp variables as well
 
-		assertf( ast::dtorStruct, "Destructor generation requires __Destructor definition." );
-		assertf( ast::dtorStruct->members.size() == 2, "__Destructor definition does not have expected fields." );
-		assertf( ast::dtorStructDestroy, "Destructor generation requires __destroy_Destructor." );
+		assertf( global.dtorStruct, "Destructor generation requires __Destructor definition." );
+		assertf( global.dtorStruct->members.size() == 2, "__Destructor definition does not have expected fields." );
+		assertf( global.dtorDestroy, "Destructor generation requires __destroy_Destructor." );
 
 		const CodeLocation loc = ret->location;
@@ -611,5 +612,5 @@
 		auto dtorFunc = getDtorFunc( ret, new ast::ExprStmt(loc, dtor ), stmtsToAddBefore );
 
-		auto dtorStructType = new ast::StructInstType(ast::dtorStruct);
+		auto dtorStructType = new ast::StructInstType( global.dtorStruct );
 
 		// what does this do???
@@ -623,9 +624,9 @@
 		static UniqueName namer( "_ret_dtor" );
 		auto retDtor = new ast::ObjectDecl(loc, namer.newName(), dtorStructType, new ast::ListInit(loc, { new ast::SingleInit(loc, ast::ConstantExpr::null(loc) ), new ast::SingleInit(loc, new ast::CastExpr( new ast::VariableExpr(loc, dtorFunc ), dtorType ) ) } ) );
-		retDtor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr(loc, ast::dtorStructDestroy ) } ) );
+		retDtor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr(loc, global.dtorDestroy ) } ) );
 		stmtsToAddBefore.push_back( new ast::DeclStmt(loc, retDtor ) );
 
 		if ( arg ) {
-			auto member = new ast::MemberExpr(loc, ast::dtorStruct->members.front().strict_as<ast::DeclWithType>(), new ast::VariableExpr(loc, retDtor ) );
+			auto member = new ast::MemberExpr(loc, global.dtorStruct->members.front().strict_as<ast::DeclWithType>(), new ast::VariableExpr(loc, retDtor ) );
 			auto object = new ast::CastExpr( new ast::AddressExpr( new ast::VariableExpr(loc, ret ) ), new ast::PointerType(new ast::VoidType() ) );
 			ast::Expr * assign = createBitwiseAssignment( member, object );
@@ -1179,4 +1180,5 @@
 			auto guard = makeFuncGuard( [this]() { symtab.enterScope(); }, [this]() { symtab.leaveScope(); } );
 			symtab.addFunction( function );
+			auto global = transUnit().global;
 
 			// need to iterate through members in reverse in order for
@@ -1224,6 +1226,6 @@
 
 							static UniqueName memberDtorNamer = { "__memberDtor" };
-							assertf( ast::dtorStruct, "builtin __Destructor not found." );
-							assertf( ast::dtorStructDestroy, "builtin __destroy_Destructor not found." );
+							assertf( global.dtorStruct, "builtin __Destructor not found." );
+							assertf( global.dtorDestroy, "builtin __destroy_Destructor not found." );
 
 							ast::Expr * thisExpr = new ast::CastExpr( new ast::AddressExpr( new ast::VariableExpr(loc, thisParam ) ), new ast::PointerType( new ast::VoidType(), ast::CV::Qualifiers() ) );
@@ -1235,6 +1237,6 @@
 							auto dtorType = new ast::PointerType( dtorFtype );
 
-							auto destructor = new ast::ObjectDecl(loc, memberDtorNamer.newName(), new ast::StructInstType( ast::dtorStruct ), new ast::ListInit(loc, { new ast::SingleInit(loc, thisExpr ), new ast::SingleInit(loc, new ast::CastExpr( dtorExpr, dtorType ) ) } ) );
-							destructor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr( loc, ast::dtorStructDestroy ) } ) );
+							auto destructor = new ast::ObjectDecl(loc, memberDtorNamer.newName(), new ast::StructInstType( global.dtorStruct ), new ast::ListInit(loc, { new ast::SingleInit(loc, thisExpr ), new ast::SingleInit(loc, new ast::CastExpr( dtorExpr, dtorType ) ) } ) );
+							destructor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr( loc, global.dtorDestroy ) } ) );
 							mutStmts->push_front( new ast::DeclStmt(loc, destructor ) );
 							mutStmts->kids.splice( mutStmts->kids.begin(), stmtsToAdd );
@@ -1331,5 +1333,5 @@
 	const ast::Expr * GenStructMemberCalls::postvisit( const ast::UntypedExpr * untypedExpr ) {
 		// xxx - functions returning ast::ptr seems wrong...
-		auto res = ResolvExpr::findVoidExpression( untypedExpr, symtab );
+		auto res = ResolvExpr::findVoidExpression( untypedExpr, { symtab, transUnit().global } );
 		// Fix CodeLocation (at least until resolver is fixed).
 		auto fix = localFillCodeLocations( untypedExpr->location, res.release() );
@@ -1368,5 +1370,5 @@
 
 		// resolve assignment and dispose of new env
-		auto resolved = ResolvExpr::findVoidExpression( assign, symtab );
+		auto resolved = ResolvExpr::findVoidExpression( assign, { symtab, transUnit().global } );
 		auto mut = resolved.get_and_mutate();
 		assertf(resolved.get() == mut, "newly resolved expression must be unique");
Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision 9d8124f79ccec28447cabfc84649853818e887f2)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision 39d89504881cd88008aec5648412e27d45b19c6e)
@@ -10,6 +10,6 @@
 // Created On       : Wed Jun 5 14:30:00 2019
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue Oct  1 14:55:00 2019
-// Update Count     : 2
+// Last Modified On : Wed Mar 16 11:58:00 2022
+// Update Count     : 3
 //
 
@@ -595,4 +595,5 @@
 	/// Actually visits expressions to find their candidate interpretations
 	class Finder final : public ast::WithShortCircuiting {
+		const ResolveContext & context;
 		const ast::SymbolTable & symtab;
 	public:
@@ -618,6 +619,6 @@
 
 		Finder( CandidateFinder & f )
-		: symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
-		  targetType( f.targetType ) {}
+		: context( f.context ), symtab( context.symtab ), selfFinder( f ),
+		  candidates( f.candidates ), tenv( f.env ), targetType( f.targetType ) {}
 
 		void previsit( const ast::Node * ) { visit_children = false; }
@@ -872,5 +873,5 @@
 			Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates );
 
-			CandidateFinder funcFinder{ symtab, tenv };
+			CandidateFinder funcFinder( context, tenv );
 			if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) {
 				auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);
@@ -918,5 +919,5 @@
 			// find function operators
 			ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" };
-			CandidateFinder opFinder{ symtab, tenv };
+			CandidateFinder opFinder( context, tenv );
 			// okay if there aren't any function operations
 			opFinder.find( opExpr, ResolvMode::withoutFailFast() );
@@ -1059,5 +1060,5 @@
 
 		void postvisit( const ast::AddressExpr * addressExpr ) {
-			CandidateFinder finder{ symtab, tenv };
+			CandidateFinder finder( context, tenv );
 			finder.find( addressExpr->arg );
 
@@ -1079,9 +1080,9 @@
 			ast::ptr< ast::Type > toType = castExpr->result;
 			assert( toType );
-			toType = resolveTypeof( toType, symtab );
+			toType = resolveTypeof( toType, context );
 			// toType = SymTab::validateType( castExpr->location, toType, symtab );
 			toType = adjustExprType( toType, tenv, symtab );
 
-			CandidateFinder finder{ symtab, tenv, toType };
+			CandidateFinder finder( context, tenv, toType );
 			finder.find( castExpr->arg, ResolvMode::withAdjustment() );
 
@@ -1136,5 +1137,5 @@
 		void postvisit( const ast::VirtualCastExpr * castExpr ) {
 			assertf( castExpr->result, "Implicit virtual cast targets not yet supported." );
-			CandidateFinder finder{ symtab, tenv };
+			CandidateFinder finder( context, tenv );
 			// don't prune here, all alternatives guaranteed to have same type
 			finder.find( castExpr->arg, ResolvMode::withoutPrune() );
@@ -1153,5 +1154,5 @@
 			auto target = inst->base.get();
 
-			CandidateFinder finder{ symtab, tenv };
+			CandidateFinder finder( context, tenv );
 
 			auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) {
@@ -1202,5 +1203,5 @@
 
 		void postvisit( const ast::UntypedMemberExpr * memberExpr ) {
-			CandidateFinder aggFinder{ symtab, tenv };
+			CandidateFinder aggFinder( context, tenv );
 			aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
 			for ( CandidateRef & agg : aggFinder.candidates ) {
@@ -1287,9 +1288,9 @@
 				addCandidate(
 					new ast::SizeofExpr{
-						sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
+						sizeofExpr->location, resolveTypeof( sizeofExpr->type, context ) },
 					tenv );
 			} else {
 				// find all candidates for the argument to sizeof
-				CandidateFinder finder{ symtab, tenv };
+				CandidateFinder finder( context, tenv );
 				finder.find( sizeofExpr->expr );
 				// find the lowest-cost candidate, otherwise ambiguous
@@ -1311,9 +1312,9 @@
 				addCandidate(
 					new ast::AlignofExpr{
-						alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
+						alignofExpr->location, resolveTypeof( alignofExpr->type, context ) },
 					tenv );
 			} else {
 				// find all candidates for the argument to alignof
-				CandidateFinder finder{ symtab, tenv };
+				CandidateFinder finder( context, tenv );
 				finder.find( alignofExpr->expr );
 				// find the lowest-cost candidate, otherwise ambiguous
@@ -1354,9 +1355,9 @@
 
 		void postvisit( const ast::LogicalExpr * logicalExpr ) {
-			CandidateFinder finder1{ symtab, tenv };
+			CandidateFinder finder1( context, tenv );
 			finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() );
 			if ( finder1.candidates.empty() ) return;
 
-			CandidateFinder finder2{ symtab, tenv };
+			CandidateFinder finder2( context, tenv );
 			finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );
 			if ( finder2.candidates.empty() ) return;
@@ -1384,15 +1385,15 @@
 		void postvisit( const ast::ConditionalExpr * conditionalExpr ) {
 			// candidates for condition
-			CandidateFinder finder1{ symtab, tenv };
+			CandidateFinder finder1( context, tenv );
 			finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() );
 			if ( finder1.candidates.empty() ) return;
 
 			// candidates for true result
-			CandidateFinder finder2{ symtab, tenv };
+			CandidateFinder finder2( context, tenv );
 			finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() );
 			if ( finder2.candidates.empty() ) return;
 
 			// candidates for false result
-			CandidateFinder finder3{ symtab, tenv };
+			CandidateFinder finder3( context, tenv );
 			finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
 			if ( finder3.candidates.empty() ) return;
@@ -1445,7 +1446,7 @@
 		void postvisit( const ast::CommaExpr * commaExpr ) {
 			ast::TypeEnvironment env{ tenv };
-			ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
-
-			CandidateFinder finder2{ symtab, env };
+			ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, context, env );
+
+			CandidateFinder finder2( context, env );
 			finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
 
@@ -1460,5 +1461,5 @@
 
 		void postvisit( const ast::ConstructorExpr * ctorExpr ) {
-			CandidateFinder finder{ symtab, tenv };
+			CandidateFinder finder( context, tenv );
 			finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() );
 			for ( CandidateRef & r : finder.candidates ) {
@@ -1469,9 +1470,9 @@
 		void postvisit( const ast::RangeExpr * rangeExpr ) {
 			// resolve low and high, accept candidates where low and high types unify
-			CandidateFinder finder1{ symtab, tenv };
+			CandidateFinder finder1( context, tenv );
 			finder1.find( rangeExpr->low, ResolvMode::withAdjustment() );
 			if ( finder1.candidates.empty() ) return;
 
-			CandidateFinder finder2{ symtab, tenv };
+			CandidateFinder finder2( context, tenv );
 			finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );
 			if ( finder2.candidates.empty() ) return;
@@ -1549,5 +1550,5 @@
 
 		void postvisit( const ast::UniqueExpr * unqExpr ) {
-			CandidateFinder finder{ symtab, tenv };
+			CandidateFinder finder( context, tenv );
 			finder.find( unqExpr->expr, ResolvMode::withAdjustment() );
 			for ( CandidateRef & r : finder.candidates ) {
@@ -1558,5 +1559,5 @@
 
 		void postvisit( const ast::StmtExpr * stmtExpr ) {
-			addCandidate( resolveStmtExpr( stmtExpr, symtab ), tenv );
+			addCandidate( resolveStmtExpr( stmtExpr, context ), tenv );
 		}
 
@@ -1570,5 +1571,5 @@
 			for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) {
 				// calculate target type
-				const ast::Type * toType = resolveTypeof( initAlt.type, symtab );
+				const ast::Type * toType = resolveTypeof( initAlt.type, context );
 				// toType = SymTab::validateType( initExpr->location, toType, symtab );
 				toType = adjustExprType( toType, tenv, symtab );
@@ -1576,5 +1577,5 @@
 				// types are not bound to the initialization type, since return type variables are
 				// only open for the duration of resolving the UntypedExpr.
-				CandidateFinder finder{ symtab, tenv, toType };
+				CandidateFinder finder( context, tenv, toType );
 				finder.find( initExpr->expr, ResolvMode::withAdjustment() );
 				for ( CandidateRef & cand : finder.candidates ) {
@@ -1693,5 +1694,5 @@
 		}
 		else {
-			satisfyAssertions(candidate, localSyms, satisfied, errors);
+			satisfyAssertions(candidate, context.symtab, satisfied, errors);
 			needRecomputeKey = true;
 		}
@@ -1855,5 +1856,5 @@
 			r->expr = ast::mutate_field(
 				r->expr.get(), &ast::Expr::result,
-				adjustExprType( r->expr->result, r->env, localSyms ) );
+				adjustExprType( r->expr->result, r->env, context.symtab ) );
 		}
 	}
@@ -1873,5 +1874,5 @@
 
 	for ( const auto & x : xs ) {
-		out.emplace_back( localSyms, env );
+		out.emplace_back( context, env );
 		out.back().find( x, ResolvMode::withAdjustment() );
 
Index: src/ResolvExpr/CandidateFinder.hpp
===================================================================
--- src/ResolvExpr/CandidateFinder.hpp	(revision 9d8124f79ccec28447cabfc84649853818e887f2)
+++ src/ResolvExpr/CandidateFinder.hpp	(revision 39d89504881cd88008aec5648412e27d45b19c6e)
@@ -10,6 +10,6 @@
 // Created On       : Wed Jun 5 14:30:00 2019
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue Oct  1  9:51:00 2019
-// Update Count     : 2
+// Last Modified On : Wed Mar 16 15:22:00 2022
+// Update Count     : 3
 //
 
@@ -25,8 +25,10 @@
 namespace ResolvExpr {
 
+struct ResolveContext;
+
 /// Data to perform expression resolution
 struct CandidateFinder {
 	CandidateList candidates;          ///< List of candidate resolutions
-	const ast::SymbolTable & localSyms;   ///< Symbol table to lookup candidates
+	const ResolveContext & context;  ///< Information about where the canditates are being found.
 	const ast::TypeEnvironment & env;  ///< Substitutions performed in this resolution
 	ast::ptr< ast::Type > targetType;  ///< Target type for resolution
@@ -34,7 +36,7 @@
 
 	CandidateFinder(
-		const ast::SymbolTable & syms, const ast::TypeEnvironment & env,
+		const ResolveContext & context, const ast::TypeEnvironment & env,
 		const ast::Type * tt = nullptr )
-	: candidates(), localSyms( syms ), env( env ), targetType( tt ) {}
+	: candidates(), context( context ), env( env ), targetType( tt ) {}
 
 	/// Fill candidates with feasible resolutions for `expr`
Index: src/ResolvExpr/CandidatePrinter.cpp
===================================================================
--- src/ResolvExpr/CandidatePrinter.cpp	(revision 9d8124f79ccec28447cabfc84649853818e887f2)
+++ src/ResolvExpr/CandidatePrinter.cpp	(revision 39d89504881cd88008aec5648412e27d45b19c6e)
@@ -10,6 +10,6 @@
 // Created On       : Tue Nov  9  9:54:00 2021
 // Last Modified By : Andrew Beach
-// Last Modified On : Tue Nov  9 15:47:00 2021
-// Update Count     : 0
+// Last Modified On : Wed Mar 16 13:56:00 2022
+// Update Count     : 1
 //
 
@@ -22,4 +22,5 @@
 #include "AST/TranslationUnit.hpp"
 #include "ResolvExpr/CandidateFinder.hpp"
+#include "ResolvExpr/Resolver.h"
 
 #include <iostream>
@@ -29,5 +30,6 @@
 namespace {
 
-class CandidatePrintCore : public ast::WithSymbolTable {
+class CandidatePrintCore : public ast::WithSymbolTable,
+		public ast::WithConstTranslationUnit {
 	std::ostream & os;
 public:
@@ -36,5 +38,5 @@
 	void postvisit( const ast::ExprStmt * stmt ) {
 		ast::TypeEnvironment env;
-		CandidateFinder finder( symtab, env );
+		CandidateFinder finder( { symtab, transUnit().global }, env );
 		finder.find( stmt->expr, ResolvMode::withAdjustment() );
 		int count = 1;
Index: src/ResolvExpr/ResolveTypeof.cc
===================================================================
--- src/ResolvExpr/ResolveTypeof.cc	(revision 9d8124f79ccec28447cabfc84649853818e887f2)
+++ src/ResolvExpr/ResolveTypeof.cc	(revision 39d89504881cd88008aec5648412e27d45b19c6e)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 12:12:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue May 19 16:49:04 2015
-// Update Count     : 3
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Mar 16 16:09:00 2022
+// Update Count     : 4
 //
 
@@ -22,4 +22,5 @@
 #include "AST/Node.hpp"
 #include "AST/Pass.hpp"
+#include "AST/TranslationUnit.hpp"
 #include "AST/Type.hpp"
 #include "AST/TypeEnvironment.hpp"
@@ -119,7 +120,8 @@
 namespace {
 	struct ResolveTypeof_new : public ast::WithShortCircuiting {
-		const ast::SymbolTable & localSymtab;
-
-		ResolveTypeof_new( const ast::SymbolTable & syms ) : localSymtab( syms ) {}
+		const ResolveContext & context;
+
+		ResolveTypeof_new( const ResolveContext & context ) :
+			context( context ) {}
 
 		void previsit( const ast::TypeofType * ) { visit_children = false; }
@@ -137,5 +139,5 @@
 				ast::TypeEnvironment dummy;
 				ast::ptr< ast::Expr > newExpr =
-					resolveInVoidContext( typeofType->expr, localSymtab, dummy );
+					resolveInVoidContext( typeofType->expr, context, dummy );
 				assert( newExpr->result && ! newExpr->result->isVoid() );
 				newType = newExpr->result;
@@ -161,6 +163,6 @@
 } // anonymous namespace
 
-const ast::Type * resolveTypeof( const ast::Type * type , const ast::SymbolTable & symtab ) {
-	ast::Pass< ResolveTypeof_new > mutator{ symtab };
+const ast::Type * resolveTypeof( const ast::Type * type , const ResolveContext & context ) {
+	ast::Pass< ResolveTypeof_new > mutator( context );
 	return type->accept( mutator );
 }
@@ -168,12 +170,13 @@
 struct FixArrayDimension {
 	// should not require a mutable symbol table - prevent pass template instantiation
-	const ast::SymbolTable & _symtab; 
-	FixArrayDimension(const ast::SymbolTable & symtab): _symtab(symtab) {}
+	const ResolveContext & context;
+	FixArrayDimension(const ResolveContext & context) : context( context ) {}
 
 	const ast::ArrayType * previsit (const ast::ArrayType * arrayType) {
 		if (!arrayType->dimension) return arrayType;
 		auto mutType = mutate(arrayType);
-		ast::ptr<ast::Type> sizetype = ast::sizeType ? ast::sizeType : new ast::BasicType(ast::BasicType::LongUnsignedInt); 
-		mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, _symtab);
+		auto globalSizeType = context.global.sizeType;
+		ast::ptr<ast::Type> sizetype = globalSizeType ? globalSizeType : new ast::BasicType(ast::BasicType::LongUnsignedInt);
+		mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, context );
 
 		if (InitTweak::isConstExpr(mutType->dimension)) {
@@ -187,14 +190,14 @@
 };
 
-const ast::Type * fixArrayType( const ast::Type * type, const ast::SymbolTable & symtab) {
-	ast::Pass<FixArrayDimension> visitor {symtab};
+const ast::Type * fixArrayType( const ast::Type * type, const ResolveContext & context ) {
+	ast::Pass<FixArrayDimension> visitor(context);
 	return type->accept(visitor);
 }
 
-const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ast::SymbolTable & symtab ) {
-	if (!decl->isTypeFixed) { 
+const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & context ) {
+	if (!decl->isTypeFixed) {
 		auto mutDecl = mutate(decl);
-		auto resolvedType = resolveTypeof(decl->type, symtab);
-		resolvedType = fixArrayType(resolvedType, symtab);
+		auto resolvedType = resolveTypeof(decl->type, context);
+		resolvedType = fixArrayType(resolvedType, context);
 		mutDecl->type = resolvedType;
 
Index: src/ResolvExpr/ResolveTypeof.h
===================================================================
--- src/ResolvExpr/ResolveTypeof.h	(revision 9d8124f79ccec28447cabfc84649853818e887f2)
+++ src/ResolvExpr/ResolveTypeof.h	(revision 39d89504881cd88008aec5648412e27d45b19c6e)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 12:14:53 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Sat Jul 22 09:38:35 2017
-// Update Count     : 3
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Mar 16 11:33:00 2022
+// Update Count     : 4
 //
 
@@ -22,12 +22,13 @@
 namespace ast {
 	class Type;
-	class SymbolTable;
 	class ObjectDecl;
 }
 
 namespace ResolvExpr {
+	struct ResolveContext;
+
 	Type *resolveTypeof( Type*, const SymTab::Indexer &indexer );
-	const ast::Type * resolveTypeof( const ast::Type *, const ast::SymbolTable & );
-	const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ast::SymbolTable & symtab );
+	const ast::Type * resolveTypeof( const ast::Type *, const ResolveContext & );
+	const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & );
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 9d8124f79ccec28447cabfc84649853818e887f2)
+++ src/ResolvExpr/Resolver.cc	(revision 39d89504881cd88008aec5648412e27d45b19c6e)
@@ -9,7 +9,7 @@
 // Author           : Aaron B. Moss
 // Created On       : Sun May 17 12:17:01 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Tue Feb  1 16:27:14 2022
-// Update Count     : 245
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Mar 16 16:07:00 2022
+// Update Count     : 246
 //
 
@@ -997,5 +997,5 @@
 		/// Calls the CandidateFinder and finds the single best candidate
 		CandidateRef findUnfinishedKindExpression(
-			const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,
+			const ast::Expr * untyped, const ResolveContext & context, const std::string & kind,
 			std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {}
 		) {
@@ -1007,5 +1007,5 @@
 			++recursion_level;
 			ast::TypeEnvironment env;
-			CandidateFinder finder{ symtab, env };
+			CandidateFinder finder( context, env );
 			finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
 			--recursion_level;
@@ -1129,5 +1129,6 @@
 
 	ast::ptr< ast::Expr > resolveInVoidContext(
-		const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env
+		const ast::Expr * expr, const ResolveContext & context,
+		ast::TypeEnvironment & env
 	) {
 		assertf( expr, "expected a non-null expression" );
@@ -1136,5 +1137,5 @@
 		ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
 		CandidateRef choice = findUnfinishedKindExpression(
-			untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
+			untyped, context, "", anyCandidate, ResolvMode::withAdjustment() );
 
 		// a cast expression has either 0 or 1 interpretations (by language rules);
@@ -1149,8 +1150,8 @@
 		/// context.
 		ast::ptr< ast::Expr > findVoidExpression(
-			const ast::Expr * untyped, const ast::SymbolTable & symtab
+			const ast::Expr * untyped, const ResolveContext & context
 		) {
 			ast::TypeEnvironment env;
-			ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env );
+			ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, context, env );
 			finishExpr( newExpr, env, untyped->env );
 			return newExpr;
@@ -1163,5 +1164,5 @@
 		/// lowest cost, returning the resolved version
 		ast::ptr< ast::Expr > findKindExpression(
-			const ast::Expr * untyped, const ast::SymbolTable & symtab,
+			const ast::Expr * untyped, const ResolveContext & context,
 			std::function<bool(const Candidate &)> pred = anyCandidate,
 			const std::string & kind = "", ResolvMode mode = {}
@@ -1169,5 +1170,5 @@
 			if ( ! untyped ) return {};
 			CandidateRef choice =
-				findUnfinishedKindExpression( untyped, symtab, kind, pred, mode );
+				findUnfinishedKindExpression( untyped, context, kind, pred, mode );
 			ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env );
 			return std::move( choice->expr );
@@ -1176,8 +1177,8 @@
 		/// Resolve `untyped` to the single expression whose candidate is the best match
 		ast::ptr< ast::Expr > findSingleExpression(
-			const ast::Expr * untyped, const ast::SymbolTable & symtab
+			const ast::Expr * untyped, const ResolveContext & context
 		) {
 			Stats::ResolveTime::start( untyped );
-			auto res = findKindExpression( untyped, symtab );
+			auto res = findKindExpression( untyped, context );
 			Stats::ResolveTime::stop();
 			return res;
@@ -1186,10 +1187,11 @@
 
 	ast::ptr< ast::Expr > findSingleExpression(
-		const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
+		const ast::Expr * untyped, const ast::Type * type,
+		const ResolveContext & context
 	) {
 		assert( untyped && type );
 		ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
-		ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
-		removeExtraneousCast( newExpr, symtab );
+		ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, context );
+		removeExtraneousCast( newExpr, context.symtab );
 		return newExpr;
 	}
@@ -1217,7 +1219,7 @@
 		/// Resolve `untyped` as an integral expression, returning the resolved version
 		ast::ptr< ast::Expr > findIntegralExpression(
-			const ast::Expr * untyped, const ast::SymbolTable & symtab
+			const ast::Expr * untyped, const ResolveContext & context
 		) {
-			return findKindExpression( untyped, symtab, hasIntegralType, "condition" );
+			return findKindExpression( untyped, context, hasIntegralType, "condition" );
 		}
 
@@ -1243,5 +1245,5 @@
 	: public ast::WithSymbolTable, public ast::WithGuards,
 	  public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting,
-	  public ast::WithStmtsToAdd<> {
+	  public ast::WithStmtsToAdd<>, public ast::WithConstTranslationUnit {
 
 		ast::ptr< ast::Type > functionReturn = nullptr;
@@ -1251,4 +1253,8 @@
 
 		bool inEnumDecl = false;
+
+		ResolveContext getContext() const {
+			return ResolveContext{ symtab, transUnit().global };
+		}
 
 	public:
@@ -1303,16 +1309,22 @@
 
 	ast::ptr< ast::Init > resolveCtorInit(
-		const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab
+		const ast::ConstructorInit * ctorInit, const ResolveContext & context
 	) {
 		assert( ctorInit );
-		ast::Pass< Resolver_new > resolver{ symtab };
+		ast::Pass< Resolver_new > resolver{ context.symtab };
+		ast::TranslationUnit transUnit;
+		transUnit.global = context.global;
+		resolver.core.translationUnit = &transUnit;
 		return ctorInit->accept( resolver );
 	}
 
 	const ast::Expr * resolveStmtExpr(
-		const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab
+		const ast::StmtExpr * stmtExpr, const ResolveContext & context
 	) {
 		assert( stmtExpr );
-		ast::Pass< Resolver_new > resolver{ symtab };
+		ast::Pass< Resolver_new > resolver{ context.symtab };
+		ast::TranslationUnit transUnit;
+		transUnit.global = context.global;
+		resolver.core.translationUnit = &transUnit;
 		auto ret = mutate(stmtExpr->accept(resolver));
 		strict_dynamic_cast< ast::StmtExpr * >( ret )->computeResult();
@@ -1321,10 +1333,10 @@
 
 	namespace {
-		const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ast::SymbolTable & symtab) {
+		const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ResolveContext & context) {
 			std::string name = attr->normalizedName();
 			if (name == "constructor" || name == "destructor") {
 				if (attr->params.size() == 1) {
 					auto arg = attr->params.front();
-					auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), symtab );
+					auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), context );
 					auto result = eval(arg);
 
@@ -1369,5 +1381,5 @@
 
 			for (auto & attr: mutDecl->attributes) {
-				attr = handleAttribute(mutDecl->location, attr, symtab);
+				attr = handleAttribute(mutDecl->location, attr, getContext() );
 			}
 
@@ -1382,5 +1394,5 @@
 			}
 			for (auto & asst : mutDecl->assertions) {
-				asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), symtab);
+				asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), getContext());
 				symtab.addId(asst);
 				mutType->assertions.emplace_back(new ast::VariableExpr(functionDecl->location, asst));
@@ -1394,10 +1406,10 @@
 
 			for (auto & param : mutDecl->params) {
-				param = fixObjectType(param.strict_as<ast::ObjectDecl>(), symtab);
+				param = fixObjectType(param.strict_as<ast::ObjectDecl>(), getContext());
 				symtab.addId(param);
 				paramTypes.emplace_back(param->get_type());
 			}
 			for (auto & ret : mutDecl->returns) {
-				ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), symtab);
+				ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), getContext());
 				returnTypes.emplace_back(ret->get_type());
 			}
@@ -1470,5 +1482,5 @@
 			// enumerator initializers should not use the enum type to initialize, since the
 			// enum type is still incomplete at this point. Use `int` instead.
-			objectDecl = fixObjectType(objectDecl, symtab);
+			objectDecl = fixObjectType(objectDecl, getContext());
 			currentObject = ast::CurrentObject{
 				objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
@@ -1476,5 +1488,5 @@
 		else {
 			if (!objectDecl->isTypeFixed) {
-				auto newDecl = fixObjectType(objectDecl, symtab);
+				auto newDecl = fixObjectType(objectDecl, getContext());
 				auto mutDecl = mutate(newDecl);
 
@@ -1507,5 +1519,5 @@
 			// nested type decls are hoisted already. no need to do anything
 			if (auto obj = member.as<ast::ObjectDecl>()) {
-				member = fixObjectType(obj, symtab);
+				member = fixObjectType(obj, getContext());
 			}
 		}
@@ -1530,14 +1542,14 @@
 		return ast::mutate_field(
 			assertDecl, &ast::StaticAssertDecl::cond,
-			findIntegralExpression( assertDecl->cond, symtab ) );
+			findIntegralExpression( assertDecl->cond, getContext() ) );
 	}
 
 	template< typename PtrType >
-	const PtrType * handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {
+	const PtrType * handlePtrType( const PtrType * type, const ResolveContext & context ) {
 		if ( type->dimension ) {
-			ast::ptr< ast::Type > sizeType = ast::sizeType;
+			ast::ptr< ast::Type > sizeType = context.global.sizeType;
 			ast::mutate_field(
 				type, &PtrType::dimension,
-				findSingleExpression( type->dimension, sizeType, symtab ) );
+				findSingleExpression( type->dimension, sizeType, context ) );
 		}
 		return type;
@@ -1545,9 +1557,9 @@
 
 	const ast::ArrayType * Resolver_new::previsit( const ast::ArrayType * at ) {
-		return handlePtrType( at, symtab );
+		return handlePtrType( at, getContext() );
 	}
 
 	const ast::PointerType * Resolver_new::previsit( const ast::PointerType * pt ) {
-		return handlePtrType( pt, symtab );
+		return handlePtrType( pt, getContext() );
 	}
 
@@ -1557,5 +1569,5 @@
 
 		return ast::mutate_field(
-			exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab ) );
+			exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, getContext() ) );
 	}
 
@@ -1564,5 +1576,5 @@
 
 		asmExpr = ast::mutate_field(
-			asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab ) );
+			asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, getContext() ) );
 
 		return asmExpr;
@@ -1578,10 +1590,10 @@
 	const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
 		return ast::mutate_field(
-			ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab ) );
+			ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, getContext() ) );
 	}
 
 	const ast::WhileDoStmt * Resolver_new::previsit( const ast::WhileDoStmt * whileDoStmt ) {
 		return ast::mutate_field(
-			whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, symtab ) );
+			whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, getContext() ) );
 	}
 
@@ -1589,10 +1601,10 @@
 		if ( forStmt->cond ) {
 			forStmt = ast::mutate_field(
-				forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab ) );
+				forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, getContext() ) );
 		}
 
 		if ( forStmt->inc ) {
 			forStmt = ast::mutate_field(
-				forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab ) );
+				forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, getContext() ) );
 		}
 
@@ -1604,5 +1616,5 @@
 		switchStmt = ast::mutate_field(
 			switchStmt, &ast::SwitchStmt::cond,
-			findIntegralExpression( switchStmt->cond, symtab ) );
+			findIntegralExpression( switchStmt->cond, getContext() ) );
 		currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result };
 		return switchStmt;
@@ -1617,5 +1629,5 @@
 			ast::ptr< ast::Expr > untyped =
 				new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
-			ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab );
+			ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, getContext() );
 
 			// case condition cannot have a cast in C, so it must be removed here, regardless of
@@ -1638,5 +1650,5 @@
 			branchStmt = ast::mutate_field(
 				branchStmt, &ast::BranchStmt::computedTarget,
-				findSingleExpression( branchStmt->computedTarget, target, symtab ) );
+				findSingleExpression( branchStmt->computedTarget, target, getContext() ) );
 		}
 		return branchStmt;
@@ -1648,5 +1660,5 @@
 			returnStmt = ast::mutate_field(
 				returnStmt, &ast::ReturnStmt::expr,
-				findSingleExpression( returnStmt->expr, functionReturn, symtab ) );
+				findSingleExpression( returnStmt->expr, functionReturn, getContext() ) );
 		}
 		return returnStmt;
@@ -1663,5 +1675,5 @@
 			throwStmt = ast::mutate_field(
 				throwStmt, &ast::ThrowStmt::expr,
-				findSingleExpression( throwStmt->expr, exceptType, symtab ) );
+				findSingleExpression( throwStmt->expr, exceptType, getContext() ) );
 		}
 		return throwStmt;
@@ -1707,5 +1719,5 @@
 
 			ast::TypeEnvironment env;
-			CandidateFinder funcFinder{ symtab, env };
+			CandidateFinder funcFinder( getContext(), env );
 
 			// Find all candidates for a function in canonical form
@@ -1921,9 +1933,9 @@
 				);
 
-				clause2.target.args.emplace_back( findSingleExpression( init, symtab ) );
+				clause2.target.args.emplace_back( findSingleExpression( init, getContext() ) );
 			}
 
 			// Resolve the conditions as if it were an IfStmt, statements normally
-			clause2.cond = findSingleExpression( clause.cond, symtab );
+			clause2.cond = findSingleExpression( clause.cond, getContext() );
 			clause2.stmt = clause.stmt->accept( *visitor );
 
@@ -1940,6 +1952,6 @@
 			ast::ptr< ast::Type > target =
 				new ast::BasicType{ ast::BasicType::LongLongUnsignedInt };
-			timeout2.time = findSingleExpression( stmt->timeout.time, target, symtab );
-			timeout2.cond = findSingleExpression( stmt->timeout.cond, symtab );
+			timeout2.time = findSingleExpression( stmt->timeout.time, target, getContext() );
+			timeout2.cond = findSingleExpression( stmt->timeout.cond, getContext() );
 			timeout2.stmt = stmt->timeout.stmt->accept( *visitor );
 
@@ -1954,5 +1966,5 @@
 			ast::WaitForStmt::OrElse orElse2;
 
-			orElse2.cond = findSingleExpression( stmt->orElse.cond, symtab );
+			orElse2.cond = findSingleExpression( stmt->orElse.cond, getContext() );
 			orElse2.stmt = stmt->orElse.stmt->accept( *visitor );
 
@@ -1975,5 +1987,5 @@
 		for (auto & expr : exprs) {
 			// only struct- and union-typed expressions are viable candidates
-			expr = findKindExpression( expr, symtab, structOrUnion, "with expression" );
+			expr = findKindExpression( expr, getContext(), structOrUnion, "with expression" );
 
 			// if with expression might be impure, create a temporary so that it is evaluated once
@@ -2001,5 +2013,5 @@
 		ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{
 			singleInit->location, singleInit->value, currentObject.getOptions() };
-		ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab );
+		ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, getContext() );
 		const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
 
Index: src/ResolvExpr/Resolver.h
===================================================================
--- src/ResolvExpr/Resolver.h	(revision 9d8124f79ccec28447cabfc84649853818e887f2)
+++ src/ResolvExpr/Resolver.h	(revision 39d89504881cd88008aec5648412e27d45b19c6e)
@@ -9,7 +9,7 @@
 // Author           : Richard C. Bilson
 // Created On       : Sun May 17 12:18:34 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Mon Feb 18 20:40:38 2019
-// Update Count     : 4
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Mar 16 11:32:00 2022
+// Update Count     : 5
 //
 
@@ -23,5 +23,7 @@
 class Declaration;
 class Expression;
+class DeletedExpr;
 class StmtExpr;
+class Type;
 namespace SymTab {
 	class Indexer;
@@ -35,4 +37,5 @@
 	class StmtExpr;
 	class SymbolTable;
+	class TranslationGlobal;
 	class TranslationUnit;
 	class Type;
@@ -55,4 +58,10 @@
 	void resolveWithExprs( std::list< Declaration * > & translationUnit );
 
+	/// Helper Type: Passes around information between various sub-calls.
+	struct ResolveContext {
+		const ast::SymbolTable & symtab;
+		const ast::TranslationGlobal & global;
+	};
+
 	/// Checks types and binds syntactic constructs to typed representations
 	void resolve( ast::TranslationUnit& translationUnit );
@@ -62,17 +71,17 @@
 	/// context.
 	ast::ptr< ast::Expr > resolveInVoidContext(
-		const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env );
+		const ast::Expr * expr, const ResolveContext &, ast::TypeEnvironment & env );
 	/// Resolve `untyped` to the single expression whose candidate is the best match for the
 	/// given type.
 	ast::ptr< ast::Expr > findSingleExpression(
-		const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab );
+		const ast::Expr * untyped, const ast::Type * type, const ResolveContext & );
 	ast::ptr< ast::Expr > findVoidExpression(
-		const ast::Expr * untyped, const ast::SymbolTable & symtab);
+		const ast::Expr * untyped, const ResolveContext & );
 	/// Resolves a constructor init expression
 	ast::ptr< ast::Init > resolveCtorInit(
-		const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab );
+		const ast::ConstructorInit * ctorInit, const ResolveContext & context );
 	/// Resolves a statement expression
 	const ast::Expr * resolveStmtExpr(
-		const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab );
+		const ast::StmtExpr * stmtExpr, const ResolveContext & context );
 } // namespace ResolvExpr
 
Index: src/Tuples/TupleAssignment.cc
===================================================================
--- src/Tuples/TupleAssignment.cc	(revision 9d8124f79ccec28447cabfc84649853818e887f2)
+++ src/Tuples/TupleAssignment.cc	(revision 39d89504881cd88008aec5648412e27d45b19c6e)
@@ -9,7 +9,7 @@
 // Author           : Rodolfo G. Esteves
 // Created On       : Mon May 18 07:44:20 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Dec 13 23:45:33 2019
-// Update Count     : 9
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Mar 16 14:06:00 2022
+// Update Count     : 10
 //
 
@@ -465,5 +465,5 @@
 					// resolve ctor/dtor for the new object
 					ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit(
-							InitTweak::genCtorInit( location, ret ), spotter.crntFinder.localSyms );
+							InitTweak::genCtorInit( location, ret ), spotter.crntFinder.context );
 					// remove environments from subexpressions of stmtExpr
 					ast::Pass< EnvRemover > rm{ env };
@@ -560,5 +560,5 @@
 					// resolve the cast expression so that rhsCand return type is bound by the cast
 					// type as needed, and transfer the resulting environment
-					ResolvExpr::CandidateFinder finder{ spotter.crntFinder.localSyms, env };
+					ResolvExpr::CandidateFinder finder( spotter.crntFinder.context, env );
 					finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() );
 					assert( finder.candidates.size() == 1 );
@@ -609,5 +609,5 @@
 					// explode the LHS so that each field of a tuple-valued expr is assigned
 					ResolvExpr::CandidateList lhs;
-					explode( *lhsCand, crntFinder.localSyms, back_inserter(lhs), true );
+					explode( *lhsCand, crntFinder.context.symtab, back_inserter(lhs), true );
 					for ( ResolvExpr::CandidateRef & cand : lhs ) {
 						// each LHS value must be a reference - some come in with a cast, if not
@@ -629,5 +629,5 @@
 							if ( isTuple( rhsCand->expr ) ) {
 								// multiple assignment
-								explode( *rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
+								explode( *rhsCand, crntFinder.context.symtab, back_inserter(rhs), true );
 								matcher.reset(
 									new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
@@ -648,5 +648,5 @@
 							// multiple assignment
 							ResolvExpr::CandidateList rhs;
-							explode( rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
+							explode( rhsCand, crntFinder.context.symtab, back_inserter(rhs), true );
 							matcher.reset(
 								new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
@@ -678,5 +678,5 @@
 				)
 
-				ResolvExpr::CandidateFinder finder{ crntFinder.localSyms, matcher->env };
+				ResolvExpr::CandidateFinder finder( crntFinder.context, matcher->env );
 
 				try {
Index: src/Validate/FindSpecialDeclsNew.cpp
===================================================================
--- src/Validate/FindSpecialDeclsNew.cpp	(revision 9d8124f79ccec28447cabfc84649853818e887f2)
+++ src/Validate/FindSpecialDeclsNew.cpp	(revision 39d89504881cd88008aec5648412e27d45b19c6e)
@@ -30,6 +30,6 @@
 
 struct FindDeclsCore : public ast::WithShortCircuiting {
-	ast::TranslationUnit::Global & global;
-	FindDeclsCore( ast::TranslationUnit::Global & g ) : global( g ) {}
+	ast::TranslationGlobal & global;
+	FindDeclsCore( ast::TranslationGlobal & g ) : global( g ) {}
 
 	void previsit( const ast::Decl * decl );
@@ -74,10 +74,4 @@
 	ast::Pass<FindDeclsCore>::run( translationUnit, translationUnit.global );
 
-	// TODO: When everything gets the globals from the translation unit,
-	// remove these.
-	ast::dereferenceOperator = translationUnit.global.dereference;
-	ast::dtorStruct = translationUnit.global.dtorStruct;
-	ast::dtorStructDestroy = translationUnit.global.dtorDestroy;
-
 	// TODO: conditionally generate 'fake' declarations for missing features,
 	// so that translation can proceed in the event that builtins, prelude,
