Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision 934fa0fc6af3737f7f5b45e08f4b84e1e8259312)
+++ 	(revision )
@@ -1,753 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// Autogen.cc --
-//
-// Author           : Rob Schluntz
-// Created On       : Thu Mar 03 15:45:56 2016
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Apr 14 15:03:00 2023
-// Update Count     : 64
-//
-
-#include "Autogen.h"
-
-#include <algorithm>               // for count_if
-#include <cassert>                 // for strict_dynamic_cast, assert, assertf
-#include <iterator>                // for back_insert_iterator, back_inserter
-#include <list>                    // for list, _List_iterator, list<>::iter...
-#include <set>                     // for set, _Rb_tree_const_iterator
-#include <utility>                 // for pair
-#include <vector>                  // for vector
-
-#include "AST/Decl.hpp"
-#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
-#include "Common/PassVisitor.h"    // for PassVisitor
-#include "Common/ScopedMap.h"      // for ScopedMap<>::const_iterator, Scope...
-#include "Common/utility.h"        // for cloneAll, operator+
-#include "GenPoly/ScopedSet.h"     // for ScopedSet, ScopedSet<>::iterator
-#include "InitTweak/GenInit.h"     // for fixReturnStatements
-#include "ResolvExpr/Resolver.h"   // for resolveDecl
-#include "SymTab/Mangler.h"        // for Mangler
-#include "SynTree/Attribute.h"     // For Attribute
-#include "SynTree/Mutator.h"       // for maybeMutate
-#include "SynTree/Statement.h"     // for CompoundStmt, ReturnStmt, ExprStmt
-#include "SynTree/Type.h"          // for FunctionType, Type, TypeInstType
-#include "SynTree/Visitor.h"       // for maybeAccept, Visitor, acceptAll
-#include "CompilationState.h"
-
-class Attribute;
-
-namespace SymTab {
-	/// Data used to generate functions generically. Specifically, the name of the generated function and a function which generates the routine protoype
-	struct FuncData {
-		typedef FunctionType * (*TypeGen)( Type *, bool );
-		FuncData( const std::string & fname, const TypeGen & genType ) : fname( fname ), genType( genType ) {}
-		std::string fname;
-		TypeGen genType;
-	};
-
-	struct AutogenerateRoutines final : public WithDeclsToAdd, public WithVisitorRef<AutogenerateRoutines>, public WithGuards, public WithShortCircuiting, public WithIndexer {
-		AutogenerateRoutines();
-
-		void previsit( EnumDecl * enumDecl );
-		void previsit( StructDecl * structDecl );
-		void previsit( UnionDecl * structDecl );
-		void previsit( TypeDecl * typeDecl );
-		void previsit( TraitDecl * traitDecl );
-		void previsit( FunctionDecl * functionDecl );
-
-		void previsit( CompoundStmt * compoundStmt );
-
-	  private:
-
-		GenPoly::ScopedSet< std::string > structsDone;
-		unsigned int functionNesting = 0;     // current level of nested functions
-
-		std::vector< FuncData > data;
-	};
-
-	/// generates routines for tuple types.
-	struct AutogenTupleRoutines : public WithDeclsToAdd, public WithVisitorRef<AutogenTupleRoutines>, public WithGuards, public WithShortCircuiting {
-		void previsit( FunctionDecl * functionDecl );
-
-		void postvisit( TupleType * tupleType );
-
-		void previsit( CompoundStmt * compoundStmt );
-
-	  private:
-		unsigned int functionNesting = 0;     // current level of nested functions
-		GenPoly::ScopedSet< std::string > seenTuples;
-	};
-
-	void autogenerateRoutines( std::list< Declaration * > &translationUnit ) {
-		PassVisitor<AutogenerateRoutines> generator;
-		acceptAll( translationUnit, generator );
-
-		// needs to be done separately because AutogenerateRoutines skips types that appear as function arguments, etc.
-		// AutogenTupleRoutines tupleGenerator;
-		// acceptAll( translationUnit, tupleGenerator );
-	}
-
-	//=============================================================================================
-	// FuncGenerator definitions
-	//=============================================================================================
-	class FuncGenerator {
-	public:
-		std::list< Declaration * > definitions, forwards;
-
-		FuncGenerator( Type * type, const std::vector< FuncData > & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : type( type ), data( data ), functionNesting( functionNesting ), indexer( indexer ) {}
-
-		virtual bool shouldAutogen() const = 0;
-		void genStandardFuncs();
-		virtual void genFieldCtors() = 0;
-	protected:
-		Type * type;
-		const std::vector< FuncData > & data;
-		unsigned int functionNesting;
-		SymTab::Indexer & indexer;
-
-		virtual void genFuncBody( FunctionDecl * dcl ) = 0;
-		virtual bool isConcurrentType() const = 0;
-
-		void resolve( FunctionDecl * dcl );
-		void generatePrototypes( std::list< FunctionDecl * > & newFuncs );
-	};
-
-	class StructFuncGenerator : public FuncGenerator {
-		StructDecl * aggregateDecl;
-	public:
-		StructFuncGenerator( StructDecl * aggregateDecl, StructInstType * refType, const std::vector< FuncData > & data,  unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ), aggregateDecl( aggregateDecl) {}
-
-		virtual bool shouldAutogen() const override;
-		virtual bool isConcurrentType() const override;
-
-		virtual void genFuncBody( FunctionDecl * dcl ) override;
-		virtual void genFieldCtors() override;
-
-	private:
-		/// generates a single struct member operation (constructor call, destructor call, assignment call)
-		void makeMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward = true );
-
-		/// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies
-		template<typename Iterator>
-		void makeFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true );
-
-		/// generate the body of a constructor which takes parameters that match fields, e.g.
-		/// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields.
-		template<typename Iterator>
-		void makeFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func );
-	};
-
-	class UnionFuncGenerator : public FuncGenerator {
-		UnionDecl * aggregateDecl;
-	public:
-		UnionFuncGenerator( UnionDecl * aggregateDecl, UnionInstType * refType, const std::vector< FuncData > & data,  unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ), aggregateDecl( aggregateDecl) {}
-
-		virtual bool shouldAutogen() const override;
-		virtual bool isConcurrentType() const override;
-
-		virtual void genFuncBody( FunctionDecl * dcl ) override;
-		virtual void genFieldCtors() override;
-
-	private:
-		/// generates a single struct member operation (constructor call, destructor call, assignment call)
-		template<typename OutputIterator>
-		void makeMemberOp( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out );
-
-		/// generates the body of a struct function by iterating the struct members (via parameters) - generates default ctor, copy ctor, assignment, and dtor bodies, but NOT field ctor bodies
-		template<typename Iterator>
-		void makeFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward = true );
-
-		/// generate the body of a constructor which takes parameters that match fields, e.g.
-		/// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields.
-		template<typename Iterator>
-		void makeFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func );
-	};
-
-	class EnumFuncGenerator : public FuncGenerator {
-	public:
-		EnumFuncGenerator( EnumInstType * refType, const std::vector< FuncData > & data,  unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ) {}
-
-		virtual bool shouldAutogen() const override;
-		virtual bool isConcurrentType() const override;
-
-		virtual void genFuncBody( FunctionDecl * dcl ) override;
-		virtual void genFieldCtors() override;
-
-	private:
-	};
-
-	class TypeFuncGenerator : public FuncGenerator {
-		TypeDecl * typeDecl;
-	public:
-		TypeFuncGenerator( TypeDecl * typeDecl, TypeInstType * refType, const std::vector<FuncData> & data, unsigned int functionNesting, SymTab::Indexer & indexer ) : FuncGenerator( refType, data, functionNesting, indexer ), typeDecl( typeDecl ) {}
-
-		virtual bool shouldAutogen() const override;
-		virtual void genFuncBody( FunctionDecl * dcl ) override;
-		virtual bool isConcurrentType() const override;
-		virtual void genFieldCtors() override;
-	};
-
-	//=============================================================================================
-	// helper functions
-	//=============================================================================================
-	void generateFunctions( FuncGenerator & gen, std::list< Declaration * > & declsToAdd ) {
-		if ( ! gen.shouldAutogen() ) return;
-
-		// generate each of the functions based on the supplied FuncData objects
-		gen.genStandardFuncs();
-		gen.genFieldCtors();
-
-		declsToAdd.splice( declsToAdd.end(), gen.forwards );
-		declsToAdd.splice( declsToAdd.end(), gen.definitions );
-	}
-
-	bool isUnnamedBitfield( ObjectDecl * obj ) {
-		return obj != nullptr && obj->name == "" && obj->bitfieldWidth != nullptr;
-	}
-
-	/// inserts a forward declaration for functionDecl into declsToAdd
-	void addForwardDecl( FunctionDecl * functionDecl, std::list< Declaration * > & declsToAdd ) {
-		FunctionDecl * decl = functionDecl->clone();
-		delete decl->statements;
-		decl->statements = nullptr;
-		declsToAdd.push_back( decl );
-		decl->fixUniqueId();
-	}
-
-	const std::list< TypeDecl * > getGenericParams( Type * t ) {
-		std::list< TypeDecl * > * ret = nullptr;
-		if ( StructInstType * inst = dynamic_cast< StructInstType * > ( t ) ) {
-			ret = inst->get_baseParameters();
-		} else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) {
-			ret = inst->get_baseParameters();
-		}
-		return ret ? *ret : std::list< TypeDecl * >();
-	}
-
-	/// given type T, generate type of default ctor/dtor, i.e. function type void (*) (T *)
-	FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic ) {
-		FunctionType *ftype = new FunctionType( Type::Qualifiers(), false );
-		if ( maybePolymorphic ) {
-			// only copy in
-			const auto & typeParams = getGenericParams( paramType );
-			cloneAll( typeParams, ftype->forall );
-		}
-		ObjectDecl *dstParam = new ObjectDecl( "_dst", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new ReferenceType( Type::Qualifiers(), paramType->clone() ), nullptr );
-		ftype->parameters.push_back( dstParam );
-		return ftype;
-	}
-
-	/// given type T, generate type of copy ctor, i.e. function type void (*) (T *, T)
-	FunctionType * genCopyType( Type * paramType, bool maybePolymorphic ) {
-		FunctionType *ftype = genDefaultType( paramType, maybePolymorphic );
-		ObjectDecl *srcParam = new ObjectDecl( "_src", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
-		ftype->parameters.push_back( srcParam );
-		return ftype;
-	}
-
-	/// given type T, generate type of assignment, i.e. function type T (*) (T *, T)
-	FunctionType * genAssignType( Type * paramType, bool maybePolymorphic ) {
-		FunctionType *ftype = genCopyType( paramType, maybePolymorphic );
-		ObjectDecl *returnVal = new ObjectDecl( "_ret", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType->clone(), nullptr );
-		ftype->returnVals.push_back( returnVal );
-		return ftype;
-	}
-
-	/// generate a function decl from a name and type. Nesting depth determines whether
-	/// the declaration is static or not; optional paramter determines if declaration is intrinsic
-	FunctionDecl * genFunc( const std::string & fname, FunctionType * ftype, unsigned int functionNesting, bool isIntrinsic = false  ) {
-		// Routines at global scope marked "static" to prevent multiple definitions in separate translation units
-		// because each unit generates copies of the default routines for each aggregate.
-		Type::StorageClasses scs = functionNesting > 0 ? Type::StorageClasses() : Type::StorageClasses( Type::Static );
-		LinkageSpec::Spec spec = isIntrinsic ? LinkageSpec::Intrinsic : LinkageSpec::AutoGen;
-		FunctionDecl * decl = new FunctionDecl( fname, scs, spec, ftype, new CompoundStmt(),
-												std::list< Attribute * >(), Type::FuncSpecifiers( Type::Inline ) );
-		decl->fixUniqueId();
-		return decl;
-	}
-
-	Type * declToType( Declaration * decl ) {
-		if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
-			return dwt->get_type();
-		}
-		return nullptr;
-	}
-
-	Type * declToTypeDeclBase( Declaration * decl ) {
-		if ( TypeDecl * td = dynamic_cast< TypeDecl * >( decl ) ) {
-			return td->base;
-		}
-		return nullptr;
-	}
-
-	//=============================================================================================
-	// FuncGenerator member definitions
-	//=============================================================================================
-	void FuncGenerator::genStandardFuncs() {
-		std::list< FunctionDecl * > newFuncs;
-		generatePrototypes( newFuncs );
-
-		for ( FunctionDecl * dcl : newFuncs ) {
-			genFuncBody( dcl );
-			if ( CodeGen::isAssignment( dcl->name ) ) {
-				// assignment needs to return a value
-				FunctionType * assignType = dcl->type;
-				assert( assignType->parameters.size() == 2 );
-				assert( assignType->returnVals.size() == 1 );
-				ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( assignType->parameters.front() );
-				dcl->statements->push_back( new ReturnStmt( new VariableExpr( dstParam ) ) );
-			}
-			resolve( dcl );
-		}
-	}
-
-	void FuncGenerator::generatePrototypes( std::list< FunctionDecl * > & newFuncs ) {
-		bool concurrent_type = isConcurrentType();
-		for ( const FuncData & d : data ) {
-			// generate a function (?{}, ?=?, ^?{}) based on the current FuncData.
-			FunctionType * ftype = d.genType( type, true );
-
-			// destructor for concurrent type must be mutex
-			if ( concurrent_type && CodeGen::isDestructor( d.fname ) ) {
-				ftype->parameters.front()->get_type()->set_mutex( true );
-			}
-
-			newFuncs.push_back( genFunc( d.fname, ftype, functionNesting ) );
-		}
-	}
-
-	void FuncGenerator::resolve( FunctionDecl * dcl ) {
-		try {
-			if (!useNewAST) // attempt to delay resolver call
-				ResolvExpr::resolveDecl( dcl, indexer );
-			if ( functionNesting == 0 ) {
-				// forward declare if top-level struct, so that
-				// type is complete as soon as its body ends
-				// Note: this is necessary if we want structs which contain
-				// generic (otype) structs as members.
-				addForwardDecl( dcl, forwards );
-			}
-			definitions.push_back( dcl );
-			indexer.addId( dcl );
-		} catch ( SemanticErrorException & ) {
-			// okay if decl does not resolve - that means the function should not be generated
-			// delete dcl;
-			delete dcl->statements;
-			dcl->statements = nullptr;
-			dcl->isDeleted = true;
-			definitions.push_back( dcl );
-			indexer.addId( dcl );
-		}
-	}
-
-	bool StructFuncGenerator::shouldAutogen() const {
-		// Builtins do not use autogeneration.
-		return ! aggregateDecl->linkage.is_builtin;
-	}
-	bool StructFuncGenerator::isConcurrentType() const { return aggregateDecl->is_thread() || aggregateDecl->is_monitor(); }
-
-	void StructFuncGenerator::genFuncBody( FunctionDecl * dcl ) {
-		// generate appropriate calls to member ctor, assignment
-		// destructor needs to do everything in reverse, so pass "forward" based on whether the function is a destructor
-		if ( ! CodeGen::isDestructor( dcl->name ) ) {
-			makeFunctionBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), dcl );
-		} else {
-			makeFunctionBody( aggregateDecl->members.rbegin(), aggregateDecl->members.rend(), dcl, false );
-		}
-	}
-
-	void StructFuncGenerator::genFieldCtors() {
-		// field ctors are only generated if default constructor and copy constructor are both generated
-		unsigned numCtors = std::count_if( definitions.begin(), definitions.end(), [](Declaration * dcl) { return CodeGen::isConstructor( dcl->name ); } );
-
-		// Field constructors are only generated if default and copy constructor
-		// are generated, since they need access to both
-		if ( numCtors != 2 ) return;
-
-		// create constructors which take each member type as a parameter.
-		// for example, for struct A { int x, y; }; generate
-		//   void ?{}(A *, int) and void ?{}(A *, int, int)
-		FunctionType * memCtorType = genDefaultType( type );
-		for ( Declaration * member : aggregateDecl->members ) {
-			DeclarationWithType * field = strict_dynamic_cast<DeclarationWithType *>( member );
-			if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) {
-				// don't make a function whose parameter is an unnamed bitfield
-				continue;
-			}
-			// do not carry over field's attributes to parameter type
-			Type * paramType = field->get_type()->clone();
-			deleteAll( paramType->attributes );
-			paramType->attributes.clear();
-			// add a parameter corresponding to this field
-			ObjectDecl * param = new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType, nullptr );
-			cloneAll_if( field->attributes, param->attributes, [](Attribute * attr) { return attr->isValidOnFuncParam(); } );
-			memCtorType->parameters.push_back( param );
-			FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
-			makeFieldCtorBody( aggregateDecl->members.begin(), aggregateDecl->members.end(), ctor );
-			resolve( ctor );
-		}
-		delete memCtorType;
-	}
-
-	void StructFuncGenerator::makeMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, bool forward ) {
-		InitTweak::InitExpander_old srcParam( src );
-
-		// assign to destination
-		Expression *dstselect = new MemberExpr( field, new CastExpr( new VariableExpr( dstParam ), strict_dynamic_cast< ReferenceType* >( dstParam->get_type() )->base->clone() ) );
-		genImplicitCall( srcParam, dstselect, func->name, back_inserter( func->statements->kids ), field, forward );
-	}
-
-	template<typename Iterator>
-	void StructFuncGenerator::makeFunctionBody( Iterator member, Iterator end, FunctionDecl * func, bool forward ) {
-		for ( ; member != end; ++member ) {
-			if ( DeclarationWithType *field = dynamic_cast< DeclarationWithType * >( *member ) ) { // otherwise some form of type declaration, e.g. Aggregate
-				// query the type qualifiers of this field and skip assigning it if it is marked const.
-				// If it is an array type, we need to strip off the array layers to find its qualifiers.
-				Type * type = field->get_type();
-				while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
-					type = at->get_base();
-				}
-
-				if ( type->get_const() && CodeGen::isAssignment( func->name ) ) {
-					// don't assign const members, but do construct/destruct
-					continue;
-				}
-
-				assert( ! func->get_functionType()->get_parameters().empty() );
-				ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().front() );
-				ObjectDecl * srcParam = nullptr;
-				if ( func->get_functionType()->get_parameters().size() == 2 ) {
-					srcParam = dynamic_cast<ObjectDecl*>( func->get_functionType()->get_parameters().back() );
-				}
-
-				// srcParam may be NULL, in which case we have default ctor/dtor
-				assert( dstParam );
-
-				Expression *srcselect = srcParam ? new MemberExpr( field, new VariableExpr( srcParam ) ) : nullptr;
-				makeMemberOp( dstParam, srcselect, field, func, forward );
-			} // if
-		} // for
-	} // makeFunctionBody
-
-	template<typename Iterator>
-	void StructFuncGenerator::makeFieldCtorBody( Iterator member, Iterator end, FunctionDecl * func ) {
-		FunctionType * ftype = func->type;
-		std::list<DeclarationWithType*> & params = ftype->parameters;
-		assert( params.size() >= 2 );  // should not call this function for default ctor, etc.
-
-		// skip 'this' parameter
-		ObjectDecl * dstParam = dynamic_cast<ObjectDecl*>( params.front() );
-		assert( dstParam );
-		std::list<DeclarationWithType*>::iterator parameter = params.begin()+1;
-		for ( ; member != end; ++member ) {
-			if ( DeclarationWithType * field = dynamic_cast<DeclarationWithType*>( *member ) ) {
-				if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) {
-					// don't make a function whose parameter is an unnamed bitfield
-					continue;
-				} else if ( parameter != params.end() ) {
-					// matching parameter, initialize field with copy ctor
-					Expression *srcselect = new VariableExpr(*parameter);
-					makeMemberOp( dstParam, srcselect, field, func );
-					++parameter;
-				} else {
-					// no matching parameter, initialize field with default ctor
-					makeMemberOp( dstParam, nullptr, field, func );
-				}
-			}
-		}
-	}
-
-	bool UnionFuncGenerator::shouldAutogen() const {
-		// Builtins do not use autogeneration.
-		return ! aggregateDecl->linkage.is_builtin;
-	}
-
-	// xxx - is this right?
-	bool UnionFuncGenerator::isConcurrentType() const { return false; };
-
-	/// generate a single union assignment expression (using memcpy)
-	template< typename OutputIterator >
-	void UnionFuncGenerator::makeMemberOp( ObjectDecl * srcParam, ObjectDecl * dstParam, OutputIterator out ) {
-		UntypedExpr *copy = new UntypedExpr( new NameExpr( "__builtin_memcpy" ) );
-		copy->args.push_back( new AddressExpr( new VariableExpr( dstParam ) ) );
-		copy->args.push_back( new AddressExpr( new VariableExpr( srcParam ) ) );
-		copy->args.push_back( new SizeofExpr( srcParam->get_type()->clone() ) );
-		*out++ = new ExprStmt( copy );
-	}
-
-	/// generates the body of a union assignment/copy constructor/field constructor
-	void UnionFuncGenerator::genFuncBody( FunctionDecl * funcDecl ) {
-		FunctionType * ftype = funcDecl->type;
-		if ( InitTweak::isCopyConstructor( funcDecl ) || InitTweak::isAssignment( funcDecl ) ) {
-			assert( ftype->parameters.size() == 2 );
-			ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() );
-			ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.back() );
-			makeMemberOp( srcParam, dstParam, back_inserter( funcDecl->statements->kids ) );
-		} else {
-			// default ctor/dtor body is empty - add unused attribute to parameter to silence warnings
-			assert( ftype->parameters.size() == 1 );
-			ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() );
-			dstParam->attributes.push_back( new Attribute( "unused" ) );
-		}
-	}
-
-	/// generate the body of a constructor which takes parameters that match fields, e.g.
-	/// void ?{}(A *, int) and void?{}(A *, int, int) for a struct A which has two int fields.
-	void UnionFuncGenerator::genFieldCtors() {
-		// field ctors are only generated if default constructor and copy constructor are both generated
-		unsigned numCtors = std::count_if( definitions.begin(), definitions.end(), [](Declaration * dcl) { return CodeGen::isConstructor( dcl->get_name() ); } );
-
-		// Field constructors are only generated if default and copy constructor
-		// are generated, since they need access to both
-		if ( numCtors != 2 ) return;
-
-		// create a constructor which takes the first member type as a parameter.
-		// for example, for Union A { int x; double y; }; generate
-		// void ?{}(A *, int)
-		// This is to mimic C's behaviour which initializes the first member of the union.
-		FunctionType * memCtorType = genDefaultType( type );
-		for ( Declaration * member : aggregateDecl->members ) {
-			DeclarationWithType * field = strict_dynamic_cast<DeclarationWithType *>( member );
-			if ( isUnnamedBitfield( dynamic_cast< ObjectDecl * > ( field ) ) ) {
-				// don't make a function whose parameter is an unnamed bitfield
-				break;
-			}
-			// do not carry over field's attributes to parameter type
-			Type * paramType = field->get_type()->clone();
-			deleteAll( paramType->attributes );
-			paramType->attributes.clear();
-			// add a parameter corresponding to this field
-			memCtorType->parameters.push_back( new ObjectDecl( field->name, Type::StorageClasses(), LinkageSpec::Cforall, nullptr, paramType, nullptr ) );
-			FunctionDecl * ctor = genFunc( "?{}", memCtorType->clone(), functionNesting );
-			ObjectDecl * srcParam = strict_dynamic_cast<ObjectDecl *>( ctor->type->parameters.back() );
-			srcParam->fixUniqueId();
-			ObjectDecl * dstParam = InitTweak::getParamThis( ctor->type );
-			makeMemberOp( srcParam, dstParam, back_inserter( ctor->statements->kids ) );
-			resolve( ctor );
-			// only generate one field ctor for unions
-			break;
-		}
-		delete memCtorType;
-	}
-
-	void EnumFuncGenerator::genFuncBody( FunctionDecl * funcDecl ) {
-		// xxx - Temporary: make these functions intrinsic so they codegen as C assignment.
-		// Really they're something of a cross between instrinsic and autogen, so should
-		// probably make a new linkage type
-		funcDecl->linkage = LinkageSpec::Intrinsic;
-		FunctionType * ftype = funcDecl->type;
-		if ( InitTweak::isCopyConstructor( funcDecl ) || InitTweak::isAssignment( funcDecl ) ) {
-			assert( ftype->parameters.size() == 2 );
-			ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() );
-			ObjectDecl * srcParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.back() );
-
-			// enum copy construct and assignment is just C-style assignment.
-			// this looks like a bad recursive call, but code gen will turn it into
-			// a C-style assignment.
-			// This happens before function pointer type conversion, so need to do it manually here
-			ApplicationExpr * callExpr = new ApplicationExpr( VariableExpr::functionPointer( funcDecl ) );
-			callExpr->get_args().push_back( new VariableExpr( dstParam ) );
-			callExpr->get_args().push_back( new VariableExpr( srcParam ) );
-			funcDecl->statements->push_back( new ExprStmt( callExpr ) );
-		} else {
-			// default ctor/dtor body is empty - add unused attribute to parameter to silence warnings
-			assert( ftype->parameters.size() == 1 );
-			ObjectDecl * dstParam = strict_dynamic_cast< ObjectDecl * >( ftype->parameters.front() );
-			dstParam->attributes.push_back( new Attribute( "unused" ) );
-		}
-	}
-
-	bool EnumFuncGenerator::shouldAutogen() const { return true; }
-	bool EnumFuncGenerator::isConcurrentType() const { return false; }
-	// enums do not have field constructors
-	void EnumFuncGenerator::genFieldCtors() {}
-
-	bool TypeFuncGenerator::shouldAutogen() const { return true; };
-
-	void TypeFuncGenerator::genFuncBody( FunctionDecl * dcl ) {
-		FunctionType * ftype = dcl->type;
-		assertf( ftype->parameters.size() == 1 || ftype->parameters.size() == 2, "Incorrect number of parameters in autogenerated typedecl function: %zd", ftype->parameters.size() );
-		DeclarationWithType * dst = ftype->parameters.front();
-		DeclarationWithType * src = ftype->parameters.size() == 2 ? ftype->parameters.back() : nullptr;
-		// generate appropriate calls to member ctor, assignment
-		UntypedExpr * expr = new UntypedExpr( new NameExpr( dcl->name ) );
-		expr->args.push_back( new CastExpr( new VariableExpr( dst ), new ReferenceType( Type::Qualifiers(), typeDecl->base->clone() ) ) );
-		if ( src ) expr->args.push_back( new CastExpr( new VariableExpr( src ), typeDecl->base->clone() ) );
-		dcl->statements->kids.push_back( new ExprStmt( expr ) );
-	};
-
-	// xxx - should reach in and determine if base type is concurrent?
-	bool TypeFuncGenerator::isConcurrentType() const { return false; };
-
-	// opaque types do not have field constructors
-	void TypeFuncGenerator::genFieldCtors() {};
-
-	//=============================================================================================
-	// Visitor definitions
-	//=============================================================================================
-	AutogenerateRoutines::AutogenerateRoutines() {
-		// the order here determines the order that these functions are generated.
-		// assignment should come last since it uses copy constructor in return.
-		data.emplace_back( "?{}", genDefaultType );
-		data.emplace_back( "?{}", genCopyType );
-		data.emplace_back( "^?{}", genDefaultType );
-		data.emplace_back( "?=?", genAssignType );
-	}
-
-	void AutogenerateRoutines::previsit( EnumDecl * enumDecl ) {
-		// must visit children (enum constants) to add them to the indexer
-		if ( enumDecl->has_body() ) {
-			EnumInstType enumInst( Type::Qualifiers(), enumDecl->get_name() );
-			enumInst.set_baseEnum( enumDecl );
-			EnumFuncGenerator gen( &enumInst, data, functionNesting, indexer );
-			generateFunctions( gen, declsToAddAfter );
-		}
-	}
-
-	void AutogenerateRoutines::previsit( StructDecl * structDecl ) {
-		visit_children = false;
-		if ( structDecl->has_body() ) {
-			StructInstType structInst( Type::Qualifiers(), structDecl->name );
-			structInst.set_baseStruct( structDecl );
-			for ( TypeDecl * typeDecl : structDecl->parameters ) {
-				structInst.parameters.push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->name, typeDecl ) ) );
-			}
-			StructFuncGenerator gen( structDecl, &structInst, data, functionNesting, indexer );
-			generateFunctions( gen, declsToAddAfter );
-		} // if
-	}
-
-	void AutogenerateRoutines::previsit( UnionDecl * unionDecl ) {
-		visit_children = false;
-		if ( unionDecl->has_body()  ) {
-			UnionInstType unionInst( Type::Qualifiers(), unionDecl->get_name() );
-			unionInst.set_baseUnion( unionDecl );
-			for ( TypeDecl * typeDecl : unionDecl->get_parameters() ) {
-				unionInst.get_parameters().push_back( new TypeExpr( new TypeInstType( Type::Qualifiers(), typeDecl->get_name(), typeDecl ) ) );
-			}
-			UnionFuncGenerator gen( unionDecl, &unionInst, data, functionNesting, indexer );
-			generateFunctions( gen, declsToAddAfter );
-		} // if
-	}
-
-	// generate ctor/dtors/assign for typedecls, e.g., otype T = int *;
-	void AutogenerateRoutines::previsit( TypeDecl * typeDecl ) {
-		if ( ! typeDecl->base ) return;
-
-		TypeInstType refType( Type::Qualifiers(), typeDecl->name, typeDecl );
-		TypeFuncGenerator gen( typeDecl, &refType, data, functionNesting, indexer );
-		generateFunctions( gen, declsToAddAfter );
-
-	}
-
-	void AutogenerateRoutines::previsit( TraitDecl * ) {
-		// ensure that we don't add assignment ops for types defined as part of the trait
-		visit_children = false;
-	}
-
-	void AutogenerateRoutines::previsit( FunctionDecl * ) {
-		// Track whether we're currently in a function.
-		// Can ignore function type idiosyncrasies, because function type can never
-		// declare a new type.
-		functionNesting += 1;
-		GuardAction( [this]()  { functionNesting -= 1; } );
-	}
-
-	void AutogenerateRoutines::previsit( CompoundStmt * ) {
-		GuardScope( structsDone );
-	}
-
-	void makeTupleFunctionBody( FunctionDecl * function ) {
-		FunctionType * ftype = function->get_functionType();
-		assertf( ftype->get_parameters().size() == 1 || ftype->get_parameters().size() == 2, "too many parameters in generated tuple function" );
-
-		UntypedExpr * untyped = new UntypedExpr( new NameExpr( function->get_name() ) );
-
-		/// xxx - &* is used to make this easier for later passes to handle
-		untyped->get_args().push_back( new AddressExpr( UntypedExpr::createDeref( new VariableExpr( ftype->get_parameters().front() ) ) ) );
-		if ( ftype->get_parameters().size() == 2 ) {
-			untyped->get_args().push_back( new VariableExpr( ftype->get_parameters().back() ) );
-		}
-		function->get_statements()->get_kids().push_back( new ExprStmt( untyped ) );
-		function->get_statements()->get_kids().push_back( new ReturnStmt( UntypedExpr::createDeref( new VariableExpr( ftype->get_parameters().front() ) ) ) );
-	}
-
-	void AutogenTupleRoutines::postvisit( TupleType * tupleType ) {
-		std::string mangleName = SymTab::Mangler::mangleType( tupleType );
-		if ( seenTuples.find( mangleName ) != seenTuples.end() ) return;
-		seenTuples.insert( mangleName );
-
-		// T ?=?(T *, T);
-		FunctionType *assignType = genAssignType( tupleType );
-
-		// void ?{}(T *); void ^?{}(T *);
-		FunctionType *ctorType = genDefaultType( tupleType );
-		FunctionType *dtorType = genDefaultType( tupleType );
-
-		// void ?{}(T *, T);
-		FunctionType *copyCtorType = genCopyType( tupleType );
-
-		std::set< TypeDecl* > done;
-		std::list< TypeDecl * > typeParams;
-		for ( Type * t : *tupleType ) {
-			if ( TypeInstType * ty = dynamic_cast< TypeInstType * >( t ) ) {
-				if ( ! done.count( ty->get_baseType() ) ) {
-					TypeDecl * newDecl = new TypeDecl( ty->get_baseType()->get_name(), Type::StorageClasses(), nullptr, TypeDecl::Dtype, true );
-					TypeInstType * inst = new TypeInstType( Type::Qualifiers(), newDecl->get_name(), newDecl );
-					newDecl->get_assertions().push_back( new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Cforall, genAssignType( inst ), nullptr,
-																		   std::list< Attribute * >(), Type::FuncSpecifiers( Type::Inline ) ) );
-					newDecl->get_assertions().push_back( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, genDefaultType( inst ), nullptr,
-																		   std::list< Attribute * >(), Type::FuncSpecifiers( Type::Inline ) ) );
-					newDecl->get_assertions().push_back( new FunctionDecl( "?{}", Type::StorageClasses(), LinkageSpec::Cforall, genCopyType( inst ), nullptr,
-																		   std::list< Attribute * >(), Type::FuncSpecifiers( Type::Inline ) ) );
-					newDecl->get_assertions().push_back( new FunctionDecl( "^?{}", Type::StorageClasses(), LinkageSpec::Cforall, genDefaultType( inst ), nullptr,
-																		   std::list< Attribute * >(), Type::FuncSpecifiers( Type::Inline ) ) );
-					typeParams.push_back( newDecl );
-					done.insert( ty->get_baseType() );
-				}
-			}
-		}
-		cloneAll( typeParams, ctorType->get_forall() );
-		cloneAll( typeParams, dtorType->get_forall() );
-		cloneAll( typeParams, copyCtorType->get_forall() );
-		cloneAll( typeParams, assignType->get_forall() );
-
-		FunctionDecl *assignDecl = genFunc( "?=?", assignType, functionNesting );
-		FunctionDecl *ctorDecl = genFunc( "?{}", ctorType, functionNesting );
-		FunctionDecl *copyCtorDecl = genFunc( "?{}", copyCtorType, functionNesting );
-		FunctionDecl *dtorDecl = genFunc( "^?{}", dtorType, functionNesting );
-
-		makeTupleFunctionBody( assignDecl );
-		makeTupleFunctionBody( ctorDecl );
-		makeTupleFunctionBody( copyCtorDecl );
-		makeTupleFunctionBody( dtorDecl );
-
-		declsToAddBefore.push_back( ctorDecl );
-		declsToAddBefore.push_back( copyCtorDecl );
-		declsToAddBefore.push_back( dtorDecl );
-		declsToAddBefore.push_back( assignDecl ); // assignment should come last since it uses copy constructor in return
-	}
-
-	void AutogenTupleRoutines::previsit( FunctionDecl *functionDecl ) {
-		visit_children = false;
-		maybeAccept( functionDecl->type, *visitor );
-		functionNesting += 1;
-		maybeAccept( functionDecl->statements, *visitor );
-		functionNesting -= 1;
-	}
-
-	void AutogenTupleRoutines::previsit( CompoundStmt * ) {
-		GuardScope( seenTuples );
-	}
-} // SymTab
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/SymTab/Autogen.h
===================================================================
--- src/SymTab/Autogen.h	(revision 934fa0fc6af3737f7f5b45e08f4b84e1e8259312)
+++ 	(revision )
@@ -1,225 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// Autogen.h --
-//
-// Author           : Rob Schluntz
-// Created On       : Sun May 17 21:53:34 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Fri Apr 14 15:06:00 2023
-// Update Count     : 17
-//
-
-#pragma once
-
-#include <cassert>                // for assert
-#include <iterator>               // for back_inserter
-#include <string>                 // for string
-
-#include "CodeGen/OperatorTable.h"
-#include "Common/UniqueName.h"    // for UniqueName
-#include "Common/utility.h"       // for splice
-#include "InitTweak/InitTweak.h"  // for InitExpander
-#include "SynTree/Constant.h"     // for Constant
-#include "SynTree/Declaration.h"  // for DeclarationWithType, ObjectDecl
-#include "SynTree/Expression.h"   // for NameExpr, ConstantExpr, UntypedExpr...
-#include "SynTree/Type.h"         // for Type, ArrayType, Type::Qualifiers
-#include "SynTree/Statement.h"    // for CompoundStmt, DeclStmt, ExprStmt
-
-class CompoundStmt;
-class Statement;
-
-namespace SymTab {
-	/// Generates assignment operators, constructors, and destructor for aggregate types as required
-	void autogenerateRoutines( std::list< Declaration * > &translationUnit );
-
-	/// returns true if obj's name is the empty string and it has a bitfield width
-	bool isUnnamedBitfield( ObjectDecl * obj );
-
-	/// generate the type of an assignment function for paramType.
-	/// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
-	FunctionType * genAssignType( Type * paramType, bool maybePolymorphic = true );
-
-	/// generate the type of a default constructor or destructor for paramType.
-	/// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
-	FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
-
-	/// generate the type of a copy constructor for paramType.
-	/// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
-	FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true );
-
-	/// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
-	template< typename OutputIterator >
-	Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
-
-	/// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
-	/// optionally returns a statement which must be inserted prior to the containing loop, if there is one
-	template< typename OutputIterator >
-	Statement * genScalarCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, std::string fname, OutputIterator out, Type * type, Type * addCast = nullptr ) {
-		bool isReferenceCtorDtor = false;
-		if ( dynamic_cast< ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
-			// reference constructors are essentially application of the rebind operator.
-			// apply & to both arguments, do not need a cast
-			fname = "?=?";
-			dstParam = new AddressExpr( dstParam );
-			addCast = nullptr;
-			isReferenceCtorDtor = true;
-		}
-
-		// want to be able to generate assignment, ctor, and dtor generically,
-		// so fname is either ?=?, ?{}, or ^?{}
-		UntypedExpr * fExpr = new UntypedExpr( new NameExpr( fname ) );
-
-		if ( addCast ) {
-			// cast to T& with qualifiers removed, so that qualified objects can be constructed
-			// and destructed with the same functions as non-qualified objects.
-			// unfortunately, lvalue is considered a qualifier. For AddressExpr to resolve, its argument
-			// must have an lvalue qualified type, so remove all qualifiers except lvalue. If we ever
-			// remove lvalue as a qualifier, this can change to
-			//   type->get_qualifiers() = Type::Qualifiers();
-			Type * castType = addCast->clone();
-			castType->get_qualifiers() -= Type::Qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic );
-			// castType->set_lvalue( true ); // xxx - might not need this
-			dstParam = new CastExpr( dstParam, new ReferenceType( Type::Qualifiers(), castType ) );
-		}
-		fExpr->args.push_back( dstParam );
-
-		Statement * listInit = srcParam.buildListInit( fExpr );
-
-		// fetch next set of arguments
-		++srcParam;
-
-		// return if adding reference fails - will happen on default constructor and destructor
-		if ( isReferenceCtorDtor && ! srcParam.addReference() ) {
-			delete fExpr;
-			return listInit;
-		}
-
-		std::list< Expression * > args = *srcParam;
-		fExpr->args.splice( fExpr->args.end(), args );
-
-		*out++ = new ExprStmt( fExpr );
-
-		srcParam.clearArrayIndices();
-
-		return listInit;
-	}
-
-	/// Store in out a loop which calls fname on each element of the array with srcParam and dstParam as arguments.
-	/// If forward is true, loop goes from 0 to N-1, else N-1 to 0
-	template< typename OutputIterator >
-	void genArrayCall( InitTweak::InitExpander_old & srcParam, Expression *dstParam, const std::string & fname, OutputIterator out, ArrayType *array, Type * addCast = nullptr, bool forward = true ) {
-		static UniqueName indexName( "_index" );
-
-		// for a flexible array member nothing is done -- user must define own assignment
-		if ( ! array->get_dimension() ) return;
-
-		if ( addCast ) {
-			// peel off array layer from cast
-			ArrayType * at = strict_dynamic_cast< ArrayType * >( addCast );
-			addCast = at->base;
-		}
-
-		Expression * begin, * end, * update, * cmp;
-		if ( forward ) {
-			// generate: for ( int i = 0; i < N; ++i )
-			begin = new ConstantExpr( Constant::from_int( 0 ) );
-			end = array->dimension->clone();
-			cmp = new NameExpr( "?<?" );
-			update = new NameExpr( "++?" );
-		} else {
-			// generate: for ( int i = N-1; i >= 0; --i )
-			begin = new UntypedExpr( new NameExpr( "?-?" ) );
-			((UntypedExpr*)begin)->args.push_back( array->dimension->clone() );
-			((UntypedExpr*)begin)->args.push_back( new ConstantExpr( Constant::from_int( 1 ) ) );
-			end = new ConstantExpr( Constant::from_int( 0 ) );
-			cmp = new NameExpr( "?>=?" );
-			update = new NameExpr( "--?" );
-		}
-
-		ObjectDecl *index = new ObjectDecl( indexName.newName(), Type::StorageClasses(), LinkageSpec::C, 0, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), new SingleInit( begin ) );
-
-		UntypedExpr *cond = new UntypedExpr( cmp );
-		cond->args.push_back( new VariableExpr( index ) );
-		cond->args.push_back( end );
-
-		UntypedExpr *inc = new UntypedExpr( update );
-		inc->args.push_back( new VariableExpr( index ) );
-
-		UntypedExpr *dstIndex = new UntypedExpr( new NameExpr( "?[?]" ) );
-		dstIndex->args.push_back( dstParam );
-		dstIndex->args.push_back( new VariableExpr( index ) );
-		dstParam = dstIndex;
-
-		// srcParam must keep track of the array indices to build the
-		// source parameter and/or array list initializer
-		srcParam.addArrayIndex( new VariableExpr( index ), array->dimension->clone() );
-
-		// for stmt's body, eventually containing call
-		CompoundStmt * body = new CompoundStmt();
-		Statement * listInit = genCall( srcParam, dstParam, fname, back_inserter( body->kids ), array->base, addCast, forward );
-
-		// block containing for stmt and index variable
-		std::list<Statement *> initList;
-		CompoundStmt * block = new CompoundStmt();
-		block->push_back( new DeclStmt( index ) );
-		if ( listInit ) block->get_kids().push_back( listInit );
-		block->push_back( new ForStmt( initList, cond, inc, body ) );
-
-		*out++ = block;
-	}
-
-	template< typename OutputIterator >
-	Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
-		if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
-			genArrayCall( srcParam, dstParam, fname, out, at, addCast, forward );
-			return 0;
-		} else {
-			return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
-		}
-	}
-
-	/// inserts into out a generated call expression to function fname with arguments dstParam
-	/// and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. decl is the
-	/// object being constructed. The function wraps constructor and destructor calls in an
-	/// ImplicitCtorDtorStmt node.
-	template< typename OutputIterator >
-	void genImplicitCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, DeclarationWithType * decl, bool forward = true ) {
-		ObjectDecl *obj = dynamic_cast<ObjectDecl *>( decl );
-		assert( obj );
-		// unnamed bit fields are not copied as they cannot be accessed
-		if ( isUnnamedBitfield( obj ) ) return;
-
-		Type * addCast = nullptr;
-		if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && ! obj->get_bitfieldWidth() ) ) ) {
-			assert( dstParam->result );
-			addCast = dstParam->result;
-		}
-		std::list< Statement * > stmts;
-		genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->type, addCast, forward );
-
-		// currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call
-		assert( stmts.size() <= 1 );
-		if ( stmts.size() == 1 ) {
-			Statement * callStmt = stmts.front();
-			if ( addCast ) {
-				// implicitly generated ctor/dtor calls should be wrapped
-				// so that later passes are aware they were generated.
-				// xxx - don't mark as an implicit ctor/dtor if obj is a bitfield,
-				// because this causes the address to be taken at codegen, which is illegal in C.
-				callStmt = new ImplicitCtorDtorStmt( callStmt );
-			}
-			*out++ = callStmt;
-		}
-	}
-
-} // namespace SymTab
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/SymTab/Demangle.cc
===================================================================
--- src/SymTab/Demangle.cc	(revision 934fa0fc6af3737f7f5b45e08f4b84e1e8259312)
+++ src/SymTab/Demangle.cc	(revision c6b4432f5c6c6679b981f5a6bded51ad30ac00d9)
@@ -21,9 +21,6 @@
 #include "CodeGen/GenType.h"
 #include "CodeGen/OperatorTable.h"
