Index: src/AST/Copy.cpp
===================================================================
--- src/AST/Copy.cpp	(revision 5dcb8815c835a84c61a3b38db0d36dc85661cdf7)
+++ src/AST/Copy.cpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
@@ -105,5 +105,6 @@
 }
 
-Node * deepCopyNode( const Node * localRoot ) {
+template<>
+Node * deepCopy<Node>( const Node * localRoot ) {
 	Pass< DeepCopyCore > dc;
 	Node const * newRoot = localRoot->accept( dc );
Index: src/AST/Copy.hpp
===================================================================
--- src/AST/Copy.hpp	(revision 5dcb8815c835a84c61a3b38db0d36dc85661cdf7)
+++ src/AST/Copy.hpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
@@ -44,10 +44,11 @@
 }
 
-Node * deepCopyNode( const Node * node );
-
 template<typename node_t>
 node_t * deepCopy( const node_t * localRoot ) {
-	return strict_dynamic_cast<node_t *>( deepCopyNode( localRoot ) );
+	return strict_dynamic_cast<node_t *>( deepCopy<Node>( localRoot ) );
 }
+
+template<>
+Node * deepCopy<Node>( const Node * localRoot );
 
 }
Index: src/AST/Init.hpp
===================================================================
--- src/AST/Init.hpp	(revision 5dcb8815c835a84c61a3b38db0d36dc85661cdf7)
+++ src/AST/Init.hpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
@@ -98,4 +98,5 @@
 	const_iterator begin() const { return initializers.begin(); }
 	const_iterator end() const { return initializers.end(); }
+	size_t size() const { return initializers.size(); }
 
 	const Init * accept( Visitor & v ) const override { return v.visit( this ); }