-#include "Common/PassVisitor.h"
 #include "Common/utility.h"								// isPrefix
 #include "Mangler.h"
-#include "SynTree/Type.h"
-#include "SynTree/Declaration.h"
 
 #define DEBUG
@@ -33,300 +30,4 @@
 #define PRINT(x) {}
 #endif
-
-namespace SymTab {
-	namespace Mangler {
-		namespace {
-			struct StringView {
-			private:
-				std::string str;
-				size_t idx = 0;
-				// typedef Type * (StringView::*parser)(Type::Qualifiers);
-				typedef std::function<Type * (Type::Qualifiers)> parser;
-				std::vector<std::pair<std::string, parser>> parsers;
-			public:
-				StringView(const std::string & str);
-
-				bool done() const { return idx >= str.size(); }
-				char cur() const { assert(! done()); return str[idx]; }
-
-				bool expect(char ch) { return str[idx++] == ch;	}
-				void next(size_t inc = 1) { idx += inc; }
-
-				/// determines if `pref` is a prefix of `str`
-				bool isPrefix(const std::string & pref);
-				bool extractNumber(size_t & out);
-				bool extractName(std::string & out);
-				bool stripMangleName(std::string & name);
-
-				Type * parseFunction(Type::Qualifiers tq);
-				Type * parseTuple(Type::Qualifiers tq);
-				Type * parseVoid(Type::Qualifiers tq);
-				Type * parsePointer(Type::Qualifiers tq);
-				Type * parseArray(Type::Qualifiers tq);
-				Type * parseStruct(Type::Qualifiers tq);
-				Type * parseUnion(Type::Qualifiers tq);
-				Type * parseEnum(Type::Qualifiers tq);
-				Type * parseType(Type::Qualifiers tq);
-
-				Type * parseType();
-				bool parse(std::string & name, Type *& type);
-			};
-
-			StringView::StringView(const std::string & str) : str(str) {
-				// basic types
-				for (size_t k = 0; k < BasicType::NUMBER_OF_BASIC_TYPES; ++k) {
-					parsers.emplace_back(Encoding::basicTypes[k], [k](Type::Qualifiers tq) {
-						PRINT( std::cerr << "basic type: " << k << std::endl; )
-						return new BasicType(tq, (BasicType::Kind)k);
-					});
-				}
-				// type variable types
-				for (size_t k = 0; k < TypeDecl::NUMBER_OF_KINDS; ++k) {
-					static const std::string typeVariableNames[] = { "DT", "DST", "OT", "FT", "TT", "ALT", };
-					static_assert(
-						sizeof(typeVariableNames)/sizeof(typeVariableNames[0]) == TypeDecl::NUMBER_OF_KINDS,
-						"Each type variable kind should have a demangle name prefix"
-					);
-					parsers.emplace_back(Encoding::typeVariables[k], [k, this](Type::Qualifiers tq) -> TypeInstType * {
-						PRINT( std::cerr << "type variable type: " << k << std::endl; )
-						size_t N;
-						if (! extractNumber(N)) return nullptr;
-						return new TypeInstType(tq, toString(typeVariableNames[k], N), (TypeDecl::Kind)k != TypeDecl::Ftype);
-					});
-				}
-				// everything else
-				parsers.emplace_back(Encoding::void_t, [this](Type::Qualifiers tq) { return parseVoid(tq); });
-				parsers.emplace_back(Encoding::function, [this](Type::Qualifiers tq) { return parseFunction(tq); });
-				parsers.emplace_back(Encoding::pointer, [this](Type::Qualifiers tq) { return parsePointer(tq); });
-				parsers.emplace_back(Encoding::array, [this](Type::Qualifiers tq) { return parseArray(tq); });
-				parsers.emplace_back(Encoding::tuple, [this](Type::Qualifiers tq) { return parseTuple(tq); });
-				parsers.emplace_back(Encoding::struct_t, [this](Type::Qualifiers tq) { return parseStruct(tq); });
-				parsers.emplace_back(Encoding::union_t, [this](Type::Qualifiers tq) { return parseUnion(tq); });
-				parsers.emplace_back(Encoding::enum_t, [this](Type::Qualifiers tq) { return parseEnum(tq); });
-				parsers.emplace_back(Encoding::type, [this](Type::Qualifiers tq) { return parseType(tq); });
-				parsers.emplace_back(Encoding::zero, [](Type::Qualifiers tq) { return new ZeroType(tq); });
-				parsers.emplace_back(Encoding::one, [](Type::Qualifiers tq) { return new OneType(tq); });
-			}
-
-			bool StringView::extractNumber(size_t & out) {
-				std::stringstream numss;
-				if (idx >= str.size()) return false;
-				while (isdigit(str[idx])) {
-					numss << str[idx];
-					++idx;
-					if (idx == str.size()) break;
-				}
-				if (! (numss >> out)) return false;
-				PRINT( std::cerr << "extractNumber success: " << out << std::endl; )
-				return true;
-			}
-
-			bool StringView::extractName(std::string & out) {
-				size_t len;
-				if (! extractNumber(len)) return false;
-				if (idx+len > str.size()) return false;
-				out = str.substr(idx, len);
-				idx += len;
-				PRINT( std::cerr << "extractName success: " << out << std::endl; )
-				return true;
-			}
-
-			bool StringView::isPrefix(const std::string & pref) {
-				// if ( pref.size() > str.size()-idx ) return false;
-				// auto its = std::mismatch( pref.begin(), pref.end(), std::next(str.begin(), idx) );
-				// if (its.first == pref.end()) {
-				// 	idx += pref.size();
-				// 	return true;
-				// }
-
-				// This update is untested because there are no tests for this code.
-				if ( ::isPrefix( str, pref, idx ) ) {
-					idx += pref.size();
-					return true;
-				}
-				return false;
-			}
-
-			// strips __NAME__cfa__TYPE_N, where N is [0-9]+: returns str is a match is found, returns empty string otherwise
-			bool StringView::stripMangleName(std::string & name) {
-				PRINT( std::cerr << "====== " << str.size() << " " << str << std::endl; )
-				if (str.size() < 2+Encoding::manglePrefix.size()) return false; // +2 for at least _1 suffix
-				if ( ! isPrefix(Encoding::manglePrefix) || ! isdigit(str.back() ) ) return false;
-
-				// get name
-				if (! extractName(name)) return false;
-
-				// find bounds for type
-				PRINT( std::cerr << idx << " " << str.size() << std::endl; )
-				PRINT( std::cerr << "[");
-				while (isdigit(str.back())) {
-					PRINT(std::cerr << ".");
-					str.pop_back();
-					if (str.size() <= idx) return false;
-				}
-				PRINT( std::cerr << "]" << std::endl );
-				if (str.back() != '_') return false;
-				str.pop_back();
-				PRINT( std::cerr << str.size() << " " << name << " " << str.substr(idx) << std::endl; )
-				return str.size() > idx;
-			}
-
-			Type * StringView::parseFunction(Type::Qualifiers tq) {
-				PRINT( std::cerr << "function..." << std::endl; )
-				if (done()) return nullptr;
-				FunctionType * ftype = new FunctionType( tq, false );
-				std::unique_ptr<Type> manager(ftype);
-				Type * retVal = parseType();
-				if (! retVal) return nullptr;
-				PRINT( std::cerr << "with return type: " << retVal << std::endl; )
-				ftype->returnVals.push_back(ObjectDecl::newObject("", retVal, nullptr));
-				if (done() || ! expect('_')) return nullptr;
-				while (! done()) {
-					PRINT( std::cerr << "got ch: " << cur() << std::endl; )
-					if (cur() == '_') return manager.release();
-					Type * param = parseType();
-					if (! param) return nullptr;
-					PRINT( std::cerr << "with parameter : " << param << std::endl; )
-					ftype->parameters.push_back(ObjectDecl::newObject("", param, nullptr));
-				}
-				return nullptr;
-			}
-
-			Type * StringView::parseTuple(Type::Qualifiers tq) {
-				PRINT( std::cerr << "tuple..." << std::endl; )
-				std::list< Type * > types;
-				size_t ncomponents;
-				if (! extractNumber(ncomponents)) return nullptr;
-				for (size_t i = 0; i < ncomponents; ++i) {
-					// TODO: delete all on return
-					if (done()) return nullptr;
-					PRINT( std::cerr << "got ch: " << cur() << std::endl; )
-					Type * t = parseType();
-					if (! t) return nullptr;
-					PRINT( std::cerr << "with type : " << t << std::endl; )
-					types.push_back(t);
-				}
-				return new TupleType( tq, types );
-			}
-
-			Type * StringView::parseVoid(Type::Qualifiers tq) {
-				return new VoidType( tq );
-			}
-
-			Type * StringView::parsePointer(Type::Qualifiers tq) {
-				PRINT( std::cerr << "pointer..." << std::endl; )
-				Type * t = parseType();
-				if (! t) return nullptr;
-				return new PointerType( tq, t );
-			}
-
-			Type * StringView::parseArray(Type::Qualifiers tq) {
-				PRINT( std::cerr << "array..." << std::endl; )
-				size_t length;
-				if (! extractNumber(length)) return nullptr;
-				Type * t = parseType();
-				if (! t) return nullptr;
-				return new ArrayType( tq, t, new ConstantExpr( Constant::from_ulong(length) ), false, false );
-			}
-
-			Type * StringView::parseStruct(Type::Qualifiers tq) {
-				PRINT( std::cerr << "struct..." << std::endl; )
-				std::string name;
-				if (! extractName(name)) return nullptr;
-				return new StructInstType(tq, name);
-			}
-
-			Type * StringView::parseUnion(Type::Qualifiers tq) {
-				PRINT( std::cerr << "union..." << std::endl; )
-				std::string name;
-				if (! extractName(name)) return nullptr;
-				return new UnionInstType(tq, name);
-			}
-
-			Type * StringView::parseEnum(Type::Qualifiers tq) {
-				PRINT( std::cerr << "enum..." << std::endl; )
-				std::string name;
-				if (! extractName(name)) return nullptr;
-				return new EnumInstType(tq, name);
-			}
-
-			Type * StringView::parseType(Type::Qualifiers tq) {
-				PRINT( std::cerr << "type..." << std::endl; )
-				std::string name;
-				if (! extractName(name)) return nullptr;
-				PRINT( std::cerr << "typename..." << name << std::endl; )
-				return new TypeInstType(tq, name, false);
-			}
-
-			Type * StringView::parseType() {
-				if (done()) return nullptr;
-
-				std::list<TypeDecl *> forall;
-				if (isPrefix(Encoding::forall)) {
-					PRINT( std::cerr << "polymorphic with..." << std::endl; )
-					size_t dcount, fcount, vcount, acount;
-					if (! extractNumber(dcount)) return nullptr;
-					PRINT( std::cerr << dcount << " dtypes" << std::endl; )
-					if (! expect('_')) return nullptr;
-					if (! extractNumber(fcount)) return nullptr;
-					PRINT( std::cerr << fcount << " ftypes" << std::endl; )
-					if (! expect('_')) return nullptr;
-					if (! extractNumber(vcount)) return nullptr;
-					PRINT( std::cerr << vcount << " ttypes" << std::endl; )
-					if (! expect('_')) return nullptr;
-					if (! extractNumber(acount)) return nullptr;
-					PRINT( std::cerr << acount << " assertions" << std::endl; )
-					if (! expect('_')) return nullptr;
-					for (size_t i = 0; i < acount; ++i) {
-						// TODO: need to recursively parse assertions, but for now just return nullptr so that
-						// demangler does not crash if there are assertions
-						return nullptr;
-					}
-					if (! expect('_')) return nullptr;
-				}
-
-				// qualifiers
-				Type::Qualifiers tq;
-				while (true) {
-					auto qual = std::find_if(Encoding::qualifiers.begin(), Encoding::qualifiers.end(), [this](decltype(Encoding::qualifiers)::value_type val) {
-						return isPrefix(val.second);
-					});
-					if (qual == Encoding::qualifiers.end()) break;
-					tq |= qual->first;
-				}
-
-				// find the correct type parser and use it
-				auto iter = std::find_if(parsers.begin(), parsers.end(), [this](std::pair<std::string, parser> & p) {
-					return isPrefix(p.first);
-				});
-				assertf(iter != parsers.end(), "Unhandled type letter: %c at index: %zd", cur(), idx);
-				Type * ret = iter->second(tq);
-				if (! ret) return nullptr;
-				ret->forall = std::move(forall);
-				return ret;
-			}
-
-			bool StringView::parse(std::string & name, Type *& type) {
-				if (! stripMangleName(name)) return false;
-				PRINT( std::cerr << "stripped name: " << name << std::endl; )
-				Type * t = parseType();
-				if (! t) return false;
-				type = t;
-				return true;
-			}
-
-			std::string demangle(const std::string & mangleName) {
-				SymTab::Mangler::StringView view(mangleName);
-				std::string name;
-				Type * type = nullptr;
-				if (! view.parse(name, type)) return mangleName;
-				auto info = CodeGen::operatorLookupByOutput(name);
-				if (info) name = info->inputName;
-				std::unique_ptr<Type> manager(type);
-				return CodeGen::genType(type, name);
-			}
-		} // namespace
-	} // namespace Mangler
-} // namespace SymTab
 
 namespace Mangle {
@@ -550,5 +251,4 @@
 	if (done()) return nullptr;
 
-	std::list<TypeDecl *> forall;
 	if (isPrefix(Encoding::forall)) {
 		PRINT( std::cerr << "polymorphic with..." << std::endl; )
Index: src/SymTab/FixFunction.cc
===================================================================
--- src/SymTab/FixFunction.cc	(revision 934fa0fc6af3737f7f5b45e08f4b84e1e8259312)
+++ src/SymTab/FixFunction.cc	(revision c6b4432f5c6c6679b981f5a6bded51ad30ac00d9)
@@ -22,83 +22,6 @@
 #include "AST/Type.hpp"
 #include "Common/utility.h"       // for copy
-#include "SynTree/Declaration.h"  // for FunctionDecl, ObjectDecl, Declarati...
-#include "SynTree/Expression.h"   // for Expression
-#include "SynTree/Type.h"         // for ArrayType, PointerType, Type, Basic...
 
 namespace SymTab {
-	class FixFunction_old : public WithShortCircuiting {
-		typedef Mutator Parent;
-	  public:
-		FixFunction_old() : isVoid( false ) {}
-
-		void premutate(FunctionDecl *functionDecl);
-		DeclarationWithType* postmutate(FunctionDecl *functionDecl);
-
-		Type * postmutate(ArrayType * arrayType);
-
-		void premutate(ArrayType * arrayType);
-		void premutate(VoidType * voidType);
-		void premutate(BasicType * basicType);
-		void premutate(PointerType * pointerType);
-		void premutate(StructInstType * aggregateUseType);
-		void premutate(UnionInstType * aggregateUseType);
-		void premutate(EnumInstType * aggregateUseType);
-		void premutate(TraitInstType * aggregateUseType);
-		void premutate(TypeInstType * aggregateUseType);
-		void premutate(TupleType * tupleType);
-		void premutate(VarArgsType * varArgsType);
-		void premutate(ZeroType * zeroType);
-		void premutate(OneType * oneType);
-
-		bool isVoid;
-	};
-
-	DeclarationWithType * FixFunction_old::postmutate(FunctionDecl *functionDecl) {
-		// can't delete function type because it may contain assertions, so transfer ownership to new object
-		ObjectDecl *pointer = new ObjectDecl( functionDecl->name, functionDecl->get_storageClasses(), functionDecl->linkage, nullptr, new PointerType( Type::Qualifiers(), functionDecl->type ), nullptr, functionDecl->attributes );
-		pointer->location = functionDecl->location;
-		functionDecl->attributes.clear();
-		functionDecl->type = nullptr;
-		delete functionDecl;
-		return pointer;
-	}
-
-	// xxx - this passes on void[], e.g.
-	//   void foo(void [10]);
-	// does not cause an error
-
-	Type * FixFunction_old::postmutate(ArrayType *arrayType) {
-		// need to recursively mutate the base type in order for multi-dimensional arrays to work.
-		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->isVarLen, arrayType->isStatic );
-		pointerType->location = arrayType->location;
-		arrayType->base = nullptr;
-		arrayType->dimension = nullptr;
-		delete arrayType;
-		return pointerType;
-	}
-
-	void FixFunction_old::premutate(VoidType *) {
-		isVoid = true;
-	}
-
-	void FixFunction_old::premutate(FunctionDecl *) { visit_children = false; }
-	void FixFunction_old::premutate(ArrayType *) { visit_children = false; }
-	void FixFunction_old::premutate(BasicType *) { visit_children = false; }
-	void FixFunction_old::premutate(PointerType *) { visit_children = false; }
-	void FixFunction_old::premutate(StructInstType *) { visit_children = false; }
-	void FixFunction_old::premutate(UnionInstType *) { visit_children = false; }
-	void FixFunction_old::premutate(EnumInstType *) { visit_children = false; }
-	void FixFunction_old::premutate(TraitInstType *) { visit_children = false; }
-	void FixFunction_old::premutate(TypeInstType *) { visit_children = false; }
-	void FixFunction_old::premutate(TupleType *) { visit_children = false; }
-	void FixFunction_old::premutate(VarArgsType *) { visit_children = false; }
-	void FixFunction_old::premutate(ZeroType *) { visit_children = false; }
-	void FixFunction_old::premutate(OneType *) { visit_children = false; }
-
-	bool fixFunction( DeclarationWithType *& dwt ) {
-		PassVisitor<FixFunction_old> fixer;
-		dwt = dwt->acceptMutator( fixer );
-		return fixer.pass.isVoid;
-	}
 
 namespace {
Index: src/SymTab/FixFunction.h
===================================================================
--- src/SymTab/FixFunction.h	(revision 934fa0fc6af3737f7f5b45e08f4b84e1e8259312)
+++ src/SymTab/FixFunction.h	(revision c6b4432f5c6c6679b981f5a6bded51ad30ac00d9)
@@ -16,7 +16,4 @@
 #pragma once
 
-#include "Common/PassVisitor.h" // for PassVisitor
-#include "SynTree/SynTree.h"    // for Types
-
 namespace ast {
 	class DeclWithType;
@@ -25,8 +22,4 @@
 
 namespace SymTab {
-	/// Replaces function and array types by equivalent pointer types. Returns true if type is 
-	/// void
-	bool fixFunction( DeclarationWithType *& );
-
 	/// Returns declaration with function and array types replaced by equivalent pointer types.
 	/// Sets isVoid to true if type is void
Index: src/SymTab/Indexer.cc
===================================================================
--- src/SymTab/Indexer.cc	(revision 934fa0fc6af3737f7f5b45e08f4b84e1e8259312)
+++ 	(revision )
@@ -1,719 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// Indexer.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 21:37:33 2015
-// Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Dec 13 23:43:19 2019
-// Update Count     : 22
-//
-
-#include "Indexer.h"
-
-#include <cassert>                 // for assert, strict_dynamic_cast
-#include <string>                  // for string, operator<<, operator!=
-#include <memory>                  // for shared_ptr, make_shared
-#include <unordered_map>           // for operator!=, unordered_map<>::const...
-#include <unordered_set>           // for unordered_set
-#include <utility>                 // for pair, make_pair, move
-#include <vector>                  // for vector
-
-#include "CodeGen/OperatorTable.h" // for isCtorDtor, isCtorDtorAssign
-#include "Common/SemanticError.h"  // for SemanticError
-#include "Common/utility.h"        // for cloneAll
-#include "Common/Stats/Counter.h"  // for counters
-#include "GenPoly/GenPoly.h"       // for getFunctionType
-#include "InitTweak/InitTweak.h"   // for isConstructor, isCopyFunction, isC...
-#include "Mangler.h"               // for Mangler
-#include "ResolvExpr/AlternativeFinder.h"  // for referenceToRvalueConversion
-#include "ResolvExpr/Unify.h"      // for typesCompatible
-#include "SynTree/LinkageSpec.h"   // for isMangled, isOverridable, Spec
-#include "SynTree/Constant.h"      // for Constant
-#include "SynTree/Declaration.h"   // for DeclarationWithType, FunctionDecl
-#include "SynTree/Expression.h"    // for Expression, ImplicitCopyCtorExpr
-#include "SynTree/Initializer.h"   // for Initializer
-#include "SynTree/Statement.h"     // for CompoundStmt, Statement, ForStmt (...
-#include "SynTree/Type.h"          // for Type, StructInstType, UnionInstType
-
-namespace SymTab {
-
-	// Statistics block
-	namespace {
-		static inline auto stats() {
-			using namespace Stats::Counters;
-			static auto group   = build<CounterGroup>("Indexers");
-			static struct {
-				SimpleCounter * count;
-				AverageCounter<double> * size;
-				SimpleCounter * new_scopes;
-				SimpleCounter * lazy_scopes;
-				AverageCounter<double> * avg_scope_depth;
-				MaxCounter<size_t> * max_scope_depth;
-				SimpleCounter * add_calls;
-				SimpleCounter * lookup_calls;
-				SimpleCounter * map_lookups;
-				SimpleCounter * map_mutations;
-			} ret = {
-				.count   = build<SimpleCounter>("Count", group),
-				.size    = build<AverageCounter<double>>("Average Size", group),
-				.new_scopes = build<SimpleCounter>("Scopes", group),
-				.lazy_scopes = build<SimpleCounter>("Lazy Scopes", group),
-				.avg_scope_depth = build<AverageCounter<double>>("Average Scope", group),
-				.max_scope_depth = build<MaxCounter<size_t>>("Max Scope", group),
-				.add_calls = build<SimpleCounter>("Add Calls", group),
-				.lookup_calls = build<SimpleCounter>("Lookup Calls", group),
-				.map_lookups = build<SimpleCounter>("Map Lookups", group),
-				.map_mutations = build<SimpleCounter>("Map Mutations", group)
-			};
-			return ret;
-		}
-	}
-
-	Indexer::Indexer( bool trackIdentifiers )
-	: idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(),
-	  prevScope(), scope( 0 ), repScope( 0 ), trackIdentifiers( trackIdentifiers ) { ++* stats().count; }
-
-	Indexer::~Indexer() {
-		stats().size->push( idTable ? idTable->size() : 0 );
-	}
-
-	void Indexer::lazyInitScope() {
-		if ( repScope < scope ) {
-			++* stats().lazy_scopes;
-			// create rollback
-			prevScope = std::make_shared<Indexer>( * this );
-			// update repScope
-			repScope = scope;
-		}
-	}
-
-	void Indexer::enterScope() {
-		++scope;
-
-		++* stats().new_scopes;
-		stats().avg_scope_depth->push( scope );
-		stats().max_scope_depth->push( scope );
-	}
-
-	void Indexer::leaveScope() {
-		if ( repScope == scope ) {
-			Ptr prev = prevScope;           // make sure prevScope stays live
-			* this = std::move(* prevScope);  // replace with previous scope
-		}
-
-		--scope;
-	}
-
-	void Indexer::lookupId( const std::string & id, std::list< IdData > &out ) const {
-		assert( trackIdentifiers );
-
-		++* stats().lookup_calls;
-		if ( ! idTable ) return;
-
-		++* stats().map_lookups;
-		auto decls = idTable->find( id );
-		if ( decls == idTable->end() ) return;
-
-		for ( auto decl : *(decls->second) ) {
-			out.push_back( decl.second );
-		}
-	}
-
-	const NamedTypeDecl * Indexer::lookupType( const std::string & id ) const {
-		++* stats().lookup_calls;
-		if ( ! typeTable ) return nullptr;
-		++* stats().map_lookups;
-		auto it = typeTable->find( id );
-		return it == typeTable->end() ? nullptr : it->second.decl;
-	}
-
-	const StructDecl * Indexer::lookupStruct( const std::string & id ) const {
-		++* stats().lookup_calls;
-		if ( ! structTable ) return nullptr;
-		++* stats().map_lookups;
-		auto it = structTable->find( id );
-		return it == structTable->end() ? nullptr : it->second.decl;
-	}
-
-	const EnumDecl * Indexer::lookupEnum( const std::string & id ) const {
-		++* stats().lookup_calls;
-		if ( ! enumTable ) return nullptr;
-		++* stats().map_lookups;
-		auto it = enumTable->find( id );
-		return it == enumTable->end() ? nullptr : it->second.decl;
-	}
-
-	const UnionDecl * Indexer::lookupUnion( const std::string & id ) const {
-		++* stats().lookup_calls;
-		if ( ! unionTable ) return nullptr;
-		++* stats().map_lookups;
-		auto it = unionTable->find( id );
-		return it == unionTable->end() ? nullptr : it->second.decl;
-	}
-
-	const TraitDecl * Indexer::lookupTrait( const std::string & id ) const {
-		++* stats().lookup_calls;
-		if ( ! traitTable ) return nullptr;
-		++* stats().map_lookups;
-		auto it = traitTable->find( id );
-		return it == traitTable->end() ? nullptr : it->second.decl;
-	}
-
-	const Indexer * Indexer::atScope( unsigned long target ) const {
-		// by lazy construction, final indexer in list has repScope 0, cannot be > target
-		// otherwise, will find first scope representing the target
-		const Indexer * indexer = this;
-		while ( indexer->repScope > target ) {
-			indexer = indexer->prevScope.get();
-		}
-		return indexer;
-	}
-
-	const NamedTypeDecl * Indexer::globalLookupType( const std::string & id ) const {
-		return atScope( 0 )->lookupType( id );
-	}
-
-	const StructDecl * Indexer::globalLookupStruct( const std::string & id ) const {
-		return atScope( 0 )->lookupStruct( id );
-	}
-
-	const UnionDecl * Indexer::globalLookupUnion( const std::string & id ) const {
-		return atScope( 0 )->lookupUnion( id );
-	}
-
-	const EnumDecl * Indexer::globalLookupEnum( const std::string & id ) const {
-		return atScope( 0 )->lookupEnum( id );
-	}
-
-	bool isFunction( const DeclarationWithType * decl ) {
-		return GenPoly::getFunctionType( decl->get_type() );
-	}
-
-	bool isObject( const DeclarationWithType * decl ) {
-		return ! isFunction( decl );
-	}
-
-	bool isDefinition( const DeclarationWithType * decl ) {
-		if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) {
-			// a function is a definition if it has a body
-			return func->statements;
-		} else {
-			// an object is a definition if it is not marked extern.
-			// both objects must be marked extern
-			return ! decl->get_storageClasses().is_extern;
-		}
-	}
-
-
-	bool Indexer::addedIdConflicts(
-			const Indexer::IdData & existing, const DeclarationWithType * added,
-			Indexer::OnConflict handleConflicts, const Declaration * deleteStmt ) {
-		// if we're giving the same name mangling to things of different types then there is
-		// something wrong
-		assert( (isObject( added ) && isObject( existing.id ) )
-			|| ( isFunction( added ) && isFunction( existing.id ) ) );
-
-		if ( LinkageSpec::isOverridable( existing.id->linkage ) ) {
-			// new definition shadows the autogenerated one, even at the same scope
-			return false;
-		} else if ( LinkageSpec::isMangled( added->linkage )
-				|| ResolvExpr::typesCompatible(
-					added->get_type(), existing.id->get_type(), Indexer() ) ) {
-
-			// it is a conflict if one declaration is deleted and the other is not
-			if ( deleteStmt && ! existing.deleteStmt ) {
-				if ( handleConflicts.mode == OnConflict::Error ) {
-					SemanticError( added, "deletion of defined identifier " );
-				}
-				return true;
-			} else if ( ! deleteStmt && existing.deleteStmt ) {
-				if ( handleConflicts.mode == OnConflict::Error ) {
-					SemanticError( added, "definition of deleted identifier " );
-				}
-				return true;
-			}
-
-			if ( isDefinition( added ) && isDefinition( existing.id ) ) {
-				if ( handleConflicts.mode == OnConflict::Error ) {
-					SemanticError( added,
-						isFunction( added ) ?
-							"duplicate function definition for " :
-							"duplicate object definition for " );
-				}
-				return true;
-			} // if
-		} else {
-			if ( handleConflicts.mode == OnConflict::Error ) {
-				SemanticError( added, "duplicate definition for " );
-			}
-			return true;
-		} // if
-
-		return true;
-	}
-
-	bool Indexer::hasCompatibleCDecl( const std::string & id, const std::string &mangleName ) const {
-		if ( ! idTable ) return false;
-
-		++* stats().map_lookups;
-		auto decls = idTable->find( id );
-		if ( decls == idTable->end() ) return false;
-
-		for ( auto decl : *(decls->second) ) {
-			// skip other scopes (hidden by this decl)
-			if ( decl.second.scope != scope ) continue;
-			// check for C decl with compatible type (by mangleName)
-			if ( ! LinkageSpec::isMangled( decl.second.id->linkage ) && decl.first == mangleName ) {
-				return true;
-			}
-		}
-
-		return false;
-	}
-
-	bool Indexer::hasIncompatibleCDecl(const std::string & id, const std::string &mangleName ) const {
-		if ( ! idTable ) return false;
-
-		++* stats().map_lookups;
-		auto decls = idTable->find( id );
-		if ( decls == idTable->end() ) return false;
-
-		for ( auto decl : *(decls->second) ) {
-			// skip other scopes (hidden by this decl)
-			if ( decl.second.scope != scope ) continue;
-			// check for C decl with incompatible type (by manglename)
-			if ( ! LinkageSpec::isMangled( decl.second.id->linkage ) && decl.first != mangleName ) {
-				return true;
-			}
-		}
-
-		return false;
-	}
-
-	/// gets the base type of the first parameter; decl must be a ctor/dtor/assignment function
-	std::string getOtypeKey( const FunctionDecl * function ) {
-		auto& params = function->type->parameters;
-		assert( ! params.empty() );
-		// use base type of pointer, so that qualifiers on the pointer type aren't considered.
-		Type * base = InitTweak::getPointerBase( params.front()->get_type() );
-		assert( base );
-		return Mangler::mangle( base );
-	}
-
-	/// gets the declaration for the function acting on a type specified by otype key,
-	/// nullptr if none such
-	const FunctionDecl * getFunctionForOtype( const DeclarationWithType * decl, const std::string& otypeKey ) {
-		const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl );
-		if ( ! func || otypeKey != getOtypeKey( func ) ) return nullptr;
-		return func;
-	}
-
-	bool Indexer::removeSpecialOverrides(Indexer::IdData& data, Indexer::MangleTable::Ptr& mangleTable ) {
-		// if a type contains user defined ctor/dtor/assign, then special rules trigger, which
-		// determinethe set of ctor/dtor/assign that can be used  by the requester. In particular,
-		// if the user defines a default ctor, then the generated default ctor is unavailable,
-		// likewise for copy ctor and dtor. If the user defines any ctor/dtor, then no generated
-		// field ctors are available. If the user defines any ctor then the generated default ctor
-		// is unavailable (intrinsic default ctor must be overridden exactly). If the user defines
-		// anything that looks like a copy constructor, then the generated copy constructor is
-		// unavailable, and likewise for the assignment operator.
-
-		// only relevant on function declarations
-		const FunctionDecl * function = dynamic_cast< const FunctionDecl * >( data.id );
-		if ( ! function ) return true;
-		// only need to perform this check for constructors, destructors, and assignment functions
-		if ( ! CodeGen::isCtorDtorAssign( data.id->name ) ) return true;
-
-		// set up information for this type
-		bool dataIsUserDefinedFunc = ! LinkageSpec::isOverridable( function->linkage );
-		bool dataIsCopyFunc = InitTweak::isCopyFunction( function, function->name );
-		std::string dataOtypeKey = getOtypeKey( function );
-
-		if ( dataIsUserDefinedFunc && dataIsCopyFunc ) {
-			// this is a user-defined copy function
-			// if this is the first such, delete/remove non-user-defined overloads as needed
-			std::vector< std::string > removed;
-			std::vector< MangleTable::value_type > deleted;
-			bool alreadyUserDefinedFunc = false;
-
-			for ( const auto& entry : * mangleTable ) {
-				// skip decls that aren't functions or are for the wrong type
-				const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
-				if ( ! decl ) continue;
-
-				bool isCopyFunc = InitTweak::isCopyFunction( decl, decl->name );
-				if ( ! LinkageSpec::isOverridable( decl->linkage ) ) {
-					// matching user-defined function
-					if ( isCopyFunc ) {
-						// mutation already performed, return early
-						return true;
-					} else {
-						// note that non-copy deletions already performed
-						alreadyUserDefinedFunc = true;
-					}
-				} else {
-					// non-user-defined function; mark for deletion/removal as appropriate
-					if ( isCopyFunc ) {
-						removed.push_back( entry.first );
-					} else if ( ! alreadyUserDefinedFunc ) {
-						deleted.push_back( entry );
-					}
-				}
-			}
-
-			// perform removals from mangle table, and deletions if necessary
-			for ( const auto& key : removed ) {
-				++* stats().map_mutations;
-				mangleTable = mangleTable->erase( key );
-			}
-			if ( ! alreadyUserDefinedFunc ) for ( const auto& entry : deleted ) {
-				++* stats().map_mutations;
-				mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } );
-			}
-		} else if ( dataIsUserDefinedFunc ) {
-			// this is a user-defined non-copy function
-			// if this is the first user-defined function, delete non-user-defined overloads
-			std::vector< MangleTable::value_type > deleted;
-
-			for ( const auto& entry : * mangleTable ) {
-				// skip decls that aren't functions or are for the wrong type
-				const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
-				if ( ! decl ) continue;
-
-				// exit early if already a matching user-defined function;
-				// earlier function will have mutated table
-				if ( ! LinkageSpec::isOverridable( decl->linkage ) ) return true;
-
-				// skip mutating intrinsic functions
-				if ( decl->linkage == LinkageSpec::Intrinsic ) continue;
-
-				// user-defined non-copy functions do not override copy functions
-				if ( InitTweak::isCopyFunction( decl, decl->name ) ) continue;
-
-				// this function to be deleted after mangleTable iteration is complete
-				deleted.push_back( entry );
-			}
-
-			// mark deletions to update mangle table
-			// this needs to be a separate loop because of iterator invalidation
-			for ( const auto& entry : deleted ) {
-				++* stats().map_mutations;
-				mangleTable = mangleTable->set( entry.first, IdData{ entry.second, function } );
-			}
-		} else if ( function->linkage != LinkageSpec::Intrinsic ) {
-			// this is an overridable generated function
-			// if there already exists a matching user-defined function, delete this appropriately
-			for ( const auto& entry : * mangleTable ) {
-				// skip decls that aren't functions or are for the wrong type
-				const FunctionDecl * decl = getFunctionForOtype( entry.second.id, dataOtypeKey );
-				if ( ! decl ) continue;
-
-				// skip non-user-defined functions
-				if ( LinkageSpec::isOverridable( decl->linkage ) ) continue;
-
-				if ( dataIsCopyFunc ) {
-					// remove current function if exists a user-defined copy function
-					// since the signatures for copy functions don't need to match exactly, using
-					// a delete statement is the wrong approach
-					if ( InitTweak::isCopyFunction( decl, decl->name ) ) return false;
-				} else {
-					// mark current function deleted by first user-defined function found
-					data.deleteStmt = decl;
-					return true;
-				}
-			}
-		}
-
-		// nothing (more) to fix, return true
-		return true;
-	}
-
-	void Indexer::addId(const DeclarationWithType * decl, OnConflict handleConflicts, const Expression * baseExpr,
-			const Declaration * deleteStmt ) {
-		++* stats().add_calls;
-		if ( ! trackIdentifiers ) return;
-		const std::string &name = decl->name;
-		if ( name == "" ) return;
-
-		std::string mangleName;
-		if ( LinkageSpec::isOverridable( decl->linkage ) ) {
-			// mangle the name without including the appropriate suffix, so overridable routines
-			// are placed into the same "bucket" as their user defined versions.
-			mangleName = Mangler::mangle( decl, false );
-		} else {
-			mangleName = Mangler::mangle( decl );
-		} // if
-
-		// this ensures that no two declarations with the same unmangled name at the same scope
-		// both have C linkage
-		if ( LinkageSpec::isMangled( decl->linkage ) ) {
-			// Check that a Cforall declaration doesn't override any C declaration
-			if ( hasCompatibleCDecl( name, mangleName ) ) {
-				SemanticError( decl, "Cforall declaration hides C function " );
-			}
-		} else {
-			// NOTE: only correct if name mangling is completely isomorphic to C
-			// type-compatibility, which it may not be.
-			if ( hasIncompatibleCDecl( name, mangleName ) ) {
-				SemanticError( decl, "conflicting overload of C function " );
-			}
-		}
-
-		// ensure tables exist and add identifier
-		MangleTable::Ptr mangleTable;
-		if ( ! idTable ) {
-			idTable = IdTable::new_ptr();
-			mangleTable = MangleTable::new_ptr();
-		} else {
-			++* stats().map_lookups;
-			auto decls = idTable->find( name );
-			if ( decls == idTable->end() ) {
-				mangleTable = MangleTable::new_ptr();
-			} else {
-				mangleTable = decls->second;
-				// skip in-scope repeat declarations of same identifier
-				++* stats().map_lookups;
-				auto existing = mangleTable->find( mangleName );
-				if ( existing != mangleTable->end()
-						&& existing->second.scope == scope
-						&& existing->second.id ) {
-					if ( addedIdConflicts( existing->second, decl, handleConflicts, deleteStmt ) ) {
-						if ( handleConflicts.mode == OnConflict::Delete ) {
-							// set delete expression for conflicting identifier
-							lazyInitScope();
-							* stats().map_mutations += 2;
-							idTable = idTable->set(
-								name,
-								mangleTable->set(
-									mangleName,
-									IdData{ existing->second, handleConflicts.deleteStmt } ) );
-						}
-						return;
-					}
-				}
-			}
-		}
-
-		// add/overwrite with new identifier
-		lazyInitScope();
-		IdData data{ decl, baseExpr, deleteStmt, scope };
-		// Ensure that auto-generated ctor/dtor/assignment are deleted if necessary
-		if ( ! removeSpecialOverrides( data, mangleTable ) ) return;
-		* stats().map_mutations += 2;
-		idTable = idTable->set( name, mangleTable->set( mangleName, std::move(data) ) );
-	}
-
-	void Indexer::addId( const DeclarationWithType * decl, const Expression * baseExpr ) {
-		// default handling of conflicts is to raise an error
-		addId( decl, OnConflict::error(), baseExpr, decl->isDeleted ? decl : nullptr );
-	}
-
-	void Indexer::addDeletedId( const DeclarationWithType * decl, const Declaration * deleteStmt ) {
-		// default handling of conflicts is to raise an error
-		addId( decl, OnConflict::error(), nullptr, deleteStmt );
-	}
-
-	bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) {
-		if ( existing->base == nullptr ) {
-			return false;
-		} else if ( added->base == nullptr ) {
-			return true;
-		} else {
-			assert( existing->base && added->base );
-			// typedef redeclarations are errors only if types are different
-			if ( ! ResolvExpr::typesCompatible( existing->base, added->base, Indexer() ) ) {
-				SemanticError( added->location, "redeclaration of " + added->name );
-			}
-		}
-		// does not need to be added to the table if both existing and added have a base that are
-		// the same
-		return true;
-	}
-
-	void Indexer::addType( const NamedTypeDecl * decl ) {
-		++* stats().add_calls;
-		const std::string & id = decl->name;
-
-		if ( ! typeTable ) {
-			typeTable = TypeTable::new_ptr();
-		} else {
-			++* stats().map_lookups;
-			auto existing = typeTable->find( id );
-			if ( existing != typeTable->end()
-				&& existing->second.scope == scope
-				&& addedTypeConflicts( existing->second.decl, decl ) ) return;
-		}
-
-		lazyInitScope();
-		++* stats().map_mutations;
-		typeTable = typeTable->set( id, Scoped<NamedTypeDecl>{ decl, scope } );
-	}
-
-	bool addedDeclConflicts( const AggregateDecl * existing, const AggregateDecl * added ) {
-		if ( ! existing->body ) {
-			return false;
-		} else if ( added->body ) {
-			SemanticError( added, "redeclaration of " );
-		} // if
-		return true;
-	}
-
-	void Indexer::addStruct( const std::string & id ) {
-		addStruct( new StructDecl( id ) );
-	}
-
-	void Indexer::addStruct( const StructDecl * decl ) {
-		++* stats().add_calls;
-		const std::string & id = decl->name;
-
-		if ( ! structTable ) {
-			structTable = StructTable::new_ptr();
-		} else {
-			++* stats().map_lookups;
-			auto existing = structTable->find( id );
-			if ( existing != structTable->end()
-				&& existing->second.scope == scope
-				&& addedDeclConflicts( existing->second.decl, decl ) ) return;
-		}
-
-		lazyInitScope();
-		++* stats().map_mutations;
-		structTable = structTable->set( id, Scoped<StructDecl>{ decl, scope } );
-	}
-
-	void Indexer::addEnum( const EnumDecl * decl ) {
-		++* stats().add_calls;
-		const std::string & id = decl->name;
-
-		if ( ! enumTable ) {
-			enumTable = EnumTable::new_ptr();
-		} else {
-			++* stats().map_lookups;
-			auto existing = enumTable->find( id );
-			if ( existing != enumTable->end()
-				&& existing->second.scope == scope
-				&& addedDeclConflicts( existing->second.decl, decl ) ) return;
-		}
-
-		lazyInitScope();
-		++* stats().map_mutations;
-		enumTable = enumTable->set( id, Scoped<EnumDecl>{ decl, scope } );
-	}
-
-	void Indexer::addUnion( const std::string & id ) {
-		addUnion( new UnionDecl( id ) );
-	}
-
-	void Indexer::addUnion( const UnionDecl * decl ) {
-		++* stats().add_calls;
-		const std::string & id = decl->name;
-
-		if ( ! unionTable ) {
-			unionTable = UnionTable::new_ptr();
-		} else {
-			++* stats().map_lookups;
-			auto existing = unionTable->find( id );
-			if ( existing != unionTable->end()
-				&& existing->second.scope == scope
-				&& addedDeclConflicts( existing->second.decl, decl ) ) return;
-		}
-
-		lazyInitScope();
-		++* stats().map_mutations;
-		unionTable = unionTable->set( id, Scoped<UnionDecl>{ decl, scope } );
-	}
-
-	void Indexer::addTrait( const TraitDecl * decl ) {
-		++* stats().add_calls;
-		const std::string & id = decl->name;
-
-		if ( ! traitTable ) {
-			traitTable = TraitTable::new_ptr();
-		} else {
-			++* stats().map_lookups;
-			auto existing = traitTable->find( id );
-			if ( existing != traitTable->end()
-				&& existing->second.scope == scope
-				&& addedDeclConflicts( existing->second.decl, decl ) ) return;
-		}
-
-		lazyInitScope();
-		++* stats().map_mutations;
-		traitTable = traitTable->set( id, Scoped<TraitDecl>{ decl, scope } );
-	}
-
-	void Indexer::addMembers( const AggregateDecl * aggr, const Expression * expr, OnConflict handleConflicts ) {
-		for ( Declaration * decl : aggr->members ) {
-			if ( DeclarationWithType * dwt = dynamic_cast< DeclarationWithType * >( decl ) ) {
-				addId( dwt, handleConflicts, expr );
-				if ( dwt->name == "" ) {
-					const Type * t = dwt->get_type()->stripReferences();
-					if ( dynamic_cast<const StructInstType *>( t ) || dynamic_cast<const UnionInstType *>( t ) ) {
-						Expression * base = expr->clone();
-						ResolvExpr::Cost cost = ResolvExpr::Cost::zero; // xxx - carry this cost into the indexer as a base cost?
-						ResolvExpr::referenceToRvalueConversion( base, cost );
-						addMembers( t->getAggr(), new MemberExpr( dwt, base ), handleConflicts );
-					}
-				}
-			}
-		}
-	}
-
-	void Indexer::addWith( const std::list< Expression * > & withExprs, const Declaration * withStmt ) {
-		for ( const Expression * expr : withExprs ) {
-			if ( expr->result ) {
-				AggregateDecl * aggr = expr->result->stripReferences()->getAggr();
-				assertf( aggr, "WithStmt expr has non-aggregate type: %s", toString( expr->result ).c_str() );
-
-				addMembers( aggr, expr, OnConflict::deleteWith( withStmt ) );
-			}
-		}
-	}
-
-	void Indexer::addIds( const std::list< DeclarationWithType * > & decls ) {
-		for ( auto d : decls ) {
-			addId( d );
-		}
-	}
-
-	void Indexer::addTypes( const std::list< TypeDecl * > & tds ) {
-		for ( auto td : tds ) {
-			addType( td );
-			addIds( td->assertions );
-		}
-	}
-
-	void Indexer::addFunctionType( const FunctionType * ftype ) {
-		addTypes( ftype->forall );
-		addIds( ftype->returnVals );
-		addIds( ftype->parameters );
-	}
-
-	Expression * Indexer::IdData::combine( ResolvExpr::Cost & cost ) const {
-		Expression * ret = nullptr;
-		if ( baseExpr ) {
-			Expression * base = baseExpr->clone();
-			ResolvExpr::referenceToRvalueConversion( base, cost );
-			ret = new MemberExpr( const_cast<DeclarationWithType *>(id), base );
-			// xxx - this introduces hidden environments, for now remove them.
-			// std::swap( base->env, ret->env );
-			delete base->env;
-			base->env = nullptr;
-		} else {
-			ret = new VariableExpr( const_cast<DeclarationWithType *>(id) );
-		}
-		if ( deleteStmt ) ret = new DeletedExpr( ret, const_cast<Declaration *>(deleteStmt) );
-		return ret;
-	}
-} // namespace SymTab
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/SymTab/Indexer.h
===================================================================
--- src/SymTab/Indexer.h	(revision 934fa0fc6af3737f7f5b45e08f4b84e1e8259312)
+++ 	(revision )
@@ -1,191 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// Indexer.h --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 21:38:55 2015
-// Last Modified By : Aaron B. Moss
-// Last Modified On : Fri Mar  8 13:55:00 2019
-// Update Count     : 9
-//
-
-#pragma once
-
-#include <functional>              // for function
-#include <list>                    // for list
-#include <memory>                  // for shared_ptr, enable_shared_from_this
-#include <string>                  // for string
-
-#include "Common/PersistentMap.h"  // for PersistentMap
-#include "SynTree/SynTree.h"       // for AST nodes
-
-namespace ResolvExpr {
-	class Cost;
-}
-
-namespace SymTab {
-	class Indexer : public std::enable_shared_from_this<SymTab::Indexer> {
-	public:
-		explicit Indexer( bool trackIdentifiers = true );
-		virtual ~Indexer();
-
-		// when using an indexer manually (e.g., within a mutator traversal), it is necessary to
-		// tell the indexer explicitly when scopes begin and end
-		void enterScope();
-		void leaveScope();
-
-		struct IdData {
-			const DeclarationWithType * id = nullptr;
-			const Expression * baseExpr = nullptr; // WithExpr
-
-			/// non-null if this declaration is deleted
-			const Declaration * deleteStmt = nullptr;
-			/// scope of identifier
-			unsigned long scope = 0;
-
-			// NOTE: shouldn't need either of these constructors, but gcc-4 does not properly support initializer lists with default members.
-			IdData() = default;
-			IdData(
-				const DeclarationWithType * id, const Expression * baseExpr, const Declaration * deleteStmt,
-				unsigned long scope )
-				: id( id ), baseExpr( baseExpr ), deleteStmt( deleteStmt ), scope( scope ) {}
-			IdData( const IdData& o, const Declaration * deleteStmt )
-				: id( o.id ), baseExpr( o.baseExpr ), deleteStmt( deleteStmt ), scope( o.scope ) {}
-
-			Expression * combine( ResolvExpr::Cost & cost ) const;
-		};
-
-		/// Gets all declarations with the given ID
-		void lookupId( const std::string & id, std::list< IdData > &out ) const;
-		/// Gets the top-most type declaration with the given ID
-		const NamedTypeDecl * lookupType( const std::string & id ) const;
-		/// Gets the top-most struct declaration with the given ID
-		const StructDecl * lookupStruct( const std::string & id ) const;
-		/// Gets the top-most enum declaration with the given ID
-		const EnumDecl * lookupEnum( const std::string & id ) const;
-		/// Gets the top-most union declaration with the given ID
-		const UnionDecl * lookupUnion( const std::string & id ) const;
-		/// Gets the top-most trait declaration with the given ID
-		const TraitDecl * lookupTrait( const std::string & id ) const;
-
-		/// Gets the type declaration with the given ID at global scope
-		const NamedTypeDecl * globalLookupType( const std::string & id ) const;
-		/// Gets the struct declaration with the given ID at global scope
-		const StructDecl * globalLookupStruct( const std::string & id ) const;
-		/// Gets the union declaration with the given ID at global scope
-		const UnionDecl * globalLookupUnion( const std::string & id ) const;
-		/// Gets the enum declaration with the given ID at global scope
-		const EnumDecl * globalLookupEnum( const std::string & id ) const;
-
-		void addId( const DeclarationWithType * decl, const Expression * baseExpr = nullptr );
-		void addDeletedId( const DeclarationWithType * decl, const Declaration * deleteStmt );
-
-		void addType( const NamedTypeDecl * decl );
-		void addStruct( const std::string & id );
-		void addStruct( const StructDecl * decl );
-		void addEnum( const EnumDecl * decl );
-		void addUnion( const std::string & id );
-		void addUnion( const UnionDecl * decl );
-		void addTrait( const TraitDecl * decl );
-
-		/// adds all of the IDs from WithStmt exprs
-		void addWith( const std::list< Expression * > & withExprs, const Declaration * withStmt );
-
-		/// convenience function for adding a list of Ids to the indexer
-		void addIds( const std::list< DeclarationWithType * > & decls );
-
-		/// convenience function for adding a list of forall parameters to the indexer
-		void addTypes( const std::list< TypeDecl * > & tds );
-
-		/// convenience function for adding all of the declarations in a function type to the indexer
-		void addFunctionType( const FunctionType * ftype );
-
-	  private:
-	  	/// Wraps a Decl * with a scope
-	  	template<typename Decl>
-		struct Scoped {
-			const Decl * decl;           ///< declaration
-			unsigned long scope;  ///< scope of this declaration
-
-			Scoped(const Decl * d, unsigned long s) : decl(d), scope(s) {}
-		};
-
-		using Ptr = std::shared_ptr<const Indexer>;
-
-		using MangleTable = PersistentMap< std::string, IdData >;
-		using IdTable = PersistentMap< std::string, MangleTable::Ptr >;
-		using TypeTable = PersistentMap< std::string, Scoped<NamedTypeDecl> >;
-		using StructTable = PersistentMap< std::string, Scoped<StructDecl> >;
-		using EnumTable = PersistentMap< std::string, Scoped<EnumDecl> >;
-		using UnionTable = PersistentMap< std::string, Scoped<UnionDecl> >;
-		using TraitTable = PersistentMap< std::string, Scoped<TraitDecl> >;
-
-		IdTable::Ptr idTable;          ///< identifier namespace
-		TypeTable::Ptr typeTable;      ///< type namespace
-		StructTable::Ptr structTable;  ///< struct namespace
-		EnumTable::Ptr enumTable;      ///< enum namespace
-		UnionTable::Ptr unionTable;    ///< union namespace
-		TraitTable::Ptr traitTable;    ///< trait namespace
-
-		Ptr prevScope;                 ///< reference to indexer for parent scope
-		unsigned long scope;           ///< Scope index of this indexer
-		unsigned long repScope;        ///< Scope index of currently represented scope
-
-		/// Ensures that a proper backtracking scope exists before a mutation
-		void lazyInitScope();
-
-		/// Gets the indexer at the given scope
-		const Indexer * atScope( unsigned long scope ) const;
-
-		/// Removes matching autogenerated constructors and destructors so that they will not be
-		/// selected. If returns false, passed decl should not be added.
-		bool removeSpecialOverrides( IdData & decl, MangleTable::Ptr & mangleTable );
-
-		/// Options for handling identifier conflicts
-		struct OnConflict {
-			enum {
-				Error,  ///< Throw a semantic error
-				Delete  ///< Delete the earlier version with the delete statement
-			} mode;
-			const Declaration * deleteStmt;  ///< Statement that deletes this expression
-
-		private:
-			OnConflict() : mode(Error), deleteStmt(nullptr) {}
-			OnConflict( const Declaration * d ) : mode(Delete), deleteStmt(d) {}
-		public:
-			OnConflict( const OnConflict& ) = default;
-
-			static OnConflict error() { return {}; }
-			static OnConflict deleteWith( const Declaration * d ) { return { d }; }
-		};
-
-		/// true if the existing identifier conflicts with the added identifier
-		bool addedIdConflicts(
-			const IdData & existing, const DeclarationWithType * added, OnConflict handleConflicts,
-			const Declaration * deleteStmt );
-
-		/// common code for addId, addDeletedId, etc.
-		void addId(const DeclarationWithType * decl, OnConflict handleConflicts,
-			const Expression * baseExpr = nullptr, const Declaration * deleteStmt = nullptr );
-
-		/// adds all of the members of the Aggregate (addWith helper)
-		void addMembers( const AggregateDecl * aggr, const Expression * expr, OnConflict handleConflicts );
-
-		/// returns true if there exists a declaration with C linkage and the given name with the same mangled name
-		bool hasCompatibleCDecl( const std::string & id, const std::string & mangleName ) const;
-		/// returns true if there exists a declaration with C linkage and the given name with a different mangled name
-		bool hasIncompatibleCDecl( const std::string & id, const std::string & mangleName ) const;
-
-	    bool trackIdentifiers;
-	};
-} // namespace SymTab
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/SymTab/Mangler.cc
===================================================================
--- src/SymTab/Mangler.cc	(revision 934fa0fc6af3737f7f5b45e08f4b84e1e8259312)
+++ src/SymTab/Mangler.cc	(revision c6b4432f5c6c6679b981f5a6bded51ad30ac00d9)
@@ -24,366 +24,6 @@
 #include "AST/Pass.hpp"
 #include "CodeGen/OperatorTable.h"       // for OperatorInfo, operatorLookup