Index: src/AST/Pass.hpp
===================================================================
--- src/AST/Pass.hpp	(revision 5dcb8815c835a84c61a3b38db0d36dc85661cdf7)
+++ src/AST/Pass.hpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
@@ -109,5 +109,5 @@
 	static auto read( node_type const * node, Args&&... args ) {
 		Pass<core_t> visitor( std::forward<Args>( args )... );
-		node_type const * temp = node->accept( visitor );
+		auto const * temp = node->accept( visitor );
 		assert( temp == node );
 		return visitor.get_result();
@@ -124,5 +124,5 @@
 	static auto read( node_type const * node ) {
 		Pass<core_t> visitor;
-		node_type const * temp = node->accept( visitor );
+		auto const * temp = node->accept( visitor );
 		assert( temp == node );
 		return visitor.get_result();
Index: src/InitTweak/FixInitNew.cpp
===================================================================
--- src/InitTweak/FixInitNew.cpp	(revision 5dcb8815c835a84c61a3b38db0d36dc85661cdf7)
+++ src/InitTweak/FixInitNew.cpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
@@ -591,5 +591,6 @@
 		// need to add __Destructor for _tmp_cp variables as well
 
-		assertf( ast::dtorStruct && ast::dtorStruct->members.size() == 2, "Destructor generation requires __Destructor definition." );
+		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." );
 
@@ -1216,6 +1217,6 @@
 
 							static UniqueName memberDtorNamer = { "__memberDtor" };
-							assertf( Validate::dtorStruct, "builtin __Destructor not found." );
-							assertf( Validate::dtorStructDestroy, "builtin __destroy_Destructor not found." );
+							assertf( ast::dtorStruct, "builtin __Destructor not found." );
+							assertf( ast::dtorStructDestroy, "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() ) );
Index: src/Validate/FindSpecialDecls.h
===================================================================
--- src/Validate/FindSpecialDecls.h	(revision 5dcb8815c835a84c61a3b38db0d36dc85661cdf7)
+++ src/Validate/FindSpecialDecls.h	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
@@ -9,7 +9,7 @@
 // Author           : Rob Schluntz
 // Created On       : Thu Aug 30 09:49:02 2018
-// Last Modified By : Rob Schluntz
-// Last Modified On : Thu Aug 30 09:51:12 2018
-// Update Count     : 2
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Nov 10 15:16:00 2021
+// Update Count     : 3
 //
 
@@ -22,4 +22,8 @@
 class StructDecl;
 class Type;
+
+namespace ast {
+	class TranslationUnit;
+}
 
 namespace Validate {
@@ -38,4 +42,9 @@
 	/// find and remember some of the special declarations that are useful for generating code, so that they do not have to be discovered multiple times.
 	void findSpecialDecls( std::list< Declaration * > & translationUnit );
+
+/// find and remember some of the special declarations that are useful for
+/// generating code, so that they do not have to be discovered multiple times.
+void findGlobalDecls( ast::TranslationUnit & translationUnit );
+
 } // namespace Validate
 
Index: src/Validate/FindSpecialDeclsNew.cpp
===================================================================
--- src/Validate/FindSpecialDeclsNew.cpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
+++ src/Validate/FindSpecialDeclsNew.cpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
@@ -0,0 +1,93 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// FindSpecialDeclsNew.cpp -- Find special declarations used in the compiler.
+//
+// Author           : Andrew Beach
+// Created On       : Wed Nov 10 13:51:00 2021
+// Last Modified By : Andrew Beach
+// Last Modified On : Wed Nov 10 15:22:00 2021
+// Update Count     : 0
+//
+
+#include "Validate/FindSpecialDecls.h"
+
+#include "AST/Decl.hpp"
+#include "AST/Pass.hpp"
+#include "AST/TranslationUnit.hpp"
+
+// NOTE: currently, it is assumed that every special declaration occurs at the
+// top-level, so function bodies, aggregate bodies, object initializers, etc.
+// are not visited. If this assumption changes, e.g., with the introduction
+// of namespaces, remove the visit_children assignments.
+
+namespace Validate {
+
+namespace {
+
+struct FindDeclsCore : public ast::WithShortCircuiting {
+	ast::TranslationUnit::Global & global;
+	FindDeclsCore( ast::TranslationUnit::Global & g ) : global( g ) {}
+
+	void previsit( const ast::Decl * decl );
+	void previsit( const ast::FunctionDecl * decl );
+	void previsit( const ast::StructDecl * decl );
+};
+
+void FindDeclsCore::previsit( const ast::Decl * ) {
+	visit_children = false;
+}
+
+void FindDeclsCore::previsit( const ast::FunctionDecl * decl ) {
+	visit_children = false;
+	if ( !global.dereference && decl->name == "*?" ) {
+		const ast::FunctionType * type = decl->type.get();
+		if ( decl->linkage == ast::Linkage::Intrinsic && type->params.size() == 1 ) {
+			const ast::PointerType * ptrType = type->params.front().strict_as<ast::PointerType>();
+			ast::ptr<ast::Type> baseType = ptrType->base;
+			if ( baseType->qualifiers == ast::CV::Qualifiers() ) {
+				const ast::TypeInstType * inst = baseType.as<ast::TypeInstType>();
+				if ( inst || inst->kind != ast::TypeDecl::Ftype ) {
+					global.dereference = decl;
+				}
+			}
+		}
+	} else if ( !global.dtorDestroy && decl->name == "__destroy_Destructor" ) {
+		global.dtorDestroy = decl;
+	}
+}
+
+void FindDeclsCore::previsit( const ast::StructDecl * decl ) {
+	visit_children = false;
+	if ( !global.dtorStruct && decl->name == "__Destructor" ) {
+		global.dtorStruct = decl;
+	}
+}
+
+} // namespace
+
+// Fill the TranslationUnit's dereference, dtorStruct and dtorDestroy fields.
+void findGlobalDecls( ast::TranslationUnit & translationUnit ) {
+	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,
+	// etc. are missing.
+}
+
+} // namespace Validate
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/InitializerLength.cpp
===================================================================
--- src/Validate/InitializerLength.cpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
+++ src/Validate/InitializerLength.cpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
@@ -0,0 +1,65 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// InitializerLength.cpp -- Calculate the length of arrays from initializers.
+//
+// Author           : Andrew Beach
+// Created On       : Fri Nov 12 11:46:00 2021
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Nov 12 13:35:00 2021
+// Update Count     : 0
+//
+
+//#include "InitializerLength.hpp"
+
+#include "AST/Expr.hpp"
+#include "AST/Decl.hpp"
+#include "AST/Pass.hpp"
+#include "AST/TranslationUnit.hpp"
+
+namespace Validate {
+
+namespace {
+
+/// for array types without an explicit length, compute the length and store it so that it
+/// is known to the rest of the phases. For example,
+///   int x[] = { 1, 2, 3 };
+///   int y[][2] = { { 1, 2, 3 }, { 1, 2, 3 } };
+/// here x and y are known at compile-time to have length 3, so change this into
+///   int x[3] = { 1, 2, 3 };
+///   int y[3][2] = { { 1, 2, 3 }, { 1, 2, 3 } };
+struct InitializerLength {
+	const ast::ObjectDecl * previsit( const ast::ObjectDecl * decl );
+};
+
+const ast::ObjectDecl * InitializerLength::previsit( const ast::ObjectDecl * decl ) {
+	if ( auto type = decl->type.as<ast::ArrayType>() ) {
+		if ( type->dimension ) return decl;
+		if ( auto init = decl->init.as<ast::ListInit>() ) {
+			ast::ObjectDecl * mutDecl = ast::mutate( decl );
+			ast::ArrayType * mutType = ast::mutate( type );
+			mutType->dimension = ast::ConstantExpr::from_ulong(
+				mutDecl->location, init->size() );
+			mutDecl->type = mutType;
+			return mutDecl;
+		}
+	}
+	return decl;
+}
+
+} // namespace
+
+void setLengthFromInitializer( ast::TranslationUnit & translationUnit ) {
+	ast::Pass<InitializerLength>::run( translationUnit );
+}
+
+} // namespace Validate
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/InitializerLength.hpp
===================================================================
--- src/Validate/InitializerLength.hpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
+++ src/Validate/InitializerLength.hpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
@@ -0,0 +1,27 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// InitializerLength.hpp -- Calculate the length of arrays from initializers.
+//
+// Author           : Andrew Beach
+// Created On       : Fri Nov 12 16:25:00 2021
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Nov 12 16:28:00 2021
+// Update Count     : 0
+//
+
+namespace Validate {
+
+/// Set implicit length of array from the initializer.
+void setLengthFromInitializer( ast::TranslationUnit & translationUnit );
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/LabelAddressFixer.cpp
===================================================================
--- src/Validate/LabelAddressFixer.cpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
+++ src/Validate/LabelAddressFixer.cpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
@@ -0,0 +1,74 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// LabelAddressFixer.cpp --
+//
+// Author           : Andrew Beach
+// Created On       : Fri Nov 12 16:30:00 2021
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Nov 12 16:30:00 2021
+// Update Count     : 0
+//
+
+#include "Validate/LabelAddressFixer.hpp"
+
+#include "AST/Decl.hpp"
+#include "AST/Expr.hpp"
+#include "AST/Pass.hpp"
+#include "AST/TranslationUnit.hpp"
+
+#include <set>
+
+namespace Validate {
+
+namespace {
+
+struct LabelFinder {
+	std::set<ast::Label> & labels;
+	LabelFinder( std::set<ast::Label> & labels ) : labels( labels ) {}
+	void previsit( const ast::Stmt * stmt ) {
+		for ( const ast::Label & label : stmt->labels ) {
+			labels.insert( label );
+		}
+	}
+};
+
+struct LabelAddressFixer : public ast::WithGuards {
+	std::set<ast::Label> labels;
+	void previsit( const ast::FunctionDecl * decl );
+	const ast::Expr * postvisit( const ast::AddressExpr * expr );
+};
+
+void LabelAddressFixer::previsit( const ast::FunctionDecl * decl ) {
+	GuardValue( labels );
+	ast::Pass<LabelFinder>::read( decl, labels );
+}
+
+const ast::Expr * LabelAddressFixer::postvisit( const ast::AddressExpr * expr ) {
+	if ( auto inner = expr->arg.as<ast::AddressExpr>() ) {
+		if ( auto nameExpr = inner->arg.as<ast::NameExpr>() ) {
+			ast::Label label( nameExpr->location, nameExpr->name );
+			if ( labels.count( label ) ) {
+				return new ast::LabelAddressExpr( nameExpr->location, std::move( label ) );
+			}
+		}
+	}
+	return expr;
+}
+
+} // namespace
+
+void fixLabelAddresses( ast::TranslationUnit & translationUnit ) {
+	ast::Pass<LabelAddressFixer>::run( translationUnit );
+}
+
+} // namespace Validate
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/LabelAddressFixer.hpp
===================================================================
--- src/Validate/LabelAddressFixer.hpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
+++ src/Validate/LabelAddressFixer.hpp	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
@@ -0,0 +1,30 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// LabelAddressFixer.hpp --
+//
+// Author           : Andrew Beach
+// Created On       : Fri Nov 12 16:29:00 2021
+// Last Modified By : Andrew Beach
+// Last Modified On : Fri Nov 12 16:35:00 2021
+// Update Count     : 0
+//
+
+namespace ast {
+	class TranslationUnit;
+}
+
+namespace Validate {
+
+void fixLabelAddresses( ast::TranslationUnit & translationUnit );
+
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Validate/module.mk
===================================================================
--- src/Validate/module.mk	(revision 5dcb8815c835a84c61a3b38db0d36dc85661cdf7)
+++ src/Validate/module.mk	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
@@ -15,4 +15,15 @@
 ###############################################################################
 
-SRC += Validate/HandleAttributes.cc Validate/HandleAttributes.h Validate/FindSpecialDecls.cc Validate/FindSpecialDecls.h
-SRCDEMANGLE += Validate/HandleAttributes.cc Validate/HandleAttributes.h Validate/FindSpecialDecls.cc Validate/FindSpecialDecls.h
+SRC_VALIDATE = \
+	Validate/HandleAttributes.cc \
+	Validate/HandleAttributes.h \
+	Validate/InitializerLength.cpp \
+	Validate/InitializerLength.hpp \
+	Validate/LabelAddressFixer.cpp \
+	Validate/LabelAddressFixer.hpp \
+	Validate/FindSpecialDeclsNew.cpp \
+	Validate/FindSpecialDecls.cc \
+	Validate/FindSpecialDecls.h
+
+SRC += $(SRC_VALIDATE)
+SRCDEMANGLE += $(SRC_VALIDATE)
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 5dcb8815c835a84c61a3b38db0d36dc85661cdf7)
+++ src/main.cc	(revision ce36b5519dcfbed597a596a468dc1684221e78ab)
@@ -72,4 +72,7 @@
 #include "SynTree/Visitor.h"                // for acceptAll
 #include "Tuples/Tuples.h"                  // for expandMemberTuples, expan...
+#include "Validate/FindSpecialDecls.h"      // for findGlobalDecls
+#include "Validate/InitializerLength.hpp"   // for setLengthFromInitializer
+#include "Validate/LabelAddressFixer.hpp"   // for fixLabelAddresses
 #include "Virtual/ExpandCasts.h"            // for expandCasts
 
@@ -323,5 +326,4 @@
 		PASS( "Validate-D", SymTab::validate_D( translationUnit ) );
 		PASS( "Validate-E", SymTab::validate_E( translationUnit ) );
-		PASS( "Validate-F", SymTab::validate_F( translationUnit ) );
 
 		CodeTools::fillLocations( translationUnit );
@@ -336,4 +338,8 @@
 			forceFillCodeLocations( transUnit );
 
+			PASS( "Set Length From Initializer", Validate::setLengthFromInitializer( transUnit ) );
+			PASS( "Find Global Decls", Validate::findGlobalDecls( transUnit ) );
+			PASS( "Fix Label Address", Validate::fixLabelAddresses( transUnit ) );
+
 			if ( symtabp ) {
 				return EXIT_SUCCESS;
@@ -396,4 +402,6 @@
 			translationUnit = convert( move( transUnit ) );
 		} else {
+			PASS( "Validate-F", SymTab::validate_F( translationUnit ) );
+
 			if ( symtabp ) {
 				deleteAll( translationUnit );