-#include "Common/PassVisitor.h"
 #include "Common/ToString.hpp"           // for toCString
 #include "Common/SemanticError.h"        // for SemanticError
-#include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
-#include "SynTree/LinkageSpec.h"         // for Spec, isOverridable, AutoGen, Int...
-#include "SynTree/Declaration.h"         // for TypeDecl, DeclarationWithType
-#include "SynTree/Expression.h"          // for TypeExpr, Expression, operator<<
-#include "SynTree/Type.h"                // for Type, ReferenceToType, Type::Fora...
-
-namespace SymTab {
-	namespace Mangler {
-		namespace {
-			/// Mangles names to a unique C identifier
-			struct Mangler_old : public WithShortCircuiting, public WithVisitorRef<Mangler_old>, public WithGuards {
-				Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
-				Mangler_old( const Mangler_old & ) = delete;
-
-				void previsit( const BaseSyntaxNode * ) { visit_children = false; }
-
-				void postvisit( const ObjectDecl * declaration );
-				void postvisit( const FunctionDecl * declaration );
-				void postvisit( const TypeDecl * declaration );
-
-				void postvisit( const VoidType * voidType );
-				void postvisit( const BasicType * basicType );
-				void postvisit( const PointerType * pointerType );
-				void postvisit( const ArrayType * arrayType );
-				void postvisit( const ReferenceType * refType );
-				void postvisit( const FunctionType * functionType );
-				void postvisit( const StructInstType * aggregateUseType );
-				void postvisit( const UnionInstType * aggregateUseType );
-				void postvisit( const EnumInstType * aggregateUseType );
-				void postvisit( const TypeInstType * aggregateUseType );
-				void postvisit( const TraitInstType * inst );
-				void postvisit( const TupleType * tupleType );
-				void postvisit( const VarArgsType * varArgsType );
-				void postvisit( const ZeroType * zeroType );
-				void postvisit( const OneType * oneType );
-				void postvisit( const QualifiedType * qualType );
-
-				std::string get_mangleName() { return mangleName; }
-			  private:
-				std::string mangleName;         ///< Mangled name being constructed
-				typedef std::map< std::string, std::pair< int, int > > VarMapType;
-				VarMapType varNums;             ///< Map of type variables to indices
-				int nextVarNum;                 ///< Next type variable index
-				bool isTopLevel;                ///< Is the Mangler at the top level
-				bool mangleOverridable;         ///< Specially mangle overridable built-in methods
-				bool typeMode;                  ///< Produce a unique mangled name for a type
-				bool mangleGenericParams;       ///< Include generic parameters in name mangling if true
-				bool inFunctionType = false;    ///< Include type qualifiers if false.
-				bool inQualifiedType = false;   ///< Add start/end delimiters around qualified type
-
-			  public:
-				Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
-					int nextVarNum, const VarMapType& varNums );
-
-			  private:
-				void mangleDecl( const DeclarationWithType * declaration );
-				void mangleRef( const ReferenceToType * refType, std::string prefix );
-
-				void printQualifiers( const Type *type );
-			}; // Mangler_old
-		} // namespace
-
-		std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
-			PassVisitor<Mangler_old> mangler( mangleOverridable, typeMode, mangleGenericParams );
-			maybeAccept( decl, mangler );
-			return mangler.pass.get_mangleName();
-		}
-
-		std::string mangleType( const Type * ty ) {
-			PassVisitor<Mangler_old> mangler( false, true, true );
-			maybeAccept( ty, mangler );
-			return mangler.pass.get_mangleName();
-		}
-
-		std::string mangleConcrete( const Type * ty ) {
-			PassVisitor<Mangler_old> mangler( false, false, false );
-			maybeAccept( ty, mangler );
-			return mangler.pass.get_mangleName();
-		}
-
-		namespace {
-			Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
-				: nextVarNum( 0 ), isTopLevel( true ),
-				mangleOverridable( mangleOverridable ), typeMode( typeMode ),
-				mangleGenericParams( mangleGenericParams ) {}
-
-			Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
-				int nextVarNum, const VarMapType& varNums )
-				: varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
-				mangleOverridable( mangleOverridable ), typeMode( typeMode ),
-				mangleGenericParams( mangleGenericParams ) {}
-
-			void Mangler_old::mangleDecl( const DeclarationWithType * declaration ) {
-				bool wasTopLevel = isTopLevel;
-				if ( isTopLevel ) {
-					varNums.clear();
-					nextVarNum = 0;
-					isTopLevel = false;
-				} // if
-				mangleName += Encoding::manglePrefix;
-				const CodeGen::OperatorInfo * opInfo = CodeGen::operatorLookup( declaration->get_name() );
-				if ( opInfo ) {
-					mangleName += std::to_string( opInfo->outputName.size() ) + opInfo->outputName;
-				} else {
-					mangleName += std::to_string( declaration->name.size() ) + declaration->name;
-				} // if
-				maybeAccept( declaration->get_type(), *visitor );
-				if ( mangleOverridable && LinkageSpec::isOverridable( declaration->get_linkage() ) ) {
-					// want to be able to override autogenerated and intrinsic routines,
-					// so they need a different name mangling
-					if ( declaration->get_linkage() == LinkageSpec::AutoGen ) {
-						mangleName += Encoding::autogen;
-					} else if ( declaration->get_linkage() == LinkageSpec::Intrinsic ) {
-						mangleName += Encoding::intrinsic;
-					} else {
-						// if we add another kind of overridable function, this has to change
-						assert( false && "unknown overrideable linkage" );
-					} // if
-				}
-				isTopLevel = wasTopLevel;
-			}
-
-			void Mangler_old::postvisit( const ObjectDecl * declaration ) {
-				mangleDecl( declaration );
-			}
-
-			void Mangler_old::postvisit( const FunctionDecl * declaration ) {
-				mangleDecl( declaration );
-			}
-
-			void Mangler_old::postvisit( const VoidType * voidType ) {
-				printQualifiers( voidType );
-				mangleName += Encoding::void_t;
-			}
-
-			void Mangler_old::postvisit( const BasicType * basicType ) {
-				printQualifiers( basicType );
-				assertf( basicType->kind < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
-				mangleName += Encoding::basicTypes[ basicType->kind ];
-			}
-
-			void Mangler_old::postvisit( const PointerType * pointerType ) {
-				printQualifiers( pointerType );
-				// mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
-				if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName += Encoding::pointer;
-				maybeAccept( pointerType->base, *visitor );
-			}
-
-			void Mangler_old::postvisit( const ArrayType * arrayType ) {
-				// TODO: encode dimension
-				printQualifiers( arrayType );
-				mangleName += Encoding::array + "0";
-				maybeAccept( arrayType->base, *visitor );
-			}
-
-			void Mangler_old::postvisit( const ReferenceType * refType ) {
-				// don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
-				// Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
-				// by pretending every reference type is a function parameter.
-				GuardValue( inFunctionType );
-				inFunctionType = true;
-				printQualifiers( refType );
-				maybeAccept( refType->base, *visitor );
-			}
-
-			namespace {
-				inline std::list< Type* > getTypes( const std::list< DeclarationWithType* > decls ) {
-					std::list< Type* > ret;
-					std::transform( decls.begin(), decls.end(), std::back_inserter( ret ),
-									std::mem_fun( &DeclarationWithType::get_type ) );
-					return ret;
-				}
-			}
-
-			void Mangler_old::postvisit( const FunctionType * functionType ) {
-				printQualifiers( functionType );
-				mangleName += Encoding::function;
-				// turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters,
-				// since qualifiers on outermost parameter type do not differentiate function types, e.g.,
-				// void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different
-				GuardValue( inFunctionType );
-				inFunctionType = true;
-				std::list< Type* > returnTypes = getTypes( functionType->returnVals );
-				if (returnTypes.empty()) mangleName += Encoding::void_t;
-				else acceptAll( returnTypes, *visitor );
-				mangleName += "_";
-				std::list< Type* > paramTypes = getTypes( functionType->parameters );
-				acceptAll( paramTypes, *visitor );
-				mangleName += "_";
-			}
-
-			void Mangler_old::mangleRef( const ReferenceToType * refType, std::string prefix ) {
-				printQualifiers( refType );
-
-				mangleName += prefix + std::to_string( refType->name.length() ) + refType->name;
-
-				if ( mangleGenericParams ) {
-					const std::list< Expression* > & params = refType->parameters;
-					if ( ! params.empty() ) {
-						mangleName += "_";
-						for ( const Expression * param : params ) {
-							const TypeExpr * paramType = dynamic_cast< const TypeExpr * >( param );
-							assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
-							maybeAccept( paramType->type, *visitor );
-						}
-						mangleName += "_";
-					}
-				}
-			}
-
-			void Mangler_old::postvisit( const StructInstType * aggregateUseType ) {
-				mangleRef( aggregateUseType, Encoding::struct_t );
-			}
-
-			void Mangler_old::postvisit( const UnionInstType * aggregateUseType ) {
-				mangleRef( aggregateUseType, Encoding::union_t );
-			}
-
-			void Mangler_old::postvisit( const EnumInstType * aggregateUseType ) {
-				mangleRef( aggregateUseType, Encoding::enum_t );
-			}
-
-			void Mangler_old::postvisit( const TypeInstType * typeInst ) {
-				VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
-				if ( varNum == varNums.end() ) {
-					mangleRef( typeInst, Encoding::type );
-				} else {
-					printQualifiers( typeInst );
-					// Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g.
-					//   forall(dtype T) void f(T);
-					//   forall(dtype S) void f(S);
-					// are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they
-					// are first found and prefixing with the appropriate encoding for the type class.
-					assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
-					mangleName += Encoding::typeVariables[varNum->second.second] + std::to_string( varNum->second.first );
-				} // if
-			}
-
-			void Mangler_old::postvisit( const TraitInstType * inst ) {
-				printQualifiers( inst );
-				mangleName += std::to_string( inst->name.size() ) + inst->name;
-			}
-
-			void Mangler_old::postvisit( const TupleType * tupleType ) {
-				printQualifiers( tupleType );
-				mangleName += Encoding::tuple + std::to_string( tupleType->types.size() );
-				acceptAll( tupleType->types, *visitor );
-			}
-
-			void Mangler_old::postvisit( const VarArgsType * varArgsType ) {
-				printQualifiers( varArgsType );
-				static const std::string vargs = "__builtin_va_list";
-				mangleName += Encoding::type + std::to_string( vargs.size() ) + vargs;
-			}
-
-			void Mangler_old::postvisit( const ZeroType * ) {
-				mangleName += Encoding::zero;
-			}
-
-			void Mangler_old::postvisit( const OneType * ) {
-				mangleName += Encoding::one;
-			}
-
-			void Mangler_old::postvisit( const QualifiedType * qualType ) {
-				bool inqual = inQualifiedType;
-				if (! inqual ) {
-					// N marks the start of a qualified type
-					inQualifiedType = true;
-					mangleName += Encoding::qualifiedTypeStart;
-				}
-				maybeAccept( qualType->parent, *visitor );
-				maybeAccept( qualType->child, *visitor );
-				if ( ! inqual ) {
-					// E marks the end of a qualified type
-					inQualifiedType = false;
-					mangleName += Encoding::qualifiedTypeEnd;
-				}
-			}
-
-			void Mangler_old::postvisit( const TypeDecl * decl ) {
-				// TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
-				// fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
-				// Note: The current scheme may already work correctly for this case, I have not thought about this deeply
-				// and the case has not yet come up in practice. Alternatively, if not then this code can be removed
-				// aside from the assert false.
-				assertf( false, "Mangler_old should not visit typedecl: %s", toCString(decl));
-				assertf( decl->kind < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
-				mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name;
-			}
-
-			__attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) {
-				for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) {
-					os << i->first << "(" << i->second.first << "/" << i->second.second << ")" << std::endl;
-				} // for
-			}
-
-			void Mangler_old::printQualifiers( const Type * type ) {
-				// skip if not including qualifiers
-				if ( typeMode ) return;
-				if ( ! type->forall.empty() ) {
-					std::list< std::string > assertionNames;
-					int dcount = 0, fcount = 0, vcount = 0, acount = 0;
-					mangleName += Encoding::forall;
-					for ( const TypeDecl * i : type->forall ) {
-						switch ( i->kind ) {
-						  case TypeDecl::Dtype:
-							dcount++;
-							break;
-						  case TypeDecl::Ftype:
-							fcount++;
-							break;
-						  case TypeDecl::Ttype:
-							vcount++;
-							break;
-						  default:
-							assertf( false, "unimplemented kind for type variable %s", SymTab::Mangler::Encoding::typeVariables[i->kind].c_str() );
-						} // switch
-						varNums[ i->name ] = std::make_pair( nextVarNum, (int)i->kind );
-						for ( const DeclarationWithType * assert : i->assertions ) {
-							PassVisitor<Mangler_old> sub_mangler(
-								mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
-							assert->accept( sub_mangler );
-							assertionNames.push_back( sub_mangler.pass.get_mangleName() );
-							acount++;
-						} // for
-					} // for
-					mangleName += std::to_string( dcount ) + "_" + std::to_string( fcount ) + "_" + std::to_string( vcount ) + "_" + std::to_string( acount ) + "_";
-					for(const auto & a : assertionNames) mangleName += a;
-//					std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
-					mangleName += "_";
-				} // if
-				if ( ! inFunctionType ) {
-					// these qualifiers do not distinguish the outermost type of a function parameter
-					if ( type->get_const() ) {
-						mangleName += Encoding::qualifiers.at(Type::Const);
-					} // if
-					if ( type->get_volatile() ) {
-						mangleName += Encoding::qualifiers.at(Type::Volatile);
-					} // if
-					// Removed due to restrict not affecting function compatibility in GCC
-					// if ( type->get_isRestrict() ) {
-					// 	mangleName += "E";
-					// } // if
-					if ( type->get_atomic() ) {
-						mangleName += Encoding::qualifiers.at(Type::Atomic);
-					} // if
-				}
-				if ( type->get_mutex() ) {
-					mangleName += Encoding::qualifiers.at(Type::Mutex);
-				} // if
-				if ( inFunctionType ) {
-					// turn off inFunctionType so that types can be differentiated for nested qualifiers
-					GuardValue( inFunctionType );
-					inFunctionType = false;
-				}
-			}
-		} // namespace
-	} // namespace Mangler
-} // namespace SymTab
 
 namespace Mangle {
Index: src/SymTab/Mangler.h
===================================================================
--- src/SymTab/Mangler.h	(revision 934fa0fc6af3737f7f5b45e08f4b84e1e8259312)
+++ src/SymTab/Mangler.h	(revision c6b4432f5c6c6679b981f5a6bded51ad30ac00d9)
@@ -22,6 +22,4 @@
 
 #include "AST/Bitfield.hpp"
-#include "SynTree/SynTree.h"  // for Types
-#include "SynTree/Visitor.h"  // for Visitor, maybeAccept
 
 // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling
@@ -35,18 +33,7 @@
 	class Node;
 }
-namespace ResolvExpr {
-	class TypeEnvironment;
-}
 
 namespace SymTab {
 	namespace Mangler {
-		/// Mangle syntax tree object; primary interface to clients
-		std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true );
-
-		/// Mangle a type name; secondary interface
-		std::string mangleType( const Type * ty );
-		/// Mangle ignoring generic type parameters
-		std::string mangleConcrete( const Type * ty );
-
 		namespace Encoding {
 			extern const std::string manglePrefix;
Index: src/SymTab/Validate.cc
===================================================================
--- src/SymTab/Validate.cc	(revision 934fa0fc6af3737f7f5b45e08f4b84e1e8259312)
+++ 	(revision )
@@ -1,1325 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// Validate.cc --
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 21:50:04 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Tue Jul 12 15:00:00 2022
-// Update Count     : 367
-//
-
-// The "validate" phase of translation is used to take a syntax tree and convert it into a standard form that aims to be
-// as regular in structure as possible.  Some assumptions can be made regarding the state of the tree after this pass is
-// complete, including:
-//
-// - No nested structure or union definitions; any in the input are "hoisted" to the level of the containing struct or
-//   union.
-//
-// - All enumeration constants have type EnumInstType.
-//
-// - The type "void" never occurs in lists of function parameter or return types.  A function
-//   taking no arguments has no argument types.
-//
-// - No context instances exist; they are all replaced by the set of declarations signified by the context, instantiated
-//   by the particular set of type arguments.
-//
-// - Every declaration is assigned a unique id.
-//
-// - No typedef declarations or instances exist; the actual type is substituted for each instance.
-//
-// - Each type, struct, and union definition is followed by an appropriate assignment operator.
-//
-// - Each use of a struct or union is connected to a complete definition of that struct or union, even if that
-//   definition occurs later in the input.
-
-#include "Validate.h"
-
-#include <cassert>                     // for assertf, assert
-#include <cstddef>                     // for size_t
-#include <list>                        // for list
-#include <string>                      // for string
-#include <unordered_map>               // for unordered_map
-#include <utility>                     // for pair
-
-#include "CodeGen/CodeGenerator.h"     // for genName
-#include "CodeGen/OperatorTable.h"     // for isCtorDtor, isCtorDtorAssign
-#include "ControlStruct/Mutate.h"      // for ForExprMutator
-#include "Common/CodeLocation.h"       // for CodeLocation
-#include "Common/Stats.h"              // for Stats::Heap
-#include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
-#include "Common/ScopedMap.h"          // for ScopedMap
-#include "Common/SemanticError.h"      // for SemanticError
-#include "Common/ToString.hpp"         // for toCString
-#include "Common/UniqueName.h"         // for UniqueName
-#include "Common/utility.h"            // for cloneAll, deleteAll
-#include "CompilationState.h"          // skip some passes in new-ast build
-#include "Concurrency/Keywords.h"      // for applyKeywords
-#include "FixFunction.h"               // for FixFunction
-#include "Indexer.h"                   // for Indexer
-#include "InitTweak/GenInit.h"         // for fixReturnStatements
-#include "InitTweak/InitTweak.h"       // for isCtorDtorAssign
-#include "ResolvExpr/typeops.h"        // for extractResultType
-#include "ResolvExpr/Unify.h"          // for typesCompatible
-#include "ResolvExpr/Resolver.h"       // for findSingleExpression
-#include "ResolvExpr/ResolveTypeof.h"  // for resolveTypeof
-#include "SymTab/Autogen.h"            // for SizeType
-#include "SymTab/ValidateType.h"       // for decayEnumsAndPointers, decayFo...
-#include "SynTree/LinkageSpec.h"       // for C
-#include "SynTree/Attribute.h"         // for noAttributes, Attribute
-#include "SynTree/Constant.h"          // for Constant
-#include "SynTree/Declaration.h"       // for ObjectDecl, DeclarationWithType
-#include "SynTree/Expression.h"        // for CompoundLiteralExpr, Expressio...
-#include "SynTree/Initializer.h"       // for ListInit, Initializer
-#include "SynTree/Label.h"             // for operator==, Label
-#include "SynTree/Mutator.h"           // for Mutator
-#include "SynTree/Type.h"              // for Type, TypeInstType, EnumInstType
-#include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
-#include "SynTree/Visitor.h"           // for Visitor
-#include "Validate/HandleAttributes.h" // for handleAttributes
-#include "Validate/FindSpecialDecls.h" // for FindSpecialDecls
-
-class CompoundStmt;
-class ReturnStmt;
-class SwitchStmt;
-
-#define debugPrint( x ) if ( doDebug ) x
-
-namespace SymTab {
-	/// hoists declarations that are difficult to hoist while parsing
-	struct HoistTypeDecls final : public WithDeclsToAdd {
-		void previsit( SizeofExpr * );
-		void previsit( AlignofExpr * );
-		void previsit( UntypedOffsetofExpr * );
-		void previsit( CompoundLiteralExpr * );
-		void handleType( Type * );
-	};
-
-	struct FixQualifiedTypes final : public WithIndexer {
-		FixQualifiedTypes() : WithIndexer(false) {}
-		Type * postmutate( QualifiedType * );
-	};
-
-	struct HoistStruct final : public WithDeclsToAdd, public WithGuards {
-		/// Flattens nested struct types
-		static void hoistStruct( std::list< Declaration * > &translationUnit );
-
-		void previsit( StructDecl * aggregateDecl );
-		void previsit( UnionDecl * aggregateDecl );
-		void previsit( StaticAssertDecl * assertDecl );
-		void previsit( StructInstType * type );
-		void previsit( UnionInstType * type );
-		void previsit( EnumInstType * type );
-
-	  private:
-		template< typename AggDecl > void handleAggregate( AggDecl * aggregateDecl );
-
-		AggregateDecl * parentAggr = nullptr;
-	};
-
-	/// Fix return types so that every function returns exactly one value
-	struct ReturnTypeFixer {
-		static void fix( std::list< Declaration * > &translationUnit );
-
-		void postvisit( FunctionDecl * functionDecl );
-		void postvisit( FunctionType * ftype );
-	};
-
-	/// Does early resolution on the expressions that give enumeration constants their values
-	struct ResolveEnumInitializers final : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveEnumInitializers>, public WithShortCircuiting {
-		ResolveEnumInitializers( const Indexer * indexer );
-		void postvisit( EnumDecl * enumDecl );
-
-	  private:
-		const Indexer * local_indexer;
-
-	};
-
-	/// Replaces array and function types in forall lists by appropriate pointer type and assigns each Object and Function declaration a unique ID.
-	struct ForallPointerDecay_old final {
-		void previsit( ObjectDecl * object );
-		void previsit( FunctionDecl * func );
-		void previsit( FunctionType * ftype );
-		void previsit( StructDecl * aggrDecl );
-		void previsit( UnionDecl * aggrDecl );
-	};
-
-	struct ReturnChecker : public WithGuards {
-		/// Checks that return statements return nothing if their return type is void
-		/// and return something if the return type is non-void.
-		static void checkFunctionReturns( std::list< Declaration * > & translationUnit );
-
-		void previsit( FunctionDecl * functionDecl );
-		void previsit( ReturnStmt * returnStmt );
-
-		typedef std::list< DeclarationWithType * > ReturnVals;
-		ReturnVals returnVals;
-	};
-
-	struct ReplaceTypedef final : public WithVisitorRef<ReplaceTypedef>, public WithGuards, public WithShortCircuiting, public WithDeclsToAdd {
-		ReplaceTypedef() : scopeLevel( 0 ) {}
-		/// Replaces typedefs by forward declarations
-		static void replaceTypedef( std::list< Declaration * > &translationUnit );
-
-		void premutate( QualifiedType * );
-		Type * postmutate( QualifiedType * qualType );
-		Type * postmutate( TypeInstType * aggregateUseType );
-		Declaration * postmutate( TypedefDecl * typeDecl );
-		void premutate( TypeDecl * typeDecl );
-		void premutate( FunctionDecl * funcDecl );
-		void premutate( ObjectDecl * objDecl );
-		DeclarationWithType * postmutate( ObjectDecl * objDecl );
-
-		void premutate( CastExpr * castExpr );
-
-		void premutate( CompoundStmt * compoundStmt );
-
-		void premutate( StructDecl * structDecl );
-		void premutate( UnionDecl * unionDecl );
-		void premutate( EnumDecl * enumDecl );
-		void premutate( TraitDecl * );
-
-		void premutate( FunctionType * ftype );
-
-	  private:
-		template<typename AggDecl>
-		void addImplicitTypedef( AggDecl * aggDecl );
-		template< typename AggDecl >
-		void handleAggregate( AggDecl * aggr );
-
-		typedef std::unique_ptr<TypedefDecl> TypedefDeclPtr;
-		typedef ScopedMap< std::string, std::pair< TypedefDeclPtr, int > > TypedefMap;
-		typedef ScopedMap< std::string, TypeDecl * > TypeDeclMap;
-		TypedefMap typedefNames;
-		TypeDeclMap typedeclNames;
-		int scopeLevel;
-		bool inFunctionType = false;
-	};
-
-	struct EliminateTypedef {
-		/// removes TypedefDecls from the AST
-		static void eliminateTypedef( std::list< Declaration * > &translationUnit );
-
-		template<typename AggDecl>
-		void handleAggregate( AggDecl * aggregateDecl );
-
-		void previsit( StructDecl * aggregateDecl );
-		void previsit( UnionDecl * aggregateDecl );
-		void previsit( CompoundStmt * compoundStmt );
-	};
-
-	struct VerifyCtorDtorAssign {
-		/// ensure that constructors, destructors, and assignment have at least one
-		/// parameter, the first of which must be a pointer, and that ctor/dtors have no
-		/// return values.
-		static void verify( std::list< Declaration * > &translationUnit );
-
-		void previsit( FunctionDecl * funcDecl );
-	};
-
-	/// ensure that generic types have the correct number of type arguments
-	struct ValidateGenericParameters {
-		void previsit( StructInstType * inst );
-		void previsit( UnionInstType * inst );
-	};
-
-	/// desugar declarations and uses of dimension paramaters like [N],
-	/// from type-system managed values, to tunnneling via ordinary types,
-	/// as char[-] in and sizeof(-) out
-	struct TranslateDimensionGenericParameters : public WithIndexer, public WithGuards {
-		static void translateDimensions( std::list< Declaration * > &translationUnit );
-		TranslateDimensionGenericParameters();
-
-		bool nextVisitedNodeIsChildOfSUIT = false; // SUIT = Struct or Union -Inst Type
-		bool visitingChildOfSUIT = false;
-		void changeState_ChildOfSUIT( bool newVal );
-		void premutate( StructInstType * sit );
-		void premutate( UnionInstType * uit );
-		void premutate( BaseSyntaxNode * node );
-
-		TypeDecl * postmutate( TypeDecl * td );
-		Expression * postmutate( DimensionExpr * de );
-		Expression * postmutate( Expression * e );
-	};
-
-	struct FixObjectType : public WithIndexer {
-		/// resolves typeof type in object, function, and type declarations
-		static void fix( std::list< Declaration * > & translationUnit );
-
-		void previsit( ObjectDecl * );
-		void previsit( FunctionDecl * );
-		void previsit( TypeDecl * );
-	};
-
-	struct InitializerLength {
-		/// 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 } };
-		static void computeLength( std::list< Declaration * > & translationUnit );
-
-		void previsit( ObjectDecl * objDecl );
-	};
-
-	struct ArrayLength : public WithIndexer {
-		static void computeLength( std::list< Declaration * > & translationUnit );
-
-		void previsit( ArrayType * arrayType );
-	};
-
-	struct CompoundLiteral final : public WithDeclsToAdd, public WithVisitorRef<CompoundLiteral> {
-		Type::StorageClasses storageClasses;
-
-		void premutate( ObjectDecl * objectDecl );
-		Expression * postmutate( CompoundLiteralExpr * compLitExpr );
-	};
-
-	struct LabelAddressFixer final : public WithGuards {
-		std::set< Label > labels;
-
-		void premutate( FunctionDecl * funcDecl );
-		Expression * postmutate( AddressExpr * addrExpr );
-	};
-
-	void validate( std::list< Declaration * > &translationUnit, __attribute__((unused)) bool doDebug ) {
-		PassVisitor<HoistTypeDecls> hoistDecls;
-		{
-			Stats::Heap::newPass("validate-A");
-			Stats::Time::BlockGuard guard("validate-A");
-			VerifyCtorDtorAssign::verify( translationUnit );  // must happen before autogen, because autogen examines existing ctor/dtors
-			acceptAll( translationUnit, hoistDecls );
-			ReplaceTypedef::replaceTypedef( translationUnit );
-			ReturnTypeFixer::fix( translationUnit ); // must happen before autogen
-			decayEnumsAndPointers( translationUnit ); // must happen before VerifyCtorDtorAssign, because void return objects should not exist; before LinkReferenceToTypes_old because it is an indexer and needs correct types for mangling
-		}
-		PassVisitor<FixQualifiedTypes> fixQual;
-		{
-			Stats::Heap::newPass("validate-B");
-			Stats::Time::BlockGuard guard("validate-B");
-			linkReferenceToTypes( translationUnit ); // Must happen before auto-gen, because it uses the sized flag.
-			mutateAll( translationUnit, fixQual ); // must happen after LinkReferenceToTypes_old, because aggregate members are accessed
-			HoistStruct::hoistStruct( translationUnit );
-			EliminateTypedef::eliminateTypedef( translationUnit );
-		}
-		PassVisitor<ValidateGenericParameters> genericParams;
-		PassVisitor<ResolveEnumInitializers> rei( nullptr );
-		{
-			Stats::Heap::newPass("validate-C");
-			Stats::Time::BlockGuard guard("validate-C");
-			Stats::Time::TimeBlock("Validate Generic Parameters", [&]() {
-				acceptAll( translationUnit, genericParams );  // check as early as possible - can't happen before LinkReferenceToTypes_old; observed failing when attempted before eliminateTypedef
-			});
-			Stats::Time::TimeBlock("Translate Dimensions", [&]() {
-				TranslateDimensionGenericParameters::translateDimensions( translationUnit );
-			});
-			if (!useNewAST) {
-			Stats::Time::TimeBlock("Resolve Enum Initializers", [&]() {
-				acceptAll( translationUnit, rei ); // must happen after translateDimensions because rei needs identifier lookup, which needs name mangling
-			});
-			}
-			Stats::Time::TimeBlock("Check Function Returns", [&]() {
-				ReturnChecker::checkFunctionReturns( translationUnit );
-			});
-			Stats::Time::TimeBlock("Fix Return Statements", [&]() {
-				InitTweak::fixReturnStatements( translationUnit ); // must happen before autogen
-			});
-		}
-		{
-			Stats::Heap::newPass("validate-D");
-			Stats::Time::BlockGuard guard("validate-D");
-			Stats::Time::TimeBlock("Apply Concurrent Keywords", [&]() {
-				Concurrency::applyKeywords( translationUnit );
-			});
-			Stats::Time::TimeBlock("Forall Pointer Decay", [&]() {
-				decayForallPointers( translationUnit ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution
-			});
-			Stats::Time::TimeBlock("Hoist Control Declarations", [&]() {
-				ControlStruct::hoistControlDecls( translationUnit );  // hoist initialization out of for statements; must happen before autogenerateRoutines
-			});
-			Stats::Time::TimeBlock("Generate Autogen routines", [&]() {
-				autogenerateRoutines( translationUnit ); // moved up, used to be below compoundLiteral - currently needs EnumAndPointerDecay_old
-			});
-		}
-		PassVisitor<CompoundLiteral> compoundliteral;
-		{
-			Stats::Heap::newPass("validate-E");
-			Stats::Time::BlockGuard guard("validate-E");
-			Stats::Time::TimeBlock("Implement Mutex Func", [&]() {
-				Concurrency::implementMutexFuncs( translationUnit );
-			});
-			Stats::Time::TimeBlock("Implement Thread Start", [&]() {
-				Concurrency::implementThreadStarter( translationUnit );
-			});
-			Stats::Time::TimeBlock("Compound Literal", [&]() {
-				mutateAll( translationUnit, compoundliteral );
-			});
-			if (!useNewAST) {
-				Stats::Time::TimeBlock("Resolve With Expressions", [&]() {
-					ResolvExpr::resolveWithExprs( translationUnit ); // must happen before FixObjectType because user-code is resolved and may contain with variables
-				});
-			}
-		}
-		PassVisitor<LabelAddressFixer> labelAddrFixer;
-		{
-			Stats::Heap::newPass("validate-F");
-			Stats::Time::BlockGuard guard("validate-F");
-			if (!useNewAST) {
-				Stats::Time::TimeCall("Fix Object Type",
-					FixObjectType::fix, translationUnit);
-			}
-			Stats::Time::TimeCall("Initializer Length",
-				InitializerLength::computeLength, translationUnit);
-			if (!useNewAST) {
-				Stats::Time::TimeCall("Array Length",
-					ArrayLength::computeLength, translationUnit);
-			}
-			Stats::Time::TimeCall("Find Special Declarations",
-				Validate::findSpecialDecls, translationUnit);
-			Stats::Time::TimeCall("Fix Label Address",
-				mutateAll<LabelAddressFixer>, translationUnit, labelAddrFixer);
-			if (!useNewAST) {
-				Stats::Time::TimeCall("Handle Attributes",
-					Validate::handleAttributes, translationUnit);
-			}
-		}
-	}
-
-	void HoistTypeDecls::handleType( Type * type ) {
-		// some type declarations are buried in expressions and not easy to hoist during parsing; hoist them here
-		AggregateDecl * aggr = nullptr;
-		if ( StructInstType * inst = dynamic_cast< StructInstType * >( type ) ) {
-			aggr = inst->baseStruct;
-		} else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( type ) ) {
-			aggr = inst->baseUnion;
-		} else if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( type ) ) {
-			aggr = inst->baseEnum;
-		}
-		if ( aggr && aggr->body ) {
-			declsToAddBefore.push_front( aggr );
-		}
-	}
-
-	void HoistTypeDecls::previsit( SizeofExpr * expr ) {
-		handleType( expr->type );
-	}
-
-	void HoistTypeDecls::previsit( AlignofExpr * expr ) {
-		handleType( expr->type );
-	}
-
-	void HoistTypeDecls::previsit( UntypedOffsetofExpr * expr ) {
-		handleType( expr->type );
-	}
-
-	void HoistTypeDecls::previsit( CompoundLiteralExpr * expr ) {
-		handleType( expr->result );
-	}
-
-
-	Type * FixQualifiedTypes::postmutate( QualifiedType * qualType ) {
-		Type * parent = qualType->parent;
-		Type * child = qualType->child;
-		if ( dynamic_cast< GlobalScopeType * >( qualType->parent ) ) {
-			// .T => lookup T at global scope
-			if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( child ) ) {
-				auto td = indexer.globalLookupType( inst->name );
-				if ( ! td ) {
-					SemanticError( qualType->location, toString("Use of undefined global type ", inst->name) );
-				}
-				auto base = td->base;
-				assert( base );
-				Type * ret = base->clone();
-				ret->get_qualifiers() = qualType->get_qualifiers();
-				return ret;
-			} else {
-				// .T => T is not a type name
-				assertf( false, "unhandled global qualified child type: %s", toCString(child) );
-			}
-		} else {
-			// S.T => S must be an aggregate type, find the declaration for T in S.
-			AggregateDecl * aggr = nullptr;
-			if ( StructInstType * inst = dynamic_cast< StructInstType * >( parent ) ) {
-				aggr = inst->baseStruct;
-			} else if ( UnionInstType * inst = dynamic_cast< UnionInstType * > ( parent ) ) {
-				aggr = inst->baseUnion;
-			} else {
-				SemanticError( qualType->location, toString("Qualified type requires an aggregate on the left, but has: ", parent) );
-			}
-			assert( aggr ); // TODO: need to handle forward declarations
-			for ( Declaration * member : aggr->members ) {
-				if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( child ) ) {
-					// name on the right is a typedef
-					if ( NamedTypeDecl * aggr = dynamic_cast< NamedTypeDecl * > ( member ) ) {
-						if ( aggr->name == inst->name ) {
-							assert( aggr->base );
-							Type * ret = aggr->base->clone();
-							ret->get_qualifiers() = qualType->get_qualifiers();
-							TypeSubstitution sub = parent->genericSubstitution();
-							sub.apply(ret);
-							return ret;
-						}
-					}
-				} else {
-					// S.T - S is not an aggregate => error
-					assertf( false, "unhandled qualified child type: %s", toCString(qualType) );
-				}
-			}
-			// failed to find a satisfying definition of type
-			SemanticError( qualType->location, toString("Undefined type in qualified type: ", qualType) );
-		}
-
-		// ... may want to link canonical SUE definition to each forward decl so that it becomes easier to lookup?
-	}
-
-
-	void HoistStruct::hoistStruct( std::list< Declaration * > &translationUnit ) {
-		PassVisitor<HoistStruct> hoister;
-		acceptAll( translationUnit, hoister );
-	}
-
-	bool shouldHoist( Declaration * decl ) {
-		return dynamic_cast< StructDecl * >( decl ) || dynamic_cast< UnionDecl * >( decl ) || dynamic_cast< StaticAssertDecl * >( decl );
-	}
-
-	namespace {
-		void qualifiedName( AggregateDecl * aggr, std::ostringstream & ss ) {
-			if ( aggr->parent ) qualifiedName( aggr->parent, ss );
-			ss << "__" << aggr->name;
-		}
-
-		// mangle nested type names using entire parent chain
-		std::string qualifiedName( AggregateDecl * aggr ) {
-			std::ostringstream ss;
-			qualifiedName( aggr, ss );
-			return ss.str();
-		}
-	}
-
-	template< typename AggDecl >
-	void HoistStruct::handleAggregate( AggDecl * aggregateDecl ) {
-		if ( parentAggr ) {
-			aggregateDecl->parent = parentAggr;
-			aggregateDecl->name = qualifiedName( aggregateDecl );
-			// Add elements in stack order corresponding to nesting structure.
-			declsToAddBefore.push_front( aggregateDecl );
-		} else {
-			GuardValue( parentAggr );
-			parentAggr = aggregateDecl;
-		} // if
-		// Always remove the hoisted aggregate from the inner structure.
-		GuardAction( [aggregateDecl]() { filter( aggregateDecl->members, shouldHoist, false ); } );
-	}
-
-	void HoistStruct::previsit( StaticAssertDecl * assertDecl ) {
-		if ( parentAggr ) {
-			declsToAddBefore.push_back( assertDecl );
-		}
-	}
-
-	void HoistStruct::previsit( StructDecl * aggregateDecl ) {
-		handleAggregate( aggregateDecl );
-	}
-
-	void HoistStruct::previsit( UnionDecl * aggregateDecl ) {
-		handleAggregate( aggregateDecl );
-	}
-
-	void HoistStruct::previsit( StructInstType * type ) {
-		// need to reset type name after expanding to qualified name
-		assert( type->baseStruct );
-		type->name = type->baseStruct->name;
-	}
-
-	void HoistStruct::previsit( UnionInstType * type ) {
-		assert( type->baseUnion );
-		type->name = type->baseUnion->name;
-	}
-
-	void HoistStruct::previsit( EnumInstType * type ) {
-		assert( type->baseEnum );
-		type->name = type->baseEnum->name;
-	}
-
-
-	bool isTypedef( Declaration * decl ) {
-		return dynamic_cast< TypedefDecl * >( decl );
-	}
-
-	void EliminateTypedef::eliminateTypedef( std::list< Declaration * > &translationUnit ) {
-		PassVisitor<EliminateTypedef> eliminator;
-		acceptAll( translationUnit, eliminator );
-		filter( translationUnit, isTypedef, true );
-	}
-
-	template< typename AggDecl >
-	void EliminateTypedef::handleAggregate( AggDecl * aggregateDecl ) {
-		filter( aggregateDecl->members, isTypedef, true );
-	}
-
-	void EliminateTypedef::previsit( StructDecl * aggregateDecl ) {
-		handleAggregate( aggregateDecl );
-	}
-
-	void EliminateTypedef::previsit( UnionDecl * aggregateDecl ) {
-		handleAggregate( aggregateDecl );
-	}
-
-	void EliminateTypedef::previsit( CompoundStmt * compoundStmt ) {
-		// remove and delete decl stmts
-		filter( compoundStmt->kids, [](Statement * stmt) {
-			if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
-				if ( dynamic_cast< TypedefDecl * >( declStmt->decl ) ) {
-					return true;
-				} // if
-			} // if
-			return false;
-		}, true);
-	}
-
-	// expand assertions from trait instance, performing the appropriate type variable substitutions
-	template< typename Iterator >
-	void expandAssertions( TraitInstType * inst, Iterator out ) {
-		assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toCString( inst ) );
-		std::list< DeclarationWithType * > asserts;
-		for ( Declaration * decl : inst->baseTrait->members ) {
-			asserts.push_back( strict_dynamic_cast<DeclarationWithType *>( decl->clone() ) );
-		}
-		// substitute trait decl parameters for instance parameters
-		applySubstitution( inst->baseTrait->parameters.begin(), inst->baseTrait->parameters.end(), inst->parameters.begin(), asserts.begin(), asserts.end(), out );
-	}
-
-	ResolveEnumInitializers::ResolveEnumInitializers( const Indexer * other_indexer ) : WithIndexer( true ) {
-		if ( other_indexer ) {
-			local_indexer = other_indexer;
-		} else {
-			local_indexer = &indexer;
-		} // if
-	}
-
-	void ResolveEnumInitializers::postvisit( EnumDecl * enumDecl ) {
-		if ( enumDecl->body ) {
-			for ( Declaration * member : enumDecl->members ) {
-				ObjectDecl * field = strict_dynamic_cast<ObjectDecl *>( member );
-				if ( field->init ) {
-					// need to resolve enumerator initializers early so that other passes that determine if an expression is constexpr have the appropriate information.
-					SingleInit * init = strict_dynamic_cast<SingleInit *>( field->init );
-					if ( !enumDecl->base || dynamic_cast<BasicType *>(enumDecl->base))
-						ResolvExpr::findSingleExpression( init->value, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), indexer );
-					else {
-						if (dynamic_cast<PointerType *>(enumDecl->base)) {
-							auto typePtr = dynamic_cast<PointerType *>(enumDecl->base);
-							ResolvExpr::findSingleExpression( init->value,
-							 new PointerType( Type::Qualifiers(), typePtr->base ), indexer );
-						} else {
-							ResolvExpr::findSingleExpression( init->value, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), indexer );
-						}
-					}
-				}
-			}
-
-		} // if
-	}
-
-	/// Fix up assertions - flattens assertion lists, removing all trait instances
-	void forallFixer( std::list< TypeDecl * > & forall, BaseSyntaxNode * node ) {
-		for ( TypeDecl * type : forall ) {
-			std::list< DeclarationWithType * > asserts;
-			asserts.splice( asserts.end(), type->assertions );
-			// expand trait instances into their members
-			for ( DeclarationWithType * assertion : asserts ) {
-				if ( TraitInstType * traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
-					// expand trait instance into all of its members
-					expandAssertions( traitInst, back_inserter( type->assertions ) );
-					delete traitInst;
-				} else {
-					// pass other assertions through
-					type->assertions.push_back( assertion );
-				} // if
-			} // for
-			// apply FixFunction to every assertion to check for invalid void type
-			for ( DeclarationWithType *& assertion : type->assertions ) {
-				bool isVoid = fixFunction( assertion );
-				if ( isVoid ) {
-					SemanticError( node, "invalid type void in assertion of function " );
-				} // if
-			} // for
-			// normalizeAssertions( type->assertions );
-		} // for
-	}
-
-	/// Replace all traits in assertion lists with their assertions.
-	void expandTraits( std::list< TypeDecl * > & forall ) {
-		for ( TypeDecl * type : forall ) {
-			std::list< DeclarationWithType * > asserts;
-			asserts.splice( asserts.end(), type->assertions );
-			// expand trait instances into their members
-			for ( DeclarationWithType * assertion : asserts ) {
-				if ( TraitInstType * traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
-					// expand trait instance into all of its members
-					expandAssertions( traitInst, back_inserter( type->assertions ) );
-					delete traitInst;
-				} else {
-					// pass other assertions through
-					type->assertions.push_back( assertion );
-				} // if
-			} // for
-		}
-	}
-
-	/// Fix each function in the assertion list and check for invalid void type.
-	void fixAssertions(
-			std::list< TypeDecl * > & forall, BaseSyntaxNode * node ) {
-		for ( TypeDecl * type : forall ) {
-			for ( DeclarationWithType *& assertion : type->assertions ) {
-				bool isVoid = fixFunction( assertion );
-				if ( isVoid ) {
-					SemanticError( node, "invalid type void in assertion of function " );
-				} // if
-			} // for
-		}
-	}
-
-	void ForallPointerDecay_old::previsit( ObjectDecl * object ) {
-		// ensure that operator names only apply to functions or function pointers
-		if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) {
-			SemanticError( object->location, toCString( "operator ", object->name.c_str(), " is not a function or function pointer." )  );
-		}
-		object->fixUniqueId();
-	}
-
-	void ForallPointerDecay_old::previsit( FunctionDecl * func ) {
-		func->fixUniqueId();
-	}
-
-	void ForallPointerDecay_old::previsit( FunctionType * ftype ) {
-		forallFixer( ftype->forall, ftype );
-	}
-
-	void ForallPointerDecay_old::previsit( StructDecl * aggrDecl ) {
-		forallFixer( aggrDecl->parameters, aggrDecl );
-	}
-
-	void ForallPointerDecay_old::previsit( UnionDecl * aggrDecl ) {
-		forallFixer( aggrDecl->parameters, aggrDecl );
-	}
-
-	void ReturnChecker::checkFunctionReturns( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<ReturnChecker> checker;
-		acceptAll( translationUnit, checker );
-	}
-
-	void ReturnChecker::previsit( FunctionDecl * functionDecl ) {
-		GuardValue( returnVals );
-		returnVals = functionDecl->get_functionType()->get_returnVals();
-	}
-
-	void ReturnChecker::previsit( ReturnStmt * returnStmt ) {
-		// Previously this also checked for the existence of an expr paired with no return values on
-		// the  function return type. This is incorrect, since you can have an expression attached to
-		// a return statement in a void-returning function in C. The expression is treated as if it
-		// were cast to void.
-		if ( ! returnStmt->get_expr() && returnVals.size() != 0 ) {
-			SemanticError( returnStmt, "Non-void function returns no values: " );
-		}
-	}
-
-
-	void ReplaceTypedef::replaceTypedef( std::list< Declaration * > &translationUnit ) {
-		PassVisitor<ReplaceTypedef> eliminator;
-		mutateAll( translationUnit, eliminator );
-		if ( eliminator.pass.typedefNames.count( "size_t" ) ) {
-			// grab and remember declaration of size_t
-			Validate::SizeType = eliminator.pass.typedefNames["size_t"].first->base->clone();
-		} else {
-			// xxx - missing global typedef for size_t - default to long unsigned int, even though that may be wrong
-			// eventually should have a warning for this case.
-			Validate::SizeType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
-		}
-	}
-
-	void ReplaceTypedef::premutate( QualifiedType * ) {
-		visit_children = false;
-	}
-
-	Type * ReplaceTypedef::postmutate( QualifiedType * qualType ) {
-		// replacing typedefs only makes sense for the 'oldest ancestor' of the qualified type
-		qualType->parent = qualType->parent->acceptMutator( * visitor );
-		return qualType;
-	}
-
-	static bool isNonParameterAttribute( Attribute * attr ) {
-		static const std::vector<std::string> bad_names = {
-			"aligned", "__aligned__",
-		};
-		for ( auto name : bad_names ) {
-			if ( name == attr->name ) {
-				return true;
-			}
-		}
-		return false;
-	}
-
-	Type * ReplaceTypedef::postmutate( TypeInstType * typeInst ) {
-		// instances of typedef types will come here. If it is an instance
-		// of a typdef type, link the instance to its actual type.
-		TypedefMap::const_iterator def = typedefNames.find( typeInst->name );
-		if ( def != typedefNames.end() ) {
-			Type * ret = def->second.first->base->clone();
-			ret->location = typeInst->location;
-			ret->get_qualifiers() |= typeInst->get_qualifiers();
-			// GCC ignores certain attributes if they arrive by typedef, this mimics that.
-			if ( inFunctionType ) {
-				ret->attributes.remove_if( isNonParameterAttribute );
-			}
-			ret->attributes.splice( ret->attributes.end(), typeInst->attributes );
-			// place instance parameters on the typedef'd type
-			if ( ! typeInst->parameters.empty() ) {
-				ReferenceToType * rtt = dynamic_cast<ReferenceToType *>(ret);
-				if ( ! rtt ) {
-					SemanticError( typeInst->location, "Cannot apply type parameters to base type of " + typeInst->name );
-				}
-				rtt->parameters.clear();
-				cloneAll( typeInst->parameters, rtt->parameters );
-				mutateAll( rtt->parameters, * visitor );  // recursively fix typedefs on parameters
-			} // if
-			delete typeInst;
-			return ret;
-		} else {
-			TypeDeclMap::const_iterator base = typedeclNames.find( typeInst->name );
-			if ( base == typedeclNames.end() ) {
-				SemanticError( typeInst->location, toString("Use of undefined type ", typeInst->name) );
-			}
-			typeInst->set_baseType( base->second );
-			return typeInst;
-		} // if
-		assert( false );
-	}
-
-	struct VarLenChecker : WithShortCircuiting {
-		void previsit( FunctionType * ) { visit_children = false; }
-		void previsit( ArrayType * at ) {
-			isVarLen |= at->isVarLen;
-		}
-		bool isVarLen = false;
-	};
-
-	bool isVariableLength( Type * t ) {
-		PassVisitor<VarLenChecker> varLenChecker;
-		maybeAccept( t, varLenChecker );
-		return varLenChecker.pass.isVarLen;
-	}
-
-	Declaration * ReplaceTypedef::postmutate( TypedefDecl * tyDecl ) {
-		if ( typedefNames.count( tyDecl->name ) == 1 && typedefNames[ tyDecl->name ].second == scopeLevel ) {
-			// typedef to the same name from the same scope
-			// must be from the same type
-
-			Type * t1 = tyDecl->base;
-			Type * t2 = typedefNames[ tyDecl->name ].first->base;
-			if ( ! ResolvExpr::typesCompatible( t1, t2, Indexer() ) ) {
-				SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name );
-			}
-			// Cannot redefine VLA typedefs. Note: this is slightly incorrect, because our notion of VLAs
-			// at this point in the translator is imprecise. In particular, this will disallow redefining typedefs
-			// with arrays whose dimension is an enumerator or a cast of a constant/enumerator. The effort required
-			// to fix this corner case likely outweighs the utility of allowing it.
-			if ( isVariableLength( t1 ) || isVariableLength( t2 ) ) {
-				SemanticError( tyDecl->location, "Cannot redefine typedef: " + tyDecl->name );
-			}
-		} else {
-			typedefNames[ tyDecl->name ] = std::make_pair( TypedefDeclPtr( tyDecl ), scopeLevel );
-		} // if
-
-		// When a typedef is a forward declaration:
-		//    typedef struct screen SCREEN;
-		// the declaration portion must be retained:
-		//    struct screen;
-		// because the expansion of the typedef is:
-		//    void rtn( SCREEN * p ) => void rtn( struct screen * p )
-		// hence the type-name "screen" must be defined.
-		// Note, qualifiers on the typedef are superfluous for the forward declaration.
-
-		Type * designatorType = tyDecl->base->stripDeclarator();
-		if ( StructInstType * aggDecl = dynamic_cast< StructInstType * >( designatorType ) ) {
-			declsToAddBefore.push_back( new StructDecl( aggDecl->name, AggregateDecl::Struct, noAttributes, tyDecl->linkage ) );
-		} else if ( UnionInstType * aggDecl = dynamic_cast< UnionInstType * >( designatorType ) ) {
-			declsToAddBefore.push_back( new UnionDecl( aggDecl->name, noAttributes, tyDecl->linkage ) );
-		} else if ( EnumInstType * enumInst = dynamic_cast< EnumInstType * >( designatorType ) ) {
-			if ( enumInst->baseEnum ) {
-				const EnumDecl * enumDecl = enumInst->baseEnum;
-				declsToAddBefore.push_back( new EnumDecl( enumDecl->name, noAttributes, enumDecl->isTyped, tyDecl->linkage, enumDecl->base ) );
-			} else {
-				declsToAddBefore.push_back( new EnumDecl( enumInst->name, noAttributes, tyDecl->linkage ) );
-			}
-		} // if
-		return tyDecl->clone();
-	}
-
-	void ReplaceTypedef::premutate( TypeDecl * typeDecl ) {
-		typedefNames.erase( typeDecl->name );
-		typedeclNames.insert( typeDecl->name, typeDecl );
-	}
-
-	void ReplaceTypedef::premutate( FunctionDecl * ) {
-		GuardScope( typedefNames );
-		GuardScope( typedeclNames );
-	}
-
-	void ReplaceTypedef::premutate( ObjectDecl * ) {
-		GuardScope( typedefNames );
-		GuardScope( typedeclNames );
-	}
-
-	DeclarationWithType * ReplaceTypedef::postmutate( ObjectDecl * objDecl ) {
-		if ( FunctionType * funtype = dynamic_cast<FunctionType *>( objDecl->type ) ) { // function type?
-			// replace the current object declaration with a function declaration
-			FunctionDecl * newDecl = new FunctionDecl( objDecl->name, objDecl->get_storageClasses(), objDecl->linkage, funtype, 0, objDecl->attributes, objDecl->get_funcSpec() );
-			objDecl->attributes.clear();
-			objDecl->set_type( nullptr );
-			delete objDecl;
-			return newDecl;
-		} // if
-		return objDecl;
-	}
-
-	void ReplaceTypedef::premutate( CastExpr * ) {
-		GuardScope( typedefNames );
-		GuardScope( typedeclNames );
-	}
-
-	void ReplaceTypedef::premutate( CompoundStmt * ) {
-		GuardScope( typedefNames );
-		GuardScope( typedeclNames );
-		scopeLevel += 1;
-		GuardAction( [this](){ scopeLevel -= 1; } );
-	}
-
-	template<typename AggDecl>
-	void ReplaceTypedef::addImplicitTypedef( AggDecl * aggDecl ) {
-		if ( typedefNames.count( aggDecl->get_name() ) == 0 ) {
-			Type * type = nullptr;
-			if ( StructDecl * newDeclStructDecl = dynamic_cast< StructDecl * >( aggDecl ) ) {
-				type = new StructInstType( Type::Qualifiers(), newDeclStructDecl->get_name() );
-			} else if ( UnionDecl * newDeclUnionDecl = dynamic_cast< UnionDecl * >( aggDecl ) ) {
-				type = new UnionInstType( Type::Qualifiers(), newDeclUnionDecl->get_name() );
-			} else if ( EnumDecl * newDeclEnumDecl = dynamic_cast< EnumDecl * >( aggDecl )  ) {
-				type = new EnumInstType( Type::Qualifiers(), newDeclEnumDecl->get_name() );
-			} // if
-			TypedefDeclPtr tyDecl( new TypedefDecl( aggDecl->get_name(), aggDecl->location, Type::StorageClasses(), type, aggDecl->get_linkage() ) );
-			typedefNames[ aggDecl->get_name() ] = std::make_pair( std::move( tyDecl ), scopeLevel );
-			// add the implicit typedef to the AST
-			declsToAddBefore.push_back( new TypedefDecl( aggDecl->get_name(), aggDecl->location, Type::StorageClasses(), type->clone(), aggDecl->get_linkage() ) );
-		} // if
-	}
-
-	template< typename AggDecl >
-	void ReplaceTypedef::handleAggregate( AggDecl * aggr ) {
-		SemanticErrorException errors;
-
-		ValueGuard< std::list<Declaration * > > oldBeforeDecls( declsToAddBefore );
-		ValueGuard< std::list<Declaration * > > oldAfterDecls ( declsToAddAfter  );
-		declsToAddBefore.clear();
-		declsToAddAfter.clear();
-
-		GuardScope( typedefNames );
-		GuardScope( typedeclNames );
-		mutateAll( aggr->parameters, * visitor );
-		mutateAll( aggr->attributes, * visitor );
-
-		// unroll mutateAll for aggr->members so that implicit typedefs for nested types are added to the aggregate body.
-		for ( std::list< Declaration * >::iterator i = aggr->members.begin(); i != aggr->members.end(); ++i ) {
-			if ( !declsToAddAfter.empty() ) { aggr->members.splice( i, declsToAddAfter ); }
-
-			try {
-				* i = maybeMutate( * i, * visitor );
-			} catch ( SemanticErrorException &e ) {
-				errors.append( e );
-			}
-
-			if ( !declsToAddBefore.empty() ) { aggr->members.splice( i, declsToAddBefore ); }
-		}
-
-		if ( !declsToAddAfter.empty() ) { aggr->members.splice( aggr->members.end(), declsToAddAfter ); }
-		if ( !errors.isEmpty() ) { throw errors; }
-	}
-
-	void ReplaceTypedef::premutate( StructDecl * structDecl ) {
-		visit_children = false;
-		addImplicitTypedef( structDecl );
-		handleAggregate( structDecl );
-	}
-
-	void ReplaceTypedef::premutate( UnionDecl * unionDecl ) {
-		visit_children = false;
-		addImplicitTypedef( unionDecl );
-		handleAggregate( unionDecl );
-	}
-
-	void ReplaceTypedef::premutate( EnumDecl * enumDecl ) {
-		addImplicitTypedef( enumDecl );
-	}
-
-	void ReplaceTypedef::premutate( FunctionType * ) {
-		GuardValue( inFunctionType );
-		inFunctionType = true;
-	}
-
-	void ReplaceTypedef::premutate( TraitDecl * ) {
-		GuardScope( typedefNames );
-		GuardScope( typedeclNames);
-	}
-
-	void VerifyCtorDtorAssign::verify( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<VerifyCtorDtorAssign> verifier;
-		acceptAll( translationUnit, verifier );
-	}
-
-	void VerifyCtorDtorAssign::previsit( FunctionDecl * funcDecl ) {
-		FunctionType * funcType = funcDecl->get_functionType();
-		std::list< DeclarationWithType * > &returnVals = funcType->get_returnVals();
-		std::list< DeclarationWithType * > &params = funcType->get_parameters();
-
-		if ( CodeGen::isCtorDtorAssign( funcDecl->get_name() ) ) { // TODO: also check /=, etc.
-			if ( params.size() == 0 ) {
-				SemanticError( funcDecl->location, "Constructors, destructors, and assignment functions require at least one parameter." );
-			}
-			ReferenceType * refType = dynamic_cast< ReferenceType * >( params.front()->get_type() );
-			if ( ! refType ) {
-				SemanticError( funcDecl->location, "First parameter of a constructor, destructor, or assignment function must be a reference." );
-			}
-			if ( CodeGen::isCtorDtor( funcDecl->get_name() ) && returnVals.size() != 0 ) {
-				if(!returnVals.front()->get_type()->isVoid()) {
-					SemanticError( funcDecl->location, "Constructors and destructors cannot have explicit return values." );
-				}
-			}
-		}
-	}
-
-	// Test for special name on a generic parameter.  Special treatment for the
-	// special name is a bootstrapping hack.  In most cases, the worlds of T's
-	// and of N's don't overlap (normal treamtemt).  The foundations in
-	// array.hfa use tagging for both types and dimensions.  Tagging treats
-	// its subject parameter even more opaquely than T&, which assumes it is
-	// possible to have a pointer/reference to such an object.  Tagging only
-	// seeks to identify the type-system resident at compile time.  Both N's
-	// and T's can make tags.  The tag definition uses the special name, which
-	// is treated as "an N or a T."  This feature is not inteded to be used
-	// outside of the definition and immediate uses of a tag.
-	static inline bool isReservedTysysIdOnlyName( const std::string & name ) {
-		// name's prefix was __CFA_tysys_id_only, before it got wrapped in __..._generic
-		int foundAt = name.find("__CFA_tysys_id_only");
-		if (foundAt == 0) return true;
-		if (foundAt == 2 && name[0] == '_' && name[1] == '_') return true;
-		return false;
-	}
-
-	template< typename Aggr >
-	void validateGeneric( Aggr * inst ) {
-		std::list< TypeDecl * > * params = inst->get_baseParameters();
-		if ( params ) {
-			std::list< Expression * > & args = inst->get_parameters();
-
-			// insert defaults arguments when a type argument is missing (currently only supports missing arguments at the end of the list).
-			// A substitution is used to ensure that defaults are replaced correctly, e.g.,
-			//   forall(otype T, otype alloc = heap_allocator(T)) struct vector;
-			//   vector(int) v;
-			// after insertion of default values becomes
-			//   vector(int, heap_allocator(T))
-			// and the substitution is built with T=int so that after substitution, the result is
-			//   vector(int, heap_allocator(int))
-			TypeSubstitution sub;
-			auto paramIter = params->begin();
-			auto argIter = args.begin();
-			for ( ; paramIter != params->end(); ++paramIter, ++argIter ) {
-				if ( argIter != args.end() ) {
-					TypeExpr * expr = dynamic_cast< TypeExpr * >( * argIter );
-					if ( expr ) {
-						sub.add( (* paramIter)->get_name(), expr->get_type()->clone() );
-					}
-				} else {
-					Type * defaultType = (* paramIter)->get_init();
-					if ( defaultType ) {
-						args.push_back( new TypeExpr( defaultType->clone() ) );
-						sub.add( (* paramIter)->get_name(), defaultType->clone() );
-						argIter = std::prev(args.end());
-					} else {
-						SemanticError( inst, "Too few type arguments in generic type " );
-					}
-				}
-				assert( argIter != args.end() );
-				bool typeParamDeclared = (*paramIter)->kind != TypeDecl::Kind::Dimension;
-				bool typeArgGiven;
-				if ( isReservedTysysIdOnlyName( (*paramIter)->name ) ) {
-					// coerce a match when declaration is reserved name, which means "either"
-					typeArgGiven = typeParamDeclared;
-				} else {
-					typeArgGiven = dynamic_cast< TypeExpr * >( * argIter );
-				}
-				if ( ! typeParamDeclared &&   typeArgGiven ) SemanticError( inst, "Type argument given for value parameter: " );
-				if (   typeParamDeclared && ! typeArgGiven ) SemanticError( inst, "Expression argument given for type parameter: " );
-			}
-
-			sub.apply( inst );
-			if ( args.size() > params->size() ) SemanticError( inst, "Too many type arguments in generic type " );
-		}
-	}
-
-	void ValidateGenericParameters::previsit( StructInstType * inst ) {
-		validateGeneric( inst );
-	}
-
-	void ValidateGenericParameters::previsit( UnionInstType * inst ) {
-		validateGeneric( inst );
-	}
-
-	void TranslateDimensionGenericParameters::translateDimensions( std::list< Declaration * > &translationUnit ) {
-		PassVisitor<TranslateDimensionGenericParameters> translator;
-		mutateAll( translationUnit, translator );
-	}
-
-	TranslateDimensionGenericParameters::TranslateDimensionGenericParameters() : WithIndexer( false ) {}
-
-	// Declaration of type variable:           forall( [N] )          ->  forall( N & | sized( N ) )
-	TypeDecl * TranslateDimensionGenericParameters::postmutate( TypeDecl * td ) {
-		if ( td->kind == TypeDecl::Dimension ) {
-			td->kind = TypeDecl::Dtype;
-			if ( ! isReservedTysysIdOnlyName( td->name ) ) {
-				td->sized = true;
-			}
-		}
-		return td;
-	}
-
-	// Situational awareness:
-	// array( float, [[currentExpr]]     )  has  visitingChildOfSUIT == true
-	// array( float, [[currentExpr]] - 1 )  has  visitingChildOfSUIT == false
-	// size_t x =    [[currentExpr]]        has  visitingChildOfSUIT == false
-	void TranslateDimensionGenericParameters::changeState_ChildOfSUIT( bool newVal ) {
-		GuardValue( nextVisitedNodeIsChildOfSUIT );
-		GuardValue( visitingChildOfSUIT );
-		visitingChildOfSUIT = nextVisitedNodeIsChildOfSUIT;
-		nextVisitedNodeIsChildOfSUIT = newVal;
-	}
-	void TranslateDimensionGenericParameters::premutate( StructInstType * sit ) {
-		(void) sit;
-		changeState_ChildOfSUIT(true);
-	}
-	void TranslateDimensionGenericParameters::premutate( UnionInstType * uit ) {
-		(void) uit;
-		changeState_ChildOfSUIT(true);
-	}
-	void TranslateDimensionGenericParameters::premutate( BaseSyntaxNode * node ) {
-		(void) node;
-		changeState_ChildOfSUIT(false);
-	}
-
-	// Passing values as dimension arguments:  array( float,     7 )  -> array( float, char[             7 ] )
-	// Consuming dimension parameters:         size_t x =    N - 1 ;  -> size_t x =          sizeof(N) - 1   ;
-	// Intertwined reality:                    array( float, N     )  -> array( float,              N        )
-	//                                         array( float, N - 1 )  -> array( float, char[ sizeof(N) - 1 ] )
-	// Intertwined case 1 is not just an optimization.
-	// Avoiding char[sizeof(-)] is necessary to enable the call of f to bind the value of N, in:
-	//   forall([N]) void f( array(float, N) & );
-	//   array(float, 7) a;
-	//   f(a);
-
-	Expression * TranslateDimensionGenericParameters::postmutate( DimensionExpr * de ) {
-		// Expression de is an occurrence of N in LHS of above examples.
-		// Look up the name that de references.
-		// If we are in a struct body, then this reference can be to an entry of the stuct's forall list.
-		// Whether or not we are in a struct body, this reference can be to an entry of a containing function's forall list.
-		// If we are in a struct body, then the stuct's forall declarations are innermost (functions don't occur in structs).
-		// Thus, a potential struct's declaration is highest priority.
-		// A struct's forall declarations are already renamed with _generic_ suffix.  Try that name variant first.
-
-		std::string useName = "__" + de->name + "_generic_";
-		TypeDecl * namedParamDecl = const_cast<TypeDecl *>( strict_dynamic_cast<const TypeDecl *, nullptr >( indexer.lookupType( useName ) ) );
-
-		if ( ! namedParamDecl ) {
-			useName = de->name;
-			namedParamDecl = const_cast<TypeDecl *>( strict_dynamic_cast<const TypeDecl *, nullptr >( indexer.lookupType( useName ) ) );
-		}
-
-		// Expect to find it always.  A misspelled name would have been parsed as an identifier.
-		assert( namedParamDecl && "Type-system-managed value name not found in symbol table" );
-
-		delete de;
-
-		TypeInstType * refToDecl = new TypeInstType( 0, useName, namedParamDecl );
-
-		if ( visitingChildOfSUIT ) {
-			// As in postmutate( Expression * ), topmost expression needs a TypeExpr wrapper
-			// But avoid ArrayType-Sizeof
-			return new TypeExpr( refToDecl );
-		} else {
-			// the N occurrence is being used directly as a runtime value,
-			// if we are in a type instantiation, then the N is within a bigger value computation
-			return new SizeofExpr( refToDecl );
-		}
-	}
-
-	Expression * TranslateDimensionGenericParameters::postmutate( Expression * e ) {
-		if ( visitingChildOfSUIT ) {
-			// e is an expression used as an argument to instantiate a type
-			if (! dynamic_cast< TypeExpr * >( e ) ) {
-				// e is a value expression
-				// but not a DimensionExpr, which has a distinct postmutate
-				Type * typeExprContent = new ArrayType( 0, new BasicType( 0, BasicType::Char ), e, true, false );
-				TypeExpr * result = new TypeExpr( typeExprContent );
-				return result;
-			}
-		}
-		return e;
-	}
-
-	void CompoundLiteral::premutate( ObjectDecl * objectDecl ) {
-		storageClasses = objectDecl->get_storageClasses();
-	}
-
-	Expression * CompoundLiteral::postmutate( CompoundLiteralExpr * compLitExpr ) {
-		// transform [storage_class] ... (struct S){ 3, ... };
-		// into [storage_class] struct S temp =  { 3, ... };
-		static UniqueName indexName( "_compLit" );
-
-		ObjectDecl * tempvar = new ObjectDecl( indexName.newName(), storageClasses, LinkageSpec::C, nullptr, compLitExpr->get_result(), compLitExpr->get_initializer() );
-		compLitExpr->set_result( nullptr );
-		compLitExpr->set_initializer( nullptr );
-		delete compLitExpr;
-		declsToAddBefore.push_back( tempvar );					// add modified temporary to current block
-		return new VariableExpr( tempvar );
-	}
-
-	void ReturnTypeFixer::fix( std::list< Declaration * > &translationUnit ) {
-		PassVisitor<ReturnTypeFixer> fixer;
-		acceptAll( translationUnit, fixer );
-	}
-
-	void ReturnTypeFixer::postvisit( FunctionDecl * functionDecl ) {
-		FunctionType * ftype = functionDecl->get_functionType();
-		std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
-		assertf( retVals.size() == 0 || retVals.size() == 1, "Function %s has too many return values: %zu", functionDecl->get_name().c_str(), retVals.size() );
-		if ( retVals.size() == 1 ) {
-			// ensure all function return values have a name - use the name of the function to disambiguate (this also provides a nice bit of help for debugging).
-			// ensure other return values have a name.
-			DeclarationWithType * ret = retVals.front();
-			if ( ret->get_name() == "" ) {
-				ret->set_name( toString( "_retval_", CodeGen::genName( functionDecl ) ) );
-			}
-			ret->get_attributes().push_back( new Attribute( "unused" ) );
-		}
-	}
-
-	void ReturnTypeFixer::postvisit( FunctionType * ftype ) {
-		// xxx - need to handle named return values - this information needs to be saved somehow
-		// so that resolution has access to the names.
-		// Note that this pass needs to happen early so that other passes which look for tuple types
-		// find them in all of the right places, including function return types.
-		std::list< DeclarationWithType * > & retVals = ftype->get_returnVals();
-		if ( retVals.size() > 1 ) {
-			// generate a single return parameter which is the tuple of all of the return values
-			TupleType * tupleType = strict_dynamic_cast< TupleType * >( ResolvExpr::extractResultType( ftype ) );
-			// ensure return value is not destructed by explicitly creating an empty ListInit node wherein maybeConstruct is false.
-			ObjectDecl * newRet = new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::Cforall, 0, tupleType, new ListInit( std::list<Initializer *>(), noDesignators, false ) );
-			deleteAll( retVals );
-			retVals.clear();
-			retVals.push_back( newRet );
-		}
-	}
-
-	void FixObjectType::fix( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<FixObjectType> fixer;
-		acceptAll( translationUnit, fixer );
-	}
-
-	void FixObjectType::previsit( ObjectDecl * objDecl ) {
-		Type * new_type = ResolvExpr::resolveTypeof( objDecl->get_type(), indexer );
-		objDecl->set_type( new_type );
-	}
-
-	void FixObjectType::previsit( FunctionDecl * funcDecl ) {
-		Type * new_type = ResolvExpr::resolveTypeof( funcDecl->type, indexer );
-		funcDecl->set_type( new_type );
-	}
-
-	void FixObjectType::previsit( TypeDecl * typeDecl ) {
-		if ( typeDecl->get_base() ) {
-			Type * new_type = ResolvExpr::resolveTypeof( typeDecl->get_base(), indexer );
-			typeDecl->set_base( new_type );
-		} // if
-	}
-
-	void InitializerLength::computeLength( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<InitializerLength> len;
-		acceptAll( translationUnit, len );
-	}
-
-	void ArrayLength::computeLength( std::list< Declaration * > & translationUnit ) {
-		PassVisitor<ArrayLength> len;
-		acceptAll( translationUnit, len );
-	}
-
-	void InitializerLength::previsit( ObjectDecl * objDecl ) {
-		if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->type ) ) {
-			if ( at->dimension ) return;
-			if ( ListInit * init = dynamic_cast< ListInit * >( objDecl->init ) ) {
-				at->dimension = new ConstantExpr( Constant::from_ulong( init->initializers.size() ) );
-			}
-		}
-	}
-
-	void ArrayLength::previsit( ArrayType * type ) {
-		if ( type->dimension ) {
-			// need to resolve array dimensions early so that constructor code can correctly determine
-			// if a type is a VLA (and hence whether its elements need to be constructed)
-			ResolvExpr::findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
-
-			// must re-evaluate whether a type is a VLA, now that more information is available
-			// (e.g. the dimension may have been an enumerator, which was unknown prior to this step)
-			type->isVarLen = ! InitTweak::isConstExpr( type->dimension );
-		}
-	}
-
-	struct LabelFinder {
-		std::set< Label > & labels;
-		LabelFinder( std::set< Label > & labels ) : labels( labels ) {}
-		void previsit( Statement * stmt ) {
-			for ( Label & l : stmt->labels ) {
-				labels.insert( l );
-			}
-		}
-	};
-
-	void LabelAddressFixer::premutate( FunctionDecl * funcDecl ) {
-		GuardValue( labels );
-		PassVisitor<LabelFinder> finder( labels );
-		funcDecl->accept( finder );
-	}
-
-	Expression * LabelAddressFixer::postmutate( AddressExpr * addrExpr ) {
-		// convert &&label into label address
-		if ( AddressExpr * inner = dynamic_cast< AddressExpr * >( addrExpr->arg ) ) {
-			if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( inner->arg ) ) {
-				if ( labels.count( nameExpr->name ) ) {
-					Label name = nameExpr->name;
-					delete addrExpr;
-					return new LabelAddressExpr( name );
-				}
-			}
-		}
-		return addrExpr;
-	}
-
-} // namespace SymTab
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/SymTab/Validate.h
===================================================================
--- src/SymTab/Validate.h	(revision 934fa0fc6af3737f7f5b45e08f4b84e1e8259312)
+++ 	(revision )
@@ -1,32 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// Validate.h -- This class is intended to perform pre-processing of declarations, validating their correctness and
-//               computing some auxilliary data that is necessary for the indexer.
-//
-// Author           : Richard C. Bilson
-// Created On       : Sun May 17 21:53:34 2015
-// Last Modified By : Andrew Beach
-// Last Modified On : Tue Jul 12 15:30:00 2022
-// Update Count     : 6
-//
-
-#pragma once
-
-#include <list>  // for list
-
-class Declaration;
-
-namespace SymTab {
-	/// Normalizes struct and function declarations
-	void validate( std::list< Declaration * > &translationUnit, bool doDebug = false );
-} // namespace SymTab
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/SymTab/ValidateType.cc
===================================================================
--- src/SymTab/ValidateType.cc	(revision 934fa0fc6af3737f7f5b45e08f4b84e1e8259312)
+++ 	(revision )
@@ -1,491 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// ValidateType.cc -- Validate and normalize types.
-//
-// Author           : Andrew Beach
-// Created On       : Mon May 16 16:21:00 2022
-// Last Modified By : Andrew Beach
-// Last Modified On : Tue May 17 14:06:00 2022
-// Update Count     : 0
-//
-
-#include "ValidateType.h"
-
-#include "CodeGen/OperatorTable.h"
-#include "Common/PassVisitor.h"
-#include "Common/ToString.hpp"
-#include "SymTab/FixFunction.h"
-#include "SynTree/Declaration.h"
-#include "SynTree/Type.h"
-
-namespace SymTab {
-
-namespace {
-
-/// Replaces enum types by int, and function or array types in function
-/// parameter and return lists by appropriate pointers.
-struct EnumAndPointerDecay_old {
-	void previsit( EnumDecl * aggregateDecl );
-	void previsit( FunctionType * func );
-};
-
-void EnumAndPointerDecay_old::previsit( EnumDecl * enumDecl ) {
-	// Set the type of each member of the enumeration to be EnumConstant
-	for ( std::list< Declaration * >::iterator i = enumDecl->members.begin(); i != enumDecl->members.end(); ++i ) {
-		ObjectDecl * obj = dynamic_cast< ObjectDecl * >( * i );
-		assert( obj );
-		obj->set_type( new EnumInstType( Type::Qualifiers( Type::Const ), enumDecl->name ) );
-	} // for
-}
-
-template< typename DWTList >
-void fixFunctionList( DWTList & dwts, bool isVarArgs, FunctionType * func ) {
-	auto nvals = dwts.size();
-	bool containsVoid = false;
-	for ( auto & dwt : dwts ) {
-		// fix each DWT and record whether a void was found
-		containsVoid |= fixFunction( dwt );
-	}
-
-	// the only case in which "void" is valid is where it is the only one in the list
-	if ( containsVoid && ( nvals > 1 || isVarArgs ) ) {
-		SemanticError( func, "invalid type void in function type " );
-	}
-
-	// one void is the only thing in the list; remove it.
-	if ( containsVoid ) {
-		delete dwts.front();
-		dwts.clear();
-	}
-}
-
-void EnumAndPointerDecay_old::previsit( FunctionType * func ) {
-	// Fix up parameters and return types
-	fixFunctionList( func->parameters, func->isVarArgs, func );
-	fixFunctionList( func->returnVals, false, func );
-}
-
-/// Associates forward declarations of aggregates with their definitions
-struct LinkReferenceToTypes_old final : public WithIndexer, public WithGuards, public WithVisitorRef<LinkReferenceToTypes_old>, public WithShortCircuiting {
-	LinkReferenceToTypes_old( const Indexer * indexer );
-
-	void postvisit( TypeInstType * typeInst );
-
-	void postvisit( EnumInstType * enumInst );
-	void postvisit( StructInstType * structInst );
-	void postvisit( UnionInstType * unionInst );
-	void postvisit( TraitInstType * traitInst );
-	void previsit( QualifiedType * qualType );
-	void postvisit( QualifiedType * qualType );
-	void postvisit( QualifiedNameExpr * qualExpr );
-	
-	void postvisit( EnumDecl * enumDecl );
-	void postvisit( StructDecl * structDecl );
-	void postvisit( UnionDecl * unionDecl );
-	void postvisit( TraitDecl * traitDecl );
-
-	void previsit( StructDecl * structDecl );
-	void previsit( UnionDecl * unionDecl );
-
-	void renameGenericParams( std::list< TypeDecl * > & params );
-
-private:
-	const Indexer * local_indexer;
-
-	typedef std::map< std::string, std::list< EnumInstType * > > ForwardEnumsType;
-	typedef std::map< std::string, std::list< StructInstType * > > ForwardStructsType;
-	typedef std::map< std::string, std::list< UnionInstType * > > ForwardUnionsType;
-	ForwardEnumsType forwardEnums;
-	ForwardStructsType forwardStructs;
-	ForwardUnionsType forwardUnions;
-	/// true if currently in a generic type body, so that type parameter instances can be renamed appropriately
-	bool inGeneric = false;
-};
-
-
-LinkReferenceToTypes_old::LinkReferenceToTypes_old( const Indexer * other_indexer ) : WithIndexer( false ) {
-	if ( other_indexer ) {
-		local_indexer = other_indexer;
-	} else {
-		local_indexer = &indexer;
-	} // if
-}
-
-void LinkReferenceToTypes_old::postvisit( EnumInstType * enumInst ) {
-	const EnumDecl * st = local_indexer->lookupEnum( enumInst->name );
-	// it's not a semantic error if the enum is not found, just an implicit forward declaration
-	if ( st ) {
-		enumInst->baseEnum = const_cast<EnumDecl *>(st); // Just linking in the node
-	} // if
-	if ( ! st || ! st->body ) {
-		// use of forward declaration
-		forwardEnums[ enumInst->name ].push_back( enumInst );
-	} // if
-}
-
-void LinkReferenceToTypes_old::postvisit( StructInstType * structInst ) {
-	const StructDecl * st = local_indexer->lookupStruct( structInst->name );
-	// it's not a semantic error if the struct is not found, just an implicit forward declaration
-	if ( st ) {
-		structInst->baseStruct = const_cast<StructDecl *>(st); // Just linking in the node
-	} // if
-	if ( ! st || ! st->body ) {
-		// use of forward declaration
-		forwardStructs[ structInst->name ].push_back( structInst );
-	} // if
-}
-
-void LinkReferenceToTypes_old::postvisit( UnionInstType * unionInst ) {
-	const UnionDecl * un = local_indexer->lookupUnion( unionInst->name );
-	// it's not a semantic error if the union is not found, just an implicit forward declaration
-	if ( un ) {
-		unionInst->baseUnion = const_cast<UnionDecl *>(un); // Just linking in the node
-	} // if
-	if ( ! un || ! un->body ) {
-		// use of forward declaration
-		forwardUnions[ unionInst->name ].push_back( unionInst );
-	} // if
-}
-
-void LinkReferenceToTypes_old::previsit( QualifiedType * ) {
-	visit_children = false;
-}
-
-void LinkReferenceToTypes_old::postvisit( QualifiedType * qualType ) {
-	// linking only makes sense for the 'oldest ancestor' of the qualified type
-	qualType->parent->accept( * visitor );
-}
-
-void LinkReferenceToTypes_old::postvisit( QualifiedNameExpr * qualExpr ) {
-	const EnumDecl * st = local_indexer->lookupEnum( qualExpr->type_decl->name );
-	qualExpr->type_decl = const_cast<EnumDecl *>(st);
-}
-
-// expand assertions from trait instance, performing the appropriate type variable substitutions
-template< typename Iterator >
-void expandAssertions( TraitInstType * inst, Iterator out ) {
-	assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toCString( inst ) );
-	std::list< DeclarationWithType * > asserts;
-	for ( Declaration * decl : inst->baseTrait->members ) {
-		asserts.push_back( strict_dynamic_cast<DeclarationWithType *>( decl->clone() ) );
-	}
-	// substitute trait decl parameters for instance parameters
-	applySubstitution( inst->baseTrait->parameters.begin(), inst->baseTrait->parameters.end(), inst->parameters.begin(), asserts.begin(), asserts.end(), out );
-}
-
-void LinkReferenceToTypes_old::postvisit( TraitDecl * traitDecl ) {
-	if ( traitDecl->name == "sized" ) {
-		// "sized" is a special trait - flick the sized status on for the type variable
-		assertf( traitDecl->parameters.size() == 1, "Built-in trait 'sized' has incorrect number of parameters: %zd", traitDecl->parameters.size() );
-		TypeDecl * td = traitDecl->parameters.front();
-		td->set_sized( true );
-	}
-
-	// move assertions from type parameters into the body of the trait
-	for ( TypeDecl * td : traitDecl->parameters ) {
-		for ( DeclarationWithType * assert : td->assertions ) {
-			if ( TraitInstType * inst = dynamic_cast< TraitInstType * >( assert->get_type() ) ) {
-				expandAssertions( inst, back_inserter( traitDecl->members ) );
-			} else {
-				traitDecl->members.push_back( assert->clone() );
-			}
-		}
-		deleteAll( td->assertions );
-		td->assertions.clear();
-	} // for
-}
-
-void LinkReferenceToTypes_old::postvisit( TraitInstType * traitInst ) {
-	// handle other traits
-	const TraitDecl * traitDecl = local_indexer->lookupTrait( traitInst->name );
-	if ( ! traitDecl ) {
-		SemanticError( traitInst->location, "use of undeclared trait " + traitInst->name );
-	} // if
-	if ( traitDecl->parameters.size() != traitInst->parameters.size() ) {
-		SemanticError( traitInst, "incorrect number of trait parameters: " );
-	} // if
-	traitInst->baseTrait = const_cast<TraitDecl *>(traitDecl); // Just linking in the node
-
-	// need to carry over the 'sized' status of each decl in the instance
-	for ( auto p : group_iterate( traitDecl->parameters, traitInst->parameters ) ) {
-		TypeExpr * expr = dynamic_cast< TypeExpr * >( std::get<1>(p) );
-		if ( ! expr ) {
-			SemanticError( std::get<1>(p), "Expression parameters for trait instances are currently unsupported: " );
-		}
-		if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( expr->get_type() ) ) {
-			TypeDecl * formalDecl = std::get<0>(p);
-			TypeDecl * instDecl = inst->baseType;
-			if ( formalDecl->get_sized() ) instDecl->set_sized( true );
-		}
-	}
-	// normalizeAssertions( traitInst->members );
-}
-
-void LinkReferenceToTypes_old::postvisit( EnumDecl * enumDecl ) {
-	// visit enum members first so that the types of self-referencing members are updated properly
-	// Replace the enum base; right now it works only for StructEnum
-	if ( enumDecl->base ) {
-		if ( const TypeInstType * base = dynamic_cast< TypeInstType * >(enumDecl->base) ) {
-			if ( const StructDecl * decl = local_indexer->lookupStruct( base->name ) ) {
-				enumDecl->base = new StructInstType( Type::Qualifiers(), const_cast< StructDecl * >( decl ) ); // Just linking in the node
-			}
-		} else if ( const PointerType * ptr = dynamic_cast< PointerType * >(enumDecl->base) ) {
-			if ( const TypeInstType * ptrBase = dynamic_cast< TypeInstType * >( ptr->base ) ) {
-				if ( const StructDecl * decl = local_indexer->lookupStruct( ptrBase->name ) ) {
-					enumDecl->base = new PointerType( Type::Qualifiers(),
-						new StructInstType( Type::Qualifiers(), const_cast< StructDecl * >( decl ) ) );
-				}
-			}
-		}
-	}
-	
-	if ( enumDecl->body ) {
-		ForwardEnumsType::iterator fwds = forwardEnums.find( enumDecl->name );
-		if ( fwds != forwardEnums.end() ) {
-			for ( std::list< EnumInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
-				(* inst)->baseEnum = enumDecl;
-			} // for
-			forwardEnums.erase( fwds );
-		} // if
-	} // if
-}
-
-void LinkReferenceToTypes_old::renameGenericParams( std::list< TypeDecl * > & params ) {
-	// rename generic type parameters uniquely so that they do not conflict with user-defined function forall parameters, e.g.
-	//   forall(otype T)
-	//   struct Box {
-	//     T x;
-	//   };
-	//   forall(otype T)
-	//   void f(Box(T) b) {
-	//     ...
-	//   }
-	// The T in Box and the T in f are different, so internally the naming must reflect that.
-	GuardValue( inGeneric );
-	inGeneric = ! params.empty();
-	for ( TypeDecl * td : params ) {
-		td->name = "__" + td->name + "_generic_";
-	}
-}
-
-void LinkReferenceToTypes_old::previsit( StructDecl * structDecl ) {
-	renameGenericParams( structDecl->parameters );
-}
-
-void LinkReferenceToTypes_old::previsit( UnionDecl * unionDecl ) {
-	renameGenericParams( unionDecl->parameters );
-}
-
-void LinkReferenceToTypes_old::postvisit( StructDecl * structDecl ) {
-	// visit struct members first so that the types of self-referencing members are updated properly
-	// xxx - need to ensure that type parameters match up between forward declarations and definition (most importantly, number of type parameters and their def>
-	if ( structDecl->body ) {
-		ForwardStructsType::iterator fwds = forwardStructs.find( structDecl->name );
-		if ( fwds != forwardStructs.end() ) {
-			for ( std::list< StructInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
-				(* inst)->baseStruct = structDecl;
-			} // for
-			forwardStructs.erase( fwds );
-		} // if
-	} // if
-}
-
-void LinkReferenceToTypes_old::postvisit( UnionDecl * unionDecl ) {
-	if ( unionDecl->body ) {
-	ForwardUnionsType::iterator fwds = forwardUnions.find( unionDecl->name );
-		if ( fwds != forwardUnions.end() ) {
-			for ( std::list< UnionInstType * >::iterator inst = fwds->second.begin(); inst != fwds->second.end(); ++inst ) {
-				(* inst)->baseUnion = unionDecl;
-			} // for
-			forwardUnions.erase( fwds );
-		} // if
-	} // if
-}
-
-void LinkReferenceToTypes_old::postvisit( TypeInstType * typeInst ) {
-	// ensure generic parameter instances are renamed like the base type
-	if ( inGeneric && typeInst->baseType ) typeInst->name = typeInst->baseType->name;
-	if ( const NamedTypeDecl * namedTypeDecl = local_indexer->lookupType( typeInst->name ) ) {
-		if ( const TypeDecl * typeDecl = dynamic_cast< const TypeDecl * >( namedTypeDecl ) ) {
-			typeInst->set_isFtype( typeDecl->kind == TypeDecl::Ftype );
-		} // if
-	} // if
-}
-
-/* // expand assertions from trait instance, performing the appropriate type variable substitutions
-template< typename Iterator >
-void expandAssertions( TraitInstType * inst, Iterator out ) {
-	assertf( inst->baseTrait, "Trait instance not linked to base trait: %s", toCString( inst ) );
-	std::list< DeclarationWithType * > asserts;
-	for ( Declaration * decl : inst->baseTrait->members ) {
-		asserts.push_back( strict_dynamic_cast<DeclarationWithType *>( decl->clone() ) );
-	}
-	// substitute trait decl parameters for instance parameters
-	applySubstitution( inst->baseTrait->parameters.begin(), inst->baseTrait->parameters.end(), inst->parameters.begin(), asserts.begin(), asserts.end(), out );
-}*/
-
-/// Replace all traits in assertion lists with their assertions.
-void expandTraits( std::list< TypeDecl * > & forall ) {
-	for ( TypeDecl * type : forall ) {
-		std::list< DeclarationWithType * > asserts;
-		asserts.splice( asserts.end(), type->assertions );
-		// expand trait instances into their members
-		for ( DeclarationWithType * assertion : asserts ) {
-			if ( TraitInstType * traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
-				// expand trait instance into all of its members
-				expandAssertions( traitInst, back_inserter( type->assertions ) );
-				delete traitInst;
-			} else {
-				// pass other assertions through
-				type->assertions.push_back( assertion );
-			} // if
-		} // for
-	} // for
-}
-
-struct TraitExpander_old final {
-	void previsit( FunctionType * type ) {
-		expandTraits( type->forall );
-	}
-	void previsit( StructDecl * decl ) {
-		expandTraits( decl->parameters );
-	}
-	void previsit( UnionDecl * decl ) {
-		expandTraits( decl->parameters );
-	}
-};
-
-/*struct TraitExpander_old final {
-	void previsit( FunctionType * );
-	void previsit( StructDecl * );
-	void previsit( UnionDecl * );
-};
-
-void TraitExpander_old::previsit( FunctionType * ftype ) {
-	expandTraits( ftype->forall );
-}
-
-void TraitExpander_old::previsit( StructDecl * aggrDecl ) {
-	expandTraits( aggrDecl->parameters );
-}
-
-void TraitExpander_old::previsit( UnionDecl * aggrDecl ) {
-	expandTraits( aggrDecl->parameters );
-}*/
-
-/// Fix each function in the assertion list and check for invalid void type.
-void fixAssertions(
-		std::list< TypeDecl * > & forall, BaseSyntaxNode * node ) {
-	for ( TypeDecl * type : forall ) {
-		for ( DeclarationWithType *& assertion : type->assertions ) {
-			bool isVoid = fixFunction( assertion );
-			if ( isVoid ) {
-				SemanticError( node, "invalid type void in assertion of function " );
-			} // if
-		} // for
-	}
-}
-
-struct AssertionFixer_old final {
-	void previsit( FunctionType * type ) {
-		fixAssertions( type->forall, type );
-	}
-	void previsit( StructDecl * decl ) {
-		fixAssertions( decl->parameters, decl );
-	}
-	void previsit( UnionDecl * decl ) {
-		fixAssertions( decl->parameters, decl );
-	}
-};
-
-/*
-struct AssertionFixer_old final {
-	void previsit( FunctionType * );
-	void previsit( StructDecl * );
-	void previsit( UnionDecl * );
-};
-
-void AssertionFixer_old::previsit( FunctionType * ftype ) {
-	fixAssertions( ftype->forall, ftype );
-}
-
-void AssertionFixer_old::previsit( StructDecl * aggrDecl ) {
-	fixAssertions( aggrDecl->parameters, aggrDecl );
-}
-
-void AssertionFixer_old::previsit( UnionDecl * aggrDecl ) {
-	fixAssertions( aggrDecl->parameters, aggrDecl );
-}*/
-
-struct CheckOperatorTypes_old final {
-	void previsit( ObjectDecl * );
-};
-
-void CheckOperatorTypes_old::previsit( ObjectDecl * object ) {
-	// ensure that operator names only apply to functions or function pointers
-	if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) {
-		SemanticError( object->location, toCString( "operator ", object->name.c_str(), " is not a function or function pointer." )  );
-	}
-}
-
-struct FixUniqueIds_old final {
-	void previsit( DeclarationWithType * decl ) {
-		decl->fixUniqueId();
-	}
-};
-
-//void FixUniqueIds_old::previsit( DeclarationWithType * decl ) {
-//	decl->fixUniqueId();
-//}
-
-
-} // namespace
-
-void validateType( Type *type, const Indexer *indexer ) {
-	PassVisitor<EnumAndPointerDecay_old> epc;
-	PassVisitor<LinkReferenceToTypes_old> lrt( indexer );
-	PassVisitor<TraitExpander_old> te;
-	PassVisitor<AssertionFixer_old> af;
-	PassVisitor<CheckOperatorTypes_old> cot;
-	PassVisitor<FixUniqueIds_old> fui;
-	type->accept( epc );
-	type->accept( lrt );
-	type->accept( te );
-	type->accept( af );
-	type->accept( cot );
-	type->accept( fui );
-}
-
-void decayEnumsAndPointers( std::list< Declaration * > & translationUnit ) {
-	PassVisitor<EnumAndPointerDecay_old> epc;
-	acceptAll( translationUnit, epc );
-}
-
-void linkReferenceToTypes( std::list< Declaration * > & translationUnit ) {
-	PassVisitor<LinkReferenceToTypes_old> lrt( nullptr );
-	acceptAll( translationUnit, lrt ); // must happen before autogen, because sized flag needs to propagate to generated functions
-}
-
-void decayForallPointers( std::list< Declaration * > & translationUnit ) {
-	PassVisitor<TraitExpander_old> te;
-	acceptAll( translationUnit, te );
-	PassVisitor<AssertionFixer_old> af;
-	acceptAll( translationUnit, af );
-	PassVisitor<CheckOperatorTypes_old> cot;
-	acceptAll( translationUnit, cot );
-	PassVisitor<FixUniqueIds_old> fui;
-	acceptAll( translationUnit, fui );
-}
-
-
-} // namespace SymTab
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/SymTab/ValidateType.h
===================================================================
--- src/SymTab/ValidateType.h	(revision 934fa0fc6af3737f7f5b45e08f4b84e1e8259312)
+++ 	(revision )
@@ -1,38 +1,0 @@
-//
-// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
-//
-// The contents of this file are covered under the licence agreement in the
-// file "LICENCE" distributed with Cforall.
-//
-// ValidateType.h -- Validate and normalize types.
-//
-// Author           : Andrew Beach
-// Created On       : Mon May 16 16:18:00 2022
-// Last Modified By : Andrew Beach
-// Last Modified On : Mon May 16 16:18:00 2022
-// Update Count     : 0
-//
-
-#pragma once
-
-#include <list>
-
-class Declaration;
-class Type;
-
-namespace SymTab {
-	class Indexer;
-
-	void validateType( Type *type, const Indexer *indexer );
-
-	// Sub-passes that are also used by the larger validate pass.
-	void decayEnumsAndPointers( std::list< Declaration * > & translationUnit );
-	void linkReferenceToTypes( std::list< Declaration * > & translationUnit );
-	void decayForallPointers( std::list< Declaration * > & translationUnit );
-}
-
-// Local Variables: //
-// tab-width: 4 //
-// mode: c++ //
-// compile-command: "make install" //
-// End: //
Index: src/SymTab/module.mk
===================================================================
--- src/SymTab/module.mk	(revision 934fa0fc6af3737f7f5b45e08f4b84e1e8259312)
+++ src/SymTab/module.mk	(revision c6b4432f5c6c6679b981f5a6bded51ad30ac00d9)
@@ -16,21 +16,13 @@
 
 SRC_SYMTAB = \
-	SymTab/Autogen.cc \
-	SymTab/Autogen.h \
 	SymTab/FixFunction.cc \
 	SymTab/FixFunction.h \
 	SymTab/GenImplicitCall.cpp \
 	SymTab/GenImplicitCall.hpp \
-	SymTab/Indexer.cc \
-	SymTab/Indexer.h \
 	SymTab/Mangler.cc \
 	SymTab/ManglerCommon.cc \
-	SymTab/Mangler.h \
-	SymTab/ValidateType.cc \
-	SymTab/ValidateType.h
+	SymTab/Mangler.h
 
-SRC += $(SRC_SYMTAB) \
-	SymTab/Validate.cc \
-	SymTab/Validate.h
+SRC += $(SRC_SYMTAB)
 
 SRCDEMANGLE += $(SRC_SYMTAB) \
